Add result flag to commands
This commit is contained in:
parent
356ff91cfd
commit
8ea342abe5
|
@ -789,32 +789,39 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
def __init__(self, ctx: Context):
|
def __init__(self, ctx: Context):
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
|
|
||||||
def _cmd_exit(self):
|
def _cmd_exit(self) -> bool:
|
||||||
"""Close connections and client"""
|
"""Close connections and client"""
|
||||||
self.ctx.exit_event.set()
|
self.ctx.exit_event.set()
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_snes(self, snes_address: str = ""):
|
def _cmd_snes(self, snes_address: str = "") -> bool:
|
||||||
"""Connect to a snes. Optionally include network address of a snes to connect to, otherwise show available devices"""
|
"""Connect to a snes. Optionally include network address of a snes to connect to, otherwise show available devices"""
|
||||||
self.ctx.snes_reconnect_address = None
|
self.ctx.snes_reconnect_address = None
|
||||||
asyncio.create_task(snes_connect(self.ctx, snes_address if snes_address else self.ctx.snes_address))
|
asyncio.create_task(snes_connect(self.ctx, snes_address if snes_address else self.ctx.snes_address))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_snes_close(self):
|
def _cmd_snes_close(self) -> bool:
|
||||||
"""Close connection to a currently connected snes"""
|
"""Close connection to a currently connected snes"""
|
||||||
self.ctx.snes_reconnect_address = None
|
self.ctx.snes_reconnect_address = None
|
||||||
if self.ctx.snes_socket is not None and not self.ctx.snes_socket.closed:
|
if self.ctx.snes_socket is not None and not self.ctx.snes_socket.closed:
|
||||||
asyncio.create_task(self.ctx.snes_socket.close())
|
asyncio.create_task(self.ctx.snes_socket.close())
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def _cmd_connect(self, address: str = ""):
|
def _cmd_connect(self, address: str = "") -> bool:
|
||||||
"""Connect to a MultiWorld Server"""
|
"""Connect to a MultiWorld Server"""
|
||||||
self.ctx.server_address = None
|
self.ctx.server_address = None
|
||||||
asyncio.create_task(connect(self.ctx, address if address else None))
|
asyncio.create_task(connect(self.ctx, address if address else None))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_disconnect(self):
|
def _cmd_disconnect(self) -> bool:
|
||||||
"""Disconnect from a MultiWorld Server"""
|
"""Disconnect from a MultiWorld Server"""
|
||||||
self.ctx.server_address = None
|
self.ctx.server_address = None
|
||||||
asyncio.create_task(disconnect(self.ctx))
|
asyncio.create_task(disconnect(self.ctx))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_received(self):
|
def _cmd_received(self) -> bool:
|
||||||
"""List all received items"""
|
"""List all received items"""
|
||||||
logging.info('Received items:')
|
logging.info('Received items:')
|
||||||
for index, item in enumerate(self.ctx.items_received, 1):
|
for index, item in enumerate(self.ctx.items_received, 1):
|
||||||
|
@ -822,8 +829,9 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
color(get_item_name_from_id(item.item), 'red', 'bold'),
|
color(get_item_name_from_id(item.item), 'red', 'bold'),
|
||||||
color(self.ctx.player_names[item.player], 'yellow'),
|
color(self.ctx.player_names[item.player], 'yellow'),
|
||||||
get_location_name_from_address(item.location), index, len(self.ctx.items_received)))
|
get_location_name_from_address(item.location), index, len(self.ctx.items_received)))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_missing(self):
|
def _cmd_missing(self) -> bool:
|
||||||
"""List all missing location checks, from your local game state"""
|
"""List all missing location checks, from your local game state"""
|
||||||
count = 0
|
count = 0
|
||||||
for location in [k for k, v in Regions.location_table.items() if type(v[0]) is int]:
|
for location in [k for k, v in Regions.location_table.items() if type(v[0]) is int]:
|
||||||
|
@ -835,8 +843,9 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
self.output(f"Found {count} missing location checks")
|
self.output(f"Found {count} missing location checks")
|
||||||
else:
|
else:
|
||||||
self.output("No missing location checks found.")
|
self.output("No missing location checks found.")
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_show_items(self, toggle: str = ""):
|
def _cmd_show_items(self, toggle: str = "") -> bool:
|
||||||
"""Toggle showing of items received across the team"""
|
"""Toggle showing of items received across the team"""
|
||||||
if toggle:
|
if toggle:
|
||||||
self.ctx.found_items = toggle.lower() in {"1", "true", "on"}
|
self.ctx.found_items = toggle.lower() in {"1", "true", "on"}
|
||||||
|
@ -844,6 +853,7 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
self.ctx.found_items = not self.ctx.found_items
|
self.ctx.found_items = not self.ctx.found_items
|
||||||
logging.info(f"Set showing team items to {self.ctx.found_items}")
|
logging.info(f"Set showing team items to {self.ctx.found_items}")
|
||||||
asyncio.create_task(send_msgs(self.ctx.socket, [['UpdateTags', get_tags(self.ctx)]]))
|
asyncio.create_task(send_msgs(self.ctx.socket, [['UpdateTags', get_tags(self.ctx)]]))
|
||||||
|
return True
|
||||||
|
|
||||||
def default(self, raw: str):
|
def default(self, raw: str):
|
||||||
asyncio.create_task(send_msgs(self.ctx.socket, [['Say', raw]]))
|
asyncio.create_task(send_msgs(self.ctx.socket, [['Say', raw]]))
|
||||||
|
|
|
@ -370,7 +370,7 @@ class CommandProcessor(metaclass=CommandMeta):
|
||||||
def output(self, text: str):
|
def output(self, text: str):
|
||||||
print(text)
|
print(text)
|
||||||
|
|
||||||
def __call__(self, raw: str):
|
def __call__(self, raw: str) -> typing.Optional[bool]:
|
||||||
if not raw:
|
if not raw:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
@ -384,11 +384,11 @@ class CommandProcessor(metaclass=CommandMeta):
|
||||||
if getattr(method, "raw_text", False): # method is requesting unprocessed text data
|
if getattr(method, "raw_text", False): # method is requesting unprocessed text data
|
||||||
arg = raw.split(maxsplit=1)
|
arg = raw.split(maxsplit=1)
|
||||||
if len(arg) > 1:
|
if len(arg) > 1:
|
||||||
method(self, arg[1]) # argument text was found, so pass it along
|
return method(self, arg[1]) # argument text was found, so pass it along
|
||||||
else:
|
else:
|
||||||
method(self) # argument may be optional, try running without args
|
return method(self) # argument may be optional, try running without args
|
||||||
else:
|
else:
|
||||||
method(self, *command[1:]) # pass each word as argument
|
return method(self, *command[1:]) # pass each word as argument
|
||||||
else:
|
else:
|
||||||
self.default(raw)
|
self.default(raw)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -449,30 +449,33 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
def default(self, raw: str):
|
def default(self, raw: str):
|
||||||
pass # default is client sending just text
|
pass # default is client sending just text
|
||||||
|
|
||||||
def _cmd_players(self):
|
def _cmd_players(self) -> bool:
|
||||||
"""Get information about connected and missing players"""
|
"""Get information about connected and missing players"""
|
||||||
if len(self.ctx.player_names) < 10:
|
if len(self.ctx.player_names) < 10:
|
||||||
notify_all(self.ctx, get_players_string(self.ctx))
|
notify_all(self.ctx, get_players_string(self.ctx))
|
||||||
else:
|
else:
|
||||||
self.output(get_players_string(self.ctx))
|
self.output(get_players_string(self.ctx))
|
||||||
|
|
||||||
def _cmd_forfeit(self):
|
def _cmd_forfeit(self) -> bool:
|
||||||
"""Surrender and send your remaining items out to their recipients"""
|
"""Surrender and send your remaining items out to their recipients"""
|
||||||
if self.ctx.forfeit_allowed:
|
if self.ctx.forfeit_allowed:
|
||||||
forfeit_player(self.ctx, self.client.team, self.client.slot)
|
forfeit_player(self.ctx, self.client.team, self.client.slot)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
self.output(
|
self.output(
|
||||||
"Sorry, client forfeiting has been disabled on this server. You can ask the server admin for a /forfeit")
|
"Sorry, client forfeiting has been disabled on this server. You can ask the server admin for a /forfeit")
|
||||||
|
return False
|
||||||
|
|
||||||
def _cmd_countdown(self, seconds: str = "10"):
|
def _cmd_countdown(self, seconds: str = "10") -> bool:
|
||||||
"""Start a countdown in seconds"""
|
"""Start a countdown in seconds"""
|
||||||
try:
|
try:
|
||||||
timer = int(seconds)
|
timer = int(seconds)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
timer = 10
|
timer = 10
|
||||||
asyncio.create_task(countdown(self.ctx, timer))
|
asyncio.create_task(countdown(self.ctx, timer))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_missing(self):
|
def _cmd_missing(self) -> bool:
|
||||||
"""List all missing location checks from the server's perspective"""
|
"""List all missing location checks from the server's perspective"""
|
||||||
buffer = "" # try not to spam small packets over network
|
buffer = "" # try not to spam small packets over network
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -485,9 +488,10 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
self.output(buffer + f"Found {count} missing location checks")
|
self.output(buffer + f"Found {count} missing location checks")
|
||||||
else:
|
else:
|
||||||
self.output("No missing location checks found.")
|
self.output("No missing location checks found.")
|
||||||
|
return True
|
||||||
|
|
||||||
@mark_raw
|
@mark_raw
|
||||||
def _cmd_getitem(self, item_name: str):
|
def _cmd_getitem(self, item_name: str) -> bool:
|
||||||
"""Cheat in an item"""
|
"""Cheat in an item"""
|
||||||
if self.ctx.item_cheat:
|
if self.ctx.item_cheat:
|
||||||
item_name, usable, response = get_intended_text(item_name, Items.item_table.keys())
|
item_name, usable, response = get_intended_text(item_name, Items.item_table.keys())
|
||||||
|
@ -496,13 +500,16 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
get_received_items(self.ctx, self.client.team, self.client.slot).append(new_item)
|
get_received_items(self.ctx, self.client.team, self.client.slot).append(new_item)
|
||||||
notify_all(self.ctx, 'Cheat console: sending "' + item_name + '" to ' + self.client.name)
|
notify_all(self.ctx, 'Cheat console: sending "' + item_name + '" to ' + self.client.name)
|
||||||
send_new_items(self.ctx)
|
send_new_items(self.ctx)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.output("Cheating is disabled.")
|
self.output("Cheating is disabled.")
|
||||||
|
return False
|
||||||
|
|
||||||
@mark_raw
|
@mark_raw
|
||||||
def _cmd_hint(self, item_or_location: str = ""):
|
def _cmd_hint(self, item_or_location: str = "") -> bool:
|
||||||
"""Use !hint {item_name/location_name}, for example !hint Lamp or !hint Link's House. """
|
"""Use !hint {item_name/location_name}, for example !hint Lamp or !hint Link's House. """
|
||||||
points_available = self.ctx.location_check_points * len(
|
points_available = self.ctx.location_check_points * len(
|
||||||
self.ctx.location_checks[self.client.team, self.client.slot]) - \
|
self.ctx.location_checks[self.client.team, self.client.slot]) - \
|
||||||
|
@ -516,6 +523,7 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
else: # location name
|
else: # location name
|
||||||
hints = collect_hints_location(self.ctx, self.client.team, self.client.slot, item_name)
|
hints = collect_hints_location(self.ctx, self.client.team, self.client.slot, item_name)
|
||||||
notify_hints(self.ctx, self.client.team, hints)
|
notify_hints(self.ctx, self.client.team, hints)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
item_name, usable, response = get_intended_text(item_or_location)
|
item_name, usable, response = get_intended_text(item_or_location)
|
||||||
if usable:
|
if usable:
|
||||||
|
@ -531,6 +539,7 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
if item_name in self.ctx.hints_sent[self.client.team, self.client.slot]:
|
if item_name in self.ctx.hints_sent[self.client.team, self.client.slot]:
|
||||||
notify_hints(self.ctx, self.client.team, hints)
|
notify_hints(self.ctx, self.client.team, hints)
|
||||||
self.output("Hint was previously used, no points deducted.")
|
self.output("Hint was previously used, no points deducted.")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
found = 0
|
found = 0
|
||||||
for hint in hints:
|
for hint in hints:
|
||||||
|
@ -538,6 +547,7 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
if not found:
|
if not found:
|
||||||
notify_hints(self.ctx, self.client.team, hints)
|
notify_hints(self.ctx, self.client.team, hints)
|
||||||
self.output("No new items found, no points deducted.")
|
self.output("No new items found, no points deducted.")
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
if self.ctx.hint_cost:
|
if self.ctx.hint_cost:
|
||||||
can_pay = points_available // (self.ctx.hint_cost * found) >= 1
|
can_pay = points_available // (self.ctx.hint_cost * found) >= 1
|
||||||
|
@ -554,10 +564,13 @@ class ClientMessageProcessor(CommandProcessor):
|
||||||
f"You have {points_available} points and need at least "
|
f"You have {points_available} points and need at least "
|
||||||
f"{self.ctx.hint_cost}, "
|
f"{self.ctx.hint_cost}, "
|
||||||
f"more if multiple items are still to be found.")
|
f"more if multiple items are still to be found.")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
self.output("Nothing found. Item/Location may not exist.")
|
self.output("Nothing found. Item/Location may not exist.")
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
||||||
|
@ -670,42 +683,47 @@ class ServerCommandProcessor(CommandProcessor):
|
||||||
notify_all(self.ctx, '[Server]: ' + raw)
|
notify_all(self.ctx, '[Server]: ' + raw)
|
||||||
|
|
||||||
@mark_raw
|
@mark_raw
|
||||||
def _cmd_kick(self, player_name: str):
|
def _cmd_kick(self, player_name: str) -> bool:
|
||||||
"""Kick specified player from the server"""
|
"""Kick specified player from the server"""
|
||||||
for client in self.ctx.clients:
|
for client in self.ctx.clients:
|
||||||
if client.auth and client.name.lower() == player_name.lower() and client.socket and not client.socket.closed:
|
if client.auth and client.name.lower() == player_name.lower() and client.socket and not client.socket.closed:
|
||||||
asyncio.create_task(client.socket.close())
|
asyncio.create_task(client.socket.close())
|
||||||
self.output(f"Kicked {client.name}")
|
self.output(f"Kicked {client.name}")
|
||||||
break
|
return True
|
||||||
else:
|
|
||||||
self.output("Could not find player to kick")
|
|
||||||
|
|
||||||
def _cmd_players(self):
|
self.output(f"Could not find player {player_name} to kick")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _cmd_players(self) -> bool:
|
||||||
"""Get information about connected players"""
|
"""Get information about connected players"""
|
||||||
self.output(get_players_string(self.ctx))
|
self.output(get_players_string(self.ctx))
|
||||||
|
return True
|
||||||
|
|
||||||
def _cmd_exit(self):
|
def _cmd_exit(self) -> bool:
|
||||||
"""Shutdown the server"""
|
"""Shutdown the server"""
|
||||||
asyncio.create_task(self.ctx.server.ws_server._close())
|
asyncio.create_task(self.ctx.server.ws_server._close())
|
||||||
self.ctx.running = False
|
self.ctx.running = False
|
||||||
|
return True
|
||||||
|
|
||||||
@mark_raw
|
@mark_raw
|
||||||
def _cmd_password(self, new_password: str = ""):
|
def _cmd_password(self, new_password: str = "") -> bool:
|
||||||
"""Set the server password. Leave the password text empty to remove the password"""
|
"""Set the server password. Leave the password text empty to remove the password"""
|
||||||
set_password(self.ctx, new_password if new_password else None)
|
set_password(self.ctx, new_password if new_password else None)
|
||||||
|
return True
|
||||||
|
|
||||||
@mark_raw
|
@mark_raw
|
||||||
def _cmd_forfeit(self, player_name: str):
|
def _cmd_forfeit(self, player_name: str) -> bool:
|
||||||
"""Send out the remaining items from a player's game to their intended recipients"""
|
"""Send out the remaining items from a player's game to their intended recipients"""
|
||||||
seeked_player = player_name.lower()
|
seeked_player = player_name.lower()
|
||||||
for (team, slot), name in self.ctx.player_names.items():
|
for (team, slot), name in self.ctx.player_names.items():
|
||||||
if name.lower() == seeked_player:
|
if name.lower() == seeked_player:
|
||||||
forfeit_player(self.ctx, team, slot)
|
forfeit_player(self.ctx, team, slot)
|
||||||
break
|
return True
|
||||||
else:
|
|
||||||
self.output("Could not find player to forfeit")
|
|
||||||
|
|
||||||
def _cmd_send(self, player_name: str, *item_name: str):
|
self.output(f"Could not find player {player_name} to forfeit")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _cmd_send(self, player_name: str, *item_name: str) -> bool:
|
||||||
"""Sends an item to the specified player"""
|
"""Sends an item to the specified player"""
|
||||||
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
||||||
if usable:
|
if usable:
|
||||||
|
@ -718,13 +736,15 @@ class ServerCommandProcessor(CommandProcessor):
|
||||||
get_received_items(self.ctx, client.team, client.slot).append(new_item)
|
get_received_items(self.ctx, client.team, client.slot).append(new_item)
|
||||||
notify_all(self.ctx, 'Cheat console: sending "' + item + '" to ' + client.name)
|
notify_all(self.ctx, 'Cheat console: sending "' + item + '" to ' + client.name)
|
||||||
send_new_items(self.ctx)
|
send_new_items(self.ctx)
|
||||||
return
|
return True
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
|
return False
|
||||||
|
|
||||||
def _cmd_hint(self, player_name: str, *item_or_location: str):
|
def _cmd_hint(self, player_name: str, *item_or_location: str) -> bool:
|
||||||
"""Send out a hint for a player's item or location to their team"""
|
"""Send out a hint for a player's item or location to their team"""
|
||||||
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
||||||
if usable:
|
if usable:
|
||||||
|
@ -739,11 +759,14 @@ class ServerCommandProcessor(CommandProcessor):
|
||||||
else: # location name
|
else: # location name
|
||||||
hints = collect_hints_location(self.ctx, team, slot, item)
|
hints = collect_hints_location(self.ctx, team, slot, item)
|
||||||
notify_hints(self.ctx, team, hints)
|
notify_hints(self.ctx, team, hints)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
return
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.output(response)
|
self.output(response)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def console(ctx: Context):
|
async def console(ctx: Context):
|
||||||
|
|
Loading…
Reference in New Issue