|
24 | 24 | #pragma semicolon 1 |
25 | 25 | #pragma newdecls required |
26 | 26 |
|
27 | | -#define PLUGIN_VERSION "22w26c" |
| 27 | +#define PLUGIN_VERSION "22w34a" |
28 | 28 |
|
29 | 29 | public Plugin myinfo = { |
30 | 30 | name = "Meta Chat Processor", |
@@ -63,6 +63,11 @@ enum mcpTransportMethod (+=1) { |
63 | 63 | mcpTransport_PrintToChat, //on drixevels discussion thread unf404 seemd to like this more, will probably break chat filters tho |
64 | 64 | } |
65 | 65 | mcpTransportMethod g_messageTransport = mcpTransport_SayText; //how to send message |
| 66 | +enum mcpMessageHookMethod (+=1) { |
| 67 | + mcpHook_UserMessage, |
| 68 | + mcpHook_CommandListener |
| 69 | +} |
| 70 | +mcpMessageHookMethod g_hookMethod = mcpHook_UserMessage; //how to hook messages |
66 | 71 | bool g_fixCompatPostCalls = true; //always call OnChatMessagePost for scp? |
67 | 72 | enum mcpInputSanity (<<=1) { |
68 | 73 | mcpInputUnchecked = 0, |
@@ -161,20 +166,36 @@ public void OnPluginStart() { |
161 | 166 | g_bUseProtobuf = (CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf); |
162 | 167 | g_processedMessages = new ArrayList(sizeof(MessageData)); |
163 | 168 |
|
164 | | - ParseConfigs(); |
| 169 | + LoadDataFiles(); |
165 | 170 | pluginAPI_init(); |
166 | 171 |
|
167 | | - UserMsg userMessage; |
168 | | - if ((userMessage = GetUserMessageId("SayText2")) != INVALID_MESSAGE_ID) { |
169 | | - if (g_bUseProtobuf) |
170 | | - HookUserMessage(userMessage, OnUserMessage_SayText2Proto, true); |
171 | | - else |
172 | | - HookUserMessage(userMessage, OnUserMessage_SayText2BB, true); |
173 | | - //} else if ((userMessage = GetUserMessageId("SayText")) != INVALID_MESSAGE_ID) { |
174 | | - //SCP only supported dods? maybe add that if people ask for it |
175 | | - } else { |
176 | | - LogError("Could not hook chat messages for this game - UserMessage SayText2 invalid"); |
177 | | - SetFailState("This game is currently not supported"); |
| 172 | + switch (g_hookMethod) { |
| 173 | + case mcpHook_UserMessage: { |
| 174 | + UserMsg userMessage; |
| 175 | + if ((userMessage = GetUserMessageId("SayText2")) != INVALID_MESSAGE_ID) { |
| 176 | + if (g_bUseProtobuf) |
| 177 | + HookUserMessage(userMessage, OnUserMessage_SayText2Proto, true); |
| 178 | + else |
| 179 | + HookUserMessage(userMessage, OnUserMessage_SayText2BB, true); |
| 180 | + //} else if ((userMessage = GetUserMessageId("SayText")) != INVALID_MESSAGE_ID) { |
| 181 | + //SCP only supported dods? maybe add that if people ask for it |
| 182 | + } else { |
| 183 | + LogError("Could not hook chat messages for this game - UserMessage SayText2 invalid"); |
| 184 | + SetFailState("This game is currently not supported, you might try switching hook mode"); |
| 185 | + } |
| 186 | + } |
| 187 | + case mcpHook_CommandListener: { |
| 188 | + if (!CommandExists("say") || !CommandExists("say_team")) { |
| 189 | + LogError("Could not hook chat messages for this game - Commands do not exist"); |
| 190 | + SetFailState("This game is currently not supported, you might try switching hook mode"); |
| 191 | + } else if (!AddCommandListener(OnCommand_SayCommand, "say") || !AddCommandListener(OnCommand_SayCommand, "say_team")) { |
| 192 | + LogError("Could not hook chat messages for this game - Command hooks not available"); |
| 193 | + SetFailState("This game is currently not supported, you might try switching hook mode"); |
| 194 | + } |
| 195 | + } |
| 196 | + default: { |
| 197 | + SetFailState("Invalid value for g_hookMethod"); |
| 198 | + } |
178 | 199 | } |
179 | 200 |
|
180 | 201 | ConVar version = CreateConVar("mcp_version", PLUGIN_VERSION, "MetaChatProcessor Version", FCVAR_DONTRECORD|FCVAR_NOTIFY); |
@@ -259,6 +280,52 @@ public Action OnUserMessage_SayText2BB(UserMsg msg_id, BfRead msg, const int[] p |
259 | 280 | return ProcessSayText2(); |
260 | 281 | } |
261 | 282 |
|
| 283 | +public Action OnCommand_SayCommand(int client, const char[] command, int argc) { |
| 284 | + if (!client || !IsClientInGame(client)) return Plugin_Continue; |
| 285 | + bool teamSay = StrEqual(command, "say_team"); |
| 286 | + int team = GetClientTeam(client); |
| 287 | + |
| 288 | + // collect basic message options |
| 289 | + g_currentMessage.Reset(); |
| 290 | + g_currentMessage.sender = client; |
| 291 | + g_currentMessage.options = mcpMsgDefault; |
| 292 | + if (g_sanitizeInput & mcpInputStripColors) g_currentMessage.options |= mcpMsgRemoveColors; |
| 293 | + |
| 294 | + // generate sender flags |
| 295 | + if (team == 1) g_currentMessage.senderflags = mcpSenderSpectator; |
| 296 | + else if (!IsPlayerAlive(client)) g_currentMessage.senderflags = mcpSenderDead; |
| 297 | + else g_currentMessage.senderflags = mcpSenderNone; |
| 298 | + // generate target group |
| 299 | + if (team == 1) g_currentMessage.group = mcpTargetSpecator; |
| 300 | + else if (team && teamSay) { |
| 301 | + if (g_msgNameTagCount) g_currentMessage.group = view_as<mcpTargetGroup>(team); |
| 302 | + else g_currentMessage.group = mcpTargetTeamSender; |
| 303 | + } |
| 304 | + else g_currentMessage.group = mcpTargetNone; |
| 305 | + |
| 306 | + // build message format string mock |
| 307 | + BuildMessageFormat(g_currentMessage.senderflags, g_currentMessage.group, g_currentMessage.msg_name, sizeof(MessageData::msg_name)); |
| 308 | + // fetch name and message |
| 309 | + GetClientName(client, g_currentMessage.sender_name, sizeof(MessageData::sender_name)); |
| 310 | + GetCmdArgString(g_currentMessage.message, 128); //this uses the max length of the chat box, no cheating with console |
| 311 | + |
| 312 | + // replace all control characters with a question mark. not possible through steam, but hacker can do |
| 313 | + int len = strlen(g_currentMessage.sender_name); |
| 314 | + for (int pos; pos<len; pos++) if (g_currentMessage.sender_name[pos] < 0x32) g_currentMessage.sender_name[pos]='?'; |
| 315 | + // copy as initial display name |
| 316 | + strcopy(g_currentMessage.sender_display, sizeof(MessageData::sender_display), g_currentMessage.sender_name); |
| 317 | + |
| 318 | + // collect recipients |
| 319 | + g_currentMessage.listRecipients.Clear(); |
| 320 | + for (int target=1; target<=MaxClients; target++) { |
| 321 | + if (!IsClientInGame(target) || IsFakeClient(target)) continue; |
| 322 | + if (teamSay && GetClientTeam(target) != team) continue; |
| 323 | + g_currentMessage.listRecipients.Push(target); |
| 324 | + } |
| 325 | + |
| 326 | + return ProcessSayText2(); //can be reused for command hook |
| 327 | +} |
| 328 | + |
262 | 329 | Action ProcessSayText2() { |
263 | 330 | Action result; |
264 | 331 | g_currentMessage.valid = true; |
|
0 commit comments