Jump to content
Korean Random

Dragon armor

User
  • Content Count

    416
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Dragon armor

  1. Дело в том, что техника заходит под ландшафт. Может быть, сервер её чуть повыше спавнит. Когда физику сделаю, тогда будет видно, проблема это или нет.
  2. Всё, нашёл у себя ошибку. Эти col, row, не [0][2], а наоборот. Не, поменьше, всего-то 15. Попробовал, ошибка не исправлена, всё так же техника завалена назад. Интересно. Сейчас сделал совсем по-другому. Взял файл из секции UDOS и загрузил в клиенте. В xml выглядит так: <transform> <row0> 0.999982 -0.000002 -0.003675 </row0> <row1> 0.000002 0.999989 -0.000004 </row1> <row2> 0.003675 0.000004 0.999982 </row2> <row3> -420.133820 -20.297848 -453.322357 </row3> </transform> А загрузилось так: 2018-08-10 21:52:00.966: INFO: [ 1.0000, 0.0000, 0.0037, -420.1338 ] 2018-08-10 21:52:00.967: INFO: [ -0.0000, 1.0000, 0.0000, -20.2978 ] 2018-08-10 21:52:00.967: INFO: [ -0.0037, -0.0000, 1.0000, -453.3224 ] 2018-08-10 21:52:00.967: INFO: [ 0.0000, 0.0000, 0.0000, 1.0000 ] Когда искал, как из матрицы вытащить координаты и углы, нашёл такое SRR0 RSR0 RRS0 TTT1 Where R is the rotation, T the translation and S scaling. В BigWorld повёрнуто на 90 градусов? Или что-то не так загрузилось? Сделал точно так же, как и загружается в клиенте. Не получается, либо матрицу надо отображать как-то по-другому, либо где-то в расчётах ошибка. Вся техника улетела вверх и в одну точку. Попробовал бинарный xml загрузить. Всё так же. Пока оставлю как есть, вернусь к этому позже. Посмотрел ещё раз. Вывод матрицы по столбцам, поэтому она и так выглядит. Но у меня получается результат с противоположным знаком. Клиент выводит 0.00367504963651, -4.00004500989e-06, -2.00002273232e-06, у меня же -0.003675, 0.000004, 0.000000. Пробовал принудительно менять знак, всё равно техника задрана вверх.
  3. И всего-то полчаса понадобилось, чтобы узнать, что считается по другому. 2018-08-10 21:07:27.027: INFO: [ -0.0055, -0.0000, 1.0000, 0.0000 ] 2018-08-10 21:07:27.027: INFO: [ 0.0000, 1.0000, 0.0000, 0.0000 ] 2018-08-10 21:07:27.027: INFO: [ -1.0000, 0.0000, -0.0055, 0.0000 ] 2018-08-10 21:07:27.027: INFO: [ 428.0589, -28.7889, -180.6909, 1.0000 ] 2018-08-10 21:07:27.027: INFO: 2018-08-10 21:07:27.027: INFO: 1.57626342773, -2.0000081804e-06, 4.00001636081e-06 У меня получается -1.576263, -0.000004, -0.000345. Нормальному. А тут перевес такой при random.randint(1, 2) в пользу первого варианта.
  4. @Pavel3333 Точно, надо движок игры попробовать задействовать, опять забыл про него. Да, это так, а как его получить из матрицы? В BigWorld это встроено в движок, а не в питоне, поэтому приходится самому искать решения.
  5. Питоновский генератор псевдослучайных чисел не подойдёт, надо что-то другое. Вот так он распределил по командам. А тут не смог из матрицы получить вектор направления. Кто подскажет, как сделать, буду благодарен. Но техника уже ориентирована, как и должно быть, а не строго на север. Решил проверить, что будет, если в одной команде сделать больше 15 игроков. @Pavel3333 Само собой, если получится что-то рабочее сделать, а не прототип, как сейчас. В памяти отложилось, может и ошибочно. Просто был уверен, что движок ограничивает видимость энтитей этого типа на 565 метров. Для меня стало открытием, что это не так. Да, знаю. Чем дальше от игрока, тем реже приходят обновления для энтити. Здесь можно этого избежать, чтобы за километр лючки у ЛТ на полном ходу можно было выцеливать.
  6. Достаточно медленно продвигается дело. Смог только заспавнить технику по точкам. Тут ещё без учёта флага visibilityMask. Здесь с учётом, но без preferableType (техника в технике появилась). Не совсем понятно, есть параметр any, который почти совпадает с другими точками для техники определённых типов. Видимо, это для какого-то режима, то есть, либо any, либо предопределённый класс техники. Вот эта навязчивая ошибка из-за чего? Удалял AppData\Roaming\Wargaming.net, всё равно не помогает. Иногда проходит, а обычно надо заново вводить пароль.
  7. I can spawn anywhere.I wanted to do so that I could see the tank, I spawned it in the air. Помню, что они писали или в видео рассказывали, что это именно ограничение движка и дальше увидеть просто не возможно. И также писали, что с переходом на новый движок, это ограничение стало искусственным. Хотя понятно, что это и в старом движке искусственное ограничение, иначе и ландшафт нельзя было бы увидеть за этой границей. https://youtu.be/YMgVfM6fOK4?t=314 Надо начинать парсить карту, давненько немного пытался это сделать, сейчас надо основательнее подойти. Хотя на первое время достаточно будет физическую модель достать. И после этого нужно физику вводить, а потом можно будет и технику заставить двигаться. У меня сомнения на счёт физического движка. Нужен какой-то упрощенный или можно взять полноценный? Как бы это realtime, ничего назад во времени не надо будет отматывать, чтобы посмотреть, кто и где был в момент события. Кстати, модов не завалялось ни у кого для этой версии? Командирскую камеру нашёл в составе модпака для читеров, но свободной камеры там нет. И не всегда запускается игра, пару раз нормально, потом пришлось удалять. Модпак, как обычно, лезет в сеть за обновлениями или чем-то ещё, у меня всё подобное заблокировано, может из-за этого отказывается работать.
  8. @Serfer_78 Благодарю. Максимальная дальность видимости 565 метров, говорили они, это максимальная дистанция, на которой в принципе можно увидеть технику, говорили они. It was a lie, Morpheus. The prophecy was a lie. В снайперском прицеле за кустами немного видно, но силуэт не обводится.
  9. СКОРОСТИ!!!111 Это ожидаемо, поэтому ресурсоёмкие вещи переношу в модули на C. 2.7.7, такая же, как и в клиенте. Да. Особенности сервера. Константа BigWorld.component = 'base'. А из-за этого вылезло много ошибок из-за отсутствующих значений в xml, например 'xpFactor', 'creditsFactor', 'freeXpFactor', '****Health' и прочих. Пришлось добавлять эти значения и решил заново запаковать. Долго, муторно, не нужно (хотя бы на данный момент). Самый первый элемент, Root. Не понятная для меня вещь - дублирование информации в энтитях и излишний (на мой взгляд) оверхед в сетевом трафике. На хабре WG писали несколько статей о том, как они стараются сократить количество трафика, борясь за каждый байт. А что в действительности? Каждый раз, когда сервер отправляет сообщение, которое принадлежит клиенту (Avatar, Account), перед ним отправляется selectPlayerEntity. Если в одном сетевом пакете будет десяток таких сообщений, их будет столько же. При этом, для других энтитей, которые принадлежат другим игрокам (Vehicle) энтити выбирается только один раз, а дальше все сообщения будут принадлежать выбранной энтити. Команда, в которую попал игрок, передаётся в Avatar.updateArena (VEHICLE_LIST) и при создании энтити игрока на арене, которая передаётся следом за предыдущей. id техники так же дублируется и тут, и там. id в базе данных аналогично, что для меня абсолютно не понятно, это-то как может измениться? Не достаточно один раз при логине передать? Или это такая задуманная (штатная) возможность смены игрока на другого? Долго не мог понять, из-за чего ошибки постоянно в логе вылазят: arena_vos.py", line 503, in getTypeInfo: ERROR: IndexError: tuple index out of range - из-за неправильной id техники AssertionError: Player's databaseID can not be empty При том с такой частотой, что клиент подвисал. Разобрался и продвинулся ещё дальше.
  10. @DrWeb7_1 Благодарю. Сегодня чуть-чуть дальше продвинулся. Карту почему-то эту выбирает, хотя пока что информацию о ней не отправлял. Как-то много непонятного с id энтитей. Почему-то используется уникальный id для каждой, а не id из базы данных для игрока. Создаётся Avatar со своим id, для него техника со своим id, для аватара отправляется сообщение о том, что он больше не контролируется (controlEntity с id аватара и false). И не понятно, id разных энтитей (аватар и техника) могут повторяться или нет? @SkepticalFox , взял было твой питоновый модуль XmlPacker/XmlUnpacker, надеясь избавиться от mxml, который у меня используется для парсинга, но производительность так сильно упала (с 6 секунд до 40+ при загрузке сервера), что пришлось на сишке самому написать. И там у тебя баг, вместо PackedTypes.Section почему-то PackedTypes.Float с нулевой длиной создаётся. Хотя это не мешает, созданный с помощью XmlPacker корректно распаковывается и работает.
  11. Можно. Но нужно много чего сделать. Повторить сетевой протокол движка (обработка доставки сообщений, подтверждение доставки, разбивка больших данных на небольшие пакеты и прочее), имитировать реальный клиент (вдруг забанят, если поведение будет отличаться). В общем, то же, что и сам делаю, но в обратную сторону. Возможно, даже проще. Кроме сетевой части. У меня все данные пересылаются с помощью Enet, чтобы избежать (по крайней мере, в данный момент) работы над сетевой частью. Над сервером работа идёт, но неспешно, ибо энтузиазм вещь такая, то он есть и засиживаешься за полночь, то его нет и даже строчки не хочется напечатать. И очень сильно не понятно, как должно быть построено взаимодействие сервера с клиентом. Кстати, почему уведомления перестали приходить на почту?
  12. Пока что плохо знаком с питоном, поэтому делаю как вижу в исходниках. Может и нет разницы. Прогресс есть. Немного печалят мелкие баги, которые, тем не менее, приходится долго искать. Всего-то надо было флаг выставить, чтобы номер пакета добавился. Картинка, видимо, по умолчанию, потому что информация об арене ещё не передана.
  13. Так сразу же попробовал, по аналогии с функциями. SyntaxError: invalid syntax class A(object): def f(self, a): print a o = A.f def h(self, a): print 'hook {0}'.format(a) o(self, a) A.f = h a = A() a.f('fff') Вот простейший пример, не работает. A.f = h ^ SyntaxError: invalid syntax Поэтому просто подменил файл на свой. И сразу же стало понятно, где и в чём ошибка. 2018-07-24 17:44:40.898: INFO: FittingSlotVO_prepareModule []-Vehicle<id:1, intCD:48657, nation:1, lock:(0, 0)>-vehicleChassis-None Первый параметр modulesData равен [], module = modulesData[0] вызывает ошибку, т.к. в modulesData нет элементов. А в __init__ такое описание: modulesData: list of modules, installed in current slot type. There is always one element for vehicle modules and zero to three for optional devices and equipments. If there's no corresponding artifact in slot, empty icon is displayed Взял сдампленный CMD_SYNC_SHOP (с которым ошибки нет) и посмотрел, что же содержится в modulesData. 2018-07-24 20:33:23.533: INFO: FittingSlotVO_prepareModule [VehicleChassis<intCD:57362, type:vehicleChassis, nation:1>]-Vehicle<id:1, intCD:48657, nation:1, lock:(0, 0)>-vehicleChassis-None 2018-07-24 20:33:23.533: INFO: FittingSlotVO_prepareModule [VehicleTurret<intCD:49683, type:vehicleTurret, nation:1>]-Vehicle<id:1, intCD:48657, nation:1, lock:(0, 0)>-vehicleTurret-None 2018-07-24 20:33:23.534: INFO: FittingSlotVO_prepareModule [VehicleGun<intCD:32788, type:vehicleGun, nation:1>]-Vehicle<id:1, intCD:48657, nation:1, lock:(0, 0)>-vehicleGun-None И так далее. А потом Ctrl+F по intCD в CMD_SYNC_SHOP. Нашёл в 'itemPrices' и 'notInShopItems'. Теперь хотя бы знаю, как исправить, когда понадобится. А так разве не будет вызов функции? Ну да, Enter забыл после o(self, a). Работает, хотя и пробовал до этого так же. Попробовал с наследованием, работает. Почему-то делал также до этого, не работало. Тоже Enter что-ли забыл?
  14. Пытаюсь запустить арену. Пока что безрезультатно. Клиент вылетает без сообщений об ошибках, хотя отправляю тоже, что и оригинальный сервер. Пытался ускорить загрузку и отправил совсем немного информации о магазине, как клиент опять начал писать странную ошибку в лог. 2018-07-24 15:28:19.821: ERROR: Traceback (most recent call last): 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/framework/entities/BaseDAAPIComponent.py", line 67, in registerFlashComponent 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/framework/entities/DisposableEntity.py", line 62, in create 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/hangar/AmmunitionPanel.py", line 127, in _populate 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/hangar/AmmunitionPanel.py", line 102, in update 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/hangar/AmmunitionPanel.py", line 155, in _update 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/hangar/AmmunitionPanel.py", line 179, in __updateDevices 2018-07-24 15:28:19.821: ERROR: File "scripts/client/helpers/dependency.py", line 134, in wrapper 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/hangar/AmmunitionPanel.py", line 70, in getFittingSlotsData 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/shared/fitting_slot_vo.py", line 40, in __init__ 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/shared/fitting_slot_vo.py", line 113, in _prepareModule 2018-07-24 15:28:19.821: ERROR: File "scripts/client/gui/Scaleform/daapi/view/lobby/shared/fitting_slot_vo.py", line 64, in _prepareModule 2018-07-24 15:28:19.821: ERROR: IndexError: list index out of range Хотел узнать, что ему не нравится в FittingSlotVO._prepareModule путём установки хука. Для функции получилось легко, а для существующего класса не получается. Пытался вот так from gui.Scaleform.daapi.view.lobby.shared.fitting_slot_vo import FittingSlotVO class FittingSlotVO_hook(FittingSlotVO): def _prepareModule(self, modulesData, vehicle, slotType, slotId): print 'FittingSlotVO_hook {0}-{1}-{2}-{3}'.format(modulesData, vehicle, slotType, slotId) super(FittingSlotVO_hook, self)._prepareModule(modulesData, vehicle, slotType, slotId) FittingSlotVO = FittingSlotVO_hook Но не получается. 2018-07-24 15:36:16.921: ERROR: TypeError: super(type, obj): obj must be an instance or subtype of type Проблема в том, что он ещё и наследуется. Кто-то может подсказать, как поставить хук? Или проще в декомпилированный файл добавить print'оф в нужных местах и в папку модов закинуть?
  15. Этого уже не вспомнил, давно делал и просто забыл, что для реплеев немного по другому.
  16. Из entities.xml берём энтити. Порядок не важен. Парсим секции def-файлов. Если есть секция "Parent", то рекурсивно сначала тот файл, потом этот, результат объединяем. Затем Implements. После, остальные секции. В файле парсим BaseMethods/CellMethods/ClientMethods раздельно. Для них у меня есть enum. typedef enum METHODS_COMPONENT { CLIENT, CELL, BASE, PROPERTIES, } METHODS_COMPONENT; Понадобится секция VariableLengthHeaderSize, по умолчанию принять 1. Ищем секцию Exposed, для ClientMethods у меня обозначено, как ошибка, т.е. его быть не должно. Для остальных, если нет, по идее, можно проигнорировать, потому что этот метод не отправляет клиент. enum { DATA_GHOSTED = 0x01, ///< Synchronised to ghost entities. DATA_OTHER_CLIENT = 0x02, ///< Sent to other clients. DATA_OWN_CLIENT = 0x04, ///< Sent to own client. DATA_BASE = 0x08, ///< Sent to the base. DATA_CLIENT_ONLY = 0x10, ///< Static client-side data only. DATA_PERSISTENT = 0x20, ///< Saved to the database. DATA_EDITOR_ONLY = 0x40, ///< Only read and written by editor. DATA_ID = 0x80, ///< Is an indexed column in the database. // New DATA_REPLAY_UNK = 0x100, DATA_BACKUPABLE = 0x200, }; const char *exposed_type = mxmlGetText(exposed, NULL); if (!exposed_type) { dd->flags |= DATA_OWN_CLIENT | DATA_BASE; } else if (component == CELL && !strcmp(exposed_type, "ALL_CLIENTS")) { dd->flags |= DATA_OWN_CLIENT; } else if (!strcmp(exposed_type, "OWN_CLIENT")) { dd->flags |= DATA_BASE; } else { printf("Error???\n"); assert(FALSE); // bp } Дальше у меня сделано вот так: dd->flags |= component & 7; Где component - это из METHODS_COMPONENT. Давно уже делал, поэтому не помню, зачем и нужно ли это. Дальше, в цикле читаем все аргументы (Arg) и подсчитываем размер, необходимый для сообщения. Размеры стандартных данных "FLOAT", "FLOAT32", "FLOAT64", "INT8", "INT16", "INT32", "INT64", "UINT8", "UINT16", "UINT32", "UINT64", "VECTOR2", "VECTOR3", "VECTOR4" стандартны, размеры "STRING", "PYTHON" сам устанавливаю в -1, чтобы пометить, что данное сообщение не фиксированного размера, соответственно, если среди аргументов встречается этот тип данных, то всё сообщение не фиксированного размера. Для "ARRAY", "TUPLE", если не указан размер (секция size вроде бы), также -1, иначе подсчитываем, согласно аргументам. Для "FIXED_DICT" только аргументы. Далее сохраняем exposed методы в порядке чтения. Устанавливаем флаги. if (component == CLIENT) { dd->flags |= IS_EXPOSED; } if (dd->flags & (IS_EXPOSED | DATA_BASE)) { Exposed_Index_Push(&method->exposed_index, dd->internal_index); } exposed_index - это просто самодельный вектор internal_index - внутренний индекс, соответствует номеру метода в def файле. Exposed_Index_Push - аналог vector.push После того, как всё прочитал, нужно отсортировать по размеру каждую энтити отдельно и каждый метод в энтити отдельно. Sort(&entity->client); Sort(&entity->base); Sort(&entity->cell); Sort(&entity->properties); //properties парсится аналогично, с той лишь разницей, что там Type, а не Arg У меня сортируется qsort_s'ом. И только для method->exposed_index. В функции сравнения. Берём длину сообщения, подсчитанную ранее, Get_Custom_Msg_Length. static int __cdecl Callback_Sort_Index(void *context, const void *key, const void *compared_key) { methods_s *client = context; const uint32_t key_index = *(uint32_t*)key; const uint32_t compared_key_index = *(uint32_t*)compared_key; const data_description_s *dd_key = Data_Description_Get_By_Index(&client->ddv, key_index); const data_description_s *dd_compared_key = Data_Description_Get_By_Index(&client->ddv, compared_key_index); const int length1 = Get_Custom_Msg_Length(dd_key); const int length2 = Get_Custom_Msg_Length(dd_compared_key); if (length2 == length1) { return dd_key->internal_index - dd_compared_key->internal_index; } if (length2 >= 0) { if (length1 >= 0) { return length1 - length2; } } else if (length1 < 0) { return -length1 - -length2; } return length2 - length1; } int32_t Get_Custom_Msg_Length(const data_description_s *dd) { int32_t result = dd->args.size; if (result < 0) { return -Get_Custom_Msg_Length_Header_Size(dd); } else if ((dd->flags & (DATA_OWN_CLIENT|DATA_BASE)) && (dd->flags & (DATA_GHOSTED|DATA_OTHER_CLIENT)) == 1) { return result + 4; } else { return result; } } static int Get_Custom_Msg_Length_Header_Size(const data_description_s *dd) { if (!(dd->flags & (DATA_OWN_CLIENT|DATA_BASE)) || dd->end_index == -1) { return dd->VariableLengthHeaderSize; } else { return 1; } } end_index у меня всегда -1, в движке, по-видимому, не всегда. Всё, отсортировали. Теперь назначаем messageID. Упрощенно, назначается таким образом: к exposed индексу прибавляется число, с которого начинаются методы. properties #define INDEX_CLIENT_SERVER_PROPERTY_BEGIN 0xA2 client #define INDEX_CLIENT_METHOD_BEGIN 0x44 base #define INDEX_EXPOSED_BASE_METHOD_BEGIN 0x87 cell #define INDEX_EXPOSED_CELL_METHOD_BEGIN 0xE Если хоть что-то понятно, то хорошо, потому что объяснять не умею. Да, не важен. Но нужно запомнить их номер, потом что именно он нужен 8 методе реплея (а 7 либо ни разу не встречал, либо не нужен). От того, какая энтити используется, зависит и значение messageID. Для разных энтитей они могут повторяться. Зачем такие сложности придумали разработчики BigWorld, когда можно было бы обойтись двумя байтами, вместо одного, мне не понятно. Видимо, был смысл. Да, и ещё. Сначала парсится spaces.xml, затем entities.xml. Хотя из первого файла ничего не используется, он будет нулевым элементом. @Monstrofil В новом движке у меня срабатывает ассерт на повторяющиеся методы. Поэтому и ошибочно выбирается неправильный. Движок это обрабатывает, а мне не нужно, поэтому не смотрел, как именно обрабатывает.
  17. @Monstrofil Пока что печатаю. Но для 1.0 и выше в движке что-то изменили, поэтому, если надо для этих версий, то не получится. Например, вот пакет. 95 должно быть chatCommandFromClient, а определяется неправильно.
  18. Разобрался. Не знаю, что имел в виду этот человек, что даже заскринил моё сообщение, но именно из-за того, что мне нужны были def файлы, мне и требовались скрипты (scripts.pkg), притом, оригинальные, не изменённые. Это больше риторический вопрос. У программистов BigWorld была причина так сделать. Попробую объяснить. Начал печатать и у меня уже к тебе вопрос. А ты знаешь, как длина сообщения считается? Или тебе этого не надо? Заодно, надо распарсить alias.xml, потому что нужны будут размеры аргументов. Сейчас набросаю примерный план действия.
  19. @maksroker ОК. @Monstrofil Как у них сейчас устроено, мне известно. Просто не понятно, почему не шифруется всё? А то заголовок, clientID не шифрованы, потом шифрование и последние 2 байта вновь не шифрованы. Кстати, для реплеев используется только Blowfish.
  20. Нет, это не при чём. Узнал об этой статье, когда у меня было сделано уже больше, чем там расписано. Автор статьи не смог разобраться с пакетом. Но за эти годы ничего в структуре сетевого протокола не поменялось. Учитывая, что он предпринял первые попытки в 2011, "За отчётные 3 года в схеме входа ничего кардинально не поменялось", то за 7 лет ничего не поменялось (да и почему должно?). Нет, только первые 2 байта являются заголовком (WORD). А в пакете с флагом 1 ещё и 2 последних, которые указывают начало смещения данных. Да, RSA. Но не всё, а только часть, которая содержит авторизацию. Почему не всё, не понятно. Проще было бы весь пакет зашифровать RSA. Дальше автор пошёл не совсем по правильному пути (на мой взгляд), стал вмешиваться в программу. У меня для перехвата используется mitm, свой приватный RSA ключ. После получения Blowfish key можно расшифровывать весь остальной трафик, который будет после авторизации. Но и там, почему-то, первое сообщение идёт не шифрованным, хоть и не содержит ничего конфиденциального, clientID и serverID. Создаётся энтити Login. Передаётся в точности то, что указано в секции Properties файла scripts\entity_defs\Login.def с флагами BASE_AND_CLIENT. В данном случае один параметр, как автор и написал Второй параметр (loginPriority) не передаётся, потому что у него флаг BASE, т.е. клиенту эти данные не доступны. Не все, не всегда. Два байта (а не один, как у автора), как уже написал - это флаги пакета. Поэтому не 0x58, а 0x458, точнее, добавляется флаг 1 << 10, означающий, что в пакете есть номер пакета, который был получен (был помечен, как надёжный, FLAG_IS_RELIABLE, 0x1). Всё верно и логично. Нет, это tickSync, служащий для синхронизации времени. Первый байт - номер пакета (0x13), второй - однобайтовый счётчик. Каждый тик сервера он увеличивается на единицу. Да, это и есть то, что он написал. А вот это мне долго было не понятно. Это некий Channel, увеличивается на 1, когда пакет не содержит флага FLAG_IS_RELIABLE. Иначе остаётся неизменным. Про шифрование он верно написал. Вот за это ГИГАНТСКАЯ благодарность автору. До прочтения этой статьи мне было непонятно, что это. Следующей статьи не вышло, дополню автора. Если размер пакета больше, чем MTU для UDP (но в протоколе меньше, примерно 1276 байт полезной нагрузки), в пакет добавляется флаг FLAG_IS_FRAGMENT 1 << 5, в конец пакета добавляются два номера, один - с какого пакета начинается пересылка, второй - каким закончится, эти номера неизменны. И, собственно, пересылаются все данные. Каждый пакет, естественно, так же содержит всю служебную информацию, заголовок, порядковый номер. Есть ещё одна возможность передать данные, размер которых больше MTU, это в пакете resourceFragment. Отправляется он как результат выполнения функции doCmdInt3 (все доступные можно посмотреть в файле ClientCommandsPort.def, секция BaseMethods, с тегом Exposed), в результате приходит ответ и вызывается функция onCmdResponse, где параметр resultID == RES_STREAM (1). Отличие этого метода пересылки в том, что пакеты приходят с каждым тиком сервера (т.е. один раз в 100 мс). Пакеты с флагом FLAG_IS_FRAGMENT идут один за другим с минимальным интервалом. А вот это никак не помогло. На скриншоте показано количество игроков на сервере/всего. Это вызов функции doCmdInt3 с cmd == CMD_REQ_SERVER_STATS, когда нужный пакет придёт, будет вызвана функция receiveServerStats, содержащая SERVER_STATISTICS (значения можно посмотреть в alias.xml). У меня на скриншотах это видно, как и должно быть в такой ситуации, один игрок. Т.к. сервер один, то общего количества не показывается. Хотя, судя по скринам, сетевой протокол немного изменился за последние 4 года. У автора нет пакета 0x13, вроде бы в то время это 0xd.
  21. У меня уже всё распарсено. У некоторых пакетов неизвестно назначение некоторых полей, структура пакетов, которые ни разу не были получены, тоже не всегда известна. Но у клиента всего 14 сообщений, которые он может отправить на сервер и то, используется 3 штуки, пока в ангаре. Остальное через питон, а там все параметры открыты. Скину всё как-нибудь, что есть. Когда что-то будет готово, что можно показать.
  22. @Pavel3333 Похоже, джуна перерос, но до миддла не дотягиваю. Но это трудно оценить, надо кого-то со стороны. У меня нет соответствующего образования, в какой-то области знания достаточно большие, в другой - нулевые. Нахватался там, здесь, применяю по необходимости. В помощи постоянно не нуждаюсь, задачи не настолько простые. Но сложные задачи за день не сделаю.
  23. Сетевой протокол мне полностью известен. Да, долго, но сейчас всё заключается в том, чтобы добавлять функции-обработчики для пакетов на питоне. Вот это вот да. Больше, чем на покатать одному по карте, рассчитывать не стоит. Хотя, как замену оффсерверу речи, естественно, не идёт. Принято. Потом посмотрю.
  24. Понятно, что нужны будут только коллижн-модели. Когда пытался разобраться со структурой файла, там находил информацию о деревьях. Это тоже нужно будет. Позиции баз, точек респавна техники там же лежит. Структура файла, как помню, достаточно простая, разбито всё на блоки, но дальше не смог сделать, потому что назначение многих блоков не понятно, смещения из одного блока использовались в другом и так далее. Мне, на тот момент не было интересно, что там. Сейчас немного рано. Хотя можно попробовать сделать загрузку карты, а потом недостающий функционал добавлять. Ты можешь всю (необходимую) информацию оттуда достать? Знаешь, как файл устроен?
×
×
  • Create New...