mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 02:15:33 +00:00
e6c626f127
ClientScriptGlobal is a new Worldstate packet that handles short, long and float values for global variables in clientside scripts. Previously, short values were handled by the ScriptGlobalShort packet, while a partially implemented ScriptGlobalFloat packet also existed, but both of those packets were Object packets because they were added near the end of 2016 when only Player and Object packets existed (with the latter actually being called WorldEvent packets at the time). Both ScriptGlobalShort and ScriptGlobalFloat have now been removed. The serverside script functions previously used to interact with ScriptGlobalShort have, however, been kept so they can be adjusted to work with local variables in clientside scripts instead in a future commit.
463 lines
13 KiB
C++
463 lines
13 KiB
C++
#include <components/openmw-mp/NetworkMessages.hpp>
|
|
|
|
#include <apps/openmw-mp/Networking.hpp>
|
|
#include <apps/openmw-mp/Player.hpp>
|
|
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
|
|
#include <fstream>
|
|
|
|
#include "Worldstate.hpp"
|
|
|
|
using namespace std;
|
|
using namespace mwmp;
|
|
|
|
BaseWorldstate *WorldstateFunctions::readWorldstate;
|
|
BaseWorldstate WorldstateFunctions::writeWorldstate;
|
|
|
|
void WorldstateFunctions::ReadReceivedWorldstate() noexcept
|
|
{
|
|
readWorldstate = mwmp::Networking::getPtr()->getReceivedWorldstate();
|
|
}
|
|
|
|
void WorldstateFunctions::CopyReceivedWorldstateToStore() noexcept
|
|
{
|
|
writeWorldstate = *readWorldstate;
|
|
}
|
|
|
|
void WorldstateFunctions::ClearKillChanges() noexcept
|
|
{
|
|
writeWorldstate.killChanges.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::ClearMapChanges() noexcept
|
|
{
|
|
writeWorldstate.mapTiles.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::ClearClientGlobals() noexcept
|
|
{
|
|
writeWorldstate.clientGlobals.clear();
|
|
}
|
|
|
|
unsigned int WorldstateFunctions::GetKillChangesSize() noexcept
|
|
{
|
|
return readWorldstate->killChanges.size();
|
|
}
|
|
|
|
unsigned int WorldstateFunctions::GetMapChangesSize() noexcept
|
|
{
|
|
return readWorldstate->mapTiles.size();
|
|
}
|
|
|
|
unsigned int WorldstateFunctions::GetClientGlobalsSize() noexcept
|
|
{
|
|
return readWorldstate->clientGlobals.size();
|
|
}
|
|
|
|
const char *WorldstateFunctions::GetKillRefId(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->killChanges.at(index).refId.c_str();
|
|
}
|
|
|
|
int WorldstateFunctions::GetKillNumber(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->killChanges.at(index).number;
|
|
}
|
|
|
|
const char *WorldstateFunctions::GetWeatherRegion() noexcept
|
|
{
|
|
return readWorldstate->weather.region.c_str();
|
|
}
|
|
|
|
int WorldstateFunctions::GetWeatherCurrent() noexcept
|
|
{
|
|
return readWorldstate->weather.currentWeather;
|
|
}
|
|
|
|
int WorldstateFunctions::GetWeatherNext() noexcept
|
|
{
|
|
return readWorldstate->weather.nextWeather;
|
|
}
|
|
|
|
int WorldstateFunctions::GetWeatherQueued() noexcept
|
|
{
|
|
return readWorldstate->weather.queuedWeather;
|
|
}
|
|
|
|
double WorldstateFunctions::GetWeatherTransitionFactor() noexcept
|
|
{
|
|
return readWorldstate->weather.transitionFactor;
|
|
}
|
|
|
|
int WorldstateFunctions::GetMapTileCellX(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->mapTiles.at(index).x;
|
|
}
|
|
|
|
int WorldstateFunctions::GetMapTileCellY(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->mapTiles.at(index).y;
|
|
}
|
|
|
|
const char *WorldstateFunctions::GetClientGlobalId(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->clientGlobals.at(index).id.c_str();
|
|
}
|
|
|
|
unsigned short WorldstateFunctions::GetClientGlobalVariableType(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->clientGlobals.at(index).variableType;
|
|
}
|
|
|
|
int WorldstateFunctions::GetClientGlobalIntValue(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->clientGlobals.at(index).intValue;
|
|
}
|
|
|
|
double WorldstateFunctions::GetClientGlobalFloatValue(unsigned int index) noexcept
|
|
{
|
|
return readWorldstate->clientGlobals.at(index).floatValue;
|
|
}
|
|
|
|
void WorldstateFunctions::SetAuthorityRegion(const char* authorityRegion) noexcept
|
|
{
|
|
writeWorldstate.authorityRegion = authorityRegion;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherRegion(const char* region) noexcept
|
|
{
|
|
writeWorldstate.weather.region = region;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherForceState(bool forceState) noexcept
|
|
{
|
|
writeWorldstate.forceWeather = forceState;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherCurrent(int currentWeather) noexcept
|
|
{
|
|
writeWorldstate.weather.currentWeather = currentWeather;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherNext(int nextWeather) noexcept
|
|
{
|
|
writeWorldstate.weather.nextWeather = nextWeather;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherQueued(int queuedWeather) noexcept
|
|
{
|
|
writeWorldstate.weather.queuedWeather = queuedWeather;
|
|
}
|
|
|
|
void WorldstateFunctions::SetWeatherTransitionFactor(double transitionFactor) noexcept
|
|
{
|
|
writeWorldstate.weather.transitionFactor = transitionFactor;
|
|
}
|
|
|
|
void WorldstateFunctions::SetHour(double hour) noexcept
|
|
{
|
|
writeWorldstate.time.hour = hour;
|
|
}
|
|
|
|
void WorldstateFunctions::SetDay(int day) noexcept
|
|
{
|
|
writeWorldstate.time.day = day;
|
|
}
|
|
|
|
void WorldstateFunctions::SetMonth(int month) noexcept
|
|
{
|
|
writeWorldstate.time.month = month;
|
|
}
|
|
|
|
void WorldstateFunctions::SetYear(int year) noexcept
|
|
{
|
|
writeWorldstate.time.year = year;
|
|
}
|
|
|
|
void WorldstateFunctions::SetDaysPassed(int daysPassed) noexcept
|
|
{
|
|
writeWorldstate.time.daysPassed = daysPassed;
|
|
}
|
|
|
|
void WorldstateFunctions::SetTimeScale(double timeScale) noexcept
|
|
{
|
|
writeWorldstate.time.timeScale = timeScale;
|
|
}
|
|
|
|
void WorldstateFunctions::SetPlayerCollisionState(bool state) noexcept
|
|
{
|
|
writeWorldstate.hasPlayerCollision = state;
|
|
}
|
|
|
|
void WorldstateFunctions::SetActorCollisionState(bool state) noexcept
|
|
{
|
|
writeWorldstate.hasActorCollision = state;
|
|
}
|
|
|
|
void WorldstateFunctions::SetPlacedObjectCollisionState(bool state) noexcept
|
|
{
|
|
writeWorldstate.hasPlacedObjectCollision = state;
|
|
}
|
|
|
|
void WorldstateFunctions::UseActorCollisionForPlacedObjects(bool useActorCollision) noexcept
|
|
{
|
|
writeWorldstate.useActorCollisionForPlacedObjects = useActorCollision;
|
|
}
|
|
|
|
void WorldstateFunctions::AddKill(const char* refId, int number) noexcept
|
|
{
|
|
mwmp::Kill kill;
|
|
kill.refId = refId;
|
|
kill.number = number;
|
|
|
|
writeWorldstate.killChanges.push_back(kill);
|
|
}
|
|
|
|
void WorldstateFunctions::AddClientGlobalInteger(const char* id, int intValue) noexcept
|
|
{
|
|
mwmp::ClientVariable clientVariable;
|
|
clientVariable.id = id;
|
|
clientVariable.variableType = mwmp::VARIABLE_TYPE::INTEGER;
|
|
clientVariable.intValue = intValue;
|
|
|
|
writeWorldstate.clientGlobals.push_back(clientVariable);
|
|
}
|
|
|
|
void WorldstateFunctions::AddClientGlobalFloat(const char* id, double floatValue) noexcept
|
|
{
|
|
mwmp::ClientVariable clientVariable;
|
|
clientVariable.id = id;
|
|
clientVariable.variableType = mwmp::VARIABLE_TYPE::FLOAT;
|
|
clientVariable.floatValue = floatValue;
|
|
|
|
writeWorldstate.clientGlobals.push_back(clientVariable);
|
|
}
|
|
|
|
void WorldstateFunctions::AddSynchronizedClientScriptId(const char *scriptId) noexcept
|
|
{
|
|
writeWorldstate.synchronizedClientScriptIds.push_back(scriptId);
|
|
}
|
|
|
|
void WorldstateFunctions::AddSynchronizedClientGlobalId(const char *globalId) noexcept
|
|
{
|
|
writeWorldstate.synchronizedClientGlobalIds.push_back(globalId);
|
|
}
|
|
|
|
void WorldstateFunctions::AddEnforcedCollisionRefId(const char *refId) noexcept
|
|
{
|
|
writeWorldstate.enforcedCollisionRefIds.push_back(refId);
|
|
}
|
|
|
|
void WorldstateFunctions::AddDestinationOverride(const char *oldCellDescription, const char *newCellDescription) noexcept
|
|
{
|
|
writeWorldstate.destinationOverrides[oldCellDescription] = newCellDescription;
|
|
}
|
|
|
|
void WorldstateFunctions::ClearSynchronizedClientScriptIds() noexcept
|
|
{
|
|
writeWorldstate.synchronizedClientScriptIds.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::ClearSynchronizedClientGlobalIds() noexcept
|
|
{
|
|
writeWorldstate.synchronizedClientGlobalIds.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::ClearEnforcedCollisionRefIds() noexcept
|
|
{
|
|
writeWorldstate.enforcedCollisionRefIds.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::ClearDestinationOverrides() noexcept
|
|
{
|
|
writeWorldstate.destinationOverrides.clear();
|
|
}
|
|
|
|
void WorldstateFunctions::SaveMapTileImageFile(unsigned int index, const char *filePath) noexcept
|
|
{
|
|
if (index >= readWorldstate->mapTiles.size())
|
|
return;
|
|
|
|
const std::vector<char>& imageData = readWorldstate->mapTiles.at(index).imageData;
|
|
|
|
std::ofstream outputFile(filePath, std::ios::binary);
|
|
std::ostream_iterator<char> outputIterator(outputFile);
|
|
std::copy(imageData.begin(), imageData.end(), outputIterator);
|
|
}
|
|
|
|
void WorldstateFunctions::LoadMapTileImageFile(int cellX, int cellY, const char* filePath) noexcept
|
|
{
|
|
mwmp::MapTile mapTile;
|
|
mapTile.x = cellX;
|
|
mapTile.y = cellY;
|
|
|
|
std::ifstream inputFile(filePath, std::ios::binary);
|
|
mapTile.imageData = std::vector<char>(std::istreambuf_iterator<char>(inputFile), std::istreambuf_iterator<char>());
|
|
|
|
if (mapTile.imageData.size() > mwmp::maxImageDataSize)
|
|
{
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Error loading image file for map tile: "
|
|
"%s has a size of %i, which is over the maximum allowed of %i!",
|
|
filePath, mapTile.imageData.size(), mwmp::maxImageDataSize);
|
|
}
|
|
else
|
|
{
|
|
writeWorldstate.mapTiles.push_back(mapTile);
|
|
}
|
|
}
|
|
|
|
void WorldstateFunctions::SendClientScriptGlobal(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_GLOBAL);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
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::SendWorldKillCount(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_WORLD_KILL_COUNT);
|
|
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;
|
|
GET_PLAYER(pid, player, );
|
|
|
|
writeWorldstate.guid = player->guid;
|
|
|
|
mwmp::WorldstatePacket *packet = mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_MAP);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
void WorldstateFunctions::SendWorldTime(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_WORLD_TIME);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
void WorldstateFunctions::SendWorldWeather(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_WORLD_WEATHER);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
void WorldstateFunctions::SendWorldCollisionOverride(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_WORLD_COLLISION_OVERRIDE);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
void WorldstateFunctions::SendWorldDestinationOverride(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_WORLD_DESTINATION_OVERRIDE);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
if (!skipAttachedPlayer)
|
|
packet->Send(false);
|
|
if (sendToOtherPlayers)
|
|
packet->Send(true);
|
|
}
|
|
|
|
void WorldstateFunctions::SendWorldRegionAuthority(unsigned short pid) noexcept
|
|
{
|
|
Player *player;
|
|
GET_PLAYER(pid, player, );
|
|
|
|
writeWorldstate.guid = player->guid;
|
|
|
|
mwmp::WorldstatePacket *packet = mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_REGION_AUTHORITY);
|
|
packet->setWorldstate(&writeWorldstate);
|
|
|
|
packet->Send(false);
|
|
|
|
// This packet should always be sent to all other players
|
|
packet->Send(true);
|
|
}
|
|
|
|
|
|
// All methods below are deprecated versions of methods from above
|
|
|
|
void WorldstateFunctions::ReadLastWorldstate() noexcept
|
|
{
|
|
ReadReceivedWorldstate();
|
|
}
|
|
|
|
void WorldstateFunctions::CopyLastWorldstateToStore() noexcept
|
|
{
|
|
CopyReceivedWorldstateToStore();
|
|
}
|