From 9608c2c2593c4109d10a3f69e347b471dd107422 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 7 Dec 2018 07:01:44 +0100 Subject: [PATCH] - improve NetSyncData to handle any simple data type in Actor --- src/actor.h | 1 - src/network/netsync.cpp | 129 ++++++++++++++++++++++++++++++++++++++++ src/network/netsync.h | 58 +++++++++--------- 3 files changed, 160 insertions(+), 28 deletions(-) diff --git a/src/actor.h b/src/actor.h index b55c88f68..95a0b466a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -643,7 +643,6 @@ public: ~AActor (); NetSyncData syncdata; - NetSyncData synccompare; virtual void OnDestroy() override; virtual void Serialize(FSerializer &arc) override; diff --git a/src/network/netsync.cpp b/src/network/netsync.cpp index 0bed8b8d1..ca81b7a31 100644 --- a/src/network/netsync.cpp +++ b/src/network/netsync.cpp @@ -22,11 +22,140 @@ #include "actor.h" #include "doomstat.h" #include "i_net.h" +#include "cmdlib.h" extern bool netserver; void CountActors(); +class NetSyncWriter +{ +public: + NetSyncWriter(NetCommand &cmd, int netid) : cmd(cmd), NetID(netid) { } + + void Write(void *compval, void *actorval, size_t size) + { + if (memcmp(compval, actorval, size) != 0) + { + if (firstwrite) + { + firstwrite = false; + cmd.addShort(NetID); + } + cmd.addByte(fieldindex); + cmd.addBuffer(actorval, (int)size); + memcpy(compval, actorval, size); + } + fieldindex++; + } + + void WriteEnd() + { + if (!firstwrite) + { + cmd.addByte(255); + } + } + +private: + NetCommand &cmd; + int NetID; + bool firstwrite = true; + int fieldindex = 0; +}; + +NetSyncClass::NetSyncClass() +{ + mSyncVars.Push({ myoffsetof(AActor, Vel.X), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Vel.Y), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Vel.Z), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, SpriteAngle.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, SpriteRotation.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Angles.Yaw.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Angles.Pitch.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Angles.Roll.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Scale.X), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Scale.Y), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Alpha), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, sprite), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, frame), sizeof(uint8_t) }); + mSyncVars.Push({ myoffsetof(AActor, effects), sizeof(uint8_t) }); + mSyncVars.Push({ myoffsetof(AActor, RenderStyle.AsDWORD), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, Translation), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, RenderRequired), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, RenderHidden), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, renderflags.Value), sizeof(uint32_t) }); + mSyncVars.Push({ myoffsetof(AActor, Floorclip), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, VisibleStartAngle.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, VisibleStartPitch.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, VisibleEndAngle.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, VisibleEndPitch.Degrees), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, Speed), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, FloatSpeed), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, CameraHeight), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, CameraFOV), sizeof(double) }); + mSyncVars.Push({ myoffsetof(AActor, StealthAlpha), sizeof(double) }); + + // To do: create NetSyncVariable entries for all the script variables we want sent to the client +} + +void NetSyncClass::InitSyncData(AActor *actor) +{ + auto &syncdata = actor->syncdata; + + size_t scriptvarsize = 0; + for (unsigned int i = 0; i < mSyncVars.Size(); i++) + scriptvarsize += mSyncVars[i].size; + syncdata.CompareData.Resize((unsigned int)scriptvarsize); + + syncdata.Pos = actor->Pos(); + + size_t pos = 0; + for (unsigned int i = 0; i < mSyncVars.Size(); i++) + { + memcpy(syncdata.CompareData.Data() + pos, ((uint8_t*)actor) + mSyncVars[i].offset, scriptvarsize); + pos += mSyncVars[i].size; + } +} + +void NetSyncClass::WriteSyncUpdate(NetCommand &cmd, AActor *actor) +{ + NetSyncWriter writer(cmd, actor->syncdata.NetID); + + DVector3 pos = actor->Pos(); + writer.Write(&actor->syncdata.Pos, &pos, sizeof(DVector3)); + + size_t compareoffset = 0; + for (unsigned int i = 0; i < mSyncVars.Size(); i++) + { + writer.Write(actor->syncdata.CompareData.Data() + compareoffset, ((uint8_t*)actor) + mSyncVars[i].offset, mSyncVars[i].size); + compareoffset += mSyncVars[i].size; + } +} + +void NetSyncClass::ReadSyncUpdate(ByteInputStream &stream, AActor *actor) +{ + while (true) + { + int fieldindex = stream.ReadByte(); + if (fieldindex == 255) + break; + + if (fieldindex == 0) + { + DVector3 pos; + stream.ReadBuffer(&pos, sizeof(DVector3)); + actor->SetOrigin(pos, true); + } + else if (fieldindex <= (int)mSyncVars.Size()) + { + stream.ReadBuffer(((uint8_t*)actor) + mSyncVars[fieldindex - 1].offset, mSyncVars[fieldindex - 1].size); + } + } +} + +///////////////////////////////////////////////////////////////////////////// + template void IDList::clear() { diff --git a/src/network/netsync.h b/src/network/netsync.h index 668bad55e..0f217fa06 100644 --- a/src/network/netsync.h +++ b/src/network/netsync.h @@ -5,35 +5,39 @@ #include "r_data/renderstyle.h" class AActor; +class NetCommand; +class ByteInputStream; -struct NetSyncData +class NetSyncVariable { - DVector3 Pos; - DVector3 Vel; - DAngle SpriteAngle; - DAngle SpriteRotation; - DRotator Angles; - DVector2 Scale; // Scaling values; 1 is normal size - double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. - int sprite; // used to find patch_t and flip value - uint8_t frame; // sprite frame to draw - uint8_t effects; // [RH] see p_effect.h - FRenderStyle RenderStyle; // Style to draw this actor with - uint32_t Translation; - uint32_t RenderRequired; // current renderer must have this feature set - uint32_t RenderHidden; // current renderer must *not* have any of these features - uint32_t renderflags; // Different rendering flags - double Floorclip; // value to use for floor clipping - DAngle VisibleStartAngle; - DAngle VisibleStartPitch; - DAngle VisibleEndAngle; - DAngle VisibleEndPitch; - double Speed; - double FloatSpeed; - double CameraHeight; // Height of camera when used as such - double CameraFOV; - double StealthAlpha; // Minmum alpha for MF_STEALTH. - int NetID; +public: + size_t offset; + size_t size; +}; + +class NetSyncClass +{ +public: + NetSyncClass(); + + void InitSyncData(AActor *actor); + void WriteSyncUpdate(NetCommand &cmd, AActor *actor); + void ReadSyncUpdate(ByteInputStream &stream, AActor *actor); + +private: + TArray mSyncVars; + + NetSyncClass(const NetSyncClass &) = delete; + NetSyncClass &operator=(const NetSyncClass &) = delete; +}; + +class NetSyncData +{ +public: + int NetID; + DVector3 Pos; + TArray CompareData; + NetSyncClass *SyncClass; // Maybe this should be stored in the actor's PClass }; //==========================================================================