Цитата
К примеру после НИ, как мы прочитаем из нет-пакета значение которого там еще нет ?
А оно будет. Движок сталкера в этом плане устроен очень интересно.
Во первых если объект был создан через all.spawn, то при создании новой игры STATE_Read будет считывать твой объект из него, поскольку .spawn файлы это по сути огромный нет-пакет. (поэтому если ты в STATE_ функциях меняешь порядок чтения\записи переменных, то можешь сломать оригинальный all.spawn. Чтобы это избежать нужно проверку на версию спавна делать - в ЗП версия
текущего спавна хранится в переменной CSE_Abstract -> m_wVersion, а изменить её на новую можно в xrServer_Objects.h - SPAWN_VERSION)
Во вторых если объект был создан скриптом через alife():create() то там ровно тоже самое. Движок сперва создаёт фейковый серверный объект на стороне клиента, нигде его не регистрируя. ( у него
вроде как даже ID нету ) В этот момент можно ему свойства любые поменять. А дальше он "отправляет" его на сервер, где данные этого объекта опять же считываются в STATE_Read и создаётся "настоящий" объект, таким образом ты STATE_-функции никак не пропустишь.
Возможно тут есть какие то особенности, ибо разбираться во всём этом себе дороже, но по примерам GSC и моему опыту всё именно так и работает. Если интересно, то вот я тоже сделал логирование в CSE_ALifeInventoryItem, и в момент
загрузки игры (не НИ) у меня вот такое вышло.
// Создаются какие то пустышки (не обязательно от нашего объекта, у них ID нету)
[65535] STATE_Read
[65535] UPDATE_Read
// Первой вызывается STATE_Read - считывает либо данные из сейва, либо из all.spawn, либо из фейкового объекта
[7151] STATE_Read
// Далее UPDATE_Read, аналогично STATE_Read, т.к эти данные тоже в сейве\спавне сохраняются
[7151] UPDATE_Read
// Дальше идёт вызов функций записи в нет_Пакет, не знаю точно для чего это нужно, но данные там не меняются
[7151] STATE_Write
[7151] UPDATE_Write
[7151] STATE_Write
[7151] UPDATE_Write
// Тут снова идёт считывание из нет_Пакета
[7151] STATE_Read
[7151] UPDATE_Read
// И наконец наш серверный объект с загруженными данными попадает к клиентскому
[7151] net_Spawn
// И в дальнейшем эти функции вызываются на апдейте
[7151] net_Export
[7151] UPDATE_Read
Как видно, при загрузке игры первым всегда идёт вызов STATE_Read. А UPDATE_Read вызывается, поскольку его данные тоже в сохранение идут. (я об этом успел подзабыть
Для новой игры:
[6538] STATE_Write
[6538] UPDATE_Write
[6538] STATE_Write
[6538] UPDATE_Write
[6538] STATE_Read
[6538] UPDATE_Read
[6538] net_Spawn
Наоборот сперва идёт UPDATE_Write - почему так происходит? А ПЫС его знает %)
А вот лог для предмета, который я заспавнил скриптом:
[16109] STATE_Write // Запишет в нет_Пакет дефолты из конструктора
[16109] STATE_Read
[16109] STATE_Write
[16109] STATE_Write
[16109] STATE_Read
[16109] net_Spawn
Для него UPDATE_ функции даже ни разу не вызвались в момент создания.
А вот что происходит в момент сохранения игры:
[16109] net_Export // Шлём данные из клиента в серверный объекта
[16109] UPDATE_Read // Считываем их там
[16109] STATE_Write // Сохраняем STATE_ в сейв
[16109] UPDATE_Write // Сохраняем UPDATE_ в сейв
Только надо учесть, что у меня стоит
эта правка, без неё у тебя скорее всего UPDATE_Read в момент сохранения вызываться не будет, из за чего в сейв будут попадать слегка устаревшие данные.
- - - - - - - - - - - - - - - - - - - -
По поводу твоего кода:
1) Добавь чтение своей переменной в net_Import (если тебе не наплевать на МП, иначе игра там вылетит\сломается)
2) В xrServer_Objects.h измени версию спавна на единичку.
3) В UPDATE_Read добавь перед m_fValue проверку на версию (if (m_wVersion > "старая_версия")).
Либо если тебя интересует только сингл (или эти данные не критичны для МП) - откати все свои правки и юзай save()\load() у клиента.
Цитата
Добавил по такому-же принципу переменную в CSE_ALifeObjectHangingLamp, но там почему-то все оказалось наоборот: первым, после создания объекта вызывается CSE_ALifeObjectHangingLamp::UPDATE_Read, соответственно из нет-пакета читается пустое значение, которое затирает дефолтное значение переменной.
Посмотри на Лог 1\Лог 2 и поймёшь почему так происходит. Если это новая игра, то сперва будет вызываться UPDATE_Write (почему хз, наверно это так спавн парсится или объект пустышка гонит в нет-пакет свои данные), если это загрузка сейва то наоборот UPDATE_Read. Добавь проверку на версию (пункт 3) и в фонарик, и в лампу - и, теоретически, твоя проблема должна исчезнуть.
- - - - - - - - - - - - - - - -
UPDATE_ и net_Export следует использовать только для передачи небольших переменных. Если тебе надо сохранить на сервере какую-нибудь строку (например длинную строку со списком апгрейдов), то следует использовать STATE_Write.
Пример можешь глянуть в inventory_item_upgradge.cpp -> add_upgrade() и в xrServer_process_event.cpp -> GE_INSTALL_UPGRADE.
Но если тебе всё равно на МП, то можешь прям из клиентского объекта напрямую изменять переменные серверного объекта.