From 36900334d0e59e76cc5d02adf546fdad2e9ff025 Mon Sep 17 00:00:00 2001 From: sebastian Date: Fri, 13 Feb 2026 17:19:48 +0100 Subject: [PATCH] UPD: Refactor BuildingSystem --- CMakeLists.txt | 17 +++++++++ src/engine/core/gui/uiComponent/UiImage.cpp | 1 - src/engine/toolbox/util.h | 15 ++++++++ src/game/GameLayer.cpp | 4 -- src/game/GameMode.cpp | 13 +++++++ src/game/GameMode.h | 5 +++ src/game/hexWorld/building/BuildingConfig.cpp | 15 ++++++++ src/game/hexWorld/building/BuildingConfig.h | 16 ++++++++ .../hexWorld/building/BuildingDefinition.h | 18 +++++++++ .../hexWorld/building/BuildingFactory.cpp | 27 ++++++++++++++ src/game/hexWorld/building/BuildingFactory.h | 17 +++++++++ src/game/hexWorld/building/BuildingRules.cpp | 23 ++++++++++++ src/game/hexWorld/building/BuildingRules.h | 17 +++++++++ .../TemporaryBuildingDefinitionFactory.h | 23 ++++++++++++ .../ecs/systems/BuildingPlacementSystem.cpp | 37 ++++++++++--------- 15 files changed, 225 insertions(+), 23 deletions(-) create mode 100644 src/engine/toolbox/util.h create mode 100644 src/game/hexWorld/building/BuildingConfig.cpp create mode 100644 src/game/hexWorld/building/BuildingConfig.h create mode 100644 src/game/hexWorld/building/BuildingDefinition.h create mode 100644 src/game/hexWorld/building/BuildingFactory.cpp create mode 100644 src/game/hexWorld/building/BuildingFactory.h create mode 100644 src/game/hexWorld/building/BuildingRules.cpp create mode 100644 src/game/hexWorld/building/BuildingRules.h create mode 100644 src/game/hexWorld/building/TemporaryBuildingDefinitionFactory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fffd4e7..e6154b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,8 +153,25 @@ add_executable(Dicewars_Siedler src/main.cpp src/game/ui/components/factorys/RessourceWidgetFactory.h src/game/ui/components/UiInventoryContainer.cpp src/game/ui/components/UiInventoryContainer.h + src/game/hexWorld/building/BuildingDefinition.h + src/game/hexWorld/building/TemporaryBuildingDefinitionFactory.h + src/game/hexWorld/building/BuildingRules.cpp + src/game/hexWorld/building/BuildingRules.h + src/game/hexWorld/building/BuildingFactory.cpp + src/game/hexWorld/building/BuildingFactory.h + src/game/hexWorld/building/BuildingConfig.cpp + src/game/hexWorld/building/BuildingConfig.h + src/engine/toolbox/util.h ) +target_compile_options(Dicewars_Siedler PRIVATE + -Wall + -Wextra + -Wpedantic + -Werror=return-type +) + + target_include_directories(Dicewars_Siedler PRIVATE lib/glfw/include lib/glm diff --git a/src/engine/core/gui/uiComponent/UiImage.cpp b/src/engine/core/gui/uiComponent/UiImage.cpp index 8580bd8..7c2122c 100644 --- a/src/engine/core/gui/uiComponent/UiImage.cpp +++ b/src/engine/core/gui/uiComponent/UiImage.cpp @@ -9,7 +9,6 @@ void UiImage::onCollectRenderData(UiRenderBundle& renderBundle) { if (!visible) return; Dimensions dims = uiPositioner.screenSpace; - std::cout << "Child Y: " << uiPositioner.screenSpace.y << "Height " << uiPositioner.screenSpace.height <(texture));; } diff --git a/src/engine/toolbox/util.h b/src/engine/toolbox/util.h new file mode 100644 index 0000000..af26e61 --- /dev/null +++ b/src/engine/toolbox/util.h @@ -0,0 +1,15 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_UTIL_H +#define DICEWARS_SIEDLER_UTIL_H +#include + +namespace util { + template + bool contains(const Range& range, const T& value) { + return std::find(range.begin(), range.end(), value) != range.end(); + } +} +#endif //DICEWARS_SIEDLER_UTIL_H \ No newline at end of file diff --git a/src/game/GameLayer.cpp b/src/game/GameLayer.cpp index 7e63258..74d9d9e 100644 --- a/src/game/GameLayer.cpp +++ b/src/game/GameLayer.cpp @@ -74,10 +74,6 @@ void GameLayer::onUpdate() if (InputManager::isKeyPressed(GLFW_KEY_A)) moveDir.x -= 1.0f; if (InputManager::isKeyPressed(GLFW_KEY_D)) moveDir.x += 1.0f; - if (InputManager::isKeyPressed(GLFW_KEY_F)) { - gameMode->getPlayerInventory(gameMode->getCurrentPlayer()).add(RessourceType::FOOD, 10); - } - camera->move(moveDir, 0.5f); tileHighlightSystem->update(*entityManager, *mousePicker, *camera); diff --git a/src/game/GameMode.cpp b/src/game/GameMode.cpp index 2259f86..cb9f25f 100644 --- a/src/game/GameMode.cpp +++ b/src/game/GameMode.cpp @@ -22,6 +22,13 @@ bool GameMode::canBuild(PlayerID player, BuildingType buildingType) { return true; } +bool GameMode::canAfford(const PlayerID player_id, RessourceType ressource, int amount) const { + if (players.contains(player_id)) { + return players.at(player_id).getInventory()->getAmount(ressource) >= amount; + } + return false; +} + void GameMode::build(PlayerID player, EntityID tileEntity, BuildingType buildingType) { if (canBuild(player, buildingType)) { players[player].getInventory()->spend(RessourceType::WOOD, 10); @@ -41,4 +48,10 @@ PlayerInventory& GameMode::getPlayerInventory(PlayerID playerID) { return *players[playerID].getInventory(); } +void GameMode::pay(PlayerID playerID, const std::unordered_map &costs) { + for (const auto &[resourceType, amount] : costs) { + players[playerID].getInventory()->spend(resourceType, amount); + } +} + diff --git a/src/game/GameMode.h b/src/game/GameMode.h index 9928bdd..ff3c6e0 100644 --- a/src/game/GameMode.h +++ b/src/game/GameMode.h @@ -13,6 +13,9 @@ class GameMode { public: GameMode(); bool canBuild(EntityID player, BuildingType buildingType); + + bool canAfford(PlayerID player_id, RessourceType ressource, int amount) const; + void build(EntityID player, EntityID tileEntity, BuildingType buildingType); void addPlayer(PlayerID playerID, std::string name); @@ -20,6 +23,8 @@ public: PlayerID getCurrentPlayer(); PlayerInventory& getPlayerInventory(PlayerID playerID); + void pay(PlayerID uint32, const std::unordered_map & pairs); + private: std::unordered_map players; diff --git a/src/game/hexWorld/building/BuildingConfig.cpp b/src/game/hexWorld/building/BuildingConfig.cpp new file mode 100644 index 0000000..772d225 --- /dev/null +++ b/src/game/hexWorld/building/BuildingConfig.cpp @@ -0,0 +1,15 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "BuildingConfig.h" + +#include "TemporaryBuildingDefinitionFactory.h" + +const BuildingDefinition & BuildingConfig::get(BuildingType type) { + if (type == BuildingType::FOREST_HUT) { + static const BuildingDefinition def = TemporaryBuildingDefinitionFactory::createForestHutDefinition(); + return def; + } + std::__throw_runtime_error("Unknown BuildingType"); +} diff --git a/src/game/hexWorld/building/BuildingConfig.h b/src/game/hexWorld/building/BuildingConfig.h new file mode 100644 index 0000000..e5ff243 --- /dev/null +++ b/src/game/hexWorld/building/BuildingConfig.h @@ -0,0 +1,16 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_BUILDINGCONFIG_H +#define DICEWARS_SIEDLER_BUILDINGCONFIG_H +#include "BuildingDefinition.h" + + +class BuildingConfig { +public: + static const BuildingDefinition& get(BuildingType type); +}; + + +#endif //DICEWARS_SIEDLER_BUILDINGCONFIG_H \ No newline at end of file diff --git a/src/game/hexWorld/building/BuildingDefinition.h b/src/game/hexWorld/building/BuildingDefinition.h new file mode 100644 index 0000000..a455719 --- /dev/null +++ b/src/game/hexWorld/building/BuildingDefinition.h @@ -0,0 +1,18 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_BUILDINGDEFINITION_H +#define DICEWARS_SIEDLER_BUILDINGDEFINITION_H +#include "../ecs/components/BuildingComponent.h" + +struct BuildingDefinition { + BuildingType type; + + std::vector allowedTileResources; + std::unordered_map resourceCosts; + + std::string model; +}; + +#endif //DICEWARS_SIEDLER_BUILDINGDEFINITION_H \ No newline at end of file diff --git a/src/game/hexWorld/building/BuildingFactory.cpp b/src/game/hexWorld/building/BuildingFactory.cpp new file mode 100644 index 0000000..83808b1 --- /dev/null +++ b/src/game/hexWorld/building/BuildingFactory.cpp @@ -0,0 +1,27 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "BuildingFactory.h" + +#include "../../../engine/core/ECS/ModelComponent.h" +#include "../../../engine/core/ECS/TransformComponent.h" +#include "../../../engine/renderer/model/AssetManager.h" + +EntityID BuildingFactory::create(EntityManager &em, const BuildingDefinition &def, + const TransformComponent &tileTransform, EntityID tileEntity, PlayerID owner) { + + EntityID e = em.createEntity(); + + em.addComponent(e, std::make_shared(AssetManager::getModel(def.model))); + + em.addComponent(e, std::make_shared( + tileTransform.position, glm::vec3(0), 1.f + )); + + em.addComponent(e, std::make_shared(def.type, tileEntity)); + + em.addComponent(e, std::make_shared(owner)); + + return e; +} diff --git a/src/game/hexWorld/building/BuildingFactory.h b/src/game/hexWorld/building/BuildingFactory.h new file mode 100644 index 0000000..fdfac25 --- /dev/null +++ b/src/game/hexWorld/building/BuildingFactory.h @@ -0,0 +1,17 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_BUILDINGFACTORY_H +#define DICEWARS_SIEDLER_BUILDINGFACTORY_H +#include "BuildingDefinition.h" +#include "../../../engine/core/ECS/EntityManager.h" + + +class BuildingFactory { +public: + static EntityID create(EntityManager& em, const BuildingDefinition& def, const TransformComponent& tileTransform, EntityID tileEntity, PlayerID owner); +}; + + +#endif //DICEWARS_SIEDLER_BUILDINGFACTORY_H \ No newline at end of file diff --git a/src/game/hexWorld/building/BuildingRules.cpp b/src/game/hexWorld/building/BuildingRules.cpp new file mode 100644 index 0000000..7cab748 --- /dev/null +++ b/src/game/hexWorld/building/BuildingRules.cpp @@ -0,0 +1,23 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "BuildingRules.h" +#include + +#include "../../../engine/toolbox/util.h" +#include "../ecs/components/TileGameplayComponent.h" + +bool BuildingRules::canPlace(const BuildingDefinition &def, const TileGameplayComponent &tile, const GameMode &gameMode, + PlayerID playerID) { + + if (tile.hasBuilding()) return false; + + if (!util::contains(def.allowedTileResources, tile.ressourceType)) return false; + + for (auto& [type, costs] : def.resourceCosts) { + if (!gameMode.canAfford(playerID, type, costs)) return false; + } + + return true; +} diff --git a/src/game/hexWorld/building/BuildingRules.h b/src/game/hexWorld/building/BuildingRules.h new file mode 100644 index 0000000..49e898a --- /dev/null +++ b/src/game/hexWorld/building/BuildingRules.h @@ -0,0 +1,17 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_BUILDINGRULES_H +#define DICEWARS_SIEDLER_BUILDINGRULES_H +#include "BuildingDefinition.h" +#include "../../GameMode.h" + + +class BuildingRules { +public: + static bool canPlace(const BuildingDefinition& def, const TileGameplayComponent& tile, const GameMode& gameMode, PlayerID playerID); +}; + + +#endif //DICEWARS_SIEDLER_BUILDINGRULES_H \ No newline at end of file diff --git a/src/game/hexWorld/building/TemporaryBuildingDefinitionFactory.h b/src/game/hexWorld/building/TemporaryBuildingDefinitionFactory.h new file mode 100644 index 0000000..34d0195 --- /dev/null +++ b/src/game/hexWorld/building/TemporaryBuildingDefinitionFactory.h @@ -0,0 +1,23 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_TEMPORARYBUILDINGDEFINITIONFACTORY_H +#define DICEWARS_SIEDLER_TEMPORARYBUILDINGDEFINITIONFACTORY_H +#include "BuildingDefinition.h" + +namespace TemporaryBuildingDefinitionFactory { + static inline BuildingDefinition createForestHutDefinition() { + auto allowedTileResources = std::vector{RessourceType::WOOD}; + auto resourceCosts = std::unordered_map{}; + resourceCosts[RessourceType::WOOD] = 10; + return { + BuildingType::FOREST_HUT, + allowedTileResources, + resourceCosts, + "cabin" + }; + } +} + +#endif //DICEWARS_SIEDLER_TEMPORARYBUILDINGDEFINITIONFACTORY_H \ No newline at end of file diff --git a/src/game/hexWorld/ecs/systems/BuildingPlacementSystem.cpp b/src/game/hexWorld/ecs/systems/BuildingPlacementSystem.cpp index 08f600c..6cdc09c 100644 --- a/src/game/hexWorld/ecs/systems/BuildingPlacementSystem.cpp +++ b/src/game/hexWorld/ecs/systems/BuildingPlacementSystem.cpp @@ -11,6 +11,9 @@ #include "../../../../engine/core/ECS/TransformComponent.h" #include "../../../../engine/platform/glfw/InputManager.h" #include "../../../../engine/renderer/model/AssetManager.h" +#include "../../building/BuildingConfig.h" +#include "../../building/BuildingFactory.h" +#include "../../building/BuildingRules.h" #include "../components/BuildingComponent.h" #include "../components/TileGameplayComponent.h" #include "GLFW/glfw3.h" @@ -21,28 +24,26 @@ void BuildingPlacementSystem::update(EntityManager& entityManager, GameMode& gam } for (EntityID entityID : entityManager.getAllEntities()) { - auto transformComponent = entityManager.getComponent(entityID); - auto tileGameplayComponent = entityManager.getComponent(entityID); - auto tileRenderComponent = entityManager.getComponent(entityID); + auto transform = entityManager.getComponent(entityID); + auto gameplay = entityManager.getComponent(entityID); + auto render = entityManager.getComponent(entityID); - if (!transformComponent || !tileGameplayComponent || !tileRenderComponent) continue; + if (!transform || !gameplay || !render) continue; + if (!render->isHighlighted) continue; - // Tile is not in focus or tile has already a building - if (!tileRenderComponent->isHighlighted || tileGameplayComponent->hasBuilding()) continue; + const auto &def = BuildingConfig::get(BuildingType::FOREST_HUT); - if (!gameMode.canBuild(player, BuildingType::FOREST_HUT)) continue; + if (!BuildingRules::canPlace(def, *gameplay, gameMode, player)) continue; - gameMode.build(player, entityID, BuildingType::FOREST_HUT); - for (auto oldID : tileGameplayComponent->entitiesOnTile) { - entityManager.destroyEntity(oldID); + gameMode.pay(player, def.resourceCosts); + + for (auto e : gameplay->entitiesOnTile) { + entityManager.destroyEntity(e); } - tileGameplayComponent->entitiesOnTile.clear(); + gameplay->entitiesOnTile.clear(); - EntityID buildingEntity = entityManager.createEntity(); - entityManager.addComponent(buildingEntity, std::make_shared(AssetManager::getModel("cabin"))); - entityManager.addComponent(buildingEntity, std::make_shared(transformComponent->position, glm::vec3(0), 1.f)); - entityManager.addComponent(buildingEntity, std::make_shared(BuildingType::FOREST_HUT, entityID)); - entityManager.addComponent(buildingEntity, std::make_shared(player)); - tileGameplayComponent->buildingEntityID = buildingEntity; + const EntityID buildingEntity = BuildingFactory::create(entityManager, def, *transform, entityID, player); + gameplay->buildingEntityID = buildingEntity; + break; } -} +};