Jump to content
Korean Random

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


Recommended Posts

@Dragon armor, а в танках в пакете entity create всегда полностью передается position и direction?
Или как в корабликах, для некоторых вместо 12 байт direction приходит всего 4? Похоже что это как-то зависит от <Volatile> в def файле.

  • Upvote 1
Link to comment
Short link
Share on other sites

@m3ybach Сделать можно, но вряд ли будет легче. Принцип-то тот же.

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

в танках в пакете entity create всегда полностью передается position и direction?

Позиция передаётся тремя float, а направление пожато до четырёх байт.

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

Похоже что это как-то зависит от <Volatile> в def файле.

Не, не зависит. От реализации может зависеть, в кораблях тоже решили съэкономить 8 байт, непонятно только, зачем.

Link to comment
Short link
Share on other sites

18.11.2022 в 00:10, Dragon armor сказал:

От реализации может зависеть, в кораблях тоже решили съэкономить 8 байт, непонятно только, зачем.

Сдампил сегодня список таблицу методов в клиенте и оказалось что есть entityCreate и entityCreateDetailed, отличаются они на 8 байт, как раз в месте где передается direction. Экономки, блин.

 

Добавил новые методы, парсинг начал проходить чуть успешнее и появились новые проблемы.

1aa10109
1aa10112
1aa106110493c2c2c2

 

Ранее в сообщении 1a были закодированы либо вызовы методов либо свойства (те самые, с offset 0x44 и 0xa2). Теперь же, на примере последнего, приходит что-то что уже не метод (методов меньше у entiity), но ещё не свойство.

 

message id  submessage id   size        attribute id   payload
1a          a1              06          11             0493c2c2c2

0x11 + 0xa1 - 0x44 = 110

 

Свойств у текущей entity класса Avatar всего 4, методов - 92. 

 

 

upd 
 

  

avatarUpdateNoAliasFullPosYawPitchRoll
avatarUpdateNoAliasFullPosYawPitch
avatarUpdateNoAliasFullPosYaw
avatarUpdateNoAliasFullPosNoDir
avatarUpdateNoAliasOnGroundYawPitchRoll
avatarUpdateNoAliasOnGroundYawPitch
avatarUpdateNoAliasOnGroundYaw
avatarUpdateNoAliasOnGroundNoDir
avatarUpdateNoAliasNoPosYawPitchRoll
avatarUpdateNoAliasNoPosYawPitch
avatarUpdateNoAliasNoPosYaw
avatarUpdateNoAliasNoPosNoDir
avatarUpdateAliasFullPosYawPitchRoll
avatarUpdateAliasFullPosYawPitch
avatarUpdateAliasFullPosYaw
avatarUpdateAliasFullPosNoDir
avatarUpdateAliasOnGroundYawPitchRoll
avatarUpdateAliasOnGroundYawPitch
avatarUpdateAliasOnGroundYaw
avatarUpdateAliasOnGroundNoDir
avatarUpdateAliasNoPosYawPitchRoll
avatarUpdateAliasNoPosYawPitch
avatarUpdateAliasNoPosYaw
avatarUpdateAliasNoPosNoDir

Мдааа, тяжелое наследие Dial-up (ADSL?) у этого движка =/

Edited by Monstrofil
Link to comment
Short link
Share on other sites

13 часов назад, Monstrofil сказал:

Мдааа, тяжелое наследие Dial-up (ADSL?) у этого движка

Самое раннее появление этого движка на видео — 1999 год, так что ты даже попал.

 

Link to comment
Short link
Share on other sites

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

тяжелое наследие Dial-up (ADSL?) у этого движка =/

Да это макросы, это же очевидно. Поищи в исходниках по avatarUpdate и увидишь, что названия ими генерируются, как и параметры, которые они принимают/отправляют.

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

Ранее в сообщении 1a были закодированы либо вызовы методов либо свойства (те самые, с offset 0x44 и 0xa2). Теперь же, на примере последнего, приходит что-то что уже не метод (методов меньше у entiity), но ещё не свойство.

Как вариант - количество базовых методов изменилось, вот и поменялись начальные идентификаторы у свойств и методов. 0x44 и 0xa2 - не константы, уже писал это. Они генерируются в зависимости от количества свойств/методов у энтити. Можно даже поискать в исходниках, хотя это могло измениться и искать, как именно теперь назначаются индексы, надо в исполняемом файле.

Например, EntityMethodDescriptions::checkExposedForSubSlots.

Link to comment
Short link
Share on other sites

16 минут назад, Dragon armor сказал:

Да это макросы, это же очевидно. Поищи в исходниках по avatarUpdate и увидишь, что названия ими генерируются, как и параметры, которые они принимают/отправляют.

 

Я видел эти макросы, "тяжёлое наследие" это не отменяет :)

 

Link to comment
Short link
Share on other sites

Эти магические номера методов это что-то что мой мозг отказывается понимать, даже после прочтения кода отосящегося к subslots.

Залез в клиент через python shell, поставил трейс на вызовы любых методов у Account entity.
Что происходит в клиенте:

('onGetPortsInfo', (PlayerAccount at 0x000001D82E0086D8, 'x\x9c%\x8d\xbdR\x83@\x14Fc\x08\x10b\xa2FM\xfc\xb7\xa6\xca\x8c\x9d\xcf\x9046\xb7d\xc6\x0bl\xd8\x15\xd8\xe5\xde]d\xb0\xb2K\xedS\xf82\x16>\x92\xcc\xd8\x9dsf\xbe\xf9>\xc7\t\x1d\xc5\t\x8dc\xf0S\xb4*#\x0f\xc2\x86E\xad\xda\x9a&\xe0\x9bL\xa0&\x1f<\xdb\xa4\x14@P\x19\x9d\x1bM!x\xd2\xeei\n\xa1\x16]o\xb8\xa4\x08\xbc\x9c{\x9aA\x98\xb7\xbaTC9\x86\xa8F\xb6BU\x95\xa09\x84\x12\xeb\xb4\xe5\x82\x16\x10\x95l\xb4u\x98;:\x81E&\x95F\xe4F\x14\x852t\n\xbe\xc3tX\x9c\x81\xaf\x1cV=-!\xd8\xbf\x19\xce-\x9d\xc3\\\x9bw\xc3\xc6Z\xd5\xdb\x92.`R\xb6,\xe8\x12\x02\xd7)\x97IZ\xc1\x14?Z\xaeP\x0bZC\x88\r\xab\xea\xe9\x99\xae b\xe3\x9c\xe0\x1ck\xba\x06\x8f\x87\xa3\x1b\x91\xd0m,W\xbb\xd1nt\xa0;\xb9\xfe\x87{\xe9o\x7f\xbf_\xb3\xed\xcf\xa2\xcb\x0e\xf4 g\xdb\x97e7h\xf95\xe8\xa3\x90\x9e\xd8\xfc\x01\xed\xeeg?'), {})

('updateBalanceStatus', (PlayerAccount at 0x000001D82E0086D8, 1), {})

('onCheckGamePing', (PlayerAccount at 0x000001D82E0086D8, 45570L), {})

 

В этот же момент в сообщениях:

# 0x7e - 0x44 == 0x3a == onGetPortsInfo ([unknown: <Blob>])
# 7eff12010000789c258dbd528340144663081062a2464dfcb7a6ca8c9dcf903436b764c60b6cd815d8e5de5d64b0b24bed53f832163e92ccd89d7366bef93ec7091dc5098d63f053b42a230fc28645adda9a26e09b4ca0261f3cdba4144050199d1b4d2178d2ee690aa1165d6fb8a408bc9c7b9a4198b7ba54433986a846b6425595a0398412ebb4e5821610956cb475983b3a8145269546e446148532740abec374589c81af1c563d2d21d8bf19ce2d9dc35c9b77c3c65ad5db922e6052b62ce81202d72997495ac1143f5aae500b5a43880dabeae999ae2062e39ce01c6bba068f87a31b91d06d2c57bbd16e74a03bb9fe877be96f7fbf5fb3edcfa2cb0ef42067db97653768f935e8a3909ed8fc01edee673fff0e0100

# selectPlayerEntity
# 1a

# ??
# a0

# selectPlayerEntity
# 1a

# ??
# a10109

# selectPlayerEntity
# 1a

# ??
# a10112

# selectPlayerEntity
# 1a

# 0x50 - 0x44 == 0x0c == updateBalanceStatus ([unknown: <UInt8>])
# 5001

# selectPlayerEntity
# 1a

# ??
# a106110493c2c2c2

# 0x70 - 0x44 == 0x2c == onCheckGamePing ([unknown: <UInt64>])
# 7002b2000000000000

 

Если на a10100, a10112, a106110493c2c2c2 можно было бы ещё подумать что они свойства, то a0 в такой формат не вписывается. Но это и не метод, никаких методов в это время не вызывалось.

 

С другой стороны иногда 2 байт (a1*06*110493c2c2c2) обозначает длину даных, т.е. это скорее всего varible-len сообщения.

 

p.s. у Account 92 exposed метода и 4 client-server свойства.
p.p.s. 0x44 и 0xa2 в клиенте всё ещё фигурируют. в asm видно что клиент заполняет entityMethod hander'ом структурку, где хандлеру соответсвуют индексы от 0x44 до 0xa2.
 

00E44FE0  Call to WorldOfWarships32.00E44FE0 from WorldOfWarships32.00A8D453
            ; registerMessage
            02336078  Arg1 = ASCII "updateEntity"
            00000001  Arg2 = 1
            00000002  Arg3 = 2
            027B75A8  Arg4 = WorldOfWarships32.27B75A8
00E44FF9  INT3: AL = 43 (67.)
00E44FE0  Call to WorldOfWarships32.00E44FE0 from WorldOfWarships32.00A8D493
            ; registerMessage
            02336068  Arg1 = ASCII "entityMethod"
            00000002  Arg2 = 2
            00000000  Arg3 = 0
            027B75D8  Arg4 = WorldOfWarships32.27B75D8
00E44FF9  INT3: AL = 44 (68.)
00E44FE0  Call to WorldOfWarships32.00E44FE0 from WorldOfWarships32.00A8D503
            ; registerMessage
            02336058  Arg1 = ASCII "entityProperty"
            00000002  Arg2 = 2
            00000000  Arg3 = 0
            027B75F0  Arg4 = WorldOfWarships32.27B75F0
00E44FF9  INT3: AL = 0A2 (162.)


Надо взять неделюку отдыха и вернуться уже со свежей головой и ассемблером. Если вдруг кого-то из читающих осенит - не молчите =)

Edited by Monstrofil
  • Upvote 2
Link to comment
Short link
Share on other sites

@Monstrofil 

А методов и свойств не больше 255 получается? Там механизм другой.

21.11.2022 в 22:24, Monstrofil сказал:

# 0x7e - 0x44 == 0x3a == onGetPortsInfo ([unknown: <Blob>])

А точно так?

 

21.11.2022 в 22:24, Monstrofil сказал:

p.p.s. 0x44 и 0xa2 в клиенте всё ещё фигурируют. в asm видно что клиент заполняет entityMethod hander'ом структурку, где хандлеру соответсвуют индексы от 0x44 до 0xa2.

Тогда только смотреть, как методам назначаются индексы. Там есть функция подсчёта md5 хеша по всем названиям, если её не удалили. Можно туда поставить брекпойнт и все параметры вытащить.

Edited by Dragon armor
Link to comment
Short link
Share on other sites

12 часов назад, Dragon armor сказал:

А методов и свойств не больше 255 получается? Там механизм другой.

 

Неа, не больше.

 

Цитата

А точно так?

Точно.

 

Цитата

Тогда только смотреть, как методам назначаются индексы. Там есть функция подсчёта md5 хеша по всем названиям, если её не удалили. Можно туда поставить брекпойнт и все параметры вытащить.

Посмотрел уже, exposed индексы в клиенте назначаются вплоть до 0x5b (dec=91). 

 

В ангаре сообщение a1 всегда variable-len (с заголовком размера) и совершенно разными payload. В примере выше я приводил пример когда оно содержит 1 и 6 байт, но так же есть вот такие случаи когда в payload прилетает pickle + zlib следующего содержания:
 

{'progress': {'lootedStages': [1, 2, 3, 4, 5, 6, 7, 8, 9], 'currentStage': 5, 'daysLeft': 9}, 'params': {'extraReward': [('Add', {'count': 750, 'type': 16})], 'duration': 30.0, 'stages': {1: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 2: {'rewards': [('Add', {'count': 750, 'type': 16})]}, 3: {'rewards': [('Add', {'count': 750, 'type': 16})]}, 4: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL004_Lucky'})]}, 5: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 6: {'rewards': [('Add', {'count': 750, 'type': 16})]}, 7: {'rewards': [('Add', {'count': 400, 'type': 6})]}, 8: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL002_Signals'})]}, 9: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 10: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 11: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 12: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL001_Credits'})]}, 13: {'rewards': [('Add', {'count': 50000, 'type': 0})]}, 14: {'rewards': [('Add', {'count': 400, 'type': 6})]}, 15: {'rewards': [('Add', {'count': 400, 'type': 6})]}, 16: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL034_Resourses'})]}, 17: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL004_Lucky'})]}, 18: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL002_Signals'})]}, 19: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL001_Credits'})]}, 20: {'rewards': [('Lootbox', {'count': 1, 'ignoreEpic': 1, 'boxType': 'PCL034_Resourses'})]}, 21: {'rewards': [('Add', {'count': 1500, 'type': 16})]}, 22: {'rewards': [('Add', {'count': 100, 'type': 1})]}, 23: {'rewards': [('Add', {'count': 1, 'type': 23})]}, 24: {'rewards': [('Lootbox', {'count': 1, 'boxType': 'PCL005_Epic'})]}}, 'id': 2211, 'background': 'blue'}, 'currentStage': 8}

Никакие методы при этом у entity не вызываются, property с таким форматом тоже нет. Склоняюсь к тому что это уже какое-то современное ноу-хау картошки и смотреть реализацию нужно будет в клиенте игры. 

 

Пока что только собираю статистику по сообщениям этого формата, парсингу они не мешают т.к. размер данных записан в само сообщение.

 

 

Вот всё что мне попадалось в одной из сессий в ангаре (чистые данные без заголовка a1 + payload len). Запишу чуть позже ещё сессию боя и может вопрос прояснится даже без копания в ассемблере.

03ffab0200780185d4d9521341140660b2872460d871df356ec8ea2e8288a8932802ed1ee324d38448c8e474cf08b9e82aafbcf61d7c145fc367f0193c27f64c4daa42257753f9ce3ffdf7ccf4f7b082508e259bc2ae0a2e25e07524c73275db76b8b5e998552e215a8458ce08196123c259a6e20ac11b4efb3f881b5196b4cc96ccf36d071246ca65f1a629cc3d094905fd3996e6078e3037f8be292c481521cd22cb96a5209363b18aed369cc2df308b3aad2637b2ee0f183031ce15a653b31b30b8b6b4d8d7feb1b8fcbf94230ab2b81405432c21daa112868b30a25347fdd4f5df3ab50f53c74c6960b1f11da4139a4efab46301479146141c237a5cd313dde949a45105a7889e66893c6e59d93e5070c6e34688a56ad5862df86ab356c1ab04febf855559667d253f3d3d5fcabb95dd169cc5259ec3b09882f3147641dff7a21754e8687309695cc165a2394daff8b4a3cd55a40905d7885ed7f4864f7f86f41ec571015348f191dd243a1d6833e3f1c3db0cb6dbcc9636b1ac5997308b717318d7af609ee216f49d6f79519d7d6e234d29b843f4aea6f7bad3fb48d30a1e107da8e96277fa086946c112d1e5409fc71eefd567a6b422b8557324ac609f271837a06095e29eea3baf79519d7d9e211d54f09ce80b4d0d9f766c7a1e29bed205a22f357dd59dae23cd2a784d7423d067d3e387f7c9d2f3999b2f6d7069bb42e217bd858d18060e297843816f0381ef7a06eed00bfb1ec787157ca0f18f81f14fbdc7e9fd28e2f88882cf345e0a8c7fe93d4e8fc3c4f15105651aaf04c6addee3d49de3f898826d1aafea7ddff1460b7f628113a986745cc157a2bb9ad63d6a585a8630740fe5848206495bcba62fbd6f6d0225a09c542048cac0ea9d80f6cf8a74fbeb5a28d119022e4e7f33a5cbc2350bf60bbf922c55362bbb558147a905072c5aaebb1c5aae3bf50f00c0f71b
09
12
110493c2c2c2

 

Link to comment
Short link
Share on other sites

  • 2 weeks later...
  • 2 weeks later...

Привел было немного в чувство весь код написанный раньше и попытался разобраться с форматом avatarUpdate.

Подопытным был выбран avatarUpdateAliasFullPosYawPitchRoll. Он же в виде макроса в старых исходниках BW:
 

AVUPMSG( Alias, FullPos, YawPitchRoll )

 

Примеры пакетов:

2dfa78ca6f22c200009a600000
2df377be7edad000105d400000
2df977f11edf9200039aa003fd
2def79daaf3cf4000052000000
2df6790a7ee1b000002b600001

 

Разочарование первое: в исходниках FullPos занимает 5 байт, YawPitchRoll - 3, ещё один байт уходит на Alias (итого 9), но в трафике 12 байт.

 

Разочарование второе: поменялся формат хранения YawPitchRoll. В исходниках это три байта указывающих на три угла, но в игровом клиенте используются 4 байта.
Первый с конца - Roll.

# aa0000XX
# 0, 32, 64, 96, 128, 160, 192, 224, 0
# XX=0 'yaw': -2.11075758934021, 'pitch': 0.0, 'roll': 0.0
# XX=192 'yaw': -2.11075758934021, 'pitch': 0.0, 'roll': 1.1780972480773926
# XX=224 'yaw': -2.11075758934021, 'pitch': 0.0, 'roll': 1.3744468688964844

# roll = XX / 256 * (math.pi / 2)

 

Четвертый с конца - Yaw.

# XX000000 by 16
# XX=0 'yaw': 0.0, 'pitch': 0.0, 'roll': 0.0
# XX=16 'yaw': 0.39269909262657166, 'pitch': 0.0, 'roll': 0.0
# XX=128 'yaw': -3.1415927410125732, 'pitch': 0.0, 'roll': 0.0

Второй и третий с конца байты указывают на pitch, инвертируют его и немного влияют на yaw и roll.

# aaXXXX00
# XX=0 'yaw': -2.11075758934021, 'pitch': 0.0, 'roll': 0.0
# XX=16 'yaw': -2.11075758934021, 'pitch': -1.5661900043487549, 'roll': 0.0
# XX=32 'yaw': -2.107689619064331, 'pitch': 0.012283843010663986, 'roll': 0.0
# XX=48 'yaw': -2.107689619064331, 'pitch': -1.5539060831069946, 'roll': 0.0
# XX=64 'yaw': -2.104621648788452, 'pitch': 0.024567686021327972, 'roll': 0.0
# XX=80 'yaw': -2.104621648788452, 'pitch': -1.541622281074524, 'roll': 0.0
# XX=96 'yaw': -2.1015536785125732, 'pitch': 0.03685152903199196, 'roll': 0.0
# XX=112 'yaw': -2.1015536785125732, 'pitch': -1.5293384790420532, 'roll': 0.0
# XX=128 'yaw': -2.0984857082366943, 'pitch': 0.049135372042655945, 'roll': 0.0

 

Разочарование третье: формат позиции тоже новый, 7 байт вместо 5. Меняя значение одного последнего байта меняется Z. Особенности: меняется не от ноля, на разных картах координата пересчитывается в разные значения (возможно зависит от размера карты).

# XX in range(0, 255, step=16), all other bytes fixed
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -459.12945556640625
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -474.75543212890625
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -490.3813781738281
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -506.00732421875
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -522.2589111328125
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -553.5108642578125
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -584.7627563476562
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -616.0146484375
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -648.517822265625
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -711.0216674804688
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -773.5255126953125
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -836.029296875
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -901.0357055664062
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -1026.0433349609375
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -1151.051025390625
# 'x': 67.27529907226562, 'y': 509.96875, 'z': -1276.05859375

 

Если кто-нибудь встречал уже эти форматы (например, где-нибудь в конфигах карт) - напишите. 

Link to comment
Short link
Share on other sites

14 часов назад, Monstrofil сказал:

Особенности: меняется не от ноля, на разных картах координата пересчитывается в разные значения

Посмотри на relativePosition.

 

14 часов назад, Monstrofil сказал:

YawPitchRoll - 3

Четыре же.

 

14 часов назад, Monstrofil сказал:

FullPos занимает 5 байт

А это 6.

 

И на лицо опять экономия байт. Вместо 24 байт без каких-либо механизмов ужимаются в 10. Ну может 14 байт - это много. Очень много. Пихать мёртвую говядину в каждый пакет - не много. А 14 байт много. Ну пусть будет увеличение размера пакета на 14 * 12 (или сколько там корабликов) 168 байт (и то не каждый пакет), даже в MTU 1500 байт укладывается вместе с остальными данными, которых примерно 250 байт.

  • Upvote 1
Link to comment
Short link
Share on other sites

18.12.2022 в 12:02, Dragon armor сказал:

Четыре же.

 

/**
 *	This class is used to pack a yaw, pitch and roll value for network
 *	transmission.
 *
 *	@ingroup network
 */
class YawPitchRoll
{
...

private:
	uint8	yaw_;
	uint8	pitch_;
	uint8	roll_;
};

inline BinaryIStream& operator>>( BinaryIStream &is, YawPitchRoll &ypr )
{
	return is >> ypr.yaw_ >> ypr.pitch_ >> ypr.roll_;
}

Я на какой-то другой YawPitchRoll смотрю?

UPD 21.12: yaw pitch roll - 11 бит + 10 бит + 11 бит, первый бит в каждой группе - знак (x - math.pi).
xzy  - 19 бит + 19 бит + 18 бит = 56 бит/7 байт, первый бит в каждой группе - знак (-1 ^ bit * x)

У y первые 4 бита после знака - экспонента, остальные - мантисса. К значению всегда прибавляется константа 2.0.
Как запакованы XZ понять не удалось.

 

UPD 30.12.

В общем-то координаты и направление распакованы, демка транслирующая состояние боя на соседний экран написана. Дальшейшее уже допиливание мелочей (PIGGIBACKS, пересылка пакетов, whatever). 

 

image.thumb.png.b77687c0ca95e8b085da12ea8d7d7bf0.png


Пожалуй на этом я и остановлюсь, думаю уже можно записать в копилку виртуальную ачивку и пойти писать очреедную статью на хабр "разбор протокола wot" :P

Edited by Monstrofil
  • Upvote 1
Link to comment
Short link
Share on other sites

  • 2 weeks later...

Вопрос про кастомизацию (переключение со своего стиля на готовый) всё ещё актуален. Когда сервер стал учитывать и пользовательский, и готовый стили, чтобы переключаться между ними, после патча 0.9.21 или 1.9.1?

Link to comment
Short link
Share on other sites

  • 2 weeks later...

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...