diff --git a/src/multiplayer.cpp b/src/multiplayer.cpp index b2d64173..b51ec474 100644 --- a/src/multiplayer.cpp +++ b/src/multiplayer.cpp @@ -4,6 +4,16 @@ #include "engine.h" #include "multiplayer_internal.h" + +void MultiplayerStaticReplicationBase::markChanged() +{ + if (updated) return; + updated = true; + next = owner->staticMemberSendList; + owner->staticMemberSendList = this; +} + + static PVector collisionable_significant; class CollisionableReplicationData { diff --git a/src/multiplayer.h b/src/multiplayer.h index ee50e169..e6b7ff89 100644 --- a/src/multiplayer.h +++ b/src/multiplayer.h @@ -125,6 +125,56 @@ bool multiplayerReplicationFunctions::isChanged(void* data, void* prev_data_p template <> bool multiplayerReplicationFunctions::isChanged(void* data, void* prev_data_ptr); +class MultiplayerStaticReplicationBase : sf::NonCopyable +{ +public: + MultiplayerObject* owner{nullptr}; + uint16_t replication_id{0}; + + bool updated{false}; + MultiplayerStaticReplicationBase* next{nullptr}; + + virtual void send(sf::Packet& packet) = 0; + virtual void receive(sf::Packet& packet) = 0; + +protected: + void markChanged(); +}; +template class MultiplayerStaticReplication : public MultiplayerStaticReplicationBase +{ +public: + MultiplayerStaticReplication(const T& initial_value) + : value(initial_value) + {} + + operator T() const + { + return value; + } + + MultiplayerStaticReplication& operator=(T&& new_value) + { + if (value != new_value) + { + value = new_value; + markChanged(); + } + return *this; + } + + void send(sf::Packet& packet) override + { + packet << value; + } + + void receive(sf::Packet& packet) override + { + packet >> value; + } + + T value; +}; + //In between class that handles all the nasty synchronization of objects between server and client. //I'm assuming that it should be a pure virtual class though. class MultiplayerObject : public virtual PObject @@ -151,6 +201,8 @@ class MultiplayerObject : public virtual PObject void(*cleanupFunction)(void* prev_data_ptr); }; std::vector memberReplicationInfo; + std::vector staticMemberReplicationInfo; + MultiplayerStaticReplicationBase* staticMemberSendList{nullptr}; public: MultiplayerObject(string multiplayerClassIdentifier); virtual ~MultiplayerObject(); @@ -217,6 +269,13 @@ class MultiplayerObject : public virtual PObject info.cleanupFunction = &multiplayerReplicationFunctions::cleanupVector; memberReplicationInfo.push_back(info); } + + template void registerMemberReplication_(F_PARAM MultiplayerStaticReplication* member) + { + member->owner = this; + member->replication_id = staticMemberReplicationInfo.size() | 0x8000; + staticMemberReplicationInfo.push_back(member); + } void registerMemberReplication_(F_PARAM sf::Vector3f* member, float update_delay = 0.0) { @@ -251,6 +310,7 @@ class MultiplayerObject : public virtual PObject private: friend class GameServer; friend class GameClient; + friend class MultiplayerStaticReplicationBase; template static inline diff --git a/src/multiplayer_client.cpp b/src/multiplayer_client.cpp index 7556676b..2b04f705 100644 --- a/src/multiplayer_client.cpp +++ b/src/multiplayer_client.cpp @@ -129,7 +129,9 @@ void GameClient::update(float /*delta*/) int16_t idx; while(packet >> idx) { - if (idx >= 0 && idx < int16_t(obj->memberReplicationInfo.size())) + if (idx & 0x8000 && (idx & 0x7FFF) < uint16_t(obj->staticMemberReplicationInfo.size())) + obj->staticMemberReplicationInfo[idx & 0x7FFF]->receive(packet); + else if (idx >= 0 && idx < int16_t(obj->memberReplicationInfo.size())) (obj->memberReplicationInfo[idx].receiveFunction)(obj->memberReplicationInfo[idx].ptr, packet); else LOG(DEBUG) << "Odd index from server replication: " << idx; @@ -157,7 +159,9 @@ void GameClient::update(float /*delta*/) P obj = objectMap[id]; while(packet >> idx) { - if (idx < int32_t(obj->memberReplicationInfo.size())) + if (idx & 0x8000 && (idx & 0x7FFF) < uint16_t(obj->staticMemberReplicationInfo.size())) + obj->staticMemberReplicationInfo[idx & 0x7FFF]->receive(packet); + else if (idx < int32_t(obj->memberReplicationInfo.size())) (obj->memberReplicationInfo[idx].receiveFunction)(obj->memberReplicationInfo[idx].ptr, packet); } } diff --git a/src/multiplayer_server.cpp b/src/multiplayer_server.cpp index 9e68c8f1..8222cf27 100644 --- a/src/multiplayer_server.cpp +++ b/src/multiplayer_server.cpp @@ -164,6 +164,15 @@ void GameServer::update(float /*gameDelta*/) } } } + while(obj->staticMemberSendList) + { + packet << obj->staticMemberSendList->replication_id; + obj->staticMemberSendList->send(packet); + //TODO: Multiplayer stats + obj->staticMemberSendList->updated = false; + obj->staticMemberSendList = obj->staticMemberSendList->next; + cnt ++; + } if (cnt > 0) { sendAll(packet); @@ -529,6 +538,11 @@ void GameServer::generateCreatePacketFor(P obj, sf::Packet& p packet << int16_t(n); (obj->memberReplicationInfo[n].sendFunction)(obj->memberReplicationInfo[n].ptr, packet); } + for(unsigned int n=0; nstaticMemberReplicationInfo.size(); n++) + { + packet << int16_t(n | 0x8000); + obj->staticMemberReplicationInfo[n]->send(packet); + } } void GameServer::generateDeletePacketFor(int32_t id, sf::Packet& packet)