From fe4a761ffe0db3d0aaa62e258f75ae2b0b0f7ef6 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 18 Jul 2021 11:36:07 +0200 Subject: [PATCH] [General] Implement game setting records for RecordDynamic packets Remove unused placeholder for variants from RecordDynamic. --- .../Script/Functions/RecordsDynamic.cpp | 60 ++++++++++++++++++- .../Script/Functions/RecordsDynamic.hpp | 32 +++++++++- apps/openmw/mwmp/RecordHelper.cpp | 31 ++++++++++ apps/openmw/mwmp/RecordHelper.hpp | 1 + apps/openmw/mwmp/Worldstate.cpp | 12 ++++ components/openmw-mp/Base/BaseStructs.hpp | 5 +- components/openmw-mp/Base/BaseWorldstate.hpp | 21 +++---- .../Worldstate/PacketRecordDynamic.cpp | 53 +++++++++++----- 8 files changed, 188 insertions(+), 27 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp index 71a1b7372..d63302ed4 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp @@ -35,6 +35,7 @@ RepairRecord tempRepair; ScriptRecord tempScript; StaticRecord tempStatic; SoundRecord tempSound; +GameSettingRecord tempGameSetting; BaseOverrides tempOverrides; @@ -403,6 +404,8 @@ void RecordsDynamicFunctions::SetRecordId(const char* id) noexcept tempStatic.data.mId = id; else if (writeRecordsType == mwmp::RECORD_TYPE::SOUND) tempSound.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + tempGameSetting.data.mId = id; else LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); } @@ -459,6 +462,8 @@ void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept tempStatic.baseId = baseId; else if (writeRecordsType == mwmp::RECORD_TYPE::SOUND) tempSound.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + tempGameSetting.baseId = baseId; else LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType); } @@ -1542,13 +1547,61 @@ void RecordsDynamicFunctions::SetRecordScriptText(const char* scriptText) noexce tempScript.data.mScriptText = scriptText; else { - LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set close sound for record type %i which lacks that property", writeRecordsType); + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set script text for record type %i which lacks that property", writeRecordsType); return; } tempOverrides.hasScriptText = true; } +void RecordsDynamicFunctions::SetRecordIntegerVariable(int intVar) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + tempGameSetting.variable.variableType = mwmp::INT; + tempGameSetting.variable.intValue = intVar; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set integer variable for record type %i which lacks that property", writeRecordsType); + return; + } +} + +void RecordsDynamicFunctions::SetRecordFloatVariable(double floatVar) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + tempGameSetting.variable.variableType = mwmp::FLOAT; + tempGameSetting.variable.floatValue = floatVar; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set float variable for record type %i which lacks that property", writeRecordsType); + return; + } +} + +void RecordsDynamicFunctions::SetRecordStringVariable(const char* stringVar) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + tempGameSetting.variable.variableType = mwmp::STRING; + tempGameSetting.variable.stringValue = stringVar; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set string variable for record type %i which lacks that property", writeRecordsType); + return; + } +} + void RecordsDynamicFunctions::SetRecordIdByIndex(unsigned int index, const char* id) noexcept { unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; @@ -1808,6 +1861,11 @@ void RecordsDynamicFunctions::AddRecord() noexcept WorldstateFunctions::writeWorldstate.soundRecords.push_back(tempSound); tempSound = {}; } + else if (writeRecordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + WorldstateFunctions::writeWorldstate.gameSettingRecords.push_back(tempGameSetting); + tempGameSetting = {}; + } effectCount = 0; tempOverrides = {}; diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp index 3749c4069..31ecacea9 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp @@ -108,6 +108,9 @@ {"SetRecordCloseSound", RecordsDynamicFunctions::SetRecordCloseSound},\ \ {"SetRecordScriptText", RecordsDynamicFunctions::SetRecordScriptText},\ + {"SetRecordIntegerVariable", RecordsDynamicFunctions::SetRecordIntegerVariable},\ + {"SetRecordFloatVariable", RecordsDynamicFunctions::SetRecordFloatVariable},\ + {"SetRecordStringVariable", RecordsDynamicFunctions::SetRecordStringVariable},\ \ {"SetRecordIdByIndex", RecordsDynamicFunctions::SetRecordIdByIndex},\ {"SetRecordEnchantmentIdByIndex", RecordsDynamicFunctions::SetRecordEnchantmentIdByIndex},\ @@ -912,11 +915,38 @@ public: * \brief Set the script text of the temporary record stored on the server for the * currently specified record type. * - * \param sound The script text of the record. + * \param scriptText The script text of the record. * \return void */ static void SetRecordScriptText(const char* scriptText) noexcept; + /** + * \brief Set the integer variable of the temporary record stored on the server for the + * currently specified record type. + * + * \param intVar The integer variable of the record. + * \return void + */ + static void SetRecordIntegerVariable(int intVar) noexcept; + + /** + * \brief Set the float variable of the temporary record stored on the server for the + * currently specified record type. + * + * \param floatVar The float variable of the record. + * \return void + */ + static void SetRecordFloatVariable(double floatVar) noexcept; + + /** + * \brief Set the string variable of the temporary record stored on the server for the + * currently specified record type. + * + * \param stringVar The string variable of the record. + * \return void + */ + static void SetRecordStringVariable(const char* stringVar) noexcept; + /** * \brief Set the id of the record at a certain index in the records stored on the server. * diff --git a/apps/openmw/mwmp/RecordHelper.cpp b/apps/openmw/mwmp/RecordHelper.cpp index 5622abb67..4735d50bb 100644 --- a/apps/openmw/mwmp/RecordHelper.cpp +++ b/apps/openmw/mwmp/RecordHelper.cpp @@ -722,6 +722,37 @@ void RecordHelper::overrideRecord(const mwmp::EnchantmentRecord& record) } } +void RecordHelper::overrideRecord(const mwmp::GameSettingRecord& record) +{ + const ESM::GameSetting& recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + MWBase::World* world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesRecordIdExist(record.baseId)) + { + const ESM::GameSetting* baseData = world->getStore().get().search(record.baseId); + ESM::GameSetting finalData = *baseData; + finalData.mId = recordData.mId; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } +} + void RecordHelper::overrideRecord(const mwmp::IngredientRecord& record) { const ESM::Ingredient &recordData = record.data; diff --git a/apps/openmw/mwmp/RecordHelper.hpp b/apps/openmw/mwmp/RecordHelper.hpp index 7b4c6b6e1..72e00cdd5 100644 --- a/apps/openmw/mwmp/RecordHelper.hpp +++ b/apps/openmw/mwmp/RecordHelper.hpp @@ -18,6 +18,7 @@ namespace RecordHelper void overrideRecord(const mwmp::CreatureRecord& record); void overrideRecord(const mwmp::DoorRecord& record); void overrideRecord(const mwmp::EnchantmentRecord& record); + void overrideRecord(const mwmp::GameSettingRecord& record); void overrideRecord(const mwmp::IngredientRecord& record); void overrideRecord(const mwmp::LightRecord& record); void overrideRecord(const mwmp::LockpickRecord& record); diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp index 10d37dbdf..1dcd27f65 100644 --- a/apps/openmw/mwmp/Worldstate.cpp +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -330,6 +330,18 @@ void Worldstate::addRecords() RecordHelper::overrideRecord(record); } } + else if (recordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + for (auto&& record : gameSettingRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(TimedLog::LOG_INFO, "- gameSetting record %s\n-- baseId is %s", record.data.mId.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideRecord(record); + } + } } bool Worldstate::containsExploredMapTile(int cellX, int cellY) diff --git a/components/openmw-mp/Base/BaseStructs.hpp b/components/openmw-mp/Base/BaseStructs.hpp index 9a5e7eec1..42176e5b2 100644 --- a/components/openmw-mp/Base/BaseStructs.hpp +++ b/components/openmw-mp/Base/BaseStructs.hpp @@ -42,7 +42,9 @@ namespace mwmp { SHORT, LONG, - FLOAT + FLOAT, + INT, + STRING }; struct ClientVariable @@ -54,6 +56,7 @@ namespace mwmp int intValue; float floatValue; + std::string stringValue; }; struct Time diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index fed41a096..fbf835940 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include #include @@ -48,6 +48,7 @@ namespace mwmp CREATURE, DOOR, ENCHANTMENT, + GAMESETTING, INGREDIENT, LIGHT, LOCKPICK, @@ -60,7 +61,6 @@ namespace mwmp SOUND, SPELL, STATIC, - VARIANT, WEAPON }; @@ -230,6 +230,14 @@ namespace mwmp BaseOverrides baseOverrides; }; + struct GameSettingRecord + { + ESM::GameSetting data; + std::string baseId; + BaseOverrides baseOverrides; + ClientVariable variable; + }; + struct IngredientRecord { ESM::Ingredient data; @@ -317,13 +325,6 @@ namespace mwmp BaseOverrides baseOverrides; }; - struct VariantRecord - { - ESM::Variant data; - std::string baseId; - BaseOverrides baseOverrides; - }; - struct WeaponRecord { ESM::Weapon data; @@ -409,6 +410,7 @@ namespace mwmp std::vector creatureRecords; std::vector doorRecords; std::vector enchantmentRecords; + std::vector gameSettingRecords; std::vector ingredientRecords; std::vector lightRecords; std::vector lockpickRecords; @@ -421,7 +423,6 @@ namespace mwmp std::vector soundRecords; std::vector spellRecords; std::vector staticRecords; - std::vector variantRecords; std::vector weaponRecords; std::vector cellsToReset; diff --git a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp index dd87ed1d0..4f0b04564 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp @@ -52,6 +52,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) worldstate->recordsCount = Utils::getVectorSize(worldstate->creatureRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::DOOR) worldstate->recordsCount = Utils::getVectorSize(worldstate->doorRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::GAMESETTING) + worldstate->recordsCount = Utils::getVectorSize(worldstate->gameSettingRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::INGREDIENT) worldstate->recordsCount = Utils::getVectorSize(worldstate->ingredientRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::LIGHT) @@ -70,8 +72,6 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) worldstate->recordsCount = Utils::getVectorSize(worldstate->staticRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::SOUND) worldstate->recordsCount = Utils::getVectorSize(worldstate->soundRecords); - else if (worldstate->recordsType == mwmp::RECORD_TYPE::VARIANT) - worldstate->recordsCount = Utils::getVectorSize(worldstate->variantRecords); else { LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i", @@ -122,6 +122,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) Utils::resetVector(worldstate->creatureRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::DOOR) Utils::resetVector(worldstate->doorRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::GAMESETTING) + Utils::resetVector(worldstate->gameSettingRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::INGREDIENT) Utils::resetVector(worldstate->ingredientRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::LOCKPICK) @@ -140,8 +142,6 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) Utils::resetVector(worldstate->soundRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::STATIC) Utils::resetVector(worldstate->staticRecords, worldstate->recordsCount); - else if (worldstate->recordsType == mwmp::RECORD_TYPE::VARIANT) - Utils::resetVector(worldstate->variantRecords, worldstate->recordsCount); } if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL) @@ -617,6 +617,41 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) } } } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::GAMESETTING) + { + for (auto&& record : worldstate->gameSettingRecords) + { + auto& recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(record.variable.variableType, send, true); + + short variableType = record.variable.variableType; + + if (variableType == mwmp::VARIABLE_TYPE::INT) + { + RW(record.variable.intValue, send); + recordData.mValue.setType(ESM::VarType::VT_Int); + recordData.mValue.setInteger(record.variable.intValue); + } + else if (variableType == mwmp::VARIABLE_TYPE::FLOAT) + { + RW(record.variable.floatValue, send); + + if (variableType == mwmp::VARIABLE_TYPE::FLOAT) + recordData.mValue.setType(ESM::VarType::VT_Float); + + recordData.mValue.setFloat(record.variable.floatValue); + } + else if (variableType == mwmp::VARIABLE_TYPE::STRING) + { + RW(record.variable.stringValue, send, true); + recordData.mValue.setType(ESM::VarType::VT_String); + recordData.mValue.setString(record.variable.stringValue); + } + } + } else if (worldstate->recordsType == mwmp::RECORD_TYPE::INGREDIENT) { for (auto &&record : worldstate->ingredientRecords) @@ -890,16 +925,6 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) } } } - // Placeholder - else if (worldstate->recordsType == mwmp::RECORD_TYPE::VARIANT) - { - for (auto&& record : worldstate->variantRecords) - { - auto& recordData = record.data; - - RW(record.baseId, send, true); - } - } } void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send)