projects-jenz/AutismBotIngame/python/ingamefollowct.py

294 lines
12 KiB
Python

#!/home/autismbot1/ze_runner/venv/bin/python3
import os
import sys
import subprocess
import atexit
from threading import Timer
import string
import random
import signal
import traceback
import socket
import codecs
import json
import datetime
import time
import glob
connection_issue_counter = 0;
call_bot_connect = True
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 writeCfgInput(Input_user):
with open(looptestPath, 'w') as f:
f.write(Input_user)
#print("wrote to file: ", Input_user)
if "connect " in Input_user:
time.sleep(1.0)
open(looptestPath, 'w').close() #clearing file.
elif "wait" in Input_user:
time.sleep(0.35)
else:
time.sleep(0.5)
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.
subprocess.Popen(["rm -rf /tmp/steam*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
subprocess.Popen(["rm -rf /tmp/dbus*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
subprocess.Popen(["rm -rf /tmp/pressure*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
subprocess.Popen(["rm -rf /tmp/tigervnc*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
subprocess.Popen(["rm -rf /tmp/dumps*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
subprocess.Popen(["rm -rf /dev/shm/u100*"], shell=True, stdout=subprocess.PIPE).communicate()[0]
#users should only have permissions to delete their own files probably
def exit_handler():
print('reached exithandler')
writeCfgInput('')
#securing the looptest.cfg wont be stuck accidently with commands
kill_owned_process("pidof cstrike_linux64")
kill_owned_process("pidof xterm")
clean_up_files()
subprocess.getoutput([f"pkill -9 -u {whoami}"])
def bot_process_movement(input_line):
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)
#request by bane that bots should simply not infect people shrug
strInput = "-attack; wait 2; -use; wait 5; -attack; wait 5; cl_minmodels 1; wait 2; +use; wait 5; "
if targeteam == 3:
strInput = "-attack; wait 2; -use; wait 5; -attack; wait 5; cl_minmodels 1; wait 2; +use; wait 5; "
#python has no switches and such
if state in [5, 7]:
strInput += "-forward; wait 2; use weapon_knife; wait 5;"
elif state >= 3:
strInput += "use weapon_knife; wait 5; +forward; wait 2;"
elif state == 0:
strInput += "use weapon_p90; wait 2; -forward; wait 2;"
elif state == 1:
strInput += "wait 2; use weapon_elite; wait 3; +forward; wait 2;"
elif state == 2:
strInput += "-forward; wait 2; use weapon_elite; wait 3;"
elif state == 8:
strInput += "use weapon_knife; wait 5; +forward; wait 2;"
#print('dist_target: ', dist_target, ' enemy distance: ', enemy_distance, ' targeteam: ', targeteam, ' state:', state)
if state not in [0, 2, 5, 7, 8]:
strInput = strinput_append(strInput, 2)
#print('strInput final:', strInput)
writeCfgInput(strInput)
def strinput_append(strInput, nth):
for _ in range(3 * nth):
boolean_val = random.choice([True, False])
if boolean_val:
strInput += " +moveleft; wait 15; -moveleft; "
else:
strInput += " +moveright; wait 15; -moveright; "
return strInput
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.
time.sleep(5)
cmd = f'vncserver -localhost no -geometry 1x1 -depth 24'
#print(f'cmd: {cmd}')
subprocess.getoutput([cmd])
print('reached .bashrc executing steam and variables')
time.sleep(10)
#we sleep here to wait for .bashrc to launch steam. It takes some time
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)
time.sleep(1)
handle_bz2_map_files()
t = Timer(30, attempt_bot_connect)
t.start()
def cpulimit_pid_of_game():
pid = return_user_owned_pid("pidof cstrike_linux64")
cmd = f"cpulimit --pid={pid} --limit=5 --background"
#print('the command is: ', cmd)
subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE).communicate()[0]
def delete_lock_file():
#just delete the tmp source_engine .lock file here so multiple instances can run at same time.
subprocess.Popen(["rm -f /tmp/source_engine*.lock"], shell=True, stdout=subprocess.PIPE).communicate()[0]
def attempt_bot_connect():
global connection_issue_counter
global call_bot_connect
connection_issue_counter += 1
call_bot_connect = True
print('finished timer callback')
def handle_bz2_map_files():
#if downloading maps we give it 10 seconds delay to see if the size changed, if not its probably safe to delete the .bz2 file as no download in progress
bz2_maps = {}
while True:
found = False
for f in glob.glob(f"/home/{whoami}/.steam/debian-installation/steamapps/common/Counter-Strike Source/cstrike/download/maps/*.bz2"):
found = True
fsize = subprocess.Popen(["du", "-sh", f], stdout=subprocess.PIPE).communicate()[0].decode().split("\t")[0]
#deleting left over bz2 files because they give missing map issue
if f in bz2_maps:
#if the size is still the same it should be abandoned bz2 file that we can delete
if bz2_maps[f] == fsize:
subprocess.Popen(["rm", f], stdout=subprocess.PIPE).communicate()[0]
bz2_maps[f] = fsize
#no bz2 maps left to be concerned about
if not found:
break
time.sleep(10)
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()
delete_lock_file()
handle_bz2_map_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 150GB
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.Popen(["rm", f], stdout=subprocess.PIPE).communicate()[0]
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 = ""
#limit the cpu allowed to be used by the game instance.
time.sleep(11)
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
delete_lock_file()
#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 == "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!')
connection_issue_counter = 0
is_bot_connected_to_ze2 = False
elif "not connected to ze2" == data:
is_bot_connected_to_ze2 = False
elif "autismo connected to ze2" == data:
print('Bot connected to ze2!')
connection_issue_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 connection_issue_counter == 5:
kill_owned_process("pidof cstrike_linux64")
sock.close()
print('exiting')
sys.exit(1)
else:
if call_bot_connect:
call_bot_connect = False
print('data: ', data)
print("connection_issue_counter: ", connection_issue_counter)
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()