Jump to content
Korean Random
Dragon armor

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

Recommended Posts

28.06.2022 в 16:15, DrWeb7_1 сказал:

Как можно собрать то, чего нет?

 

Код шредингера.

Share this post


Link to post

Short link
Share on other sites

Каким образом можно достать цену на элемент кастомизации, если его нет в блоке itemPrices каталога Магазина?

 

image.png.5ef2a7599481e551a257dd8e57034b15.png

У объекта c11n_components.CamouflageItem нет атрибута, связанного с ценой, есть только priceGroup (priceGroupTags), но это не то и не туда — просто перечисление технических свойств элемента кастомизации, например 'legacy', 'camo', 'ussr' для ряда из спойлера.

Если цены находятся в c11n_components.CustomizationCache, то где они? Если нет, то какие варианты, кроме парсинга XML?

 

Проблема неактуальна, ошибся при поиске. Ничего не пропало никуда.

Edited by DrWeb7_1
Доктору нужен доктор. Всё нормально.

Share this post


Link to post

Short link
Share on other sites

@AddNikita , ну вот как раз тебе задачка на разобраться, если хочется помочь (да, я умею отвечать с сильной задержкой).

Share this post


Link to post

Short link
Share on other sites
20 минут назад, kerbal сказал:

Приветствую, модификация готова к использованию?

Ты где-то видишь ссылку на скачивание?

Share this post


Link to post

Short link
Share on other sites

Автору огромный респект за проделанную работу !

Хотелось бы увидеть хоть какие-то исходники(наработки), даже сырые и недоделанные ! либо какие-нибудь контакты для кооперирования. 

Share this post


Link to post

Short link
Share on other sites

@Dragon armor привет, если ещё бываешь тут, подскажи пожалуйста пару моментов.

 

Вклинился между клиентом и сервером wows, получаю и дешифрую пакеты используя blowfish, но возникает много вопросов.
1. Получаю пакет entityCreate, в данном случае происходит создание Login entity. Декодирую, получаю entityid и список properties (для этой entity в корабликах они пустые)

# login entity create payload (no props on setup)
# header?      ?? entityid def id  ??  footer?
# 5804138f0508 00 e9e01330 0600    00  01020000000100000075f05577efbeadde05
login_create = b'X\x04\x13\x8f\x05\x08\x00\xe9\xe0\x130\x06\x00\x00\x01\x02\x00\x00\x00\x01\x00\x00\x00u\xf0Uw\xef\xbe\xad\xde\x05'

 

2. Получаю другой пакет через некоторое время, с запросом выполнить метод syncUserStorage (угадал по параметрам, перепроверил через python shell, это точно он).

# login call sync method
# syncUserStorage ([clientDataRevision: <UInt32>, spaID: <UInt64>, urls: <Array> [<String>, ...]])
# exposed id = 2 (with 0x44 offset = 0x46)
# header      method id   ?? clientDataRevision   spaID              urls.len   string.len
# 580413941a  46          6b 01000000             5f79581e00000000   01         5d
# string = https://s-ed1.cloud.gcore.lu/530-wows-users-params/hhh/ggg/fff/eee/ddd/c1e5/b21e/f509114719d1
# 68747470733a2f2f732d6564312e636c6f75642e67636f72652e6c752f3533302d776f77732d75736572732d706172616d732f6868682f6767672f6666662f6565652f6464642f633165352f623231652f663530393131343731396431
# footer
# 090000000100000000efbeadde02
login_sync = b'X\x04\x13\x94\x1aFk\x01\x00\x00\x00_yX\x1e\x00\x00\x00\x00\x01]https://s-ed1.cloud.gcore.lu/530-wows-users-params/hhh/ggg/fff/eee/ddd/c1e5/b21e/f509114719d1\t\x00\x00\x00\x01\x00\x00\x00\x00\xef\xbe\xad\xde\x02'

 

В пакете есть exposed id, есть данные для вызова метода, но я в упор не вижу как определить entity id для которой нужно выполнить указанные действия. Полученный в первом сообщении e9e01330 вообще больше нигде в декодированном трафике не фигурирует.

 

Оба пакета меньше 32 байт, делиться в моем понимании на части они не должны, так как же клиент определяет какой для entity нужно вызвать метод?

 

 

upd, а вот тот же call method для Account, тоже нет никаких упоминаний про entity id
 

# account id on creation b'\xb5H\x0f0'
# 0x44 + 44 onCheckGamePing ([time: <UInt64>])
#             method id   time                      footer?
# 580413691a  70          f971310000000000          770d0000780c0000f32935c5beefbeadde06
onCheckGamePing = b'X\x04\x13i\x1ap\xf9q1\x00\x00\x00\x00\x00w\r\x00\x00x\x0c\x00\x00\xf3)5\xc5\xbe\xef\xbe\xad\xde\x06'

upd2: всли посмотреть в разрезе времени как меняются параметры, то получается такая картина, ничего статического что могло бы служить entity id я не наблюдаю :sad:
 

# account id on creation b'\xb5H\x0f0' aka b5480f30
# 44 onCheckGamePing ([time: <UInt64>])
# flags?  counter?    packet id?  method id   time                      footer?
# 5804    1369        1a          70          f971310000000000          770d0000 780c0000  f32935c5be  efbeadde06
# 5804    136a        1a          70          5c312a0000000000          78000000 3c000000  08c84f708d  efbeadde06
# 5804    136d        1a          70          06332a0000000000          7b000000 3f000000  ce0e17c551  efbeadde06
# 5804    136e        1a          70          8d332a0000000000          7c000000 40000000  e1f376a5f2  efbeadde06
# 5804    136f        1a          70          20342a0000000000          7d000000 41000000  d33eb24317  efbeadde06
# 5804    1370        1a          70          b4342a0000000000          7e000000 42000000  1cd046fac3  efbeadde06
# 5804    1371        1a          70          3a352a0000000000          7f000000 43000000  882900003a  efbeadde06
# 5804    1372        1a          70          ce352a0000000000          80000000 45000000  db5c1dbb1e  efbeadde06

 

upd3: нашел ещё пакет в котором сразу два вызова entitymethod, тот же запуск игры что и в предыдущих. Почему-то нет информации о том что пакет содержит два payload в первых 8 байтах, видимо искать нужно в footer'e. Возможно там же где-то entity_id, но его я в упор не вижу.
 

# onCheckGamePing + onTotalUsersCountUpdate in one packet
# 580413871a7087412a00000000001a802f2e80027d71012855024e414d682055044153494171024db917550d43555252454e545f5245414c4d71034d3362752e950000005a00000022aeaaefbeadde04
# flags?  counter?    packet id?  method id   time = 2769287
# 5804    1387        1a          70          87412a0000000000
#
#                     packet id?  method id   ??     size
#                     1a          80          2f     2e
#
#                     pickle data {'NA': 8423, 'CURRENT_REALM': 25482, 'ASIA': 4917}
#                     80027d71012855024e414d682055044153494171024db917550d43555252454e545f5245414c4d71034d3362752e
#                     footer
#                     95000000 5a000000 22aeaa efbeadde04

 

Edited by Monstrofil

Share this post


Link to post

Short link
Share on other sites
2 часа назад, Monstrofil сказал:

5804

Это флаги, да. Вроде бы определение типа пакета относительно BigWorld, типа «надёжный», «фрагмент пакета», и подобное.

 

onCheckGamePing, он из скриптов как-то вызывается?

2 часа назад, Monstrofil сказал:

counter

Может быть, это какой-то ответ (или запрос) на функцию из аналогичного WoT AccountCommands? У них сначала идёт requestID, потом уже аргументы, которые передаются серверу. requestID в любом случае шлётся клиентом и сервер должен на него вернуть пакет с таким же номером. Возможно, я спутал всё.

Edited by DrWeb7_1

Share this post


Link to post

Short link
Share on other sites
12 минут назад, DrWeb7_1 сказал:

onCheckGamePing, он из скриптов как-то вызывается?

 

Хм, я изначально предположил что этот пакет сервер просто присылает с сервера периодически, но, похоже, у него есть зеркальный запрос checkGamePing идущий от клиента к base server.
 


# client -> base (checkGamePing)
#             flags?  counter?    packet id?  method id?                                     request id?
# request ->  5804    01ff        93          15          9a960800c9302a00 00000000 3a000000 77000000     59 efbeadde02
#             5804    01ff        93          15          9a9608005c312a00 00000000 3b000000 78000000     2f efbeadde02
#             5804    01ff        93          15          9a960800df312a00 00000000 3c000000 79000000     a7 efbeadde02

# base -> client (onCheckGamePing)
#             flags?  counter?    packet id?  method id   time             request id?
# response -> 5804    1369        1a          70          c9302a0000000000 77000000     3b000000 de0695d2     f9 efbeadde06
#             5804    136a        1a          70          5c312a0000000000 78000000     3c000000 08c84f70     8d efbeadde06
#             5804    136b        1a          70          df312a0000000000 79000000     3d000000 7468438d     e3 efbeadde06


Если присмотреться, то 77000000 из футера первого сообщения клиента соответствует первому ответу сервера и так далее. А 3b000000 которое вернул сервер в футере используется в следующем запросе от клиента к base. 

И всё равно в упор не вижу где связь с entity id =/

Share this post


Link to post

Short link
Share on other sites
11 минут назад, Monstrofil сказал:

Хм, я изначально предположил что этот пакет сервер просто присылает с сервера периодически, но, похоже, у него есть зеркальный запрос checkGamePing идущий от клиента к base server.

У танков это именно зеркальный запрос-ответ, например, так со статистикой игроков на сервере/кластере. Каждые несколько секунд клиент посылает AccountCommands.CMD_REQ_SERVER_STATS (блок команд CmdInt3, в ангаре через Account, в бою через Avatar, но вроде уже статистика игроков на сервере/кластере в бою не показывается последние восемь, а то и более, патчей).

Проверку пинга в танках не смотрел.

11 минут назад, Monstrofil сказал:

И всё равно в упор не вижу где связь с entity id =/

У каждой сущности, например, как в WoT, есть свои команды, которые могут (не обязаны) быть общими. Вероятно, у тебя к сущности Login, если я правильно понял, прилепили проверку пинга. Она в порту (или как там ангар называется) деактивируется, отдавая управление Account или ты Login расковыриваешь на самом экране логина?

Edited by DrWeb7_1

Share this post


Link to post

Short link
Share on other sites
7 минут назад, DrWeb7_1 сказал:

Вероятно, у тебя к сущности Login, если я правильно понял, прилепили проверку пинга. Она в порту (или как там ангар называется) деактивируется, отдавая управление Account или ты Login расковыриваешь на самом экране логина?

checkGamePing и onCheckGamePing это уже методы Account, Login к этому времени уже давно уничтожается.

Я просто привожу эти примеры поскольку с Account у меня та же проблема что с Login. Если вдаваться чуть подробнее, то происходит следующее:
1. приходит сообщение entityCreate, в нем есть entityId - уникальный идентификатор entity и наверняка есть request id, на который я в данный момент подзабил.
2. через время уходят - приходят запросы на вызов base/client методов, в которых уже не фигурирует entity id. как клиент определяет какой из существующих на данный момент в клиенте entity нужно вызвать метод onCheckGamePing (предварительно декодировав его из exposedId), если в самом запросе нет entityId? неужели он хранит цепочку request id для определения entityId исходя из первого entitycreate?

В реплеях было проще, там все запросы на entitymethod лежат сразу с entityid и exposedinxex =/
 

    def __init__(self, stream):
        self.entityId, = struct.unpack('I', stream.read(4))
        self.messageId, = struct.unpack('I', stream.read(4))

        self.payload = BinaryStream(stream)

 

Edited by Monstrofil

Share this post


Link to post

Short link
Share on other sites
30 минут назад, Monstrofil сказал:

приходит сообщение entityCreate, в нем есть entityId - уникальный идентификатор entity и наверняка есть request id, на который я в данный момент подзабил.

А если полученными переменными воспользоваться?

31 минуту назад, Monstrofil сказал:

неужели он хранит цепочку request id для определения entityId исходя из первого entitycreate?

Пока разбирался в устройстве мода оффлайн-ангара WoT, меня такой же вопрос посетил, когда я увидел, что данные аккаунта синхронизируются без явного указания что есть что. Клиент не говорит «хочу сначала профиль, потом статистику, потом магазин». Он либо ожидает такую последовательность, которую сервер должен магическим образом понять из одного AccountCommands.CMD_SYNC_DATA, в котором нет аргументов (ЕМНИП), либо может переставить данные местами, если они придут в другом порядке. ХЗ.

Share this post


Link to post

Short link
Share on other sites
4 часа назад, Monstrofil сказал:

1. Получаю пакет entityCreate, в данном случае происходит создание Login entity. Декодирую, получаю entityid и список properties (для этой entity в корабликах они пустые)

4 часа назад, Monstrofil сказал:

так как же клиент определяет какой для entity нужно вызвать метод

Через entityCreate энтити создаётся и используется дальше пока не будет создана новая.

Edited by Dragon armor

Share this post


Link to post

Short link
Share on other sites
8 минут назад, Dragon armor сказал:

Через entityCreate энтити создаётся и используется дальше пока не будет создана новая.

Такое поведение только при общении с Base? А в бою что будет, где 28+ энтитей создается? Или там уже общение с Cell и чуть другие параметры в пакетах?

До Cell ещё не добрался.

Share this post


Link to post

Short link
Share on other sites
8 минут назад, Monstrofil сказал:

А в бою что будет, где 28+ энтитей создается?

Либо сервер явно указывает, какая энтити на данный момент активна (например, через selectEntity), либо сами (внутренние) функции устанавливают энтити активной (множества функций начинающихся с avatarUpdate* и другие). Энтити игрока устанавливается через selectPlayerEntity.

Share this post


Link to post

Short link
Share on other sites
13 часов назад, Dragon armor сказал:

Либо сервер явно указывает, какая энтити на данный момент активна (например, через selectEntity), либо сами (внутренние) функции устанавливают энтити активной (множества функций начинающихся с avatarUpdate* и другие). Энтити игрока устанавливается через selectPlayerEntity.

Ну, это может сработать в сторону сервера, но не наоборот. Когда на клиенте 28 энтити и нужно у каждой из них повызывать методы то явно где-то должен быть entityID в запросе. Ладно, проверю эту теорию позже.

 

Цитата

Не все, не всегда. Два байта (а не один, как у автора), как уже написал - это флаги пакета. Поэтому не 0x58, а 0x458, точнее, добавляется флаг 1 << 10, означающий, что в пакете есть номер пакета, который был получен (был помечен, как надёжный, FLAG_IS_RELIABLE, 0x1).

Тут ещё в теме в самом начале обсуждали флаги пакетов и отметили FLAG_IS_RELIABLE одновременно как 0x1 и 1 << 10, хотя в сорсах BW он вообще 0x0010.

Учитывая что FLAG_IS_FRAGMENT = 0x0020 из сорсов совпадает с реальностью, FLAG_IS_RELIABLE
на первой странице это опечатка, или действительно поменяли идентификатор?

Share this post


Link to post

Short link
Share on other sites

Так, пока разбирался с FRAGMENT пакетами ещё одна загадка нарисовалась.

 

На клиент приходит вызов метода с двумя BLOB и INT8 следующего содержания

# onGetMapList
# arg1 (blob len=14186, 6a37 in hex)        arg2 (blob len=13, 0d in hex)      arg3 (int8)
# 789c959d057...c51695c2bf7de0ffd0b5f8ce    789c6b600a65d0030003ba0106         0

Размер первого Blob = 14186 + второго 13 + int8 дает 14200 байт.

Но если посмотреть в пакеты, то там следующие значения:

# in packet
# methodid   size of arg1 (14205)    arg1 (blob len=14186, 14205-14186 = 19)       size of arg2   arg2                          arg3 (int)
# 7c         ff7d370000              789c959d057...c51695c2bf7de0ffd0b5f8ce        0d             789c6b600a65d0030003ba0106    00

Размер второго Blob описан правильно, Int8 присутствует, но размер парвого blob декодируется как 14205, что больше чем размер payload в целом.

 

Размер первого blob распаковываю используя магию от разработчиков BW по упаковыванию int32 в три байта.
https://github.com/Monstrofil/bigworld-2.0/blob/5969290b3f1710910c7cecdad6a34b2016fad9e7/lib/cstdmf/binary_stream.hpp#L265
https://github.com/Monstrofil/bigworld-2.0/blob/5969290b3f1710910c7cecdad6a34b2016fad9e7/lib/cstdmf/binary_stream.ipp#L162

Кто-нибудь уже сталкивался с подобным?

 

 

upd: целый день с этим провозился и только сейчас заметил что размер blob по какой-то причине дописан в конец payload, сразу после uint8.

ff6a3700

А ff7d370000 это размер всего payload в целом :wacko:

 

 

UPD 09.11.

Разбирался сегодня с выравниванием под blowfish. Предварительно пришел к следующему: последний байт = количество добавленных байт - 1. Добавленные байты находятся сразу перед efbeadde и, похоже, ничего не значат. По какой-то причине добавляются не нулевые значения, причин этого понять не удалось.

# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'enddata123', 42)
# 5804 01d3abf17a ba19 00 00 00000000 00000000 000a656e6464617461313233  2a000000 4f150000 c8190000 efbeadde 01
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'enddata12', 42)
# 5804 01d3abf17a ba18 00 00 00000000 00000000 0009656e64646174613132    2a000000 a3160000 521b0000 00 efbeadde 02
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'enddata1', 42)
# 5804 01d3abf17a ba17 00 00 00000000 00000000 0008656e646461746131      2a000000 3a150000 b1190000 5f9f efbeadde 03
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'enddata', 42)
# 5804 01d3abf17a ba16 00 00 00000000 00000000 0007656e6464617461        2a000000 10120000 f4150000 545f52 efbeadde 04
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'enddat', 42)
# 5804 01d3abf17a ba15 00 00 00000000 00000000 0006656e64646174          2a000000 b8130000 df170000 04545f52 efbeadde 05
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'endda', 42)
# 5804 01d3abf17a ba14 00 00 00000000 00000000 0005656e646461            2a000000 c5130000 eb170000 3767da15a1 efbeadde 06
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'endd', 42)
# 5804 01d3abf17a ba13 00 00 00000000 00000000 0004656e6464              2a000000 d1130000 f6170000 000004545f52 efbeadde 07
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'end', 42)
# 5804 01d3abf17a ba12 00 00 00000000 00000000 0003656e64                2a000000 dd130000 01180000 00000004545f52 efbeadde 08
# >>> BigWorld.player().base.getAccountData('', '', 0, 0, 'en', 42)
# 5804 01d3abf17a ba11 00 00 00000000 00000000 0002656e                  2a000000 a0140000 f0180000 efbeadde 01

Написал код который заменяет рандомный мусор в дополнительных байтах на нужное количество 0xff, скормил такие ответы клиенту и серверу и ничего не поменялось.

Edited by Monstrofil

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...