diff --git a/src/plugin.cpp b/src/plugin.cpp index 85b645c..02f2941 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -3,7 +3,6 @@ #include "common.h" #include "detour.h" #include "gameconfig.h" -#include "icvar.h" #include "iserver.h" #include "module.h" #include "overrides.h" @@ -27,43 +26,6 @@ CGameEntitySystem* g_entitySystem = nullptr; bool g_enabled = true; bool g_armed = false; -static int ForceFullUpdateForAllClients() -{ - if (!g_networkServerService || !g_gameConfig) - return 0; - - CNetworkGameServerBase* server = g_networkServerService->GetIGameServer(); - if (!server) - return 0; - - int listOffset = g_gameConfig->GetOffset("CNetworkGameServer_ClientList"); - int deltaTickOffset = g_gameConfig->GetOffset("CServerSideClient_DeltaTick"); - if (listOffset < 0 || deltaTickOffset < 0) - return 0; - - auto* list = reinterpret_cast(server) + listOffset; - int count = *reinterpret_cast(list); - if (count <= 0 || count > 256) - return 0; - - auto** clients = *reinterpret_cast(list + 8); - if (!clients) - return 0; - - int forced = 0; - for (int i = 0; i < count; ++i) - { - void* client = clients[i]; - if (!client) - continue; - - auto* deltaTick = reinterpret_cast(reinterpret_cast(client) + deltaTickOffset); - *deltaTick = -1; - ++forced; - } - return forced; -} - void SPMessage(const char* msg, ...) { va_list args; @@ -97,154 +59,6 @@ CGameEntitySystem* GameEntitySystem() return g_entitySystem; } -CON_COMMAND_F(sp_enable, "Enable SendProxy overrides", FCVAR_NONE) -{ - if (args.ArgC() >= 2) - g_enabled = atoi(args[1]) != 0; - SPMessage("enabled=%d\n", g_enabled ? 1 : 0); -} - -CON_COMMAND_F(sp_arm, "Arm SendProxy override application after the map is fully loaded", FCVAR_NONE) -{ - if (args.ArgC() >= 2) - g_armed = atoi(args[1]) != 0; - SPMessage("armed=%d\n", g_armed ? 1 : 0); -} - -CON_COMMAND_F(sp_trace, "Enable SendProxy tracing", FCVAR_NONE) -{ - if (args.ArgC() >= 2) - g_overrides.SetTrace(atoi(args[1]) != 0); - SPMessage("trace=%d\n", g_overrides.Trace() ? 1 : 0); -} - -CON_COMMAND_F(sp_dump, "Dump SendProxy state", FCVAR_NONE) -{ - SPMessage("enabled=%d armed=%d entitySystem=%p\n", g_enabled ? 1 : 0, g_armed ? 1 : 0, GameEntitySystem()); - DumpDetourStats(); - g_overrides.Dump(); -} - -CON_COMMAND_F(sp_fullupdate, "Force full snapshot update for all connected clients", FCVAR_NONE) -{ - int forced = ForceFullUpdateForAllClients(); - RequestSnapshotFullUpdates(); - SPMessage("forced full update for %d clients; queued snapshot fallback\n", forced); -} - -CON_COMMAND_F(sp_entities, "sp_entities [substring] [limit]", FCVAR_NONE) -{ - CGameEntitySystem* entitySystem = GameEntitySystem(); - if (!entitySystem) - { - SPWarning("no entity system\n"); - return; - } - - const char* filter = args.ArgC() >= 2 ? args[1] : ""; - int limit = args.ArgC() >= 3 ? atoi(args[2]) : 80; - if (limit <= 0) - limit = 80; - - auto healthField = schema::FindField("CBaseEntity", "m_iHealth"); - int printed = 0; - int visited = 0; - for (auto* identity = entitySystem->m_EntityList.m_pFirstActiveEntity; identity && visited < 16384; identity = identity->m_pNext, ++visited) - { - const char* designer = identity->m_designerName.String(); - const char* classDesigner = identity->m_pClass ? identity->m_pClass->m_designerName.String() : ""; - if (filter && *filter && !V_stristr(designer ? designer : "", filter) && !V_stristr(classDesigner ? classDesigner : "", filter)) - continue; - - int health = -999999; - if (identity->m_pInstance && healthField.found) - health = *reinterpret_cast(reinterpret_cast(identity->m_pInstance) + healthField.offset); - - SPMessage("entity idx=%d inst=%p designer=%s class=%s health=%d\n", - identity->m_EHandle.GetEntryIndex(), - identity->m_pInstance, - designer ? designer : "", - classDesigner ? classDesigner : "", - health); - if (++printed >= limit) - break; - } - SPMessage("entities printed=%d visited=%d filter=%s\n", printed, visited, filter ? filter : ""); -} - -CON_COMMAND_F(sp_clear, "Clear SendProxy rules", FCVAR_NONE) -{ - g_overrides.Clear(); - SPMessage("rules cleared\n"); -} - -CON_COMMAND_F(sp_set_exact, "sp_set_exact ", FCVAR_NONE) -{ - if (args.ArgC() < 7) - { - SPWarning("usage: sp_set_exact \n"); - return; - } - - int recipientSlot = !V_stricmp(args[1], "all") ? -1 : atoi(args[1]); - int entityIndex = atoi(args[2]); - std::string error; - int id = g_overrides.AddCompiledRule(recipientSlot, entityIndex, args[3], args[4], args[5], args[6], error); - if (!id) - { - SPWarning("%s\n", error.c_str()); - return; - } - - g_enabled = true; - g_armed = true; - SPMessage("enabled=1 armed=1 rule_id=%d\n", id); -} - -CON_COMMAND_F(sp_unset, "sp_unset ", FCVAR_NONE) -{ - if (args.ArgC() < 2) - { - SPWarning("usage: sp_unset \n"); - return; - } - - int id = atoi(args[1]); - if (!g_overrides.RemoveRule(id)) - { - SPWarning("rule %d not found\n", id); - return; - } - SPMessage("rule %d removed\n", id); -} - -CON_COMMAND_F(sp_dirty, "sp_dirty ", FCVAR_NONE) -{ - if (args.ArgC() < 4) - { - SPWarning("usage: sp_dirty \n"); - return; - } - - std::string error; - if (!g_overrides.MarkEntityFieldDirty(atoi(args[1]), args[2], args[3], error)) - { - SPWarning("%s\n", error.empty() ? "failed to mark field dirty" : error.c_str()); - return; - } - SPMessage("marked entity %d %s::%s dirty\n", atoi(args[1]), args[2], args[3]); -} - -CON_COMMAND_F(sp_set, "sp_set ", FCVAR_NONE) -{ - const char* argv[8] {}; - for (int i = 0; i < args.ArgC() && i < 8; ++i) - argv[i] = args[i]; - std::string error; - if (!g_overrides.AddFromTokens(args.ArgC(), argv, error)) - SPWarning("%s\n", error.c_str()); -} - extern "C" __attribute__((visibility("default"))) int SendProxy_SetOverride(int recipientSlot, int entityIndex, const char* className, const char* fieldPath, const char* type, const char* value) { std::string error; @@ -282,159 +96,18 @@ extern "C" __attribute__((visibility("default"))) bool SendProxy_MarkDirty(int e return true; } -CON_COMMAND_F(sp_weapon_test, "sp_weapon_test ", FCVAR_NONE) -{ - if (args.ArgC() < 3) - { - SPWarning("usage: sp_weapon_test \n"); - return; - } - std::string error; - if (!g_overrides.AddWeaponItemDefRule(-1, args[1], static_cast(atoi(args[2])), error)) - SPWarning("%s\n", error.c_str()); -} - -static void SetHealthMoneyCommand(const CCommand& args) -{ - if (args.ArgC() < 2) - { - SPWarning("usage: sp_health_money <0|1>\n"); - return; - } - - bool enable = atoi(args[1]) != 0; - std::string error; - if (!g_overrides.SetHealthMoneyTest(enable, error)) - { - SPWarning("%s\n", error.c_str()); - return; - } - - if (enable) - { - g_enabled = true; - g_armed = true; - SPMessage("enabled=1 armed=1\n"); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); - } - else if (g_overrides.Empty()) - { - g_armed = false; - SPMessage("armed=0\n"); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); - } -} - -CON_COMMAND_F(sp_health_money, "sp_health_money <0|1>", FCVAR_NONE) -{ - SetHealthMoneyCommand(args); -} - -CON_COMMAND_F(sp_health_money_test, "sp_health_money_test <0|1>", FCVAR_NONE) -{ - SetHealthMoneyCommand(args); -} - -CON_COMMAND_F(sp_health_42, "sp_health_42 <0|1>", FCVAR_NONE) -{ - if (args.ArgC() < 2) - { - SPWarning("usage: sp_health_42 <0|1>\n"); - return; - } - - bool enable = atoi(args[1]) != 0; - std::string error; - if (!g_overrides.SetHealth42Test(enable, error)) - { - SPWarning("%s\n", error.c_str()); - return; - } - - if (enable) - { - g_enabled = true; - g_armed = true; - SPMessage("enabled=1 armed=1\n"); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); - } - else if (g_overrides.Empty()) - { - g_armed = false; - SPMessage("armed=0\n"); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); - } -} - -CON_COMMAND_F(sp_health_recipient, "sp_health_recipient [value]", FCVAR_NONE) -{ - if (args.ArgC() < 2) - { - SPWarning("usage: sp_health_recipient [value]\n"); - return; - } - - if (!V_stricmp(args[1], "clear")) - { - g_overrides.ClearRecipientHealthValues(); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); - return; - } - - if (args.ArgC() < 3) - { - SPWarning("usage: sp_health_recipient [value]\n"); - return; - } - - int recipientSlot = !V_stricmp(args[1], "all") ? -1 : atoi(args[1]); - int value = atoi(args[2]); - std::string error; - if (!g_overrides.SetRecipientHealthValue(recipientSlot, value, error)) - { - SPWarning("%s\n", error.c_str()); - return; - } - - if (!g_overrides.Health42Test()) - { - if (!g_overrides.SetHealth42Test(true, error)) - { - SPWarning("%s\n", error.c_str()); - return; - } - } - - g_enabled = true; - g_armed = true; - SPMessage("enabled=1 armed=1\n"); - SPMessage("marked health dirty for %d players\n", g_overrides.MarkPlayerHealthDirty()); -} - -CON_COMMAND_F(sp_schema_fields, "sp_schema_fields [substring]", FCVAR_NONE) -{ - if (args.ArgC() < 2) - { - SPWarning("usage: sp_schema_fields [substring]\n"); - return; - } - schema::DumpFields(args[1], args.ArgC() >= 3 ? args[2] : ""); -} - PLUGIN_EXPOSE(SendProxyPlugin, g_SendProxy); bool SendProxyPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool late) { PLUGIN_SAVEVARS(); - ICvar* icvar = nullptr; GET_V_IFACE_CURRENT(GetEngineFactory, g_engine, IVEngineServer2, SOURCE2ENGINETOSERVER_INTERFACE_VERSION); GET_V_IFACE_ANY(GetEngineFactory, g_networkServerService, INetworkServerService, NETWORKSERVERSERVICE_INTERFACE_VERSION); GET_V_IFACE_ANY(GetServerFactory, g_gameClients, IServerGameClients, SOURCE2GAMECLIENTS_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, g_schemaSystem, ISchemaSystem, SCHEMASYSTEM_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, g_gameResourceService, IGameResourceService, GAMERESOURCESERVICESERVER_INTERFACE_VERSION); GET_V_IFACE_ANY(GetFileSystemFactory, g_fileSystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION); - GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); modules::engine = new CModule(ROOTBIN, "engine2"); modules::server = new CModule(GAMEBIN, "server"); @@ -459,10 +132,7 @@ bool SendProxyPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxle } g_SMAPI->AddListener(this, this); - g_pCVar = icvar; - META_CONVAR_REGISTER(FCVAR_RELEASE | FCVAR_CLIENT_CAN_EXECUTE | FCVAR_GAMEDLL); - g_engine->ServerCommand("execifexists addons/sendproxy/configs/sendproxy.cfg\n"); SPMessage("loaded\n"); return true; } @@ -470,7 +140,6 @@ bool SendProxyPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxle bool SendProxyPlugin::Unload(char*, size_t) { ShutdownSnapshotDetour(); - ConVar_Unregister(); delete g_gameConfig; delete modules::engine; delete modules::server;