From e738b0b593e89d29bcd8e8104ee20115f4b9057a Mon Sep 17 00:00:00 2001 From: Silvris <58583688+Silvris@users.noreply.github.com> Date: Tue, 14 May 2024 17:18:25 -0500 Subject: [PATCH] typing cleanup --- worlds/kdl3/Client.py | 53 +++++++++++++++++++++++------------------- worlds/kdl3/Regions.py | 22 +++++++++--------- worlds/kdl3/Rom.py | 4 ++-- worlds/kdl3/Room.py | 2 +- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/worlds/kdl3/Client.py b/worlds/kdl3/Client.py index f6bf4f854f..f701ea10fa 100644 --- a/worlds/kdl3/Client.py +++ b/worlds/kdl3/Client.py @@ -17,7 +17,7 @@ from .ClientAddrs import consumable_addrs, star_addrs from typing import TYPE_CHECKING if TYPE_CHECKING: - from SNIClient import SNIClientCommandProcessor + from SNIClient import SNIClientCommandProcessor, SNIContext snes_logger = logging.getLogger("SNES") @@ -81,17 +81,16 @@ deathlink_messages = defaultdict(lambda: " was defeated.", { @mark_raw -def cmd_gift(self: "SNIClientCommandProcessor"): +def cmd_gift(self: "SNIClientCommandProcessor") -> None: """Toggles gifting for the current game.""" - if not getattr(self.ctx, "gifting", None): - setattr(self.ctx, "gifting", True) - else: - self.ctx.gifting = not self.ctx.gifting - self.output(f"Gifting set to {self.ctx.gifting}") + handler = self.ctx.client_handler + assert isinstance(handler, KDL3SNIClient) + handler.gifting = not handler.gifting + self.output(f"Gifting set to {handler.gifting}") async_start(update_object(self.ctx, f"Giftboxes;{self.ctx.team}", { f"{self.ctx.slot}": { - "IsOpen": self.ctx.gifting, + "IsOpen": handler.gifting, **kdl3_gifting_options } })) @@ -100,16 +99,17 @@ def cmd_gift(self: "SNIClientCommandProcessor"): class KDL3SNIClient(SNIClient): game = "Kirby's Dream Land 3" patch_suffix = ".apkdl3" - levels = None - consumables = None - stars = None - item_queue: typing.List = [] - initialize_gifting = False + levels: typing.Dict[int, typing.List[int]] = {} + consumables: typing.Optional[bool] = None + stars: typing.Optional[bool] = None + item_queue: typing.List[int] = [] + initialize_gifting: bool = False + gifting: bool = False giftbox_key: str = "" motherbox_key: str = "" client_random: random.Random = random.Random() - async def deathlink_kill_player(self, ctx) -> None: + async def deathlink_kill_player(self, ctx: "SNIContext") -> None: from SNIClient import DeathState, snes_buffered_write, snes_flush_writes, snes_read game_state = await snes_read(ctx, KDL3_GAME_STATE, 1) if game_state[0] == 0xFF: @@ -131,7 +131,7 @@ class KDL3SNIClient(SNIClient): ctx.death_state = DeathState.dead ctx.last_death_link = time.time() - async def validate_rom(self, ctx) -> bool: + async def validate_rom(self, ctx: "SNIContext") -> bool: from SNIClient import snes_read rom_name = await snes_read(ctx, KDL3_ROMNAME, 0x15) if rom_name is None or rom_name == bytes([0] * 0x15) or rom_name[:4] != b"KDL3": @@ -152,7 +152,7 @@ class KDL3SNIClient(SNIClient): ctx.items_handling |= (death_link[0] & 0b10) # set local items if enabled return True - async def pop_item(self, ctx, in_stage): + async def pop_item(self, ctx: "SNIContext", in_stage: bool) -> None: from SNIClient import snes_buffered_write, snes_read if len(self.item_queue) > 0: item = self.item_queue.pop() @@ -169,7 +169,7 @@ class KDL3SNIClient(SNIClient): else: self.item_queue.append(item) # no more slots, get it next go around - async def pop_gift(self, ctx): + async def pop_gift(self, ctx: "SNIContext") -> None: if self.giftbox_key in ctx.stored_data and ctx.stored_data[self.giftbox_key]: from SNIClient import snes_read, snes_buffered_write key, gift = ctx.stored_data[self.giftbox_key].popitem() @@ -215,7 +215,7 @@ class KDL3SNIClient(SNIClient): quality = min(10, quality * 2) else: # it's not really edible, but he'll eat it anyway - quality = self.client_random.choices(range(0, 2), {0: 75, 1: 25})[0] + quality = self.client_random.choices(range(0, 2), [75, 25])[0] kirby_hp = await snes_read(ctx, KDL3_KIRBY_HP, 1) gooey_hp = await snes_read(ctx, KDL3_KIRBY_HP + 2, 1) snes_buffered_write(ctx, KDL3_SOUND_FX, bytes([0x26])) @@ -225,7 +225,8 @@ class KDL3SNIClient(SNIClient): else: snes_buffered_write(ctx, KDL3_KIRBY_HP, struct.pack("H", min(kirby_hp[0] + quality, 10))) - async def pick_gift_recipient(self, ctx, gift): + async def pick_gift_recipient(self, ctx: "SNIContext", gift: int) -> None: + assert ctx.slot if gift != 4: gift_base = kdl3_gifts[gift] else: @@ -239,7 +240,7 @@ class KDL3SNIClient(SNIClient): if desire > most_applicable: most_applicable = desire most_applicable_slot = int(slot) - elif most_applicable_slot == ctx.slot and info["AcceptsAnyGift"]: + elif most_applicable_slot != ctx.slot and most_applicable == -1 and info["AcceptsAnyGift"]: # only send to ourselves if no one else will take it most_applicable_slot = int(slot) # print(most_applicable, most_applicable_slot) @@ -258,7 +259,7 @@ class KDL3SNIClient(SNIClient): item_uuid: item, }) - async def game_watcher(self, ctx) -> None: + async def game_watcher(self, ctx: "SNIContext") -> None: try: from SNIClient import snes_buffered_write, snes_flush_writes, snes_read rom = await snes_read(ctx, KDL3_ROMNAME, 0x15) @@ -279,11 +280,12 @@ class KDL3SNIClient(SNIClient): await initialize_giftboxes(ctx, self.giftbox_key, self.motherbox_key, bool(enable_gifting[0])) self.initialize_gifting = True # can't check debug anymore, without going and copying the value. might be important later. - if self.levels is None: + if not self.levels: self.levels = dict() for i in range(5): level_data = await snes_read(ctx, KDL3_LEVEL_ADDR + (14 * i), 14) - self.levels[i] = unpack("HHHHHHH", level_data) + self.levels[i] = [int.from_bytes(level_data[idx:idx+1], "little") + for idx in range(0, len(level_data), 2)] self.levels[5] = [0x0205, # Hyper Zone 0, # MG-5, can't send from here 0x0300, # Boss Butch @@ -402,6 +404,9 @@ class KDL3SNIClient(SNIClient): if star not in ctx.checked_locations and stars[star_addrs[star]] == 0x01: new_checks.append(star) + if not game_state: + return + if game_state[0] != 0xFF: await self.pop_gift(ctx) await self.pop_item(ctx, game_state[0] != 0xFF) @@ -409,7 +414,7 @@ class KDL3SNIClient(SNIClient): # boss status boss_flag_bytes = await snes_read(ctx, KDL3_BOSS_STATUS, 2) - boss_flag = unpack("H", boss_flag_bytes)[0] + boss_flag = int.from_bytes(boss_flag_bytes, "little") for bitmask, boss in zip(range(1, 11, 2), boss_locations.keys()): if boss_flag & (1 << bitmask) > 0 and boss not in ctx.checked_locations: new_checks.append(boss) diff --git a/worlds/kdl3/Regions.py b/worlds/kdl3/Regions.py index ac27d8bbf5..e2faa9a09c 100644 --- a/worlds/kdl3/Regions.py +++ b/worlds/kdl3/Regions.py @@ -2,8 +2,8 @@ import orjson import os from pkgutil import get_data -from typing import TYPE_CHECKING, List, Dict, Optional, Union -from BaseClasses import Region +from typing import TYPE_CHECKING, List, Dict, Optional, Union, Callable +from BaseClasses import Region, CollectionState from worlds.generic.Rules import add_item_rule from .Locations import KDL3Location from .Names import LocationName @@ -40,7 +40,7 @@ first_world_limit = { def generate_valid_level(world: "KDL3World", level: int, stage: int, - possible_stages: List[int], placed_stages: List[int]): + possible_stages: List[int], placed_stages: List[Optional[int]]) -> int: new_stage = world.random.choice(possible_stages) if level == 1: if stage == 0 and new_stage in first_stage_blacklist: @@ -53,7 +53,7 @@ def generate_valid_level(world: "KDL3World", level: int, stage: int, return new_stage -def generate_rooms(world: "KDL3World", level_regions: Dict[int, Region]): +def generate_rooms(world: "KDL3World", level_regions: Dict[int, Region]) -> None: level_names = {LocationName.level_names[level]: level for level in LocationName.level_names} room_data = orjson.loads(get_data(__name__, os.path.join("data", "Rooms.json"))) rooms: Dict[str, KDL3Room] = dict() @@ -84,7 +84,7 @@ def generate_rooms(world: "KDL3World", level_regions: Dict[int, Region]): first_rooms[0x770200 + room.level - 1] = room else: first_rooms[0x770000 + ((room.level - 1) * 6) + room.stage] = room - exits = dict() + exits: Dict[str, Callable[[CollectionState], bool]] = dict() for def_exit in room.default_exits: target = f"{level_names[room.level]} {room.stage} - {def_exit['room']}" access_rule = tuple(def_exit["access_rule"]) @@ -119,7 +119,7 @@ def generate_rooms(world: "KDL3World", level_regions: Dict[int, Region]): .parent_region.add_exits([first_rooms[0x770200 + level - 1].name]) -def generate_valid_levels(world: "KDL3World", enforce_world: bool, enforce_pattern: bool) -> dict: +def generate_valid_levels(world: "KDL3World", enforce_world: bool, enforce_pattern: bool) -> Dict[int, List[int]]: levels: Dict[int, List[Optional[int]]] = { 1: [None] * 7, 2: [None] * 7, @@ -168,11 +168,11 @@ def generate_valid_levels(world: "KDL3World", enforce_world: bool, enforce_patte boss_shuffle = BossShuffle.options[options.pop()] for option in options: if "-" in option: - loc, boss = option.split("-") + loc, plando_boss = option.split("-") loc = loc.title() - boss = boss.title() - levels[LocationName.level_names[loc]][6] = LocationName.boss_names[boss] - plando_bosses.append(LocationName.boss_names[boss]) + plando_boss = plando_boss.title() + levels[LocationName.level_names[loc]][6] = LocationName.boss_names[plando_boss] + plando_bosses.append(LocationName.boss_names[plando_boss]) else: option = option.title() for level in levels: @@ -231,7 +231,7 @@ def create_levels(world: "KDL3World") -> None: generate_rooms(world, levels) - level6.add_locations({LocationName.goals[world.options.goal]: None}, KDL3Location) + level6.add_locations({LocationName.goals[world.options.goal.value]: None}, KDL3Location) menu.connect(level1, "Start Game") level1.connect(level2, "To Level 2") diff --git a/worlds/kdl3/Rom.py b/worlds/kdl3/Rom.py index 13983f5995..25f4eed102 100644 --- a/worlds/kdl3/Rom.py +++ b/worlds/kdl3/Rom.py @@ -431,8 +431,8 @@ def patch_rom(world: "KDL3World", patch: KDL3ProcedurePatch) -> None: elif world.options.music_shuffle == 2: for room in rooms: room.music = world.random.choice(music_choices) - for room in room_music: - patch.write_token(APTokenTypes.WRITE, room + 2, + for room_ptr in room_music: + patch.write_token(APTokenTypes.WRITE, room_ptr + 2, world.random.choice(music_choices).to_bytes(1, "little")) for i in range(5): # level themes diff --git a/worlds/kdl3/Room.py b/worlds/kdl3/Room.py index 122e4c53dd..2f32792b74 100644 --- a/worlds/kdl3/Room.py +++ b/worlds/kdl3/Room.py @@ -31,7 +31,7 @@ class KDL3Room(Region): def __init__(self, name: str, player: int, multiworld: MultiWorld, hint: Optional[str], level: int, stage: int, room: int, pointer: int, music: int, - default_exits: List[Dict[str, Union[int, List[str]]]], + default_exits: List[Dict[str, List[str]]], animal_pointers: List[int], enemies: List[str], entity_load: List[List[int]], consumables: List[Dict[str, Union[int, str]]], consumable_pointer: int) -> None: