From 963fc1ae4c3c5aa68e6396b7b6f09138fd30821c Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Wed, 27 Apr 2016 22:31:33 -0400 Subject: [PATCH] WIP game event parsing --- demboyz/game/gameevents.cpp | 112 ++++++++++++++++++ demboyz/game/gameevents.h | 57 +++++++++ demboyz/game/sourcecontext.cpp | 16 +++ demboyz/game/sourcecontext.h | 18 +++ demboyz/io/demreader.cpp | 1 + demboyz/io/jsonreader.cpp | 1 + demboyz/netmessages/nethandlers.h | 5 +- demboyz/netmessages/svc_createstringtable.cpp | 1 + demboyz/netmessages/svc_gameevent.cpp | 25 +++- demboyz/netmessages/svc_gameevent.h | 2 + demboyz/netmessages/svc_gameeventlist.cpp | 17 ++- demboyz/netmessages/svc_gameeventlist.h | 15 +-- demboyz/netmessages/svc_prefetch.cpp | 1 + demboyz/netmessages/svc_serverinfo.cpp | 1 + demboyz/netmessages/svc_tempentities.cpp | 1 + 15 files changed, 249 insertions(+), 24 deletions(-) create mode 100644 demboyz/game/gameevents.cpp create mode 100644 demboyz/game/gameevents.h create mode 100644 demboyz/game/sourcecontext.cpp create mode 100644 demboyz/game/sourcecontext.h diff --git a/demboyz/game/gameevents.cpp b/demboyz/game/gameevents.cpp new file mode 100644 index 0000000..85e884d --- /dev/null +++ b/demboyz/game/gameevents.cpp @@ -0,0 +1,112 @@ + +#include "gameevents.h" +#include "base/bitfile.h" +#include + +namespace GameEvents +{ + EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc, std::vector& stringMem) + { + stringMem.reserve(stringMem.size() + MAX_EVENT_BYTES); + EventDataMap data; + char tempStr[MAX_EVENT_BYTES]; + for (const EventValue& value : desc.values) + { + EventData& eventData = data[value.name]; + eventData.type = value.type; + switch(value.type) + { + case EventValueType::String: + { + int length = 0; + const bool ok = bitbuf.ReadString(tempStr, sizeof(tempStr), false, &length); + assert(ok); + length += 1; // for null terminator + + eventData.strOffset = stringMem.size(); + stringMem.insert(stringMem.end(), tempStr, tempStr + length + 1); + break; + } + case EventValueType::Float: + { + eventData.flValue = bitbuf.ReadFloat(); + break; + } + case EventValueType::Long: + { + eventData.i32Value = bitbuf.ReadSBitLong(32); + break; + } + case EventValueType::Short: + { + eventData.i16Value = bitbuf.ReadSBitLong(16); + break; + } + case EventValueType::Byte: + { + eventData.u8Value = bitbuf.ReadUBitLong(8); + break; + } + case EventValueType::Bool: + { + eventData.bValue = bitbuf.ReadOneBit() != 0; + break; + } + case EventValueType::Local: + default: + assert(false); + break; + } + } + return data; + } + + void PrintEventData(bf_read& bitbuf, const EventDescriptor& desc) + { + char tempStr[MAX_EVENT_BYTES]; + printf("%s:\n", desc.name); + for (const EventValue& value : desc.values) + { + printf(" %s: ", value.name); + switch(value.type) + { + case EventValueType::String: + { + const bool ok = bitbuf.ReadString(tempStr, sizeof(tempStr), false, nullptr); + assert(ok); + printf("%s\n", tempStr); + break; + } + case EventValueType::Float: + { + printf("%f\n", bitbuf.ReadFloat()); + break; + } + case EventValueType::Long: + { + printf("%i\n", bitbuf.ReadSBitLong(32)); + break; + } + case EventValueType::Short: + { + printf("%i\n", bitbuf.ReadSBitLong(16)); + break; + } + case EventValueType::Byte: + { + printf("%u\n", bitbuf.ReadUBitLong(8)); + break; + } + case EventValueType::Bool: + { + printf("%s\n", (bitbuf.ReadOneBit() != 0) ? "true" : "false"); + break; + } + case EventValueType::Local: + default: + assert(false); + break; + } + } + } +} diff --git a/demboyz/game/gameevents.h b/demboyz/game/gameevents.h new file mode 100644 index 0000000..6603f2e --- /dev/null +++ b/demboyz/game/gameevents.h @@ -0,0 +1,57 @@ + +#pragma once + +#include "netmessages/netcontants.h" +#include +#include +#include +#include + +//#define WIP_GAMEEVENTS + +class bf_read; + +namespace GameEvents +{ + enum EventValueType : uint8_t + { + Local = 0, // not networked + String = 1, // zero terminated ASCII string + Float = 2, // 32 bit float + Long = 3, // 32 bit signed int + Short = 4, // 16 bit signed int + Byte = 5, // 8 bit unsigned int + Bool = 6 // 1 bit unsigned int + }; + + struct EventValue + { + EventValueType type; + char name[MAX_EVENT_NAME_LENGTH]; + }; + + struct EventDescriptor + { + uint16_t id; + char name[MAX_EVENT_NAME_LENGTH]; + std::vector values; + }; + + struct EventData + { + EventValueType type; + union + { + ptrdiff_t strOffset; + float flValue; + int32_t i32Value; + int16_t i16Value; + uint8_t u8Value; + bool bValue; + }; + }; + + using EventDataMap = std::map; + EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc, std::vector& stringMem); + void PrintEventData(bf_read& bitbuf, const EventDescriptor& desc); +} diff --git a/demboyz/game/sourcecontext.cpp b/demboyz/game/sourcecontext.cpp new file mode 100644 index 0000000..fb4737a --- /dev/null +++ b/demboyz/game/sourcecontext.cpp @@ -0,0 +1,16 @@ + +#include "sourcecontext.h" +#include "netmessages/svc_gameeventlist.h" + +SourceGameContext::SourceGameContext(): + protocol(0), + gameEventList(nullptr) +{ +} + +SourceGameContext::~SourceGameContext() +{ + protocol = 0; + delete gameEventList; + gameEventList = nullptr; +} diff --git a/demboyz/game/sourcecontext.h b/demboyz/game/sourcecontext.h new file mode 100644 index 0000000..8140af0 --- /dev/null +++ b/demboyz/game/sourcecontext.h @@ -0,0 +1,18 @@ + +#pragma once + +#include + +namespace NetMsg +{ + struct SVC_GameEventList; +} + +struct SourceGameContext +{ + SourceGameContext(); + ~SourceGameContext(); + + int16_t protocol; + NetMsg::SVC_GameEventList* gameEventList; +}; diff --git a/demboyz/io/demreader.cpp b/demboyz/io/demreader.cpp index 12257c5..45255e5 100644 --- a/demboyz/io/demreader.cpp +++ b/demboyz/io/demreader.cpp @@ -4,6 +4,7 @@ #include "demofile/demofile.h" #include "demofile/demotypes.h" +#include "game/sourcecontext.h" #include "netmessages/nethandlers.h" #include "netmessages/netcontants.h" #include "demmessages/demhandlers.h" diff --git a/demboyz/io/jsonreader.cpp b/demboyz/io/jsonreader.cpp index 0f1d1ba..fa2da22 100644 --- a/demboyz/io/jsonreader.cpp +++ b/demboyz/io/jsonreader.cpp @@ -5,6 +5,7 @@ #include "base/jsonfile.h" #include "io/idemowriter.h" +#include "game/sourcecontext.h" #include "netmessages/nethandlers.h" #include "demmessages/demhandlers.h" diff --git a/demboyz/netmessages/nethandlers.h b/demboyz/netmessages/nethandlers.h index 62580da..6e63080 100644 --- a/demboyz/netmessages/nethandlers.h +++ b/demboyz/netmessages/nethandlers.h @@ -25,10 +25,7 @@ namespace NetHandlers using JsonWrite = base::JsonWriterFile; } -struct SourceGameContext -{ - int16_t protocol; -}; +struct SourceGameContext; #if !defined(MAX_OSPATH) #define MAX_OSPATH 260 // max length of a filesystem pathname diff --git a/demboyz/netmessages/svc_createstringtable.cpp b/demboyz/netmessages/svc_createstringtable.cpp index a577286..fd18c4a 100644 --- a/demboyz/netmessages/svc_createstringtable.cpp +++ b/demboyz/netmessages/svc_createstringtable.cpp @@ -2,6 +2,7 @@ #include "svc_createstringtable.h" #include "base/bitfile.h" #include "base/jsonfile.h" +#include "game/sourcecontext.h" #include "netmath.h" #include "netcontants.h" diff --git a/demboyz/netmessages/svc_gameevent.cpp b/demboyz/netmessages/svc_gameevent.cpp index 5c8d7ae..50fd9f7 100644 --- a/demboyz/netmessages/svc_gameevent.cpp +++ b/demboyz/netmessages/svc_gameevent.cpp @@ -5,13 +5,32 @@ #include "netcontants.h" #include "netmath.h" +#ifdef WIP_GAMEEVENTS +#include "svc_gameeventlist.h" +#endif + namespace NetHandlers { bool SVC_GameEvent_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data) { - data->dataLengthInBits = bitbuf.ReadUBitLong(11); - data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); - bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + const unsigned int numBits = bitbuf.ReadUBitLong(11); + const size_t numBytes = math::BitsToBytes(numBits); + + data->dataLengthInBits = numBits; + data->data.reset(new uint8_t[numBytes]); + bitbuf.ReadBits(data->data.get(), numBits); + +#ifdef WIP_GAMEEVENTS + { + BitRead bitbuf2(data->data.get(), numBytes, numBits); + const size_t id = bitbuf2.ReadUBitLong(9); + //std::vector stringMem; + //GameEvents::ParseEventData(bitbuf2, context.gameEventList->eventDescriptors[id], stringMem); + GameEvents::PrintEventData(bitbuf2, context.gameEventList->eventDescriptors[id]); + printf("%i\n", id); + } +#endif // WIP_GAMEEVENTS + return !bitbuf.IsOverflowed(); } diff --git a/demboyz/netmessages/svc_gameevent.h b/demboyz/netmessages/svc_gameevent.h index 112ca72..7e7c2ef 100644 --- a/demboyz/netmessages/svc_gameevent.h +++ b/demboyz/netmessages/svc_gameevent.h @@ -2,12 +2,14 @@ #pragma once #include "nethandlers.h" +#include "game/gameevents.h" #include namespace NetMsg { struct SVC_GameEvent { + GameEvents::EventDataMap eventData; std::unique_ptr data; uint16_t dataLengthInBits; }; diff --git a/demboyz/netmessages/svc_gameeventlist.cpp b/demboyz/netmessages/svc_gameeventlist.cpp index c97832c..37856bc 100644 --- a/demboyz/netmessages/svc_gameeventlist.cpp +++ b/demboyz/netmessages/svc_gameeventlist.cpp @@ -2,11 +2,12 @@ #include "svc_gameeventlist.h" #include "base/bitfile.h" #include "base/jsonfile.h" +#include "game/sourcecontext.h" #include "netcontants.h" #include "netmath.h" -using EventDescriptor = NetMsg::SVC_GameEventList::EventDescriptor; -using EventValue = NetMsg::SVC_GameEventList::EventValue; +using EventDescriptor = GameEvents::EventDescriptor; +using EventValue = GameEvents::EventValue; uint32_t CalculateNumDataBits(const std::vector& eventDescriptors) { @@ -38,13 +39,20 @@ namespace NetHandlers event.id = bitbuf.ReadUBitLong(MAX_EVENT_BITS); bitbuf.ReadString(event.name, sizeof(event.name)); EventValue value; - while ((value.type = bitbuf.ReadUBitLong(3)) > 0) + while ((value.type = static_cast(bitbuf.ReadUBitLong(3))) > 0) { bitbuf.ReadString(value.name, sizeof(value.name)); event.values.push_back(value); } event.values.shrink_to_fit(); } + +#ifdef WIP_GAMEEVENTS + if (!context.gameEventList) + { + context.gameEventList = new NetMsg::SVC_GameEventList(*data); + } +#endif return !bitbuf.IsOverflowed(); } @@ -52,6 +60,7 @@ namespace NetHandlers { bitbuf.WriteUBitLong(data->eventDescriptors.size(), MAX_EVENT_BITS); bitbuf.WriteUBitLong(data->dataLengthInBits, 20); + assert(data->dataLengthInBits == CalculateNumDataBits(data->eventDescriptors)); for (EventDescriptor& event : data->eventDescriptors) { bitbuf.WriteUBitLong(event.id, MAX_EVENT_BITS); @@ -79,7 +88,7 @@ namespace NetHandlers base::JsonReaderArray values = obj.ReadArray("values"); values.TransformTo(event.values, [](base::JsonReaderObject& obj, EventValue& value) { - value.type = obj.ReadUInt32("type"); + value.type = static_cast(obj.ReadUInt32("type")); obj.ReadString("name", value.name, sizeof(value.name)); }); }); diff --git a/demboyz/netmessages/svc_gameeventlist.h b/demboyz/netmessages/svc_gameeventlist.h index de780e0..33d1cc9 100644 --- a/demboyz/netmessages/svc_gameeventlist.h +++ b/demboyz/netmessages/svc_gameeventlist.h @@ -3,26 +3,15 @@ #include "nethandlers.h" #include "netcontants.h" +#include "game/gameevents.h" #include namespace NetMsg { struct SVC_GameEventList { - struct EventValue - { - uint8_t type; - char name[MAX_EVENT_NAME_LENGTH]; - }; - struct EventDescriptor - { - uint16_t id; - char name[MAX_EVENT_NAME_LENGTH]; - std::vector values; - }; - + std::vector eventDescriptors; uint32_t dataLengthInBits; - std::vector eventDescriptors; }; } diff --git a/demboyz/netmessages/svc_prefetch.cpp b/demboyz/netmessages/svc_prefetch.cpp index ac4d47c..995303f 100644 --- a/demboyz/netmessages/svc_prefetch.cpp +++ b/demboyz/netmessages/svc_prefetch.cpp @@ -2,6 +2,7 @@ #include "svc_prefetch.h" #include "base/bitfile.h" #include "base/jsonfile.h" +#include "game/sourcecontext.h" #include "netcontants.h" namespace NetHandlers diff --git a/demboyz/netmessages/svc_serverinfo.cpp b/demboyz/netmessages/svc_serverinfo.cpp index 34e3340..4fe81b1 100644 --- a/demboyz/netmessages/svc_serverinfo.cpp +++ b/demboyz/netmessages/svc_serverinfo.cpp @@ -2,6 +2,7 @@ #include "svc_serverinfo.h" #include "base/bitfile.h" #include "base/jsonfile.h" +#include "game/sourcecontext.h" namespace NetHandlers { diff --git a/demboyz/netmessages/svc_tempentities.cpp b/demboyz/netmessages/svc_tempentities.cpp index 1b1cb8d..cef52a7 100644 --- a/demboyz/netmessages/svc_tempentities.cpp +++ b/demboyz/netmessages/svc_tempentities.cpp @@ -2,6 +2,7 @@ #include "svc_tempentities.h" #include "base/bitfile.h" #include "base/jsonfile.h" +#include "game/sourcecontext.h" #include "netcontants.h" #include "netmath.h"