diff --git a/AutismBotIngame/python/ingamefollowct.py b/AutismBotIngame/python/ingamefollowct.py index 2258f24..7c5bf9b 100644 --- a/AutismBotIngame/python/ingamefollowct.py +++ b/AutismBotIngame/python/ingamefollowct.py @@ -14,19 +14,9 @@ import json import datetime import time import glob +import pwd restart_time = datetime.datetime.now() + datetime.timedelta(hours=3) -block_connection = False -the_undesired_crash_counter = 0 #hate this monkey solution -shoot_distance = 450.0 -shoot_burst_cycles = 4 -enemy_chase_distance = 450.0 -team_follow_distance = 800.0 -infect_chase_distance = 300.0 -momentum_hold_seconds = 1.4 -min_forward_wait = 6 -max_forward_wait = 12 -last_forward_time = 0.0 whoami = subprocess.getoutput("whoami") with open(f'/home/{whoami}/ze_runner/config.json') as jsonfile: @@ -49,10 +39,6 @@ def writeCfgInput(Input_user): time.sleep(0.35) open(looptestPath, 'w').close() #clearing file. -def close_observer(observer): - observer.stop() - observer.join() #supposedly needed to clear resources again. - 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. @@ -61,8 +47,12 @@ def clean_up_files(): 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) - #users should only have permissions to delete their own files probably + #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 @@ -77,8 +67,14 @@ def clean_up_files(): break file_size = cur_file_size - #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 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') @@ -87,90 +83,11 @@ def exit_handler(): kill_owned_process("pidof xterm") clean_up_files() + check_if_bz2_downloading() + delete_bsp_files() + subprocess.getoutput(f"pkill -9 -u {whoami}") -def bot_process_movement(input_line): - try: - dist_target = input_line[input_line.index("dist_target:") + len("dist_target:"):input_line.index("enemy_distance")] - enemy_distance = input_line[input_line.index("enemy_distance:") + len("enemy_distance:"):input_line.index("targeteam:")] - targeteam = input_line[input_line.index("targeteam:") + len("targeteam:"):input_line.index("state:")] - state = input_line[input_line.index("state:") + len("state:"):] - - state = int(state.strip()) - dist_target = float(dist_target) - enemy_distance = float(enemy_distance) - targeteam = int(targeteam) - except (ValueError, IndexError): - # Ignore malformed movement packets instead of crashing the main loop. - return - - global last_forward_time - strInput = "cl_minmodels 1; wait 2; " - - if targeteam == 3: - strInput = "cl_minmodels 1; wait 2; " - - def forward_burst(wait_ticks): - return f"+forward; wait {wait_ticks}; -forward; " - - is_aggressive_state = state >= 3 or state == 1 or state == 8 - far_from_team = dist_target > team_follow_distance - enemy_close = enemy_distance <= enemy_chase_distance - enemy_very_close = enemy_distance <= infect_chase_distance - very_close_to_team = dist_target < (team_follow_distance * 0.35) - momentum_active = time.time() - last_forward_time < momentum_hold_seconds - - # Decide one primary forward burst to avoid conflicting movement bursts in a single packet. - forward_ticks = 0 - if far_from_team: - # Strong regroup push when separated from teammates. - forward_ticks = random.randint(min_forward_wait, max_forward_wait + 2) - elif enemy_close: - # Controlled chase pressure when enemy is in range. - forward_ticks = random.randint(min_forward_wait - 1, max_forward_wait - 1) - elif is_aggressive_state or momentum_active: - # Keep motion alive without overcommitting. - forward_ticks = 2 - - # Prevent overshooting teammates when no nearby threat. - if very_close_to_team and not enemy_close: - forward_ticks = min(forward_ticks, 2) - - if forward_ticks > 0: - strInput += forward_burst(forward_ticks) - last_forward_time = time.time() - else: - strInput += "wait 2;" - - if enemy_very_close: - # Close-range commit with a short firing hold. - strInput += "+attack; wait 16; -attack; wait 4; " - - if dist_target <= team_follow_distance and not enemy_very_close: - # Lighter, steadier strafes while maintaining formation. - strafe_pulses = 1 if very_close_to_team else 2 - strInput = strinput_append(strInput, strafe_pulses) - if enemy_distance <= shoot_distance: - for _ in range(shoot_burst_cycles): - strInput += "+attack; wait 12; -attack; wait 4; " - #print('strInput final:', strInput) - writeCfgInput(strInput) - -def strinput_append(strInput, nth): - if nth <= 0: - return strInput - - direction_left = random.choice([True, False]) - for _ in range(nth): - # Keep direction for a pulse to reduce jitter, occasionally switch. - if direction_left: - strInput += f" +moveleft; wait {random.randint(10, 16)}; -moveleft; " - else: - strInput += f" +moveright; wait {random.randint(10, 16)}; -moveright; " - if random.random() < 0.30: - direction_left = not direction_left - return strInput - def kill_user_owned_pid(pid): #print('pid: ', pid, ' killed') pid = int(pid.strip()) @@ -226,97 +143,12 @@ def cpulimit_pid_of_game(): #cmd = f"cpulimit --pid={pid} --limit=55 --background > /dev/null 2>&1" subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).communicate()[0] -def my_file_created_function(event_path): - #print(f"New file created: {event_path}") - if event_path.startswith("/tmp/source_engine") and event_path.endswith(".lock"): - subprocess.run(["rm", "-rf", event_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - return - if not event_path.lower().endswith(".bsp.bz2"): - return - - global block_connection - block_connection = True - overwrite_file_access() #set chmod once for the bsp bz2 file. - file_size = None - - while True: - if not os.path.exists(event_path): - print(f'finished the bz2 file {event_path}') - break - - owner = pwd.getpwuid(os.stat(event_path).st_uid).pw_name - if whoami == owner: # we are the user that owns the file on disk - cur_file_size = os.path.getsize(event_path) - if file_size == cur_file_size: - print(f"Deleting {event_path} due to being stuck on download.") - subprocess.run(["rm", "-rf", event_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - continue - file_size = cur_file_size - else: - writeCfgInput("disconnect;") - time.sleep(10) - - overwrite_file_access() #set chmod for the actual bsp file - global the_undesired_crash_counter - the_undesired_crash_counter = 0 - block_connection = False - -class NewFileHandler(FileSystemEventHandler): - def on_created(self, event): - my_file_created_function(event.src_path) - -def handle_temp_files(): - #mostly its just downloading maps that we will be doing - root_dir = f"/tmp" - event_handler = NewFileHandler() - observer = Observer() - # Schedule the observer to watch the root directory and its subdirectories recursively - observer.schedule(event_handler, root_dir, recursive=True) - observer.start() - return observer - -def handle_bz2_files(): - #mostly its just downloading maps that we will be doing - root_dir = f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download" - event_handler = NewFileHandler() - observer = Observer() - # Schedule the observer to watch the root directory and its subdirectories recursively - observer.schedule(event_handler, root_dir, recursive=True) - observer.start() - return observer - -def bot_process_surf(input_line): - # Placeholder to avoid crashes until surfing behavior is implemented. - return - -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() - observer = handle_bz2_files() - observer1 = handle_temp_files() - - maps_folder_size = subprocess.Popen(["du", "-sh", f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download/maps"], stdout=subprocess.PIPE).communicate()[0].decode().split("\t")[0] - #deleting when maps folder larger than some GB - if maps_folder_size.endswith("G"): - maps_folder_size = float(maps_folder_size[:-1]) - if maps_folder_size > 40.0: - for f in glob.glob(f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download/maps/*"): - subprocess.run(["rm", "-rf", f], stdout=subprocess.PIPE) - - 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 = "" + 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() +def launch_game(): #give the game some time to launch fail_safe = 5 while return_user_owned_pid("pidof cstrike_linux64") is None: @@ -329,6 +161,28 @@ if __name__ == '__main__': time.sleep(10) cpulimit_pid_of_game() +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 = "" + + failed_connect_count = 0 + + launch_game() try: while True: try: @@ -353,52 +207,37 @@ if __name__ == '__main__': writeCfgInput(response_msg) if ip != data_ports['ovh_ip']: continue - elif data == "rtv": - response_msg = "say rtv" - writeCfgInput(response_msg) 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 + failed_connect_count = 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 + failed_connect_count = 0 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 + if datetime.datetime.now() >= restart_time or return_user_owned_pid("pidof cstrike_linux64") is None: kill_owned_process("pidof cstrike_linux64") sock.close() - close_observer(observer) - close_observer(observer1) - print('exiting after running the game for several hours or game being stuck on map change.') + print('exiting after running for several hours.') + sys.exit(1) + print('data: ', data) + overwrite_file_access() + bot_connect(data) + failed_connect_count += 1 + if failed_connect_count >= 2: + kill_owned_process("pidof cstrike_linux64") + sock.close() + print('exiting after running for several hours.') sys.exit(1) - elif not block_connection: #need this check to prevent connection spam during content downloading. - print('data: ', data, ' the_undesired_crash_counter: ', the_undesired_crash_counter) - the_undesired_crash_counter += 1 - 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) - elif data.startswith("dist_target:"): - bot_process_movement(data) - elif data.startswith("surfing:"): - bot_process_surf(data) - elif data.startswith("hull info:"): - hull_info = data[data.index("hull info:") + len("hull info:"):] - strInput = "" - if hull_info == "jump": - strInput += "+jump; wait 5; -jump; +duck; wait 50; -duck; wait 5; " - elif hull_info == "crouch": - strInput += "+duck; wait 50; -duck; wait 5; " - writeCfgInput(strInput) finally: sock.close() - close_observer(observer) - close_observer(observer1) diff --git a/AutismBotIngame/scripting/autism_bot_simulate_movement.sp b/AutismBotIngame/scripting/autism_bot_simulate_movement.sp index 040bc09..d193a92 100755 --- a/AutismBotIngame/scripting/autism_bot_simulate_movement.sp +++ b/AutismBotIngame/scripting/autism_bot_simulate_movement.sp @@ -29,8 +29,6 @@ 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 @@ -66,7 +64,7 @@ public void OnPluginStart() connect_socket(); chat_cooldown = false; - g_hTimer_bot_connect = CreateTimer(90.0, bot_check_connect, _, TIMER_REPEAT); + g_hTimer_bot_connect = CreateTimer(60.0, bot_check_connect, _, TIMER_REPEAT); g_hTimer_pressing = CreateTimer(2.0, check_team, _, TIMER_REPEAT); target_client[1] = -1; @@ -95,6 +93,30 @@ public void OnPluginEnd() } } +public void OnMapEnd() +{ + int autism_bot_counter = 0; + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && specific_bot_player[i] != -1) + { + autism_bot_counter++; + } + } + for (int i = 1; i <= MaxClients; i++) + { + if (autism_bot_counter <= 1) + { + break; + } + if (IsValidClient(i) && specific_bot_player[i] != -1) + { + KickClient(i); + autism_bot_counter--; + } + } +} + 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))