#pragma once #include "shared/keyvalues.h" // use the R2 namespace for game funcs namespace R2 { // Cbuf enum class ECommandTarget_t { CBUF_FIRST_PLAYER = 0, CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2 CBUF_SERVER = CBUF_LAST_PLAYER + 1, CBUF_COUNT, }; enum class cmd_source_t { // Added to the console buffer by gameplay code. Generally unrestricted. kCommandSrcCode, // Sent from code via engine->ClientCmd, which is restricted to commands visible // via FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS. kCommandSrcClientCmd, // Typed in at the console or via a user key-bind. Generally unrestricted, although // the client will throttle commands sent to the server this way to 16 per second. kCommandSrcUserInput, // Came in over a net connection as a clc_stringcmd // host_client will be valid during this state. // // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand // server commands hardcoded into gameplay code (e.g. "joingame") kCommandSrcNetClient, // Received from the server as the client // // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE kCommandSrcNetServer, // Being played back from a demo file // // Not currently restricted by convar flag, but some commands manually ignore calls // from this source. FIXME: Should be heavily restricted as demo commands can come // from untrusted sources. kCommandSrcDemoFile, // Invalid value used when cleared kCommandSrcInvalid = -1 }; typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)(); extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer; typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source); extern Cbuf_AddTextType Cbuf_AddText; typedef void (*Cbuf_ExecuteType)(); extern Cbuf_ExecuteType Cbuf_Execute; extern bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource); // CEngine enum EngineQuitState { QUIT_NOTQUITTING = 0, QUIT_TODESKTOP, QUIT_RESTART }; enum class EngineState_t { DLL_INACTIVE = 0, // no dll DLL_ACTIVE, // engine is focused DLL_CLOSE, // closing down dll DLL_RESTART, // engine is shutting down but will restart right away DLL_PAUSED, // engine is paused, can become active from this state }; class CEngine { public: virtual void unknown() = 0; // unsure if this is where virtual bool Load(bool dedicated, const char* baseDir) = 0; virtual void Unload() = 0; virtual void SetNextState(EngineState_t iNextState) = 0; virtual EngineState_t GetState() = 0; virtual void Frame() = 0; virtual double GetFrameTime() = 0; virtual float GetCurTime() = 0; EngineQuitState m_nQuitting; EngineState_t m_nDllState; EngineState_t m_nNextDllState; double m_flCurrentTime; float m_flFrameTime; double m_flPreviousTime; float m_flFilteredTime; float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited. }; extern CEngine* g_pEngine; extern void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...); #pragma once typedef enum { NA_NULL = 0, NA_LOOPBACK, NA_IP, } netadrtype_t; #pragma pack(push, 1) typedef struct netadr_s { netadrtype_t type; unsigned char ip[16]; // IPv6 // IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is: // 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01 unsigned short port; } netadr_t; #pragma pack(pop) #pragma pack(push, 1) typedef struct netpacket_s { netadr_t adr; // sender address // int source; // received source char unk[10]; double received_time; unsigned char* data; // pointer to raw packet data void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer) char unk2[16]; int size; // bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer) // int size; // size in bytes // int wiresize; // size in bytes before decompression // bool stream; // was send as stream // struct netpacket_s* pNext; // for internal use, should be NULL in public } netpacket_t; #pragma pack(pop) // #56169 $DB69 PData size // #512 $200 Trailing data // #100 $64 Safety buffer const int PERSISTENCE_MAX_SIZE = 0xDDCD; // note: NOT_READY and READY are the only entries we have here that are defined by the vanilla game // entries after this are custom and used to determine the source of persistence, e.g. whether it is local or remote enum class ePersistenceReady : char { NOT_READY, READY = 3, READY_INSECURE = 3, READY_REMOTE }; enum class eSignonState : int { NONE = 0, // no state yet; about to connect CHALLENGE = 1, // client challenging server; all OOB packets CONNECTED = 2, // client is connected to server; netchans ready NEW = 3, // just got serverinfo and string tables PRESPAWN = 4, // received signon buffers GETTINGDATA = 5, // respawn-defined signonstate, assumedly this is for persistence SPAWN = 6, // ready to receive entity packets FIRSTSNAP = 7, // another respawn-defined one FULL = 8, // we are fully connected; first non-delta packet received CHANGELEVEL = 9, // server is changing level; please wait }; // clang-format off OFFSET_STRUCT(CBaseClient) { STRUCT_SIZE(0x2D728) FIELD(0x16, char m_Name[64]) FIELD(0x258, KeyValues* m_ConVars) FIELD(0x2A0, eSignonState m_Signon) FIELD(0x358, char m_ClanTag[16]) FIELD(0x484, bool m_bFakePlayer) FIELD(0x4A0, ePersistenceReady m_iPersistenceReady) FIELD(0x4FA, char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE]) FIELD(0xF500, char m_UID[32]) }; // clang-format on extern CBaseClient* g_pClientArray; enum server_state_t { ss_dead = 0, // Dead ss_loading, // Spawning ss_active, // Running ss_paused, // Running, but paused }; extern server_state_t* g_pServerState; extern char* g_pModName; // clang-format off OFFSET_STRUCT(CGlobalVars) { FIELD(0x0, // Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time // perf clock, but not that it doesn't obey host_timescale/host_framerate) double m_flRealTime); FIELDS(0x8, // Absolute frame counter - continues to increase even if game is paused int m_nFrameCount; // Non-paused frametime float m_flAbsoluteFrameTime; // Current time // // On the client, this (along with tickcount) takes a different meaning based on what // piece of code you're in: // // - While receiving network packets (like in PreDataUpdate/PostDataUpdate and proxies), // this is set to the SERVER TICKCOUNT for that packet. There is no interval between // the server ticks. // [server_current_Tick * tick_interval] // // - While rendering, this is the exact client clock // [client_current_tick * tick_interval + interpolation_amount] // // - During prediction, this is based on the client's current tick: // [client_current_tick * tick_interval] float m_flCurTime; ) FIELDS(0x30, // Time spent on last server or client frame (has nothing to do with think intervals) float m_flFrameTime; // current maxplayers setting int m_nMaxClients; ) FIELDS(0x3C, // Simulation ticks - does not increase when game is paused uint32_t m_nTickCount; // this is weird and doesn't seem to increase once per frame? // Simulation tick interval float m_flTickInterval; ) FIELDS(0x60, const char* m_pMapName; int m_nMapVersion; ) //FIELD(0x98, double m_flRealTime); // again? }; // clang-format on extern CGlobalVars* g_pGlobals; } // namespace R2