diff --git a/demboyz/demowriter.cpp b/demboyz/demowriter.cpp index 1e601f1..8376658 100644 --- a/demboyz/demowriter.cpp +++ b/demboyz/demowriter.cpp @@ -26,3 +26,23 @@ IDemoWriter* IDemoWriter::CreateDemoWriter(void* outputFp) DemoWriter::DemoWriter(FILE* outputFp) { } + +void DemoWriter::StartWriting(demoheader_t& header) +{ +} + +void DemoWriter::EndWriting() +{ +} + +void DemoWriter::StartCommandPacket(CommandPacket& packet) +{ +} + +void DemoWriter::EndCommandPacket() +{ +} + +void DemoWriter::WriteNetPacket(NetPacket& packet) +{ +} diff --git a/demboyz/demreader.cpp b/demboyz/demreader.cpp index 935fe5a..eb3ae04 100644 --- a/demboyz/demreader.cpp +++ b/demboyz/demreader.cpp @@ -2,36 +2,51 @@ #include "demoreader.h" #include "idemowriter.h" #include "demofile.h" +#include "demotypes.h" -/*void ParsePacket(const std::vector& packet) +#include "netmessages/netmessages.h" +#include "netmessages/netcontants.h" +#include "bitbuf.h" +#include +#include + +typedef bool (*NetMsgReadFn)(bf_read& bitbuf, SourceGameContext& context, void* data); + +static const NetMsgReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitRead); +//static const void* netDataStructs[] = DECLARE_NET_DATA_ARRAY; + +void ParsePacket(uint8_t* packet, size_t length, IDemoWriter* writer) { - assert(packet.size() <= NET_MAX_PAYLOAD); - bf_read bitbuf(packet.data(), packet.size()); + assert(length <= NET_MAX_PAYLOAD); + bf_read bitbuf(packet, length); + NetPacket netPacket; while (bitbuf.GetNumBitsLeft() >= NETMSG_TYPE_BITS) { - uint32 typeId = bitbuf.ReadUBitLong(NETMSG_TYPE_BITS); - printf("%i\n", typeId); - //ProcessNetMsg(typeId, bitbuf); + netPacket.type = bitbuf.ReadUBitLong(NETMSG_TYPE_BITS); + //netPacket.data = netDataStructs[netPacket.type]; + //netHandlers[netPacket.type](bitbuf, context, ); } } -void ParseDemoSequence(const std::vector& sequenceData) +void ParseDemo(DemoFileReader& reader, IDemoWriter* writer) { + democmdinfo_t cmdInfo; CommandPacket packet; + packet.cmdInfo = &cmdInfo; std::vector buffer; + buffer.resize(NET_MAX_PAYLOAD); - DemoSequenceReader reader(sequenceData); - for (; reader.ReadCmdHeader(packet.cmd, packet.tick);) + do { + reader.ReadCmdHeader(packet.cmd, packet.tick); switch (packet.cmd) { case dem_signon: case dem_packet: - reader.ReadCmdInfo(packet.cmdInfo); + reader.ReadCmdInfo(*packet.cmdInfo); reader.ReadSequenceInfo(packet.sequenceInfo1, packet.sequenceInfo2); assert(packet.sequenceInfo1 == packet.sequenceInfo2); - reader.ReadRawData(buffer); - ParsePacket(buffer); + reader.ReadRawData(buffer.data(), buffer.size()); break; case dem_synctick: // nothing @@ -40,7 +55,7 @@ void ParseDemoSequence(const std::vector& sequenceData) reader.ReadRawData(nullptr, 1024); break; case dem_usercmd: - reader.ReadUserCmd(buffer, 256); + reader.ReadUserCmd(buffer.data(), 256); break; case dem_datatables: // TODO: datatables @@ -59,14 +74,23 @@ void ParseDemoSequence(const std::vector& sequenceData) assert(false); break; } - } -}*/ + writer->StartCommandPacket(packet); + if (packet.cmd == dem_packet || packet.cmd == dem_signon) + { + ParsePacket(buffer.data(), buffer.size(), writer); + } + writer->EndCommandPacket(); + } while (packet.cmd != dem_stop); +} void DemoReader::ProcessDem(void* inputFp, IDemoWriter* writer) { DemoFileReader demoFile(reinterpret_cast(inputFp)); - - //auto demoHeader = demoFile.GetDemoHeader(); - //ParseDemoSequence(demoFile.GetSignOnData()); - //ParseDemoSequence(demoFile.GetDemoData()); + { + demoheader_t header; + demoFile.ReadDemoHeader(header); + writer->StartWriting(header); + } + ParseDemo(demoFile, writer); + writer->EndWriting(); } diff --git a/demboyz/jsonwriter.cpp b/demboyz/jsonwriter.cpp index 4923293..658f280 100644 --- a/demboyz/jsonwriter.cpp +++ b/demboyz/jsonwriter.cpp @@ -22,3 +22,27 @@ IDemoWriter* IDemoWriter::CreateJsonWriter(void* outputFp) { return new JsonWriter(reinterpret_cast(outputFp)); } + +JsonWriter::JsonWriter(FILE* outputFp) +{ +} + +void JsonWriter::StartWriting(demoheader_t& header) +{ +} + +void JsonWriter::EndWriting() +{ +} + +void JsonWriter::StartCommandPacket(CommandPacket& packet) +{ +} + +void JsonWriter::EndCommandPacket() +{ +} + +void JsonWriter::WriteNetPacket(NetPacket& packet) +{ +} diff --git a/demboyz/netmessages.cpp b/demboyz/netmessages.cpp index e29fa59..38f3620 100644 --- a/demboyz/netmessages.cpp +++ b/demboyz/netmessages.cpp @@ -1,23 +1,9 @@ - +/* #include "netmessages.h" #include "demofilebitbuf.h" +#include "sourcenetcontants.h" #include - -namespace math -{ - unsigned int log2(unsigned int value) - { - unsigned int res = 0; - while (value >>= 1) - ++res; - return res; - } - - unsigned int Bits2Bytes(unsigned int bits) - { - return ((bits + 7) >> 3); - } -} +#include "netmath.h" void Net_NOP(CBitRead& bitbuf) { @@ -81,6 +67,7 @@ void Net_SignonState(CBitRead& bitbuf) const int spawnCount = bitbuf.ReadLong(); } +// verified void SVC_Print(CBitRead& bitbuf) { char textBuffer[2048]; @@ -127,6 +114,7 @@ void SVC_ServerInfo(CBitRead& bitbuf) // } } +// verified void SVC_SendTable(CBitRead& bitbuf) { const bool needsDecoder = bitbuf.ReadOneBit() != 0; @@ -160,6 +148,7 @@ void SVC_ClassInfo(CBitRead& bitbuf) } } +// verified void SVC_SetPause(CBitRead& bitbuf) { const bool paused = bitbuf.ReadOneBit() != 0; @@ -191,7 +180,7 @@ void SVC_CreateStringTable(CBitRead& bitbuf) // } // else // { - // const int lengthInBits = bitbuf.ReadUBitLong(NET_MAX_PALYLOAD_BITS + 1); + // const int lengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS + 1); // } const bool userDataFixedSize = bitbuf.ReadOneBit() != 0; @@ -234,6 +223,7 @@ void SVC_VoiceInit(CBitRead& bitbuf) const int quality = bitbuf.ReadByte(); // custom quality setting } +// verified void SVC_VoiceData(CBitRead& bitbuf) { const int fromClientIndex = bitbuf.ReadByte(); @@ -266,6 +256,7 @@ void SVC_Sounds(CBitRead& bitbuf) bitbuf.SeekRelative(lengthInBits); } +// verified void SVC_SetView(CBitRead& bitbuf) { const int entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS); @@ -309,6 +300,7 @@ void SVC_TerrainMod(CBitRead& bitbuf) assert(false); } +// verified void SVC_UserMessage(CBitRead& bitbuf) { const int msgType = bitbuf.ReadByte(); @@ -318,6 +310,7 @@ void SVC_UserMessage(CBitRead& bitbuf) bitbuf.SeekRelative(lengthInBits); } +// verified void SVC_EntityMessage(CBitRead& bitbuf) { const int entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS); @@ -328,6 +321,7 @@ void SVC_EntityMessage(CBitRead& bitbuf) bitbuf.SeekRelative(lengthInBits); } +// verified void SVC_GameEvent(CBitRead& bitbuf) { const int lengthInBits = bitbuf.ReadUBitLong(11); @@ -335,6 +329,7 @@ void SVC_GameEvent(CBitRead& bitbuf) bitbuf.SeekRelative(lengthInBits); } +// verified void SVC_PacketEntities(CBitRead& bitbuf) { const int maxEntries = bitbuf.ReadUBitLong(MAX_EDICT_BITS); @@ -357,7 +352,7 @@ void SVC_PacketEntities(CBitRead& bitbuf) void SVC_TempEntities(CBitRead& bitbuf) { const int numEntries = bitbuf.ReadUBitLong(EVENT_INDEX_BITS); - const int lengthInBits = bitbuf.ReadUBitLong(NET_MAX_PALYLOAD_BITS); + const int lengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS); bitbuf.SeekRelative(lengthInBits); } @@ -391,17 +386,20 @@ void SVC_Menu(CBitRead& bitbuf) void SVC_GameEventList(CBitRead& bitbuf) { const int numEvents = bitbuf.ReadUBitLong(MAX_EVENT_BITS); + const int lengthInBits = bitbuf.ReadUBitLong(20); for (int i = 0; i < numEvents; ++i) { const int id = bitbuf.ReadUBitLong(MAX_EVENT_BITS); char name[MAX_EVENT_NAME_LENGTH]; bitbuf.ReadString(name, sizeof(name)); printf("%s\n", name); - assert(false); + while (bitbuf.ReadUBitLong(3) > 0) + { + bitbuf.ReadString(name, sizeof(name)); + } // gameeventmanager.cpp ParseEventList } - const int lengthInBits = bitbuf.ReadUBitLong(20); - bitbuf.SeekRelative(lengthInBits); + //bitbuf.SeekRelative(lengthInBits); } void SVC_GetCvarValue(CBitRead& bitbuf) @@ -411,48 +409,4 @@ void SVC_GetCvarValue(CBitRead& bitbuf) char cvarName[256]; bitbuf.ReadString(cvarName, sizeof(cvarName)); } - -static const int NUM_MESSAGES = static_cast(NetMsg::SVC_LASTMSG) + 1; - -void ProcessNetMsg(const std::uint32_t msgType, CBitRead& bitbuf) -{ - static NetMsgFn netMsgHandler[NUM_MESSAGES] = - { - &Net_NOP, - &Net_Disconnect, - &Net_File, - &Net_Tick, - &Net_StringCmd, - &Net_SetConVar, - &Net_SignonState, - - &SVC_Print, - &SVC_ServerInfo, - &SVC_SendTable, - &SVC_ClassInfo, - &SVC_SetPause, - &SVC_CreateStringTable, - &SVC_UpdateStringTable, - &SVC_VoiceInit, - &SVC_VoiceData, - &SVC_HLTV, - &SVC_Sounds, - &SVC_SetView, - &SVC_FixAngle, - &SVC_CrosshairAngle, - &SVC_BSPDecal, - &SVC_TerrainMod, - &SVC_UserMessage, - &SVC_EntityMessage, - &SVC_GameEvent, - &SVC_PacketEntities, - &SVC_TempEntities, - &SVC_Prefetch, - &SVC_Menu, - &SVC_GameEventList, - &SVC_GetCvarValue - }; - - assert(msgType < NUM_MESSAGES); - netMsgHandler[msgType](bitbuf); -} +*/ diff --git a/demboyz/netmessages.h b/demboyz/netmessages.h deleted file mode 100644 index fad69dd..0000000 --- a/demboyz/netmessages.h +++ /dev/null @@ -1,114 +0,0 @@ - -#pragma once - -#include - -class CBitRead; - -typedef void(*NetMsgFn)(CBitRead& bitbuf); - -enum constants -{ - // was 5 - NETMSG_TYPE_BITS = 6, // 2^NETMSG_TYPE_BITS > SVC_LASTMSG - - // was 96000 - NET_MAX_PAYLOAD = 288000, // largest message size in bytes - - // was 17 - NET_MAX_PALYLOAD_BITS = 19, // 2^NET_MAX_PALYLOAD_BITS > NET_MAX_PAYLOAD - - // table index is sent in log2(MAX_TABLES) bits - MAX_TABLES = 32, // Table id is 4 bits - - // How many bits to use to encode an edict. - MAX_EDICT_BITS = 11, // # of bits needed to represent max edicts - - // Max # of edicts in a level - MAX_EDICTS = (1< (NET_MAX_PAYLOAD * 8) - EVENT_INDEX_BITS = 8, - MAX_SOUND_INDEX_BITS = 13, - - - SIGNONSTATE_NONE = 0, // no state yet, about to connect - SIGNONSTATE_CHALLENGE = 1, // client challenging server, all OOB packets - SIGNONSTATE_CONNECTED = 2, // client is connected to server, netchans ready - SIGNONSTATE_NEW = 3, // just got serverinfo and string tables - SIGNONSTATE_PRESPAWN = 4, // received signon buffers - SIGNONSTATE_SPAWN = 5, // ready to receive entity packets - SIGNONSTATE_FULL = 6, // we are fully connected, first non-delta packet received - SIGNONSTATE_CHANGELEVEL = 7 // server is changing level, please wait -}; - -enum class NetMsg: std::uint8_t -{ - net_NOP = 0, // nop command used for padding - net_Disconnect = 1, // disconnect, last message in connection - net_File = 2, // file transmission message request/deny - - net_Tick = 3, // send last world tick - net_StringCmd = 4, // a string command - net_SetConVar = 5, // sends one/multiple convar settings - net_SignonState = 6, // signals current signon state - - // - // server to client - // - - svc_Print = 7, // print text to console - svc_ServerInfo = 8, // first message from server about game, map etc - svc_SendTable = 9, // sends a sendtable description for a game class - svc_ClassInfo = 10, // Info about classes (first byte is a CLASSINFO_ define). - svc_SetPause = 11, // tells client if server paused or unpaused - - - svc_CreateStringTable = 12, // inits shared string tables - svc_UpdateStringTable = 13, // updates a string table - - svc_VoiceInit = 14, // inits used voice codecs & quality - svc_VoiceData = 15, // Voicestream data from the server - - //svc_HLTV = 16, // HLTV control messages - - svc_Sounds = 17, // starts playing sound - - svc_SetView = 18, // sets entity as point of view - svc_FixAngle = 19, // sets/corrects players viewangle - svc_CrosshairAngle = 20, // adjusts crosshair in auto aim mode to lock on traget - - svc_BSPDecal = 21, // add a static decal to the worl BSP - - // NOTE: This is now unused! - // svc_TerrainMod = 22, // modification to the terrain/displacement - - // Message from server side to client side entity - svc_UserMessage = 23, // a game specific message - svc_EntityMessage = 24, // a message for an entity - svc_GameEvent = 25, // global game event fired - - svc_PacketEntities = 26, // non-delta compressed entities - - svc_TempEntities = 27, // non-reliable event object - - svc_Prefetch = 28, // only sound indices for now - - svc_Menu = 29, // display a menu from a plugin - - svc_GameEventList = 30, // list of known games events and fields - - svc_GetCvarValue = 31, // Server wants to know the value of a cvar on the client. - - SVC_LASTMSG = 31 // last known server messages -}; - -void ProcessNetMsg(const std::uint32_t msgType, CBitRead& bitbuf); diff --git a/demboyz/netmessages/net_disconnect.cpp b/demboyz/netmessages/net_disconnect.cpp new file mode 100644 index 0000000..3a0cd0a --- /dev/null +++ b/demboyz/netmessages/net_disconnect.cpp @@ -0,0 +1,33 @@ + +#include "net_disconnect.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool Net_Disconnect_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data) + { + bitbuf.ReadString(data->message, sizeof(data->message)); + return !bitbuf.IsOverflowed(); + } + + bool Net_Disconnect_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data) + { + bitbuf.WriteString(data->message); + return !bitbuf.IsOverflowed(); + } + + bool Net_Disconnect_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data) + { + return true; + } + + bool Net_Disconnect_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data) + { + return true; + } + + void Net_Disconnect_ToString_Internal(std::ostringstream& out, NetMsg::Net_Disconnect* data) + { + // nothing + } +} diff --git a/demboyz/netmessages/net_disconnect.h b/demboyz/netmessages/net_disconnect.h new file mode 100644 index 0000000..0ec7ee4 --- /dev/null +++ b/demboyz/netmessages/net_disconnect.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_Disconnect + { + char message[1024]; + }; +} + +DECLARE_NET_HANDLERS(Net_Disconnect); diff --git a/demboyz/netmessages/net_file.cpp b/demboyz/netmessages/net_file.cpp new file mode 100644 index 0000000..dd5980f --- /dev/null +++ b/demboyz/netmessages/net_file.cpp @@ -0,0 +1,37 @@ + +#include "net_file.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool Net_File_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_File* data) + { + data->transferID = bitbuf.ReadUBitLong(32); + bitbuf.ReadString(data->filename, sizeof(data->filename)); + data->isRequest = bitbuf.ReadOneBit() != 0; + return !bitbuf.IsOverflowed(); + } + + bool Net_File_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_File* data) + { + bitbuf.WriteUBitLong(data->transferID, 32); + bitbuf.WriteString(data->filename); + bitbuf.WriteOneBit(data->isRequest); + return !bitbuf.IsOverflowed(); + } + + bool Net_File_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_File* data) + { + return true; + } + + bool Net_File_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_File* data) + { + return true; + } + + void Net_File_ToString_Internal(std::ostringstream& out, NetMsg::Net_File* data) + { + // nothing + } +} diff --git a/demboyz/netmessages/net_file.h b/demboyz/netmessages/net_file.h new file mode 100644 index 0000000..09400e5 --- /dev/null +++ b/demboyz/netmessages/net_file.h @@ -0,0 +1,16 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_File + { + std::uint32_t transferID; + bool isRequest; + char filename[1024]; + }; +} + +DECLARE_NET_HANDLERS(Net_File); diff --git a/demboyz/netmessages/net_nop.cpp b/demboyz/netmessages/net_nop.cpp new file mode 100644 index 0000000..38c7dc1 --- /dev/null +++ b/demboyz/netmessages/net_nop.cpp @@ -0,0 +1,29 @@ + +#include "net_nop.h" + +namespace NetHandlers +{ + bool Net_NOP_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_NOP* data) + { + return true; + } + + bool Net_NOP_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_NOP* data) + { + return true; + } + + bool Net_NOP_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_NOP* data) + { + return true; + } + + bool Net_NOP_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_NOP* data) + { + return true; + } + + void Net_NOP_ToString_Internal(std::ostringstream& out, NetMsg::Net_NOP* data) + { + } +} diff --git a/demboyz/netmessages/net_nop.h b/demboyz/netmessages/net_nop.h new file mode 100644 index 0000000..d040efa --- /dev/null +++ b/demboyz/netmessages/net_nop.h @@ -0,0 +1,13 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_NOP + { + }; +} + +DECLARE_NET_HANDLERS(Net_NOP); diff --git a/demboyz/netmessages/net_setconvar.cpp b/demboyz/netmessages/net_setconvar.cpp new file mode 100644 index 0000000..8c4e8af --- /dev/null +++ b/demboyz/netmessages/net_setconvar.cpp @@ -0,0 +1,46 @@ + +#include "net_setconvar.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + using cvar_t = NetMsg::Net_SetConVar::cvar_t; + + bool Net_SetConVar_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data) + { + data->cvars.resize(bitbuf.ReadUBitLong(8)); + for (cvar_t& cvar : data->cvars) + { + bitbuf.ReadString(cvar.name, sizeof(cvar.name)); + bitbuf.ReadString(cvar.value, sizeof(cvar.value)); + } + return !bitbuf.IsOverflowed(); + } + + bool Net_SetConVar_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data) + { + bitbuf.WriteUBitLong(data->cvars.size(), 8); + for (cvar_t& cvar : data->cvars) + { + bitbuf.WriteString(cvar.name); + bitbuf.WriteString(cvar.value); + } + return !bitbuf.IsOverflowed(); + } + + bool Net_SetConVar_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data) + { + return true; + } + + bool Net_SetConVar_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data) + { + return true; + } + + void Net_SetConVar_ToString_Internal(std::ostringstream& out, NetMsg::Net_SetConVar* data) + { + cvar_t cvar = data->cvars[0]; + out << "net_SetConVar: " << data->cvars.size() << " cvars, \"" << cvar.name << "\"=\"" << cvar.value << '"'; + } +} diff --git a/demboyz/netmessages/net_setconvar.h b/demboyz/netmessages/net_setconvar.h new file mode 100644 index 0000000..7b64786 --- /dev/null +++ b/demboyz/netmessages/net_setconvar.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct Net_SetConVar + { + typedef struct cvar_s + { + char name[MAX_OSPATH]; + char value[MAX_OSPATH]; + } cvar_t; + + std::vector cvars; + }; +} + +DECLARE_NET_HANDLERS(Net_SetConVar); diff --git a/demboyz/netmessages/net_signonstate.cpp b/demboyz/netmessages/net_signonstate.cpp new file mode 100644 index 0000000..76e7131 --- /dev/null +++ b/demboyz/netmessages/net_signonstate.cpp @@ -0,0 +1,36 @@ + +#include "net_signonstate.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool Net_SignonState_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_SignonState* data) + { + data->signonState = bitbuf.ReadUBitLong(8); + data->spawnCount = bitbuf.ReadUBitLong(32); + //assert(signonState >= SIGNONSTATE_NONE && signonState <= SIGNONSTATE_CHANGELEVEL); + return !bitbuf.IsOverflowed(); + } + + bool Net_SignonState_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_SignonState* data) + { + bitbuf.WriteUBitLong(data->signonState, 8); + bitbuf.WriteUBitLong(data->spawnCount, 32); + return !bitbuf.IsOverflowed(); + } + + bool Net_SignonState_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SignonState* data) + { + return true; + } + + bool Net_SignonState_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_SignonState* data) + { + return true; + } + + void Net_SignonState_ToString_Internal(std::ostringstream& out, NetMsg::Net_SignonState* data) + { + out << "net_SignonState: state " << data->signonState << ", count " << data->spawnCount; + } +} diff --git a/demboyz/netmessages/net_signonstate.h b/demboyz/netmessages/net_signonstate.h new file mode 100644 index 0000000..641f1cf --- /dev/null +++ b/demboyz/netmessages/net_signonstate.h @@ -0,0 +1,15 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_SignonState + { + std::uint32_t spawnCount; + std::uint8_t signonState; + }; +} + +DECLARE_NET_HANDLERS(Net_SignonState); diff --git a/demboyz/netmessages/net_stringcmd.cpp b/demboyz/netmessages/net_stringcmd.cpp new file mode 100644 index 0000000..e29bfd0 --- /dev/null +++ b/demboyz/netmessages/net_stringcmd.cpp @@ -0,0 +1,33 @@ + +#include "net_stringcmd.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool Net_StringCmd_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data) + { + bitbuf.ReadString(data->command, sizeof(data->command)); + return !bitbuf.IsOverflowed(); + } + + bool Net_StringCmd_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data) + { + bitbuf.WriteString(data->command); + return !bitbuf.IsOverflowed(); + } + + bool Net_StringCmd_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data) + { + return true; + } + + bool Net_StringCmd_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data) + { + return true; + } + + void Net_StringCmd_ToString_Internal(std::ostringstream& out, NetMsg::Net_StringCmd* data) + { + out << "net_StringCmd: \"" << data->command << '"'; + } +} diff --git a/demboyz/netmessages/net_stringcmd.h b/demboyz/netmessages/net_stringcmd.h new file mode 100644 index 0000000..4570af8 --- /dev/null +++ b/demboyz/netmessages/net_stringcmd.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_StringCmd + { + char command[1024]; + }; +} + +DECLARE_NET_HANDLERS(Net_StringCmd); diff --git a/demboyz/netmessages/net_tick.cpp b/demboyz/netmessages/net_tick.cpp new file mode 100644 index 0000000..63ed07a --- /dev/null +++ b/demboyz/netmessages/net_tick.cpp @@ -0,0 +1,37 @@ + +#include "net_tick.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool Net_Tick_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::Net_Tick* data) + { + data->tick = bitbuf.ReadUBitLong(32); + data->hostFrameTime = bitbuf.ReadUBitLong(16); + data->hostFrameTimeStdDev = bitbuf.ReadUBitLong(16); + return !bitbuf.IsOverflowed(); + } + + bool Net_Tick_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::Net_Tick* data) + { + bitbuf.WriteUBitLong(data->tick, 32); + bitbuf.WriteUBitLong(data->hostFrameTime, 16); + bitbuf.WriteUBitLong(data->hostFrameTimeStdDev, 16); + return !bitbuf.IsOverflowed(); + } + + bool Net_Tick_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Tick* data) + { + return true; + } + + bool Net_Tick_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::Net_Tick* data) + { + return true; + } + + void Net_Tick_ToString_Internal(std::ostringstream& out, NetMsg::Net_Tick* data) + { + out << "net_Tick: tick " << data->tick; + } +} diff --git a/demboyz/netmessages/net_tick.h b/demboyz/netmessages/net_tick.h new file mode 100644 index 0000000..48f0333 --- /dev/null +++ b/demboyz/netmessages/net_tick.h @@ -0,0 +1,18 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct Net_Tick + { + static const std::uint32_t NET_TICK_SCALEUP = 100000; + + std::int32_t tick; + std::uint16_t hostFrameTime; + std::uint16_t hostFrameTimeStdDev; + }; +} + +DECLARE_NET_HANDLERS(Net_Tick); diff --git a/demboyz/netmessages/netcontants.h b/demboyz/netmessages/netcontants.h new file mode 100644 index 0000000..abc1919 --- /dev/null +++ b/demboyz/netmessages/netcontants.h @@ -0,0 +1,46 @@ + +#pragma once + +enum constants +{ + // was 5 + NETMSG_TYPE_BITS = 6, // 2^NETMSG_TYPE_BITS > SVC_LASTMSG + + // was 96000 + NET_MAX_PAYLOAD = 288000, // largest message size in bytes + + // was 17 + NET_MAX_PAYLOAD_BITS = 19, // 2^NET_MAX_PAYLOAD_BITS > NET_MAX_PAYLOAD + + // table index is sent in log2(MAX_TABLES) bits + MAX_TABLES = 32, // Table id is 4 bits + + // How many bits to use to encode an edict. + MAX_EDICT_BITS = 11, // # of bits needed to represent max edicts + + // Max # of edicts in a level + MAX_EDICTS = (1 << MAX_EDICT_BITS), + MAX_DECAL_INDEX_BITS = 9, + SP_MODEL_INDEX_BITS = 11, + MAX_SERVER_CLASS_BITS = 9, + + MAX_EVENT_NAME_LENGTH = 32, + MAX_EVENT_BITS = 9, + MAX_EVENT_NUMBER = (1 << MAX_EVENT_BITS), + MAX_EVENT_BYTES = 1024, + + DELTASIZE_BITS = 20, // must be: 2^DELTASIZE_BITS > (NET_MAX_PAYLOAD * 8) + EVENT_INDEX_BITS = 8, + MAX_SOUND_INDEX_BITS = 13, + + MAX_USER_MSG_DATA = 255, + + SIGNONSTATE_NONE = 0, // no state yet, about to connect + SIGNONSTATE_CHALLENGE = 1, // client challenging server, all OOB packets + SIGNONSTATE_CONNECTED = 2, // client is connected to server, netchans ready + SIGNONSTATE_NEW = 3, // just got serverinfo and string tables + SIGNONSTATE_PRESPAWN = 4, // received signon buffers + SIGNONSTATE_SPAWN = 5, // ready to receive entity packets + SIGNONSTATE_FULL = 6, // we are fully connected, first non-delta packet received + SIGNONSTATE_CHANGELEVEL = 7 // server is changing level, please wait +}; diff --git a/demboyz/netmessages/nethandlers.h b/demboyz/netmessages/nethandlers.h new file mode 100644 index 0000000..44fbc10 --- /dev/null +++ b/demboyz/netmessages/nethandlers.h @@ -0,0 +1,88 @@ + +#pragma once + +#include +#include + +class bf_read; +class bf_write; +class JsonRead; +class JsonWrite; + +struct SourceGameContext +{ + int16_t protocol; +}; + +#if !defined(MAX_OSPATH) +#define MAX_OSPATH 260 // max length of a filesystem pathname +#endif + +#define DECLARE_NET_HANDLERS(msgname) \ + namespace NetHandlers \ + { \ + namespace \ + { \ + bool msgname##_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::##msgname* data); \ + bool msgname##_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::##msgname* data); \ + bool msgname##_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::##msgname* data); \ + bool msgname##_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::##msgname* data); \ + void msgname##_ToString_Internal(std::ostringstream& out, NetMsg::##msgname* data); \ + } \ + inline bool msgname##_BitRead(bf_read& bitbuf, SourceGameContext& context, void* data) \ + { \ + return msgname##_BitRead_Internal(bitbuf, context, reinterpret_cast(data)); \ + } \ + inline bool msgname##_BitWrite(bf_write& bitbuf, SourceGameContext& context, void* data) \ + { \ + return msgname##_BitWrite_Internal(bitbuf, context, reinterpret_cast(data)); \ + } \ + inline bool msgname##_JsonRead(JsonRead& jsonbuf, SourceGameContext& context, void* data) \ + { \ + return msgname##_JsonRead_Internal(jsonbuf, context, reinterpret_cast(data)); \ + } \ + inline bool msgname##_JsonWrite(JsonWrite& jsonbuf, SourceGameContext& context, void* data) \ + { \ + return msgname##_JsonWrite_Internal(jsonbuf, context, reinterpret_cast(data)); \ + } \ + inline void msgname##_ToString(std::ostringstream& out, void* data) \ + { \ + msgname##_ToString_Internal(out, reinterpret_cast(data)); \ + } \ + } + +#define DECLARE_NET_HANDLER_ARRAY(funcname) \ + { \ + &NetHandlers::Net_NOP_##funcname, \ + &NetHandlers::Net_Disconnect_##funcname, \ + &NetHandlers::Net_File_##funcname, \ + &NetHandlers::Net_Tick_##funcname, \ + &NetHandlers::Net_StringCmd_##funcname, \ + &NetHandlers::Net_SetConVar_##funcname, \ + &NetHandlers::Net_SignonState_##funcname, \ + &NetHandlers::SVC_Print_##funcname, \ + &NetHandlers::SVC_ServerInfo_##funcname, \ + &NetHandlers::SVC_SendTable_##funcname, \ + &NetHandlers::SVC_ClassInfo_##funcname, \ + &NetHandlers::SVC_SetPause_##funcname, \ + &NetHandlers::SVC_CreateStringTable_##funcname, \ + &NetHandlers::SVC_UpdateStringTable_##funcname, \ + &NetHandlers::SVC_VoiceInit_##funcname, \ + &NetHandlers::SVC_VoiceData_##funcname, \ + &NetHandlers::SVC_HLTV_##funcname, \ + &NetHandlers::SVC_Sounds_##funcname, \ + &NetHandlers::SVC_SetView_##funcname, \ + &NetHandlers::SVC_FixAngle_##funcname, \ + &NetHandlers::SVC_CrosshairAngle_##funcname, \ + &NetHandlers::SVC_BSPDecal_##funcname, \ + &NetHandlers::SVC_TerrainMod_##funcname, \ + &NetHandlers::SVC_UserMessage_##funcname, \ + &NetHandlers::SVC_EntityMessage_##funcname, \ + &NetHandlers::SVC_GameEvent_##funcname, \ + &NetHandlers::SVC_PacketEntities_##funcname, \ + &NetHandlers::SVC_TempEntities_##funcname, \ + &NetHandlers::SVC_Prefetch_##funcname, \ + &NetHandlers::SVC_Menu_##funcname, \ + &NetHandlers::SVC_GameEventList_##funcname, \ + &NetHandlers::SVC_GetCvarValue_##funcname \ + } diff --git a/demboyz/netmessages/netmath.h b/demboyz/netmessages/netmath.h new file mode 100644 index 0000000..95356b3 --- /dev/null +++ b/demboyz/netmessages/netmath.h @@ -0,0 +1,20 @@ + +#pragma once + +#include + +namespace math +{ + static size_t log2(size_t value) + { + size_t res = 0; + while (value >>= 1) + ++res; + return res; + } + + static size_t BitsToBytes(size_t bits) + { + return ((bits + 7) >> 3); + } +} diff --git a/demboyz/netmessages/netmessages.h b/demboyz/netmessages/netmessages.h new file mode 100644 index 0000000..0a39982 --- /dev/null +++ b/demboyz/netmessages/netmessages.h @@ -0,0 +1,105 @@ + +#pragma once + +#include + +#if !defined( MAX_OSPATH ) +#define MAX_OSPATH 260 // max length of a filesystem pathname +#endif + +#include "net_nop.h" +#include "net_disconnect.h" +#include "net_file.h" +#include "net_tick.h" +#include "net_stringcmd.h" +#include "net_setconvar.h" +#include "net_signonstate.h" +#include "svc_print.h" +#include "svc_serverinfo.h" +#include "svc_sendtable.h" +#include "svc_classinfo.h" +#include "svc_setpause.h" +#include "svc_createstringtable.h" +#include "svc_updatestringtable.h" +#include "svc_voiceinit.h" +#include "svc_voicedata.h" +#include "svc_hltv.h" +#include "svc_sounds.h" +#include "svc_setview.h" +#include "svc_fixangle.h" +#include "svc_crosshairangle.h" +#include "svc_bspdecal.h" +#include "svc_terrainmod.h" +#include "svc_usermessage.h" +#include "svc_entitymessage.h" +#include "svc_gameevent.h" +#include "svc_packetentities.h" +#include "svc_tempentities.h" +#include "svc_prefetch.h" +#include "svc_menu.h" +#include "svc_gameeventlist.h" +#include "svc_getcvarvalue.h" + +namespace NetMsg +{ + enum + { + net_NOP = 0, // nop command used for padding + net_Disconnect = 1, // disconnect, last message in connection + net_File = 2, // file transmission message request/deny + + net_Tick = 3, // send last world tick + net_StringCmd = 4, // a string command + net_SetConVar = 5, // sends one/multiple convar settings + net_SignonState = 6, // signals current signon state + + // + // server to client + // + + svc_Print = 7, // print text to console + svc_ServerInfo = 8, // first message from server about game, map etc + svc_SendTable = 9, // sends a sendtable description for a game class + svc_ClassInfo = 10, // Info about classes (first byte is a CLASSINFO_ define). + svc_SetPause = 11, // tells client if server paused or unpaused + + + svc_CreateStringTable = 12, // inits shared string tables + svc_UpdateStringTable = 13, // updates a string table + + svc_VoiceInit = 14, // inits used voice codecs & quality + svc_VoiceData = 15, // Voicestream data from the server + + //svc_HLTV = 16, // HLTV control messages + + svc_Sounds = 17, // starts playing sound + + svc_SetView = 18, // sets entity as point of view + svc_FixAngle = 19, // sets/corrects players viewangle + svc_CrosshairAngle = 20, // adjusts crosshair in auto aim mode to lock on traget + + svc_BSPDecal = 21, // add a static decal to the world BSP + + // NOTE: This is now unused! + // svc_TerrainMod = 22, // modification to the terrain/displacement + + // Message from server side to client side entity + svc_UserMessage = 23, // a game specific message + svc_EntityMessage = 24, // a message for an entity + svc_GameEvent = 25, // global game event fired + + svc_PacketEntities = 26, // non-delta compressed entities + + svc_TempEntities = 27, // non-reliable event object + + svc_Prefetch = 28, // only sound indices for now + + svc_Menu = 29, // display a menu from a plugin + + svc_GameEventList = 30, // list of known games events and fields + + svc_GetCvarValue = 31, // Server wants to know the value of a cvar on the client. + + SVC_LASTMSG = 31 // last known server messages + }; +} diff --git a/demboyz/netmessages/svc_bspdecal.cpp b/demboyz/netmessages/svc_bspdecal.cpp new file mode 100644 index 0000000..0d47ade --- /dev/null +++ b/demboyz/netmessages/svc_bspdecal.cpp @@ -0,0 +1,61 @@ + +#include "svc_bspdecal.h" +#include "bitbuf.h" +#include "netcontants.h" + +namespace NetHandlers +{ + bool SVC_BSPDecal_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data) + { + bitbuf.ReadBitVec3Coord(data->position); + data->decalTextureIndex = bitbuf.ReadUBitLong(MAX_DECAL_INDEX_BITS); + if (bitbuf.ReadOneBit() != 0) + { + data->entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS); + data->modelIndex = bitbuf.ReadUBitLong(SP_MODEL_INDEX_BITS); + } + else + { + data->entIndex = 0; + data->modelIndex = 0; + } + data->lowPriority = bitbuf.ReadOneBit() != 0; + return !bitbuf.IsOverflowed(); + } + + bool SVC_BSPDecal_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data) + { + bitbuf.WriteBitVec3Coord(data->position); + bitbuf.WriteUBitLong(data->decalTextureIndex, MAX_DECAL_INDEX_BITS); + if (data->entIndex != 0) + { + bitbuf.WriteOneBit(1); + bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS); + bitbuf.WriteUBitLong(data->modelIndex, SP_MODEL_INDEX_BITS); + } + else + { + bitbuf.WriteOneBit(0); + } + bitbuf.WriteOneBit(data->lowPriority); + return !bitbuf.IsOverflowed(); + } + + bool SVC_BSPDecal_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data) + { + return true; + } + + bool SVC_BSPDecal_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data) + { + return true; + } + + void SVC_BSPDecal_ToString_Internal(std::ostringstream& out, NetMsg::SVC_BSPDecal* data) + { + out << "svc_BSPDecal: tex " << data->decalTextureIndex + << ", ent " << data->entIndex + << ", mod " << data->modelIndex + << " lowpriority " << data->lowPriority; + } +} diff --git a/demboyz/netmessages/svc_bspdecal.h b/demboyz/netmessages/svc_bspdecal.h new file mode 100644 index 0000000..1a59beb --- /dev/null +++ b/demboyz/netmessages/svc_bspdecal.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "nethandlers.h" +#include "vector.h" + +namespace NetMsg +{ + struct SVC_BSPDecal + { + Vector position; + uint16_t decalTextureIndex; + uint16_t entIndex; + uint16_t modelIndex; + bool lowPriority; + }; +} + +DECLARE_NET_HANDLERS(SVC_BSPDecal); diff --git a/demboyz/netmessages/svc_classinfo.cpp b/demboyz/netmessages/svc_classinfo.cpp new file mode 100644 index 0000000..df53447 --- /dev/null +++ b/demboyz/netmessages/svc_classinfo.cpp @@ -0,0 +1,62 @@ + +#include "svc_classinfo.h" +#include "bitbuf.h" +#include "netmath.h" + +using class_t = NetMsg::SVC_ClassInfo::class_t; + +namespace NetHandlers +{ + bool SVC_ClassInfo_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data) + { + const int16_t numServerClasses = bitbuf.ReadShort(); + const bool createOnClient = bitbuf.ReadOneBit() != 0; + data->numServerClasses = numServerClasses; + data->createOnClient = createOnClient; + if (!createOnClient) + { + const int numServerClassBits = math::log2(numServerClasses) + 1; + data->serverClasses.resize(numServerClasses); + for (class_t& serverClass : data->serverClasses) + { + serverClass.classID = bitbuf.ReadUBitLong(numServerClassBits); + bitbuf.ReadString(serverClass.className, sizeof(serverClass.className)); + bitbuf.ReadString(serverClass.dataTableName, sizeof(serverClass.dataTableName)); + } + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_ClassInfo_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data) + { + bitbuf.WriteShort(data->numServerClasses); + bitbuf.WriteOneBit(data->createOnClient); + if (!data->createOnClient) + { + const int numServerClassBits = math::log2(data->numServerClasses) + 1; + for (class_t& serverClass : data->serverClasses) + { + bitbuf.WriteUBitLong(serverClass.classID, numServerClassBits); + bitbuf.WriteString(serverClass.className); + bitbuf.WriteString(serverClass.dataTableName); + } + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_ClassInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data) + { + return true; + } + + bool SVC_ClassInfo_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data) + { + return true; + } + + void SVC_ClassInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ClassInfo* data) + { + out << "svc_ClassInfo: num " << data->numServerClasses + << ", " << (data->createOnClient ? "use client classes" : "full update"); + } +} diff --git a/demboyz/netmessages/svc_classinfo.h b/demboyz/netmessages/svc_classinfo.h new file mode 100644 index 0000000..c82fbfe --- /dev/null +++ b/demboyz/netmessages/svc_classinfo.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_ClassInfo + { + typedef struct class_s + { + uint32_t classID; + char className[256]; + char dataTableName[256]; + } class_t; + + int16_t numServerClasses; + bool createOnClient; + std::vector serverClasses; + }; +} + +DECLARE_NET_HANDLERS(SVC_ClassInfo); diff --git a/demboyz/netmessages/svc_createstringtable.cpp b/demboyz/netmessages/svc_createstringtable.cpp new file mode 100644 index 0000000..f05b9f9 --- /dev/null +++ b/demboyz/netmessages/svc_createstringtable.cpp @@ -0,0 +1,104 @@ + +#include "svc_createstringtable.h" +#include "bitbuf.h" +#include "netmath.h" +#include "netcontants.h" + +namespace NetHandlers +{ + bool SVC_CreateStringTable_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) + { + if (bitbuf.PeekUBitLong(8) == ':') + { + data->isFileNames = true; + bitbuf.ReadByte(); + } + else + { + data->isFileNames = false; + } + bitbuf.ReadString(data->tableName, sizeof(data->tableName)); + data->maxEntries = bitbuf.ReadWord(); + data->numEntries = bitbuf.ReadUBitLong(math::log2(data->maxEntries) + 1); + if (context.protocol > 23) + { + data->dataLengthInBits = bitbuf.ReadVarInt32(); + } + else + { + data->dataLengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS + 1); + } + data->isUserDataFixedSize = bitbuf.ReadOneBit() != 0; + if (data->isUserDataFixedSize) + { + data->userDataSize = bitbuf.ReadUBitLong(12); + data->userDataSizeBits = bitbuf.ReadUBitLong(4); + } + else + { + data->userDataSize = 0; + data->userDataSizeBits = 0; + } + if (context.protocol > 14) + { + data->unk1 = bitbuf.ReadOneBit() != 0; + } + else + { + data->unk1 = false; + } + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_CreateStringTable_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) + { + if (data->isFileNames) + { + bitbuf.WriteByte(':'); + } + bitbuf.WriteString(data->tableName); + bitbuf.WriteWord(data->maxEntries); + bitbuf.WriteUBitLong(data->numEntries, math::log2(data->maxEntries) + 1); + if (context.protocol > 23) + { + bitbuf.WriteVarInt32(data->dataLengthInBits); + } + else + { + bitbuf.WriteUBitLong(data->dataLengthInBits, NET_MAX_PAYLOAD_BITS + 1); + } + bitbuf.WriteOneBit(data->isUserDataFixedSize); + if (data->isUserDataFixedSize) + { + bitbuf.WriteUBitLong(data->userDataSize, 12); + bitbuf.WriteUBitLong(data->userDataSizeBits, 4); + } + if (context.protocol > 14) + { + bitbuf.WriteOneBit(data->unk1); + } + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_CreateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) + { + return true; + } + + bool SVC_CreateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data) + { + return true; + } + + void SVC_CreateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CreateStringTable* data) + { + out << "svc_CreateStringTable: table " << data->tableName + << ", entries " << data->numEntries + << ", bytes " << math::BitsToBytes(data->dataLengthInBits) + << " userdatasize " << data->userDataSize + << " userdatabits " << data->userDataSizeBits; + } +} diff --git a/demboyz/netmessages/svc_createstringtable.h b/demboyz/netmessages/svc_createstringtable.h new file mode 100644 index 0000000..bd10bc2 --- /dev/null +++ b/demboyz/netmessages/svc_createstringtable.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_CreateStringTable + { + bool isFileNames; + char tableName[256]; + uint16_t maxEntries; + uint16_t numEntries; + uint32_t dataLengthInBits; + bool isUserDataFixedSize; + uint16_t userDataSize; + uint8_t userDataSizeBits; + bool unk1; + std::unique_ptr data; + }; +} + +DECLARE_NET_HANDLERS(SVC_CreateStringTable); diff --git a/demboyz/netmessages/svc_crosshairangle.cpp b/demboyz/netmessages/svc_crosshairangle.cpp new file mode 100644 index 0000000..8191a3b --- /dev/null +++ b/demboyz/netmessages/svc_crosshairangle.cpp @@ -0,0 +1,44 @@ + +#include "svc_crosshairangle.h" +#include "bitbuf.h" +#include + +namespace NetHandlers +{ + bool SVC_CrosshairAngle_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) + { + data->x = bitbuf.ReadBitAngle(16); + data->y = bitbuf.ReadBitAngle(16); + data->z = bitbuf.ReadBitAngle(16); + return !bitbuf.IsOverflowed(); + } + + bool SVC_CrosshairAngle_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) + { + bitbuf.WriteBitAngle(data->x, 16); + bitbuf.WriteBitAngle(data->y, 16); + bitbuf.WriteBitAngle(data->z, 16); + return !bitbuf.IsOverflowed(); + } + + bool SVC_CrosshairAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) + { + return true; + } + + bool SVC_CrosshairAngle_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data) + { + return true; + } + + void SVC_CrosshairAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CrosshairAngle* data) + { + const std::streamsize oldPrecision = out.precision(); + out << "svc_CrosshairAngle:" + << std::setprecision(1) << std::fixed + << " (" << data->x + << " " << data->y + << " " << data->z << ")" + << std::defaultfloat << std::setprecision(oldPrecision); + } +} diff --git a/demboyz/netmessages/svc_crosshairangle.h b/demboyz/netmessages/svc_crosshairangle.h new file mode 100644 index 0000000..06a384e --- /dev/null +++ b/demboyz/netmessages/svc_crosshairangle.h @@ -0,0 +1,16 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_CrosshairAngle + { + float x; + float y; + float z; + }; +} + +DECLARE_NET_HANDLERS(SVC_CrosshairAngle); diff --git a/demboyz/netmessages/svc_entitymessage.cpp b/demboyz/netmessages/svc_entitymessage.cpp new file mode 100644 index 0000000..ba6a6e6 --- /dev/null +++ b/demboyz/netmessages/svc_entitymessage.cpp @@ -0,0 +1,44 @@ + +#include "svc_entitymessage.h" +#include "bitbuf.h" +#include "netcontants.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_EntityMessage_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data) + { + data->entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS); + data->classID = bitbuf.ReadUBitLong(MAX_SERVER_CLASS_BITS); + data->dataLengthInBits = bitbuf.ReadUBitLong(11); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_EntityMessage_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data) + { + bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS); + bitbuf.WriteUBitLong(data->classID, MAX_SERVER_CLASS_BITS); + bitbuf.WriteUBitLong(data->dataLengthInBits, 11); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_EntityMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data) + { + return true; + } + + bool SVC_EntityMessage_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data) + { + return true; + } + + void SVC_EntityMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_EntityMessage* data) + { + out << "svc_EntityMessage: entity " << data->entIndex + << ", class " << data->classID + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_entitymessage.h b/demboyz/netmessages/svc_entitymessage.h new file mode 100644 index 0000000..e941ed6 --- /dev/null +++ b/demboyz/netmessages/svc_entitymessage.h @@ -0,0 +1,18 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_EntityMessage + { + std::unique_ptr data; + uint16_t dataLengthInBits; + uint16_t entIndex; + uint16_t classID; + }; +} + +DECLARE_NET_HANDLERS(SVC_EntityMessage); diff --git a/demboyz/netmessages/svc_fixangle.cpp b/demboyz/netmessages/svc_fixangle.cpp new file mode 100644 index 0000000..f6f3a87 --- /dev/null +++ b/demboyz/netmessages/svc_fixangle.cpp @@ -0,0 +1,46 @@ + +#include "svc_fixangle.h" +#include "bitbuf.h" +#include + +namespace NetHandlers +{ + bool SVC_FixAngle_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data) + { + data->relative = bitbuf.ReadOneBit() != 0; + data->x = bitbuf.ReadBitAngle(16); + data->y = bitbuf.ReadBitAngle(16); + data->z = bitbuf.ReadBitAngle(16); + return !bitbuf.IsOverflowed(); + } + + bool SVC_FixAngle_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data) + { + bitbuf.WriteOneBit(data->relative); + bitbuf.WriteBitAngle(data->x, 16); + bitbuf.WriteBitAngle(data->y, 16); + bitbuf.WriteBitAngle(data->z, 16); + return !bitbuf.IsOverflowed(); + } + + bool SVC_FixAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data) + { + return true; + } + + bool SVC_FixAngle_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data) + { + return true; + } + + void SVC_FixAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_FixAngle* data) + { + const std::streamsize oldPrecision = out.precision(); + out << "svc_FixAngle: " << (data->relative ? "relative" : "absolute") + << std::setprecision(1) << std::fixed + << " " << data->x + << " " << data->y + << " " << data->z + << std::defaultfloat << std::setprecision(oldPrecision); + } +} diff --git a/demboyz/netmessages/svc_fixangle.h b/demboyz/netmessages/svc_fixangle.h new file mode 100644 index 0000000..b212c48 --- /dev/null +++ b/demboyz/netmessages/svc_fixangle.h @@ -0,0 +1,17 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_FixAngle + { + bool relative; + float x; + float y; + float z; + }; +} + +DECLARE_NET_HANDLERS(SVC_FixAngle); diff --git a/demboyz/netmessages/svc_gameevent.cpp b/demboyz/netmessages/svc_gameevent.cpp new file mode 100644 index 0000000..dc84276 --- /dev/null +++ b/demboyz/netmessages/svc_gameevent.cpp @@ -0,0 +1,38 @@ + +#include "svc_gameevent.h" +#include "bitbuf.h" +#include "netcontants.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_GameEvent_BitRead_Internal(bf_read& 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); + return !bitbuf.IsOverflowed(); + } + + bool SVC_GameEvent_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data) + { + bitbuf.WriteUBitLong(data->dataLengthInBits, 11); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_GameEvent_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data) + { + return true; + } + + bool SVC_GameEvent_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data) + { + return true; + } + + void SVC_GameEvent_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEvent* data) + { + out << "svc_GameEvent: bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_gameevent.h b/demboyz/netmessages/svc_gameevent.h new file mode 100644 index 0000000..112ca72 --- /dev/null +++ b/demboyz/netmessages/svc_gameevent.h @@ -0,0 +1,16 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_GameEvent + { + std::unique_ptr data; + uint16_t dataLengthInBits; + }; +} + +DECLARE_NET_HANDLERS(SVC_GameEvent); diff --git a/demboyz/netmessages/svc_gameeventlist.cpp b/demboyz/netmessages/svc_gameeventlist.cpp new file mode 100644 index 0000000..bd5e573 --- /dev/null +++ b/demboyz/netmessages/svc_gameeventlist.cpp @@ -0,0 +1,64 @@ + +#include "svc_gameeventlist.h" +#include "bitbuf.h" +#include "netcontants.h" +#include "netmath.h" + +using EventDescriptor = NetMsg::SVC_GameEventList::EventDescriptor; +using EventValue = NetMsg::SVC_GameEventList::EventValue; + +namespace NetHandlers +{ + bool SVC_GameEventList_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data) + { + data->eventDescriptors.resize(bitbuf.ReadUBitLong(MAX_EVENT_BITS)); + data->dataLengthInBits = bitbuf.ReadUBitLong(20); + for (EventDescriptor& event : data->eventDescriptors) + { + event.id = bitbuf.ReadUBitLong(MAX_EVENT_BITS); + bitbuf.ReadString(event.name, sizeof(event.name)); + EventValue value; + while ((value.type = bitbuf.ReadUBitLong(3)) > 0) + { + bitbuf.ReadString(value.name, sizeof(value.name)); + event.values.push_back(value); + } + event.values.shrink_to_fit(); + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_GameEventList_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data) + { + bitbuf.WriteUBitLong(data->eventDescriptors.size(), MAX_EVENT_BITS); + bitbuf.WriteUBitLong(data->dataLengthInBits, 20); + for (EventDescriptor& event : data->eventDescriptors) + { + bitbuf.WriteUBitLong(event.id, MAX_EVENT_BITS); + bitbuf.WriteString(event.name); + for (EventValue& value : event.values) + { + bitbuf.WriteUBitLong(value.type, 3); + bitbuf.WriteString(value.name); + } + bitbuf.WriteUBitLong(0, 3); + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_GameEventList_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data) + { + return true; + } + + bool SVC_GameEventList_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data) + { + return true; + } + + void SVC_GameEventList_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEventList* data) + { + out << "svc_GameEventList: number " << data->eventDescriptors.size() + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_gameeventlist.h b/demboyz/netmessages/svc_gameeventlist.h new file mode 100644 index 0000000..d9198c7 --- /dev/null +++ b/demboyz/netmessages/svc_gameeventlist.h @@ -0,0 +1,29 @@ + +#pragma once + +#include "nethandlers.h" +#include "netcontants.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; + }; + + uint16_t dataLengthInBits; + std::vector eventDescriptors; + }; +} + +DECLARE_NET_HANDLERS(SVC_GameEventList); diff --git a/demboyz/netmessages/svc_getcvarvalue.cpp b/demboyz/netmessages/svc_getcvarvalue.cpp new file mode 100644 index 0000000..37abe3a --- /dev/null +++ b/demboyz/netmessages/svc_getcvarvalue.cpp @@ -0,0 +1,36 @@ + +#include "svc_getcvarvalue.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool SVC_GetCvarValue_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) + { + data->cookie = bitbuf.ReadSBitLong(32); + bitbuf.ReadString(data->cvarName, sizeof(data->cvarName)); + return !bitbuf.IsOverflowed(); + } + + bool SVC_GetCvarValue_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) + { + bitbuf.WriteSBitLong(data->cookie, 32); + bitbuf.WriteString(data->cvarName); + return !bitbuf.IsOverflowed(); + } + + bool SVC_GetCvarValue_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) + { + return true; + } + + bool SVC_GetCvarValue_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data) + { + return true; + } + + void SVC_GetCvarValue_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GetCvarValue* data) + { + out << "svc_GetCvarValue: cvar: " << data->cvarName + << ", cookie: " << data->cookie; + } +} diff --git a/demboyz/netmessages/svc_getcvarvalue.h b/demboyz/netmessages/svc_getcvarvalue.h new file mode 100644 index 0000000..b0e9dbf --- /dev/null +++ b/demboyz/netmessages/svc_getcvarvalue.h @@ -0,0 +1,15 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_GetCvarValue + { + int32_t cookie; + char cvarName[256]; + }; +} + +DECLARE_NET_HANDLERS(SVC_GetCvarValue); diff --git a/demboyz/netmessages/svc_hltv.cpp b/demboyz/netmessages/svc_hltv.cpp new file mode 100644 index 0000000..5f61704 --- /dev/null +++ b/demboyz/netmessages/svc_hltv.cpp @@ -0,0 +1,35 @@ + +#include "svc_hltv.h" +#include + +namespace NetHandlers +{ + bool SVC_HLTV_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_HLTV* data) + { + assert(false); + return true; + } + + bool SVC_HLTV_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_HLTV* data) + { + assert(false); + return true; + } + + bool SVC_HLTV_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_HLTV* data) + { + assert(false); + return true; + } + + bool SVC_HLTV_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_HLTV* data) + { + assert(false); + return true; + } + + void SVC_HLTV_ToString_Internal(std::ostringstream& out, NetMsg::SVC_HLTV* data) + { + out << "svc_HLTV"; + } +} diff --git a/demboyz/netmessages/svc_hltv.h b/demboyz/netmessages/svc_hltv.h new file mode 100644 index 0000000..a2141e6 --- /dev/null +++ b/demboyz/netmessages/svc_hltv.h @@ -0,0 +1,13 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_HLTV + { + }; +} + +DECLARE_NET_HANDLERS(SVC_HLTV); diff --git a/demboyz/netmessages/svc_menu.cpp b/demboyz/netmessages/svc_menu.cpp new file mode 100644 index 0000000..a99bce7 --- /dev/null +++ b/demboyz/netmessages/svc_menu.cpp @@ -0,0 +1,56 @@ + +#include "svc_menu.h" +#include "bitbuf.h" + +using DialogType = NetMsg::SVC_Menu::DialogType; + +#define KEYVALUES_TOKEN_SIZE 1024 + +static const char* KeyValuesBin_GetName(uint8_t* data, size_t dataLength) +{ + if (dataLength <= 2) + { + return nullptr; + } + return reinterpret_cast(data + 1); +} + +namespace NetHandlers +{ + bool SVC_Menu_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_Menu* data) + { + data->type = static_cast(bitbuf.ReadShort()); + data->dataLengthInBytes = bitbuf.ReadWord(); + data->menuBinaryKeyValues.reset(new uint8_t[data->dataLengthInBytes]); + bitbuf.ReadBytes(data->menuBinaryKeyValues.get(), data->dataLengthInBytes); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Menu_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_Menu* data) + { + bitbuf.WriteShort(static_cast(data->type)); + bitbuf.WriteWord(data->dataLengthInBytes); + bitbuf.WriteBytes(data->menuBinaryKeyValues.get(), data->dataLengthInBytes); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Menu_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Menu* data) + { + return true; + } + + bool SVC_Menu_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_Menu* data) + { + return true; + } + + void SVC_Menu_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Menu* data) + { + // binary keyvalues in form [type][name][value] + // [char][cstr][type] + const char* name = KeyValuesBin_GetName(data->menuBinaryKeyValues.get(), data->dataLengthInBytes); + out << "svc_Menu: " << static_cast(data->type) + << " \"" << (name ? name : "No KeyValues") + << "\" (len:" << data->dataLengthInBytes << ")"; + } +} diff --git a/demboyz/netmessages/svc_menu.h b/demboyz/netmessages/svc_menu.h new file mode 100644 index 0000000..5be6054 --- /dev/null +++ b/demboyz/netmessages/svc_menu.h @@ -0,0 +1,32 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_Menu + { + enum class DialogType : uint16_t + { + // just an on screen message + DIALOG_MSG = 0, + // an options menu + DIALOG_MENU, + // a richtext dialog + DIALOG_TEXT, + // an entry box + DIALOG_ENTRY, + // Ask the client to connect to a specified IP address. + // Only the "time" and "title" keys are used. + DIALOG_ASKCONNECT + }; + + std::unique_ptr menuBinaryKeyValues; + uint16_t dataLengthInBytes; + DialogType type; + }; +} + +DECLARE_NET_HANDLERS(SVC_Menu); diff --git a/demboyz/netmessages/svc_packetentities.cpp b/demboyz/netmessages/svc_packetentities.cpp new file mode 100644 index 0000000..5b6b530 --- /dev/null +++ b/demboyz/netmessages/svc_packetentities.cpp @@ -0,0 +1,63 @@ + +#include "svc_packetentities.h" +#include "bitbuf.h" +#include "netcontants.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_PacketEntities_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data) + { + data->maxEntries = bitbuf.ReadUBitLong(MAX_EDICT_BITS); + data->isDelta = bitbuf.ReadOneBit() != 0; + if (data->isDelta) + { + data->deltaFromTick = bitbuf.ReadLong(); + } + else + { + data->deltaFromTick = -1; + } + data->baselineIndex = bitbuf.ReadUBitLong(1); + data->numUpdatedEntries = bitbuf.ReadUBitLong(MAX_EDICT_BITS); + data->dataLengthInBits = bitbuf.ReadUBitLong(DELTASIZE_BITS); + data->updateBaseline = bitbuf.ReadOneBit() != 0; + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_PacketEntities_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data) + { + bitbuf.WriteUBitLong(data->maxEntries, MAX_EDICT_BITS); + if (data->isDelta) + { + bitbuf.WriteLong(data->deltaFromTick); + } + bitbuf.WriteUBitLong(data->baselineIndex, 1); + bitbuf.WriteUBitLong(data->numUpdatedEntries, MAX_EDICT_BITS); + bitbuf.WriteUBitLong(data->dataLengthInBits, DELTASIZE_BITS); + bitbuf.WriteOneBit(data->updateBaseline); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_PacketEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data) + { + return true; + } + + bool SVC_PacketEntities_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data) + { + return true; + } + + void SVC_PacketEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_PacketEntities* data) + { + out << "svc_PacketEntities: delta " << data->deltaFromTick + << ", max " << data->maxEntries + << ", changed " << data->numUpdatedEntries + << "," << (data->updateBaseline ? " BL update," : "") + << " bytes" << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_packetentities.h b/demboyz/netmessages/svc_packetentities.h new file mode 100644 index 0000000..d0d4045 --- /dev/null +++ b/demboyz/netmessages/svc_packetentities.h @@ -0,0 +1,22 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_PacketEntities + { + std::unique_ptr data; + uint32_t dataLengthInBits; + uint32_t deltaFromTick; + uint16_t maxEntries; + uint16_t numUpdatedEntries; + uint8_t baselineIndex; + bool updateBaseline; + bool isDelta; + }; +} + +DECLARE_NET_HANDLERS(SVC_PacketEntities); diff --git a/demboyz/netmessages/svc_prefetch.cpp b/demboyz/netmessages/svc_prefetch.cpp new file mode 100644 index 0000000..720eb8c --- /dev/null +++ b/demboyz/netmessages/svc_prefetch.cpp @@ -0,0 +1,36 @@ + +#include "svc_prefetch.h" +#include "bitbuf.h" +#include "netcontants.h" + +namespace NetHandlers +{ + bool SVC_Prefetch_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data) + { + data->type = NetMsg::SVC_Prefetch::SOUND; + data->soundIndex = bitbuf.ReadUBitLong(MAX_SOUND_INDEX_BITS); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Prefetch_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data) + { + bitbuf.WriteUBitLong(data->soundIndex, MAX_SOUND_INDEX_BITS); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Prefetch_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data) + { + return true; + } + + bool SVC_Prefetch_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data) + { + return true; + } + + void SVC_Prefetch_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Prefetch* data) + { + out << "svc_Prefetch: type " << data->type + << " index " << data->soundIndex; + } +} diff --git a/demboyz/netmessages/svc_prefetch.h b/demboyz/netmessages/svc_prefetch.h new file mode 100644 index 0000000..f53918e --- /dev/null +++ b/demboyz/netmessages/svc_prefetch.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_Prefetch + { + enum Types + { + SOUND = 0 + }; + uint16_t type; + uint16_t soundIndex; + }; +} + +DECLARE_NET_HANDLERS(SVC_Prefetch); diff --git a/demboyz/netmessages/svc_print.cpp b/demboyz/netmessages/svc_print.cpp new file mode 100644 index 0000000..408116f --- /dev/null +++ b/demboyz/netmessages/svc_print.cpp @@ -0,0 +1,33 @@ + +#include "svc_print.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool SVC_Print_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_Print* data) + { + bitbuf.ReadString(data->text, sizeof(data->text)); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Print_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_Print* data) + { + bitbuf.WriteString(data->text); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Print_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Print* data) + { + return true; + } + + bool SVC_Print_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_Print* data) + { + return true; + } + + void SVC_Print_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Print* data) + { + out << "svc_Print: \"" << data->text << '"'; + } +} diff --git a/demboyz/netmessages/svc_print.h b/demboyz/netmessages/svc_print.h new file mode 100644 index 0000000..6554f4e --- /dev/null +++ b/demboyz/netmessages/svc_print.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_Print + { + char text[2048]; + }; +} + +DECLARE_NET_HANDLERS(SVC_Print); diff --git a/demboyz/netmessages/svc_sendtable.cpp b/demboyz/netmessages/svc_sendtable.cpp new file mode 100644 index 0000000..adcbd30 --- /dev/null +++ b/demboyz/netmessages/svc_sendtable.cpp @@ -0,0 +1,40 @@ + +#include "svc_sendtable.h" +#include "bitbuf.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_SendTable_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data) + { + data->needsDecoder = bitbuf.ReadOneBit() != 0; + data->dataLengthInBits = bitbuf.ReadShort(); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_SendTable_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data) + { + bitbuf.WriteOneBit(data->needsDecoder); + bitbuf.WriteShort(data->dataLengthInBits); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_SendTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data) + { + return true; + } + + bool SVC_SendTable_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data) + { + return true; + } + + void SVC_SendTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SendTable* data) + { + out << "svc_SendTable: needs Decoder " << (data->needsDecoder ? "yes" : "no") + << ",bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_sendtable.h b/demboyz/netmessages/svc_sendtable.h new file mode 100644 index 0000000..b17cef5 --- /dev/null +++ b/demboyz/netmessages/svc_sendtable.h @@ -0,0 +1,17 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_SendTable + { + bool needsDecoder; + int16_t dataLengthInBits; + std::unique_ptr data; + }; +} + +DECLARE_NET_HANDLERS(SVC_SendTable); diff --git a/demboyz/netmessages/svc_serverinfo.cpp b/demboyz/netmessages/svc_serverinfo.cpp new file mode 100644 index 0000000..7d223eb --- /dev/null +++ b/demboyz/netmessages/svc_serverinfo.cpp @@ -0,0 +1,83 @@ + +#include "svc_serverinfo.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool SVC_ServerInfo_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data) + { + data->protocol = bitbuf.ReadShort(); + data->serverCount = bitbuf.ReadLong(); + data->isHLTV = bitbuf.ReadOneBit() != 0; + data->isDedicated = bitbuf.ReadOneBit() != 0; + data->clientCRC = bitbuf.ReadLong(); + data->maxClasses = bitbuf.ReadWord(); + if (context.protocol <= 17) + { + data->mapCRC = bitbuf.ReadLong(); + } + else + { + bitbuf.ReadBytes(data->unk1, sizeof(data->unk1)); + } + data->playerSlot = bitbuf.ReadByte(); + data->maxClients = bitbuf.ReadByte(); + data->tickInterval = bitbuf.ReadFloat(); + data->os = bitbuf.ReadChar(); + bitbuf.ReadString(data->gameDir, sizeof(data->gameDir)); + bitbuf.ReadString(data->mapName, sizeof(data->mapName)); + bitbuf.ReadString(data->skyName, sizeof(data->skyName)); + bitbuf.ReadString(data->hostName, sizeof(data->hostName)); + if (context.protocol > 15) + { + data->unk2 = bitbuf.ReadOneBit() != 0; + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_ServerInfo_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data) + { + bitbuf.WriteShort(data->protocol); + bitbuf.WriteLong(data->serverCount); + bitbuf.WriteOneBit(data->isHLTV); + bitbuf.WriteOneBit(data->isDedicated); + bitbuf.WriteLong(data->clientCRC); + bitbuf.WriteWord(data->maxClasses); + if (context.protocol <= 17) + { + bitbuf.WriteLong(data->mapCRC); + } + else + { + bitbuf.WriteBytes(data->unk1, sizeof(data->unk1)); + } + bitbuf.WriteByte(data->playerSlot); + bitbuf.WriteByte(data->maxClients); + bitbuf.WriteFloat(data->tickInterval); + bitbuf.WriteChar(data->os); + bitbuf.WriteString(data->gameDir); + bitbuf.WriteString(data->mapName); + bitbuf.WriteString(data->skyName); + bitbuf.WriteString(data->hostName); + if (context.protocol > 15) + { + bitbuf.WriteOneBit(data->unk2); + } + return !bitbuf.IsOverflowed(); + } + + bool SVC_ServerInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data) + { + return true; + } + + bool SVC_ServerInfo_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data) + { + return true; + } + + void SVC_ServerInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ServerInfo* data) + { + out << "svc_ServerInfo: game \"" << data->gameDir << "\", map \"" << data->mapName << "\", max " << data->maxClients; + } +} diff --git a/demboyz/netmessages/svc_serverinfo.h b/demboyz/netmessages/svc_serverinfo.h new file mode 100644 index 0000000..632933d --- /dev/null +++ b/demboyz/netmessages/svc_serverinfo.h @@ -0,0 +1,30 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_ServerInfo + { + int16_t protocol; // protocol version + uint32_t serverCount; // number of changelevels since server start + bool isHLTV; // HLTV server ? + bool isDedicated; // dedicated server ? + uint32_t clientCRC; // client.dll CRC server is using + uint16_t maxClasses; // max number of server classes + uint32_t mapCRC; // server map CRC + uint8_t unk1[16]; + uint8_t playerSlot; // our client slot number + uint8_t maxClients; // max number of clients on server + float tickInterval; // server tick interval + char os; // 'l' = linux, 'w' = Win32 + char gameDir[MAX_OSPATH]; // game directory eg "tf2" + char mapName[MAX_OSPATH]; // name of current map + char skyName[MAX_OSPATH]; // name of current skybox + char hostName[MAX_OSPATH]; // host name + bool unk2; + }; +} + +DECLARE_NET_HANDLERS(SVC_ServerInfo); diff --git a/demboyz/netmessages/svc_setpause.cpp b/demboyz/netmessages/svc_setpause.cpp new file mode 100644 index 0000000..267b8df --- /dev/null +++ b/demboyz/netmessages/svc_setpause.cpp @@ -0,0 +1,33 @@ + +#include "svc_setpause.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool SVC_SetPause_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data) + { + data->isPaused = bitbuf.ReadOneBit() != 0; + return !bitbuf.IsOverflowed(); + } + + bool SVC_SetPause_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data) + { + bitbuf.WriteOneBit(data->isPaused); + return !bitbuf.IsOverflowed(); + } + + bool SVC_SetPause_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data) + { + return true; + } + + bool SVC_SetPause_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data) + { + return true; + } + + void SVC_SetPause_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetPause* data) + { + out << "svc_SetPause: " << (data->isPaused ? "paused" : "unpaused"); + } +} diff --git a/demboyz/netmessages/svc_setpause.h b/demboyz/netmessages/svc_setpause.h new file mode 100644 index 0000000..f645d3e --- /dev/null +++ b/demboyz/netmessages/svc_setpause.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_SetPause + { + bool isPaused; + }; +} + +DECLARE_NET_HANDLERS(SVC_SetPause); diff --git a/demboyz/netmessages/svc_setview.cpp b/demboyz/netmessages/svc_setview.cpp new file mode 100644 index 0000000..3375f7a --- /dev/null +++ b/demboyz/netmessages/svc_setview.cpp @@ -0,0 +1,34 @@ + +#include "svc_setview.h" +#include "bitbuf.h" +#include "netcontants.h" + +namespace NetHandlers +{ + bool SVC_SetView_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_SetView* data) + { + data->entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS); + return !bitbuf.IsOverflowed(); + } + + bool SVC_SetView_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_SetView* data) + { + bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS); + return !bitbuf.IsOverflowed(); + } + + bool SVC_SetView_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetView* data) + { + return true; + } + + bool SVC_SetView_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetView* data) + { + return true; + } + + void SVC_SetView_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetView* data) + { + out << "svc_SetView: view entity " << data->entIndex; + } +} diff --git a/demboyz/netmessages/svc_setview.h b/demboyz/netmessages/svc_setview.h new file mode 100644 index 0000000..e4ba4f7 --- /dev/null +++ b/demboyz/netmessages/svc_setview.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_SetView + { + uint16_t entIndex; + }; +} + +DECLARE_NET_HANDLERS(SVC_SetView); diff --git a/demboyz/netmessages/svc_sounds.cpp b/demboyz/netmessages/svc_sounds.cpp new file mode 100644 index 0000000..379e3c7 --- /dev/null +++ b/demboyz/netmessages/svc_sounds.cpp @@ -0,0 +1,59 @@ + +#include "svc_sounds.h" +#include "bitbuf.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_Sounds_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data) + { + data->reliableSound = bitbuf.ReadOneBit() != 0; + if (data->reliableSound) + { + data->numSounds = 1; + data->dataLengthInBits = bitbuf.ReadUBitLong(8); + } + else + { + data->numSounds = bitbuf.ReadUBitLong(8); + data->dataLengthInBits = bitbuf.ReadUBitLong(16); + } + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Sounds_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data) + { + if (data->reliableSound) + { + bitbuf.WriteOneBit(1); + bitbuf.WriteUBitLong(data->dataLengthInBits, 8); + } + else + { + bitbuf.WriteOneBit(0); + bitbuf.WriteUBitLong(data->numSounds, 8); + bitbuf.WriteUBitLong(data->dataLengthInBits, 16); + } + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_Sounds_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data) + { + return true; + } + + bool SVC_Sounds_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data) + { + return true; + } + + void SVC_Sounds_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Sounds* data) + { + out << "svc_Sounds: number " << data->numSounds + << (data->reliableSound ? ", reliable" : "") + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_sounds.h b/demboyz/netmessages/svc_sounds.h new file mode 100644 index 0000000..8aa3877 --- /dev/null +++ b/demboyz/netmessages/svc_sounds.h @@ -0,0 +1,18 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_Sounds + { + bool reliableSound; + uint8_t numSounds; + uint16_t dataLengthInBits; + std::unique_ptr data; + }; +} + +DECLARE_NET_HANDLERS(SVC_Sounds); diff --git a/demboyz/netmessages/svc_tempentities.cpp b/demboyz/netmessages/svc_tempentities.cpp new file mode 100644 index 0000000..5a236bf --- /dev/null +++ b/demboyz/netmessages/svc_tempentities.cpp @@ -0,0 +1,41 @@ + +#include "svc_tempentities.h" +#include "bitbuf.h" +#include "netcontants.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_TempEntities_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data) + { + data->numEntries = bitbuf.ReadUBitLong(EVENT_INDEX_BITS); + data->dataLengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_TempEntities_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data) + { + bitbuf.WriteUBitLong(data->numEntries, EVENT_INDEX_BITS); + bitbuf.WriteUBitLong(data->dataLengthInBits, NET_MAX_PAYLOAD_BITS); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_TempEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data) + { + return true; + } + + bool SVC_TempEntities_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data) + { + return true; + } + + void SVC_TempEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_TempEntities* data) + { + out << "svc_TempEntities: number " << data->numEntries + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_tempentities.h b/demboyz/netmessages/svc_tempentities.h new file mode 100644 index 0000000..28d8998 --- /dev/null +++ b/demboyz/netmessages/svc_tempentities.h @@ -0,0 +1,17 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_TempEntities + { + std::unique_ptr data; + uint32_t dataLengthInBits; + uint32_t numEntries; + }; +} + +DECLARE_NET_HANDLERS(SVC_TempEntities); diff --git a/demboyz/netmessages/svc_terrainmod.cpp b/demboyz/netmessages/svc_terrainmod.cpp new file mode 100644 index 0000000..667fda5 --- /dev/null +++ b/demboyz/netmessages/svc_terrainmod.cpp @@ -0,0 +1,35 @@ + +#include "svc_terrainmod.h" +#include + +namespace NetHandlers +{ + bool SVC_TerrainMod_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_TerrainMod* data) + { + assert(false); + return true; + } + + bool SVC_TerrainMod_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_TerrainMod* data) + { + assert(false); + return true; + } + + bool SVC_TerrainMod_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_TerrainMod* data) + { + assert(false); + return true; + } + + bool SVC_TerrainMod_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_TerrainMod* data) + { + assert(false); + return true; + } + + void SVC_TerrainMod_ToString_Internal(std::ostringstream& out, NetMsg::SVC_TerrainMod* data) + { + out << "svc_TerrainMod"; + } +} diff --git a/demboyz/netmessages/svc_terrainmod.h b/demboyz/netmessages/svc_terrainmod.h new file mode 100644 index 0000000..757ccf2 --- /dev/null +++ b/demboyz/netmessages/svc_terrainmod.h @@ -0,0 +1,13 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_TerrainMod + { + }; +} + +DECLARE_NET_HANDLERS(SVC_TerrainMod); diff --git a/demboyz/netmessages/svc_updatestringtable.cpp b/demboyz/netmessages/svc_updatestringtable.cpp new file mode 100644 index 0000000..461951b --- /dev/null +++ b/demboyz/netmessages/svc_updatestringtable.cpp @@ -0,0 +1,52 @@ + +#include "svc_updatestringtable.h" +#include "bitbuf.h" +#include "netmath.h" +#include "netcontants.h" + +namespace NetHandlers +{ + bool SVC_UpdateStringTable_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) + { + data->tableID = bitbuf.ReadUBitLong(math::log2(MAX_TABLES)); + data->numChangedEntries = (bitbuf.ReadOneBit() != 0) ? bitbuf.ReadWord() : 1; + data->dataLengthInBits = bitbuf.ReadUBitLong(20); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_UpdateStringTable_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) + { + bitbuf.WriteUBitLong(data->tableID, math::log2(MAX_TABLES)); + if (data->numChangedEntries != 1) + { + bitbuf.WriteOneBit(1); + bitbuf.WriteWord(data->numChangedEntries); + } + else + { + bitbuf.WriteOneBit(0); + } + bitbuf.WriteUBitLong(data->dataLengthInBits, 20); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_UpdateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) + { + return true; + } + + bool SVC_UpdateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data) + { + return true; + } + + void SVC_UpdateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UpdateStringTable* data) + { + out << "svc_UpdateStringTable: table " << data->tableID + << ", changed " << data->numChangedEntries + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_updatestringtable.h b/demboyz/netmessages/svc_updatestringtable.h new file mode 100644 index 0000000..3125a8e --- /dev/null +++ b/demboyz/netmessages/svc_updatestringtable.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_UpdateStringTable + { + uint32_t tableID; + bool twoOrMoreChangedEntries; + uint16_t numChangedEntries; + uint32_t dataLengthInBits; + std::unique_ptr data; + }; +} + +DECLARE_NET_HANDLERS(SVC_UpdateStringTable); diff --git a/demboyz/netmessages/svc_usermessage.cpp b/demboyz/netmessages/svc_usermessage.cpp new file mode 100644 index 0000000..e0ab6ee --- /dev/null +++ b/demboyz/netmessages/svc_usermessage.cpp @@ -0,0 +1,43 @@ + +#include "svc_usermessage.h" +#include "bitbuf.h" +#include "netmath.h" +#include "netcontants.h" +#include + +namespace NetHandlers +{ + bool SVC_UserMessage_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data) + { + data->msgType = bitbuf.ReadByte(); + data->dataLengthInBits = bitbuf.ReadUBitLong(11); + assert(math::BitsToBytes(data->dataLengthInBits) <= MAX_USER_MSG_DATA); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_UserMessage_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data) + { + bitbuf.WriteByte(data->msgType); + bitbuf.WriteUBitLong(data->dataLengthInBits, 11); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_UserMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data) + { + return true; + } + + bool SVC_UserMessage_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data) + { + return true; + } + + void SVC_UserMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UserMessage* data) + { + out << "svc_UserMessage: type " << data->msgType + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_usermessage.h b/demboyz/netmessages/svc_usermessage.h new file mode 100644 index 0000000..7194752 --- /dev/null +++ b/demboyz/netmessages/svc_usermessage.h @@ -0,0 +1,17 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_UserMessage + { + std::unique_ptr data; + uint16_t dataLengthInBits; + uint8_t msgType; + }; +} + +DECLARE_NET_HANDLERS(SVC_UserMessage); diff --git a/demboyz/netmessages/svc_voicedata.cpp b/demboyz/netmessages/svc_voicedata.cpp new file mode 100644 index 0000000..97f8072 --- /dev/null +++ b/demboyz/netmessages/svc_voicedata.cpp @@ -0,0 +1,42 @@ + +#include "svc_voicedata.h" +#include "bitbuf.h" +#include "netmath.h" + +namespace NetHandlers +{ + bool SVC_VoiceData_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data) + { + data->fromClientIndex = bitbuf.ReadByte(); + data->proximity = !!bitbuf.ReadByte(); + data->dataLengthInBits = bitbuf.ReadWord(); + data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]); + bitbuf.ReadBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_VoiceData_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data) + { + bitbuf.WriteByte(data->fromClientIndex); + bitbuf.WriteByte(data->proximity); + bitbuf.WriteWord(data->dataLengthInBits); + bitbuf.WriteBits(data->data.get(), data->dataLengthInBits); + return !bitbuf.IsOverflowed(); + } + + bool SVC_VoiceData_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data) + { + return true; + } + + bool SVC_VoiceData_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data) + { + return true; + } + + void SVC_VoiceData_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceData* data) + { + out << "svc_VoiceData: client " << data->fromClientIndex + << ", bytes " << math::BitsToBytes(data->dataLengthInBits); + } +} diff --git a/demboyz/netmessages/svc_voicedata.h b/demboyz/netmessages/svc_voicedata.h new file mode 100644 index 0000000..c68e24c --- /dev/null +++ b/demboyz/netmessages/svc_voicedata.h @@ -0,0 +1,18 @@ + +#pragma once + +#include "nethandlers.h" +#include + +namespace NetMsg +{ + struct SVC_VoiceData + { + uint8_t fromClientIndex; + bool proximity; // stored in a byte + uint16_t dataLengthInBits; + std::unique_ptr data; + }; +} + +DECLARE_NET_HANDLERS(SVC_VoiceData); diff --git a/demboyz/netmessages/svc_voiceinit.cpp b/demboyz/netmessages/svc_voiceinit.cpp new file mode 100644 index 0000000..36a09bf --- /dev/null +++ b/demboyz/netmessages/svc_voiceinit.cpp @@ -0,0 +1,36 @@ + +#include "svc_voiceinit.h" +#include "bitbuf.h" + +namespace NetHandlers +{ + bool SVC_VoiceInit_BitRead_Internal(bf_read& bitbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data) + { + bitbuf.ReadString(data->voiceCodec, sizeof(data->voiceCodec)); + data->quality = bitbuf.ReadByte(); + return !bitbuf.IsOverflowed(); + } + + bool SVC_VoiceInit_BitWrite_Internal(bf_write& bitbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data) + { + bitbuf.WriteString(data->voiceCodec); + bitbuf.WriteByte(data->quality); + return !bitbuf.IsOverflowed(); + } + + bool SVC_VoiceInit_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data) + { + return true; + } + + bool SVC_VoiceInit_JsonWrite_Internal(JsonWrite& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data) + { + return true; + } + + void SVC_VoiceInit_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceInit* data) + { + out << "svc_VoiceInit: codec \"" << data->voiceCodec + << "\", qualitty " << data->quality; + } +} diff --git a/demboyz/netmessages/svc_voiceinit.h b/demboyz/netmessages/svc_voiceinit.h new file mode 100644 index 0000000..f302160 --- /dev/null +++ b/demboyz/netmessages/svc_voiceinit.h @@ -0,0 +1,15 @@ + +#pragma once + +#include "nethandlers.h" + +namespace NetMsg +{ + struct SVC_VoiceInit + { + char voiceCodec[MAX_OSPATH]; // used voice codec .dll + uint8_t quality; // custom quality setting + }; +} + +DECLARE_NET_HANDLERS(SVC_VoiceInit); diff --git a/external/sourcesdk/valve_support.h b/external/sourcesdk/valve_support.h index ecaddcc..5755a18 100644 --- a/external/sourcesdk/valve_support.h +++ b/external/sourcesdk/valve_support.h @@ -33,7 +33,7 @@ using byte = char; #define Q_memcpy memcpy -bool is_little_endian() +inline bool is_little_endian() { union { uint32 i; diff --git a/premake/demboyz.lua b/premake/demboyz.lua index 1376f21..68a9309 100644 --- a/premake/demboyz.lua +++ b/premake/demboyz.lua @@ -5,6 +5,7 @@ solution "demboyz" startproject "demboyz" configurations { "Debug", "Release" } platforms "x32" + flags "MultiProcessorCompile" project "demboyz" kind "ConsoleApp"