From 0a5b24be2b714b741d837f4392a455788c4b07ce Mon Sep 17 00:00:00 2001 From: Jarno Date: Tue, 23 Aug 2022 01:02:10 +0200 Subject: [PATCH] [Core] Phase out Print packets and added Countdown type to print json (#812) * [Core] Added Countdown type to print json to distinct the count down message from other types * Added backward compatibility check * Fixed review comments * Updated header category * Apply suggestions from code review Co-authored-by: Hussein Farran * Completely phased out Print in favor of PrintJson * Updated docs to warn about phasing out of Print * Removed faulty import Co-authored-by: Hussein Farran --- MultiServer.py | 38 ++++++++++++++++++++++++++++++-------- docs/network protocol.md | 16 ++++++++++++++-- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/MultiServer.py b/MultiServer.py index 8a1844bf..6354f8e7 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -36,6 +36,7 @@ from NetUtils import Endpoint, ClientStatus, NetworkItem, decode, encode, Networ SlotType min_client_version = Version(0, 1, 6) +print_command_compatability_threshold = Version(0, 3, 5) # Remove backwards compatibility around 0.3.7 colorama.init() # functions callable on storable data on the server by clients @@ -291,20 +292,27 @@ class Context: # text - def notify_all(self, text): + def notify_all(self, text: str): logging.info("Notice (all): %s" % text) - self.broadcast_all([{"cmd": "Print", "text": text}]) + broadcast_text_all(self, text) def notify_client(self, client: Client, text: str): if not client.auth: return logging.info("Notice (Player %s in team %d): %s" % (client.name, client.team + 1, text)) - asyncio.create_task(self.send_msgs(client, [{"cmd": "Print", "text": text}])) + if client.version >= print_command_compatability_threshold: + asyncio.create_task(self.send_msgs(client, [{"cmd": "PrintJSON", "data": [{ "text": text }]}])) + else: + asyncio.create_task(self.send_msgs(client, [{"cmd": "Print", "text": text}])) def notify_client_multiple(self, client: Client, texts: typing.List[str]): if not client.auth: return - asyncio.create_task(self.send_msgs(client, [{"cmd": "Print", "text": text} for text in texts])) + if client.version >= print_command_compatability_threshold: + asyncio.create_task(self.send_msgs(client, + [{"cmd": "PrintJSON", "data": [{ "text": text }]} for text in texts])) + else: + asyncio.create_task(self.send_msgs(client, [{"cmd": "Print", "text": text} for text in texts])) # loading @@ -721,19 +729,33 @@ async def on_client_left(ctx: Context, client: Client): ctx.client_connection_timers[client.team, client.slot] = datetime.datetime.now(datetime.timezone.utc) -async def countdown(ctx: Context, timer): - ctx.notify_all(f'[Server]: Starting countdown of {timer}s') +async def countdown(ctx: Context, timer: int): + broadcast_countdown(ctx, timer, f"[Server]: Starting countdown of {timer}s") if ctx.countdown_timer: ctx.countdown_timer = timer # timer is already running, set it to a different time else: ctx.countdown_timer = timer while ctx.countdown_timer > 0: - ctx.notify_all(f'[Server]: {ctx.countdown_timer}') + broadcast_countdown(ctx, ctx.countdown_timer, f"[Server]: {ctx.countdown_timer}") ctx.countdown_timer -= 1 await asyncio.sleep(1) - ctx.notify_all(f'[Server]: GO') + broadcast_countdown(ctx, 0, f"[Server]: GO") ctx.countdown_timer = 0 +def broadcast_text_all(ctx: Context, text: str, additional_arguments: dict = {}): + old_clients, new_clients = [], [] + + for teams in ctx.clients.values(): + for clients in teams.values(): + for client in clients: + new_clients.append(client) if client.version >= print_command_compatability_threshold \ + else old_clients.append(client) + + ctx.broadcast(old_clients, [{"cmd": "Print", "text": text }]) + ctx.broadcast(new_clients, [{**{"cmd": "PrintJSON", "data": [{ "text": text }]}, **additional_arguments}]) + +def broadcast_countdown(ctx: Context, timer: int, message: str): + broadcast_text_all(ctx, message, { "type": "Countdown", "countdown": timer }) def get_players_string(ctx: Context): auth_clients = {(c.team, c.slot) for c in ctx.endpoints if c.auth} diff --git a/docs/network protocol.md b/docs/network protocol.md index b12768e2..34251424 100644 --- a/docs/network protocol.md +++ b/docs/network protocol.md @@ -152,7 +152,8 @@ The arguments for RoomUpdate are identical to [RoomInfo](#RoomInfo) barring: All arguments for this packet are optional, only changes are sent. ### Print -Sent to clients purely to display a message to the player. +Sent to clients purely to display a message to the player. +* *Deprecation warning: clients that connect with version 0.3.5 or higher will nolonger recieve Print packets, instead all messsages are send as [PrintJSON](#PrintJSON)* #### Arguments | Name | Type | Notes | | ---- | ---- | ----- | @@ -164,10 +165,21 @@ Sent to clients purely to display a message to the player. This packet differs f | Name | Type | Notes | | ---- | ---- | ----- | | data | list\[[JSONMessagePart](#JSONMessagePart)\] | Type of this part of the message. | -| type | str | May be present to indicate the nature of this message. Known types are Hint and ItemSend. | +| type | str | May be present to indicate the [PrintJsonType](#PrintJsonType) of this message. | | receiving | int | Is present if type is Hint or ItemSend and marks the destination player's ID. | | item | [NetworkItem](#NetworkItem) | Is present if type is Hint or ItemSend and marks the source player id, location id, item id and item flags. | | found | bool | Is present if type is Hint, denotes whether the location hinted for was checked. | +| countdown | int | Is present if type is `Countdown`, denotes the amount of seconds remaining on the countdown. | + +##### PrintJsonType +PrintJsonType indicates the type of [PrintJson](#PrintJson) packet, different types can be handled differently by the client and can also contain additional arguments. When receiving an unknown type the data's list\[[JSONMessagePart](#JSONMessagePart)\] should still be printed as normal. + +Currently defined types are: +| Type | Notes | +| ---- | ----- | +| ItemSend | The message is in response to a player receiving an item. | +| Hint | The message is in response to a player hinting. | +| Countdown | The message contains information about the current server Countdown. | ### DataPackage Sent to clients to provide what is known as a 'data package' which contains information to enable a client to most easily communicate with the Archipelago server. Contents include things like location id to name mappings, among others; see [Data Package Contents](#Data-Package-Contents) for more info.