1from io import StringIO 2 3import freeOrionAIInterface as fo 4from freeorion_tools import chat_human 5from code import InteractiveInterpreter 6import logging 7import sys 8from logging import error 9 10interpreter = InteractiveInterpreter({'fo': fo}) 11debug_mode = False 12 13 14RED = '<rgba 255 0 0 255>%s</rgba>' 15WHITE = '<rgba 255 255 255 255>%s</rgba>' 16ENTERING_DEBUG_MESSAGE = 'Entering debug mode' 17 18 19def handle_debug_chat(sender, message): 20 global debug_mode 21 human_id = [x for x in fo.allPlayerIDs() if fo.playerIsHost(x)][0] 22 ais = [x for x in fo.allPlayerIDs() if not fo.playerIsHost(x)] 23 is_debug_chat = False 24 if message == ENTERING_DEBUG_MESSAGE: 25 is_debug_chat = True 26 if sender != human_id: 27 return is_debug_chat # don't chat with bots 28 elif message == 'stop': 29 is_debug_chat = True 30 if debug_mode: 31 chat_human("exiting debug mode") 32 debug_mode = False 33 elif debug_mode: 34 print('>', message, end='') 35 is_debug_chat = True 36 out, err = [x.strip('\n') for x in shell(message)] 37 if out: 38 chat_human(WHITE % out) 39 if err: 40 chat_human(RED % err) 41 elif message.startswith('start'): 42 is_debug_chat = True 43 try: 44 player_id = int(message[5:].strip()) 45 except ValueError as e: 46 error(e) 47 chat_human(str(e)) 48 return True 49 if player_id == fo.playerID(): 50 debug_mode = True 51 52 initial_code = [ 53 'from aistate_interface import get_aistate', 54 ] 55 56 # add some variables to scope: (name, help text, value) 57 scopes_variable = ( 58 ('ai', 'aistate', 'get_aistate()'), 59 ('u', 'universe', 'fo.getUniverse()'), 60 ('e', 'empire', 'fo.getEmpire()'), 61 ) 62 for var, _, code in scopes_variable: 63 initial_code.append('%s = %s' % (var, code)) 64 65 shell(';'.join(initial_code)) 66 67 variable_template = '<u><rgba 255 255 0 255>%s</rgba></u>%s %s' 68 variables = (variable_template % (var, ' ' * (3 - len(var)), name) for var, name, _ in scopes_variable) 69 chat_human(WHITE % "%s\n" 70 "Print <rgba 255 255 0 255>'stop'</rgba> to exit.\n" 71 "Local variables:\n" 72 " %s" % (ENTERING_DEBUG_MESSAGE, '\n '.join(variables))) 73 74 elif message == 'help': 75 is_debug_chat = True 76 if ais[0] == fo.playerID(): 77 chat_human(WHITE % "Chat commands:") 78 chat_human(WHITE % " <u><rgba 0 255 255 255>start id</rgba></u>: start debug for selected empire") 79 chat_human(WHITE % " <u><rgba 0 255 255 255>stop</rgba></u>: stop debug") 80 chat_human(WHITE % "Empire ids:") 81 for player in fo.allPlayerIDs(): 82 if not fo.playerIsHost(player): 83 chat_human(' <rgba {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}>id={0.empireID} empire_name={0.name}</rgba> player_name={1}'.format(fo.getEmpire(fo.playerEmpireID(player)), fo.playerName(player))) 84 return is_debug_chat 85 86 87def shell(msg): 88 old_stdout = sys.stdout 89 old_stderr = sys.stderr 90 91 sys.stdout = StringIO() 92 sys.stderr = StringIO() 93 handler = logging.StreamHandler(sys.stdout) 94 logging.getLogger().addHandler(handler) 95 96 interpreter.runsource(msg) 97 98 logging.getLogger().removeHandler(handler) 99 100 sys.stdout.seek(0) 101 out = sys.stdout.read() 102 sys.stderr.seek(0) 103 err = sys.stderr.read() 104 sys.stdout = old_stdout 105 sys.stderr = old_stderr 106 return out, err 107