Общее.
Обмен с сервером происходит по протоколу WebSocket в бинарном формате. Слово "arraybuffer" должно что-то сказать JS-экспертам. Возможно вы хотите почитать вот это: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket.
На сервер никак не нужно логиниться через WebSocket. После соединения, сервер считает вас живым, пока сам не отключил, и заваливает разными командами о состоянии мира, которые вам нужно (или не нужно) обработать - очень похоже на коннект с какой-нибудь биржей.
Сервер имеет право подумать про вас плохо и порвать соединение без объяснения причин, если вы попытались прислать 100 килобайт мусора, зафлудить его подозрииельными запросами (типа "дай карту за километр от меня, которую я не вижу") и т.п. Если с вами совсем жить нельзя, то сервер может послать файрволу -j DROP на всю вашу подсеть или сделать что-то подобное.
Server -> Client
Команды от сервера клиенту. Вам не нужно ничего делать, чтобы начать их получать. Сервер считает, что вы готовы принять любую из них после соединения, поэтому сразу начинает вас заваливать командами, не ожидая ничего. Некоторые команды обновляют статус чего-то едущего в вашем поле зрения, а некоторые являются ответами на ваши запросы ранее.
Первый байт - opcode - всегда задаёт команду. После байта opcode идёт последовательность полей данных, специфичных для каждой команды. Формат данных всего пакета для данного opcode (вместе с ним) показаны в колонке Packet.
Каждое поле данных может иметь тип uint8, uint16, uint32 или string(N). uint16 - это 16-битное целое little-engian, остальное вы поняли.
Тип string передаётся так: len:uintN, data:(len), где len - длина строки, N - битность len (8, 16, 32) и далее указанное число байт самой строки. Если это строки текста, то передаются не помню в какой кодировке, кажется cp1251 для компактности.
string будем обозначать как string(N), где N определяет битность len в конкретном случае.
Команды, помеченные красным могут в некотором будущем полностью поменять свой размер, назначение, исчезнуть и т.п. Если вы написали бота, который перестал работать - проверьте как поменялись эти команды в этом документе. Если пропал красный маркер, значит в этом виде команды мы будем уверены достаточно долго.
Opcode | Packet | Описание |
---|---|---|
0x64 |
opcode:uint8 |
CMD_OUT_SETTINGS - неиспользуемая или устаревшая команда "сброс состояния". Не нужна. Ничего не делает. |
0x65 |
opcode:uint8 |
CMD_OUT_LOGIN - танк id появился в поле зрения. Клиент может выделить память под id (создать объект танка с таким id) и считать все дальнейшие команды про данный id валидными. |
0x66 |
opcode:uint8 |
CMD_OUT_LOGOUT - обратная от 0x65. id пропал из поля зрения. |
0x67 |
opcode:uint8 Если extended != 0, то добавляются ещё такие поля: look:uint8 |
CMD_OUT_STATUS - обновление статуса танка id. Эта команда приходит клиенту, когда любой (или несколько) параметров у танка id поменяется, например увеличится число денег или уменьшится здоровье. Для танков вне поля зрения (за экраном) эта команда, естественно, не приходит. Каким танки в вашем поле зрения решает сервер (по расстоянию от вас). |
0x68 |
opcode:uint8 Далее size число раз передаётся строка таблицы в формате:
money:uint32 |
CMD_OUT_RATING_USERS - обновление рейтинга юзеров; та табличка, которую видно сверху-справа. |
0x69 |
opcode:uint8 |
CMD_OUT_POS - текущие координаты (x, y) и скорость (sx, sy) танка id. Скорость (sx, sy) передаётся умноженной на 1000000.0, поэтому после получения нужно поделить на эту константу и работать с sx, sy как с типами float/double. dirlook - направление, в котором смотрит танк (0 - up, 1 - down, 2 - left, 3 - right). |
0x6A |
opcode:uint8 |
CMD_OUT_PARTICLE_BORN - создана частица. Это может быть пуля, здоровье и т.п. Клиенту нужны эти данные только для анимации полёта частиц. Клиент не рассчитывает столкновения, хотя ему никто не может помешать делать это для себя. (x, y) - координаты рождения частицы, (sx, sy) - скорость частицы; передаётся умноженной на 1000000.0. |
0x6B |
opcode:uint8 |
CMD_OUT_PARTICLE_DIE - частица id померла (с чем-то столкнулась или истек срок годности/дальности). Можно удалить из памяти и перестать анимировать. Причина исчезновения частицы не сообщается. |
0x6С |
opcode:uint8 Далее передаётся size кирпичей в таком формате:
x:uint32 |
CMD_OUT_MAP - квадрат кирпичей карты.
type - всегда ноль, (bx, by) - верхний левый угол блока этих кирпичей - клиент передаёт это в запросе size - число кирпичей в квадрате val - значение (цвет) кирпича: |
0x6D |
opcode:uint8 |
CMD_OUT_BRICK - апдейт значения указанного кирпича. Возможно крипич усилили, ослабили или удалили совсем. Координаты кирпича: (x0, y0), x1 и y1 не используются. value как в команде CMD_OUT_MAP. |
0x6E |
opcode:uint8 Далее size пакетов такого содержания:
x:uint32 |
CMD_OUT_BRICK_INFO - информация о кирпиче по указанным координатам. Приходит по запросу от юзера. Есть проверка на область видимости, бесполезно получать слишком далёкие кирпичи от себя. Через эту команду реализована функция отображения крепости и типа кирпича, когда вы водите по кирпичам мышкой. Запросная команда - CMD_IN_POINTER_POS описана в секции Client -> Server. |
0x6F |
opcode:uint8 |
CMD_OUT_SERVER_STATS - разная серверная техническая статистика. Не использовать. Может быть выпилена-переделана. Возможно даже не передаётся. |
0x70 |
opcode:uint8 |
CMD_OUT_PING - пинг от сервера. type - не используется/рандом. pingcode - важно это запомнить и ответить в PONG, иначе могут отключить. |
0x71 |
opcode:uint8 |
CMD_OUT_KEY_SVAL - передача какого-то key=value. Смысл key определяется key. Не относится к критичным функциям, можно выкинуть. Чаще всего применяется для отображения какого-нибудь окошка со свойствами выделенного танка в интерфейсе. Подробнее спецификация появится не сегодня. |
0x72 |
opcode:uint8 |
CMD_OUT_KEY_IVAL - аналогично CMD_OUT_KEY_SVAL, только value имеет тип uint32 |
0x73 |
opcode:uint8 |
CMD_OUT_RADAR - направление стрелки радара вашего танка; показывает на ближайший танк с живым человеком. dir_radians передаётся в радианах типом float, умноженным на 10000. state - не используется. Если клиент не получал этой команды более 300 мсек, показания радара считать невалидными. |
0x74 |
opcode:uint8 |
CMD_OUT_KEY_STATUS - информация о ключе, введённом клиентом. Сколько в этом ключе денег, поинтов и т.п. Команда будет переделана в перспективе. Последние 4 32-битных поля содержат бред, вы не хотите о нём думать, просто он есть. Не тратьте годы жизни на взлом, это реально мусор. |
0x75 |
unknown |
reserved |
0x76 |
opcode:uint8 |
CMD_OUT_SELECTED - информация о том, какой танк выделен. Нужно клиенту для рисования этого танка на синем фоне, больше незачем. id - кто выделен, state - выделен ли он. |
0x77 |
unknown |
reserved |
0x78 |
opcode:uint8 |
CMD_OUT_MESSAGE - текстовое сообщение клиенту. Сюда входят и системные сообщения от сервера и сообщения чата. Если from == 0, значит это системное сообщение. Странно, что длина строки сдеана 32 битой, но всё же 4 GiB данных здесь не бывает. |
Client -> Server
Эти комнады клиент отправляет серверу, чтобы сообщить что он поехал, повернул, начал стрелять, ответил на пинг или отправил что-то в чат.
На все команды есть флуд-контроли и проверки, так что может не пробовать получать карту на другом конце мира или зафлудить чат.
Передача невалидных/неполных команд молча пропускается сервером.
Opcode | Packet | Описание |
---|---|---|
0x01 |
opcode:uint8 |
CMD_IN_MOVE - двигатель и руль - "ехать или нет и куда ехать".
state - [0-1] - стоять-ехать; dirhold - [0-1] - нажата ли клавиша shift для удержания направления носа танка; dirdrive - [0-4] - в каком направлении вы едете; 0 - up, 1 - down, 2 - left, 3 - right |
0x02 |
opcode:uint8 |
CMD_IN_FIRE - стрельба.
state - [0-1] - выкл-вкл; dir_radians - направление стрельбы в радианах, умноженное на 10000; |
0x03 |
opcode:uint8 |
CMD_IN_CLICK_SCREEN - устарело, не применяется. |
0x04 |
opcode:uint8 |
CMD_IN_PONG - ответ на пинг. Нужно передать запомненный из PING pingcode. Остальные поля - 0. |
0x05 |
opcode:uint8 |
CMD_IN_GETMAP - получить кусок карты. Через эту команду клиент видит окружающий мир. Формат может показаться запутанным, но он простой: Запрашивается прямоугольник R = (x0, x1, y0, y1) карты. Например, вы хотите видеть кусок размером 5x5 с левым верхним углом (X=100, Y=200), тогда ваш R будет (100, 105, 200, 205). Не стоит запрашивать прямоугольник слишком далеко от себя или слишком большой (иначе просто ничего не придёт в ответ - на сообщения об ошибках мы не тратим трафик) - ограничивайтесь размерами 10x10. Попробуйте запросить карту вокруг себя небольшими квадратиками, получив после соединения в какой-то момент своё местоположение после команд LOGIN и POS. |
0x06 |
opcode:uint8 |
CMD_IN_CONTROL - передача разнообразных параметров на сервер. Параметр определяется key, смысл его значения зависит от key и помещается в одно из двух полей: value_int, value_str.
Некоторые важные key: 900 - покупка предмета; класс покупаемого предмета нужно передать в value_str, например "aid" - это аптечка; Тут нужно расписывать все возможные типы, но вы можете загребать JS-код, они там где-то перечислены. Проверка на длину строки стоит, не парьтесь с хаканьем. [1000-1003] - выбор одного из 4 текущего оружия танка; value не важны; например передача ключа 1000 выбирает первую красную стрелялку. |
0x07 |
opcode:uint8 |
CMD_IN_POINTER_POS - запрос информации о кирпиче (x, y). type не используется, передавайте 0 туда на всякий случай. |