Jump to content
Korean Random
Dragon armor

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

Recommended Posts

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

Например, вот пакет. 95 должно быть chatCommandFromClient, а определяется неправильно.

 

 

Кстати, может и правильно определяется, т.к. chatCommandFromClient в последнем клиенте вообще нет.

UPD: а, не, обманываю, chatCommandFromClient есть в интерфейсе "Chat", сорри.

Edited by Monstrofil

Share this post


Link to post

Short link
Share on other sites

Из 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

 

Если хоть что-то понятно, то хорошо, потому что объяснять не умею.

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

Из entities.xml берём энтити. Порядок не важен.

Да, не важен. Но нужно запомнить их номер, потом что именно он нужен 8 методе реплея (а 7 либо ни разу не встречал, либо не нужен). От того, какая энтити используется, зависит и значение messageID. Для разных энтитей они могут повторяться. Зачем такие сложности придумали разработчики BigWorld, когда можно было бы обойтись двумя байтами, вместо одного, мне не понятно. Видимо, был смысл.

Да, и ещё. Сначала парсится spaces.xml, затем entities.xml. Хотя из первого файла ничего не используется, он будет нулевым элементом.

@Monstrofil В новом движке у меня срабатывает ассерт на повторяющиеся методы. Поэтому и ошибочно выбирается неправильный. Движок это обрабатывает, а мне не нужно, поэтому не смотрел, как именно обрабатывает.

Edited by Dragon armor
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

@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 по той же схеме работают.

 

 

Edited by Monstrofil
  • Upvote 1

Share this post


Link to post

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

exposedIndex - индекс нужного метода в массиве после сортировки по длинне сообщения, никаких INDEX_CLIENT_METHOD_BEGIN добавлять не нужно.

Этого уже не вспомнил, давно делал и просто забыл, что для реплеев немного по другому.

Share this post


Link to post

Short link
Share on other sites

Пытаюсь запустить арену. Пока что безрезультатно. Клиент вылетает без сообщений об ошибках, хотя отправляю тоже, что и оригинальный сервер.

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

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'оф в нужных местах и в папку модов закинуть?

Share this post


Link to post

Short link
Share on other sites
14 minutes ago, Dragon armor said:

Пытаюсь запустить арену. Пока что безрезультатно. Клиент вылетает без сообщений об ошибках, хотя отправляю тоже, что и оригинальный сервер.

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


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'оф в нужных местах и в папку модов закинуть?

Сделай как stranics  в debugutils

Edited by SkepticalFox

Share this post


Link to post

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

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

Попробуй так:

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)

FSVO_hooked = FittingSlotVO_hook()

FittingSlotVO = FSVO_hooked

 

Share this post


Link to post

Short link
Share on other sites
1 hour ago, Pavel3333 said:

Попробуй так:

бред

достаточно так

orig_prepareModule = FittingSlotVO._prepareModule

def hooked_prepareModule(self, modulesData, vehicle, slotType, slotId):
    print 'hooked_prepareModule {0}-{1}-{2}-{3}'.format(modulesData, vehicle, slotType, slotId)
    orig_prepareModule(self, modulesData, vehicle, slotType, slotId)

FittingSlotVO._prepareModule = orig_prepareModule

зачем подменять класс?

Edited by SkepticalFox

Share this post


Link to post

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

достаточно так

Так сразу же попробовал, по аналогии с функциями. 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'. Теперь хотя бы знаю, как исправить, когда понадобится.

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

FSVO_hooked = FittingSlotVO_hook()

А так разве не будет вызов функции?

Только что, Dragon armor сказал:

Вот простейший пример, не работает.

Ну да, Enter забыл после o(self, a). Работает, хотя и пробовал до этого так же.

Попробовал с наследованием, работает. Почему-то делал также до этого, не работало. Тоже Enter что-ли забыл?

Share this post


Link to post

Short link
Share on other sites
41 minutes ago, Dragon armor said:

class A(object):

а зачем object?

Да и код этот отрабатывает на Python 2.7(и на 3.6)

<<< hook fff
<<< fff

Edited by SkepticalFox

Share this post


Link to post

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

а зачем object?

Пока что плохо знаком с питоном, поэтому делаю как вижу в исходниках. Может и нет разницы.

Прогресс есть. Немного печалят мелкие баги, которые, тем не менее, приходится долго искать. Всего-то надо было флаг выставить, чтобы номер пакета добавился. Картинка, видимо, по умолчанию, потому что информация об арене ещё не передана.

shot_030.jpg

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

@Dragon armor очень крутая работа! За алгоритм по определению номеров из .def отдельное спасибо. Такой вопрос, понимая протокол между сервером и клиентом, можно ли сделать отдельное приложение/сервис для подключения к игровым чатам на реальном сервере (клановый, список друзей)?

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites
В 29.07.2018 в 21:49, reven86 сказал:

понимая протокол между сервером и клиентом, можно ли сделать отдельное приложение/сервис для подключения к игровым чатам на реальном сервере (клановый, список друзей)?

Можно. Но нужно много чего сделать. Повторить сетевой протокол движка (обработка доставки сообщений, подтверждение доставки, разбивка больших данных на небольшие пакеты и прочее), имитировать реальный клиент (вдруг забанят, если поведение будет отличаться). В общем, то же, что и сам делаю, но в обратную сторону. Возможно, даже проще. Кроме сетевой части. У меня все данные пересылаются с помощью Enet, чтобы избежать (по крайней мере, в данный момент) работы над сетевой частью.

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

Кстати, почему уведомления перестали приходить на почту?

Share this post


Link to post

Short link
Share on other sites

Интересно... очень даже хороший проект! Перестала игра нравиться в каком-то смысле после патча 0.9.23 (он же 1.0), а тут возможность ещё раз взглянуть на 0.9.22... удачи в разработке!

Share this post


Link to post

Short link
Share on other sites

@DrWeb7_1 Благодарю.

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

Как-то много непонятного с id энтитей. Почему-то используется уникальный id для каждой, а не id из базы данных для игрока. Создаётся Avatar со своим id, для него техника со своим id, для аватара отправляется сообщение о том, что он больше не контролируется (controlEntity с id аватара и false). И не понятно, id разных энтитей (аватар и техника) могут повторяться или нет?

 @SkepticalFox , взял было твой питоновый модуль XmlPacker/XmlUnpacker, надеясь избавиться от mxml, который у меня используется для парсинга, но производительность так сильно упала (с 6 секунд до 40+ при загрузке сервера), что пришлось на сишке самому написать. И там у тебя баг, вместо PackedTypes.Section почему-то PackedTypes.Float с нулевой длиной создаётся. Хотя это не мешает, созданный с помощью XmlPacker корректно распаковывается и работает.

shot_033.jpg

Share this post


Link to post

Short link
Share on other sites
8 hours ago, Dragon armor said:

с 6 секунд до 40+ при загрузке сервера

а что ты хотел от питона? кстати, какая у тебя версия? на второй очень тормозит

ты для сервера каждый раз парсишь все эти файлы?

а паковщик тебе зачем?

просто создай БД с нужной информацией из этих файлов

 

8 hours ago, Dragon armor said:

И там у тебя баг, вместо PackedTypes.Section почему-то PackedTypes.Float с нулевой длиной создаётся.

Скорее вместо PackedTypes.String, а это вообще не страшно

Edited by SkepticalFox

Share this post


Link to post

Short link
Share on other sites
В 03.08.2018 в 08:01, SkepticalFox сказал:

а что ты хотел от питона?

СКОРОСТИ!!!111

Это ожидаемо, поэтому ресурсоёмкие вещи переношу в модули на C.

В 03.08.2018 в 08:01, SkepticalFox сказал:

кстати, какая у тебя версия? на второй очень тормозит

2.7.7, такая же, как и в клиенте.

В 03.08.2018 в 08:01, SkepticalFox сказал:

ты для сервера каждый раз парсишь все эти файлы? 

Да.

В 03.08.2018 в 08:01, SkepticalFox сказал:

а паковщик тебе зачем?

Особенности сервера. Константа BigWorld.component = 'base'. А из-за этого вылезло много ошибок из-за отсутствующих значений в xml, например 'xpFactor', 'creditsFactor', 'freeXpFactor', '****Health' и прочих. Пришлось добавлять эти значения и решил заново запаковать.

В 03.08.2018 в 08:01, SkepticalFox сказал:

просто создай БД с нужной информацией из этих файлов

Долго, муторно, не нужно (хотя бы на данный момент).

В 03.08.2018 в 08:01, SkepticalFox сказал:

Скорее вместо PackedTypes.String

Самый первый элемент, 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

При том с такой частотой, что клиент подвисал. Разобрался и продвинулся ещё дальше.

shot_035.jpg

shot_036.jpg

shot_037.jpg

shot_038.jpg

shot_039.jpg

shot_040.jpg

shot_041.jpg

  • Upvote 4

Share this post


Link to post

Short link
Share on other sites

@Serfer_78 Благодарю.

 

Максимальная дальность видимости 565 метров, говорили они, это максимальная дистанция, на которой в принципе можно увидеть технику, говорили они.

It was a lie, Morpheus. The prophecy was a lie.

shot_042.jpg

shot_042.jpg

shot_046.jpg

shot_047.jpg

shot_048.jpg

В снайперском прицеле за кустами немного видно, но силуэт не обводится.

shot_049.jpg

  • Upvote 4

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