From a938e9c66ce38ab30234534a496c14252ec577d1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Apr 2024 18:30:19 +0200 Subject: [PATCH] moved the NetworkEntityManager into the backend code. --- src/common/objects/dobject.cpp | 161 ++++++++++++++++++++++++++++++++ src/common/objects/dobject.h | 21 +++++ src/d_main.cpp | 2 + src/d_net.cpp | 162 --------------------------------- src/d_net.h | 19 ---- src/g_game.cpp | 2 +- src/p_saveg.cpp | 2 +- 7 files changed, 186 insertions(+), 183 deletions(-) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index b66029a535..e3d2b9240f 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -622,3 +622,164 @@ void *DObject::ScriptVar(FName field, PType *type) // This is only for internal use so I_Error is fine. I_Error("Variable %s not found in %s\n", field.GetChars(), cls->TypeName.GetChars()); } + + +//========================================================================== +// +// +// +//========================================================================== + +void NetworkEntityManager::InitializeNetworkEntities() +{ + if (!s_netEntities.Size()) + s_netEntities.AppendFill(nullptr, NetIDStart); // Allocate the first 0-8 slots for the world and clients. +} + +// Clients need special handling since they always go in slots 1 - MAXPLAYERS. +void NetworkEntityManager::SetClientNetworkEntity(DObject* mo, const uint32_t id) +{ + // If resurrecting, we need to swap the corpse's position with the new pawn's + // position so it's no longer considered the client's body. + DObject* const oldBody = s_netEntities[id]; + if (oldBody != nullptr) + { + if (oldBody == mo) + return; + + const uint32_t curID = mo->GetNetworkID(); + + s_netEntities[curID] = oldBody; + oldBody->ClearNetworkID(); + oldBody->SetNetworkID(curID); + + mo->ClearNetworkID(); + } + else + { + RemoveNetworkEntity(mo); // Free up its current id. + } + + s_netEntities[id] = mo; + mo->SetNetworkID(ClientNetIDStart + id); +} + +void NetworkEntityManager::AddNetworkEntity(DObject* const ent) +{ + if (ent->IsNetworked()) + return; + + // Slot 0 is reserved for the world. + // Clients go in the first 1 - MAXPLAYERS slots + // Everything else is first come first serve. + uint32_t id = WorldNetID; + if (s_openNetIDs.Size()) + { + s_openNetIDs.Pop(id); + s_netEntities[id] = ent; + } + else + { + id = s_netEntities.Push(ent); + } + + ent->SetNetworkID(id); +} + +void NetworkEntityManager::RemoveNetworkEntity(DObject* const ent) +{ + if (!ent->IsNetworked()) + return; + + const uint32_t id = ent->GetNetworkID(); + if (id == WorldNetID) + return; + + assert(s_netEntities[id] == ent); + if (id >= NetIDStart) + s_openNetIDs.Push(id); + s_netEntities[id] = nullptr; + ent->ClearNetworkID(); +} + +DObject* NetworkEntityManager::GetNetworkEntity(const uint32_t id) +{ + if (id == WorldNetID || id >= s_netEntities.Size()) + return nullptr; + + return s_netEntities[id]; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DObject::SetNetworkID(const uint32_t id) +{ + if (!IsNetworked()) + { + ObjectFlags |= OF_Networked; + _networkID = id; + } +} + +void DObject::ClearNetworkID() +{ + ObjectFlags &= ~OF_Networked; + _networkID = NetworkEntityManager::WorldNetID; +} + +void DObject::EnableNetworking(const bool enable) +{ + if (enable) + NetworkEntityManager::AddNetworkEntity(this); + else + NetworkEntityManager::RemoveNetworkEntity(this); +} + +void DObject::RemoveFromNetwork() +{ + NetworkEntityManager::RemoveNetworkEntity(this); +} + +static unsigned int GetNetworkID(DObject* const self) +{ + return self->GetNetworkID(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkID, GetNetworkID) +{ + PARAM_SELF_PROLOGUE(DObject); + + ACTION_RETURN_INT(self->GetNetworkID()); +} + +static void EnableNetworking(DObject* const self, const bool enable) +{ + self->EnableNetworking(enable); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, EnableNetworking, EnableNetworking) +{ + PARAM_SELF_PROLOGUE(DObject); + PARAM_BOOL(enable); + + self->EnableNetworking(enable); + return 0; +} + +static DObject* GetNetworkEntity(const unsigned int id) +{ + return NetworkEntityManager::GetNetworkEntity(id); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkEntity, GetNetworkEntity) +{ + PARAM_PROLOGUE; + PARAM_UINT(id); + + ACTION_RETURN_OBJECT(NetworkEntityManager::GetNetworkEntity(id)); +} + diff --git a/src/common/objects/dobject.h b/src/common/objects/dobject.h index f193379c11..f7f1e195d0 100644 --- a/src/common/objects/dobject.h +++ b/src/common/objects/dobject.h @@ -487,4 +487,25 @@ inline T *&DObject::PointerVar(FName field) return *(T**)ScriptVar(field, nullptr); // pointer check is more tricky and for the handful of uses in the DECORATE parser not worth the hassle. } + +class NetworkEntityManager +{ +private: + inline static TArray s_netEntities = {}; + inline static TArray s_openNetIDs = {}; + +public: + NetworkEntityManager() = delete; + + static constexpr uint32_t WorldNetID = 0u; + static constexpr uint32_t ClientNetIDStart = 1u; + inline static uint32_t NetIDStart;// = MAXPLAYERS + 1u; + + static void InitializeNetworkEntities(); + static void SetClientNetworkEntity(DObject* mo, const uint32_t id); + static void AddNetworkEntity(DObject* const ent); + static void RemoveNetworkEntity(DObject* const ent); + static DObject* GetNetworkEntity(const uint32_t id); +}; + #endif //__DOBJECT_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index 723fff3887..a4e8f5eb96 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1,4 +1,5 @@ //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // Copyright 1993-1996 id Software // Copyright 1999-2016 Randy Heit // Copyright 2002-2016 Christoph Oelckers @@ -3617,6 +3618,7 @@ static int D_DoomMain_Internal (void) const char *wad; FIWadManager *iwad_man; + NetworkEntityManager::NetIDStart = MAXPLAYERS + 1; GC::AddMarkerFunc(GC_MarkGameRoots); VM_CastSpriteIDToString = Doom_CastSpriteIDToString; diff --git a/src/d_net.cpp b/src/d_net.cpp index 656b07e0b7..d70425f769 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2971,168 +2971,6 @@ int Net_GetLatency(int *ld, int *ad) // //========================================================================== -void NetworkEntityManager::InitializeNetworkEntities() -{ - if (!s_netEntities.Size()) - s_netEntities.AppendFill(nullptr, NetIDStart); // Allocate the first 0-8 slots for the world and clients. -} - -// Clients need special handling since they always go in slots 1 - MAXPLAYERS. -void NetworkEntityManager::SetClientNetworkEntity(player_t* const client) -{ - AActor* const mo = client->mo; - const uint32_t id = ClientNetIDStart + mo->Level->PlayerNum(client); - - // If resurrecting, we need to swap the corpse's position with the new pawn's - // position so it's no longer considered the client's body. - DObject* const oldBody = s_netEntities[id]; - if (oldBody != nullptr) - { - if (oldBody == mo) - return; - - const uint32_t curID = mo->GetNetworkID(); - - s_netEntities[curID] = oldBody; - oldBody->ClearNetworkID(); - oldBody->SetNetworkID(curID); - - mo->ClearNetworkID(); - } - else - { - RemoveNetworkEntity(mo); // Free up its current id. - } - - s_netEntities[id] = mo; - mo->SetNetworkID(id); -} - -void NetworkEntityManager::AddNetworkEntity(DObject* const ent) -{ - if (ent->IsNetworked()) - return; - - // Slot 0 is reserved for the world. - // Clients go in the first 1 - MAXPLAYERS slots - // Everything else is first come first serve. - uint32_t id = WorldNetID; - if (s_openNetIDs.Size()) - { - s_openNetIDs.Pop(id); - s_netEntities[id] = ent; - } - else - { - id = s_netEntities.Push(ent); - } - - ent->SetNetworkID(id); -} - -void NetworkEntityManager::RemoveNetworkEntity(DObject* const ent) -{ - if (!ent->IsNetworked()) - return; - - const uint32_t id = ent->GetNetworkID(); - if (id == WorldNetID) - return; - - assert(s_netEntities[id] == ent); - if (id >= NetIDStart) - s_openNetIDs.Push(id); - s_netEntities[id] = nullptr; - ent->ClearNetworkID(); -} - -DObject* NetworkEntityManager::GetNetworkEntity(const uint32_t id) -{ - if (id == WorldNetID || id >= s_netEntities.Size()) - return nullptr; - - return s_netEntities[id]; -} - -//========================================================================== -// -// -// -//========================================================================== - -void DObject::SetNetworkID(const uint32_t id) -{ - if (!IsNetworked()) - { - ObjectFlags |= OF_Networked; - _networkID = id; - } -} - -void DObject::ClearNetworkID() -{ - ObjectFlags &= ~OF_Networked; - _networkID = NetworkEntityManager::WorldNetID; -} - -void DObject::EnableNetworking(const bool enable) -{ - if (enable) - NetworkEntityManager::AddNetworkEntity(this); - else - NetworkEntityManager::RemoveNetworkEntity(this); -} - -void DObject::RemoveFromNetwork() -{ - NetworkEntityManager::RemoveNetworkEntity(this); -} - -static unsigned int GetNetworkID(DObject* const self) -{ - return self->GetNetworkID(); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkID, GetNetworkID) -{ - PARAM_SELF_PROLOGUE(DObject); - - ACTION_RETURN_INT(self->GetNetworkID()); -} - -static void EnableNetworking(DObject* const self, const bool enable) -{ - self->EnableNetworking(enable); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, EnableNetworking, EnableNetworking) -{ - PARAM_SELF_PROLOGUE(DObject); - PARAM_BOOL(enable); - - self->EnableNetworking(enable); - return 0; -} - -static DObject* GetNetworkEntity(const unsigned int id) -{ - return NetworkEntityManager::GetNetworkEntity(id); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkEntity, GetNetworkEntity) -{ - PARAM_PROLOGUE; - PARAM_UINT(id); - - ACTION_RETURN_OBJECT(NetworkEntityManager::GetNetworkEntity(id)); -} - -//========================================================================== -// -// -// -//========================================================================== - // [RH] List "ping" times CCMD (pings) { diff --git a/src/d_net.h b/src/d_net.h index e4029bd660..e6a6a32b9f 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -98,25 +98,6 @@ extern int ticdup; class player_t; class DObject; -class NetworkEntityManager -{ -private: - inline static TArray s_netEntities = {}; - inline static TArray s_openNetIDs = {}; - -public: - NetworkEntityManager() = delete; - - inline static uint32_t WorldNetID = 0u; - inline static uint32_t ClientNetIDStart = 1u; - inline static uint32_t NetIDStart = MAXPLAYERS + 1u; - - static void InitializeNetworkEntities(); - static void SetClientNetworkEntity(player_t* const client); - static void AddNetworkEntity(DObject* const ent); - static void RemoveNetworkEntity(DObject* const ent); - static DObject* GetNetworkEntity(const uint32_t id); -}; // [RH] // New generic packet structure: diff --git a/src/g_game.cpp b/src/g_game.cpp index ac09977d8f..56a84d4825 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1425,7 +1425,7 @@ void FLevelLocals::PlayerReborn (int player) p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; p->playerstate = PST_LIVE; - NetworkEntityManager::SetClientNetworkEntity(p); + NetworkEntityManager::SetClientNetworkEntity(p->mo, p - players); if (gamestate != GS_TITLELEVEL) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index de4f7c1c1e..e581247597 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -660,7 +660,7 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) for (unsigned int i = 0u; i < MAXPLAYERS; ++i) { if (PlayerInGame(i) && Players[i]->mo != nullptr) - NetworkEntityManager::SetClientNetworkEntity(Players[i]); + NetworkEntityManager::SetClientNetworkEntity(Players[i]->mo, i); } } }