Merge branch 'main' into kvui_fixed_dpi

This commit is contained in:
Fabian Dill
2026-08-04 07:07:22 +02:00
committed by GitHub
10 changed files with 38 additions and 36 deletions
+1 -5
View File
@@ -49,7 +49,7 @@ class ThreadBarrierProxy:
return getattr(self.obj, name)
else:
raise RuntimeError("You are in a threaded context and global random state was removed for your safety. "
"Please use multiworld.per_slot_randoms[player] or randomize ahead of output.")
"Please use world.random or randomize ahead of output.")
class HasNameAndPlayer(Protocol):
@@ -100,8 +100,6 @@ class MultiWorld():
game: Dict[int, str]
random: random.Random
per_slot_randoms: Utils.DeprecateDict[int, random.Random]
"""Deprecated. Please use `self.random` instead."""
class AttributeProxy():
def __init__(self, rule):
@@ -177,8 +175,6 @@ class MultiWorld():
set_player_attr('game', "Archipelago")
set_player_attr('completion_condition', lambda state: True)
self.worlds = {}
self.per_slot_randoms = Utils.DeprecateDict("Using per_slot_randoms is now deprecated. Please use the "
"world's random object instead (usually self.random)", True)
self.plando_options = PlandoOptions.none
def get_all_ids(self) -> Tuple[int, ...]:
-17
View File
@@ -1012,23 +1012,6 @@ def deprecate(message: str, add_stacklevels: int = 0):
warnings.warn(message, stacklevel=2 + add_stacklevels)
class DeprecateDict(dict):
log_message: str
should_error: bool
def __init__(self, message: str, error: bool = False) -> None:
self.log_message = message
self.should_error = error
super().__init__()
def __getitem__(self, item: Any) -> Any:
if self.should_error:
deprecate(self.log_message, add_stacklevels=1)
elif __debug__:
warnings.warn(self.log_message, stacklevel=2)
return super().__getitem__(item)
def _extend_freeze_support() -> None:
"""Extend multiprocessing.freeze_support() to also work on Non-Windows and without setting spawn method first."""
# original upstream issue: https://github.com/python/cpython/issues/76327
+1 -1
View File
@@ -6,7 +6,7 @@ jinja2==3.1.6
schema==0.7.8
kivy==2.3.1
bsdiff4==1.2.6
platformdirs==4.9.4
platformdirs==4.10.1
certifi==2026.2.25
cython==3.2.4
cymem==2.0.13
+1
View File
@@ -115,6 +115,7 @@ class TestGenerateWeights(TestGenerateMain):
settings = get_settings()
settings.generator.player_files_path = settings.generator.PlayerFilesPath(self.yaml_input_dir)
settings.generator.players = 5 # arbitrary number, should be enough
settings.generator.race = 0 # make sure race mode is disabled so the below seed is actually respected
settings._filename = None
user_path_backup = user_path.cached_path
user_path.cached_path = local_path()
-1
View File
@@ -363,7 +363,6 @@ class World(metaclass=AutoWorldRegister):
self.multiworld = multiworld
self.player = player
self.random = Random(multiworld.random.getrandbits(64))
multiworld.per_slot_randoms[player] = self.random
def __getattr__(self, item: str) -> Any:
if item == "settings":
-1
View File
@@ -405,7 +405,6 @@ if not is_frozen():
from worlds import AutoWorldRegister
from worlds.Files import APWorldContainer
from Launcher import open_folder
import argparse
parser = argparse.ArgumentParser(prog="Build APWorlds", description="Build script for APWorlds")
+10 -2
View File
@@ -19,7 +19,7 @@ from .rules import MessengerHardRules, MessengerOOBRules, MessengerRules
from .shop import FIGURINES, PROG_SHOP_ITEMS, SHOP_ITEMS, USEFUL_SHOP_ITEMS, shuffle_shop_prices
from .subclasses import MessengerItem, MessengerRegion, MessengerShopLocation
from .transitions import disconnect_entrances, shuffle_transitions
from .universal_tracker import reverse_portal_exits_into_portal_plando, reverse_transitions_into_plando_connections
from .universal_tracker import reverse_portal_exits_into_portal_plando, reverse_shop_prices, reverse_transitions_into_plando_connections
components.append(
Component(
@@ -169,7 +169,11 @@ class MessengerWorld(World):
if self.options.early_meditation:
self.multiworld.early_items[self.player]["Meditation"] = 1
self.shop_prices, self.figurine_prices = shuffle_shop_prices(self)
if not hasattr(self.multiworld, "re_gen_passthrough"):
self.shop_prices, self.figurine_prices = shuffle_shop_prices(self)
else:
if slot_data := self.multiworld.re_gen_passthrough.get(self.game):
self.shop_prices, self.figurine_prices = reverse_shop_prices(slot_data["shop"], slot_data["figures"])
starting_portals = ["Autumn Hills", "Howling Grotto", "Glacial Peak", "Riviere Turquoise", "Sunken Shrine",
"Searing Crags"]
@@ -276,6 +280,10 @@ class MessengerWorld(World):
self.multiworld.itempool += filler
if hasattr(self.multiworld, "re_gen_passthrough"):
if slot_data := self.multiworld.re_gen_passthrough.get(self.game):
self.total_shards = slot_data["max_price"]
def set_rules(self) -> None:
logic = self.options.logic_level
if logic == Logic.option_normal:
+10
View File
@@ -1,9 +1,11 @@
from Options import PlandoConnection
from .connections import RANDOMIZED_CONNECTIONS
from .portals import REGION_ORDER, SHOP_POINTS, CHECKPOINTS
from .shop import FIGURINES, SHOP_ITEMS
from .transitions import TRANSITIONS
REVERSED_RANDOMIZED_CONNECTIONS = {v: k for k, v in RANDOMIZED_CONNECTIONS.items()}
REVERSED_SHOP_ITEMS = {v.internal_name: k for k, v in (SHOP_ITEMS | FIGURINES).items()}
def find_spot(portal_key: int) -> str:
@@ -26,6 +28,14 @@ def reverse_portal_exits_into_portal_plando(portal_exits: list[int]) -> list[Pla
PlandoConnection("Glacial Peak", find_spot(portal_exits[5]), "both"),
]
def reverse_shop_prices(
shop_prices: dict[str, int], figures_prices: dict[str, int]
) -> tuple[dict[str, int], dict[str, int]]:
return (
{REVERSED_SHOP_ITEMS[item_internal_name]: price for item_internal_name, price in shop_prices.items()},
{REVERSED_SHOP_ITEMS[item_internal_name]: price for item_internal_name, price in figures_prices.items()},
)
def reverse_transitions_into_plando_connections(transitions: list[list[int]]) -> list[PlandoConnection]:
plando_connections = []
+3 -2
View File
@@ -91,6 +91,7 @@ class SC2World(World):
game = "Starcraft 2"
web = Starcraft2WebWorld()
settings: ClassVar[settings.Starcraft2Settings]
disable_ut = True
item_name_to_id = {name: data.code for name, data in get_full_item_list().items()}
location_name_to_id = {location.name: location.code for location in DEFAULT_LOCATION_LIST}
@@ -433,7 +434,7 @@ def create_and_flag_explicit_item_locks_and_excludes(world: SC2World) -> List[Fi
if max_count and count > max_count:
return max_count
return count
auto_excludes = Counter({item_name: 1 for item_name in item_groups.legacy_items})
if world.options.exclude_overpowered_items.value == ExcludeOverpoweredItems.option_true:
for item_name in item_groups.overpowered_items:
@@ -1066,7 +1067,7 @@ def fill_pool_with_kerrigan_levels(world: SC2World, item_pool: List[StarcraftIte
or (world.options.grant_story_levels and not kerrigan_build_missions)
):
return
def add_kerrigan_level_items(level_amount: int, item_amount: int):
name = f"{level_amount} Kerrigan Level"
if level_amount > 1:
+12 -7
View File
@@ -1,5 +1,6 @@
import logging
from typing import Callable, Dict, List, Set, Tuple, TYPE_CHECKING, Iterable
from collections import Counter
from BaseClasses import Location, ItemClassification
from .item import StarcraftItem, ItemFilterFlags, item_names, item_parents, item_groups
@@ -110,7 +111,7 @@ class ValidInventory:
self.player = world.player
self.world: 'SC2World' = world
# Track all Progression items and those with complex rules for filtering
self.logical_inventory: Dict[str, int] = {}
self.logical_inventory: Counter[str] = Counter()
for item in item_pool:
if not item_table[item.name].is_important_for_filtering():
continue
@@ -125,13 +126,13 @@ class ValidInventory:
self.item_name_to_child_items.setdefault(parent_item, []).append(item)
def has(self, item: str, player: int, count: int = 1) -> bool:
return self.logical_inventory.get(item, 0) >= count
return self.logical_inventory[item] >= count
def has_any(self, items: Set[str], player: int) -> bool:
return any(self.logical_inventory.get(item) for item in items)
return any(self.logical_inventory[item] for item in items)
def has_all(self, items: Set[str], player: int) -> bool:
return all(self.logical_inventory.get(item) for item in items)
return all(self.logical_inventory[item] for item in items)
def has_group(self, item_group: str, player: int, count: int = 1) -> bool:
return False # Deliberately fails here, as item pooling is not aware about mission layout
@@ -140,13 +141,17 @@ class ValidInventory:
return 0 # For item filtering assume no missions are beaten
def count(self, item: str, player: int) -> int:
return self.logical_inventory.get(item, 0)
return self.logical_inventory[item]
def count_from_list(self, items: Iterable[str], player: int) -> int:
return sum(self.logical_inventory.get(item, 0) for item in items)
return sum(self.logical_inventory[item] for item in items)
def count_from_list_unique(self, items: Iterable[str], player: int) -> int:
return sum(item in self.logical_inventory for item in items)
result = 0
for item in items:
if self.logical_inventory[item] > 0:
result += 1
return result
def generate_reduced_inventory(self, inventory_size: int, filler_amount: int, mission_requirements: List[Tuple[str, Callable]]) -> List[StarcraftItem]:
"""Attempts to generate a reduced inventory that can fulfill the mission requirements."""