typing cleanup

This commit is contained in:
Silvris
2024-05-14 17:18:25 -05:00
parent e784a218dd
commit e738b0b593
4 changed files with 43 additions and 38 deletions

View File

@@ -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)

View File

@@ -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")

View File

@@ -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

View File

@@ -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: