From 247d2fad306c3b14ec21ec0da0581d785a16a5c6 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Thu, 1 Aug 2019 09:48:57 +0300 Subject: [PATCH] [General] Implement activator & static records for RecordDynamic packets --- .../Script/Functions/RecordsDynamic.cpp | 30 +++++ apps/openmw/mwmp/RecordHelper.cpp | 110 ++++++++++++++++++ apps/openmw/mwmp/RecordHelper.hpp | 9 ++ apps/openmw/mwmp/Worldstate.cpp | 24 ++++ components/openmw-mp/Base/BaseWorldstate.hpp | 22 +++- .../Worldstate/PacketRecordDynamic.cpp | 46 ++++++++ 6 files changed, 240 insertions(+), 1 deletion(-) diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp index b7842da5a..ffe3425ae 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp @@ -24,6 +24,8 @@ MiscellaneousRecord tempMiscellaneous; WeaponRecord tempWeapon; ContainerRecord tempContainer; DoorRecord tempDoor; +ActivatorRecord tempActivator; +StaticRecord tempStatic; BaseOverrides tempOverrides; @@ -343,6 +345,10 @@ void RecordsDynamicFunctions::SetRecordId(const char* id) noexcept tempContainer.data.mId = id; else if (writeRecordsType == mwmp::RECORD_TYPE::DOOR) tempDoor.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + tempActivator.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::STATIC) + tempStatic.data.mId = id; else LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); } @@ -375,6 +381,10 @@ void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept tempContainer.baseId = baseId; else if (writeRecordsType == mwmp::RECORD_TYPE::DOOR) tempDoor.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + tempActivator.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::STATIC) + tempStatic.baseId = baseId; else LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType); } @@ -442,6 +452,8 @@ void RecordsDynamicFunctions::SetRecordName(const char* name) noexcept tempContainer.data.mName = name; else if (writeRecordsType == mwmp::RECORD_TYPE::DOOR) tempDoor.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + tempActivator.data.mName = name; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set name for record type %i which lacks that property", writeRecordsType); @@ -475,6 +487,10 @@ void RecordsDynamicFunctions::SetRecordModel(const char* model) noexcept tempContainer.data.mModel = model; else if (writeRecordsType == mwmp::RECORD_TYPE::DOOR) tempDoor.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + tempActivator.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::STATIC) + tempStatic.data.mModel = model; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set model for record type %i which lacks that property", writeRecordsType); @@ -533,6 +549,8 @@ void RecordsDynamicFunctions::SetRecordScript(const char* script) noexcept tempContainer.data.mScript = script; else if (writeRecordsType == mwmp::RECORD_TYPE::DOOR) tempDoor.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + tempActivator.data.mScript = script; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set script for record type %i which lacks that property", writeRecordsType); @@ -1258,6 +1276,18 @@ void RecordsDynamicFunctions::AddRecord() noexcept WorldstateFunctions::writeWorldstate.doorRecords.push_back(tempDoor); tempDoor = {}; } + else if (writeRecordsType == mwmp::RECORD_TYPE::ACTIVATOR) + { + tempActivator.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.activatorRecords.push_back(tempActivator); + tempActivator = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::STATIC) + { + tempStatic.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.staticRecords.push_back(tempStatic); + tempStatic = {}; + } tempOverrides = {}; } diff --git a/apps/openmw/mwmp/RecordHelper.cpp b/apps/openmw/mwmp/RecordHelper.cpp index c99c40ddb..2839b6632 100644 --- a/apps/openmw/mwmp/RecordHelper.cpp +++ b/apps/openmw/mwmp/RecordHelper.cpp @@ -104,6 +104,20 @@ bool RecordHelper::doesDoorRecordExist(const std::string& id) return world->getStore().get().search(id); } +bool RecordHelper::doesActivatorRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + +bool RecordHelper::doesStaticRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + std::string RecordHelper::createCreatureRecord(const ESM::Creature& record) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -960,6 +974,88 @@ void RecordHelper::overrideDoorRecord(const mwmp::DoorRecord& record) world->updatePtrsWithRefId(recordData.mId); } +void RecordHelper::overrideActivatorRecord(const mwmp::ActivatorRecord& record) +{ + const ESM::Activator &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesActivatorRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesActivatorRecordExist(record.baseId)) + { + const ESM::Activator *baseData = world->getStore().get().search(record.baseId); + ESM::Activator finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasName) + finalData.mName = recordData.mName; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + if (record.baseOverrides.hasScript) + finalData.mScript = recordData.mScript; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + +void RecordHelper::overrideStaticRecord(const mwmp::StaticRecord& record) +{ + const ESM::Static &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesStaticRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesStaticRecordExist(record.baseId)) + { + const ESM::Static *baseData = world->getStore().get().search(record.baseId); + ESM::Static finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + void RecordHelper::overrideCreatureRecord(const ESM::Creature& record) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1043,3 +1139,17 @@ void RecordHelper::overrideDoorRecord(const ESM::Door& record) world->getModifiableStore().overrideRecord(record); } + +void RecordHelper::overrideActivatorRecord(const ESM::Activator& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} + +void RecordHelper::overrideStaticRecord(const ESM::Static& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} diff --git a/apps/openmw/mwmp/RecordHelper.hpp b/apps/openmw/mwmp/RecordHelper.hpp index 9f4e1ffd7..2161a8776 100644 --- a/apps/openmw/mwmp/RecordHelper.hpp +++ b/apps/openmw/mwmp/RecordHelper.hpp @@ -27,6 +27,9 @@ namespace RecordHelper bool doesContainerRecordExist(const std::string& id); bool doesDoorRecordExist(const std::string& id); + bool doesActivatorRecordExist(const std::string& id); + bool doesStaticRecordExist(const std::string& id); + std::string createCreatureRecord(const ESM::Creature& record); std::string createNpcRecord(const ESM::NPC& record); @@ -46,6 +49,9 @@ namespace RecordHelper void overrideContainerRecord(const mwmp::ContainerRecord& record); void overrideDoorRecord(const mwmp::DoorRecord& record); + void overrideActivatorRecord(const mwmp::ActivatorRecord& record); + void overrideStaticRecord(const mwmp::StaticRecord& record); + void overrideCreatureRecord(const ESM::Creature& record); void overrideNpcRecord(const ESM::NPC& record); @@ -61,6 +67,9 @@ namespace RecordHelper void overrideContainerRecord(const ESM::Container& record); void overrideDoorRecord(const ESM::Door& record); + + void overrideActivatorRecord(const ESM::Activator& record); + void overrideStaticRecord(const ESM::Static& record); } diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp index 5e47892b5..d8c11120b 100644 --- a/apps/openmw/mwmp/Worldstate.cpp +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -182,6 +182,30 @@ void Worldstate::addRecords() RecordHelper::overrideDoorRecord(record); } } + else if (recordsType == mwmp::RECORD_TYPE::ACTIVATOR) + { + for (auto &&record : activatorRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- activator record %s, %s\n-- baseId is %s", record.data.mId.c_str(), record.data.mName.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideActivatorRecord(record); + } + } + else if (recordsType == mwmp::RECORD_TYPE::STATIC) + { + for (auto &&record : staticRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- static record %s\n-- baseId is %s", record.data.mId.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideStaticRecord(record); + } + } } bool Worldstate::containsExploredMapTile(int cellX, int cellY) diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index fc07ef964..1909d4203 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include @@ -35,7 +37,9 @@ namespace mwmp SPELL, WEAPON, CONTAINER, - DOOR + DOOR, + ACTIVATOR, + STATIC }; // When using an existing record as a base, this struct tracks which changes @@ -100,6 +104,13 @@ namespace mwmp bool hasCloseSound = false; }; + struct ActivatorRecord + { + ESM::Activator data; + std::string baseId; + BaseOverrides baseOverrides; + }; + struct ArmorRecord { ESM::Armor data; @@ -182,6 +193,13 @@ namespace mwmp BaseOverrides baseOverrides; }; + struct StaticRecord + { + ESM::Static data; + std::string baseId; + BaseOverrides baseOverrides; + }; + struct WeaponRecord { ESM::Weapon data; @@ -243,6 +261,7 @@ namespace mwmp unsigned short recordsType; unsigned int recordsCount; + std::vector activatorRecords; std::vector armorRecords; std::vector bookRecords; std::vector clothingRecords; @@ -254,6 +273,7 @@ namespace mwmp std::vector npcRecords; std::vector potionRecords; std::vector spellRecords; + std::vector staticRecords; std::vector weaponRecords; bool isValid; diff --git a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp index 0d548f648..69913a5bf 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp @@ -44,6 +44,10 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) worldstate->recordsCount = Utils::getVectorSize(worldstate->containerRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::DOOR) worldstate->recordsCount = Utils::getVectorSize(worldstate->doorRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::ACTIVATOR) + worldstate->recordsCount = Utils::getVectorSize(worldstate->activatorRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::STATIC) + worldstate->recordsCount = Utils::getVectorSize(worldstate->staticRecords); else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i", @@ -88,6 +92,10 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) Utils::resetVector(worldstate->containerRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::DOOR) Utils::resetVector(worldstate->doorRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::ACTIVATOR) + Utils::resetVector(worldstate->activatorRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::STATIC) + Utils::resetVector(worldstate->staticRecords, worldstate->recordsCount); } if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL) @@ -498,6 +506,44 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) } } } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::ACTIVATOR) + { + for (auto &&record : worldstate->activatorRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mName, send, true); + RW(recordData.mModel, send, true); + RW(recordData.mScript, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasName, send); + RW(overrides.hasModel, send); + RW(overrides.hasScript, send); + } + } + } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::STATIC) + { + for (auto &&record : worldstate->staticRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mModel, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasModel, send); + } + } + } } void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send)