Add a way to show found items on client/server (#52)
* Add a way to show found items on client/server * item show stuff: use less ram and cpu, rename a few things * Add UpdateTags server command. Co-authored-by: Fabian Dill <fabian.dill@web.de>
This commit is contained in:
parent
2bec95b4f8
commit
7b620e94f7
|
@ -5,8 +5,6 @@ import logging
|
|||
import typing
|
||||
import urllib.parse
|
||||
import atexit
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
exit_func = atexit.register(input, "Press enter to close.")
|
||||
|
@ -31,7 +29,7 @@ class ReceivedItem(typing.NamedTuple):
|
|||
player: int
|
||||
|
||||
class Context:
|
||||
def __init__(self, snes_address, server_address, password):
|
||||
def __init__(self, snes_address, server_address, password, found_items):
|
||||
self.snes_address = snes_address
|
||||
self.server_address = server_address
|
||||
|
||||
|
@ -64,6 +62,7 @@ class Context:
|
|||
self.awaiting_rom = False
|
||||
self.rom = None
|
||||
self.auth = None
|
||||
self.found_items = found_items
|
||||
|
||||
|
||||
color_codes = {'reset': 0, 'bold': 1, 'underline': 4, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34,
|
||||
|
@ -719,6 +718,12 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||
logging.info(
|
||||
'%s sent %s to %s (%s)' % (player_sent, item, player_recvd, get_location_name_from_address(location)))
|
||||
|
||||
elif cmd == 'ItemFound':
|
||||
found = ReceivedItem(*args)
|
||||
item = color(get_item_name_from_id(found.item), 'cyan' if found.player != ctx.slot else 'green')
|
||||
player_sent = color(ctx.player_names[found.player], 'yellow' if found.player != ctx.slot else 'magenta')
|
||||
logging.info('%s found %s (%s)' % (player_sent, item, get_location_name_from_address(found.location)))
|
||||
|
||||
elif cmd == 'Hint':
|
||||
hints = [Utils.Hint(*hint) for hint in args]
|
||||
for hint in hints:
|
||||
|
@ -733,6 +738,11 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||
elif cmd == 'Print':
|
||||
logging.info(args)
|
||||
|
||||
def get_tags(ctx: Context):
|
||||
tags = ['Berserker']
|
||||
if ctx.found_items:
|
||||
tags.append('FoundItems')
|
||||
return tags
|
||||
|
||||
async def server_auth(ctx: Context, password_requested):
|
||||
if password_requested and not ctx.password:
|
||||
|
@ -745,7 +755,7 @@ async def server_auth(ctx: Context, password_requested):
|
|||
ctx.awaiting_rom = False
|
||||
ctx.auth = ctx.rom.copy()
|
||||
await send_msgs(ctx.socket, [['Connect', {
|
||||
'password': ctx.password, 'rom': ctx.auth, 'version': [1, 2, 0], 'tags': ['Berserker']
|
||||
'password': ctx.password, 'rom': ctx.auth, 'version': [1, 2, 0], 'tags': get_tags(ctx)
|
||||
}]])
|
||||
|
||||
async def console_input(ctx : Context):
|
||||
|
@ -819,6 +829,14 @@ async def console_loop(ctx : Context):
|
|||
if location not in ctx.locations_checked:
|
||||
logging.info('Missing: ' + location)
|
||||
|
||||
elif precommand == "show_items":
|
||||
if len(command) > 1:
|
||||
ctx.found_items = command[1].lower() in {"1", "true", "on"}
|
||||
else:
|
||||
ctx.found_items = not ctx.found_items
|
||||
logging.info(f"Set showing team items to {ctx.found_items}")
|
||||
asyncio.create_task(send_msgs(ctx.socket, [['UpdateTags', get_tags(ctx)]]))
|
||||
|
||||
elif precommand == "license":
|
||||
with open("LICENSE") as f:
|
||||
logging.info(f.read())
|
||||
|
@ -970,6 +988,7 @@ async def main():
|
|||
parser.add_argument('--connect', default=None, help='Address of the multiworld host.')
|
||||
parser.add_argument('--password', default=None, help='Password of the multiworld host.')
|
||||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||
parser.add_argument('--founditems', default=False, action='store_true', help='Show items found by other players for themselves.')
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||
|
@ -981,7 +1000,7 @@ async def main():
|
|||
logging.info(f"Wrote rom file to {romfile}")
|
||||
asyncio.create_task(run_game(romfile))
|
||||
|
||||
ctx = Context(args.snes, args.connect, args.password)
|
||||
ctx = Context(args.snes, args.connect, args.password, args.founditems)
|
||||
|
||||
input_task = asyncio.create_task(console_loop(ctx))
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import logging
|
|||
import zlib
|
||||
import collections
|
||||
import typing
|
||||
import os
|
||||
|
||||
import ModuleUpdate
|
||||
|
||||
|
@ -39,6 +38,10 @@ class Client:
|
|||
self.tags = []
|
||||
self.version = [0, 0, 0]
|
||||
|
||||
@property
|
||||
def wants_item_notification(self):
|
||||
return self.auth and "FoundItems" in self.tags
|
||||
|
||||
|
||||
class Context:
|
||||
def __init__(self, host: str, port: int, password: str, location_check_points: int, hint_cost: int,
|
||||
|
@ -135,7 +138,6 @@ def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
|
|||
payload = texts
|
||||
asyncio.create_task(send_msgs(client.socket, payload))
|
||||
|
||||
|
||||
async def server(websocket, path, ctx: Context):
|
||||
client = Client(websocket)
|
||||
ctx.clients.append(client)
|
||||
|
@ -210,7 +212,7 @@ def get_connected_players_string(ctx: Context):
|
|||
return f'{len(auth_clients)} players of {len(ctx.player_names)} connected ' + text[:-1]
|
||||
|
||||
|
||||
def get_received_items(ctx: Context, team: int, player: int):
|
||||
def get_received_items(ctx: Context, team: int, player: int) -> typing.List[ReceivedItem]:
|
||||
return ctx.received_items.setdefault((team, player), [])
|
||||
|
||||
|
||||
|
@ -235,7 +237,7 @@ def forfeit_player(ctx: Context, team: int, slot: int):
|
|||
|
||||
|
||||
def register_location_checks(ctx: Context, team: int, slot: int, locations):
|
||||
ctx.location_checks[team, slot] |= set(locations)
|
||||
|
||||
|
||||
found_items = False
|
||||
for location in locations:
|
||||
|
@ -254,8 +256,17 @@ def register_location_checks(ctx: Context, team: int, slot: int, locations):
|
|||
recvd_items.append(new_item)
|
||||
if slot != target_player:
|
||||
broadcast_team(ctx, team, [['ItemSent', (slot, location, target_player, target_item)]])
|
||||
logging.info('(Team #%d) %s sent %s to %s (%s)' % (team+1, ctx.player_names[(team, slot)], get_item_name_from_id(target_item), ctx.player_names[(team, target_player)], get_location_name_from_address(location)))
|
||||
logging.info('(Team #%d) %s sent %s to %s (%s)' % (
|
||||
team + 1, ctx.player_names[(team, slot)], get_item_name_from_id(target_item),
|
||||
ctx.player_names[(team, target_player)], get_location_name_from_address(location)))
|
||||
found_items = True
|
||||
elif target_player == slot: # local pickup, notify clients of the pickup
|
||||
if location not in ctx.location_checks[team, slot]:
|
||||
for client in ctx.clients:
|
||||
if client.team == team and client.wants_item_notification:
|
||||
asyncio.create_task(
|
||||
send_msgs(client.socket, [['ItemFound', (target_item, location, slot)]]))
|
||||
ctx.location_checks[team, slot] |= set(locations)
|
||||
send_new_items(ctx)
|
||||
|
||||
if found_items:
|
||||
|
@ -398,6 +409,12 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
|||
logging.info(f"{client.name} in team {client.team+1} scouted {', '.join([l[0] for l in locs])}")
|
||||
await send_msgs(client.socket, [['LocationInfo', [l[1:] for l in locs]]])
|
||||
|
||||
if cmd == 'UpdateTags':
|
||||
if not args or type(args) is not list:
|
||||
await send_msgs(client.socket, [['InvalidArguments', 'UpdateTags']])
|
||||
return
|
||||
client.tags = args
|
||||
|
||||
if cmd == 'Say':
|
||||
if type(args) is not str or not args.isprintable():
|
||||
await send_msgs(client.socket, [['InvalidArguments', 'Say']])
|
||||
|
|
Loading…
Reference in New Issue