From a7b9143514acf0f0082d10735c8fcc11433e9636 Mon Sep 17 00:00:00 2001 From: Seatori <92278897+Seatori@users.noreply.github.com> Date: Mon, 6 Jul 2026 22:55:27 -0400 Subject: [PATCH 1/5] Add support for defining multiple generic filler items --- schemas/Manual.game.schema.json | 7 +++++-- src/Items.py | 16 ++++++++++++---- src/__init__.py | 13 +++++++++++-- src/hooks/World.py | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/schemas/Manual.game.schema.json b/schemas/Manual.game.schema.json index 360dda4f..11ad351f 100644 --- a/schemas/Manual.game.schema.json +++ b/schemas/Manual.game.schema.json @@ -17,8 +17,11 @@ "type": "string" }, "filler_item_name": { - "description": "Name of the filler items that get placed when there's no more real items to place.", - "type": "string" + "description": "Names of the filler items that get placed when there's no more real items to place.", + "type": ["string", "array"], + "items": { + "type":"string" + } }, "starting_items": { "description": "(Optional) Starting inventory", diff --git a/src/Items.py b/src/Items.py index 402f37ed..0a02e70f 100644 --- a/src/Items.py +++ b/src/Items.py @@ -15,7 +15,7 @@ count = starting_index -filler_found = False +filler_found = [] # add sequential generated ids to the lists for key, val in enumerate(item_table): @@ -30,13 +30,21 @@ item_table[key]["progression"] = val["progression"] if "progression" in val else False if isinstance(val.get("category", []), str): item_table[key]["category"] = [val["category"]] - if item_table[key].get("name") == filler_item_name: - filler_found = True + if item_table[key].get("name") in filler_item_name: + filler_found.append(item_table[key].get("name")) count += 1 # add the filler item to the list of items for lookup -if filler_item_name and not filler_found: +if isinstance(filler_item_name, list): + for generic_filler in filler_item_name: + if generic_filler not in filler_found: + item_table.append({ + "name": generic_filler, + "id": count, + }) + count += 1 +elif isinstance(filler_item_name, str) and not filler_found: item_table.append({ "name": filler_item_name, "id": count, diff --git a/src/__init__.py b/src/__init__.py index fb363ddc..597678ec 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -75,7 +75,16 @@ class ManualWorld(World): origin_region_name = "Manual" def get_filler_item_name(self) -> str: - return hook_get_filler_item_name(self, self.multiworld, self.player) or self.filler_item_name + if isinstance(hook_get_filler_item_name(self, self.multiworld, self.player), str): + return hook_get_filler_item_name(self, self.multiworld, self.player) + elif isinstance(hook_get_filler_item_name(self, self.multiworld, self.player), list): + hook_random_filler_name = self.random.choice(hook_get_filler_item_name(self, self.multiworld, self.player)) + return hook_random_filler_name + elif isinstance(filler_item_name, str): + return self.filler_item_name + else: + random_filler_name = self.random.choice(filler_item_name) + return random_filler_name def interpret_slot_data(self, slot_data: dict[str, Any]) -> dict[str, Any]: #this is called by tools like UT @@ -126,7 +135,7 @@ def create_items(self): items_config: dict[str, int|dict[ItemClassification | str | int, int]] = {} for name in configured_item_names.values(): if name == "__Victory__": continue - if name == filler_item_name: continue # intentionally using the Game.py filler_item_name here because it's a non-Items item + if name in filler_item_name: continue # intentionally using the Game.py filler_item_name here because it's a non-Items item item = self.item_name_to_item[name] item_count = int(item.get("count", 1)) diff --git a/src/hooks/World.py b/src/hooks/World.py index 930f476b..d523424d 100644 --- a/src/hooks/World.py +++ b/src/hooks/World.py @@ -34,7 +34,7 @@ # Use this function to change the valid filler items to be created to replace item links or starting items. # Default value is the `filler_item_name` from game.json -def hook_get_filler_item_name(world: World, multiworld: MultiWorld, player: int) -> str | bool: +def hook_get_filler_item_name(world: World, multiworld: MultiWorld, player: int) -> list[str] | str | bool: return False def before_generate_early(world: World, multiworld: MultiWorld, player: int) -> None: From 60a0167d9ba644a99c567a1c98cc573b015013b5 Mon Sep 17 00:00:00 2001 From: Seafo <92278897+Seatori@users.noreply.github.com> Date: Tue, 7 Jul 2026 02:21:33 -0400 Subject: [PATCH 2/5] Apply suggestion from @silasary Co-authored-by: Katelyn Gigante --- src/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/__init__.py b/src/__init__.py index 597678ec..32448130 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -75,11 +75,11 @@ class ManualWorld(World): origin_region_name = "Manual" def get_filler_item_name(self) -> str: - if isinstance(hook_get_filler_item_name(self, self.multiworld, self.player), str): - return hook_get_filler_item_name(self, self.multiworld, self.player) - elif isinstance(hook_get_filler_item_name(self, self.multiworld, self.player), list): - hook_random_filler_name = self.random.choice(hook_get_filler_item_name(self, self.multiworld, self.player)) - return hook_random_filler_name + hook_result = hook_get_filler_item_name(self, self.multiworld, self.player) + if hook_result and isinstance(hook_result, str): + return hook_result + elif hook_result and isinstance(hook_result, list): + return self.random.choice(hook_result) elif isinstance(filler_item_name, str): return self.filler_item_name else: From 32f90cbe13b3cb5edbd064c3e4c2806678785b76 Mon Sep 17 00:00:00 2001 From: Seatori <92278897+Seatori@users.noreply.github.com> Date: Tue, 7 Jul 2026 02:35:24 -0400 Subject: [PATCH 3/5] Type checking in create_items --- src/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/__init__.py b/src/__init__.py index 32448130..3489f12b 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -135,7 +135,11 @@ def create_items(self): items_config: dict[str, int|dict[ItemClassification | str | int, int]] = {} for name in configured_item_names.values(): if name == "__Victory__": continue - if name in filler_item_name: continue # intentionally using the Game.py filler_item_name here because it's a non-Items item + # intentionally using the Game.py filler_item_name here because it can be a non-Items item + if isinstance(filler_item_name, str): + if name == filler_item_name: continue + elif isinstance(filler_item_name, list): + if name in filler_item_name: continue item = self.item_name_to_item[name] item_count = int(item.get("count", 1)) From 8f0338b9652447abb4778b297eeee6e056adfb3a Mon Sep 17 00:00:00 2001 From: Seatori <92278897+Seatori@users.noreply.github.com> Date: Tue, 7 Jul 2026 03:55:54 -0400 Subject: [PATCH 4/5] Change filler_found to a set --- src/Items.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Items.py b/src/Items.py index 0a02e70f..20b5bbd3 100644 --- a/src/Items.py +++ b/src/Items.py @@ -15,7 +15,7 @@ count = starting_index -filler_found = [] +filler_found: set[str] = set() # add sequential generated ids to the lists for key, val in enumerate(item_table): @@ -31,7 +31,7 @@ if isinstance(val.get("category", []), str): item_table[key]["category"] = [val["category"]] if item_table[key].get("name") in filler_item_name: - filler_found.append(item_table[key].get("name")) + filler_found.add(item_table[key].get("name")) count += 1 From eed81639cf7c3a368308e29bc6af356dc5231af5 Mon Sep 17 00:00:00 2001 From: Seatori <92278897+Seatori@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:06:13 -0400 Subject: [PATCH 5/5] Type checking for filler_found --- src/Items.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Items.py b/src/Items.py index 20b5bbd3..0369b215 100644 --- a/src/Items.py +++ b/src/Items.py @@ -30,8 +30,12 @@ item_table[key]["progression"] = val["progression"] if "progression" in val else False if isinstance(val.get("category", []), str): item_table[key]["category"] = [val["category"]] - if item_table[key].get("name") in filler_item_name: - filler_found.add(item_table[key].get("name")) + if isinstance(filler_item_name, list): + if item_table[key].get("name") in filler_item_name: + filler_found.add(item_table[key].get("name")) + elif isinstance(filler_item_name, str): + if item_table[key].get("name") == filler_item_name: + filler_found.add(item_table[key].get("name")) count += 1