UPD: Refactor BuildingSystem

This commit is contained in:
sebastian 2026-02-13 17:19:48 +01:00
parent c3a0fa662c
commit 36900334d0
15 changed files with 225 additions and 23 deletions

View File

@ -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

View File

@ -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 <<std::endl;
GUITexture texture(textureID, glm::vec2(dims.x, dims.y), glm::vec2(dims.width, dims.height));
renderBundle.addGUITexture(std::make_shared<GUITexture>(texture));;
}

15
src/engine/toolbox/util.h Normal file
View File

@ -0,0 +1,15 @@
//
// Created by sebastian on 13.02.26.
//
#ifndef DICEWARS_SIEDLER_UTIL_H
#define DICEWARS_SIEDLER_UTIL_H
#include <algorithm>
namespace util {
template<typename Range, typename T>
bool contains(const Range& range, const T& value) {
return std::find(range.begin(), range.end(), value) != range.end();
}
}
#endif //DICEWARS_SIEDLER_UTIL_H

View File

@ -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);

View File

@ -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<RessourceType, int> &costs) {
for (const auto &[resourceType, amount] : costs) {
players[playerID].getInventory()->spend(resourceType, amount);
}
}

View File

@ -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<RessourceType, int> & pairs);
private:
std::unordered_map<PlayerID, Player> players;

View File

@ -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");
}

View File

@ -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

View File

@ -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<RessourceType> allowedTileResources;
std::unordered_map<RessourceType, int> resourceCosts;
std::string model;
};
#endif //DICEWARS_SIEDLER_BUILDINGDEFINITION_H

View File

@ -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<ModelComponent>(AssetManager::getModel(def.model)));
em.addComponent(e, std::make_shared<TransformComponent>(
tileTransform.position, glm::vec3(0), 1.f
));
em.addComponent(e, std::make_shared<BuildingComponent>(def.type, tileEntity));
em.addComponent(e, std::make_shared<OwnerComponent>(owner));
return e;
}

View File

@ -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

View File

@ -0,0 +1,23 @@
//
// Created by sebastian on 13.02.26.
//
#include "BuildingRules.h"
#include <algorithm>
#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;
}

View File

@ -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

View File

@ -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>{RessourceType::WOOD};
auto resourceCosts = std::unordered_map<RessourceType, int>{};
resourceCosts[RessourceType::WOOD] = 10;
return {
BuildingType::FOREST_HUT,
allowedTileResources,
resourceCosts,
"cabin"
};
}
}
#endif //DICEWARS_SIEDLER_TEMPORARYBUILDINGDEFINITIONFACTORY_H

View File

@ -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<TransformComponent>(entityID);
auto tileGameplayComponent = entityManager.getComponent<TileGameplayComponent>(entityID);
auto tileRenderComponent = entityManager.getComponent<TileRenderComponent>(entityID);
auto transform = entityManager.getComponent<TransformComponent>(entityID);
auto gameplay = entityManager.getComponent<TileGameplayComponent>(entityID);
auto render = entityManager.getComponent<TileRenderComponent>(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<ModelComponent>(AssetManager::getModel("cabin")));
entityManager.addComponent(buildingEntity, std::make_shared<TransformComponent>(transformComponent->position, glm::vec3(0), 1.f));
entityManager.addComponent(buildingEntity, std::make_shared<BuildingComponent>(BuildingType::FOREST_HUT, entityID));
entityManager.addComponent(buildingEntity, std::make_shared<OwnerComponent>(player));
tileGameplayComponent->buildingEntityID = buildingEntity;
const EntityID buildingEntity = BuildingFactory::create(entityManager, def, *transform, entityID, player);
gameplay->buildingEntityID = buildingEntity;
break;
}
}
};