def test_finds_locations( inventory: PlayerInventory, item_templates_repository: ItemTemplatesRepository = Provide[ AppContainer.repos.templates], item_factory: ItemFactory = Provide[AppContainer.items.factory], ) -> None: # Should be able to completely fill EOD stash with PSUs width, height = inventory.grid_size psu_template = item_templates_repository.get_template( TemplateId("57347c2e24597744902c94a1")) for i in range((width * height) // (2 * 2)): psu, _ = item_factory.create_item(psu_template) inventory.place_item(psu) with pytest.raises(NoSpaceError): psu, _ = item_factory.create_item(psu_template) inventory.place_item(psu)
def test_should_not_be_able_to_place_items_out_of_bounds( inventory: PlayerInventory, test_coords: Tuple[int, int], item_templates_repository: ItemTemplatesRepository = Provide[ AppContainer.repos.templates], item_factory: ItemFactory = Provide[AppContainer.items.factory], ) -> None: magbox = item_factory.create_item( item_templates_repository.get_template( TemplateId("5c127c4486f7745625356c13")))[0] x, y = test_coords with pytest.raises(PlayerInventory.InvalidItemLocation): inventory.place_item( item=magbox, location=ItemInventoryLocation( x=x, y=y, r=ItemOrientationEnum.Horizontal.value), )
def complete_quest( self, quest_id: str, templates_repository: ItemTemplatesRepository = Provide[ AppContainer.repos.templates], trader_manager: TraderManager = Provide[AppContainer.trader.manager], ) -> None: quest_template = self.__quests_repository.get_quest_template(quest_id) quest = self.get_quest(quest_id) quest.status = QuestStatus.Success reward_items: List[Item] = [] for reward in quest_template.rewards.Success: if isinstance(reward, QuestRewardItem): for reward_item in reward.items: item_template = templates_repository.get_template( reward_item) stack_size: int = item_template.props.StackMaxSize while reward_item.upd.StackObjectsCount > 0: amount_to_split = min( reward_item.upd.StackObjectsCount, stack_size) reward_items.append( PlayerInventory.simple_split_item( reward_item, amount_to_split)) elif isinstance(reward, QuestRewardExperience): exp_amount: str = reward.value self.profile.receive_experience(int(exp_amount)) elif isinstance(reward, QuestRewardTraderStanding): standing_change = float(reward.value) trader_id = reward.target trader = trader_manager.get_trader(TraderType(trader_id)) trader_view = trader.view(player_profile=self.profile) standing = trader_view.standing standing.current_standing += standing_change elif isinstance(reward, QuestRewardAssortUnlock): # We're checking for quest assort when generating it for specific player pass else: raise ValueError( f"Unknown reward: {reward.__class__.__name__} {reward}") message = MailDialogueMessage( uid=quest_template.traderId, type=StrictInt(MailMessageType.QuestSuccess.value), templateId= "5ab0f32686f7745dd409f56b", # TODO: Right now this is a placeholder systemData={}, items=MailMessageItems.from_items(reward_items), hasRewards=True, ) self.profile.mail.add_message(message)
def read(self) -> None: if any( not path.exists() for path in (self.pmc_profile_path, self.scav_profile_path) ): raise Profile.ProfileDoesNotExistsError self.pmc = ProfileModel.parse_file(self.pmc_profile_path) self.scav = ProfileModel.parse_file(self.scav_profile_path) self.encyclopedia = self.__encyclopedia_factory(profile=self) self.inventory = PlayerInventory(profile=self) self.inventory.read() self.quests = self.__quests_factory(profile=self) self.hideout = self.__hideout_factory(profile=self) self.hideout.read() self.mail = Mail(profile=self, notifier_service=self.__notifier_service) self.mail.read()
def read( self, notifier_service: NotifierService = Provide[ AppContainer.notifier.service] ) -> None: if any(not path.exists() for path in (self.pmc_profile_path, self.scav_profile_path)): raise Profile.ProfileDoesNotExistsError self.pmc = ProfileModel.parse_file(self.pmc_profile_path) self.scav = ProfileModel.parse_file(self.scav_profile_path) self.encyclopedia = Encyclopedia(profile=self) self.inventory = PlayerInventory(profile=self) self.inventory.read() self.quests = Quests(profile=self) self.hideout = Hideout(profile=self) self.hideout.read() self.mail = Mail(self, notifier_service) self.mail.read()
class Profile: class ProfileDoesNotExistsError(Exception): pass pmc: ProfileModel scav: ProfileModel hideout: Hideout quests: Quests inventory: PlayerInventory encyclopedia: Encyclopedia mail: Mail def __init__( self, profile_dir: Path, profile_id: str, encyclopedia_factory: Callable[..., Encyclopedia], hideout_factory: Callable[..., Hideout], quests_factory: Callable[..., Quests], notifier_service: NotifierService, ): self.__encyclopedia_factory = encyclopedia_factory self.__hideout_factory = hideout_factory self.__quests_factory = quests_factory self.__notifier_service = notifier_service self.profile_dir = profile_dir self.profile_id = profile_id self.pmc_profile_path = self.profile_dir.joinpath("pmc_profile.json") self.scav_profile_path = self.profile_dir.joinpath("scav_profile.json") def add_insurance(self, item: Item, trader: TraderType) -> None: # TODO: Move this function into IInsuranceService self.pmc.InsuredItems.append( ItemInsurance(item_id=item.id, trader_id=trader.value) ) def receive_experience(self, amount: int) -> None: self.pmc.Info.Experience += amount def read(self) -> None: if any( not path.exists() for path in (self.pmc_profile_path, self.scav_profile_path) ): raise Profile.ProfileDoesNotExistsError self.pmc = ProfileModel.parse_file(self.pmc_profile_path) self.scav = ProfileModel.parse_file(self.scav_profile_path) self.encyclopedia = self.__encyclopedia_factory(profile=self) self.inventory = PlayerInventory(profile=self) self.inventory.read() self.quests = self.__quests_factory(profile=self) self.hideout = self.__hideout_factory(profile=self) self.hideout.read() self.mail = Mail(profile=self, notifier_service=self.__notifier_service) self.mail.read() def write(self) -> None: self.hideout.write() self.mail.write() self.inventory.write() atomic_write(self.pmc.json(exclude_defaults=True), self.pmc_profile_path) atomic_write(self.scav.json(exclude_defaults=True), self.scav_profile_path) def update(self) -> None: self.hideout.update()
def _make_inventory(inventory_path: str) -> PlayerInventory: target_inventory = InventoryModel.parse_file(inventory_path) with patch.object(player_profile.pmc, "Inventory", target_inventory): inventory = PlayerInventory(player_profile) inventory.read() return inventory
def inventory(player_profile: Profile) -> PlayerInventory: inventory = PlayerInventory(player_profile) inventory.read() return inventory
def test_places_items(inventory: PlayerInventory, random_items: List[Item]) -> None: for item in random_items: inventory.place_item(item) assert all(item in inventory.items.values() for item in random_items)
class Profile: # pylint: disable=too-many-instance-attributes # Disabling that in case of profile is reasonable class ProfileDoesNotExistsError(Exception): pass pmc: ProfileModel scav: ProfileModel hideout: Hideout quests: Quests inventory: PlayerInventory encyclopedia: Encyclopedia mail: Mail def __init__(self, profile_id: str): self.profile_id = profile_id self.profile_dir = root_dir.joinpath("resources", "profiles", profile_id) self.pmc_profile_path = self.profile_dir.joinpath("pmc_profile.json") self.scav_profile_path = self.profile_dir.joinpath("scav_profile.json") @staticmethod def exists(profile_id: str) -> bool: return root_dir.joinpath("resources", "profiles", profile_id).exists() def add_insurance(self, item: Item, trader: TraderType) -> None: self.pmc.InsuredItems.append( ItemInsurance(item_id=item.id, trader_id=trader.value)) # Todo remove insurance from items that aren't present in inventory after raid def receive_experience(self, amount: int) -> None: self.pmc.Info.Experience += amount @inject def read( self, notifier_service: NotifierService = Provide[ AppContainer.notifier.service] ) -> None: if any(not path.exists() for path in (self.pmc_profile_path, self.scav_profile_path)): raise Profile.ProfileDoesNotExistsError self.pmc = ProfileModel.parse_file(self.pmc_profile_path) self.scav = ProfileModel.parse_file(self.scav_profile_path) self.encyclopedia = Encyclopedia(profile=self) self.inventory = PlayerInventory(profile=self) self.inventory.read() self.quests = Quests(profile=self) self.hideout = Hideout(profile=self) self.hideout.read() self.mail = Mail(self, notifier_service) self.mail.read() def write(self) -> None: self.hideout.write() self.mail.write() self.inventory.write() atomic_write(self.pmc.json(exclude_defaults=True), self.pmc_profile_path) atomic_write(self.scav.json(exclude_defaults=True), self.scav_profile_path) def update(self) -> None: self.hideout.update() def __enter__(self) -> Profile: self.read() return self def __exit__( self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType], ) -> None: if exc_type is None: self.write()