diff --git a/src/events.cpp b/src/events.cpp index 98f5fb5d8d..97b03f7204 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -31,7 +31,6 @@ ** */ #include "events.h" -#include "vm.h" #include "vmintern.h" #include "r_utility.h" #include "g_levellocals.h" @@ -90,6 +89,165 @@ static const FString* ListGetString(VMVa_List& tags) return nullptr; } +IMPLEMENT_CLASS(DNetworkBuffer, false, false); + +void DNetworkBuffer::AddByte(int byte) +{ + ++_size; + _buffer.Push({ NET_BYTE, byte }); +} + +void DNetworkBuffer::AddWord(int word) +{ + _size += 2u; + _buffer.Push({ NET_WORD, word }); +} + +void DNetworkBuffer::AddLong(int msg) +{ + _size += 4u; + _buffer.Push({ NET_LONG, msg }); +} + +void DNetworkBuffer::AddFloat(double msg) +{ + _size += 4u; + _buffer.Push({ NET_FLOAT, msg }); +} + +void DNetworkBuffer::AddString(const FString& msg) +{ + _size += msg.Len() + 1u; + _buffer.Push({ NET_STRING, msg }); +} + +void DNetworkBuffer::OnDestroy() +{ + Super::OnDestroy(); + + _buffer.Clear(); +} + +void DNetworkBuffer::Serialize(FSerializer& arc) +{ + Super::Serialize(arc); + + if (arc.isWriting()) + { + if (!_buffer.Size()) + return; + + if (arc.BeginArray("types")) + { + for (const auto& value : _buffer) + { + int i = value.GetType(); + arc(nullptr, i); + } + + arc.EndArray(); + } + + if (arc.BeginArray("values")) + { + for (const auto& value : _buffer) + { + switch (value.GetType()) + { + case NET_FLOAT: + { + double f = value.GetFloat(); + arc(nullptr, f); + break; + } + + case NET_STRING: + { + FString s = value.GetString(); + arc(nullptr, s); + break; + } + + default: + { + int i = value.GetInt(); + arc(nullptr, i); + break; + } + } + } + + arc.EndArray(); + } + } + else + { + TArray types = {}; + arc("types", types); + + if (!types.Size()) + return; + + if (arc.BeginArray("values")) + { + // Something got corrupted, don't repopulate the buffer. + if (arc.ArraySize() != types.Size()) + { + arc.EndArray(); + return; + } + + for (int type : types) + { + switch (type) + { + case NET_BYTE: + { + int i = 0; + arc(nullptr, i); + AddByte(i); + break; + } + + case NET_WORD: + { + int i = 0; + arc(nullptr, i); + AddWord(i); + break; + } + + case NET_LONG: + { + int i = 0; + arc(nullptr, i); + AddLong(i); + break; + } + + case NET_FLOAT: + { + double f = 0.0; + arc(nullptr, f); + AddFloat(f); + break; + } + + case NET_STRING: + { + FString s = {}; + arc(nullptr, s); + AddString(s); + break; + } + } + } + + arc.EndArray(); + } + } +} + void EventManager::CallOnRegister() { for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) @@ -311,7 +469,7 @@ bool EventManager::SendNetworkCommand(const FName& cmd, VMVa_List& args) return true; } -bool EventManager::SendNetworkBuffer(const FName& cmd, const FNetworkBuffer* buffer) +bool EventManager::SendNetworkBuffer(const FName& cmd, const DNetworkBuffer* buffer) { if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) return false; @@ -324,27 +482,27 @@ bool EventManager::SendNetworkBuffer(const FName& cmd, const FNetworkBuffer* buf { for (unsigned int i = 0u; i < buffer->GetBufferSize(); ++i) { - const auto& pair = buffer->GetPair(i); - switch (pair.GetType()) + const auto& value = buffer->GetValue(i); + switch (value.GetType()) { case NET_BYTE: - Net_WriteByte(pair.GetInt()); + Net_WriteByte(value.GetInt()); break; case NET_WORD: - Net_WriteWord(pair.GetInt()); + Net_WriteWord(value.GetInt()); break; case NET_LONG: - Net_WriteLong(pair.GetInt()); + Net_WriteLong(value.GetInt()); break; case NET_FLOAT: - Net_WriteFloat(pair.GetFloat()); + Net_WriteFloat(value.GetFloat()); break; case NET_STRING: - Net_WriteString(pair.GetString()); + Net_WriteString(value.GetString()); break; } } @@ -913,6 +1071,22 @@ DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadName) ACTION_RETURN_INT(res.GetIndex()); } +DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadMapUnit) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + constexpr double FixedToFloat = 1.0 / (1 << 16); + ACTION_RETURN_FLOAT(self->ReadLong() * FixedToFloat); +} + +DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadAngle) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + const DAngle bam = DAngle::fromBam(self->ReadLong()); + ACTION_RETURN_FLOAT(bam.Degrees()); +} + DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadVector2) { PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); @@ -934,6 +1108,30 @@ DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadVector3) ACTION_RETURN_VEC3(vec); } +DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadVector4) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + DVector4 vec = {}; + vec.X = self->ReadFloat(); + vec.Y = self->ReadFloat(); + vec.Z = self->ReadFloat(); + vec.W = self->ReadFloat(); + ACTION_RETURN_VEC4(vec); +} + +DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadQuat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); + + DQuaternion quat = {}; + quat.X = self->ReadFloat(); + quat.Y = self->ReadFloat(); + quat.Z = self->ReadFloat(); + quat.W = self->ReadFloat(); + ACTION_RETURN_QUAT(quat); +} + DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadIntArray) { PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand); @@ -995,57 +1193,75 @@ DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadStringArray) return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddByte) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddByte) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_INT(value); self->AddByte(value); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddWord) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddWord) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_INT(value); self->AddWord(value); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddLong) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddLong) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_INT(value); self->AddLong(value); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddFloat) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddFloat) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_FLOAT(value); self->AddFloat(value); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddString) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddString) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_STRING(value); self->AddString(value); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddName) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddName) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_NAME(value); self->AddString(value.GetChars()); return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddVector2) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddMapUnit) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(value); + + constexpr int FloatToFixed = 1 << 16; + self->AddLong(static_cast(value * FloatToFixed)); + return 0; +} + +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddAngle) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_ANGLE(value); + self->AddLong(value.BAMs()); + return 0; +} + +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddVector2) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_FLOAT(x); PARAM_FLOAT(y); self->AddFloat(x); @@ -1053,9 +1269,9 @@ DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddVector2) return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddVector3) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddVector3) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); @@ -1065,9 +1281,37 @@ DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddVector3) return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddIntArray) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddVector4) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(w); + self->AddFloat(x); + self->AddFloat(y); + self->AddFloat(z); + self->AddFloat(w); + return 0; +} + +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddQuat) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(w); + self->AddFloat(x); + self->AddFloat(y); + self->AddFloat(z); + self->AddFloat(w); + return 0; +} + +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddIntArray) +{ + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_POINTER(values, TArray); PARAM_INT(type); @@ -1094,9 +1338,9 @@ DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddIntArray) return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddFloatArray) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddFloatArray) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_POINTER(values, TArray); unsigned int size = values->Size(); @@ -1107,9 +1351,9 @@ DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddFloatArray) return 0; } -DEFINE_ACTION_FUNCTION(FNetworkBuffer, AddStringArray) +DEFINE_ACTION_FUNCTION(DNetworkBuffer, AddStringArray) { - PARAM_SELF_STRUCT_PROLOGUE(FNetworkBuffer); + PARAM_SELF_PROLOGUE(DNetworkBuffer); PARAM_POINTER(values, TArray); unsigned int size = values->Size(); @@ -1143,7 +1387,7 @@ DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkBuffer) { PARAM_PROLOGUE; PARAM_NAME(cmd); - PARAM_POINTER(buffer, FNetworkBuffer); + PARAM_OBJECT(buffer, DNetworkBuffer); ACTION_RETURN_BOOL(currentVMLevel->localEventManager->SendNetworkBuffer(cmd, buffer)); } diff --git a/src/events.h b/src/events.h index ca72076840..39edbe95f5 100755 --- a/src/events.h +++ b/src/events.h @@ -1,5 +1,6 @@ #pragma once +#include #include "dobject.h" #include "serializer.h" #include "d_event.h" @@ -132,19 +133,21 @@ public: } }; -struct FNetworkBuffer +class DNetworkBuffer final : public DObject { + DECLARE_CLASS(DNetworkBuffer, DObject) + public: - struct BufferPair + struct BufferValue { private: ENetCmd _type; - VMValue _message; + std::variant _message; public: - BufferPair(const ENetCmd type, const int message) : _type(type), _message(message) {} - BufferPair(const ENetCmd type, const double message) : _type(type), _message(message) {} - BufferPair(const ENetCmd type, const FString* message) : _type(type), _message(message) {} + BufferValue(const ENetCmd type, const int message) : _type(type), _message(message) {} + BufferValue(const ENetCmd type, const double message) : _type(type), _message(message) {} + BufferValue(const ENetCmd type, const FString& message) : _type(type), _message(message) {} inline ENetCmd GetType() const { @@ -153,24 +156,23 @@ public: inline int GetInt() const { - return _message.i; + return std::get(_message); } inline double GetFloat() const { - return _message.f; + return std::get(_message); } inline const char* GetString() const { - return _message.s().GetChars(); + return std::get(_message).GetChars(); } }; private: - unsigned int _size; - TArray _buffer; - TArray _strings; // Local copies of these need to be stored since VMValues store pointers to strings. + unsigned int _size = 0u; + TArray _buffer = {}; public: inline unsigned int GetBytes() const @@ -183,41 +185,18 @@ public: return _buffer.Size(); } - inline const BufferPair& GetPair(unsigned int i) const + inline const BufferValue& GetValue(unsigned int i) const { return _buffer[i]; } - void AddByte(int byte) - { - ++_size; - _buffer.Push({ NET_BYTE, byte }); - } - - void AddWord(int word) - { - _size += 2u; - _buffer.Push({ NET_WORD, word }); - } - - void AddLong(int msg) - { - _size += 4u; - _buffer.Push({ NET_LONG, msg }); - } - - void AddFloat(double msg) - { - _size += 4u; - _buffer.Push({ NET_FLOAT, msg }); - } - - void AddString(const FString& msg) - { - _size += msg.Len() + 1u; - unsigned int index = _strings.Push(msg); - _buffer.Push({ NET_STRING, &_strings[index] }); - } + void AddByte(int byte); + void AddWord(int word); + void AddLong(int msg); + void AddFloat(double msg); + void AddString(const FString& msg); + void OnDestroy() override; + void Serialize(FSerializer& arc) override; }; // ============================================== @@ -504,7 +483,7 @@ struct EventManager // Send a custom network command from ZScript. bool SendNetworkCommand(const FName& cmd, VMVa_List& args); // Send a pre-built command buffer over. - bool SendNetworkBuffer(const FName& cmd, const FNetworkBuffer* buffer); + bool SendNetworkBuffer(const FName& cmd, const DNetworkBuffer* buffer); // check if there is anything that should receive GUI events bool CheckUiProcessors(); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index bc85a7b284..49fc9bc5ef 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -812,10 +812,6 @@ void InitThingdef() netcmdstruct->Size = sizeof(FNetworkCommand); netcmdstruct->Align = alignof(FNetworkCommand); - auto netbuffstruct = NewStruct("NetworkBuffer", nullptr); - netbuffstruct->Size = sizeof(FNetworkBuffer); - netbuffstruct->Align = alignof(FNetworkBuffer); - auto fltd = NewStruct("FLineTraceData", nullptr); fltd->Size = sizeof(FLineTraceData); fltd->Align = alignof(FLineTraceData); diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index 297753908f..6c07dc3782 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -20,14 +20,18 @@ struct NetworkCommand native play version("4.12") // Wrappers native Name ReadName(); + native double ReadMapUnit(); // 16.16 long -> double + native double ReadAngle(); // BAM long -> double native Vector2 ReadVector2(); native Vector3 ReadVector3(); + native Vector4 ReadVector4(); + native Quat ReadQuat(); native void ReadIntArray(out Array values, ENetCmd intSize = NET_LONG); native void ReadFloatArray(out Array values); native void ReadStringArray(out Array values, bool skipEmpty = false); } -struct NetworkBuffer native version("4.12") +class NetworkBuffer native version("4.12") { native void AddByte(int value); native void AddWord(int value); @@ -37,8 +41,12 @@ struct NetworkBuffer native version("4.12") // Wrappers native void AddName(Name value); + native void AddMapUnit(double value); // double -> 16.16 long + native void AddAngle(double value); // double -> BAM long native void AddVector2(Vector2 value); native void AddVector3(Vector3 value); + native void AddVector4(Vector4 value); + native void AddQuat(Quat value); native void AddIntArray(Array values, ENetCmd intSize = NET_LONG); native void AddFloatArray(Array values); native void AddStringArray(Array values);