From 0033d3aeba0cb02e1c0e4d3c09f6d262825890d8 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Mon, 13 Jul 2015 23:25:49 -0400 Subject: [PATCH] Added json reader utilities and implemented json reader functions to dem, net, and svc types --- demboyz/base/jsonfile.cpp | 256 +++++++++++++++++- demboyz/base/jsonfile.h | 93 +++++++ demboyz/demmessages/dem_consolecmd.cpp | 13 +- demboyz/demmessages/dem_datatables.cpp | 13 +- demboyz/demmessages/dem_packet.cpp | 15 +- demboyz/demmessages/dem_stringtables.cpp | 96 +++++-- demboyz/demmessages/dem_usercmd.cpp | 12 +- demboyz/demmessages/demhandlers.cpp | 8 +- demboyz/demmessages/demhandlers.h | 12 +- demboyz/demofile/demojson.cpp | 92 +++++++ demboyz/demofile/demojson.h | 15 + demboyz/io/idemowriter.h | 2 +- demboyz/io/jsonreader.cpp | 85 ++++++ demboyz/io/jsonwriter.cpp | 17 +- demboyz/netmessages/net_disconnect.cpp | 10 +- demboyz/netmessages/net_file.cpp | 12 +- demboyz/netmessages/net_nop.cpp | 2 - demboyz/netmessages/net_setconvar.cpp | 20 +- demboyz/netmessages/net_signonstate.cpp | 11 +- demboyz/netmessages/net_stringcmd.cpp | 10 +- demboyz/netmessages/net_tick.cpp | 12 +- demboyz/netmessages/nethandlers.cpp | 8 +- demboyz/netmessages/nethandlers.h | 14 +- demboyz/netmessages/svc_bspdecal.cpp | 14 +- demboyz/netmessages/svc_classinfo.cpp | 21 +- demboyz/netmessages/svc_createstringtable.cpp | 23 +- demboyz/netmessages/svc_crosshairangle.cpp | 10 +- demboyz/netmessages/svc_entitymessage.cpp | 14 +- demboyz/netmessages/svc_fixangle.cpp | 11 +- demboyz/netmessages/svc_gameevent.cpp | 12 +- demboyz/netmessages/svc_gameeventlist.cpp | 23 +- demboyz/netmessages/svc_getcvarvalue.cpp | 11 +- demboyz/netmessages/svc_menu.cpp | 13 +- demboyz/netmessages/svc_packetentities.cpp | 18 +- demboyz/netmessages/svc_prefetch.cpp | 11 +- demboyz/netmessages/svc_print.cpp | 10 +- demboyz/netmessages/svc_sendtable.cpp | 13 +- demboyz/netmessages/svc_serverinfo.cpp | 35 ++- demboyz/netmessages/svc_setpause.cpp | 10 +- demboyz/netmessages/svc_setview.cpp | 10 +- demboyz/netmessages/svc_sounds.cpp | 14 +- demboyz/netmessages/svc_tempentities.cpp | 13 +- demboyz/netmessages/svc_updatestringtable.cpp | 14 +- demboyz/netmessages/svc_usermessage.cpp | 13 +- demboyz/netmessages/svc_voicedata.cpp | 14 +- demboyz/netmessages/svc_voiceinit.cpp | 11 +- 46 files changed, 1012 insertions(+), 154 deletions(-) diff --git a/demboyz/base/jsonfile.cpp b/demboyz/base/jsonfile.cpp index 6c69417..edcfe5a 100644 --- a/demboyz/base/jsonfile.cpp +++ b/demboyz/base/jsonfile.cpp @@ -1,10 +1,13 @@ #include "jsonfile.h" #include +#include #define CBASE64_IMPLEMENTATION #include "cbase64/cbase64.h" +#define RIGHT_TO_LEFT_BITS + namespace base { JsonWriterFile::JsonWriterFile(FILE* fp, char* buffer, std::size_t length): @@ -186,23 +189,23 @@ namespace base cbase64_init_encodestate(&state); const std::size_t numBytes = ((numBits + 7) >> 3); - const int encodedLength = cbase64_calc_encoded_length(numBytes); - char* const encoded = (char*)malloc(encodedLength); + char* const encoded = (char*)malloc(cbase64_calc_encoded_length(numBytes)); char* encodedCurOut = encoded; + const std::size_t numBytesWithoutBits = (numBits >> 3); const std::size_t numTrailingBits = (numBits & 7); + + encodedCurOut += cbase64_encode_block(data, numBytesWithoutBits, encodedCurOut, &state); if (numTrailingBits > 0) { - const std::size_t numBytesWithoutBits = (numBits >> 3); - encodedCurOut += cbase64_encode_block(data, numBytesWithoutBits, encodedCurOut, &state); - const unsigned char lastByteClean = data[numBytesWithoutBits] & ~(0xFF >> numTrailingBits); +#ifdef LEFT_TO_RIGHT_BITS + const unsigned char lastByteClean = data[numBytesWithoutBits] & (0xFF >> numTrailingBits); +#else // RIGHT_TO_LEFT_BITS + const unsigned char lastByteClean = data[numBytesWithoutBits] & ~(0xFF << numTrailingBits); +#endif encodedCurOut += cbase64_encode_block(&lastByteClean, 1, encodedCurOut, &state); } - else - { - encodedCurOut += cbase64_encode_block(data, numBytes, encodedCurOut, &state); - } encodedCurOut += cbase64_encode_blockend(encodedCurOut, &state); writer.String(encoded, encodedCurOut - encoded); @@ -214,4 +217,239 @@ namespace base { JsonWriterFile::WriteBits(name, data, numBytes * 8); } + + JsonReaderIterator::JsonReaderIterator(JsonValue* value): + m_value(value) + { + } + + JsonReaderObject JsonReaderIterator::operator*() const + { + return JsonReaderObject(*m_value, false); + } + + JsonReaderIterator& JsonReaderIterator::operator++() + { + ++m_value; + return *this; + } + + bool JsonReaderIterator::operator==(const JsonReaderIterator& other) const + { + return m_value == other.m_value; + } + + bool JsonReaderIterator::operator!=(const JsonReaderIterator& other) const + { + return m_value != other.m_value; + } + + JsonReaderArray::JsonReaderArray(JsonValue& value, bool parseError): + m_value(value), + m_hasReadError(parseError) + { + } + + bool JsonReaderArray::HasReadError() const + { + return m_hasReadError; + } + + std::size_t JsonReaderArray::size() const + { + return m_value.Size(); + } + + JsonReaderIterator JsonReaderArray::begin() + { + return JsonReaderIterator(m_value.Begin()); + } + + JsonReaderIterator JsonReaderArray::end() + { + return JsonReaderIterator(m_value.End()); + } + + JsonReaderObject::JsonReaderObject(JsonValue& value, bool parseError): + m_value(value), + m_hasReadError(parseError) + { + } + + bool JsonReaderObject::HasReadError() const + { + return m_hasReadError; + } + + JsonReaderObject JsonReaderObject::ReadObject(const char* name) const + { + JsonValue& value = m_value[name]; + return JsonReaderObject(value, !value.IsObject()); + } + + JsonReaderArray JsonReaderObject::ReadArray(const char* name) const + { + JsonValue& value = m_value[name]; + return JsonReaderArray(value, !value.IsArray()); + } + + bool JsonReaderObject::ReadBool(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsBool()) + { + m_hasReadError = true; + return false; + } + return val.GetBool(); + } + + char JsonReaderObject::ReadChar(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsString() || val.GetStringLength() != 1) + { + m_hasReadError = true; + return false; + } + return *val.GetString(); + } + + std::int32_t JsonReaderObject::ReadInt32(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsInt()) + { + m_hasReadError = true; + return 0; + } + return val.GetInt(); + } + + std::int64_t JsonReaderObject::ReadInt64(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsInt64()) + { + m_hasReadError = true; + return 0; + } + return val.GetInt64(); + } + + std::uint32_t JsonReaderObject::ReadUInt32(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsUint()) + { + m_hasReadError = true; + return 0; + } + return val.GetUint(); + } + + std::uint64_t JsonReaderObject::ReadUint64(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsUint64()) + { + m_hasReadError = true; + return 0; + } + return val.GetUint64(); + } + + std::uint32_t JsonReaderObject::ReadString(const char* name, char* dest, std::uint32_t maxLength) + { + const auto& val = m_value[name]; + if (!val.IsString()) + { + m_hasReadError = true; + return 0; + } + strncpy(dest, val.GetString(), maxLength - 1); + dest[maxLength - 1] = '\0'; + return std::min(maxLength - 1, val.GetStringLength()); + } + + float JsonReaderObject::ReadFloat(const char* name) + { + const auto& val = m_value[name]; + if (!val.IsDouble()) + { + m_hasReadError = true; + return 0.0f; + } + return val.GetDouble(); + } + + std::size_t JsonReaderObject::ReadBits(const char* name, unsigned char* dest, std::size_t numBits) + { + const auto& val = m_value[name]; + if (!val.IsString()) + { + m_hasReadError = true; + return 0; + } + + const char* const encodedBits = val.GetString(); + const std::size_t numEncodedBytes = val.GetStringLength(); + const std::size_t numDecodedBytes = cbase64_calc_decoded_length(encodedBits, numEncodedBytes); + if (!dest || (numDecodedBytes == 0)) + { + return numDecodedBytes * 8; + } + + const std::size_t numBytes = ((numBits + 7) >> 3); + if ((numDecodedBytes == 0) || (numBytes < numDecodedBytes)) + { + return 0; + } + + unsigned char* lastByte = &dest[numDecodedBytes - 1]; + unsigned char restoreBits = *lastByte; + + cbase64_decodestate state; + cbase64_init_decodestate(&state); + const size_t numWritten = cbase64_decode_block(encodedBits, numEncodedBytes, dest, &state); + assert(numWritten == numDecodedBytes); + + const std::size_t numTrailingBits = (numBits & 7); + if (numTrailingBits > 0) + { + // clean up end of decoded, clean up start of restoreBits + // then combine +#ifdef LEFT_TO_RIGHT_BITS + *lastByte = (*lastByte & ~(0xFF >> numTrailingBits)) | + (restoreBits & (0xFF >> numTrailingBits)); +#else // RIGHT_TO_LEFT_BITS + *lastByte = (*lastByte & ~(0xFF << numTrailingBits)) | + (restoreBits & (0xFF << numTrailingBits)); +#endif + } + return numBits; + } + + std::size_t JsonReaderObject::ReadBytes(const char* name, unsigned char* dest, std::size_t numBytes) + { + const std::size_t numBitsRead = ReadBits(name, dest, numBytes * 8); + assert((numBitsRead & 7) == 0); + return (numBitsRead / 8); + } + + JsonReaderFile::JsonReaderFile(FILE* fp, char* buffer, std::size_t length): + m_fileStream(fp, buffer, length), + m_document() + { + } + + JsonReaderObject JsonReaderFile::ParseObject() + { + const int flags = rapidjson::kParseValidateEncodingFlag | + rapidjson::kParseStopWhenDoneFlag; + + auto& document = m_document; + document.ParseStream(m_fileStream); + return JsonReaderObject(document, document.HasParseError()); + } } diff --git a/demboyz/base/jsonfile.h b/demboyz/base/jsonfile.h index a086585..094784a 100644 --- a/demboyz/base/jsonfile.h +++ b/demboyz/base/jsonfile.h @@ -2,7 +2,9 @@ #pragma once #include +#include #include +#include #include #include #include @@ -49,4 +51,95 @@ namespace base rapidjson::Writer> m_writer; FILE* m_fp; }; + + class JsonReaderObject; + class JsonReaderIterator + { + public: + using JsonValue = rapidjson::GenericValue>; + + public: + explicit JsonReaderIterator(JsonValue* value); + + JsonReaderObject operator*() const; + JsonReaderIterator& operator++(); + bool operator==(const JsonReaderIterator& other) const; + bool operator!=(const JsonReaderIterator& other) const; + + private: + JsonValue* m_value; + }; + + class JsonReaderArray + { + public: + using JsonValue = rapidjson::GenericValue>; + + public: + explicit JsonReaderArray(JsonValue& value, bool parseError); + + bool HasReadError() const; + + std::size_t size() const; + JsonReaderIterator begin(); + JsonReaderIterator end(); + + template + void TransformTo(Container& c, Fn fn) + { + c.resize(m_value.Size()); + std::size_t index = 0; + for (base::JsonReaderObject& obj : *this) + { + fn(obj, c[index++]); + } + } + + private: + JsonValue& m_value; + bool m_hasReadError; + }; + + class JsonReaderObject + { + public: + using JsonValue = rapidjson::GenericValue>; + + public: + explicit JsonReaderObject(JsonValue& value, bool parseError); + + bool HasReadError() const; + + JsonReaderObject ReadObject(const char* name) const; + JsonReaderArray ReadArray(const char* name) const; + + bool ReadBool(const char* name); + char ReadChar(const char* name); + std::int32_t ReadInt32(const char* name); + std::int64_t ReadInt64(const char* name); + std::uint32_t ReadUInt32(const char* name); + std::uint64_t ReadUint64(const char* name); + std::size_t ReadString(const char* name, char* dest, std::size_t maxLength); + std::string ReadString(const char* name, std::size_t maxLength); + float ReadFloat(const char* name); + + std::size_t ReadBits(const char* name, unsigned char* dest, std::size_t numBits); + std::size_t ReadBytes(const char* name, unsigned char* dest, std::size_t numBytes); + + private: + JsonValue& m_value; + bool m_hasReadError; + }; + + class JsonReaderFile + { + public: + JsonReaderFile(FILE* fp, char* buffer, std::size_t length); + + JsonReaderObject ParseObject(); + + private: + rapidjson::FileReadStream m_fileStream; + rapidjson::GenericDocument> m_document; + }; } diff --git a/demboyz/demmessages/dem_consolecmd.cpp b/demboyz/demmessages/dem_consolecmd.cpp index fb8ac0f..96fdee8 100644 --- a/demboyz/demmessages/dem_consolecmd.cpp +++ b/demboyz/demmessages/dem_consolecmd.cpp @@ -22,12 +22,21 @@ namespace DemHandlers bool Dem_ConsoleCmd_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_ConsoleCmd* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + char command[DemMsg::Dem_ConsoleCmd::COMMAND_MAX_LENGTH]; + reader.ReadString("command", command, sizeof(command)); + data->command.assign(command); + return !reader.HasReadError(); } bool Dem_ConsoleCmd_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_ConsoleCmd* data) { + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteString("command", data->command); - return true; + jsonbuf.EndObject(); + return jsonbuf.IsComplete(); } } diff --git a/demboyz/demmessages/dem_datatables.cpp b/demboyz/demmessages/dem_datatables.cpp index 2d46aa7..de57b13 100644 --- a/demboyz/demmessages/dem_datatables.cpp +++ b/demboyz/demmessages/dem_datatables.cpp @@ -19,13 +19,20 @@ namespace DemHandlers bool Dem_DataTables_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_DataTables* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + data->data.reset(reader.ReadBytes("data", nullptr, 0)); + reader.ReadBytes("data", data->data.begin(), DemMsg::Dem_DataTables::DATA_MAX_LENGTH); + return !reader.HasReadError(); } bool Dem_DataTables_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_DataTables* data) { - //jsonbuf.WriteInt32("dataLengthInBytes", data->data.length()); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBytes("data", data->data.begin(), data->data.length()); - return true; + jsonbuf.EndObject(); + return jsonbuf.IsComplete(); } } diff --git a/demboyz/demmessages/dem_packet.cpp b/demboyz/demmessages/dem_packet.cpp index df6d684..e6b74d7 100644 --- a/demboyz/demmessages/dem_packet.cpp +++ b/demboyz/demmessages/dem_packet.cpp @@ -2,6 +2,7 @@ #include "dem_packet.h" #include "demofile/demofile.h" #include "demofile/demojson.h" +#include "netmessages/nethandlers.h" namespace DemHandlers { @@ -9,7 +10,6 @@ namespace DemHandlers { demofile.ReadCmdInfo(data->cmdInfo); demofile.ReadSequenceInfo(data->sequenceNum1, data->sequenceNum2); - //data->dataLengthInBytes = demofile.ReadRawData(data->data, sizeof(data->data)); return demofile.IsOk(); } @@ -17,19 +17,26 @@ namespace DemHandlers { demofile.WriteCmdInfo(data->cmdInfo); demofile.WriteSequenceInfo(data->sequenceNum1, data->sequenceNum2); - //demofile.WriteRawData(data->data, data->dataLengthInBytes); return demofile.IsOk(); } bool Dem_Packet_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_Packet* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + bool readError = DemoJsonReader::ReadCmdInfo(reader, data->cmdInfo); + readError |= DemoJsonReader::ReadSequenceInfo(reader, data->sequenceNum1, data->sequenceNum2); + return !readError && !reader.HasReadError(); } bool Dem_Packet_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_Packet* data) { + jsonbuf.Reset(); + jsonbuf.StartObject(); DemoJsonWriter::WriteCmdInfo(jsonbuf, data->cmdInfo); DemoJsonWriter::WriteSequenceInfo(jsonbuf, data->sequenceNum1, data->sequenceNum2); - return true; + jsonbuf.EndObject(); + return jsonbuf.IsComplete(); } } diff --git a/demboyz/demmessages/dem_stringtables.cpp b/demboyz/demmessages/dem_stringtables.cpp index df9118c..602fccb 100644 --- a/demboyz/demmessages/dem_stringtables.cpp +++ b/demboyz/demmessages/dem_stringtables.cpp @@ -40,12 +40,22 @@ static void StringTableEntry_BitWrite(bf_write& bitbuf, DemMsg::Dem_StringTables } } -static void StringTableEntry_JsonWrite(JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTableEntry* data) +static void StringTableEntry_JsonRead(base::JsonReaderObject& jsonbuf, DemMsg::Dem_StringTables::StringTableEntry* data) { - jsonbuf.StartObject(data->entryName.c_str()); - //jsonbuf.WriteUInt32("dataLengthInBytes", data->data.length()); + using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry; + { + char entryName[StringTableEntry::ENTRYNAME_MAX_LENGTH]; + jsonbuf.ReadString("name", entryName, sizeof(entryName)); + data->entryName.assign(entryName); + } + data->data.reset(jsonbuf.ReadBytes("data", nullptr, 0)); + jsonbuf.ReadBytes("data", data->data.begin(), data->data.length()); +} + +static void StringTableEntry_JsonWrite(DemHandlers::JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTableEntry* data) +{ + jsonbuf.WriteString("name", data->entryName); jsonbuf.WriteBytes("data", data->data.begin(), data->data.length()); - jsonbuf.EndObject(); } static void StringTable_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::StringTable* data) @@ -100,10 +110,37 @@ static void StringTable_BitWrite(bf_write& bitbuf, DemMsg::Dem_StringTables::Str } } -static void StringTable_JsonWrite(JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTable* data) +static void StringTable_JsonRead(base::JsonReaderObject& jsonbuf, DemMsg::Dem_StringTables::StringTable* data) +{ + using StringTable = DemMsg::Dem_StringTables::StringTable; + using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry; + { + char tableName[StringTable::TABLENAME_MAX_LENGTH]; + jsonbuf.ReadString("tableName", tableName, sizeof(tableName)); + data->tableName.assign(tableName); + } + + { + base::JsonReaderArray entries = jsonbuf.ReadArray("entries"); + entries.TransformTo(data->entries, [](base::JsonReaderObject& obj, StringTableEntry& entry) + { + StringTableEntry_JsonRead(obj, &entry); + }); + } + { + base::JsonReaderArray entriesClientSide = jsonbuf.ReadArray("entriesClientSide"); + entriesClientSide.TransformTo(data->entriesClientSide, [](base::JsonReaderObject& obj, StringTableEntry& entry) + { + StringTableEntry_JsonRead(obj, &entry); + }); + } +} + +static void StringTable_JsonWrite(DemHandlers::JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTable* data) { using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry; - jsonbuf.StartArray(data->tableName.c_str()); + jsonbuf.WriteString("tableName", data->tableName); + jsonbuf.StartArray("entries"); for (const StringTableEntry& entry : data->entries) { jsonbuf.StartObject(); @@ -111,6 +148,15 @@ static void StringTable_JsonWrite(JsonWrite& jsonbuf, const DemMsg::Dem_StringTa jsonbuf.EndObject(); } jsonbuf.EndArray(); + + jsonbuf.StartArray("entriesClientSide"); + for (const StringTableEntry& entry : data->entriesClientSide) + { + jsonbuf.StartObject(); + StringTableEntry_JsonWrite(jsonbuf, &entry); + jsonbuf.EndObject(); + } + jsonbuf.EndArray(); } namespace DemHandlers @@ -161,29 +207,43 @@ namespace DemHandlers bool Dem_StringTables_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_StringTables* data) { + using StringTable = DemMsg::Dem_StringTables::StringTable; + { + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + data->stringtables.reset(reader.ReadInt32("numStringTables")); + data->numTrailingBits = reader.ReadUInt32("numTrailingBits"); + data->trailingBitsValue = reader.ReadUInt32("trailingBitsValue"); + } + { + for (StringTable& table : data->stringtables) + { + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + StringTable_JsonRead(reader, &table); + } + } return true; } bool Dem_StringTables_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_StringTables* data) { using StringTable = DemMsg::Dem_StringTables::StringTable; - jsonbuf.StartArray("tables"); + jsonbuf.Reset(); + jsonbuf.StartObject(); + jsonbuf.WriteInt32("numStringTables", data->stringtables.length()); + jsonbuf.WriteUInt32("numTrailingBits", data->numTrailingBits); + jsonbuf.WriteUInt32("trailingBitsValue", data->trailingBitsValue, (data->numTrailingBits > 0)); + jsonbuf.EndObject(); + for (const StringTable& table : data->stringtables) { + jsonbuf.Reset(); jsonbuf.StartObject(); StringTable_JsonWrite(jsonbuf, &table); jsonbuf.EndObject(); } - jsonbuf.EndArray(); - jsonbuf.WriteUInt32("numTrailingBits", data->numTrailingBits); - if (data->numTrailingBits > 0) - { - jsonbuf.WriteUInt32("trailingBitsValue", data->trailingBitsValue); - } - else - { - jsonbuf.WriteNull("trailingBitsValue"); - } - return true; + return jsonbuf.IsComplete(); } } diff --git a/demboyz/demmessages/dem_usercmd.cpp b/demboyz/demmessages/dem_usercmd.cpp index 1bff307..28083e1 100644 --- a/demboyz/demmessages/dem_usercmd.cpp +++ b/demboyz/demmessages/dem_usercmd.cpp @@ -19,13 +19,21 @@ namespace DemHandlers bool Dem_UserCmd_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_UserCmd* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + DemoJsonReader::ReadUserCmd(reader, data->commandNum, + data->commandData, DemMsg::Dem_UserCmd::COMMANDDATA_MAX_LENGTH); + return !reader.HasReadError(); } bool Dem_UserCmd_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_UserCmd* data) { + jsonbuf.Reset(); + jsonbuf.StartObject(); DemoJsonWriter::WriteUserCmd(jsonbuf, data->commandNum, data->commandData.begin(), data->commandData.length()); - return true; + jsonbuf.EndObject(); + return jsonbuf.IsComplete(); } } diff --git a/demboyz/demmessages/demhandlers.cpp b/demboyz/demmessages/demhandlers.cpp index 034edd9..8781a24 100644 --- a/demboyz/demmessages/demhandlers.cpp +++ b/demboyz/demmessages/demhandlers.cpp @@ -41,10 +41,10 @@ void DemHandlers::DestroyDemMsgStructs(void* demDataStructs[9]) &DemHandlers::Dem_StringTables_##funcname \ } -typedef bool (*DemMsgFileReadFn)(FileRead& demofile, void* data); -typedef bool (*DemMsgFileWriteFn)(FileWrite& demofile, void* data); -typedef bool (*DemMsgJsonReadFn)(JsonRead& jsonbuf, void* data); -typedef bool (*DemMsgJsonWriteFn)(JsonWrite& jsonbuf, void* data); +typedef bool (*DemMsgFileReadFn)(DemHandlers::FileRead& demofile, void* data); +typedef bool (*DemMsgFileWriteFn)(DemHandlers::FileWrite& demofile, void* data); +typedef bool (*DemMsgJsonReadFn)(DemHandlers::JsonRead& jsonbuf, void* data); +typedef bool (*DemMsgJsonWriteFn)(DemHandlers::JsonWrite& jsonbuf, void* data); bool DemHandlers::DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data) { diff --git a/demboyz/demmessages/demhandlers.h b/demboyz/demmessages/demhandlers.h index df6487d..c0e5c2a 100644 --- a/demboyz/demmessages/demhandlers.h +++ b/demboyz/demmessages/demhandlers.h @@ -5,6 +5,7 @@ namespace base { + class JsonReaderFile; class JsonWriterFile; } @@ -13,10 +14,13 @@ class DemoFileWriter; class DemoFileReader2; class DemoFileWriter2; -using FileRead = DemoFileReader; -using FileWrite = DemoFileWriter; -class JsonRead; -using JsonWrite = base::JsonWriterFile; +namespace DemHandlers +{ + using FileRead = DemoFileReader; + using FileWrite = DemoFileWriter; + using JsonRead = base::JsonReaderFile; + using JsonWrite = base::JsonWriterFile; +} #define DECLARE_DEM_HANDLERS(msgname) \ namespace DemHandlers \ diff --git a/demboyz/demofile/demojson.cpp b/demboyz/demofile/demojson.cpp index 69973f7..731030b 100644 --- a/demboyz/demofile/demojson.cpp +++ b/demboyz/demofile/demojson.cpp @@ -1,6 +1,92 @@ #include "demojson.h" #include "demofile/demotypes.h" +#include + +bool DemoJsonReader::ReadDemoHeader(base::JsonReaderObject& reader, demoheader_t& header) +{ + base::JsonReaderObject object = reader.ReadObject("demoheader"); + object.ReadString("demofilestamp", header.demofilestamp, sizeof(header.demofilestamp)); + header.demoprotocol = object.ReadInt32("demoprotocol"); + header.networkprotocol = object.ReadInt32("networkprotocol"); + object.ReadString("servername", header.servername, sizeof(header.servername)); + object.ReadString("clientname", header.clientname, sizeof(header.clientname)); + object.ReadString("mapname", header.mapname, sizeof(header.mapname)); + object.ReadString("gamedirectory", header.gamedirectory, sizeof(header.gamedirectory)); + header.playback_time = object.ReadFloat("playback_time"); + header.playback_ticks = object.ReadInt32("playback_ticks"); + header.playback_frames = object.ReadInt32("playback_frames"); + header.signonlength = object.ReadInt32("signonlength"); + return !reader.HasReadError() && !object.HasReadError(); +} + +bool DemoJsonReader::ReadSequenceInfo(base::JsonReaderObject& reader, + int32_t& seqNum1, int32_t& seqNum2) +{ + seqNum1 = reader.ReadInt32("sequenceNum1"); + seqNum2 = reader.ReadInt32("sequenceNum2"); + return !reader.HasReadError(); +} + +bool DemoJsonReader::ReadCmdInfo(base::JsonReaderObject& reader, democmdinfo_t& info) +{ + democmdinfo_t::Split_t& split = info.u[0]; + base::JsonReaderObject object = reader.ReadObject("democmdinfo"); + split.flags = object.ReadInt32("flags"); + bool readError = ReadVector(object, "viewOrigin", split.viewOrigin); + readError |= ReadAngle(object, "viewAngles", split.viewAngles); + readError |= ReadAngle(object, "localViewAngles", split.localViewAngles); + readError |= ReadVector(object, "viewOrigin2", split.viewOrigin2); + readError |= ReadAngle(object, "viewAngles2", split.viewAngles2); + readError |= ReadAngle(object, "localViewAngles2", split.localViewAngles2); + return !readError && !reader.HasReadError() && !object.HasReadError(); +} + +bool DemoJsonReader::ReadCmdHeader(base::JsonReaderObject& reader, unsigned char& cmd, int32_t& tick) +{ + cmd = reader.ReadUInt32("cmd"); + tick = reader.ReadInt32("tick"); + return !reader.HasReadError(); +} + +bool DemoJsonReader::ReadUserCmd(base::JsonReaderObject& reader, int32_t& cmdNum, + uint8_t* buffer, int32_t length, int32_t& bytesRead) +{ + base::JsonReaderObject object = reader.ReadObject("usercmd"); + cmdNum = object.ReadInt32("cmd"); + bytesRead = object.ReadBytes("data", buffer, length); + return !object.HasReadError(); +} + +bool DemoJsonReader::ReadUserCmd(base::JsonReaderObject& reader, int32_t cmdNum, + Array& dest, int32_t maxLength) +{ + base::JsonReaderObject object = reader.ReadObject("usercmd"); + cmdNum = object.ReadInt32("cmd"); + + const int32_t numBytes = object.ReadBytes("data", nullptr, 0); + dest.reset(std::min(maxLength, numBytes)); + object.ReadBytes("data", dest.begin(), dest.length()); + return !object.HasReadError(); +} + +bool DemoJsonReader::ReadVector(base::JsonReaderObject& reader, const char* name, Vector& vec) +{ + base::JsonReaderObject object = reader.ReadObject(name); + vec.x = object.ReadFloat("x"); + vec.y = object.ReadFloat("y"); + vec.z = object.ReadFloat("z"); + return !reader.HasReadError() && !object.HasReadError(); +} + +bool DemoJsonReader::ReadAngle(base::JsonReaderObject& reader, const char* name, QAngle& angles) +{ + base::JsonReaderObject object = reader.ReadObject(name); + angles.x = object.ReadFloat("pitch"); + angles.y = object.ReadFloat("yaw"); + angles.z = object.ReadFloat("roll"); + return !reader.HasReadError() && !object.HasReadError(); +} void DemoJsonWriter::WriteDemoHeader(base::JsonWriterFile& writer, const demoheader_t& header) { @@ -41,6 +127,12 @@ void DemoJsonWriter::WriteCmdInfo(base::JsonWriterFile& writer, writer.EndObject(); } +void DemoJsonWriter::WriteCmdHeader(base::JsonWriterFile& writer, unsigned char cmd, int32_t tick) +{ + writer.WriteUInt32("cmd", cmd); + writer.WriteInt32("tick", tick); +} + void DemoJsonWriter::WriteUserCmd(base::JsonWriterFile& writer, int32_t cmdNum, const uint8_t* buffer, int32_t length) { diff --git a/demboyz/demofile/demojson.h b/demboyz/demofile/demojson.h index 07f8e92..fe86218 100644 --- a/demboyz/demofile/demojson.h +++ b/demboyz/demofile/demojson.h @@ -1,6 +1,7 @@ #pragma once +#include "base/array.h" #include "base/jsonfile.h" #include #include @@ -10,11 +11,25 @@ struct democmdinfo_t; class Vector; class QAngle; +namespace DemoJsonReader +{ + bool ReadDemoHeader(base::JsonReaderObject& reader, demoheader_t& header); + bool ReadSequenceInfo(base::JsonReaderObject& reader, int32_t& seqNum1, int32_t& seqNum2); + bool ReadCmdInfo(base::JsonReaderObject& reader, democmdinfo_t& info); + bool ReadCmdHeader(base::JsonReaderObject& reader, unsigned char& cmd, int32_t& tick); + bool ReadUserCmd(base::JsonReaderObject& reader, int32_t& cmdNum, + uint8_t* buffer, int32_t length, int32_t& bytesRead); + bool ReadUserCmd(base::JsonReaderObject& reader, int32_t cmdNum, Array& dest, int32_t maxLength); + bool ReadVector(base::JsonReaderObject& reader, const char* name, Vector& vec); + bool ReadAngle(base::JsonReaderObject& reader, const char* name, QAngle& angle); +} + namespace DemoJsonWriter { void WriteDemoHeader(base::JsonWriterFile& writer, const demoheader_t& header); void WriteSequenceInfo(base::JsonWriterFile& writer, int32_t seqNum1, int32_t seqNum2); void WriteCmdInfo(base::JsonWriterFile& writer, const democmdinfo_t& info); + void WriteCmdHeader(base::JsonWriterFile& writer, unsigned char cmd, int32_t tick); void WriteUserCmd(base::JsonWriterFile& writer, int32_t cmdNum, const uint8_t* buffer, int32_t length); void WriteVector(base::JsonWriterFile& writer, const char* name, const Vector& vec); void WriteAngle(base::JsonWriterFile& writer, const char* name, const QAngle& angle); diff --git a/demboyz/io/idemowriter.h b/demboyz/io/idemowriter.h index 28a03ff..ed68254 100644 --- a/demboyz/io/idemowriter.h +++ b/demboyz/io/idemowriter.h @@ -19,7 +19,7 @@ struct CommandPacket struct NetPacket { - uint32_t type; + int32_t type; void* data; }; diff --git a/demboyz/io/jsonreader.cpp b/demboyz/io/jsonreader.cpp index 3a329f1..41c2ab9 100644 --- a/demboyz/io/jsonreader.cpp +++ b/demboyz/io/jsonreader.cpp @@ -1,6 +1,91 @@ #include "demoreader.h" +#include "demofile/demotypes.h" +#include "demofile/demojson.h" +#include "base/jsonfile.h" +#include "io/idemowriter.h" + +#include "netmessages/nethandlers.h" +#include "demmessages/demhandlers.h" + +int32_t ReadNetpacket(base::JsonReaderFile& jsonReader, PacketTrailingBits& trailingBits) +{ + base::JsonReaderObject reader = jsonReader.ParseObject(); + assert(!reader.HasReadError()); + const int32_t type = reader.ReadInt32("netpacket"); + if (type < 0) + { + base::JsonReaderObject reader = jsonReader.ParseObject(); + assert(!reader.HasReadError()); + trailingBits.numTrailingBits = reader.ReadInt32("numTrailingBits"); + trailingBits.value = reader.ReadInt32("trailingBitsValue"); + } + return type; +} + +PacketTrailingBits ParsePacket(base::JsonReaderFile& jsonReader, + SourceGameContext& context, IDemoWriter* writer, + void* netDataStructs[32]) +{ + PacketTrailingBits trailingBits = PacketTrailingBits(); + NetPacket netPacket = NetPacket(); + while ((netPacket.type = ReadNetpacket(jsonReader, trailingBits)) >= 0) + { + netPacket.data = netDataStructs[netPacket.type]; + NetHandlers::NetMsg_JsonRead(netPacket.type, jsonReader, context, netPacket.data); + writer->WriteNetPacket(netPacket, context); + } + return trailingBits; +} void DemoReader::ProcessJson(std::FILE* inputFp, IDemoWriter* writer) { + void* netDataStructs[32]; + void* demDataStructs[9]; + NetHandlers::CreateNetMsgStructs(netDataStructs); + DemHandlers::CreateDemMsgStructs(demDataStructs); + + SourceGameContext context = SourceGameContext(); + char buffer[4096]; + base::JsonReaderFile jsonReader(inputFp, buffer, sizeof(buffer)); + { + base::JsonReaderObject reader = jsonReader.ParseObject(); + assert(!reader.HasReadError()); + + demoheader_t header; + if (!DemoJsonReader::ReadDemoHeader(reader, header)) + { + return; + } + writer->StartWriting(header); + context.protocol = header.networkprotocol; + } + + CommandPacket packet; + do + { + { + base::JsonReaderObject reader = jsonReader.ParseObject(); + if (reader.HasReadError()) + { + assert(!reader.HasReadError()); + } + + DemoJsonReader::ReadCmdHeader(reader, packet.cmd, packet.tick); + } + packet.data = demDataStructs[packet.cmd]; + DemHandlers::DemMsg_JsonRead(packet.cmd, jsonReader, packet.data); + + PacketTrailingBits trailingBits = PacketTrailingBits(); + writer->StartCommandPacket(packet); + if (packet.cmd == dem_packet || packet.cmd == dem_signon) + { + trailingBits = ParsePacket(jsonReader, context, writer, netDataStructs); + } + writer->EndCommandPacket(trailingBits); + } while (packet.cmd != dem_stop); + writer->EndWriting(); + + DemHandlers::DestroyDemMsgStructs(demDataStructs); + NetHandlers::DestroyNetMsgStructs(netDataStructs); } diff --git a/demboyz/io/jsonwriter.cpp b/demboyz/io/jsonwriter.cpp index 53751a9..8ebe968 100644 --- a/demboyz/io/jsonwriter.cpp +++ b/demboyz/io/jsonwriter.cpp @@ -59,14 +59,10 @@ void JsonWriter::StartCommandPacket(const CommandPacket& packet) auto& jsonFile = m_jsonFile; jsonFile.Reset(); jsonFile.StartObject(); - jsonFile.WriteInt32("tick", packet.tick); - jsonFile.WriteString("cmd", DemoCmdToString(packet.cmd)); + DemoJsonWriter::WriteCmdHeader(jsonFile, packet.cmd, packet.tick); jsonFile.EndObject(); - jsonFile.Reset(); - jsonFile.StartObject(); DemHandlers::DemMsg_JsonWrite(packet.cmd, jsonFile, packet.data); - jsonFile.EndObject(); assert(jsonFile.IsComplete()); if (packet.cmd == dem_packet || packet.cmd == dem_signon) @@ -83,11 +79,14 @@ void JsonWriter::EndCommandPacket(const PacketTrailingBits& trailingBits) auto& jsonFile = m_jsonFile; jsonFile.Reset(); jsonFile.StartObject(); - jsonFile.StartObject("netpackets_end"); + jsonFile.WriteInt32("netpacket", -1); + jsonFile.EndObject(); + + jsonFile.Reset(); + jsonFile.StartObject(); jsonFile.WriteInt32("numTrailingBits", trailingBits.numTrailingBits); jsonFile.WriteInt32("trailingBitsValue", trailingBits.value, (trailingBits.numTrailingBits > 0)); jsonFile.EndObject(); - jsonFile.EndObject(); assert(jsonFile.IsComplete()); } } @@ -97,7 +96,9 @@ void JsonWriter::WriteNetPacket(NetPacket& packet, SourceGameContext& context) auto& jsonFile = m_jsonFile; jsonFile.Reset(); jsonFile.StartObject(); - NetHandlers::NetMsg_JsonWrite(packet.type, jsonFile, context, packet.data); + jsonFile.WriteInt32("netpacket", packet.type); jsonFile.EndObject(); + + NetHandlers::NetMsg_JsonWrite(packet.type, jsonFile, context, packet.data); assert(jsonFile.IsComplete()); } diff --git a/demboyz/netmessages/net_disconnect.cpp b/demboyz/netmessages/net_disconnect.cpp index 0379cd3..902462d 100644 --- a/demboyz/netmessages/net_disconnect.cpp +++ b/demboyz/netmessages/net_disconnect.cpp @@ -19,15 +19,19 @@ namespace NetHandlers bool Net_Disconnect_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + reader.ReadString("message", data->message, sizeof(data->message)); + return !reader.HasReadError(); } bool Net_Disconnect_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_Disconnect* data) { - jsonbuf.StartObject("net_disconnect"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteString("message", data->message); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_Disconnect_ToString_Internal(std::ostringstream& out, NetMsg::Net_Disconnect* data) diff --git a/demboyz/netmessages/net_file.cpp b/demboyz/netmessages/net_file.cpp index df252d4..5863a5a 100644 --- a/demboyz/netmessages/net_file.cpp +++ b/demboyz/netmessages/net_file.cpp @@ -23,17 +23,23 @@ namespace NetHandlers bool Net_File_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_File* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->transferID = reader.ReadUInt32("transferId"); + reader.ReadString("filename", data->filename, sizeof(data->filename)); + data->isRequest = reader.ReadBool("isRequest"); + return !reader.HasReadError(); } bool Net_File_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_File* data) { - jsonbuf.StartObject("net_file"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("transferId", data->transferID); jsonbuf.WriteString("filename", data->filename); jsonbuf.WriteBool("isRequest", data->isRequest); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_File_ToString_Internal(std::ostringstream& out, NetMsg::Net_File* data) diff --git a/demboyz/netmessages/net_nop.cpp b/demboyz/netmessages/net_nop.cpp index 55703e2..fabc98f 100644 --- a/demboyz/netmessages/net_nop.cpp +++ b/demboyz/netmessages/net_nop.cpp @@ -21,8 +21,6 @@ namespace NetHandlers bool Net_NOP_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_NOP* data) { - jsonbuf.StartObject("net_nop"); - jsonbuf.EndObject(); return true; } diff --git a/demboyz/netmessages/net_setconvar.cpp b/demboyz/netmessages/net_setconvar.cpp index 4891019..9edc6e1 100644 --- a/demboyz/netmessages/net_setconvar.cpp +++ b/demboyz/netmessages/net_setconvar.cpp @@ -21,7 +21,7 @@ namespace NetHandlers bool Net_SetConVar_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_SetConVar* data) { bitbuf.WriteByte(data->cvars.size()); - for (cvar_t& cvar : data->cvars) + for (const cvar_t& cvar : data->cvars) { bitbuf.WriteString(cvar.name); bitbuf.WriteString(cvar.value); @@ -31,14 +31,24 @@ namespace NetHandlers bool Net_SetConVar_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + base::JsonReaderArray cvars = reader.ReadArray("cvars"); + cvars.TransformTo(data->cvars, [](base::JsonReaderObject& obj, cvar_t& cvar) + { + obj.ReadString("name", cvar.name, sizeof(cvar.name)); + obj.ReadString("value", cvar.value, sizeof(cvar.value)); + }); + return !reader.HasReadError(); } bool Net_SetConVar_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_SetConVar* data) { - jsonbuf.StartObject("net_setconvar"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.StartArray("cvars"); - for (cvar_t& cvar : data->cvars) + for (const cvar_t& cvar : data->cvars) { jsonbuf.StartObject(); jsonbuf.WriteString("name", cvar.name); @@ -47,7 +57,7 @@ namespace NetHandlers } jsonbuf.EndArray(); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_SetConVar_ToString_Internal(std::ostringstream& out, NetMsg::Net_SetConVar* data) diff --git a/demboyz/netmessages/net_signonstate.cpp b/demboyz/netmessages/net_signonstate.cpp index e3557c0..4080712 100644 --- a/demboyz/netmessages/net_signonstate.cpp +++ b/demboyz/netmessages/net_signonstate.cpp @@ -22,16 +22,21 @@ namespace NetHandlers bool Net_SignonState_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SignonState* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->signonState = reader.ReadUInt32("signonState"); + data->spawnCount = reader.ReadUInt32("spawnCount"); + return !reader.HasReadError(); } bool Net_SignonState_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_SignonState* data) { - jsonbuf.StartObject("net_signonstate"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("signonState", data->signonState); jsonbuf.WriteUInt32("spawnCount", data->spawnCount); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_SignonState_ToString_Internal(std::ostringstream& out, NetMsg::Net_SignonState* data) diff --git a/demboyz/netmessages/net_stringcmd.cpp b/demboyz/netmessages/net_stringcmd.cpp index 5c31f9b..d15d29f 100644 --- a/demboyz/netmessages/net_stringcmd.cpp +++ b/demboyz/netmessages/net_stringcmd.cpp @@ -19,15 +19,19 @@ namespace NetHandlers bool Net_StringCmd_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + reader.ReadString("command", data->command, sizeof(data->command)); + return !reader.HasReadError(); } bool Net_StringCmd_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_StringCmd* data) { - jsonbuf.StartObject("net_stringcmd"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteString("command", data->command); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_StringCmd_ToString_Internal(std::ostringstream& out, NetMsg::Net_StringCmd* data) diff --git a/demboyz/netmessages/net_tick.cpp b/demboyz/netmessages/net_tick.cpp index 31a220a..2ceb14c 100644 --- a/demboyz/netmessages/net_tick.cpp +++ b/demboyz/netmessages/net_tick.cpp @@ -23,17 +23,23 @@ namespace NetHandlers bool Net_Tick_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Tick* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->tick = reader.ReadInt32("tick"); + data->hostFrameTime = reader.ReadUInt32("hostFrameTime"); + data->hostFrameTimeStdDev = reader.ReadUInt32("hostFrameTimeStdDev"); + return !reader.HasReadError(); } bool Net_Tick_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_Tick* data) { - jsonbuf.StartObject("net_tick"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("tick", data->tick); jsonbuf.WriteUInt32("hostFrameTime", data->hostFrameTime); jsonbuf.WriteUInt32("hostFrameTimeStdDev", data->hostFrameTimeStdDev); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void Net_Tick_ToString_Internal(std::ostringstream& out, NetMsg::Net_Tick* data) diff --git a/demboyz/netmessages/nethandlers.cpp b/demboyz/netmessages/nethandlers.cpp index 27107ca..b8e18f7 100644 --- a/demboyz/netmessages/nethandlers.cpp +++ b/demboyz/netmessages/nethandlers.cpp @@ -111,10 +111,10 @@ void NetHandlers::DestroyNetMsgStructs(void* netDataStructs[32]) &NetHandlers::SVC_GetCvarValue_##funcname \ } -typedef bool (*NetMsgBitReadFn)(BitRead& bitbuf, SourceGameContext& context, void* data); -typedef bool (*NetMsgBitWriteFn)(BitWrite& bitbuf, const SourceGameContext& context, void* data); -typedef bool (*NetMsgJsonReadFn)(JsonRead& jsonbuf, SourceGameContext& context, void* data); -typedef bool (*NetMsgJsonWriteFn)(JsonWrite& jsonbuf, const SourceGameContext& context, void* data); +typedef bool (*NetMsgBitReadFn)(NetHandlers::BitRead& bitbuf, SourceGameContext& context, void* data); +typedef bool (*NetMsgBitWriteFn)(NetHandlers::BitWrite& bitbuf, const SourceGameContext& context, void* data); +typedef bool (*NetMsgJsonReadFn)(NetHandlers::JsonRead& jsonbuf, SourceGameContext& context, void* data); +typedef bool (*NetMsgJsonWriteFn)(NetHandlers::JsonWrite& jsonbuf, const SourceGameContext& context, void* data); typedef void (*NetMsgToStringFn)(std::ostringstream& out, void* data); bool NetHandlers::NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameContext& context, void* data) diff --git a/demboyz/netmessages/nethandlers.h b/demboyz/netmessages/nethandlers.h index 7f6c524..e08cc94 100644 --- a/demboyz/netmessages/nethandlers.h +++ b/demboyz/netmessages/nethandlers.h @@ -6,16 +6,22 @@ namespace base { + class JsonReaderFile; class JsonWriterFile; + class BitFileRead; + class BitFileWrite; } class bf_read; class bf_write; -using BitRead = bf_read; -using BitWrite = bf_write; -class JsonRead; -using JsonWrite = base::JsonWriterFile; +namespace NetHandlers +{ + using BitRead = bf_read; + using BitWrite = bf_write; + using JsonRead = base::JsonReaderFile; + using JsonWrite = base::JsonWriterFile; +} struct SourceGameContext { diff --git a/demboyz/netmessages/svc_bspdecal.cpp b/demboyz/netmessages/svc_bspdecal.cpp index d8705ea..d3434b8 100644 --- a/demboyz/netmessages/svc_bspdecal.cpp +++ b/demboyz/netmessages/svc_bspdecal.cpp @@ -45,19 +45,27 @@ namespace NetHandlers bool SVC_BSPDecal_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + DemoJsonReader::ReadVector(reader, "position", data->position); + data->decalTextureIndex = reader.ReadUInt32("decalTextureIndex"); + data->entIndex = reader.ReadUInt32("entIndex"); + data->modelIndex = reader.ReadUInt32("modelIndex"); + data->lowPriority = reader.ReadBool("lowPriority"); + return !reader.HasReadError(); } bool SVC_BSPDecal_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_BSPDecal* data) { - jsonbuf.StartObject("svc_bspdecal"); + jsonbuf.Reset(); + jsonbuf.StartObject(); DemoJsonWriter::WriteVector(jsonbuf, "position", data->position); jsonbuf.WriteUInt32("decalTextureIndex", data->decalTextureIndex); jsonbuf.WriteUInt32("entIndex", data->entIndex); jsonbuf.WriteUInt32("modelIndex", data->modelIndex); jsonbuf.WriteBool("lowPriority", data->lowPriority); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_BSPDecal_ToString_Internal(std::ostringstream& out, NetMsg::SVC_BSPDecal* data) diff --git a/demboyz/netmessages/svc_classinfo.cpp b/demboyz/netmessages/svc_classinfo.cpp index 3ecdfb0..34489f6 100644 --- a/demboyz/netmessages/svc_classinfo.cpp +++ b/demboyz/netmessages/svc_classinfo.cpp @@ -47,12 +47,27 @@ namespace NetHandlers bool SVC_ClassInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->numServerClasses = reader.ReadInt32("numServerClasses"); + data->createOnClient = reader.ReadBool("createOnClient"); + if (!data->createOnClient) + { + base::JsonReaderArray serverClasses = reader.ReadArray("serverClasses"); + serverClasses.TransformTo(data->serverClasses, [](base::JsonReaderObject& obj, class_t& serverClass) + { + serverClass.classID = obj.ReadUInt32("classId"); + obj.ReadString("className", serverClass.className, sizeof(serverClass.className)); + obj.ReadString("dataTableName", serverClass.dataTableName, sizeof(serverClass.dataTableName)); + }); + } + return !reader.HasReadError(); } bool SVC_ClassInfo_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_ClassInfo* data) { - jsonbuf.StartObject("svc_classinfo"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("numServerClasses", data->numServerClasses); jsonbuf.WriteBool("createOnClient", data->createOnClient); if (!data->createOnClient) @@ -67,7 +82,7 @@ namespace NetHandlers jsonbuf.EndArray(); } jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_ClassInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ClassInfo* data) diff --git a/demboyz/netmessages/svc_createstringtable.cpp b/demboyz/netmessages/svc_createstringtable.cpp index 411b806..da73fb3 100644 --- a/demboyz/netmessages/svc_createstringtable.cpp +++ b/demboyz/netmessages/svc_createstringtable.cpp @@ -82,12 +82,29 @@ namespace NetHandlers bool SVC_CreateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->isFileNames = reader.ReadBool("isFilenames"); + reader.ReadString("tableName", data->tableName, sizeof(data->tableName)); + data->maxEntries = reader.ReadUInt32("maxEntries"); + data->numEntries = reader.ReadUInt32("numEntries"); + data->dataLengthInBits = reader.ReadInt32("dataLengthInBits"); + data->isUserDataFixedSize = reader.ReadBool("isUserDataFixedSize"); + data->userDataSize = reader.ReadUInt32("userDataSize"); + data->userDataSizeBits = reader.ReadUInt32("userDataSizeBits"); + if (context.protocol > 14) + { + data->unk1 = reader.ReadBool("unk1"); + } + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_CreateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) { - jsonbuf.StartObject("svc_createstringtable"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBool("isFilenames", data->isFileNames); jsonbuf.WriteString("tableName", data->tableName); jsonbuf.WriteUInt32("maxEntries", data->maxEntries); @@ -102,7 +119,7 @@ namespace NetHandlers } jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_CreateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CreateStringTable* data) diff --git a/demboyz/netmessages/svc_crosshairangle.cpp b/demboyz/netmessages/svc_crosshairangle.cpp index 9b96a07..cfd7fa6 100644 --- a/demboyz/netmessages/svc_crosshairangle.cpp +++ b/demboyz/netmessages/svc_crosshairangle.cpp @@ -25,15 +25,19 @@ namespace NetHandlers bool SVC_CrosshairAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + DemoJsonReader::ReadAngle(reader, "angle", data->angle); + return !reader.HasReadError(); } bool SVC_CrosshairAngle_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) { - jsonbuf.StartObject("svc_crosshairangle"); + jsonbuf.Reset(); + jsonbuf.StartObject(); DemoJsonWriter::WriteAngle(jsonbuf, "angle", data->angle); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_CrosshairAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CrosshairAngle* data) diff --git a/demboyz/netmessages/svc_entitymessage.cpp b/demboyz/netmessages/svc_entitymessage.cpp index a89a66d..125ed4b 100644 --- a/demboyz/netmessages/svc_entitymessage.cpp +++ b/demboyz/netmessages/svc_entitymessage.cpp @@ -28,18 +28,26 @@ namespace NetHandlers bool SVC_EntityMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->entIndex = reader.ReadUInt32("entIndex"); + data->classID = reader.ReadUInt32("classId"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_EntityMessage_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_EntityMessage* data) { - jsonbuf.StartObject("svc_entitymessage"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("entIndex", data->entIndex); jsonbuf.WriteUInt32("classId", data->classID); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_EntityMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_EntityMessage* data) diff --git a/demboyz/netmessages/svc_fixangle.cpp b/demboyz/netmessages/svc_fixangle.cpp index fc4e01c..d033e5a 100644 --- a/demboyz/netmessages/svc_fixangle.cpp +++ b/demboyz/netmessages/svc_fixangle.cpp @@ -27,16 +27,21 @@ namespace NetHandlers bool SVC_FixAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->relative = reader.ReadBool("relative"); + DemoJsonReader::ReadAngle(reader, "angle", data->angle); + return !reader.HasReadError(); } bool SVC_FixAngle_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_FixAngle* data) { - jsonbuf.StartObject("svc_fixangle"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBool("relative", data->relative); DemoJsonWriter::WriteAngle(jsonbuf, "angle", data->angle); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_FixAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_FixAngle* data) diff --git a/demboyz/netmessages/svc_gameevent.cpp b/demboyz/netmessages/svc_gameevent.cpp index 30a54b9..5c8d7ae 100644 --- a/demboyz/netmessages/svc_gameevent.cpp +++ b/demboyz/netmessages/svc_gameevent.cpp @@ -24,16 +24,22 @@ namespace NetHandlers bool SVC_GameEvent_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_GameEvent_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GameEvent* data) { - jsonbuf.StartObject("svc_gameevent"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_GameEvent_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEvent* data) diff --git a/demboyz/netmessages/svc_gameeventlist.cpp b/demboyz/netmessages/svc_gameeventlist.cpp index ac627a0..c97832c 100644 --- a/demboyz/netmessages/svc_gameeventlist.cpp +++ b/demboyz/netmessages/svc_gameeventlist.cpp @@ -68,12 +68,29 @@ namespace NetHandlers bool SVC_GameEventList_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + + base::JsonReaderArray eventDescriptors = reader.ReadArray("eventDescriptors"); + eventDescriptors.TransformTo(data->eventDescriptors, [](base::JsonReaderObject& obj, EventDescriptor& event) + { + event.id = obj.ReadUInt32("id"); + obj.ReadString("name", event.name, sizeof(event.name)); + base::JsonReaderArray values = obj.ReadArray("values"); + values.TransformTo(event.values, [](base::JsonReaderObject& obj, EventValue& value) + { + value.type = obj.ReadUInt32("type"); + obj.ReadString("name", value.name, sizeof(value.name)); + }); + }); + data->dataLengthInBits = CalculateNumDataBits(data->eventDescriptors); + return !reader.HasReadError(); } bool SVC_GameEventList_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GameEventList* data) { - jsonbuf.StartObject("svc_gameeventlist"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.StartArray("eventDescriptors"); for (const EventDescriptor& event : data->eventDescriptors) { @@ -93,7 +110,7 @@ namespace NetHandlers } jsonbuf.EndArray(); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_GameEventList_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEventList* data) diff --git a/demboyz/netmessages/svc_getcvarvalue.cpp b/demboyz/netmessages/svc_getcvarvalue.cpp index c6b5302..e9defe1 100644 --- a/demboyz/netmessages/svc_getcvarvalue.cpp +++ b/demboyz/netmessages/svc_getcvarvalue.cpp @@ -21,16 +21,21 @@ namespace NetHandlers bool SVC_GetCvarValue_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->cookie = reader.ReadInt32("cookie"); + reader.ReadString("cvarName", data->cvarName, sizeof(data->cvarName)); + return !reader.HasReadError(); } bool SVC_GetCvarValue_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) { - jsonbuf.StartObject("svc_getcvarvalue"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("cookie", data->cookie); jsonbuf.WriteString("cvarName", data->cvarName); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_GetCvarValue_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GetCvarValue* data) diff --git a/demboyz/netmessages/svc_menu.cpp b/demboyz/netmessages/svc_menu.cpp index 1ae447c..e8f710b 100644 --- a/demboyz/netmessages/svc_menu.cpp +++ b/demboyz/netmessages/svc_menu.cpp @@ -37,17 +37,24 @@ namespace NetHandlers bool SVC_Menu_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Menu* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->type = static_cast(reader.ReadInt32("dialogType")); + data->dataLengthInBytes = reader.ReadUInt32("dataLengthInBytes"); + data->menuBinaryKeyValues.reset(new uint8_t[data->dataLengthInBytes]); + reader.ReadBytes("data", data->menuBinaryKeyValues.get(), data->dataLengthInBytes); + return !reader.HasReadError(); } bool SVC_Menu_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Menu* data) { - jsonbuf.StartObject("svc_menu"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("dialogType", static_cast(data->type)); jsonbuf.WriteUInt32("dataLengthInBytes", data->dataLengthInBytes); jsonbuf.WriteBytes("data", data->menuBinaryKeyValues.get(), data->dataLengthInBytes); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_Menu_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Menu* data) diff --git a/demboyz/netmessages/svc_packetentities.cpp b/demboyz/netmessages/svc_packetentities.cpp index a8cdf5e..5ec02e2 100644 --- a/demboyz/netmessages/svc_packetentities.cpp +++ b/demboyz/netmessages/svc_packetentities.cpp @@ -50,12 +50,24 @@ namespace NetHandlers bool SVC_PacketEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->maxEntries = reader.ReadInt32("maxEntries"); + data->isDelta = reader.ReadBool("isDelta"); + data->deltaFromTick = reader.ReadInt32("deltaFromTick"); + data->baselineIndex = reader.ReadUInt32("baselineIndex"); + data->numUpdatedEntries = reader.ReadUInt32("numUpdatedEntries"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->updateBaseline = reader.ReadBool("updateBaseline"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_PacketEntities_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_PacketEntities* data) { - jsonbuf.StartObject("svc_packetentities"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("maxEntries", data->maxEntries); jsonbuf.WriteBool("isDelta", data->isDelta); jsonbuf.WriteInt32("deltaFromTick", data->deltaFromTick); @@ -65,7 +77,7 @@ namespace NetHandlers jsonbuf.WriteBool("updateBaseline", data->updateBaseline); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_PacketEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_PacketEntities* data) diff --git a/demboyz/netmessages/svc_prefetch.cpp b/demboyz/netmessages/svc_prefetch.cpp index e49b01f..ac4d47c 100644 --- a/demboyz/netmessages/svc_prefetch.cpp +++ b/demboyz/netmessages/svc_prefetch.cpp @@ -35,16 +35,21 @@ namespace NetHandlers bool SVC_Prefetch_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->type = reader.ReadUInt32("type"); + data->soundIndex = reader.ReadUInt32("soundIndex"); + return !reader.HasReadError(); } bool SVC_Prefetch_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Prefetch* data) { - jsonbuf.StartObject("svc_prefetch"); + jsonbuf.Reset(); + jsonbuf.StartObject();; jsonbuf.WriteUInt32("type", data->type); jsonbuf.WriteUInt32("soundIndex", data->soundIndex); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_Prefetch_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Prefetch* data) diff --git a/demboyz/netmessages/svc_print.cpp b/demboyz/netmessages/svc_print.cpp index 38883ce..fadb0de 100644 --- a/demboyz/netmessages/svc_print.cpp +++ b/demboyz/netmessages/svc_print.cpp @@ -19,15 +19,19 @@ namespace NetHandlers bool SVC_Print_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Print* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + reader.ReadString("text", data->text, sizeof(data->text)); + return !reader.HasReadError(); } bool SVC_Print_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Print* data) { - jsonbuf.StartObject("svc_print"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteString("text", data->text); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_Print_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Print* data) diff --git a/demboyz/netmessages/svc_sendtable.cpp b/demboyz/netmessages/svc_sendtable.cpp index 685ad9e..e431cc9 100644 --- a/demboyz/netmessages/svc_sendtable.cpp +++ b/demboyz/netmessages/svc_sendtable.cpp @@ -25,17 +25,24 @@ namespace NetHandlers bool SVC_SendTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->needsDecoder = reader.ReadBool("needsDecoder"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_SendTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SendTable* data) { - jsonbuf.StartObject("svc_sendtable"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBool("needsDecoder", data->needsDecoder); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_SendTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SendTable* data) diff --git a/demboyz/netmessages/svc_serverinfo.cpp b/demboyz/netmessages/svc_serverinfo.cpp index 2b5c4ba..34e3340 100644 --- a/demboyz/netmessages/svc_serverinfo.cpp +++ b/demboyz/netmessages/svc_serverinfo.cpp @@ -69,12 +69,41 @@ namespace NetHandlers bool SVC_ServerInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->protocol = reader.ReadInt32("protocol"); + data->serverCount = reader.ReadUInt32("serverCount"); + data->isHLTV = reader.ReadBool("isHltv"); + data->isDedicated = reader.ReadBool("isDedicated"); + data->clientCRC = reader.ReadUInt32("clientCrc"); + data->maxClasses = reader.ReadUInt32("maxClasses"); + if (context.protocol <= 17) + { + data->mapCRC = reader.ReadUInt32("mapCRC"); + } + else + { + reader.ReadBytes("unk1", data->unk1, sizeof(data->unk1)); + } + data->playerSlot = reader.ReadUInt32("playerSlot"); + data->maxClients = reader.ReadUInt32("maxClients"); + data->tickInterval = reader.ReadFloat("tickInterval"); + data->os = reader.ReadChar("os"); + reader.ReadString("gameDir", data->gameDir, sizeof(data->gameDir)); + reader.ReadString("mapName", data->mapName, sizeof(data->mapName)); + reader.ReadString("skyName", data->skyName, sizeof(data->skyName)); + reader.ReadString("hostName", data->hostName, sizeof(data->hostName)); + if (context.protocol > 15) + { + data->unk2 = reader.ReadBool("unk2"); + } + return !reader.HasReadError(); } bool SVC_ServerInfo_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_ServerInfo* data) { - jsonbuf.StartObject("svc_serverinfo"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteInt32("protocol", data->protocol); jsonbuf.WriteUInt32("serverCount", data->serverCount); jsonbuf.WriteBool("isHltv", data->isHLTV); @@ -102,7 +131,7 @@ namespace NetHandlers jsonbuf.WriteBool("unk2", data->unk2); } jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_ServerInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ServerInfo* data) diff --git a/demboyz/netmessages/svc_setpause.cpp b/demboyz/netmessages/svc_setpause.cpp index a921036..b3f1d74 100644 --- a/demboyz/netmessages/svc_setpause.cpp +++ b/demboyz/netmessages/svc_setpause.cpp @@ -19,15 +19,19 @@ namespace NetHandlers bool SVC_SetPause_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->isPaused = reader.ReadBool("isPaused"); + return !reader.HasReadError(); } bool SVC_SetPause_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SetPause* data) { - jsonbuf.StartObject("svc_setpause"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBool("isPaused", data->isPaused); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_SetPause_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetPause* data) diff --git a/demboyz/netmessages/svc_setview.cpp b/demboyz/netmessages/svc_setview.cpp index 7c1d6c1..7b1de45 100644 --- a/demboyz/netmessages/svc_setview.cpp +++ b/demboyz/netmessages/svc_setview.cpp @@ -20,15 +20,19 @@ namespace NetHandlers bool SVC_SetView_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetView* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->entIndex = reader.ReadUInt32("entIndex"); + return !reader.HasReadError(); } bool SVC_SetView_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SetView* data) { - jsonbuf.StartObject("svc_setview"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("entIndex", data->entIndex); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_SetView_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetView* data) diff --git a/demboyz/netmessages/svc_sounds.cpp b/demboyz/netmessages/svc_sounds.cpp index 39adb87..669c114 100644 --- a/demboyz/netmessages/svc_sounds.cpp +++ b/demboyz/netmessages/svc_sounds.cpp @@ -43,18 +43,26 @@ namespace NetHandlers bool SVC_Sounds_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->reliableSound = reader.ReadBool("reliableSound"); + data->numSounds = reader.ReadUInt32("numSounds"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_Sounds_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Sounds* data) { - jsonbuf.StartObject("svc_sounds"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteBool("reliableSound", data->reliableSound); jsonbuf.WriteUInt32("numSounds", data->numSounds); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_Sounds_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Sounds* data) diff --git a/demboyz/netmessages/svc_tempentities.cpp b/demboyz/netmessages/svc_tempentities.cpp index 0304f65..1b1cb8d 100644 --- a/demboyz/netmessages/svc_tempentities.cpp +++ b/demboyz/netmessages/svc_tempentities.cpp @@ -40,17 +40,24 @@ namespace NetHandlers bool SVC_TempEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->numEntries = reader.ReadUInt32("numEntries"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_TempEntities_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_TempEntities* data) { - jsonbuf.StartObject("svc_tempentities"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("numEntries", data->numEntries); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_TempEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_TempEntities* data) diff --git a/demboyz/netmessages/svc_updatestringtable.cpp b/demboyz/netmessages/svc_updatestringtable.cpp index 896374f..144e2fe 100644 --- a/demboyz/netmessages/svc_updatestringtable.cpp +++ b/demboyz/netmessages/svc_updatestringtable.cpp @@ -36,18 +36,26 @@ namespace NetHandlers bool SVC_UpdateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->tableID = reader.ReadUInt32("tableId"); + data->numChangedEntries = reader.ReadUInt32("numChangedEntries"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_UpdateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) { - jsonbuf.StartObject("svc_updatestringtable"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("tableId", data->tableID); jsonbuf.WriteUInt32("numChangedEntries", data->numChangedEntries); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_UpdateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UpdateStringTable* data) diff --git a/demboyz/netmessages/svc_usermessage.cpp b/demboyz/netmessages/svc_usermessage.cpp index 28bfcbd..5f5e276 100644 --- a/demboyz/netmessages/svc_usermessage.cpp +++ b/demboyz/netmessages/svc_usermessage.cpp @@ -28,17 +28,24 @@ namespace NetHandlers bool SVC_UserMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->msgType = reader.ReadUInt32("msgType"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_UserMessage_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_UserMessage* data) { - jsonbuf.StartObject("svc_usermessage"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("msgType", data->msgType); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_UserMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UserMessage* data) diff --git a/demboyz/netmessages/svc_voicedata.cpp b/demboyz/netmessages/svc_voicedata.cpp index b22a3f9..b9114e4 100644 --- a/demboyz/netmessages/svc_voicedata.cpp +++ b/demboyz/netmessages/svc_voicedata.cpp @@ -27,18 +27,26 @@ namespace NetHandlers bool SVC_VoiceData_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + data->fromClientIndex = reader.ReadUInt32("fromClientIndex"); + data->proximity = reader.ReadBool("proximity"); + data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits"); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + reader.ReadBits("data", data->data.get(), data->dataLengthInBits); + return !reader.HasReadError(); } bool SVC_VoiceData_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_VoiceData* data) { - jsonbuf.StartObject("svc_voicedata"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteUInt32("fromClientIndex", data->fromClientIndex); jsonbuf.WriteBool("proximity", data->proximity); jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits); jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_VoiceData_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceData* data) diff --git a/demboyz/netmessages/svc_voiceinit.cpp b/demboyz/netmessages/svc_voiceinit.cpp index 56759eb..805b23d 100644 --- a/demboyz/netmessages/svc_voiceinit.cpp +++ b/demboyz/netmessages/svc_voiceinit.cpp @@ -21,16 +21,21 @@ namespace NetHandlers bool SVC_VoiceInit_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data) { - return true; + base::JsonReaderObject reader = jsonbuf.ParseObject(); + assert(!reader.HasReadError()); + reader.ReadString("voiceCodec", data->voiceCodec, sizeof(data->voiceCodec)); + data->quality = reader.ReadUInt32("quality"); + return !reader.HasReadError(); } bool SVC_VoiceInit_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_VoiceInit* data) { - jsonbuf.StartObject("svc_voiceinit"); + jsonbuf.Reset(); + jsonbuf.StartObject(); jsonbuf.WriteString("voiceCodec", data->voiceCodec); jsonbuf.WriteUInt32("quality", data->quality); jsonbuf.EndObject(); - return true; + return jsonbuf.IsComplete(); } void SVC_VoiceInit_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceInit* data)