Implement PrintJSON

Remove deprecated network packets
Make Client send new locations checked only once
Simplify register_location_checks
Rip out Server savegame compatibility
This commit is contained in:
Fabian Dill
2021-03-02 22:31:44 +01:00
parent 07b9fcfefc
commit 7871555620
7 changed files with 164 additions and 192 deletions

View File

@@ -9,10 +9,15 @@ import websockets
from Utils import Version
class JSONMessagePart(typing.TypedDict):
type: typing.Optional[str]
color: typing.Optional[str]
text: typing.Optional[str]
class JSONMessagePart(typing.TypedDict, total=False):
text: str
# optional
type: str
color: str
# mainly for items, optional
found: bool
class CLientStatus(enum.IntEnum):
CLIENT_UNKNOWN = 0
@@ -144,6 +149,16 @@ class HandlerMeta(type):
attrs['__init__'] = __init__
return super(HandlerMeta, mcs).__new__(mcs, name, bases, attrs)
class JSONTypes(str, enum.Enum):
color = "color"
text = "text"
player_id = "player_id"
player_name = "player_name"
item_name = "item_name"
item_id = "item_id"
location_name = "location_name"
location_id = "location_id"
entrance_name = "entrance_name"
class JSONtoTextParser(metaclass=HandlerMeta):
def __init__(self, ctx):
@@ -158,18 +173,16 @@ class JSONtoTextParser(metaclass=HandlerMeta):
return handler(node)
def _handle_color(self, node: JSONMessagePart):
if node["color"] in color_codes:
return color_code(node["color"]) + self._handle_text(node) + color_code("reset")
else:
logging.warning(f"Unknown color in node {node}")
return self._handle_text(node)
codes = node["color"].split(";")
buffer = "".join(color_code(code) for code in codes)
return buffer + self._handle_text(node) + color_code("reset")
def _handle_text(self, node: JSONMessagePart):
return node.get("text", "")
def _handle_player_id(self, node: JSONMessagePart):
player = node["text"]
node["color"] = 'yellow' if player != self.ctx.slot else 'magenta'
player = int(node["text"])
node["color"] = 'magenta' if player == self.ctx.slot else 'yellow'
node["text"] = self.ctx.player_names[player]
return self._handle_color(node)
@@ -178,6 +191,32 @@ class JSONtoTextParser(metaclass=HandlerMeta):
node["color"] = 'yellow'
return self._handle_color(node)
def _handle_item_name(self, node: JSONMessagePart):
# todo: use a better info source
from worlds.alttp.Items import progression_items
node["color"] = 'green' if node.get("found", False) else 'cyan'
if node["text"] in progression_items:
node["color"] += ";white_bg"
return self._handle_color(node)
def _handle_item_id(self, node: JSONMessagePart):
item_id = int(node["text"])
node["text"] = self.ctx.item_name_getter(item_id)
return self._handle_item_name(node)
def _handle_location_name(self, node: JSONMessagePart):
node["color"] = 'blue_bg;white'
return self._handle_color(node)
def _handle_location_id(self, node: JSONMessagePart):
item_id = int(node["text"])
node["text"] = self.ctx.location_name_getter(item_id)
return self._handle_item_name(node)
def _handle_entrance_name(self, node: JSONMessagePart):
node["color"] = 'white_bg;black'
return self._handle_color(node)
color_codes = {'reset': 0, 'bold': 1, 'underline': 4, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34,
'magenta': 35, 'cyan': 36, 'white': 37, 'black_bg': 40, 'red_bg': 41, 'green_bg': 42, 'yellow_bg': 43,
@@ -190,3 +229,49 @@ def color_code(*args):
def color(text, *args):
return color_code(*args) + text + color_code('reset')
def add_json_text(parts: list, text: typing.Any, **kwargs) -> None:
parts.append({"text": str(text), **kwargs})
class Hint(typing.NamedTuple):
receiving_player: int
finding_player: int
location: int
item: int
found: bool
entrance: str = ""
def re_check(self, ctx, team) -> Hint:
if self.found:
return self
found = self.location in ctx.location_checks[team, self.finding_player]
if found:
return Hint(self.receiving_player, self.finding_player, self.location, self.item, found, self.entrance)
return self
def __hash__(self):
return hash((self.receiving_player, self.finding_player, self.location, self.item, self.entrance))
def as_network_message(self) -> dict:
parts = []
add_json_text(parts, "[Hint]: ")
add_json_text(parts, self.receiving_player, type="player_id")
add_json_text(parts, "'s ")
add_json_text(parts, self.item, type="item_id", found=self.found)
add_json_text(parts, " is at ")
add_json_text(parts, self.location, type="location_id")
add_json_text(parts, " in ")
add_json_text(parts, self.finding_player, type ="player_id")
if self.entrance:
add_json_text(parts, "'s World at ")
add_json_text(parts, self.entrance, type="entrance_name")
else:
add_json_text(parts, "'s World")
if self.found:
add_json_text(parts, ". (found)")
else:
add_json_text(parts, ".")
return {"cmd": "PrintJSON", "text": parts, "type": "hint"}