Я немного изменил описание по сравнению с оригинальным из lua_help.script. Добавил типы возвращаемых значений, перегруппировал и убрал некоторую шелуху. Более подробно о методах класса:
net_packet() - конструктор, вызывается в виде глобальной функции так:
local packet = net_packet()
созданный пакет по умолчанию имеет позиции чтения и записи установленные в 0
Не всегда надо создавать свой пакет. Часто приходится иметь дело с уже готовым пакетом (см. следующую статью об использовании нетпакетов)
w_tell() - возвращает текущую позицию записи
r_tell() - возвращает текущую позицию чтения
r_advance(shift) - смещает позицию чтения на shift байт. Смещение может быть отрицательным.
r_seek(pos) - устанавливает позицию чтения в pos
r_elapsed() - возвращает w_tell() - r_tell()
r_eof() - возвращает true, если r_tell() < w_tell(), иначе false
w_begin(number) - пишет двухбайтовое число в начало пакета и устанавливает позицию записи равной 2. Единственным другим способом начать запись с начала пакета - это создать новый пакет, у которого позиция записи установлена в 0.
r_begin(number&) - Непонятный метод. По аналогии с w_begin должен читать с начала пакета два байта и устанавливать позицию чтения в 2. Однако у меня приводит к вылету. Ну, в любом случае можно обойтись и без него.
Важный момент! Нет никакого способа узнать, что в процессе чтения или записи позиция чтения или записи вышла за пределы пакета. При чтении подразумевается, что прочитать можно столько, сколько записано. Для этого и есть функции r_elapsed() и r_eof(). А вот при записи никакой границы сверху нет, поэтому можно запросто записать больше, чем 8 кбайт. Ясно, что при этом произойдёт переполнение буфера с почти обязательным последующим вылетом игры. Так что надо самостоятельно следить за размером позиции записи и проверять, чтобы при последующей записи она не вышла бы за размеры пакета. Для этого надо знать, сколько мы запишем, ещё до того, как запишем. В особенности это важно для строк, которые имеют переменную длину. Поступаем примерно так:
Код
if string.len(s) + 1 + packet:w_tell() > 8192 then
-- здесь делаем что-то, например крашим игру и выводим сообщение, что не надо жадничать =)
end
packet:w_stringZ(s)Обратите внимание на "+ 1" в вычислении новой позиции записи. Строки имеют дополнительный невидимый нулевой символ в конце, и их физическая длина на один больше, чем длина в символах, которую возвращает функция string.len().
Остальные методы предназначены собственно для чтения и записи. Описывать их все в подробностях нет смысла, только общий принцип. Читаем так:
local value = packet:r_XXX()
здесь XXX - это тип значения, которое читается. Значение читается из буфера начиная с текущей позиции чтения, а позиция чтения увеличивается на размер читаемого значения. В переменную value будет помещено значение того типа, которое прочитано.
аналогично пишем в буфер:
packet:w_XXX(value)
Значение пишется начиная с текущей позиции записи, а позиция записи увеличивается на размер типа XXX.
для целых типов:
u - знаковое значение
s - беззнаковое значение
8, 16, 24, 32, 64 - один, два, три, четыре, восемь байт соответственно
Обратите внимаение, что для типа s8 (знаковый байт) нет метода записи. Подозреваю, что вместо него можно использовать соответствующий метод для беззнакового типа.
float - число с плавающей запятой одинарной точности, 4 байта
stringZ - строка (размер равен длине + 1 байт)
bool - логическое значение (1 байт)
vec3 - объект типа vector - вектор из трёх float (12 байт)
matrix - объект типа matrix. Состоит из 4-х векторов (48 байт)
sdir - ? непонятно, на запись берёт вектор и пишет 6 байт
dir - ? аналогично, но пишет 2 байта
angle8 - ? берёт float и пишет 1 байт
angle16 - ? аналогично, но пишет 2 байта
четыре последних метода при чтении у меня вызывают вылет. зачем нужны, неизвестно.
ClientID - объект класа ClientID. Судя по всему, это надо для сетевой игры.
float_q8, float_q16 - пока непонятно
Назначение методов с w_chunk_ вообще непонятно, тем более, что для них отсутствуют соответствующие методы на чтение.