feat(entities): andamiatge del sistema d'entitats (classes, factory, bus, YAML, placeholders, smoke tests)
This commit is contained in:
1 parent
984cc820c0
commit
96b71b0f65
48 files changed
+1957
No files matched your search
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
// Forward: els events poden dur un punter a `Entity` (p. ex. quin sarcòfag
|
||||
// s'ha obert). No cal incloure el header complet aquí.
|
||||
class Entity;
|
||||
|
||||
// Event pub/sub minimalista. Hi ha un únic `EventBus` per mundus (propietat
|
||||
// de l'`EntityManager`); les entitats que el necessiten en reben un punter
|
||||
// via `Entity::setEventBus`. Aquest sistema cobreix les necessitats
|
||||
// actuals (sarcophagus_opened, level_complete, player_hit) sense portar-hi
|
||||
// senyalització més pesada.
|
||||
//
|
||||
// Decisió: `std::variant` per al payload — evita any/void* i facilita
|
||||
// consumir events tipats amb `std::get_if`. Si apareixen més tipus de
|
||||
// payload, s'amplia aquí sense tocar cridants existents.
|
||||
struct Event {
|
||||
std::string name;
|
||||
using Payload = std::variant<std::monostate, int, std::string, Entity*>;
|
||||
Payload payload;
|
||||
};
|
||||
|
||||
class EventBus {
|
||||
public:
|
||||
using Handler = std::function<void(const Event&)>;
|
||||
using SubId = std::size_t;
|
||||
|
||||
EventBus() = default;
|
||||
EventBus(const EventBus&) = delete;
|
||||
EventBus(EventBus&&) = delete;
|
||||
auto operator=(const EventBus&) -> EventBus& = delete;
|
||||
auto operator=(EventBus&&) -> EventBus& = delete;
|
||||
~EventBus() = default;
|
||||
|
||||
// Retorna un identificador únic per poder-se donar de baixa amb
|
||||
// `unsubscribe`. Els identificadors s'assignen globalment i no es
|
||||
// reutilitzen fins a overflow (acceptable per a la vida d'un nivell).
|
||||
auto subscribe(const std::string& name, Handler handler) -> SubId;
|
||||
void unsubscribe(SubId id);
|
||||
|
||||
// Publica a tots els subscriptors registrats per al nom. Si no n'hi ha
|
||||
// cap, no fa res.
|
||||
void publish(const Event& event);
|
||||
|
||||
// Forma ergonòmica: construeix un Event amb nom + payload opcional.
|
||||
void publish(const std::string& name) {
|
||||
publish(Event{.name = name, .payload = std::monostate{}});
|
||||
}
|
||||
void publish(const std::string& name, Entity* entity) {
|
||||
publish(Event{.name = name, .payload = entity});
|
||||
}
|
||||
void publish(const std::string& name, int value) {
|
||||
publish(Event{.name = name, .payload = value});
|
||||
}
|
||||
|
||||
private:
|
||||
struct Subscription {
|
||||
SubId id;
|
||||
Handler handler;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::vector<Subscription>> subs_;
|
||||
std::uint64_t next_id_{1};
|
||||
};
|
||||
Reference in new issue
Block a user