Перейти к содержимому
Korean Random

Monstrofil

Пользователь
  • Публикации

    58
  • Зарегистрирован

  • Посещение

Репутация

39

Контакты

  • Ник
    Monstrofil

Посетители профиля

6 089 просмотров профиля
  1. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    совсем наглея Таки ещё раз предлагаю опенсорснуться, пока интереснейшая тема совсем не заглохла
  2. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Учитывая что сервер собирается под linux, я очень удивился бы наличию sln
  3. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Вы меня ещё больше запутали Понятное дело что ВГшные правки не утекали. В изначальном сообщении говорилось что исходников сервера (т.е. даже "ванильных") нет даже в древнем сливе bw191(?), а во втором @Dragon armor упоминает что есть только линуксовые бинари. Но в то же время я их прямо сейчас наблюдаю в виде сорсов.
  4. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    А в тех что я кидал разве серверной части нет?
  5. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Что-то все разбежались... а опенсорснуть свои достижения никто не желает?
  6. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Что-то мне подсказывает что все же физ. движок если не захлебнется от такого количества моделей, то как минимум начнет подтормаживать. И в итоге придется сначала писать препроцессор, который поубирает лишние полигоны.
  7. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    XXXXZZZZ[o|i].chunk, каждый 100х100 попугаев. В питоне есть метод BigWorld.findChunkFromPoint(point, spaceID), можешь проверить, но емнип ты правильно написал. spaceID можно из какой-нибудь entity вытянуть
  8. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    @Dragon armorпроверил танки, тут это пакет 0x24 в реплее, используется для обновления destroyedFragiles/fallenColumns/fallenTrees/damageStickers/других list/dict . ...или вот DEBUG:root:nested property request for id=10261187 isSlice=True data=ef0093bda506 DEBUG:root:next path item: fallenTrees(3) DEBUG:root:object: [[0, 141, 189, 112, 163], [0, 145, 189, 113, 58], [0, 146, 189, 128, 30]] <class 'def_generator.nested_types.PyFixedList'> DEBUG:root:Bits per array index: 2 DEBUG:root:List index: 3 DEBUG:root:Slice index: 3 DEBUG:root:new list object: [[0, 147, 189, 165, 6]] DEBUG:root: DEBUG:root: DEBUG:root:nested property request for id=10912843 isSlice=True data=e3c00802ea66e2ed5d87 DEBUG:root:next path item: damageStickers(12) DEBUG:root:object: [11992011582228136455L, 4675071338421158407L, 5466597707613143559L] <class 'def_generator.nested_types.PyFixedList'> DEBUG:root:Bits per array index: 2 DEBUG:root:List index: 3 DEBUG:root:Slice index: 3 DEBUG:root:new list object: [9754213924599366152L] Те же три пустых байта в пакете, тот же формат. self.entity_id, = struct.unpack('I', stream.read(4)) self.is_slice = struct.unpack('b', stream.read(1))[0] == 1 self.payload_size, = struct.unpack('b', stream.read(1)) self.u = stream.read(3) # unknown self.payload = stream.read() Так что если будут с ним проблемы - пиши, попробую помочь.
  9. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Так вот без контекста сложно сказать... причешу код для корабельных реплеев и опопробую то же самое на танковых, тогда смогу сказать точно. К примеру, разбор одного из упакованных путей для изменения свойства entity.state['resources'][0]['amountByEntities'][2]. 1010 1110 0111 1110‬ | AE 7E + PAYLOAD len(entity) == 11 => 4 bytes for entityPropertyId ‭1 0101 => entityPropertyId = 5 => state len(entity.state) == 16 keys in dict => 4 bytes 1 1001 => PropertyId = 9 => resources //resources - под индексом 9 в .def файле len(entity.state['resources']) == 1 item in array => 0 bytes 1 => PropertyId = 0 => resorces[0] len(entity.state['resources'][0]) == 2 keys in dict => 1 bytes 1 1 => PropertyId = 1 => resources[0]['amountByEntities'] //amountByEntities - под индексом 1 в .def файле len(entity.state['resources'][0]['amountByEntities']) == 3 items in array => 2 bytes 1 10 => PropertyId = 2 => resources[0]['amountByEntities'][2] 0 => exit while Object by path: {'current': 0, 'max': 550, 'id': 550, 'min': 0}, len = 4 => 3 bytes 001 => 1 => current
  10. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Именно что 3 байта, не знаю их предназначение но они всегда по нулям.. Да, это оно, а obj.childLength() - как раз текущее кол-во свойств (размер массива / кол-во ключей в словаре / кол-во свойств в entity).
  11. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    @Dragon armor, короче разобрался с этим кошмаром, австралийские(?) разрабы решили там зачем-то экономить каждый бит(!). Определить setNested/setSlice можно по флагу в пакете, он сразу после entityId лежит. Потом лежит размер, 3 байта 0x00 и, собственно, данные (по крайней мере в реплее). Что setNested что setSlice начинаются с упакованного пути к изменяемому элементу, читать приходится побитово. Псевдокодом будет примерно так. pOwner = entity while bits.pop(0) == 1 && pOwner length = obj.childLength() // длина массива || кол-во элементов в словаре || для entity - кол-во свойств bits = bitsRequires(length) // смотрим сколько бит нужно дабы уместить индекс для контейнера выше => ceil(log(length, 2)) propertyId = readBits(bitsArray, bits) // читаем нужное кол-во бит, недостающее добиваем нулями до "целого" байта, переводим в int32 pOwner = pOwner.getPropertyByIndex(propertyId) // для массива - берем по индексу элемент, для словаря - по порядковому номеру свойство в .def файлике, для entity - по exposedId Потом (уже вне цикла while) начинаются отличия, для setNested читаем индекс изменяемого свойства как обычно: maxBits = bitsRequires(pOwner.childLenght()) propertyId = readBits(bits, maxBits) Всё, остаток информации можно распаковать используя тип данных из def/alias. Для setSlice чуть иначе maxBits = bitsRequires(pOwner.childLenght() + 1) index1 = readBits(bits, maxBits) index2 = readBits(bits, maxBits) // если индекс превышает кол-во элементов в pOwner -> добавляем новый // если index2 > index1 && payload == None -> удаляем из массива // замены, похоже, выполняются через setNested В общем-то ничего особо сложного когда разобрался, но мозг мне этот пакет выносил долго...
  12. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    С setNested_PROPERTY / setSlice_PROPERTY ещё не сталкивался?
  13. Monstrofil

    Распакова *.pkg файлов

    Декомпильнуть - не знаю, а влезть можно через copy_reg.pyc. Правда ходят слухи за модификацию скриптов присылают письма счастья. Вкратце: в idx лежат: - список нод (mx32 байта, тут есть id и parent_id) - строки-соответствия нодам - список структур с информацией о файлике (nx40 байт), тут же можно найти смещение и размер файла в .pkg Периодически формат немного меняют. https://github.com/Monstrofil/project_m/blob/master/dev/ResMgr.py
  14. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    @Dragon armor, действительно что-то заумное придумали разрабы BigWorld, особенно с этой зависимостью exposedId от размера пакета... Anyway, проверил работоспособность на версии 1.0.2.2. Для моих нужд нужны только ClientMethods, так что и парсил только их. В общем что пришлось сделать: 1. Парсим .def не забывая про implements и parent, записываем ClientMethods в список в порядке чтения def-файлов (необходимо для корректной сортировки сообщений с variable-length. 2. Высчитываем длинну тех сообщений, которые можем (те, которые нельзя вычислить помечаем как +inf) 3. Сортируем массив сообщений по их длинне. exposedIndex - индекс нужного метода в массиве после сортировки по длинне сообщения, никаких INDEX_CLIENT_METHOD_BEGIN добавлять не нужно. Прогнал на нескольких реплеях, все сообщения распаковуются без проблем. p.s. Properties по той же схеме работают.
  15. Monstrofil

    Мод "Эмулятор сервера World of Tanks".

    Кстати, может и правильно определяется, т.к. chatCommandFromClient в последнем клиенте вообще нет. UPD: а, не, обманываю, chatCommandFromClient есть в интерфейсе "Chat", сорри.
×