Skip to content

Commit

Permalink
Merge main into option-groups
Browse files Browse the repository at this point in the history
  • Loading branch information
LegendaryLinux committed Mar 16, 2024
2 parents 0dde475 + 8a8263f commit b11a3c6
Show file tree
Hide file tree
Showing 1,008 changed files with 82,020 additions and 19,696 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/analyze-modified-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Determine modified files (pull_request)"
if: github.event_name == 'pull_request'
Expand All @@ -50,7 +50,7 @@ jobs:
run: |
echo "diff=." >> $GITHUB_ENV
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
if: env.diff != ''
with:
python-version: 3.8
Expand Down
33 changes: 26 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ on:
- '.github/workflows/build.yml'
- 'setup.py'
- 'requirements.txt'
- '*.iss'
pull_request:
paths:
- '.github/workflows/build.yml'
- 'setup.py'
- 'requirements.txt'
- '*.iss'
workflow_dispatch:

env:
Expand All @@ -25,9 +27,9 @@ jobs:
build-win-py38: # RCs will still be built and signed by hand
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Download run-time dependencies
Expand All @@ -46,25 +48,42 @@ jobs:
cd build
Rename-Item "exe.$NAME" Archipelago
7z a -mx=9 -mhe=on -ms "../dist/$ZIP_NAME" Archipelago
Rename-Item Archipelago "exe.$NAME" # inno_setup.iss expects the original name
- name: Store 7z
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.ZIP_NAME }}
path: dist/${{ env.ZIP_NAME }}
retention-days: 7 # keep for 7 days, should be enough
- name: Build Setup
run: |
& "${env:ProgramFiles(x86)}\Inno Setup 6\iscc.exe" inno_setup.iss /DNO_SIGNTOOL
if ( $? -eq $false ) {
Write-Error "Building setup failed!"
exit 1
}
$contents = Get-ChildItem -Path setups/*.exe -Force -Recurse
$SETUP_NAME=$contents[0].Name
echo "SETUP_NAME=$SETUP_NAME" >> $Env:GITHUB_ENV
- name: Store Setup
uses: actions/upload-artifact@v4
with:
name: ${{ env.SETUP_NAME }}
path: setups/${{ env.SETUP_NAME }}
retention-days: 7 # keep for 7 days, should be enough

build-ubuntu2004:
runs-on: ubuntu-20.04
steps:
# - copy code below to release.yml -
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install base dependencies
run: |
sudo apt update
sudo apt -y install build-essential p7zip xz-utils wget libglib2.0-0
sudo apt -y install python3-gi libgirepository1.0-dev # should pull dependencies for gi installation below
- name: Get a recent python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build-time dependencies
Expand Down Expand Up @@ -100,13 +119,13 @@ jobs:
source venv/bin/activate
python setup.py build_exe --yes
- name: Store AppImage
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.APPIMAGE_NAME }}
path: dist/${{ env.APPIMAGE_NAME }}
retention-days: 7
- name: Store .tar.gz
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.TAR_NAME }}
path: dist/${{ env.TAR_NAME }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/label-pull-requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ jobs:
steps:
- uses: actions/labeler@v5
with:
sync-labels: true
sync-labels: false
peer_review:
name: 'Apply peer review label'
needs: labeler
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened' ||
github.event.action == 'ready_for_review') && !github.event.pull_request.draft
Expand All @@ -30,6 +31,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
unblock_draft_prs:
name: 'Remove waiting-on labels'
needs: labeler
if: github.event.action == 'converted_to_draft' || github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV # tag x.y.z will become "Archipelago x.y.z"
- name: Create Release
uses: softprops/action-gh-release@b7e450da2a4b4cb4bfbae528f788167786cfcedf
uses: softprops/action-gh-release@975c1b265e11dd76618af1c374e7981f9a6ff44a
with:
draft: true # don't publish right away, especially since windows build is added by hand
prerelease: false
Expand All @@ -35,14 +35,14 @@ jobs:
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
# - code below copied from build.yml -
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install base dependencies
run: |
sudo apt update
sudo apt -y install build-essential p7zip xz-utils wget libglib2.0-0
sudo apt -y install python3-gi libgirepository1.0-dev # should pull dependencies for gi installation below
- name: Get a recent python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build-time dependencies
Expand Down Expand Up @@ -74,7 +74,7 @@ jobs:
echo "TAR_NAME=$TAR_NAME" >> $GITHUB_ENV
# - code above copied from build.yml -
- name: Add to Release
uses: softprops/action-gh-release@b7e450da2a4b4cb4bfbae528f788167786cfcedf
uses: softprops/action-gh-release@975c1b265e11dd76618af1c374e7981f9a6ff44a
with:
draft: true # see above
prerelease: false
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ jobs:
os: macos-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python.version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python.version }}
- name: Install dependencies
Expand Down
34 changes: 25 additions & 9 deletions BaseClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class MultiWorld():
game: Dict[int, str]

random: random.Random
per_slot_randoms: Dict[int, random.Random]
per_slot_randoms: Utils.DeprecateDict[int, random.Random]
"""Deprecated. Please use `self.random` instead."""

class AttributeProxy():
Expand All @@ -110,10 +110,14 @@ def __iadd__(self, other: Iterable[Region]):
return self

def append(self, region: Region):
assert region.name not in self.region_cache[region.player], \
f"{region.name} already exists in region cache."
self.region_cache[region.player][region.name] = region

def extend(self, regions: Iterable[Region]):
for region in regions:
assert region.name not in self.region_cache[region.player], \
f"{region.name} already exists in region cache."
self.region_cache[region.player][region.name] = region

def add_group(self, new_id: int):
Expand Down Expand Up @@ -213,7 +217,8 @@ def set_player_attr(attr, val):
set_player_attr('game', "A Link to the Past")
set_player_attr('completion_condition', lambda state: True)
self.worlds = {}
self.per_slot_randoms = {}
self.per_slot_randoms = Utils.DeprecateDict("Using per_slot_randoms is now deprecated. Please use the "
"world's random object instead (usually self.random)")
self.plando_options = PlandoOptions.none

def get_all_ids(self) -> Tuple[int, ...]:
Expand Down Expand Up @@ -247,14 +252,13 @@ def get_player_groups(self, player) -> Set[int]:
return {group_id for group_id, group in self.groups.items() if player in group["players"]}

def set_seed(self, seed: Optional[int] = None, secure: bool = False, name: Optional[str] = None):
assert not self.worlds, "seed needs to be initialized before Worlds"
self.seed = get_seed(seed)
if secure:
self.secure()
else:
self.random.seed(self.seed)
self.seed_name = name if name else str(self.seed)
self.per_slot_randoms = {player: random.Random(self.random.getrandbits(64)) for player in
range(1, self.players + 1)}

def set_options(self, args: Namespace) -> None:
# TODO - remove this section once all worlds use options dataclasses
Expand All @@ -271,7 +275,6 @@ def set_options(self, args: Namespace) -> None:
for player in self.player_ids:
world_type = AutoWorld.AutoWorldRegister.world_types[self.game[player]]
self.worlds[player] = world_type(self, player)
self.worlds[player].random = self.per_slot_randoms[player]
options_dataclass: typing.Type[Options.PerGameCommonOptions] = world_type.options_dataclass
self.worlds[player].options = options_dataclass(**{option_key: getattr(args, option_key)[player]
for option_key in options_dataclass.type_hints})
Expand Down Expand Up @@ -713,14 +716,23 @@ def can_reach(self,
assert isinstance(player, int), "can_reach: player is required if spot is str"
# try to resolve a name
if resolution_hint == 'Location':
spot = self.multiworld.get_location(spot, player)
return self.can_reach_location(spot, player)
elif resolution_hint == 'Entrance':
spot = self.multiworld.get_entrance(spot, player)
return self.can_reach_entrance(spot, player)
else:
# default to Region
spot = self.multiworld.get_region(spot, player)
return self.can_reach_region(spot, player)
return spot.can_reach(self)

def can_reach_location(self, spot: str, player: int) -> bool:
return self.multiworld.get_location(spot, player).can_reach(self)

def can_reach_entrance(self, spot: str, player: int) -> bool:
return self.multiworld.get_entrance(spot, player).can_reach(self)

def can_reach_region(self, spot: str, player: int) -> bool:
return self.multiworld.get_region(spot, player).can_reach(self)

def sweep_for_events(self, key_only: bool = False, locations: Optional[Iterable[Location]] = None) -> None:
if locations is None:
locations = self.multiworld.get_filled_locations()
Expand Down Expand Up @@ -877,6 +889,8 @@ def __delitem__(self, index: int) -> None:
del(self.region_manager.location_cache[location.player][location.name])

def insert(self, index: int, value: Location) -> None:
assert value.name not in self.region_manager.location_cache[value.player], \
f"{value.name} already exists in the location cache."
self._list.insert(index, value)
self.region_manager.location_cache[value.player][value.name] = value

Expand All @@ -887,6 +901,8 @@ def __delitem__(self, index: int) -> None:
del(self.region_manager.entrance_cache[entrance.player][entrance.name])

def insert(self, index: int, value: Entrance) -> None:
assert value.name not in self.region_manager.entrance_cache[value.player], \
f"{value.name} already exists in the entrance cache."
self._list.insert(index, value)
self.region_manager.entrance_cache[value.player][value.name] = value

Expand Down Expand Up @@ -1016,7 +1032,7 @@ class Location:
locked: bool = False
show_in_spoiler: bool = True
progress_type: LocationProgressType = LocationProgressType.DEFAULT
always_allow = staticmethod(lambda item, state: False)
always_allow = staticmethod(lambda state, item: False)
access_rule: Callable[[CollectionState], bool] = staticmethod(lambda state: True)
item_rule = staticmethod(lambda item: True)
item: Optional[Item] = None
Expand Down
35 changes: 31 additions & 4 deletions CommonClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
Utils.init_logging("TextClient", exception_logger="Client")

from MultiServer import CommandProcessor
from NetUtils import Endpoint, decode, NetworkItem, encode, JSONtoTextParser, \
ClientStatus, Permission, NetworkSlot, RawJSONtoTextParser
from NetUtils import (Endpoint, decode, NetworkItem, encode, JSONtoTextParser, ClientStatus, Permission, NetworkSlot,
RawJSONtoTextParser, add_json_text, add_json_location, add_json_item, JSONTypes)
from Utils import Version, stream_input, async_start
from worlds import network_data_package, AutoWorldRegister
import os
Expand Down Expand Up @@ -72,9 +72,16 @@ def _cmd_disconnect(self) -> bool:

def _cmd_received(self) -> bool:
"""List all received items"""
self.output(f'{len(self.ctx.items_received)} received items:')
item: NetworkItem
self.output(f'{len(self.ctx.items_received)} received items, sorted by time:')
for index, item in enumerate(self.ctx.items_received, 1):
self.output(f"{self.ctx.item_names[item.item]} from {self.ctx.player_names[item.player]}")
parts = []
add_json_item(parts, item.item, self.ctx.slot, item.flags)
add_json_text(parts, " from ")
add_json_location(parts, item.location, item.player)
add_json_text(parts, " by ")
add_json_text(parts, item.player, type=JSONTypes.player_id)
self.ctx.on_print_json({"data": parts, "cmd": "PrintJSON"})
return True

def _cmd_missing(self, filter_text = "") -> bool:
Expand Down Expand Up @@ -115,6 +122,15 @@ def _cmd_items(self):
for item_name in AutoWorldRegister.world_types[self.ctx.game].item_name_to_id:
self.output(item_name)

def _cmd_item_groups(self):
"""List all item group names for the currently running game."""
if not self.ctx.game:
self.output("No game set, cannot determine existing item groups.")
return False
self.output(f"Item Group Names for {self.ctx.game}")
for group_name in AutoWorldRegister.world_types[self.ctx.game].item_name_groups:
self.output(group_name)

def _cmd_locations(self):
"""List all location names for the currently running game."""
if not self.ctx.game:
Expand All @@ -124,6 +140,15 @@ def _cmd_locations(self):
for location_name in AutoWorldRegister.world_types[self.ctx.game].location_name_to_id:
self.output(location_name)

def _cmd_location_groups(self):
"""List all location group names for the currently running game."""
if not self.ctx.game:
self.output("No game set, cannot determine existing location groups.")
return False
self.output(f"Location Group Names for {self.ctx.game}")
for group_name in AutoWorldRegister.world_types[self.ctx.game].location_name_groups:
self.output(group_name)

def _cmd_ready(self):
"""Send ready status to server."""
self.ctx.ready = not self.ctx.ready
Expand Down Expand Up @@ -733,8 +758,10 @@ async def process_server_cmd(ctx: CommonContext, args: dict):
elif cmd == 'ConnectionRefused':
errors = args["errors"]
if 'InvalidSlot' in errors:
ctx.disconnected_intentionally = True
ctx.event_invalid_slot()
elif 'InvalidGame' in errors:
ctx.disconnected_intentionally = True
ctx.event_invalid_game()
elif 'IncompatibleVersion' in errors:
raise Exception('Server reported your client version as incompatible. '
Expand Down
9 changes: 5 additions & 4 deletions Fill.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ def fill_restrictive(multiworld: MultiWorld, base_state: CollectionState, locati

def remaining_fill(multiworld: MultiWorld,
locations: typing.List[Location],
itempool: typing.List[Item]) -> None:
itempool: typing.List[Item],
name: str = "Remaining") -> None:
unplaced_items: typing.List[Item] = []
placements: typing.List[Location] = []
swapped_items: typing.Counter[typing.Tuple[int, str]] = Counter()
Expand Down Expand Up @@ -265,10 +266,10 @@ def remaining_fill(multiworld: MultiWorld,
placements.append(spot_to_fill)
placed += 1
if not placed % 1000:
_log_fill_progress("Remaining", placed, total)
_log_fill_progress(name, placed, total)

if total > 1000:
_log_fill_progress("Remaining", placed, total)
_log_fill_progress(name, placed, total)

if unplaced_items and locations:
# There are leftover unplaceable items and locations that won't accept them
Expand Down Expand Up @@ -466,7 +467,7 @@ def mark_for_locking(location: Location):

inaccessible_location_rules(multiworld, multiworld.state, defaultlocations)

remaining_fill(multiworld, excludedlocations, filleritempool)
remaining_fill(multiworld, excludedlocations, filleritempool, "Remaining Excluded")
if excludedlocations:
raise FillError(
f"Not enough filler items for excluded locations. There are {len(excludedlocations)} more locations than items")
Expand Down
Loading

0 comments on commit b11a3c6

Please sign in to comment.