From 435d3edf6c6ada99bae5b4ed3cbf8a1a2bf83a3b Mon Sep 17 00:00:00 2001 From: jenz Date: Wed, 6 May 2026 14:01:06 +0200 Subject: [PATCH] removed autism bot movement from python file over to sourcemod and redid how connections are done to the server as well as map delection --- AutismBotIngame/python/new_ingame_followct.py | 237 ++++++++ .../scripting/autism_bot_simulate_movement.sp | 528 ++++++++++++++++++ 2 files changed, 765 insertions(+) create mode 100644 AutismBotIngame/python/new_ingame_followct.py create mode 100755 AutismBotIngame/scripting/autism_bot_simulate_movement.sp diff --git a/AutismBotIngame/python/new_ingame_followct.py b/AutismBotIngame/python/new_ingame_followct.py new file mode 100644 index 0000000..c815ae6 --- /dev/null +++ b/AutismBotIngame/python/new_ingame_followct.py @@ -0,0 +1,237 @@ +#!/home/autismbot1/ze_runner/venv/bin/python3 +import os +import sys +import subprocess +import atexit +import pwd +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler +import random +import signal +import socket +import codecs +import json +import datetime +import time +import glob + +restart_time = datetime.datetime.now() + datetime.timedelta(hours=3) +the_undesired_crash_counter = 0 #hate this monkey solution + +whoami = subprocess.getoutput("whoami") +with open(f'/home/{whoami}/ze_runner/config.json') as jsonfile: + data_ports = json.load(jsonfile) +looptestPath = f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/cfg/looptest.cfg" +chatmsg = "" + +def overwrite_file_access(): + #setting defaults with setfacl for the download directory does not work seemingly + subprocess.Popen(["chmod", "-R", "g+rwx", f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).communicate() + +def writeCfgInput(Input_user): + with open(looptestPath, 'w') as f: + f.write(Input_user) + #print("wrote to file: ", Input_user) + if "connect" in Input_user or "retry;" in Input_user: + #give extra time for disconnect, retry and connect commands + time.sleep(1.0) + else: + time.sleep(0.35) + open(looptestPath, 'w').close() #clearing file. + +def clean_up_files(): + #deleting POSIX shared memory objects, as long as one process has them open they exist. THis is to prevent /dev/shm from being full + #due to steam child processes. + #even with steam turned offline might there be chromium web browsers left over from steam who still hold processes open. + #only kind of potential issues from this is steam cloud being out of sync, which is really fucking irrelevant. + for pattern in ["/tmp/steam*", "/tmp/dbus*", "/tmp/pressure*", "/tmp/tigervnc*", "/tmp/dumps*", "/dev/shm/u100*"]: + for path in glob.glob(pattern): + subprocess.run(["rm", "-rf", path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + #clean up the game cache as it otherwise just keeps growing in gigabyte size + subprocess.run(["rm", "-rf", f"/home/{whoami}/.steam/steam/steamapps/common/Counter-Strike Source/cstrike/cache"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + +def check_if_bz2_downloading(): + #users should only have permissions to delete their own files probably + #check if any bz2 files left over. + for f in glob.glob(f"/home/{whoami}/.steam/steam/steamapps/common/Counter-Strike Source/cstrike/download/**/*.bz2", recursive=True): + file_size = None + while True: + time.sleep(10) + if not os.path.exists(f): + break # finished downloading, bz2 file is removed. + cur_file_size = os.path.getsize(f) + if file_size == cur_file_size: + # delete the bz2 file if its not progressing downloading + subprocess.run(["rm", "-rf", f], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + break + file_size = cur_file_size + +def delete_bsp_files(): + #quite a more radical approach to just always delete all maps, well the download should be quick and the remaining bots have the bsp in memory... + #the bots would have struggle connecting sometimes due to bsp files that were already downloaded before hand (maybe corrupted?) + for f in glob.glob(f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download/maps/*"): + #ai slop IF statement for checking if file modified less than 10 minutes ago. + if time.time() - os.path.getmtime(f) < 600: + continue + subprocess.run(["rm", "-rf", f], stdout=subprocess.PIPE) + +def exit_handler(): + print('reached exithandler') + #securing the looptest.cfg wont be stuck accidently with commands + kill_owned_process("pidof cstrike_linux64") + kill_owned_process("pidof xterm") + + clean_up_files() + check_if_bz2_downloading() + delete_bsp_files() + + subprocess.getoutput(f"pkill -9 -u {whoami}") + +def kill_user_owned_pid(pid): + #print('pid: ', pid, ' killed') + pid = int(pid.strip()) + os.kill(pid, signal.SIGKILL) + time.sleep(10) + +def return_user_owned_pid(pidof): + owner_pid = subprocess.getoutput([f"{pidof}"]) + if owner_pid: + for pid in owner_pid.split(" "): + username = subprocess.getoutput([f"""ps -o user= -p {pid}"""]) + if username == whoami: + return pid + return None + +def kill_owned_process(pidof): + pid = return_user_owned_pid(pidof) + while pid: + kill_user_owned_pid(pid) + pid = return_user_owned_pid(pidof) + +def restart_sdl_and_steam(): + #subprocess.getoutput(["screen -XS XTERM quit"]) + kill_owned_process("pidof cstrike_linux64") + kill_owned_process("pidof xterm") + + subprocess.getoutput([f'vncserver -kill']) #only displays vncservers for the specific user. + subprocess.getoutput([f'vncserver -list -cleanstale']) #cleans stale sessions by removing files from disk + time.sleep(5) + + cmd = f'vncserver -localhost no -geometry 1x1 -depth 24' + #cmd = f'vncserver -localhost no -geometry 800x800 -depth 24' + #print(f'cmd: {cmd}') + subprocess.getoutput(cmd) + print('reached .bashrc executing steam and variables') + +def bot_connect(data): + #use whatever ip you want here to connect with + str1 = "" + if "connect to ze" == data: + str1 = f"connect {data_ports['server_ip_port_ze']};" + elif "connect to ze2" == data: + str1 = f"connect {data_ports['server_ip_port_ze2']};" #wait 15000; + writeCfgInput(str1) + +def cpulimit_pid_of_game(): + # ' > /dev/null' redirects stdout to /dev/null + # '2>&1' redirects stderr to the same place as stdout + pid = return_user_owned_pid("pidof cstrike_linux64") + if pid is None: + return + cmd = f"cpulimit --pid={pid} --limit=25 --background > /dev/null 2>&1" + #cmd = f"cpulimit --pid={pid} --limit=55 --background > /dev/null 2>&1" + subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).communicate()[0] + + time.sleep(3) + for source_engine_lock in glob.glob("/tmp/source_engine_*"): + subprocess.run(["rm", "-rf", source_engine_lock], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + overwrite_file_access() + +if __name__ == '__main__': + atexit.register(exit_handler) + local_port = data_ports['udp_port'] + external_port_messages = data_ports['chat_external_port'] + buffer_size = 4096 #potentially not large enough? + + clean_up_files() + check_if_bz2_downloading() + delete_bsp_files() + + restart_sdl_and_steam() + is_bot_connected_to_ze2 = False + + print('preparing to launch game....') + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(("", local_port)) + sock.settimeout(5.0) + messager_name = "" + + #give the game some time to launch + fail_safe = 5 + while return_user_owned_pid("pidof cstrike_linux64") is None: + #just a fail safe to prevent being stuck forever. + if fail_safe <= 0: + sys.exit(1) + time.sleep(10) + print("launching game...") + fail_safe -= 1 + time.sleep(10) + cpulimit_pid_of_game() + + try: + while True: + try: + #print("socket waiting for recvfrom") + data, addr = sock.recvfrom(buffer_size) + except socket.timeout: + continue + data = codecs.decode(data, "utf-8", "ignore") + ip = addr[0] + port = addr[1] + #print('port: ', port, " ip: ", ip) + #print('data: ', data) + if not data: + continue + + #print("ip: ", ip, " port: ", port) + if ip == data_ports['discord_bot_ip'] and port == external_port_messages: + if messager_name in data: + messager_name = "" + response_msg = f"""say {messager_name} {data}""" + print("remote UDP packet response_msg: ", response_msg) + writeCfgInput(response_msg) + if ip != data_ports['ovh_ip']: + continue + elif data == "bot kicked server full": + print('bot kicked server full: ', datetime.datetime.now().time()) + elif "autismo connected to ze" == data: + print('Bot connected to ze!') + is_bot_connected_to_ze2 = False + the_undesired_crash_counter = 0 + elif "not connected to ze2" == data: + is_bot_connected_to_ze2 = False + elif "autismo connected to ze2" == data: + print('Bot connected to ze2!') + the_undesired_crash_counter = 0 + is_bot_connected_to_ze2 = True + elif "connect to ze" == data or ("connect to ze2" == data and not is_bot_connected_to_ze2): + if datetime.datetime.now() >= restart_time or return_user_owned_pid("pidof cstrike_linux64") is None or the_undesired_crash_counter >= 5: + #it already finished downloading the contnet, it just cant connect. probably stuck. shitty solution welp + kill_owned_process("pidof cstrike_linux64") + sock.close() + print('exiting after running the game for several hours or game being stuck on map change.') + sys.exit(1) + print('data: ', data, ' the_undesired_crash_counter: ', the_undesired_crash_counter) + the_undesired_crash_counter += 1 + check_if_bz2_downloading() + overwrite_file_access() + bot_connect(data) + elif "clientmessage:" in data: + messager_name = data.split("clientmessage:", 1)[1].split(f" {data_ports['magic_secret']}")[0] + databyte_send_message = messager_name + data.split(f"{data_ports['magic_secret']}")[1] + sock.sendto(databyte_send_message.encode(), (data_ports["discord_bot_ip"], external_port_messages)) + #print('databyte_send_message: ', databyte_send_message) + finally: + sock.close() diff --git a/AutismBotIngame/scripting/autism_bot_simulate_movement.sp b/AutismBotIngame/scripting/autism_bot_simulate_movement.sp new file mode 100755 index 0000000..b7efc63 --- /dev/null +++ b/AutismBotIngame/scripting/autism_bot_simulate_movement.sp @@ -0,0 +1,528 @@ +#pragma semicolon 1 +#pragma newdecls required +#define DEBUG + +#define PLUGIN_AUTHOR "jenz" +#define PLUGIN_VERSION "1.9" +#define generic_length 256 + +#include +#include +#include +#include +#include +#include +#include + +int target_client[5]; //4 autism bots. + +#define BUFFER_SIZE 198 // ~2 seconds at 66 tick +enum struct FrameData { + int buttons; + float vel[3]; + float angles[3]; + int impulse; +} + +FrameData g_Buffer[MAXPLAYERS+1][BUFFER_SIZE]; +int g_WriteHead[MAXPLAYERS+1]; // where were writing next +int g_FrameCount[MAXPLAYERS+1]; // total frames captured +int g_DelayTicks = 128; // delay + + + +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 input +Handle global_socket; + +//timer handle +Handle g_hTimer_pressing = null; +Handle g_hTimer_bot_connect = null; + +int specific_bot_player[MAXPLAYERS + 1]; + +public Plugin myinfo = +{ + name = "autism bot simulate player movement", + author = PLUGIN_AUTHOR, + description = "just copies player movement to the autism bots", + version = PLUGIN_VERSION, + url = "" +}; + +public void OnPluginStart() +{ + //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; + + g_hTimer_bot_connect = CreateTimer(30.0, bot_check_connect, _, TIMER_REPEAT); + g_hTimer_pressing = CreateTimer(2.0, check_team, _, TIMER_REPEAT); + + target_client[1] = -1; + target_client[2] = -1; + target_client[3] = -1; + target_client[4] = -1; + + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i)) + { + OnClientPostAdminCheck(i); + } + } +} + +public void OnPluginEnd() +{ + if (g_hTimer_pressing != null) + { + delete g_hTimer_pressing; + } + if (g_hTimer_bot_connect != null) + { + delete g_hTimer_bot_connect; + } +} + +public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]) +{ + if (!IsValidClient(client) || IsFakeClient(client)) + { + return; + } + int head = g_WriteHead[client]; + g_Buffer[client][head].buttons = buttons; + g_Buffer[client][head].impulse = impulse; + g_Buffer[client][head].vel = vel; + g_Buffer[client][head].angles = angles; + + g_WriteHead[client] = (head + 1) % BUFFER_SIZE; + g_FrameCount[client]++; +} + +public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) +{ + if (specific_bot_player[client] == -1 || !IsValidClient(target_client[specific_bot_player[client]])) + { + return Plugin_Continue; + } + int target = target_client[specific_bot_player[client]]; + // Read from the slot that is DelayTicks behind current write head + int readSlot = (g_WriteHead[target] - g_DelayTicks + BUFFER_SIZE) % BUFFER_SIZE; + + buttons = g_Buffer[target][readSlot].buttons; + impulse = g_Buffer[target][readSlot].impulse; + vel = g_Buffer[target][readSlot].vel; + angles = g_Buffer[target][readSlot].angles; + + return Plugin_Changed; +} + +public void Event_RoundStart(Handle event, const char[] name, bool dontBroadcast) +{ + target_client[1] = -1; + target_client[2] = -1; + target_client[3] = -1; + target_client[4] = -1; + + chat_cooldown = false; + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && IsPlayerAlive(i) && specific_bot_player[i] != -1) + { + for (int j = 1; j <= MaxClients; j++) + { + if (IsValidClient(j) && GetClientTeam(j) == GetClientTeam(i) && IsPlayerAlive(j) && GetClientIdleTime(j) < 20) + { + if (target_client[1] == j || target_client[2] == j || target_client[3] == j || target_client[4]) + { + continue; //one of the autism bots already got this dude as their target. + } + float vec[3]; + GetClientAbsOrigin(j, vec); + TeleportEntity(i, vec, NULL_VECTOR, NULL_VECTOR); + target_client[specific_bot_player[i]] = j; + break; + } + } + } + } +} + +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 void is_autism_bot1(int client) +{ + char auth[50]; + GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); + if (StrEqual("[U:1:120378081]", auth, false) || StrEqual("STEAM_0:1:60189040", auth, false)) + { + specific_bot_player[client] = 1; + } +} + +public void is_autism_bot2(int client) +{ + char auth[50]; + GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); + if (StrEqual("[U:1:1036189204]", auth, false) || StrEqual("STEAM_0:0:518094602", auth, false)) + { + specific_bot_player[client] = 2; + } +} + +public void is_autism_bot3(int client) +{ + char auth[50]; + GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); + if (StrEqual("[U:1:408797742]", auth, false) || StrEqual("STEAM_0:0:204398871", auth, false)) + { + specific_bot_player[client] = 3; + } +} + +public void is_autism_bot4(int client) +{ + char auth[50]; + GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); + if (StrEqual("[U:1:1221121532]", auth, false) || StrEqual("STEAM_0:0:610560766", auth, false)) + { + specific_bot_player[client] = 4; + } +} + +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) && specific_bot_player[i] != -1) + { + FakeClientCommandEx(i, "say rtv"); + } + } + } + return Plugin_Handled; +} + +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; + } + if (specific_bot_player[client] == -1) + { + 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) && specific_bot_player[i] != -1) + { + int port_number = specific_bot_player[i] - 1; + cmd_talk_help(ports[port_number], 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 void send_socket_msg(char[] query_msg, int len, int port) +{ + //LogMessage("query_msg: %s port: %i", query_msg, port); + if (global_socket != INVALID_HANDLE && SocketIsConnected(global_socket)) + SocketSendTo(global_socket, query_msg, len, "127.0.0.1", port); //udp +} + +public Action bot_check_connect(Handle timer, any data) +{ + //this is designed for being ran from several css servers + int client_count = GetClientCount(false); + char msg[generic_length]; + int i_port = GetConVarInt(FindConVar("hostport")); + bool bot1_connected = false; + bool bot2_connected = false; + bool bot3_connected = false; + bool bot4_connected = false; + for (int i = 1; i <= MaxClients; i++) + if (IsValidClient(i) && !IsFakeClient(i)) + { + if (specific_bot_player[i] == 1) + bot1_connected = true; + if (specific_bot_player[i] == 2) + bot2_connected = true; + if (specific_bot_player[i] == 3) + bot3_connected = true; + if (specific_bot_player[i] == 4) + bot4_connected = true; + } + + if (i_port == server_ports[0]) + { + int max_allowed_players = 55; + char current_map[128]; + GetCurrentMap(current_map, sizeof(current_map)); + if (client_count > max_allowed_players) + { + Format(msg, sizeof(msg), "connect to ze2"); + send_socket_msg(msg, strlen(msg), ports[0]); + send_socket_msg(msg, strlen(msg), ports[1]); + send_socket_msg(msg, strlen(msg), ports[2]); + send_socket_msg(msg, strlen(msg), ports[3]); + } + else if (client_count < max_allowed_players - 5) + { + Format(msg, sizeof(msg), "connect to ze"); + if (!bot1_connected) + send_socket_msg(msg, strlen(msg), ports[0]); + if (!bot2_connected) + send_socket_msg(msg, strlen(msg), ports[1]); + if (!bot3_connected) + send_socket_msg(msg, strlen(msg), ports[2]); + if (!bot4_connected) + send_socket_msg(msg, strlen(msg), ports[3]); + } + } + else + { + //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"); + if (!bot1_connected) + send_socket_msg(msg, strlen(msg), ports[0]); + if (!bot2_connected) + send_socket_msg(msg, strlen(msg), ports[1]); + if (!bot3_connected) + send_socket_msg(msg, strlen(msg), ports[2]); + if (!bot4_connected) + send_socket_msg(msg, strlen(msg), ports[3]); + } + return Plugin_Continue; +} + +public Action check_team(Handle timer, any data) +{ + int valid_ct_counter = 0; + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) continue; + if (specific_bot_player[client] == -1 && GetClientTeam(client) > CS_TEAM_SPECTATOR) + { + valid_ct_counter++; + } + } + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) + { + continue; + } + if (specific_bot_player[client] != -1 && GetClientTeam(client) <= CS_TEAM_SPECTATOR) + { + if (valid_ct_counter < 3) + { + continue; + } + ChangeClientTeam(client, CS_TEAM_T); + continue; + } + if (specific_bot_player[client] != -1) + { + if (IsPlayerAlive(client)) + { + target_client[specific_bot_player[client]] = GetClosestClient_option1(client); + } + } + } + bool found_valid_ct = false; + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) continue; + if (specific_bot_player[client] == -1 && GetClientTeam(client) > CS_TEAM_SPECTATOR && IsPlayerAlive(client)) + { + found_valid_ct = true; + break; + } + } + if (!found_valid_ct) + { + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client)) continue; + if (specific_bot_player[client] != -1 && IsPlayerAlive(client)) + { + ForcePlayerSuicide(client); + } + } + } + return Plugin_Continue; +} + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client)) + return true; + return false; +} + +public int GetClosestClient_option1(int autism_client) +{ + float nearestdistance = -1.0; + int nearest = -1; + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && !IsFakeClient(i) && IsPlayerAlive(i) && i != autism_client) + { + if (GetClientIdleTime(i) > 20 || GetClientTeam(autism_client) != GetClientTeam(i)) + { + continue; + } + float pos[3]; + GetEntPropVector(i, Prop_Send, "m_vecOrigin", pos); + float dist_target = get_power_distance(autism_client, pos); + + if (specific_bot_player[i] != -1) + { + //just making sure bots have lowest priority + dist_target = 9000000.0; + } + if (nearestdistance < 0 || dist_target < nearestdistance) + { + nearest = i; + nearestdistance = dist_target; + } + } + } + return nearest; +} + +public float get_power_distance(int target_player, float pos[3]) +{ + float vec[3]; + GetClientAbsOrigin(target_player, vec); + return GetVectorDistance(vec, pos); +} + +public void OnClientPutInServer(int client) +{ + specific_bot_player[client] = -1; +} + +public void OnClientPostAdminCheck(int client) +{ + specific_bot_player[client] = -1; + is_autism_bot1(client); + is_autism_bot2(client); + is_autism_bot3(client); + is_autism_bot4(client); + + //checks if ze or ze2 + int i_port = GetConVarInt(FindConVar("hostport")); + char msg[generic_length]; + if (i_port == server_ports[0]) + { + Format(msg, sizeof(msg), "autismo connected to ze"); + } + else + { + Format(msg, sizeof(msg), "autismo connected to ze2"); + } + + if (specific_bot_player[client] != -1) + { + send_socket_msg(msg, strlen(msg), ports[specific_bot_player[client] - 1]); + } +} + +public void OnSocketError(Handle socket, const int errorType, const int errorNum, any args) +{ + CloseHandle(socket); + LogError("[MR] Socket error: %d (errno %d)", errorType, errorNum); + CreateTimer(10.0, TimerConnect, INVALID_HANDLE, TIMER_HNDL_CLOSE); +} + +stock void connect_socket() +{ + if (global_socket == INVALID_HANDLE || !SocketIsConnected(global_socket)) + { + int i_port = GetConVarInt(FindConVar("hostport")); + int target_port = ports[4]; //default ze + if (i_port == server_ports[1]) + { + //ze2 + target_port = ports[5]; + } + //socket otherwise declare in public OnConfigsExecuted(){} + 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); //48474 on ze + } +} + +public void OnClientDisconnect(int client) +{ + specific_bot_player[client] = -1; +} + +//Socket callback +public void OnSocketConnected(Handle socket, int arg) +{ + +} + +//manage message +public void OnSocketReceive(Handle socket, char receiveData [3500], int dataSize, int hFile) +{ + +} + +public void OnSocketDisconnected(Handle socket, int arg) +{ + CreateTimer(10.0, TimerConnect, INVALID_HANDLE, TIMER_HNDL_CLOSE); +} + +public Action TimerConnect(Handle timer, any arg) +{ + connect_socket(); + return Plugin_Handled; +}