diff --git a/apps/openmw-mp/Script/Functions/Worldstate.cpp b/apps/openmw-mp/Script/Functions/Worldstate.cpp index 05de958fc..5ce39cea8 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.cpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.cpp @@ -153,11 +153,21 @@ void WorldstateFunctions::UseActorCollisionForPlacedObjects(bool useActorCollisi writeWorldstate.useActorCollisionForPlacedObjects = useActorCollision; } +void WorldstateFunctions::AddSynchronizedClientScriptId(const char *scriptId) noexcept +{ + writeWorldstate.synchronizedClientScriptIds.push_back(scriptId); +} + void WorldstateFunctions::AddEnforcedCollisionRefId(const char *refId) noexcept { writeWorldstate.enforcedCollisionRefIds.push_back(refId); } +void WorldstateFunctions::ClearSynchronizedClientScriptIds() noexcept +{ + writeWorldstate.synchronizedClientScriptIds.clear(); +} + void WorldstateFunctions::ClearEnforcedCollisionRefIds() noexcept { writeWorldstate.enforcedCollisionRefIds.clear(); @@ -196,6 +206,22 @@ void WorldstateFunctions::LoadMapTileImageFile(int cellX, int cellY, const char* } } +void WorldstateFunctions::SendClientScriptSettings(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + writeWorldstate.guid = player->guid; + + mwmp::WorldstatePacket *packet = mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_CLIENT_SCRIPT_SETTINGS); + packet->setWorldstate(&writeWorldstate); + + if (!skipAttachedPlayer) + packet->Send(false); + if (sendToOtherPlayers) + packet->Send(true); +} + void WorldstateFunctions::SendWorldMap(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept { Player *player; diff --git a/apps/openmw-mp/Script/Functions/Worldstate.hpp b/apps/openmw-mp/Script/Functions/Worldstate.hpp index 3728d84a9..6406b53b6 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.hpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.hpp @@ -43,12 +43,16 @@ {"SetPlacedObjectCollisionState", WorldstateFunctions::SetPlacedObjectCollisionState},\ {"UseActorCollisionForPlacedObjects", WorldstateFunctions::UseActorCollisionForPlacedObjects},\ \ + {"AddSynchronizedClientScriptId", WorldstateFunctions::AddSynchronizedClientScriptId},\ {"AddEnforcedCollisionRefId", WorldstateFunctions::AddEnforcedCollisionRefId},\ + \ + {"ClearSynchronizedClientScriptIds", WorldstateFunctions::ClearSynchronizedClientScriptIds},\ {"ClearEnforcedCollisionRefIds", WorldstateFunctions::ClearEnforcedCollisionRefIds},\ \ {"SaveMapTileImageFile", WorldstateFunctions::SaveMapTileImageFile},\ {"LoadMapTileImageFile", WorldstateFunctions::LoadMapTileImageFile},\ \ + {"SendClientScriptSettings", WorldstateFunctions::SendClientScriptSettings},\ {"SendWorldMap", WorldstateFunctions::SendWorldMap},\ {"SendWorldTime", WorldstateFunctions::SendWorldTime},\ {"SendWorldWeather", WorldstateFunctions::SendWorldWeather},\ @@ -293,6 +297,15 @@ public: */ static void UseActorCollisionForPlacedObjects(bool useActorCollision) noexcept; + /** + * \brief Add an ID to the list of script IDs whose variables should all be synchronized + * across players. + * + * \param scriptId The ID. + * \return void + */ + static void AddSynchronizedClientScriptId(const char* scriptId) noexcept; + /** * \brief Add a refId to the list of refIds for which collision should be enforced * irrespective of other settings. @@ -303,7 +316,15 @@ public: static void AddEnforcedCollisionRefId(const char* refId) noexcept; /** - * \brief Clear the list of refIdsd for which collision should be enforced irrespective + * \brief Clear the list of script IDs whose variables should all be synchronized + * across players. + * + * \return void + */ + static void ClearSynchronizedClientScriptIds() noexcept; + + /** + * \brief Clear the list of refIds for which collision should be enforced irrespective * of other settings. * * \return void @@ -331,6 +352,19 @@ public: */ static void LoadMapTileImageFile(int cellX, int cellY, const char* filePath) noexcept; + /** + * \brief Send a ClientScriptSettings packet with the current client script settings in + * the write-only worldstate. + * + * \param pid The player ID attached to the packet. + * \param sendToOtherPlayers Whether this packet should be sent to players other than the + * player attached to the packet (false by default). + * \param skipAttachedPlayer Whether the packet should skip being sent to the player attached + * to the packet (false by default). + * \return void + */ + static void SendClientScriptSettings(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept; + /** * \brief Send a WorldRegionAuthority packet establishing a certain player as the only one who * should process certain region-specific events (such as weather changes). diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 05a684732..3f8ce4330 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -134,8 +134,8 @@ add_openmw_dir (mwmp/processors/object BaseObjectProcessor ProcessorScriptGlobalFloat ) -add_openmw_dir (mwmp/processors/worldstate ProcessorCellCreate ProcessorCellReset ProcessorRecordDynamic - ProcessorWorldCollisionOverride ProcessorWorldMap ProcessorWorldRegionAuthority ProcessorWorldTime +add_openmw_dir (mwmp/processors/worldstate ProcessorCellCreate ProcessorCellReset ProcessorClientScriptSettings + ProcessorRecordDynamic ProcessorWorldCollisionOverride ProcessorWorldMap ProcessorWorldRegionAuthority ProcessorWorldTime ProcessorWorldWeather ) diff --git a/apps/openmw/mwmp/Main.cpp b/apps/openmw/mwmp/Main.cpp index b5d8aab5e..8c8bb94fa 100644 --- a/apps/openmw/mwmp/Main.cpp +++ b/apps/openmw/mwmp/Main.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -231,79 +232,12 @@ CellController *Main::getCellController() const return mCellController; } -// When sending packets with ingame script values, certain packets -// should be ignored because of their potential for spam bool Main::isValidPacketScript(std::string script) { - static const int validPacketScriptsCount = 21; - static const std::string validPacketScripts[validPacketScriptsCount] = { - // Ghostgate buttons - "GG_OpenGate1", // coc Ghostgate - "GG_OpenGate2", - // Dwemer ruin cranks - "Arkn_doors", // coe 0, -2 - "nchuleftingthWrong1", // coc "Nchuleftingth, Test of Pattern" - "nchuleftingthWrong2", - "nchulfetingthRight", - "Akula_innerdoors", // coc "Akulakhan's Chamber" - "Dagoth_doors", // coe 2, 8 - // Sotha Sil levers - "SothaLever1", // coc "Sotha Sil, Outer Flooded Halls" - "SothaLever2", - "SothaLever3", - "SothaLever4", - "SothaLever5", - "SothaLever6", - "SothaLever7", - "SothaLever8", - "SothaLever9", - "SothaLever10", - "SothaLever11", - "SothaOilLever", // coc "Sotha Sil, Dome of Udok" - // Generic state script - "LocalState" - }; + mwmp::BaseWorldstate *worldstate = get().getNetworking()->getWorldstate(); - static const int invalidPacketScriptsCount = 17; - static const std::string invalidPacketScripts[invalidPacketScriptsCount] = { - // Spammy shorts - "OutsideBanner", - "sleeperScript", - "dreamer_talkerEnable", - "drenSlaveOwners", - "ahnassiScript", - "hlormarScript", - // Spammy floats - "Float", - "SignRotate", - "FaluraScript", - "jsaddhaScript", - // Spammy globals - "wraithguardScript", - // Spammy globals leading to crashes - "LegionUniform", - "OrdinatorUniform", - "LorkhanHeart", - "ouch_keening", - "ouch_sunder", - "ouch_wraithguard" - }; - - for (const auto &validPacketScript : validPacketScripts) - { - if (Misc::StringUtils::ciEqual(script, validPacketScript)) - return true; - } + if (Utils::vectorContains(worldstate->synchronizedClientScriptIds, script)) + return true; return false; - - /* Switch over to this when using a blacklist system - for (int i = 0; i < invalidPacketScriptsCount; i++) - { - if (Misc::StringUtils::ciEqual(script, invalidPacketScripts[i])) - return false; - } - - return true; - */ } diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 4e3c71de3..cb60d77c0 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -91,6 +91,7 @@ #include "WorldstateProcessor.hpp" #include "worldstate/ProcessorCellCreate.hpp" #include "worldstate/ProcessorCellReset.hpp" +#include "worldstate/ProcessorClientScriptSettings.hpp" #include "worldstate/ProcessorRecordDynamic.hpp" #include "worldstate/ProcessorWorldCollisionOverride.hpp" #include "worldstate/ProcessorWorldMap.hpp" @@ -189,6 +190,7 @@ void ProcessorInitializer() WorldstateProcessor::AddProcessor(new ProcessorCellCreate()); WorldstateProcessor::AddProcessor(new ProcessorCellReset()); + WorldstateProcessor::AddProcessor(new ProcessorClientScriptSettings()); WorldstateProcessor::AddProcessor(new ProcessorRecordDynamic()); WorldstateProcessor::AddProcessor(new ProcessorWorldCollisionOverride()); WorldstateProcessor::AddProcessor(new ProcessorWorldMap()); diff --git a/apps/openmw/mwmp/processors/worldstate/ProcessorClientScriptSettings.hpp b/apps/openmw/mwmp/processors/worldstate/ProcessorClientScriptSettings.hpp new file mode 100644 index 000000000..2db5a8b12 --- /dev/null +++ b/apps/openmw/mwmp/processors/worldstate/ProcessorClientScriptSettings.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_PROCESSORCLIENTSCRIPTSETTINGS_HPP +#define OPENMW_PROCESSORCLIENTSCRIPTSETTINGS_HPP + + +#include +#include +#include "../WorldstateProcessor.hpp" + +namespace mwmp +{ + class ProcessorClientScriptSettings : public WorldstateProcessor + { + public: + ProcessorClientScriptSettings() + { + BPP_INIT(ID_CLIENT_SCRIPT_SETTINGS) + } + + virtual void Do(WorldstatePacket &packet, Worldstate &worldstate) + { + // Placeholder + } + }; +} + + + +#endif //OPENMW_PROCESSORCLIENTSCRIPTSETTINGS_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 339de9071..0481b9439 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -208,8 +208,8 @@ add_component_dir (openmw-mp/Packets/Object add_component_dir (openmw-mp/Packets/Worldstate WorldstatePacket - PacketCellCreate PacketCellReset PacketRecordDynamic PacketWorldCollisionOverride PacketWorldMap - PacketWorldRegionAuthority PacketWorldTime PacketWorldWeather + PacketCellCreate PacketCellReset PacketClientScriptSettings PacketRecordDynamic PacketWorldCollisionOverride + PacketWorldMap PacketWorldRegionAuthority PacketWorldTime PacketWorldWeather ) add_component_dir (fallback diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index 90b6dd072..8d42680eb 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -307,6 +307,7 @@ namespace mwmp RakNet::RakNetGUID guid; mwmp::Time time; + std::vector synchronizedClientScriptIds; bool hasPlayerCollision; bool hasActorCollision; diff --git a/components/openmw-mp/Controllers/WorldstatePacketController.cpp b/components/openmw-mp/Controllers/WorldstatePacketController.cpp index a25d0a567..6794448d7 100644 --- a/components/openmw-mp/Controllers/WorldstatePacketController.cpp +++ b/components/openmw-mp/Controllers/WorldstatePacketController.cpp @@ -1,5 +1,6 @@ #include "../Packets/Worldstate/PacketCellCreate.hpp" #include "../Packets/Worldstate/PacketCellReset.hpp" +#include "../Packets/Worldstate/PacketClientScriptSettings.hpp" #include "../Packets/Worldstate/PacketRecordDynamic.hpp" #include "../Packets/Worldstate/PacketWorldCollisionOverride.hpp" #include "../Packets/Worldstate/PacketWorldMap.hpp" @@ -21,6 +22,7 @@ mwmp::WorldstatePacketController::WorldstatePacketController(RakNet::RakPeerInte { AddPacket(&packets, peer); AddPacket(&packets, peer); + AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); diff --git a/components/openmw-mp/NetworkMessages.hpp b/components/openmw-mp/NetworkMessages.hpp index d2f6ba5e5..af3867fd6 100644 --- a/components/openmw-mp/NetworkMessages.hpp +++ b/components/openmw-mp/NetworkMessages.hpp @@ -99,7 +99,7 @@ enum GameMessages ID_GAME_SETTINGS, ID_GAME_PREINIT, - ID_CELL_CREATE, + ID_CLIENT_SCRIPT_SETTINGS, ID_CELL_RESET, ID_RECORD_DYNAMIC, ID_WORLD_COLLISION_OVERRIDE, diff --git a/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.cpp b/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.cpp new file mode 100644 index 000000000..1a494e9cb --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.cpp @@ -0,0 +1,33 @@ +#include "PacketClientScriptSettings.hpp" +#include + +using namespace mwmp; + +PacketClientScriptSettings::PacketClientScriptSettings(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer) +{ + packetID = ID_CLIENT_SCRIPT_SETTINGS; + orderChannel = CHANNEL_WORLDSTATE; +} + +void PacketClientScriptSettings::Packet(RakNet::BitStream *bs, bool send) +{ + WorldstatePacket::Packet(bs, send); + + uint32_t clientScriptsCount; + + if (send) + clientScriptsCount = static_cast(worldstate->synchronizedClientScriptIds.size()); + + RW(clientScriptsCount, send); + + if (!send) + { + worldstate->synchronizedClientScriptIds.clear(); + worldstate->synchronizedClientScriptIds.resize(clientScriptsCount); + } + + for (auto &&clientScriptId : worldstate->synchronizedClientScriptIds) + { + RW(clientScriptId, send); + } +} diff --git a/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.hpp b/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.hpp new file mode 100644 index 000000000..378200bad --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketClientScriptSettings.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP +#define OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP + +#include + +namespace mwmp +{ + class PacketClientScriptSettings : public WorldstatePacket + { + public: + PacketClientScriptSettings(RakNet::RakPeerInterface *peer); + + virtual void Packet(RakNet::BitStream *bs, bool send); + }; +} + +#endif //OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP