.clang-format

This commit is contained in:
NukeBird 2025-02-13 19:47:52 +03:00
parent 432673fa0e
commit d89827046a
6 changed files with 295 additions and 237 deletions

4
.clang-format Normal file
View file

@ -0,0 +1,4 @@
BasedOnStyle: LLVM
BreakBeforeBraces: Allman
AccessModifierOffset: -4
IndentWidth: 4

68
dbc.cpp
View file

@ -1,44 +1,54 @@
#include "dbc.hpp" #include "dbc.hpp"
#include <iostream> #include <iostream>
void dbc::log(const string &message) { void dbc::log(const string &message)
std::cerr << "!!!!!!!!!!" << message << std::endl; {
std::cerr << "!!!!!!!!!!" << message << std::endl;
} }
void dbc::sentinel(const string &message) { void dbc::sentinel(const string &message)
string err = fmt::format("[SENTINEL!] {}", message); {
dbc::log(err); string err = fmt::format("[SENTINEL!] {}", message);
throw dbc::SentinelError{err};
}
void dbc::pre(const string &message, bool test) {
if(!test) {
string err = fmt::format("[PRE!] {}", message);
dbc::log(err); dbc::log(err);
throw dbc::PreCondError{err}; throw dbc::SentinelError{err};
}
} }
void dbc::pre(const string &message, std::function<bool()> tester) { void dbc::pre(const string &message, bool test)
dbc::pre(message, tester()); {
if (!test)
{
string err = fmt::format("[PRE!] {}", message);
dbc::log(err);
throw dbc::PreCondError{err};
}
} }
void dbc::post(const string &message, bool test) { void dbc::pre(const string &message, std::function<bool()> tester)
if(!test) { {
string err = fmt::format("[POST!] {}", message); dbc::pre(message, tester());
dbc::log(err);
throw dbc::PostCondError{err};
}
} }
void dbc::post(const string &message, std::function<bool()> tester) { void dbc::post(const string &message, bool test)
dbc::post(message, tester()); {
if (!test)
{
string err = fmt::format("[POST!] {}", message);
dbc::log(err);
throw dbc::PostCondError{err};
}
} }
void dbc::check(bool test, const string &message) { void dbc::post(const string &message, std::function<bool()> tester)
if(!test) { {
string err = fmt::format("[CHECK!] {}\n", message); dbc::post(message, tester());
dbc::log(err); }
throw dbc::CheckError{err};
} void dbc::check(bool test, const string &message)
{
if (!test)
{
string err = fmt::format("[CHECK!] {}\n", message);
dbc::log(err);
throw dbc::CheckError{err};
}
} }

50
dbc.hpp
View file

@ -1,29 +1,39 @@
#pragma once #pragma once
#include <string>
#include <fmt/core.h> #include <fmt/core.h>
#include <functional> #include <functional>
#include <string>
using std::string; using std::string;
namespace dbc { namespace dbc
class Error { {
public: class Error
const string message; {
Error(string m) : message{m} {} public:
Error(const char *m) : message{m} {} const string message;
}; Error(string m) : message{m} {}
Error(const char *m) : message{m} {}
};
class CheckError : public Error {}; class CheckError : public Error
class SentinelError : public Error {}; {
class PreCondError : public Error {}; };
class PostCondError : public Error {}; class SentinelError : public Error
{
};
class PreCondError : public Error
{
};
class PostCondError : public Error
{
};
void log(const string &message); void log(const string &message);
void sentinel(const string &message); void sentinel(const string &message);
void pre(const string &message, bool test); void pre(const string &message, bool test);
void pre(const string &message, std::function<bool()> tester); void pre(const string &message, std::function<bool()> tester);
void post(const string &message, bool test); void post(const string &message, bool test);
void post(const string &message, std::function<bool()> tester); void post(const string &message, std::function<bool()> tester);
void check(bool test, const string &message); void check(bool test, const string &message);
} } // namespace dbc

View file

@ -1,156 +1,169 @@
#pragma once #pragma once
#include "dbc.hpp"
#include <any>
#include <functional> #include <functional>
#include <queue>
#include <tuple>
#include <typeindex> #include <typeindex>
#include <typeinfo> #include <typeinfo>
#include <unordered_map> #include <unordered_map>
#include <any>
#include <tuple>
#include <queue>
#include "dbc.hpp"
namespace DinkyECS { namespace DinkyECS
typedef unsigned long Entity; {
typedef unsigned long Entity;
using EntityMap = std::unordered_map<Entity, std::any>; using EntityMap = std::unordered_map<Entity, std::any>;
struct Event { struct Event
{
int event = 0; int event = 0;
Entity entity = 0; Entity entity = 0;
std::any data; std::any data;
}; };
typedef std::queue<Event> EventQueue; typedef std::queue<Event> EventQueue;
struct World { struct World
{
unsigned long entity_count = 0; unsigned long entity_count = 0;
std::unordered_map<std::type_index, EntityMap> $components; std::unordered_map<std::type_index, EntityMap> $components;
std::unordered_map<std::type_index, std::any> $facts; std::unordered_map<std::type_index, std::any> $facts;
std::unordered_map<std::type_index, EventQueue> $events; std::unordered_map<std::type_index, EventQueue> $events;
std::vector<Entity> $constants; std::vector<Entity> $constants;
Entity entity() { Entity entity() { return ++entity_count; }
return ++entity_count;
}
void clone_into(DinkyECS::World &to_world) { void clone_into(DinkyECS::World &to_world)
to_world.$constants = $constants; {
to_world.$facts = $facts; to_world.$constants = $constants;
to_world.entity_count = entity_count; to_world.$facts = $facts;
to_world.entity_count = entity_count;
for(auto eid : $constants) { for (auto eid : $constants)
for(const auto &[tid, eid_map] : $components) { {
auto& their_map = to_world.$components[tid]; for (const auto &[tid, eid_map] : $components)
if(eid_map.contains(eid)) { {
their_map.insert_or_assign(eid, eid_map.at(eid)); auto &their_map = to_world.$components[tid];
} if (eid_map.contains(eid))
{
their_map.insert_or_assign(eid, eid_map.at(eid));
}
}
} }
}
} }
void make_constant(DinkyECS::Entity entity) { void make_constant(DinkyECS::Entity entity)
{
$constants.push_back(entity); $constants.push_back(entity);
} }
template <typename Comp> template <typename Comp> EntityMap &entity_map_for()
EntityMap& entity_map_for() { {
return $components[std::type_index(typeid(Comp))]; return $components[std::type_index(typeid(Comp))];
} }
template <typename Comp> template <typename Comp> EventQueue &queue_map_for()
EventQueue& queue_map_for() { {
return $events[std::type_index(typeid(Comp))]; return $events[std::type_index(typeid(Comp))];
} }
template <typename Comp> template <typename Comp> void remove(Entity ent)
void remove(Entity ent) { {
EntityMap &map = entity_map_for<Comp>(); EntityMap &map = entity_map_for<Comp>();
map.erase(ent); map.erase(ent);
} }
template <typename Comp> template <typename Comp> void set_the(Comp val)
void set_the(Comp val) { {
$facts.insert_or_assign(std::type_index(typeid(Comp)), val); $facts.insert_or_assign(std::type_index(typeid(Comp)), val);
} }
template <typename Comp> template <typename Comp> Comp &get_the()
Comp &get_the() { {
auto comp_id = std::type_index(typeid(Comp)); auto comp_id = std::type_index(typeid(Comp));
dbc::check($facts.contains(comp_id), dbc::check($facts.contains(comp_id),
fmt::format("!!!! ATTEMPT to access world fact that hasn't been set yet: {}", typeid(Comp).name())); fmt::format("!!!! ATTEMPT to access world fact that hasn't "
"been set yet: {}",
typeid(Comp).name()));
// use .at to get std::out_of_range if fact not set // use .at to get std::out_of_range if fact not set
std::any &res = $facts.at(comp_id); std::any &res = $facts.at(comp_id);
return std::any_cast<Comp&>(res); return std::any_cast<Comp &>(res);
} }
template <typename Comp> template <typename Comp> bool has_the()
bool has_the() { {
auto comp_id = std::type_index(typeid(Comp)); auto comp_id = std::type_index(typeid(Comp));
return $facts.contains(comp_id); return $facts.contains(comp_id);
} }
template <typename Comp> template <typename Comp> void set(Entity ent, Comp val)
void set(Entity ent, Comp val) { {
EntityMap &map = entity_map_for<Comp>(); EntityMap &map = entity_map_for<Comp>();
map.insert_or_assign(ent, val); map.insert_or_assign(ent, val);
} }
template <typename Comp> template <typename Comp> Comp &get(Entity ent)
Comp &get(Entity ent) { {
EntityMap &map = entity_map_for<Comp>(); EntityMap &map = entity_map_for<Comp>();
// use .at for bounds checking // use .at for bounds checking
std::any &res = map.at(ent); std::any &res = map.at(ent);
return std::any_cast<Comp&>(res); return std::any_cast<Comp &>(res);
} }
template <typename Comp> template <typename Comp> bool has(Entity ent)
bool has(Entity ent) { {
EntityMap &map = entity_map_for<Comp>(); EntityMap &map = entity_map_for<Comp>();
return map.contains(ent); return map.contains(ent);
} }
template<typename Comp> template <typename Comp>
void query(std::function<void(const Entity&, Comp&)> cb) { void query(std::function<void(const Entity &, Comp &)> cb)
{
EntityMap &map = entity_map_for<Comp>(); EntityMap &map = entity_map_for<Comp>();
for(auto& [entity, any_comp] : map) { for (auto &[entity, any_comp] : map)
Comp &res = std::any_cast<Comp&>(any_comp); {
cb(entity, res); Comp &res = std::any_cast<Comp &>(any_comp);
cb(entity, res);
} }
} }
template<typename CompA, typename CompB> template <typename CompA, typename CompB>
void query(std::function<void(const Entity&, CompA&, CompB&)> cb) { void query(std::function<void(const Entity &, CompA &, CompB &)> cb)
{
EntityMap &map_a = entity_map_for<CompA>(); EntityMap &map_a = entity_map_for<CompA>();
EntityMap &map_b = entity_map_for<CompB>(); EntityMap &map_b = entity_map_for<CompB>();
for(auto& [entity, any_a] : map_a) { for (auto &[entity, any_a] : map_a)
if(map_b.contains(entity)) { {
CompA &res_a = std::any_cast<CompA&>(any_a); if (map_b.contains(entity))
CompB &res_b = get<CompB>(entity); {
cb(entity, res_a, res_b); CompA &res_a = std::any_cast<CompA &>(any_a);
} CompB &res_b = get<CompB>(entity);
cb(entity, res_a, res_b);
}
} }
} }
template<typename Comp> template <typename Comp> void send(Comp event, Entity entity, std::any data)
void send(Comp event, Entity entity, std::any data) { {
EventQueue &queue = queue_map_for<Comp>(); EventQueue &queue = queue_map_for<Comp>();
queue.push({event, entity, data}); queue.push({event, entity, data});
} }
template<typename Comp> template <typename Comp> Event recv()
Event recv() { {
EventQueue &queue = queue_map_for<Comp>(); EventQueue &queue = queue_map_for<Comp>();
Event evt = queue.front(); Event evt = queue.front();
queue.pop(); queue.pop();
return evt; return evt;
} }
template<typename Comp> template <typename Comp> bool has_event()
bool has_event() { {
EventQueue &queue = queue_map_for<Comp>(); EventQueue &queue = queue_map_for<Comp>();
return !queue.empty(); return !queue.empty();
} }
}; };
} } // namespace DinkyECS

204
main.cpp
View file

@ -10,137 +10,155 @@ using namespace fmt;
using DinkyECS::Entity; using DinkyECS::Entity;
using std::string; using std::string;
struct Player { struct Player
string name; {
Entity eid; string name;
Entity eid;
}; };
struct Position { struct Position
Point location; {
Point location;
}; };
// DINKY_HAS_COMPONENT(Point, x, y); // DINKY_HAS_COMPONENT(Point, x, y);
// DINKY_HAS_COMPONENT(Position, location); // DINKY_HAS_COMPONENT(Position, location);
struct Motion { struct Motion
int dx; {
int dy; int dx;
bool random=false; int dy;
bool random = false;
}; };
// DINKY_HAS_COMPONENT(Motion, dx, dy, random); // DINKY_HAS_COMPONENT(Motion, dx, dy, random);
struct Velocity { struct Velocity
double x, y; {
double x, y;
}; };
// DINKY_HAS_COMPONENT(Velocity, x, y); // DINKY_HAS_COMPONENT(Velocity, x, y);
struct Gravity { struct Gravity
double level; {
double level;
}; };
// DINKY_HAS_COMPONENT(Gravity, level); // DINKY_HAS_COMPONENT(Gravity, level);
struct DaGUI { struct DaGUI
int event; {
int event;
}; };
void configure(DinkyECS::World &world, Entity &test) { void configure(DinkyECS::World &world, Entity &test)
println("---Configuring the base system."); {
Entity test2 = world.entity(); println("---Configuring the base system.");
Entity test2 = world.entity();
world.set<Position>(test, {10,20}); world.set<Position>(test, {10, 20});
world.set<Velocity>(test, {1,2}); world.set<Velocity>(test, {1, 2});
world.set<Position>(test2, {1,1}); world.set<Position>(test2, {1, 1});
world.set<Velocity>(test2, {9,19}); world.set<Velocity>(test2, {9, 19});
println("---- Setting up the player as a fact in the system."); println("---- Setting up the player as a fact in the system.");
auto player_eid = world.entity(); auto player_eid = world.entity();
Player player_info{"Zed", player_eid}; Player player_info{"Zed", player_eid};
// just set some player info as a fact with the entity id // just set some player info as a fact with the entity id
world.set_the<Player>(player_info); world.set_the<Player>(player_info);
world.set<Velocity>(player_eid, {0,0}); world.set<Velocity>(player_eid, {0, 0});
world.set<Position>(player_eid, {0,0}); world.set<Position>(player_eid, {0, 0});
auto enemy = world.entity(); auto enemy = world.entity();
world.set<Velocity>(enemy, {0,0}); world.set<Velocity>(enemy, {0, 0});
world.set<Position>(enemy, {0,0}); world.set<Position>(enemy, {0, 0});
println("--- Creating facts (singletons)"); println("--- Creating facts (singletons)");
world.set_the<Gravity>({0.9}); world.set_the<Gravity>({0.9});
} }
int main() { int main()
DinkyECS::World world; {
Entity test = world.entity(); DinkyECS::World world;
Entity test = world.entity();
configure(world, test); configure(world, test);
Position &pos = world.get<Position>(test); Position &pos = world.get<Position>(test);
REQUIRE(pos.location.x == 10); REQUIRE(pos.location.x == 10);
REQUIRE(pos.location.y == 20); REQUIRE(pos.location.y == 20);
Velocity &vel = world.get<Velocity>(test); Velocity &vel = world.get<Velocity>(test);
REQUIRE(vel.x == 1); REQUIRE(vel.x == 1);
REQUIRE(vel.y == 2); REQUIRE(vel.y == 2);
world.query<Position>([](const auto &ent, auto &pos) { world.query<Position>(
REQUIRE(ent > 0); [](const auto &ent, auto &pos)
REQUIRE(pos.location.x >= 0); {
REQUIRE(pos.location.y >= 0); REQUIRE(ent > 0);
}); REQUIRE(pos.location.x >= 0);
REQUIRE(pos.location.y >= 0);
});
world.query<Velocity>([](const auto &ent, auto &vel) { world.query<Velocity>(
REQUIRE(ent > 0); [](const auto &ent, auto &vel)
REQUIRE(vel.x >= 0); {
REQUIRE(vel.y >= 0); REQUIRE(ent > 0);
}); REQUIRE(vel.x >= 0);
REQUIRE(vel.y >= 0);
});
println("--- Manually get the velocity in position system:"); println("--- Manually get the velocity in position system:");
world.query<Position>([&](const auto &ent, auto &pos) { world.query<Position>(
Velocity &vel = world.get<Velocity>(ent); [&](const auto &ent, auto &pos)
{
Velocity &vel = world.get<Velocity>(ent);
REQUIRE(ent > 0); REQUIRE(ent > 0);
REQUIRE(pos.location.x >= 0); REQUIRE(pos.location.x >= 0);
REQUIRE(pos.location.y >= 0); REQUIRE(pos.location.y >= 0);
REQUIRE(ent > 0); REQUIRE(ent > 0);
REQUIRE(vel.x >= 0); REQUIRE(vel.x >= 0);
REQUIRE(vel.y >= 0); REQUIRE(vel.y >= 0);
}); });
println("--- Query only entities with Position and Velocity:"); println("--- Query only entities with Position and Velocity:");
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) { world.query<Position, Velocity>(
Gravity &grav = world.get_the<Gravity>(); [&](const auto &ent, auto &pos, auto &vel)
REQUIRE(grav.level <= 1.0f); {
REQUIRE(grav.level > 0.5f); Gravity &grav = world.get_the<Gravity>();
REQUIRE(ent > 0); REQUIRE(grav.level <= 1.0f);
REQUIRE(pos.location.x >= 0); REQUIRE(grav.level > 0.5f);
REQUIRE(pos.location.y >= 0); REQUIRE(ent > 0);
REQUIRE(ent > 0); REQUIRE(pos.location.x >= 0);
REQUIRE(vel.x >= 0); REQUIRE(pos.location.y >= 0);
REQUIRE(vel.y >= 0); REQUIRE(ent > 0);
}); REQUIRE(vel.x >= 0);
REQUIRE(vel.y >= 0);
});
// now remove Velocity // now remove Velocity
REQUIRE(world.has<Velocity>(test)); REQUIRE(world.has<Velocity>(test));
world.remove<Velocity>(test); world.remove<Velocity>(test);
//REQUIRE_THROWS(world.get<Velocity>(test)); // REQUIRE_THROWS(world.get<Velocity>(test));
REQUIRE(!world.has<Velocity>(test)); REQUIRE(!world.has<Velocity>(test));
println("--- After remove test, should only result in test2:"); println("--- After remove test, should only result in test2:");
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) { world.query<Position, Velocity>(
auto &in_position = world.get<Position>(ent); [&](const auto &ent, auto &pos, auto &vel)
auto &in_velocity = world.get<Velocity>(ent); {
REQUIRE(pos.location.x >= 0); auto &in_position = world.get<Position>(ent);
REQUIRE(pos.location.y >= 0); auto &in_velocity = world.get<Velocity>(ent);
REQUIRE(in_position.location.x == pos.location.x); REQUIRE(pos.location.x >= 0);
REQUIRE(in_position.location.y == pos.location.y); REQUIRE(pos.location.y >= 0);
REQUIRE(in_velocity.x == vel.x); REQUIRE(in_position.location.x == pos.location.x);
REQUIRE(in_velocity.y == vel.y); REQUIRE(in_position.location.y == pos.location.y);
}); REQUIRE(in_velocity.x == vel.x);
return 0; REQUIRE(in_velocity.y == vel.y);
});
return 0;
} }

View file

@ -1,21 +1,24 @@
#pragma once #pragma once
#include <vector> #include <vector>
struct Point { struct Point
size_t x = 0; {
size_t y = 0; size_t x = 0;
size_t y = 0;
bool operator==(const Point& other) const { bool operator==(const Point &other) const
return other.x == x && other.y == y; {
} return other.x == x && other.y == y;
}
}; };
typedef std::vector<Point> PointList; typedef std::vector<Point> PointList;
template<> struct std::hash<Point> { template <> struct std::hash<Point>
size_t operator()(const Point& p) const { {
auto hasher = std::hash<int>(); size_t operator()(const Point &p) const
return hasher(p.x) ^ hasher(p.y); {
} auto hasher = std::hash<int>();
return hasher(p.x) ^ hasher(p.y);
}
}; };