diff --git a/BaseClasses.py b/BaseClasses.py index bf89a0e6ec..1d3b7ee922 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -54,6 +54,7 @@ class MultiWorld(): local_early_items: Dict[int, Dict[str, int]] local_items: Dict[int, Options.LocalItems] non_local_items: Dict[int, Options.NonLocalItems] + allow_collect: Dict[int, Options.AllowCollect] progression_balancing: Dict[int, Options.ProgressionBalancing] completion_condition: Dict[int, Callable[[CollectionState], bool]] indirect_connections: Dict[Region, Set[Entrance]] diff --git a/Main.py b/Main.py index 983874f593..7d14431824 100644 --- a/Main.py +++ b/Main.py @@ -312,7 +312,7 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No client_versions[slot] = player_world.required_client_version games[slot] = world.game[slot] slot_info[slot] = NetUtils.NetworkSlot(names[0][slot - 1], world.game[slot], - world.player_types[slot]) + world.player_types[slot], bool(world.allow_collect[slot].value)) for slot, group in world.groups.items(): games[slot] = world.game[slot] slot_info[slot] = NetUtils.NetworkSlot(group["name"], world.game[slot], world.player_types[slot], diff --git a/MultiServer.py b/MultiServer.py index 1df0936259..132c73dd8c 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -220,6 +220,7 @@ class Context: self.save_dirty = False self.tags = ['AP'] self.games: typing.Dict[int, str] = {} + self.allow_collect: typing.Dict[int, bool] = {} self.minimum_client_versions: typing.Dict[int, Utils.Version] = {} self.seed_name = "" self.groups = {} @@ -417,6 +418,8 @@ class Context: self.games = {slot: slot_info.game for slot, slot_info in self.slot_info.items()} self.groups = {slot: slot_info.group_members for slot, slot_info in self.slot_info.items() if slot_info.type == SlotType.group} + self.allow_collect = {slot: slot_info.allow_collect if type(slot_info.allow_collect) is bool else True + for slot, slot_info in self.slot_info.items()} else: self.games = decoded_obj["games"] self.groups = {} @@ -429,6 +432,7 @@ class Context: } # locations may need converting for slot, locations in self.locations.items(): + self.allow_collect[slot] = True for location, item_data in locations.items(): if len(item_data) < 3: locations[location] = (*item_data, 0) @@ -903,6 +907,8 @@ def collect_player(ctx: Context, team: int, slot: int, is_group: bool = False): """register any locations that are in the multidata, pointing towards this player""" all_locations = collections.defaultdict(set) for source_slot, location_data in ctx.locations.items(): + if not ctx.allow_collect[source_slot]: + continue for location_id, values in location_data.items(): if values[1] == slot: all_locations[source_slot].add(location_id) diff --git a/NetUtils.py b/NetUtils.py index ca44fdea22..40a1fe7a91 100644 --- a/NetUtils.py +++ b/NetUtils.py @@ -71,6 +71,7 @@ class NetworkSlot(typing.NamedTuple): name: str game: str type: SlotType + allow_collect: bool = True group_members: typing.Union[typing.List[int], typing.Tuple] = () # only populated if type == group diff --git a/Options.py b/Options.py index 53bf357630..7a9eb8275a 100644 --- a/Options.py +++ b/Options.py @@ -862,9 +862,15 @@ class ProgressionBalancing(SpecialRange): } +class AllowCollect(DefaultOnToggle): + """Controls whether items are collected from the slot when a player does a !collect or not.""" + display_name = "Allow Collect" + + common_options = { "progression_balancing": ProgressionBalancing, - "accessibility": Accessibility + "accessibility": Accessibility, + "allow_collect": AllowCollect }