Skip to content

Commit

Permalink
Merge branch 'main' into smw-main
Browse files Browse the repository at this point in the history
  • Loading branch information
PoryGone committed Mar 3, 2024
2 parents 1f7cc95 + b8bf67a commit 66ef5d7
Show file tree
Hide file tree
Showing 198 changed files with 6,932 additions and 5,289 deletions.
31 changes: 31 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'is: documentation':
- changed-files:
- all-globs-to-all-files: '{**/docs/**,**/README.md}'

'affects: webhost':
- changed-files:
- all-globs-to-any-file: 'WebHost.py'
- all-globs-to-any-file: 'WebHostLib/**/*'

'affects: core':
- changed-files:
- all-globs-to-any-file:
- '!*Client.py'
- '!README.md'
- '!LICENSE'
- '!*.yml'
- '!.gitignore'
- '!**/docs/**'
- '!typings/kivy/**'
- '!test/**'
- '!data/**'
- '!.run/**'
- '!.github/**'
- '!worlds_disabled/**'
- '!worlds/**'
- '!WebHost.py'
- '!WebHostLib/**'
- any-glob-to-any-file: # exceptions to the above rules of "stuff that isn't core"
- 'worlds/generic/**/*.py'
- 'worlds/*.py'
- 'CommonClient.py'
44 changes: 44 additions & 0 deletions .github/workflows/label-pull-requests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Label Pull Request
on:
pull_request_target:
types: ['opened', 'reopened', 'synchronize', 'ready_for_review', 'converted_to_draft', 'closed']
branches: ['main']
permissions:
contents: read
pull-requests: write

jobs:
labeler:
name: 'Apply content-based labels'
if: github.event.action == 'opened' || github.event.action == 'reopened' || github.event.action == 'synchronize'
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
with:
sync-labels: true
peer_review:
name: 'Apply peer review label'
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened' ||
github.event.action == 'ready_for_review') && !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: 'Add label'
run: "gh pr edit \"$PR_URL\" --add-label 'waiting-on: peer-review'"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
unblock_draft_prs:
name: 'Remove waiting-on labels'
if: github.event.action == 'converted_to_draft' || github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: 'Remove labels'
run: |-
gh pr edit "$PR_URL" --remove-label 'waiting-on: peer-review' \
--remove-label 'waiting-on: core-review' \
--remove-label 'waiting-on: world-maintainer' \
--remove-label 'waiting-on: author'
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65 changes: 65 additions & 0 deletions .github/workflows/scan-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Native Code Static Analysis

on:
push:
paths:
- '**.c'
- '**.cc'
- '**.cpp'
- '**.cxx'
- '**.h'
- '**.hh'
- '**.hpp'
- '**.pyx'
- 'setup.py'
- 'requirements.txt'
- '.github/workflows/scan-build.yml'
pull_request:
paths:
- '**.c'
- '**.cc'
- '**.cpp'
- '**.cxx'
- '**.h'
- '**.hh'
- '**.hpp'
- '**.pyx'
- 'setup.py'
- 'requirements.txt'
- '.github/workflows/scan-build.yml'

jobs:
scan-build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Install scan-build command
run: |
sudo apt install clang-tools-17
- name: Get a recent python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip -r requirements.txt
- name: scan-build
run: |
source venv/bin/activate
scan-build-17 --status-bugs -o scan-build-reports -disable-checker deadcode.DeadStores python setup.py build -y
- name: Store report
if: failure()
uses: actions/upload-artifact@v4
with:
name: scan-build-reports
path: scan-build-reports
55 changes: 35 additions & 20 deletions BaseClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
import Options
import Utils

if typing.TYPE_CHECKING:
from worlds import AutoWorld


class Group(TypedDict, total=False):
name: str
game: str
world: auto_world
world: "AutoWorld.World"
players: Set[int]
item_pool: Set[str]
replacement_items: Dict[int, Optional[str]]
Expand Down Expand Up @@ -55,7 +58,7 @@ class MultiWorld():
plando_texts: List[Dict[str, str]]
plando_items: List[List[Dict[str, Any]]]
plando_connections: List
worlds: Dict[int, auto_world]
worlds: Dict[int, "AutoWorld.World"]
groups: Dict[int, Group]
regions: RegionManager
itempool: List[Item]
Expand Down Expand Up @@ -107,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 @@ -156,11 +163,11 @@ def __init__(self, players: int):
self.fix_trock_doors = self.AttributeProxy(
lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted')
self.fix_skullwoods_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])
self.fix_palaceofdarkness_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])
self.fix_trock_exit = self.AttributeProxy(
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'])
lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeons_simple'])

for player in range(1, players + 1):
def set_player_attr(attr, val):
Expand Down Expand Up @@ -219,6 +226,8 @@ def get_all_ids(self) -> Tuple[int, ...]:
def add_group(self, name: str, game: str, players: Set[int] = frozenset()) -> Tuple[int, Group]:
"""Create a group with name and return the assigned player ID and group.
If a group of this name already exists, the set of players is extended instead of creating a new one."""
from worlds import AutoWorld

for group_id, group in self.groups.items():
if group["name"] == name:
group["players"] |= players
Expand Down Expand Up @@ -253,6 +262,8 @@ def set_seed(self, seed: Optional[int] = None, secure: bool = False, name: Optio

def set_options(self, args: Namespace) -> None:
# TODO - remove this section once all worlds use options dataclasses
from worlds import AutoWorld

all_keys: Set[str] = {key for player in self.player_ids for key in
AutoWorld.AutoWorldRegister.world_types[self.game[player]].options_dataclass.type_hints}
for option_key in all_keys:
Expand All @@ -270,6 +281,8 @@ def set_options(self, args: Namespace) -> None:
for option_key in options_dataclass.type_hints})

def set_item_links(self):
from worlds import AutoWorld

item_links = {}
replacement_prio = [False, True, None]
for player in self.player_ids:
Expand Down Expand Up @@ -572,9 +585,10 @@ def fulfills_accessibility(self, state: Optional[CollectionState] = None):

def location_condition(location: Location):
"""Determine if this location has to be accessible, location is already filtered by location_relevant"""
if location.player in players["minimal"]:
return False
return True
if location.player in players["locations"] or (location.item and location.item.player not in
players["minimal"]):
return True
return False

def location_relevant(location: Location):
"""Determine if this location is relevant to sweep."""
Expand Down Expand Up @@ -823,8 +837,8 @@ def __repr__(self):
return self.__str__()

def __str__(self):
world = self.parent_region.multiworld if self.parent_region else None
return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})'
multiworld = self.parent_region.multiworld if self.parent_region else None
return multiworld.get_name_string_for_object(self) if multiworld else f'{self.name} (Player {self.player})'


class Region:
Expand Down Expand Up @@ -867,6 +881,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 @@ -877,6 +893,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 @@ -1040,8 +1058,8 @@ def __repr__(self):
return self.__str__()

def __str__(self):
world = self.parent_region.multiworld if self.parent_region and self.parent_region.multiworld else None
return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})'
multiworld = self.parent_region.multiworld if self.parent_region and self.parent_region.multiworld else None
return multiworld.get_name_string_for_object(self) if multiworld else f'{self.name} (Player {self.player})'

def __hash__(self):
return hash((self.name, self.player))
Expand Down Expand Up @@ -1175,7 +1193,7 @@ def set_entrance(self, entrance: str, exit_: str, direction: str, player: int) -
{"player": player, "entrance": entrance, "exit": exit_, "direction": direction}

def create_playthrough(self, create_paths: bool = True) -> None:
"""Destructive to the world while it is run, damage gets repaired afterwards."""
"""Destructive to the multiworld while it is run, damage gets repaired afterwards."""
from itertools import chain
# get locations containing progress items
multiworld = self.multiworld
Expand Down Expand Up @@ -1262,12 +1280,12 @@ def create_playthrough(self, create_paths: bool = True) -> None:
for location in sphere:
state.collect(location.item, True, location)

required_locations -= sphere

collection_spheres.append(sphere)

logging.debug('Calculated final sphere %i, containing %i of %i progress items.', len(collection_spheres),
len(sphere), len(required_locations))

required_locations -= sphere
if not sphere:
raise RuntimeError(f'Not all required items reachable. Unreachable locations: {required_locations}')

Expand Down Expand Up @@ -1326,6 +1344,8 @@ def get_path(state: CollectionState, region: Region) -> List[Union[Tuple[str, st
get_path(state, multiworld.get_region('Inverted Big Bomb Shop', player))

def to_file(self, filename: str) -> None:
from worlds import AutoWorld

def write_option(option_key: str, option_obj: Options.AssembleOptions) -> None:
res = getattr(self.multiworld.worlds[player].options, option_key)
display_name = getattr(option_obj, "display_name", option_key)
Expand Down Expand Up @@ -1449,8 +1469,3 @@ def get_seed(seed: Optional[int] = None) -> int:
random.seed(None)
return random.randint(0, pow(10, seeddigits) - 1)
return seed


from worlds import AutoWorld

auto_world = AutoWorld.World
1 change: 1 addition & 0 deletions CommonClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,4 +941,5 @@ async def main(args):


if __name__ == '__main__':
logging.getLogger().setLevel(logging.INFO) # force log-level to work around log level resetting to WARNING
run_as_textclient()
Loading

0 comments on commit 66ef5d7

Please sign in to comment.