diff --git a/src/NoPELib/player_settings.py b/src/NoPELib/player_settings.py index 8d22f79..ab4d8fb 100644 --- a/src/NoPELib/player_settings.py +++ b/src/NoPELib/player_settings.py @@ -237,6 +237,9 @@ class ExpansionsManager: Container of the expansions to try making available activeExpansions: dict of Expansion Container of the relevent expansions + + Methods: + expansionPlayersChanged """ defaultExpansionConfig = {"players": (), "types": ()} keysConvert2Tuple = ("players", "types") @@ -251,6 +254,7 @@ class ExpansionsManager: """ # Create the attributes self.playersManager = playersManager + self._playersLookUp = {} self._cfg = playersManager.config["expansions"] if includedExpansions is not None: self._includedExpansions = tuple(includedExpansions) @@ -306,7 +310,7 @@ class ExpansionsManager: def _listPossiblyValidExpansions(self): """ - List expansions that are included, defined in expansionsLib and are available + List expansions that are: included, defined in expansionsLib and available to at least one active player. """ activePlayers = set(self.playersManager.keys()) @@ -319,14 +323,20 @@ class ExpansionsManager: def _createExpansion(self, expansionID): try: + # Create the expansion expansion = getattr(expansionsLib, expansionID)(expansionID, self) + # Update the lookup + for player in self._getPlayersFillMissing(expansionID): + self._playersLookUp[player].append(expansionID) + return expansion except Exception as e: - print(f"Could not initilise {expansionID} because of traceback:") - print(e) - else: - self._activeExpansions[expansionID] = expansion + return e def _removeExpansion(self, expansionID): + # Update the lookup + for player in self._getPlayersFillMissing(expansionID): + self._playersLookUp[player].pop(expansionID) + # Remove the expansion expansion = self._activeExpansions.pop(expansionID) expansion.close() del expansion @@ -346,7 +356,11 @@ class ExpansionsManager: # Add the new expansions expansionsToAdd = possiblyValidExpansions.difference(previousExpansions) for expansionID in expansionsToAdd: - self._createExpansion(expansionID) + creation_out = self._createExpansion(expansionID) + if isinstance(creation_out, expansionsLib.Expansion): + self._activeExpansions[expansionID] = creation_out + else: + print(creation_out) def _activePlayerAdded(self, playerName): # Find the expansions that are to be created @@ -358,7 +372,11 @@ class ExpansionsManager: ] # Create the expansions for expansionID in filteredAddition: - self._createExpansion(expansionID) + creation_out = self._createExpansion(expansionID) + if isinstance(creation_out, expansionsLib.Expansion): + self._activeExpansions[expansionID] = creation_out + else: + print(creation_out) def _activePlayerRemoved(self, playerName): # Find the expansions that are to be removed @@ -373,15 +391,55 @@ class ExpansionsManager: def _errorOccured(self, expansionID): self._removeExpansion(expansionID) - def expansionPlayersChanged(self, expansionID): + def expansionPlayersChanged(self, expansionID, newPlayers): + """ + Method that allows changing the assigned players of an expansion. + + Arguments: + expansionID (str): + newPlayers (tuple of str): + """ + # Save the change + previousPlayers = self._cfg[expansionID]["players"] + self._cfg[expansionID]["players"] = tuple(newPlayers) + # Check the state of the expansion expansionIsActive = expansionID in self._activeExpansions activePlayers = set(self.playersManager.keys()) expansionHasNoPlayers = self._getPlayersFillMissing(expansionID).isdisjoint(activePlayers) expansionDefined = hasattr(expansionsLib, expansionID) + # Update the activation status + activeChanged = False if expansionIsActive and expansionHasNoPlayers: self._removeExpansion(expansionID) + activeChanged = True elif (not expansionIsActive) and (not expansionHasNoPlayers) and expansionDefined: - self._createExpansion(expansionID) + creation_out = self._createExpansion(expansionID) + if isinstance(creation_out, expansionsLib.Expansion): + self._activeExpansions[expansionID] = creation_out + activeChanged = True + elif isinstance(creation_out, Exception): + print(creation_out) + # Update the inverse lookup + if not activeChanged: + removedPlayers = set(previousPlayers).difference(newPlayers) + addedPlayers = set(newPlayers).difference(previousPlayers) + for playerName in removedPlayers: + self._playersLookUp[playerName].pop(expansionID) + for playerName in addedPlayers: + self._playersLookUp[playerName].append(expansionID) + + def lookupPlayer(self, playerName): + """ + Get a tuple of all expansions available to a player. + + Arguments: + playerName (str): Name of the player + + Returns: + expansionsID (tuple of str): ID of the expansions available to the + player + """ + return tuple(self._playersLookUp[playerName]) if __name__ == "__main__":