mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-07 00:16:36 -08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f72631eb0 | ||
|
|
75fcf21fb7 | ||
|
|
0ddf6bcdfa | ||
|
|
98661cd069 | ||
|
|
86a5699b40 | ||
|
|
414710d05c |
@@ -29,6 +29,8 @@ SET(SOURCE_FILES
|
||||
src/core/utils.h
|
||||
src/core/globals.h
|
||||
src/core/globals.cpp
|
||||
src/core/coreconfig.h
|
||||
src/core/coreconfig.cpp
|
||||
src/core/gameconfig.h
|
||||
src/core/gameconfig.cpp
|
||||
src/core/log.h
|
||||
@@ -84,7 +86,7 @@ SET(SOURCE_FILES
|
||||
|
||||
if (LINUX)
|
||||
# memoverride.cpp is not usable on CMake Windows, cuz CMake default link libraries (seems) always link ucrt.lib
|
||||
set(SOURCE_FILES
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
libraries/hl2sdk-cs2/public/tier0/memoverride.cpp
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"PublicChatTrigger": "!",
|
||||
"SilentChatTrigger": "/",
|
||||
"PublicChatTrigger": [ "!" ],
|
||||
"SilentChatTrigger": [ "/" ],
|
||||
"FollowCS2ServerGuidelines": true
|
||||
}
|
||||
@@ -50,14 +50,14 @@
|
||||
"CBaseModelEntity_SetModel": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x2A\\x48\\x89\\x7C\\x24\\x2A\\x55\\x48\\x8B\\xEC\\x48\\x83\\xEC\\x50\\x48\\x8B\\xF9",
|
||||
"linux": "\\x55\\x48\\x89\\xF2\\x48\\x89\\xE5\\x41\\x54\\x49\\x89\\xFC\\x48\\x8D\\x7D\\xE0\\x48\\x83\\xEC\\x18\\x48\\x8D\\x05\\xE5\\xD1\\xBF\\x00"
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x7C\\x24\\x20\\x55\\x48\\x8B\\xEC\\x48\\x83\\xEC\\x50\\x48\\x8B\\xF9\\x4C\\x8B\\xC2\\x48\\x8B\\x0D\\x69\\x07\\xD9\\x00",
|
||||
"linux": "\\x55\\x48\\x89\\xF2\\x48\\x89\\xE5\\x41\\x54\\x49\\x89\\xFC\\x48\\x8D\\x7D\\xE0\\x48\\x83\\xEC\\x18\\x48\\x8D\\x05\\x15\\xD4\\xBF\\x00"
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_CommitSuicide": {
|
||||
"offsets": {
|
||||
"windows": 355,
|
||||
"linux": 355
|
||||
"windows": 356,
|
||||
"linux": 356
|
||||
}
|
||||
},
|
||||
"CBaseEntity_Teleport": {
|
||||
|
||||
@@ -23,6 +23,7 @@ using System.Text.Json.Serialization;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
@@ -31,9 +32,9 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// </summary>
|
||||
internal sealed partial class CoreConfigData
|
||||
{
|
||||
[JsonPropertyName("PublicChatTrigger")] public string PublicChatTrigger { get; set; } = "!";
|
||||
[JsonPropertyName("PublicChatTrigger")] public IEnumerable<string> PublicChatTrigger { get; set; } = new HashSet<string>() { "!" };
|
||||
|
||||
[JsonPropertyName("SilentChatTrigger")] public string SilentChatTrigger { get; set; } = "/";
|
||||
[JsonPropertyName("SilentChatTrigger")] public IEnumerable<string> SilentChatTrigger { get; set; } = new HashSet<string>() { "/" };
|
||||
|
||||
[JsonPropertyName("FollowCS2ServerGuidelines")] public bool FollowCS2ServerGuidelines { get; set; } = true;
|
||||
}
|
||||
@@ -46,12 +47,12 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// <summary>
|
||||
/// List of characters to use for public chat triggers.
|
||||
/// </summary>
|
||||
public static string PublicChatTrigger => _coreConfig.PublicChatTrigger;
|
||||
public static IEnumerable<string> PublicChatTrigger => _coreConfig.PublicChatTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// List of characters to use for silent chat triggers.
|
||||
/// </summary>
|
||||
public static string SilentChatTrigger => _coreConfig.SilentChatTrigger;
|
||||
public static IEnumerable<string> SilentChatTrigger => _coreConfig.SilentChatTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
|
||||
@@ -26,7 +26,7 @@ public partial class CCSPlayerController
|
||||
|
||||
public void PrintToConsole(string message)
|
||||
{
|
||||
NativeAPI.PrintToConsole((int)EntityIndex.Value.Value, message);
|
||||
NativeAPI.PrintToConsole((int)EntityIndex.Value.Value, $"{message}\n\0");
|
||||
}
|
||||
|
||||
public void PrintToChat(string message)
|
||||
|
||||
@@ -31,9 +31,15 @@ public partial class VirtualFunction
|
||||
{
|
||||
if (!_createdFunctions.TryGetValue(signature, out var function))
|
||||
{
|
||||
function = NativeAPI.CreateVirtualFunctionBySignature(IntPtr.Zero, Addresses.ServerPath, signature,
|
||||
argumentTypes.Count(), (int)returnType, arguments);
|
||||
_createdFunctions[signature] = function;
|
||||
try
|
||||
{
|
||||
function = NativeAPI.CreateVirtualFunctionBySignature(IntPtr.Zero, Addresses.ServerPath, signature,
|
||||
argumentTypes.Count(), (int)returnType, arguments);
|
||||
_createdFunctions[signature] = function;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return function;
|
||||
|
||||
@@ -354,7 +354,7 @@ namespace TestPlugin
|
||||
[ConsoleCommand("cssharp_attribute", "This is a custom attribute event")]
|
||||
public void OnCommand(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
Log("cssharp_attribute called!");
|
||||
command.ReplyToCommand("cssharp_attribute called", true);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_changelevel", "Changes map")]
|
||||
|
||||
78
src/core/coreconfig.cpp
Normal file
78
src/core/coreconfig.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "core/log.h"
|
||||
#include "core/coreconfig.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
CCoreConfig::CCoreConfig(const std::string& path) { m_sPath = path; }
|
||||
|
||||
CCoreConfig::~CCoreConfig() = default;
|
||||
|
||||
bool CCoreConfig::Init(char* conf_error, int conf_error_size)
|
||||
{
|
||||
std::ifstream ifs(m_sPath);
|
||||
|
||||
if (!ifs) {
|
||||
V_snprintf(conf_error, conf_error_size, "CoreConfig file not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_json = json::parse(ifs);
|
||||
|
||||
try {
|
||||
PublicChatTrigger = m_json["PublicChatTrigger"];
|
||||
SilentChatTrigger = m_json["SilentChatTrigger"];
|
||||
FollowCS2ServerGuidelines = m_json["FollowCS2ServerGuidelines"];
|
||||
} catch (const std::exception& ex) {
|
||||
V_snprintf(conf_error, conf_error_size, "Failed to parse CoreConfig file: %s", ex.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string CCoreConfig::GetPath() const
|
||||
{
|
||||
return m_sPath;
|
||||
}
|
||||
|
||||
bool CCoreConfig::IsTriggerInternal(std::vector<std::string> triggers, const std::string& message, std::string*& prefix) const
|
||||
{
|
||||
for (std::string& trigger : triggers)
|
||||
{
|
||||
if (message.rfind(trigger, 0) == 0)
|
||||
{
|
||||
prefix = &trigger;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCoreConfig::IsSilentChatTrigger(const std::string& message, std::string*& prefix) const
|
||||
{
|
||||
return IsTriggerInternal(SilentChatTrigger, message, prefix);
|
||||
}
|
||||
|
||||
bool CCoreConfig::IsPublicChatTrigger(const std::string& message, std::string*& prefix) const
|
||||
{
|
||||
return IsTriggerInternal(PublicChatTrigger, message, prefix);
|
||||
}
|
||||
} // namespace counterstrikesharp
|
||||
50
src/core/coreconfig.h
Normal file
50
src/core/coreconfig.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/globals.h"
|
||||
#include <string>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
class CCoreConfig
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> PublicChatTrigger = { std::string("!") };
|
||||
std::vector<std::string> SilentChatTrigger = { std::string("/") };
|
||||
bool FollowCS2ServerGuidelines = true;
|
||||
|
||||
using json = nlohmann::json;
|
||||
CCoreConfig(const std::string& path);
|
||||
~CCoreConfig();
|
||||
|
||||
bool Init(char* conf_error, int conf_error_size);
|
||||
const std::string GetPath() const;
|
||||
|
||||
bool IsSilentChatTrigger(const std::string& message, std::string*& prefix) const;
|
||||
bool IsPublicChatTrigger(const std::string& message, std::string*& prefix) const;
|
||||
|
||||
private:
|
||||
bool IsTriggerInternal(std::vector<std::string> triggers, const std::string& message, std::string*& prefix) const;
|
||||
|
||||
private:
|
||||
std::string m_sPath;
|
||||
json m_json;
|
||||
};
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "const.h"
|
||||
#include "utils/virtual.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -54,6 +56,45 @@ inline uint64_t hash_64_fnv1a_const(const char *str, const uint64_t value = val_
|
||||
}
|
||||
|
||||
namespace schema {
|
||||
static std::vector<std::string> CS2BadList = {
|
||||
"m_bIsValveDS",
|
||||
"m_bIsQuestEligible",
|
||||
"m_iItemDefinitionIndex", // in unmanaged this cannot be set.
|
||||
"m_iEntityLevel",
|
||||
"m_iItemIDHigh",
|
||||
"m_iItemIDLow",
|
||||
"m_iAccountID",
|
||||
"m_iEntityQuality",
|
||||
|
||||
"m_bInitialized",
|
||||
"m_szCustomName",
|
||||
"m_iAttributeDefinitionIndex",
|
||||
"m_iRawValue32",
|
||||
"m_iRawInitialValue32",
|
||||
"m_flValue", // MNetworkAlias "m_iRawValue32"
|
||||
"m_flInitialValue", // MNetworkAlias "m_iRawInitialValue32"
|
||||
"m_bSetBonus",
|
||||
"m_nRefundableCurrency",
|
||||
|
||||
"m_OriginalOwnerXuidLow",
|
||||
"m_OriginalOwnerXuidHigh",
|
||||
|
||||
"m_nFallbackPaintKit",
|
||||
"m_nFallbackSeed",
|
||||
"m_flFallbackWear",
|
||||
"m_nFallbackStatTrak",
|
||||
|
||||
"m_iCompetitiveWins",
|
||||
"m_iCompetitiveRanking",
|
||||
"m_iCompetitiveRankType",
|
||||
"m_iCompetitiveRankingPredicted_Win",
|
||||
"m_iCompetitiveRankingPredicted_Loss",
|
||||
"m_iCompetitiveRankingPredicted_Tie",
|
||||
|
||||
"m_nActiveCoinRank",
|
||||
"m_nMusicID",
|
||||
};
|
||||
|
||||
int16_t FindChainOffset(const char *className);
|
||||
SchemaKey GetOffset(const char *className, uint32_t classKey, const char *memberName, uint32_t memberKey);
|
||||
} // namespace schema
|
||||
|
||||
@@ -65,6 +65,7 @@ SourceHook::Impl::CSourceHookImpl source_hook_impl;
|
||||
SourceHook::ISourceHook *source_hook = &source_hook_impl;
|
||||
ISmmAPI *ismm = nullptr;
|
||||
CGameEntitySystem* entitySystem = nullptr;
|
||||
CCoreConfig* coreConfig = nullptr;
|
||||
CGameConfig* gameConfig = nullptr;
|
||||
|
||||
// Custom Managers
|
||||
|
||||
@@ -49,6 +49,7 @@ class HookManager;
|
||||
class EntityManager;
|
||||
class ChatManager;
|
||||
class ServerManager;
|
||||
class CCoreConfig;
|
||||
class CGameConfig;
|
||||
|
||||
namespace globals {
|
||||
@@ -99,6 +100,7 @@ extern int source_hook_pluginid;
|
||||
extern IGameEventSystem *gameEventSystem;
|
||||
extern CounterStrikeSharpMMPlugin *mmPlugin;
|
||||
extern ISmmAPI *ismm;
|
||||
extern CCoreConfig* coreConfig;
|
||||
extern CGameConfig* gameConfig;
|
||||
|
||||
void Initialize();
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <public/eiface.h>
|
||||
#include "core/memory.h"
|
||||
#include "core/log.h"
|
||||
#include "core/coreconfig.h"
|
||||
#include "core/gameconfig.h"
|
||||
|
||||
#include <funchook.h>
|
||||
@@ -56,9 +57,6 @@ void ChatManager::OnShutdown() {}
|
||||
void DetourHostSay(CBaseEntity* pController, CCommand& args, bool teamonly, int unk1,
|
||||
const char* unk2)
|
||||
{
|
||||
CCommand newArgs;
|
||||
newArgs.Tokenize(args.Arg(1));
|
||||
|
||||
if (pController) {
|
||||
auto pEvent = globals::gameEventManager->CreateEvent("player_chat", true);
|
||||
if (pEvent) {
|
||||
@@ -70,48 +68,53 @@ void DetourHostSay(CBaseEntity* pController, CCommand& args, bool teamonly, int
|
||||
}
|
||||
}
|
||||
|
||||
if (*args[1] == '/' || *args[1] == '!') {
|
||||
globals::chatManager.OnSayCommandPost(pController, newArgs);
|
||||
return;
|
||||
std::string* prefix;
|
||||
bool bSilent = globals::coreConfig->IsSilentChatTrigger(args[1], prefix);
|
||||
bool bCommand = bSilent || globals::coreConfig->IsPublicChatTrigger(args[1], prefix);
|
||||
|
||||
if (!bSilent) {
|
||||
m_pHostSay(pController, args, teamonly, unk1, unk2);
|
||||
}
|
||||
|
||||
m_pHostSay(pController, args, teamonly, unk1, unk2);
|
||||
if (bCommand)
|
||||
{
|
||||
char *pszMessage = (char *)(args.ArgS() + prefix->length() + 1);
|
||||
|
||||
// Trailing slashes are only removed if Host_Say has been called.
|
||||
if (bSilent)
|
||||
pszMessage[V_strlen(pszMessage) - 1] = 0;
|
||||
|
||||
CCommand args;
|
||||
args.Tokenize(pszMessage);
|
||||
|
||||
auto prefixedPhrase = std::string("css_") + args.Arg(0);
|
||||
auto bValidWithPrefix = globals::conCommandManager.IsValidValveCommand(prefixedPhrase.c_str());
|
||||
|
||||
if (bValidWithPrefix) {
|
||||
// Re-tokenize with a `css_` prefix if we have found that its a valid command.
|
||||
args.Tokenize(("css_" + std::string(pszMessage)).c_str());
|
||||
}
|
||||
|
||||
globals::chatManager.OnSayCommandPost(pController, args);
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatManager::OnSayCommandPre(CBaseEntity* pController, CCommand& command) { return false; }
|
||||
|
||||
void ChatManager::OnSayCommandPost(CBaseEntity* pController, CCommand& command)
|
||||
{
|
||||
const char* args = command.ArgS();
|
||||
auto commandStr = command.Arg(0);
|
||||
|
||||
return InternalDispatch(pController, commandStr + 1, command);
|
||||
return InternalDispatch(pController, commandStr, command);
|
||||
}
|
||||
|
||||
void ChatManager::InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhase,
|
||||
CCommand& fullCommand)
|
||||
{
|
||||
auto ppArgV = new const char*[fullCommand.ArgC()];
|
||||
ppArgV[0] = strdup(szTriggerPhase);
|
||||
for (int i = 1; i < fullCommand.ArgC(); i++) {
|
||||
ppArgV[i] = fullCommand.Arg(i);
|
||||
}
|
||||
|
||||
auto prefixedPhrase = std::string("css_") + szTriggerPhase;
|
||||
|
||||
auto bValidWithPrefix = globals::conCommandManager.IsValidValveCommand(prefixedPhrase.c_str());
|
||||
|
||||
if (bValidWithPrefix) {
|
||||
ppArgV[0] = prefixedPhrase.c_str();
|
||||
}
|
||||
|
||||
CCommand commandCopy(fullCommand.ArgC(), ppArgV);
|
||||
|
||||
if (pPlayerController == nullptr) {
|
||||
globals::conCommandManager.ExecuteCommandCallbacks(
|
||||
commandCopy.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, CPlayerSlot(-1)),
|
||||
commandCopy, HookMode::Pre);
|
||||
delete[] ppArgV;
|
||||
fullCommand.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, CPlayerSlot(-1)),
|
||||
fullCommand, HookMode::Pre);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,8 +122,7 @@ void ChatManager::InternalDispatch(CBaseEntity* pPlayerController, const char* s
|
||||
auto slot = CPlayerSlot(index - 1);
|
||||
|
||||
globals::conCommandManager.ExecuteCommandCallbacks(
|
||||
commandCopy.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, slot), commandCopy,
|
||||
fullCommand.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, slot), fullCommand,
|
||||
HookMode::Pre);
|
||||
delete[] ppArgV;
|
||||
}
|
||||
} // namespace counterstrikesharp
|
||||
@@ -54,7 +54,6 @@ class ChatManager : public GlobalClass
|
||||
|
||||
bool OnSayCommandPre(CBaseEntity* pController, CCommand& args);
|
||||
void OnSayCommandPost(CBaseEntity* pController, CCommand& args);
|
||||
|
||||
private:
|
||||
void InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhrase,
|
||||
CCommand& pFullCommand);
|
||||
|
||||
@@ -170,6 +170,9 @@ ConCommandInfo::~ConCommandInfo()
|
||||
globals::callbackManager.ReleaseCallback(callback_pre);
|
||||
globals::callbackManager.ReleaseCallback(callback_post);
|
||||
}
|
||||
ConCommandInfo::ConCommandInfo(bool bNoCallbacks) {
|
||||
|
||||
}
|
||||
|
||||
ConCommandManager::ConCommandManager() {}
|
||||
|
||||
@@ -181,6 +184,10 @@ void ConCommandManager::OnAllInitialized()
|
||||
&ConCommandManager::Hook_DispatchConCommand, false);
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand_Post, true);
|
||||
|
||||
m_global_cmd.callback_pre = globals::callbackManager.CreateCallback("OnClientCommandGlobalPre");
|
||||
m_global_cmd.callback_post =
|
||||
globals::callbackManager.CreateCallback("OnClientCommandGlobalPost");
|
||||
}
|
||||
|
||||
void ConCommandManager::OnShutdown()
|
||||
@@ -189,6 +196,9 @@ void ConCommandManager::OnShutdown()
|
||||
&ConCommandManager::Hook_DispatchConCommand, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand_Post, true);
|
||||
|
||||
globals::callbackManager.ReleaseCallback(m_global_cmd.callback_pre);
|
||||
globals::callbackManager.ReleaseCallback(m_global_cmd.callback_post);
|
||||
}
|
||||
|
||||
void CommandCallback(const CCommandContext& context, const CCommand& command)
|
||||
@@ -199,6 +209,15 @@ void CommandCallback(const CCommandContext& context, const CCommand& command)
|
||||
|
||||
void ConCommandManager::AddCommandListener(const char* name, CallbackT callback, HookMode mode)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
if (mode == HookMode::Pre) {
|
||||
m_global_cmd.callback_pre->AddListener(callback);
|
||||
} else {
|
||||
m_global_cmd.callback_post->AddListener(callback);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto strName = std::string(name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[strName];
|
||||
|
||||
@@ -210,7 +229,6 @@ void ConCommandManager::AddCommandListener(const char* name, CallbackT callback,
|
||||
if (hExistingCommand.IsValid()) {
|
||||
pInfo->command = globals::cvars->GetCommand(hExistingCommand);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mode == HookMode::Pre) {
|
||||
@@ -218,11 +236,19 @@ void ConCommandManager::AddCommandListener(const char* name, CallbackT callback,
|
||||
} else {
|
||||
pInfo->callback_post->AddListener(callback);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ConCommandManager::RemoveCommandListener(const char* name, CallbackT callback, HookMode mode)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
if (mode == HookMode::Pre) {
|
||||
m_global_cmd.callback_pre->RemoveListener(callback);
|
||||
} else {
|
||||
m_global_cmd.callback_post->RemoveListener(callback);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto strName = std::string(name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[strName];
|
||||
|
||||
@@ -285,10 +311,43 @@ bool ConCommandManager::RemoveValveCommand(const char* name)
|
||||
HookResult ConCommandManager::ExecuteCommandCallbacks(const char* name, const CCommandContext& ctx,
|
||||
const CCommand& args, HookMode mode)
|
||||
{
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager::ExecuteCommandCallbacks][{}]: {}", mode == Pre ? "Pre" : "Post", name);
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager::ExecuteCommandCallbacks][{}]: {}",
|
||||
mode == Pre ? "Pre" : "Post", name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[std::string(name)];
|
||||
|
||||
HookResult result = HookResult::Continue;
|
||||
|
||||
auto globalCallback = mode == HookMode::Pre ? m_global_cmd.callback_pre : m_global_cmd.callback_post;
|
||||
|
||||
if (globalCallback->GetFunctionCount() > 0) {
|
||||
globalCallback->ScriptContext().Reset();
|
||||
globalCallback->ScriptContext().Push(ctx.GetPlayerSlot().Get());
|
||||
globalCallback->ScriptContext().Push(&args);
|
||||
|
||||
for (auto fnMethodToCall : globalCallback->GetFunctions()) {
|
||||
if (!fnMethodToCall)
|
||||
continue;
|
||||
fnMethodToCall(&globalCallback->ScriptContextStruct());
|
||||
|
||||
auto hookResult = globalCallback->ScriptContext().GetResult<HookResult>();
|
||||
|
||||
if (hookResult >= HookResult::Stop) {
|
||||
if (mode == HookMode::Pre) {
|
||||
return HookResult::Stop;
|
||||
}
|
||||
|
||||
result = hookResult;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hookResult >= HookResult::Handled) {
|
||||
result = hookResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pInfo) {
|
||||
return HookResult::Continue;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto pCallback = mode == HookMode::Pre ? pInfo->callback_pre : pInfo->callback_post;
|
||||
@@ -302,14 +361,16 @@ HookResult ConCommandManager::ExecuteCommandCallbacks(const char* name, const CC
|
||||
continue;
|
||||
fnMethodToCall(&pCallback->ScriptContextStruct());
|
||||
|
||||
auto result = pCallback->ScriptContext().GetResult<HookResult>();
|
||||
auto thisResult = pCallback->ScriptContext().GetResult<HookResult>();
|
||||
|
||||
if (result >= HookResult::Handled) {
|
||||
if (thisResult >= HookResult::Handled) {
|
||||
return result;
|
||||
} else if (thisResult > result) {
|
||||
result = thisResult;
|
||||
}
|
||||
}
|
||||
|
||||
return HookResult::Continue;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConCommandManager::Hook_DispatchConCommand(ConCommandHandle cmd, const CCommandContext& ctx,
|
||||
|
||||
@@ -58,6 +58,7 @@ class ConCommandInfo {
|
||||
|
||||
public:
|
||||
ConCommandInfo();
|
||||
ConCommandInfo(bool bNoCallbacks);
|
||||
~ConCommandInfo();
|
||||
|
||||
public:
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
private:
|
||||
std::vector<ConCommandInfo*> m_cmd_list;
|
||||
std::map<std::string, ConCommandInfo*, CaseInsensitiveComparator> m_cmd_lookup;
|
||||
ConCommandInfo m_global_cmd = ConCommandInfo(true);
|
||||
};
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -20,7 +20,9 @@ inline std::string GameDirectory() {
|
||||
return gameDirectory;
|
||||
}
|
||||
|
||||
inline std::string PluginDirectory() { return GameDirectory() + "/addons/counterstrikesharp"; }
|
||||
inline std::string GetRootDirectory() { return GameDirectory() + "/addons/counterstrikesharp"; }
|
||||
inline std::string PluginsDirectory() { return GameDirectory() + "/addons/counterstrikesharp/plugins"; }
|
||||
inline std::string ConfigsDirectory() { return GameDirectory() + "/addons/counterstrikesharp/configs"; }
|
||||
inline std::string GamedataDirectory() { return GameDirectory() + "/addons/counterstrikesharp/gamedata"; }
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "core/global_listener.h"
|
||||
#include "core/log.h"
|
||||
#include "core/coreconfig.h"
|
||||
#include "core/gameconfig.h"
|
||||
#include "core/timer_system.h"
|
||||
#include "core/utils.h"
|
||||
@@ -83,6 +84,17 @@ bool CounterStrikeSharpMMPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, s
|
||||
GET_V_IFACE_ANY(GetEngineFactory, globals::gameEventSystem, IGameEventSystem,
|
||||
GAMEEVENTSYSTEM_INTERFACE_VERSION);
|
||||
|
||||
auto coreconfig_path = std::string(utils::ConfigsDirectory() + "/core.json");
|
||||
globals::coreConfig = new CCoreConfig(coreconfig_path);
|
||||
char coreconfig_error[255] = "";
|
||||
|
||||
if (!globals::coreConfig->Init(coreconfig_error, sizeof(coreconfig_error))) {
|
||||
CSSHARP_CORE_ERROR("Could not read \'{}\'. Error: {}", coreconfig_path, coreconfig_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
CSSHARP_CORE_INFO("CoreConfig loaded.");
|
||||
|
||||
auto gamedata_path = std::string(utils::GamedataDirectory() + "/gamedata.json");
|
||||
globals::gameConfig = new CGameConfig(gamedata_path);
|
||||
char conf_error[255] = "";
|
||||
|
||||
@@ -96,7 +96,7 @@ void* get_export(void* h, const char* name)
|
||||
// Using the nethost library, discover the location of hostfxr and get exports
|
||||
bool load_hostfxr()
|
||||
{
|
||||
std::string base_dir = counterstrikesharp::utils::PluginDirectory();
|
||||
std::string base_dir = counterstrikesharp::utils::GetRootDirectory();
|
||||
namespace css = counterstrikesharp;
|
||||
#if _WIN32
|
||||
std::wstring buffer =
|
||||
@@ -164,7 +164,7 @@ CDotNetManager::~CDotNetManager() {}
|
||||
|
||||
bool CDotNetManager::Initialize()
|
||||
{
|
||||
const std::string base_dir = counterstrikesharp::utils::PluginDirectory();
|
||||
const std::string base_dir = counterstrikesharp::utils::GetRootDirectory();
|
||||
|
||||
CSSHARP_CORE_INFO("Loading .NET runtime...");
|
||||
|
||||
@@ -184,7 +184,7 @@ bool CDotNetManager::Initialize()
|
||||
std::string((base_dir + "/api/CounterStrikeSharp.API.runtimeconfig.json").c_str());
|
||||
CSSHARP_CORE_INFO("Loading CSS API, Runtime Config: {}", wide_str);
|
||||
#endif
|
||||
|
||||
|
||||
const auto load_assembly_and_get_function_pointer = get_dotnet_load_assembly(wide_str.c_str());
|
||||
if (load_assembly_and_get_function_pointer == nullptr) {
|
||||
CSSHARP_CORE_ERROR("Failed to load CSS API.");
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "core/log.h"
|
||||
#include "schema.h"
|
||||
#include "core/function.h"
|
||||
#include "core/coreconfig.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
@@ -122,6 +123,12 @@ void SetSchemaValueByName(ScriptContext& script_context)
|
||||
auto dataType = script_context.GetArgument<DataType_t>(1);
|
||||
auto className = script_context.GetArgument<const char*>(2);
|
||||
auto memberName = script_context.GetArgument<const char*>(3);
|
||||
|
||||
if (globals::coreConfig->FollowCS2ServerGuidelines && std::find(schema::CS2BadList.begin(), schema::CS2BadList.end(), memberName) != schema::CS2BadList.end()) {
|
||||
CSSHARP_CORE_ERROR("Cannot set '{}::{}' with \"FollowCS2ServerGuidelines\" option enabled.", className, memberName);
|
||||
return;
|
||||
}
|
||||
|
||||
auto classKey = hash_32_fnv1a_const(className);
|
||||
auto memberKey = hash_32_fnv1a_const(memberName);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user