diff --git a/app/Services/ObjectService.php b/app/Services/ObjectService.php index 3377ce4e..37b034c1 100644 --- a/app/Services/ObjectService.php +++ b/app/Services/ObjectService.php @@ -11,6 +11,7 @@ use OGame\GameObjects\Models\BuildingObject; use OGame\GameObjects\Models\DefenseObject; use OGame\GameObjects\Models\Enums\GameObjectType; +use OGame\GameObjects\Models\Fields\GameObjectRequirement; use OGame\GameObjects\Models\ResearchObject; use OGame\GameObjects\Models\ShipObject; use OGame\GameObjects\Models\StationObject; @@ -333,34 +334,12 @@ public static function getBuildingObjectsWithStorage(): array */ public static function objectRequirementsMet(string $machine_name, PlanetService $planet, PlayerService $player): bool { - try { - $object = self::getObjectByMachineName($machine_name); - - foreach ($object->requirements as $requirement) { - // Load required object and check if requirements are met. - $object_required = self::getObjectByMachineName($requirement->object_machine_name); - - if ($object_required->type === GameObjectType::Research) { - // Check if requirements are met with existing technology. - if ($player->getResearchLevel($object_required->machine_name) < $requirement->level) { - return false; - } - } else { - // Check if requirements are met with existing buildings. - if ($planet->getObjectLevel($object_required->machine_name) < $requirement->level) { - return false; - } - } - } - } catch (Exception $e) { - return false; - } - - return true; + $object = self::getObjectByMachineName($machine_name); + return count(self::filterCompletedRequirements($object->requirements, $planet, $player)) === 0; } /** - * Check if object requirements are met (for building it). + * Check if object requirements are met (for building it) with previous levels completed. * * @param string $machine_name * @param PlanetService $planet @@ -373,9 +352,9 @@ public static function objectRequirementsWithLevelsMet(string $machine_name, int try { $object = self::getObjectByMachineName($machine_name); - // Check that the object's previous levels exist. + // Check that the object's previous level exists. if ($target_level) { - if (!self::hasRequiredLevels($target_level, $object, $planet, $player)) { + if (!self::hasPreviousLevels($target_level, $object, $planet, $player)) { return false; } } @@ -383,11 +362,11 @@ public static function objectRequirementsWithLevelsMet(string $machine_name, int return false; } - return self::objectRequirementsMet($machine_name, $planet, $player); + return count(self::filterCompletedRequirements($object->requirements, $planet, $player)) === 0; } /** - * Check if object requirements are met with existing and queued items (for building it). + * Check if object requirements are met (for building it) with existing and queued items. * * @param string $machine_name * @param PlanetService $planet @@ -398,49 +377,18 @@ public static function objectRequirementsWithLevelsMet(string $machine_name, int public static function objectRequirementsMetWithQueue(string $machine_name, int $target_level, PlanetService $planet, PlayerService $player): bool { // Check the object's requirements against the existing objects - if (self::objectRequirementsWithLevelsMet($machine_name, $target_level, $planet, $player)) { - return true; - } - - // Check the object’s requirements against the queued objects. - try { - $object = self::getObjectByMachineName($machine_name); - - if (!self::hasRequiredLevelsInQueue($target_level, $object, $planet, $player)) { - return false; - } - - foreach ($object->requirements as $requirement) { - // Load required object and check if requirements are met. - $object_required = self::getObjectByMachineName($requirement->object_machine_name); - - // Skip the queue check for the research lab, as it must be present for research objects. - if ($object_required->machine_name === 'research_lab') { - if ($planet->getObjectLevel('research_lab') === $requirement->level) { - continue; - } else { - return false; - } - } + $object = self::getObjectByMachineName($machine_name); + $incompleteRequirements = self::filterCompletedRequirements($object->requirements, $planet, $player); - if ($object_required->type === GameObjectType::Research) { - // Check if the requirements are met by the items in the research queue. - if (!$player->isResearchingTech($requirement->object_machine_name, $requirement->level)) { - return false; - } - } else { - // Check if the requirements are met by the items in the building queue. - // The building queue is checked only for building queue objects, not for unit queue objects. - if (!$planet->isBuildingObject($requirement->object_machine_name, $requirement->level)) { - return false; - } - } - } - } catch (Exception $e) { + if (!self::hasPreviousLevelsInQueue($target_level, $object, $planet, $player)) { return false; } - return true; + if (count($incompleteRequirements) === 0) { + return true; + } + + return count(self::filterQueuedRequirements($incompleteRequirements, $planet, $player)) === 0; } /** @@ -575,6 +523,78 @@ public static function getObjectRawPrice(string $machine_name, int $level = 0): return new Resources($metal, $crystal, $deuterium, $energy); } + /** + * Filter out completed requirements. + * + * @param array $requirements + * @param PlanetService $planet + * @param PlayerService $player + * @return array + */ + private static function filterCompletedRequirements(array $requirements, PlanetService $planet, PlayerService $player): array + { + return array_filter($requirements, function ($requirement) use ($planet, $player) { + try { + $object = self::getObjectByMachineName($requirement->object_machine_name); + + if ($object->type === GameObjectType::Research) { + // Check if requirements are met with existing technology. + if ($player->getResearchLevel($requirement->object_machine_name) < $requirement->level) { + return true; + } + } else { + // Check if requirements are met with existing buildings. + if ($planet->getObjectLevel($requirement->object_machine_name) < $requirement->level) { + return true; + } + } + + return false; + } catch (Exception $e) { + return true; + } + }); + } + + /** + * Filter out queued requirements. + * + * @param array $requirements + * @param PlanetService $planet + * @param PlayerService $player + * @return array + */ + private static function filterQueuedRequirements(array $requirements, PlanetService $planet, PlayerService $player): array + { + return array_filter($requirements, function ($requirement) use ($planet, $player) { + try { + $object = self::getObjectByMachineName($requirement->object_machine_name); + + // Skip the queue check for the research lab, as it must be present for research objects. + if ($requirement->object_machine_name === 'research_lab') { + return ($planet->getObjectLevel('research_lab') !== $requirement->level); + } + + if ($object->type === GameObjectType::Research) { + // Check if the requirements are met by the items in the research queue. + if (!$player->isResearchingTech($requirement->object_machine_name, $requirement->level)) { + return true; + } + } else { + // Check if the requirements are met by the items in the building queue. + // The building queue is checked only for building queue objects, not for unit queue objects. + if (!$planet->isBuildingObject($requirement->object_machine_name, $requirement->level)) { + return true; + } + } + + return false; + } catch (Exception $e) { + return true; + } + }); + } + /** * Check if object previous level requirements are met (for building it). * @@ -584,7 +604,7 @@ public static function getObjectRawPrice(string $machine_name, int $level = 0): * @param PlayerService $player * @return bool */ - private static function hasRequiredLevels(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool + private static function hasPreviousLevels(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool { $current_level = 0; @@ -611,7 +631,7 @@ private static function hasRequiredLevels(int $target_level, GameObject $object, * @param PlayerService $player * @return bool */ - private static function hasRequiredLevelsInQueue(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool + private static function hasPreviousLevelsInQueue(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool { // Check prior levels from queues $current_level = 0; diff --git a/app/Services/ResearchQueueService.php b/app/Services/ResearchQueueService.php index ac289998..19f0086f 100644 --- a/app/Services/ResearchQueueService.php +++ b/app/Services/ResearchQueueService.php @@ -122,7 +122,7 @@ public function add(PlayerService $player, PlanetService $planet, int $research_ // Check to see how many other items of this technology there are already // in the queue, because if so then the level needs to be higher than that. - $amount = $this->activeBuildingQueueItemCount($player, $research_object_id); + $amount = $this->activeResearchQueueItemCount($player, $research_object_id); $next_level = $current_level + $amount + 1; // Check if user satisifes requirements to research this object. @@ -147,6 +147,10 @@ public function add(PlayerService $player, PlanetService $planet, int $research_ /** * Retrieve current research queue for a planet. * + * @TODO this function is not retrieving the queue for a planet + * like the comment says, instead the queue is retrieved for a player. + * Bug or incorrect comment? + * * @param PlanetService $planet * @return ResearchQueueListViewModel * @throws Exception @@ -193,14 +197,13 @@ public function retrieveQueue(PlanetService $planet): ResearchQueueListViewModel } /** - * Get the amount of already existing queue items for a particular - * building. + * Get the amount of player active research queue items. * * @param PlayerService $player - * @param int $building_id + * @param int $tech_id * @return int */ - public function activeBuildingQueueItemCount(PlayerService $player, int $building_id): int + public function activeResearchQueueItemCount(PlayerService $player, int $tech_id = 0): int { // Fetch queue items from model return $this->model @@ -208,7 +211,7 @@ public function activeBuildingQueueItemCount(PlayerService $player, int $buildin ->join('users', 'planets.user_id', '=', 'users.id') ->where([ ['users.id', $player->getId()], - ['research_queues.object_id', $building_id], + ['research_queues.object_id', $tech_id], ['research_queues.processed', 0], ['research_queues.canceled', 0], ])