From dd44cb5e4989232918966295336ceb4fc22b96e7 Mon Sep 17 00:00:00 2001 From: jenz Date: Fri, 9 Oct 2026 15:05:32 +0200 Subject: [PATCH] making the simulate movement plugin obsolete and moving all the connection management related content into a separate plugin so that its isolated from other functionality --- .../scripting/autism_bot_connection.sp | 400 ++++++++++++++++++ ... autism_bot_simulate_movement_obsolete.sp} | 0 2 files changed, 400 insertions(+) create mode 100644 AutismBotIngame/scripting/autism_bot_connection.sp rename AutismBotIngame/scripting/{autism_bot_simulate_movement.sp => autism_bot_simulate_movement_obsolete.sp} (100%) diff --git a/AutismBotIngame/scripting/autism_bot_connection.sp b/AutismBotIngame/scripting/autism_bot_connection.sp new file mode 100644 index 0000000..2968632 --- /dev/null +++ b/AutismBotIngame/scripting/autism_bot_connection.sp @@ -0,0 +1,400 @@ +#pragma semicolon 1 +#pragma newdecls required + +#define PLUGIN_AUTHOR "jenz" +#define PLUGIN_VERSION "1.0" +#define generic_length 256 + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_AUTISM_BOTS 4 + +int g_BotIndex[MAXPLAYERS + 1]; // 0 = not an autism bot, 1-4 = autism bot index + +int ports[7] = {48470, 48471, 48472, 48473, 48474, 48479, 48480}; //last three indexes are ports its sending udp from in plugin +int server_ports[2] = {27015, 27035}; //server ports: ze, ze2 + +bool chat_cooldown = false; + +//socket for bot communication +Handle global_socket = null; + +ConVar g_cvHostPort; + +public Plugin myinfo = +{ + name = "autism bot connection", + author = PLUGIN_AUTHOR, + description = "connection state management for the autism bots", + version = PLUGIN_VERSION, + url = "" +}; + +public void OnPluginStart() +{ + g_cvHostPort = FindConVar("hostport"); + + //talking + RegConsoleCmd("sm_autism", cmd_talk, "talking to the bot through java application"); + RegConsoleCmd("sm_botrtv", cmd_botrtv, "making bots rtv"); + + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); + + //UDP connection + connect_socket(); + chat_cooldown = false; + + // map downloads go to the first port only, once per cycle + CreateTimer(60.0, Timer_MapDownload, _, TIMER_REPEAT); + + // per-bot connect checks, staggered 5 seconds apart + for (int index = 1; index <= MAX_AUTISM_BOTS; index++) + { + CreateTimer(float(index - 1) * 5.0 + 0.1, Timer_StartConnectCheck, index); + } + + // team joining / killing bots when no human is left alive + CreateTimer(2.0, Timer_CheckTeam, _, TIMER_REPEAT); + + // late load + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && IsClientAuthorized(i)) + { + OnClientPostAdminCheck(i); + } + } +} + +// --------------------------------------------------------------------------- +// bot identification +// --------------------------------------------------------------------------- + +int GetBotClientForIndex(int index) +{ + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && g_BotIndex[i] == index) + { + return i; + } + } + return -1; +} + +public void OnClientPutInServer(int client) +{ + g_BotIndex[client] = 0; +} + +public void OnClientPostAdminCheck(int client) +{ + g_BotIndex[client] = 0; + if (IsFakeClient(client)) + { + return; + } + + int index = GetClientAutismBotIndex(client); + if (index < 1 || index > MAX_AUTISM_BOTS) + { + return; + } + g_BotIndex[client] = index; + + //checks if ze or ze2 + char msg[generic_length]; + if (g_cvHostPort.IntValue == server_ports[0]) + { + Format(msg, sizeof(msg), "autismo connected to ze"); + } + else if (g_cvHostPort.IntValue == server_ports[1]) + { + Format(msg, sizeof(msg), "autismo connected to ze2"); + } + else + { + return; + } + send_socket_msg(msg, strlen(msg), ports[index - 1]); +} + +public void OnClientDisconnect(int client) +{ + g_BotIndex[client] = 0; +} + +// --------------------------------------------------------------------------- +// team joining +// --------------------------------------------------------------------------- + +public Action Timer_CheckTeam(Handle timer, any data) +{ + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client) || g_BotIndex[client] == 0) + { + continue; + } + if (GetClientTeam(client) <= CS_TEAM_SPECTATOR) + { + ChangeClientTeam(client, CS_TEAM_T); + CreateTimer(1.0, zspawn, GetClientSerial(client)); + } + } + + // no real human alive on CT anymore -> kill the bots so they dont hold up the round + bool found_valid_ct = false; + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) continue; + if (g_BotIndex[client] == 0 && GetClientTeam(client) > CS_TEAM_T && IsPlayerAlive(client)) + { + found_valid_ct = true; + break; + } + } + if (!found_valid_ct) + { + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) continue; + if (g_BotIndex[client] != 0 && IsPlayerAlive(client)) + { + ForcePlayerSuicide(client); + } + } + } + return Plugin_Continue; +} + +public Action zspawn(Handle hTimer, int Serial) +{ + int client; + if ((client = GetClientFromSerial(Serial)) == 0) + { + return Plugin_Handled; + } + if (IsValidClient(client)) + { + FakeClientCommandEx(client, "joinclass"); + FakeClientCommandEx(client, "say /zspawn"); + } + return Plugin_Handled; +} + +// --------------------------------------------------------------------------- +// chat / rtv +// --------------------------------------------------------------------------- + +public void Event_RoundStart(Handle event, const char[] name, bool dontBroadcast) +{ + chat_cooldown = false; +} + +public void cmd_talk_help(int port, int client, char[] info) +{ + char msg[generic_length * 5]; + chat_cooldown = true; + char magic_code[16]; + Format(magic_code, sizeof(magic_code), autism_bot_code); //included with unloze.secrets simply. + Format(msg, sizeof(msg), "clientmessage:%N %s %s", client, magic_code, info); + send_socket_msg(msg, strlen(msg), port); + CreateTimer(2.0, bot_chat_cooldown); +} + +public Action cmd_talk(int client, int args) +{ + char info[generic_length]; + GetCmdArgString(info, sizeof(info)); + + if (strlen(info) == 0) + { + PrintToChat(client, "Add a message to the command if autism bot is ingame and running on discord"); + return Plugin_Handled; + } + // kept from the original plugin: only the bot accounts themselves can use sm_autism + if (g_BotIndex[client] == 0) + { + return Plugin_Handled; + } + if (chat_cooldown) + { + PrintToChat(client, "spamming bot too much, applying cooldown"); + return Plugin_Handled; + } + bool bot_found = false; + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && g_BotIndex[i] != 0) + { + cmd_talk_help(ports[g_BotIndex[i] - 1], client, info); + bot_found = true; + } + } + if (!bot_found) + { + PrintToChat(client, "bot not connected to server"); + } + return Plugin_Handled; +} + +public Action bot_chat_cooldown(Handle timer, any data) +{ + chat_cooldown = false; + return Plugin_Continue; +} + +public Action cmd_botrtv(int client, int args) +{ + if (CheckCommandAccess(client, "sm_kick", ADMFLAG_KICK) || CheckCommandAccess(client, "sm_reserved", ADMFLAG_RESERVATION)) + { + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && g_BotIndex[i] != 0) + { + FakeClientCommandEx(i, "say rtv"); + } + } + } + return Plugin_Handled; +} + +// --------------------------------------------------------------------------- +// connection management +// --------------------------------------------------------------------------- + +public void OnMapVoteEnd(const char[] map) +{ + if (StrEqual(map, "##extend##") || StrEqual(map, "##dontchange##")) + { + return; + } + + char msg[generic_length]; + Format(msg, sizeof(msg), "download map:%s", map); + send_socket_msg(msg, strlen(msg), ports[0]); +} + +public Action Timer_MapDownload(Handle timer, any data) +{ + char map[64]; + char msg[generic_length]; + if (GetNextMap(map, sizeof(map))) + { + Format(msg, sizeof(msg), "download map:%s", map); + send_socket_msg(msg, strlen(msg), ports[0]); + } + + GetCurrentMap(map, sizeof(map)); + Format(msg, sizeof(msg), "download map:%s", map); + send_socket_msg(msg, strlen(msg), ports[0]); + return Plugin_Continue; +} + +public Action Timer_StartConnectCheck(Handle timer, int index) +{ + CreateTimer(60.0, Timer_ConnectCheck, index, TIMER_REPEAT); + return Plugin_Stop; +} + +//this is designed for being ran from several css servers +public Action Timer_ConnectCheck(Handle timer, int index) +{ + char msg[generic_length]; + int client_count = GetClientCount(false); + bool connected = GetBotClientForIndex(index) != -1; + int port = ports[index - 1]; + + if (g_cvHostPort.IntValue == server_ports[0]) + { + int max_allowed_players = 55; + if (client_count > max_allowed_players) + { + Format(msg, sizeof(msg), "connect to ze2"); + send_socket_msg(msg, strlen(msg), port); + } + else if (client_count < max_allowed_players - 5 && !connected) + { + Format(msg, sizeof(msg), "connect to ze"); + send_socket_msg(msg, strlen(msg), port); + } + } + else if (!connected) + { + //in case the bot is not connected to ze2 anymore make sure that is_bot_connected_to_ze2 is set to false again + Format(msg, sizeof(msg), "not connected to ze2"); + send_socket_msg(msg, strlen(msg), port); + } + return Plugin_Continue; +} + +// --------------------------------------------------------------------------- +// socket +// --------------------------------------------------------------------------- + +public void send_socket_msg(char[] query_msg, int len, int port) +{ + if (global_socket != null && SocketIsConnected(global_socket)) + { + SocketSendTo(global_socket, query_msg, len, "127.0.0.1", port); //udp + } +} + +stock void connect_socket() +{ + if (global_socket == null || !SocketIsConnected(global_socket)) + { + int target_port = ports[4]; //default ze + if (g_cvHostPort.IntValue == server_ports[1]) + { + //ze2 + target_port = ports[5]; + } + global_socket = SocketCreate(SOCKET_UDP, OnSocketError); + SocketSetOption(global_socket, SocketReuseAddr, 1); + SocketBind(global_socket, "127.0.0.0", target_port); + SocketConnect(global_socket, OnSocketConnected, OnSocketReceive, OnSocketDisconnected, "127.0.0.1", target_port); + } +} + +public void OnSocketError(Handle socket, const int errorType, const int errorNum, any args) +{ + CloseHandle(socket); + if (socket == global_socket) + { + global_socket = null; // otherwise connect_socket would query a closed handle + } + LogError("[autism bot] Socket error: %d (errno %d)", errorType, errorNum); + CreateTimer(10.0, TimerConnect); +} + +public void OnSocketConnected(Handle socket, int arg) +{ +} + +public void OnSocketReceive(Handle socket, char receiveData[3500], int dataSize, int hFile) +{ +} + +public void OnSocketDisconnected(Handle socket, int arg) +{ + CreateTimer(10.0, TimerConnect); +} + +public Action TimerConnect(Handle timer, any arg) +{ + connect_socket(); + return Plugin_Stop; +} + +stock bool IsValidClient(int client) +{ + return client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client); +} diff --git a/AutismBotIngame/scripting/autism_bot_simulate_movement.sp b/AutismBotIngame/scripting/autism_bot_simulate_movement_obsolete.sp similarity index 100% rename from AutismBotIngame/scripting/autism_bot_simulate_movement.sp rename to AutismBotIngame/scripting/autism_bot_simulate_movement_obsolete.sp