1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-29 17:15:32 +00:00

[General] Implement ClientScriptSettings packet, part 1

For starters, the new packet can set which client scripts have all of their variables synchronized between players. The previous hardcoded list of IDs for synchronized scripts has been removed.
This commit is contained in:
David Cernat 2019-09-09 10:28:35 +03:00
parent 25e27ccb95
commit 3acfbad55d
12 changed files with 153 additions and 76 deletions

View file

@ -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;

View file

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

View file

@ -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
)

View file

@ -1,5 +1,6 @@
#include <cstdlib>
#include <components/openmw-mp/Utils.hpp>
#include <components/openmw-mp/TimedLog.hpp>
#include <components/openmw-mp/Version.hpp>
@ -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;
*/
}

View file

@ -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());

View file

@ -0,0 +1,28 @@
#ifndef OPENMW_PROCESSORCLIENTSCRIPTSETTINGS_HPP
#define OPENMW_PROCESSORCLIENTSCRIPTSETTINGS_HPP
#include <apps/openmw/mwbase/world.hpp>
#include <apps/openmw/mwbase/environment.hpp>
#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

View file

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

View file

@ -307,6 +307,7 @@ namespace mwmp
RakNet::RakNetGUID guid;
mwmp::Time time;
std::vector<std::string> synchronizedClientScriptIds;
bool hasPlayerCollision;
bool hasActorCollision;

View file

@ -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<PacketCellCreate>(&packets, peer);
AddPacket<PacketCellReset>(&packets, peer);
AddPacket<PacketClientScriptSettings>(&packets, peer);
AddPacket<PacketRecordDynamic>(&packets, peer);
AddPacket<PacketWorldCollisionOverride>(&packets, peer);
AddPacket<PacketWorldMap>(&packets, peer);

View file

@ -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,

View file

@ -0,0 +1,33 @@
#include "PacketClientScriptSettings.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
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<uint32_t>(worldstate->synchronizedClientScriptIds.size());
RW(clientScriptsCount, send);
if (!send)
{
worldstate->synchronizedClientScriptIds.clear();
worldstate->synchronizedClientScriptIds.resize(clientScriptsCount);
}
for (auto &&clientScriptId : worldstate->synchronizedClientScriptIds)
{
RW(clientScriptId, send);
}
}

View file

@ -0,0 +1,17 @@
#ifndef OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP
#define OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP
#include <components/openmw-mp/Packets/Worldstate/WorldstatePacket.hpp>
namespace mwmp
{
class PacketClientScriptSettings : public WorldstatePacket
{
public:
PacketClientScriptSettings(RakNet::RakPeerInterface *peer);
virtual void Packet(RakNet::BitStream *bs, bool send);
};
}
#endif //OPENMW_PACKETCLIENTSCRIPTSETTINGS_HPP