Skip to content

Commit

Permalink
Merge branch 'main' into per_game_datapackage
Browse files Browse the repository at this point in the history
# Conflicts:
#	worlds/__init__.py
  • Loading branch information
ThePhar committed Nov 5, 2023
2 parents 7aff89f + e1f1bf8 commit b2b56b8
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
if any(world.item_links.values()):
world._all_state = None

logger.info("Running Item Plando")
logger.info("Running Item Plando.")

distribute_planned(world)

Expand Down
10 changes: 7 additions & 3 deletions Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,16 @@ def user_path(*path: str) -> str:
if user_path.cached_path != local_path():
import filecmp
if not os.path.exists(user_path("manifest.json")) or \
not os.path.exists(local_path("manifest.json")) or \
not filecmp.cmp(local_path("manifest.json"), user_path("manifest.json"), shallow=True):
import shutil
for dn in ("Players", "data/sprites"):
for dn in ("Players", "data/sprites", "data/lua"):
shutil.copytree(local_path(dn), user_path(dn), dirs_exist_ok=True)
for fn in ("manifest.json",):
shutil.copy2(local_path(fn), user_path(fn))
if not os.path.exists(local_path("manifest.json")):
warnings.warn(f"Upgrading {user_path()} from something that is not a proper install")
else:
shutil.copy2(local_path("manifest.json"), user_path("manifest.json"))
os.makedirs(user_path("worlds"), exist_ok=True)

return os.path.join(user_path.cached_path, *path)

Expand Down
36 changes: 21 additions & 15 deletions worlds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@
import zipimport
from typing import Dict, List, NamedTuple, TYPE_CHECKING, TypedDict

from Utils import user_path, local_path

if TYPE_CHECKING:
from .AutoWorld import World


folder = os.path.dirname(__file__)
local_folder = os.path.dirname(__file__)
user_folder = user_path("worlds") if user_path() != local_path() else None

__all__ = {
"lookup_world_item_id_to_name",
"lookup_world_location_id_to_name",
"network_data_package",
"AutoWorldRegister",
"world_sources",
"folder",
"local_folder",
"user_folder",
"GamePackage",
"DataPackage",
}
Expand All @@ -40,13 +43,13 @@ class WorldSource(NamedTuple):
is_zip: bool = False
relative: bool = True # relative to regular world import folder

def __repr__(self):
def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.path}, is_zip={self.is_zip}, relative={self.relative})"

@property
def resolved_path(self) -> str:
if self.relative:
return os.path.join(folder, self.path)
return os.path.join(local_folder, self.path)
return self.path

def load(self) -> bool:
Expand All @@ -55,6 +58,7 @@ def load(self) -> bool:
importer = zipimport.zipimporter(self.resolved_path)
if hasattr(importer, "find_spec"): # new in Python 3.10
spec = importer.find_spec(os.path.basename(self.path).rsplit(".", 1)[0])
assert spec, f"{self.path} is not a loadable module"
mod = importlib.util.module_from_spec(spec)
else: # TODO: remove with 3.8 support
mod = importer.load_module(os.path.basename(self.path).rsplit(".", 1)[0])
Expand All @@ -71,7 +75,7 @@ def load(self) -> bool:
importlib.import_module(f".{self.path}", "worlds")
return True

except Exception as e:
except Exception:
# A single world failing can still mean enough is working for the user, log and carry on
import traceback
import io
Expand All @@ -85,15 +89,17 @@ def load(self) -> bool:


# find potential world containers, currently folders and zip-importable .apworld's
world_sources: List[WorldSource] = []
file: os.DirEntry # for me (Berserker) at least, PyCharm doesn't seem to infer the type correctly
for file in os.scandir(folder):
# prevent loading of __pycache__ and allow _* for non-world folders, disable files/folders starting with "."
if not file.name.startswith(("_", ".")):
if file.is_dir():
world_sources.append(WorldSource(file.name))
elif file.is_file() and file.name.endswith(".apworld"):
world_sources.append(WorldSource(file.name, is_zip=True))
world_sources: typing.List[WorldSource] = []
for folder in (folder for folder in (user_folder, local_folder) if folder):
relative = folder == local_folder
for entry in os.scandir(folder):
# prevent loading of __pycache__ and allow _* for non-world folders, disable files/folders starting with "."
if not entry.name.startswith(("_", ".")):
file_name = entry.name if relative else os.path.join(folder, entry.name)
if entry.is_dir():
world_sources.append(WorldSource(file_name, relative=relative))
elif entry.is_file() and entry.name.endswith(".apworld"):
world_sources.append(WorldSource(file_name, is_zip=True, relative=relative))

# import all submodules to trigger AutoWorldRegister
world_sources.sort()
Expand Down
3 changes: 2 additions & 1 deletion worlds/oot/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ def set_shop_rules(ootworld):
# The goal is to automatically set item rules based on age requirements in case entrances were shuffled
def set_entrances_based_rules(ootworld):

all_state = ootworld.multiworld.get_all_state(False)
all_state = ootworld.get_state_with_complete_itempool()
all_state.sweep_for_events(locations=ootworld.get_locations())

for location in filter(lambda location: location.type == 'Shop', ootworld.get_locations()):
# If a shop is not reachable as adult, it can't have Goron Tunic or Zora Tunic as child can't buy these
Expand Down
6 changes: 3 additions & 3 deletions worlds/oot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,8 @@ def generate_basic(self): # mostly killing locations that shouldn't exist by se
# Kill unreachable events that can't be gotten even with all items
# Make sure to only kill actual internal events, not in-game "events"
all_state = self.get_state_with_complete_itempool()
all_state.sweep_for_events()
all_locations = self.get_locations()
all_state.sweep_for_events(locations=all_locations)
reachable = self.multiworld.get_reachable_locations(all_state, self.player)
unreachable = [loc for loc in all_locations if
(loc.internal or loc.type == 'Drop') and loc.event and loc.locked and loc not in reachable]
Expand Down Expand Up @@ -856,7 +856,7 @@ def prefill_state(base_state):
state = base_state.copy()
for item in self.get_pre_fill_items():
self.collect(state, item)
state.sweep_for_events(self.get_locations())
state.sweep_for_events(locations=self.get_locations())
return state

# Prefill shops, songs, and dungeon items
Expand All @@ -868,7 +868,7 @@ def prefill_state(base_state):
state = CollectionState(self.multiworld)
for item in self.itempool:
self.collect(state, item)
state.sweep_for_events(self.get_locations())
state.sweep_for_events(locations=self.get_locations())

# Place dungeon items
special_fill_types = ['GanonBossKey', 'BossKey', 'SmallKey', 'HideoutSmallKey', 'Map', 'Compass']
Expand Down
2 changes: 1 addition & 1 deletion worlds/sm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ def get_player_ItemLocation(progression_only: bool):
escapeTrigger = None
if self.variaRando.randoExec.randoSettings.restrictions["EscapeTrigger"]:
#used to simulate received items
first_local_collected_loc = next(itemLoc for itemLoc in SMWorld.spheres if itemLoc.player == self.player)
first_local_collected_loc = next(itemLoc for itemLoc in spheres if itemLoc.player == self.player)

playerItemsItemLocs = get_player_ItemLocation(False)
playerProgItemsItemLocs = get_player_ItemLocation(True)
Expand Down

0 comments on commit b2b56b8

Please sign in to comment.