1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 18:19:55 +00:00

[General] Add and implement new Worldstate packet type

This commit is contained in:
David Cernat 2018-05-18 06:40:28 +03:00
parent e8b22a2e5e
commit 43a944ddaf
18 changed files with 346 additions and 14 deletions

View file

@ -164,6 +164,7 @@ set(PROCESSORS
processors/PlayerProcessor.cpp processors/PlayerProcessor.cpp
processors/ActorProcessor.cpp processors/ActorProcessor.cpp
processors/ObjectProcessor.cpp processors/ObjectProcessor.cpp
processors/WorldstateProcessor.cpp
) )
source_group(tes3mp-server\\processors FILES ${PROCESSORS}) source_group(tes3mp-server\\processors FILES ${PROCESSORS})

View file

@ -26,6 +26,7 @@
#include "processors/PlayerProcessor.hpp" #include "processors/PlayerProcessor.hpp"
#include "processors/ActorProcessor.hpp" #include "processors/ActorProcessor.hpp"
#include "processors/ObjectProcessor.hpp" #include "processors/ObjectProcessor.hpp"
#include "processors/WorldstateProcessor.hpp"
using namespace mwmp; using namespace mwmp;
using namespace std; using namespace std;
@ -46,6 +47,7 @@ Networking::Networking(RakNet::RakPeerInterface *peer) : mclient(nullptr)
playerPacketController = new PlayerPacketController(peer); playerPacketController = new PlayerPacketController(peer);
actorPacketController = new ActorPacketController(peer); actorPacketController = new ActorPacketController(peer);
objectPacketController = new ObjectPacketController(peer); objectPacketController = new ObjectPacketController(peer);
worldstatePacketController = new WorldstatePacketController(peer);
// Set send stream // Set send stream
playerPacketController->SetStream(0, &bsOut); playerPacketController->SetStream(0, &bsOut);
@ -193,6 +195,18 @@ void Networking::processObjectPacket(RakNet::Packet *packet)
} }
void Networking::processWorldstatePacket(RakNet::Packet *packet)
{
Player *player = Players::getPlayer(packet->guid);
if (!player->isHandshaked() || player->getLoadState() != Player::POSTLOADED)
return;
if (!WorldstateProcessor::Process(*packet, baseWorldstate))
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled WorldstatePacket with identifier %i has arrived", packet->data[0]);
}
void Networking::update(RakNet::Packet *packet) void Networking::update(RakNet::Packet *packet)
{ {
Player *player = Players::getPlayer(packet->guid); Player *player = Players::getPlayer(packet->guid);
@ -280,6 +294,11 @@ void Networking::update(RakNet::Packet *packet)
objectPacketController->SetStream(&bsIn, 0); objectPacketController->SetStream(&bsIn, 0);
processObjectPacket(packet); processObjectPacket(packet);
} }
else if (worldstatePacketController->ContainsPacket(packet->data[0]))
{
worldstatePacketController->SetStream(&bsIn, 0);
processWorldstatePacket(packet);
}
else else
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled RakNet packet with identifier %i has arrived", packet->data[0]); LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled RakNet packet with identifier %i has arrived", packet->data[0]);
} }
@ -357,6 +376,11 @@ ObjectPacketController *Networking::getObjectPacketController() const
return objectPacketController; return objectPacketController;
} }
WorldstatePacketController *Networking::getWorldstatePacketController() const
{
return worldstatePacketController;
}
BaseActorList *Networking::getLastActorList() BaseActorList *Networking::getLastActorList()
{ {
return &baseActorList; return &baseActorList;
@ -367,6 +391,11 @@ BaseObjectList *Networking::getLastObjectList()
return &baseObjectList; return &baseObjectList;
} }
BaseWorldstate *Networking::getLastWorldstate()
{
return &baseWorldstate;
}
int Networking::getCurrentMpNum() int Networking::getCurrentMpNum()
{ {
return currentMpNum; return currentMpNum;

View file

@ -1,13 +1,10 @@
//
// Created by koncord on 12.01.16.
//
#ifndef OPENMW_NETWORKING_HPP #ifndef OPENMW_NETWORKING_HPP
#define OPENMW_NETWORKING_HPP #define OPENMW_NETWORKING_HPP
#include <components/openmw-mp/Controllers/PlayerPacketController.hpp> #include <components/openmw-mp/Controllers/PlayerPacketController.hpp>
#include <components/openmw-mp/Controllers/ActorPacketController.hpp> #include <components/openmw-mp/Controllers/ActorPacketController.hpp>
#include <components/openmw-mp/Controllers/ObjectPacketController.hpp> #include <components/openmw-mp/Controllers/ObjectPacketController.hpp>
#include <components/openmw-mp/Controllers/WorldstatePacketController.hpp>
#include <components/openmw-mp/Packets/PacketPreInit.hpp> #include <components/openmw-mp/Packets/PacketPreInit.hpp>
#include "Player.hpp" #include "Player.hpp"
@ -31,6 +28,7 @@ namespace mwmp
void processPlayerPacket(RakNet::Packet *packet); void processPlayerPacket(RakNet::Packet *packet);
void processActorPacket(RakNet::Packet *packet); void processActorPacket(RakNet::Packet *packet);
void processObjectPacket(RakNet::Packet *packet); void processObjectPacket(RakNet::Packet *packet);
void processWorldstatePacket(RakNet::Packet *packet);
void update(RakNet::Packet *packet); void update(RakNet::Packet *packet);
unsigned short numberOfConnections() const; unsigned short numberOfConnections() const;
@ -44,9 +42,11 @@ namespace mwmp
PlayerPacketController *getPlayerPacketController() const; PlayerPacketController *getPlayerPacketController() const;
ActorPacketController *getActorPacketController() const; ActorPacketController *getActorPacketController() const;
ObjectPacketController *getObjectPacketController() const; ObjectPacketController *getObjectPacketController() const;
WorldstatePacketController *getWorldstatePacketController() const;
BaseActorList *getLastActorList(); BaseActorList *getLastActorList();
BaseObjectList *getLastObjectList(); BaseObjectList *getLastObjectList();
BaseWorldstate *getLastWorldstate();
int getCurrentMpNum(); int getCurrentMpNum();
void setCurrentMpNum(int value); void setCurrentMpNum(int value);
@ -76,10 +76,12 @@ namespace mwmp
BaseActorList baseActorList; BaseActorList baseActorList;
BaseObjectList baseObjectList; BaseObjectList baseObjectList;
BaseWorldstate baseWorldstate;
PlayerPacketController *playerPacketController; PlayerPacketController *playerPacketController;
ActorPacketController *actorPacketController; ActorPacketController *actorPacketController;
ObjectPacketController *objectPacketController; ObjectPacketController *objectPacketController;
WorldstatePacketController *worldstatePacketController;
bool running; bool running;
int exitCode; int exitCode;

View file

@ -0,0 +1,40 @@
#include "WorldstateProcessor.hpp"
#include "Networking.hpp"
using namespace mwmp;
template<class T>
typename BasePacketProcessor<T>::processors_t BasePacketProcessor<T>::processors;
void WorldstateProcessor::Do(WorldstatePacket &packet, Player &player, BaseWorldstate &worldstate)
{
packet.Send(true);
}
bool WorldstateProcessor::Process(RakNet::Packet &packet, BaseWorldstate &worldstate) noexcept
{
worldstate.guid = packet.guid;
for (auto &processor : processors)
{
if (processor.first == packet.data[0])
{
Player *player = Players::getPlayer(packet.guid);
WorldstatePacket *myPacket = Networking::get().getWorldstatePacketController()->GetPacket(packet.data[0]);
myPacket->setWorldstate(&worldstate);
worldstate.isValid = true;
if (!processor.second->avoidReading)
myPacket->Read();
if (worldstate.isValid)
processor.second->Do(*myPacket, *player, worldstate);
else
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Received %s that failed integrity check and was ignored!", processor.second->strPacketID.c_str());
return true;
}
}
return false;
}

View file

@ -0,0 +1,22 @@
#ifndef OPENMW_BASEWORLDSTATEPROCESSOR_HPP
#define OPENMW_BASEWORLDSTATEPROCESSOR_HPP
#include <components/openmw-mp/Base/BasePacketProcessor.hpp>
#include <components/openmw-mp/Packets/BasePacket.hpp>
#include <components/openmw-mp/Packets/Worldstate/WorldstatePacket.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Player.hpp"
namespace mwmp
{
class WorldstateProcessor : public BasePacketProcessor<WorldstateProcessor>
{
public:
virtual void Do(WorldstatePacket &packet, Player &player, BaseWorldstate &worldstate);
static bool Process(RakNet::Packet &packet, BaseWorldstate &worldstate) noexcept;
};
}
#endif //OPENMW_BASEWORLDSTATEPROCESSOR_HPP

View file

@ -104,7 +104,8 @@ add_openmw_dir (mwmp Main Networking LocalPlayer DedicatedPlayer PlayerList Loca
add_openmw_dir (mwmp/GUI GUIChat GUILogin PlayerMarkerCollection GUIDialogList TextInputDialog add_openmw_dir (mwmp/GUI GUIChat GUILogin PlayerMarkerCollection GUIDialogList TextInputDialog
) )
add_openmw_dir(mwmp/processors BaseClientPacketProcessor PlayerProcessor ObjectProcessor ActorProcessor ProcessorInitializer add_openmw_dir(mwmp/processors BaseClientPacketProcessor PlayerProcessor ObjectProcessor ActorProcessor WorldstateProcessor
ProcessorInitializer
) )
add_openmw_dir (mwmp/processors/actor ProcessorActorAI ProcessorActorAnimFlags ProcessorActorAnimPlay ProcessorActorAttack add_openmw_dir (mwmp/processors/actor ProcessorActorAI ProcessorActorAnimFlags ProcessorActorAnimPlay ProcessorActorAttack

View file

@ -39,6 +39,7 @@
#include "processors/PlayerProcessor.hpp" #include "processors/PlayerProcessor.hpp"
#include "processors/ObjectProcessor.hpp" #include "processors/ObjectProcessor.hpp"
#include "processors/ActorProcessor.hpp" #include "processors/ActorProcessor.hpp"
#include "processors/WorldstateProcessor.hpp"
#include "GUIController.hpp" #include "GUIController.hpp"
#include "CellController.hpp" #include "CellController.hpp"
@ -197,7 +198,7 @@ string listComparison(PacketPreInit::PluginContainer checksums, PacketPreInit::P
} }
Networking::Networking(): peer(RakNet::RakPeerInterface::GetInstance()), playerPacketController(peer), Networking::Networking(): peer(RakNet::RakPeerInterface::GetInstance()), playerPacketController(peer),
actorPacketController(peer), objectPacketController(peer) actorPacketController(peer), objectPacketController(peer), worldstatePacketController(peer)
{ {
RakNet::SocketDescriptor sd; RakNet::SocketDescriptor sd;
@ -208,6 +209,7 @@ Networking::Networking(): peer(RakNet::RakPeerInterface::GetInstance()), playerP
playerPacketController.SetStream(0, &bsOut); playerPacketController.SetStream(0, &bsOut);
actorPacketController.SetStream(0, &bsOut); actorPacketController.SetStream(0, &bsOut);
objectPacketController.SetStream(0, &bsOut); objectPacketController.SetStream(0, &bsOut);
worldstatePacketController.SetStream(0, &bsOut);
connected = 0; connected = 0;
ProcessorInitializer(); ProcessorInitializer();
@ -433,6 +435,11 @@ void Networking::receiveMessage(RakNet::Packet *packet)
if (!ObjectProcessor::Process(*packet, objectList)) if (!ObjectProcessor::Process(*packet, objectList))
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled ObjectPacket with identifier %i has arrived", packet->data[0]); LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled ObjectPacket with identifier %i has arrived", packet->data[0]);
} }
else if (worldstatePacketController.ContainsPacket(packet->data[0]))
{
if (!WorldstateProcessor::Process(*packet, worldstate))
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled WorldstatePacket with identifier %i has arrived", packet->data[0]);
}
} }
PlayerPacket *Networking::getPlayerPacket(RakNet::MessageID id) PlayerPacket *Networking::getPlayerPacket(RakNet::MessageID id)
@ -450,6 +457,11 @@ ObjectPacket *Networking::getObjectPacket(RakNet::MessageID id)
return objectPacketController.GetPacket(id); return objectPacketController.GetPacket(id);
} }
WorldstatePacket *Networking::getWorldstatePacket(RakNet::MessageID id)
{
return worldstatePacketController.GetPacket(id);
}
LocalPlayer *Networking::getLocalPlayer() LocalPlayer *Networking::getLocalPlayer()
{ {
return mwmp::Main::get().getLocalPlayer(); return mwmp::Main::get().getLocalPlayer();
@ -465,6 +477,11 @@ ObjectList *Networking::getObjectList()
return &objectList; return &objectList;
} }
BaseWorldstate *Networking::getWorldstate()
{
return &worldstate;
}
bool Networking::isConnected() bool Networking::isConnected()
{ {
return connected; return connected;

View file

@ -16,6 +16,7 @@
#include <components/openmw-mp/Controllers/PlayerPacketController.hpp> #include <components/openmw-mp/Controllers/PlayerPacketController.hpp>
#include <components/openmw-mp/Controllers/ActorPacketController.hpp> #include <components/openmw-mp/Controllers/ActorPacketController.hpp>
#include <components/openmw-mp/Controllers/ObjectPacketController.hpp> #include <components/openmw-mp/Controllers/ObjectPacketController.hpp>
#include <components/openmw-mp/Controllers/WorldstatePacketController.hpp>
#include <components/files/collections.hpp> #include <components/files/collections.hpp>
@ -34,6 +35,7 @@ namespace mwmp
PlayerPacket *getPlayerPacket(RakNet::MessageID id); PlayerPacket *getPlayerPacket(RakNet::MessageID id);
ActorPacket *getActorPacket(RakNet::MessageID id); ActorPacket *getActorPacket(RakNet::MessageID id);
ObjectPacket *getObjectPacket(RakNet::MessageID id); ObjectPacket *getObjectPacket(RakNet::MessageID id);
WorldstatePacket *getWorldstatePacket(RakNet::MessageID id);
RakNet::SystemAddress serverAddress() RakNet::SystemAddress serverAddress()
{ {
@ -45,6 +47,7 @@ namespace mwmp
LocalPlayer *getLocalPlayer(); LocalPlayer *getLocalPlayer();
ActorList *getActorList(); ActorList *getActorList();
ObjectList *getObjectList(); ObjectList *getObjectList();
BaseWorldstate *getWorldstate();
private: private:
bool connected; bool connected;
@ -55,9 +58,11 @@ namespace mwmp
PlayerPacketController playerPacketController; PlayerPacketController playerPacketController;
ActorPacketController actorPacketController; ActorPacketController actorPacketController;
ObjectPacketController objectPacketController; ObjectPacketController objectPacketController;
WorldstatePacketController worldstatePacketController;
ActorList actorList; ActorList actorList;
ObjectList objectList; ObjectList objectList;
BaseWorldstate worldstate;
void receiveMessage(RakNet::Packet *packet); void receiveMessage(RakNet::Packet *packet);

View file

@ -1,11 +1,6 @@
//
// Created by koncord on 31.03.17.
//
#include "ProcessorInitializer.hpp" #include "ProcessorInitializer.hpp"
#include "PlayerProcessor.hpp" #include "PlayerProcessor.hpp"
#include "player/ProcessorChatMessage.hpp" #include "player/ProcessorChatMessage.hpp"
#include "player/ProcessorGUIMessageBox.hpp" #include "player/ProcessorGUIMessageBox.hpp"
#include "player/ProcessorHandshake.hpp" #include "player/ProcessorHandshake.hpp"
@ -80,6 +75,7 @@
#include "object/ProcessorScriptGlobalFloat.hpp" #include "object/ProcessorScriptGlobalFloat.hpp"
#include "object/ProcessorVideoPlay.hpp" #include "object/ProcessorVideoPlay.hpp"
#include "ActorProcessor.hpp"
#include "actor/ProcessorActorAI.hpp" #include "actor/ProcessorActorAI.hpp"
#include "actor/ProcessorActorAnimFlags.hpp" #include "actor/ProcessorActorAnimFlags.hpp"
#include "actor/ProcessorActorAnimPlay.hpp" #include "actor/ProcessorActorAnimPlay.hpp"
@ -95,6 +91,8 @@
#include "actor/ProcessorActorStatsDynamic.hpp" #include "actor/ProcessorActorStatsDynamic.hpp"
#include "actor/ProcessorActorTest.hpp" #include "actor/ProcessorActorTest.hpp"
#include "WorldstateProcessor.hpp"
using namespace mwmp; using namespace mwmp;
void ProcessorInitializer() void ProcessorInitializer()

View file

@ -0,0 +1,40 @@
#include "../Networking.hpp"
#include "WorldstateProcessor.hpp"
#include "../Main.hpp"
using namespace mwmp;
template<class T>
typename BasePacketProcessor<T>::processors_t BasePacketProcessor<T>::processors;
bool WorldstateProcessor::Process(RakNet::Packet &packet, BaseWorldstate &worldstate)
{
RakNet::BitStream bsIn(&packet.data[1], packet.length, false);
bsIn.Read(guid);
worldstate.guid = guid;
WorldstatePacket *myPacket = Main::get().getNetworking()->getWorldstatePacket(packet.data[0]);
myPacket->SetReadStream(&bsIn);
for (auto &processor : processors)
{
if (processor.first == packet.data[0])
{
myGuid = Main::get().getLocalPlayer()->guid;
request = packet.length == myPacket->headerSize();
worldstate.isValid = true;
if (!request && !processor.second->avoidReading)
myPacket->Read();
if (worldstate.isValid)
processor.second->Do(*myPacket, worldstate);
else
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Received %s that failed integrity check and was ignored!", processor.second->strPacketID.c_str());
return true;
}
}
return false;
}

View file

@ -0,0 +1,22 @@
#ifndef OPENMW_WORLDSTATEPROCESSOR_HPP
#define OPENMW_WORLDSTATEPROCESSOR_HPP
#include <components/openmw-mp/Log.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <components/openmw-mp/Packets/Worldstate/WorldstatePacket.hpp>
#include "BaseClientPacketProcessor.hpp"
namespace mwmp
{
class WorldstateProcessor : public BasePacketProcessor<WorldstateProcessor>, public BaseClientPacketProcessor
{
public:
virtual void Do(WorldstatePacket &packet, BaseWorldstate &worldstate) = 0;
static bool Process(RakNet::Packet &packet, BaseWorldstate &worldstate);
};
}
#endif //OPENMW_WORLDSTATEPROCESSOR_HPP

View file

@ -150,11 +150,11 @@ add_component_dir (openmw-mp
) )
add_component_dir (openmw-mp/Base add_component_dir (openmw-mp/Base
BaseActor BaseObjectList BasePacketProcessor BasePlayer BaseStructs BaseActor BaseObjectList BasePacketProcessor BasePlayer BaseStructs BaseWorldstate
) )
add_component_dir (openmw-mp/Controllers add_component_dir (openmw-mp/Controllers
PlayerPacketController ActorPacketController ObjectPacketController PlayerPacketController ActorPacketController ObjectPacketController WorldstatePacketController
) )
add_component_dir(openmw-mp/Master add_component_dir(openmw-mp/Master
@ -196,6 +196,10 @@ add_component_dir (openmw-mp/Packets/Object
PacketScriptMemberFloat PacketScriptGlobalShort PacketScriptGlobalFloat PacketScriptMemberFloat PacketScriptGlobalShort PacketScriptGlobalFloat
) )
add_component_dir (openmw-mp/Packets/Worldstate
WorldstatePacket
)
add_component_dir (fallback add_component_dir (fallback
fallback validate fallback validate
) )

View file

@ -0,0 +1,26 @@
#ifndef OPENMW_BASEWORLDSTATE_HPP
#define OPENMW_BASEWORLDSTATE_HPP
#include <components/openmw-mp/Base/BaseStructs.hpp>
#include <RakNetTypes.h>
namespace mwmp
{
class BaseWorldstate
{
public:
BaseWorldstate()
{
}
RakNet::RakNetGUID guid;
bool isValid;
};
}
#endif //OPENMW_BASEWORLDSTATE_HPP

View file

@ -0,0 +1,36 @@
#include "WorldstatePacketController.hpp"
template <typename T>
inline void AddPacket(mwmp::WorldstatePacketController::packets_t *packets, RakNet::RakPeerInterface *peer)
{
T *packet = new T(peer);
typedef mwmp::WorldstatePacketController::packets_t::value_type value_t;
packets->insert(value_t(packet->GetPacketID(), value_t::second_type(packet)));
}
mwmp::WorldstatePacketController::WorldstatePacketController(RakNet::RakPeerInterface *peer)
{
}
mwmp::WorldstatePacket *mwmp::WorldstatePacketController::GetPacket(RakNet::MessageID id)
{
return packets[(unsigned char)id].get();
}
void mwmp::WorldstatePacketController::SetStream(RakNet::BitStream *inStream, RakNet::BitStream *outStream)
{
for(const auto &packet : packets)
packet.second->SetStreams(inStream, outStream);
}
bool mwmp::WorldstatePacketController::ContainsPacket(RakNet::MessageID id)
{
for(const auto &packet : packets)
{
if (packet.first == id)
return true;
}
return false;
}

View file

@ -0,0 +1,27 @@
#ifndef OPENMW_WORLDSTATEPACKETCONTROLLER_HPP
#define OPENMW_WORLDSTATEPACKETCONTROLLER_HPP
#include <RakPeerInterface.h>
#include "../Packets/Worldstate/WorldstatePacket.hpp"
#include <unordered_map>
#include <memory>
namespace mwmp
{
class WorldstatePacketController
{
public:
WorldstatePacketController(RakNet::RakPeerInterface *peer);
WorldstatePacket *GetPacket(RakNet::MessageID id);
void SetStream(RakNet::BitStream *inStream, RakNet::BitStream *outStream);
bool ContainsPacket(RakNet::MessageID id);
typedef std::unordered_map<unsigned char, std::unique_ptr<WorldstatePacket> > packets_t;
private:
packets_t packets;
};
}
#endif //OPENMW_WORLDSTATEPACKETCONTROLLER_HPP

View file

@ -116,7 +116,8 @@ enum OrderingChannel
CHANNEL_ACTOR, CHANNEL_ACTOR,
CHANNEL_PLAYER, CHANNEL_PLAYER,
CHANNEL_OBJECT, CHANNEL_OBJECT,
CHANNEL_MASTER CHANNEL_MASTER,
CHANNEL_WORLDSTATE
}; };

View file

@ -0,0 +1,31 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include <PacketPriority.h>
#include <RakPeer.h>
#include "WorldstatePacket.hpp"
using namespace mwmp;
WorldstatePacket::WorldstatePacket(RakNet::RakPeerInterface *peer) : BasePacket(peer)
{
packetID = 0;
priority = HIGH_PRIORITY;
reliability = RELIABLE_ORDERED;
orderChannel = CHANNEL_WORLDSTATE;
this->peer = peer;
}
WorldstatePacket::~WorldstatePacket()
{
}
void WorldstatePacket::setWorldstate(BaseWorldstate *worldstate)
{
this->worldstate = worldstate;
guid = worldstate->guid;
}
BaseWorldstate *WorldstatePacket::getWorldstate()
{
return worldstate;
}

View file

@ -0,0 +1,30 @@
#ifndef OPENMW_WORLDSTATEPACKET_HPP
#define OPENMW_WORLDSTATEPACKET_HPP
#include <string>
#include <RakNetTypes.h>
#include <BitStream.h>
#include <PacketPriority.h>
#include <components/openmw-mp/Base/BaseWorldstate.hpp>
#include <components/openmw-mp/Packets/BasePacket.hpp>
namespace mwmp
{
class WorldstatePacket : public BasePacket
{
public:
WorldstatePacket(RakNet::RakPeerInterface *peer);
~WorldstatePacket();
void setWorldstate(BaseWorldstate *worldstate);
BaseWorldstate *getWorldstate();
protected:
BaseWorldstate *worldstate;
};
}
#endif //OPENMW_WORLDSTATEPACKET_HPP