This commit is contained in:
Fabian Dill 2020-04-23 06:16:54 +02:00
parent 83b5ac389a
commit 7582767401
3 changed files with 80 additions and 14 deletions

View File

@ -16,6 +16,7 @@ ModuleUpdate.update()
import colorama import colorama
import websockets import websockets
import prompt_toolkit import prompt_toolkit
import typing
from prompt_toolkit.patch_stdout import patch_stdout from prompt_toolkit.patch_stdout import patch_stdout
import Regions import Regions
@ -48,7 +49,7 @@ class Context:
self.team = None self.team = None
self.slot = None self.slot = None
self.player_names = {} self.player_names: typing.Dict[int: str] = {}
self.locations_checked = set() self.locations_checked = set()
self.locations_scouted = set() self.locations_scouted = set()
self.items_received = [] self.items_received = []
@ -742,8 +743,12 @@ async def process_server_cmd(ctx : Context, cmd, args):
logging.info(f"[Hint]: {player_recvd}'s {item} can be found " logging.info(f"[Hint]: {player_recvd}'s {item} can be found "
f"at {get_location_name_from_address(hint.location)} in {player_find}'s World." + f"at {get_location_name_from_address(hint.location)} in {player_find}'s World." +
(" (found)" if hint.found else "")) (" (found)" if hint.found else ""))
elif cmd == "AliasUpdate":
ctx.player_names = {p: n for p, n in args}
elif cmd == 'Print': elif cmd == 'Print':
logging.info(args) logging.info(args)
else:
logging.debug(f"unknown command {args}")
def get_tags(ctx: Context): def get_tags(ctx: Context):
tags = ['Berserker'] tags = ['Berserker']

View File

@ -73,6 +73,7 @@ class Context:
self.countdown_timer = 0 self.countdown_timer = 0
self.clients = [] self.clients = []
self.received_items = {} self.received_items = {}
self.name_aliases: typing.Dict[typing.Tuple[int, int], str] = {}
self.location_checks = collections.defaultdict(set) self.location_checks = collections.defaultdict(set)
self.hint_cost = hint_cost self.hint_cost = hint_cost
self.location_check_points = location_check_points self.location_check_points = location_check_points
@ -90,9 +91,9 @@ class Context:
"received_items": tuple((k, v) for k, v in self.received_items.items()), "received_items": tuple((k, v) for k, v in self.received_items.items()),
"hints_used": tuple((key, value) for key, value in self.hints_used.items()), "hints_used": tuple((key, value) for key, value in self.hints_used.items()),
"hints": tuple((key, list(value)) for key, value in self.hints.items()), "hints": tuple((key, list(value)) for key, value in self.hints.items()),
"location_checks": tuple((key, tuple(value)) for key, value in self.location_checks.items()) "location_checks": tuple((key, tuple(value)) for key, value in self.location_checks.items()),
"name_aliases": tuple((key, value) for key, value in self.name_aliases.items()),
} }
return d return d
def set_save(self, savedata: dict): def set_save(self, savedata: dict):
@ -118,11 +119,18 @@ class Context:
self.hints[team, hint.receiving_player].add(hint) self.hints[team, hint.receiving_player].add(hint)
# even if it is the same hint, it won't be duped due to set # even if it is the same hint, it won't be duped due to set
self.hints[team, hint.finding_player].add(hint) self.hints[team, hint.finding_player].add(hint)
if "name_aliases" in savedata:
self.name_aliases.update({tuple(key): value for key, value in savedata["name_aliases"]})
self.location_checks.update({tuple(key): set(value) for key, value in savedata["location_checks"]}) self.location_checks.update({tuple(key): set(value) for key, value in savedata["location_checks"]})
logging.info(f'Loaded save file with {sum([len(p) for p in received_items.values()])} received items ' logging.info(f'Loaded save file with {sum([len(p) for p in received_items.values()])} received items '
f'for {len(received_items)} players') f'for {len(received_items)} players')
def get_aliased_name(self, team: int, slot: int):
if (team, slot) in self.name_aliases:
return f"{self.name_aliases[team, slot]} ({self.player_names[team, slot]})"
else:
return self.player_names[team, slot]
async def send_msgs(client: Client, msgs): async def send_msgs(client: Client, msgs):
websocket = client.socket websocket = client.socket
@ -134,12 +142,25 @@ async def send_msgs(client: Client, msgs):
logging.exception("Exception during send_msgs") logging.exception("Exception during send_msgs")
await client.disconnect() await client.disconnect()
def broadcast_all(ctx : Context, msgs):
async def send_json_msgs(client: Client, msg: str):
websocket = client.socket
if not websocket or not websocket.open or websocket.closed:
return
try:
await websocket.send(msg)
except websockets.ConnectionClosed:
logging.exception("Exception during send_msgs")
await client.disconnect()
def broadcast_all(ctx: Context, msgs):
for client in ctx.clients: for client in ctx.clients:
if client.auth: if client.auth:
asyncio.create_task(send_msgs(client, msgs)) asyncio.create_task(send_msgs(client, msgs))
def broadcast_team(ctx : Context, team, msgs):
def broadcast_team(ctx: Context, team, msgs):
for client in ctx.clients: for client in ctx.clients:
if client.auth and client.team == team: if client.auth and client.team == team:
asyncio.create_task(send_msgs(client, msgs)) asyncio.create_task(send_msgs(client, msgs))
@ -163,7 +184,7 @@ def notify_client(client: Client, text: str):
# separated out, due to compatibilty between clients # separated out, due to compatibilty between clients
def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]): def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
cmd = [["Hint", hints]] # make sure it is a list, as it can be set internally cmd = json.dumps([["Hint", hints]]) # make sure it is a list, as it can be set internally
texts = [['Print', format_hint(ctx, team, hint)] for hint in hints] texts = [['Print', format_hint(ctx, team, hint)] for hint in hints]
for _, text in texts: for _, text in texts:
logging.info("Notice (Team #%d): %s" % (team + 1, text)) logging.info("Notice (Team #%d): %s" % (team + 1, text))
@ -171,9 +192,23 @@ def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
if client.auth and client.team == team: if client.auth and client.team == team:
if "Berserker" in client.tags: if "Berserker" in client.tags:
payload = cmd payload = cmd
asyncio.create_task(send_json_msgs(client, payload))
else: else:
payload = texts payload = texts
asyncio.create_task(send_msgs(client, payload)) asyncio.create_task(send_msgs(client, payload))
def update_aliases(ctx: Context, team: int, client: typing.Optional[Client] = None):
cmd = json.dumps([["AliasUpdate",
[(key[1], ctx.get_aliased_name(*key)) for key, value in ctx.player_names.items() if
key[0] == team]]]) # make sure it is a list, as it can be set internally
if client is None:
for client in ctx.clients:
if client.team == team and client.auth and client.version > [2, 0, 3]:
asyncio.create_task(send_json_msgs(client, cmd))
else:
asyncio.create_task(send_json_msgs(client, cmd))
async def server(websocket, path, ctx: Context): async def server(websocket, path, ctx: Context):
client = Client(websocket, ctx) client = Client(websocket, ctx)
@ -199,7 +234,8 @@ async def server(websocket, path, ctx: Context):
async def on_client_connected(ctx: Context, client: Client): async def on_client_connected(ctx: Context, client: Client):
await send_msgs(client, [['RoomInfo', { await send_msgs(client, [['RoomInfo', {
'password': ctx.password is not None, 'password': ctx.password is not None,
'players': [(client.team, client.slot, client.name) for client in ctx.clients if client.auth], 'players': [(client.team, client.slot, ctx.name_aliases.get((client.team, client.slot), client.name)) for client
in ctx.clients if client.auth],
# tags are for additional features in the communication. # tags are for additional features in the communication.
# Name them by feature or fork, as you feel is appropriate. # Name them by feature or fork, as you feel is appropriate.
'tags': ['Berserker'], 'tags': ['Berserker'],
@ -210,10 +246,13 @@ async def on_client_disconnected(ctx: Context, client: Client):
if client.auth: if client.auth:
await on_client_left(ctx, client) await on_client_left(ctx, client)
async def on_client_joined(ctx: Context, client: Client): async def on_client_joined(ctx: Context, client: Client):
notify_all(ctx, "%s (Team #%d) has joined the game. Client(%s, %s)." % (client.name, client.team + 1, notify_all(ctx,
".".join(str(x) for x in client.version), "%s (Team #%d) has joined the game. Client(%s, %s)." % (ctx.get_aliased_name(client.team, client.slot),
client.tags)) client.team + 1,
".".join(str(x) for x in client.version),
client.tags))
async def on_client_left(ctx: Context, client: Client): async def on_client_left(ctx: Context, client: Client):
notify_all(ctx, "%s (Team #%d) has left the game" % (client.name, client.team + 1)) notify_all(ctx, "%s (Team #%d) has left the game" % (client.name, client.team + 1))
@ -515,6 +554,23 @@ class ClientMessageProcessor(CommandProcessor):
self.output("No missing location checks found.") self.output("No missing location checks found.")
return True return True
@mark_raw
def _cmd_alias(self, alias_name: str = ""):
if alias_name:
alias_name = alias_name[:15]
self.ctx.name_aliases[self.client.team, self.client.slot] = alias_name
self.output(f"Hello, {alias_name}")
update_aliases(self.ctx, self.client.team)
save(self.ctx)
return True
elif (self.client.team, self.client.slot) in self.ctx.name_aliases:
del (self.ctx.name_aliases[self.client.team, self.client.slot])
self.output("Removed Alias")
update_aliases(self.ctx, self.client.team)
save(self.ctx)
return True
return False
@mark_raw @mark_raw
def _cmd_getitem(self, item_name: str) -> bool: def _cmd_getitem(self, item_name: str) -> bool:
"""Cheat in an item""" """Cheat in an item"""
@ -685,7 +741,7 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
await send_msgs(client, [['InvalidArguments', 'Say']]) await send_msgs(client, [['InvalidArguments', 'Say']])
return return
notify_all(ctx, client.name + ': ' + args) notify_all(ctx, ctx.get_aliased_name(client.team, client.slot) + ': ' + args)
print(args) print(args)
client.messageprocessor(args) client.messageprocessor(args)
@ -718,6 +774,11 @@ class ServerCommandProcessor(CommandProcessor):
self.output(f"Could not find player {player_name} to kick") self.output(f"Could not find player {player_name} to kick")
return False return False
def _cmd_save(self) -> bool:
"""Save current state to multidata"""
save(self.ctx)
return True
def _cmd_players(self) -> bool: 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))

View File

@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
__version__ = "2.0.3" __version__ = "2.0.4"
_version_tuple = tuple(int(piece, 10) for piece in __version__.split(".")) _version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
import os import os