Streamlined library and reworked the way runtime components work

This commit is contained in:
2020-05-12 02:06:10 +02:00
parent c794e4a5d2
commit de5af0a5aa
11 changed files with 424 additions and 359 deletions

View File

@@ -9,8 +9,7 @@
namespace ecs::lua {
struct Wrapper : Component {
// @todo Figure out a more elegant way
Wrapper(sol::table _table) : Component(ComponentID::id<Wrapper>), table(_table) {}
Wrapper() : Component(ComponentID::id<Wrapper>) {}
Wrapper() {}
sol::table table;
};

View File

@@ -2,6 +2,10 @@
#include "ecs.h"
#ifdef _OPTIONAL_ECS_SERIAL
#include "ecs-serial.h"
#endif
namespace sol {
template<>
struct is_container<ecs::View<>> : std::true_type {};
@@ -14,35 +18,159 @@ namespace ecs::lua {
preload["ecs"] = [&lua] {
sol::table ecs = lua.create_table();
ecs.set_function("register", [&lua] (std::string name, sol::table table) {
size_t id = ComponentID::regist(name);
std::unordered_map<std::string, sol::type> map;
for (auto [skey, stype] : table) {
std::string key = skey.as<std::string>();
std::string type = stype.as<std::string>();
if (!type.compare("string")) {
map.insert({key, sol::type::string});
} else if (!type.compare("number")) {
map.insert({key, sol::type::number});
} else if (!type.compare("boolean")) {
map.insert({key, sol::type::boolean});
}
}
#ifdef _OPTIONAL_ECS_SERIAL
auto serialize = [map, name] (std::ostream& os, ecs::Component* component) {
std::cout << "SERIALIZE: " << name << '\n';
Wrapper* wrapper = (Wrapper*)component;
// Write each of the entries
io::write<size_t>(os, map.size());
for (auto [key, type] : map) {
io::write<std::string>(os, key);
switch (type) {
case sol::type::string:
io::write<std::string>(os, wrapper->table.get<std::string>(key));
break;
case sol::type::number:
io::write<float>(os, wrapper->table.get<float>(key));
break;
case sol::type::boolean:
io::write<bool>(os, wrapper->table.get<bool>(key));
break;
default:
break;
}
}
};
auto deserialize = [map] (std::istream& is, Component* component) {
std::cout << "DESERIALIZE\n";
Wrapper* wrapper = (Wrapper*)component;
// Write each of the entries
size_t size = io::read<size_t>(is);
for (size_t i = 0; i < size; ++i) {
std::string key = io::read<std::string>(is);
const auto it = map.find(key);
sol::type type = it->second;
std::cout << key << '\n';
switch (type) {
case sol::type::string:
std::cout << "STRING\n";
wrapper->table[key] = io::read<std::string>(is);
break;
case sol::type::number:
std::cout << "NUMBER\n";
wrapper->table[key] = io::read<float>(is);
break;
case sol::type::boolean:
std::cout << "BOOL\n";
wrapper->table[key] = io::read<bool>(is);
break;
default:
break;
}
}
};
auto create = [&lua, map] {
std::cout << "CREATE\n";
Wrapper* wrapper = new Wrapper();
wrapper->table = lua.create_table();
for (auto [key, type] : map) {
switch (type) {
case sol::type::string:
wrapper->table[key] = "";
break;
case sol::type::number:
wrapper->table[key] = 0;
break;
case sol::type::boolean:
wrapper->table[key] = true;
break;
default:
break;
}
}
return wrapper;
};
ecs::serial::register_component_custom(id, serialize, deserialize, create);
#endif
lua.set_function("_internal_to_" + name, [] (ecs::Component* component) {
return (Wrapper*)component;
});
sol::table component = lua.create_table();
component.set_function("new", sol::factories([&lua, id, map] (sol::table table) {
Wrapper* wrapper = new Wrapper();
wrapper->table = lua.create_table();
for (auto [key, type] : map) {
wrapper->table[key] = table[key];
}
return std::make_pair(id, wrapper);
}));
return component;
});
ecs.new_usertype<Entity>("Entity",
"__tostring", [] (Entity* thiz) {
return uuids::to_string(thiz->uuid);
},
"add_component", [] (Entity* thiz, Component* component, std::string name) {
return thiz->add_component(ComponentID::get_id({name})[0], component);
"add_component", [] (Entity* thiz, size_t id, Component* component) {
return thiz->add_component(id, component);
},
"has_components", [] (Entity* thiz, sol::variadic_args args) {
std::vector<std::string> names;
for (std::string name : args) {
names.push_back(name);
}
return thiz->has_components(ComponentID::get_id(names));
return thiz->has_components(ComponentID::resolve(names));
},
"get_component", [&lua] (Entity* thiz, std::string name) -> sol::object {
// Convert to the correct component type
Component* component = thiz->get_component(ComponentID::get_id({name})[0]);
if (!component->_runtime) {
// @todo Figure out a more elegant way to convert
auto f1 = lua["_internal_to_" + name];
if (f1.valid()) {
return f1(component);
}
} else {
// @todo This call is not very fast...
auto f1 = lua["_internal_to_" + ComponentID::get_name(component->_id)];
if (f1.valid()) {
return f1(component);
}
Component* component = thiz->get_component(ComponentID::resolve(name));
// @todo Figure out a more elegant way to convert
auto f1 = lua["_internal_to_" + name];
if (f1.valid()) {
return f1(component);
}
throw std::runtime_error("Unknown component");
}
@@ -71,7 +199,7 @@ namespace ecs::lua {
for (std::string name : args) {
names.push_back(name);
}
return thiz->view(ComponentID::get_id(names));
return thiz->view(ComponentID::resolve(names));
}
);
@@ -79,8 +207,7 @@ namespace ecs::lua {
};
preload["ecs.Wrapper"] = [&lua] {
sol::table component = lua.create_table();
component.new_usertype<Wrapper>("Wrapper",
lua.new_usertype<Wrapper>("Wrapper",
"__index", [] (Wrapper* thiz, std::string key) {
return thiz->table[key];
},
@@ -89,16 +216,6 @@ namespace ecs::lua {
},
sol::base_classes, sol::bases<ecs::Component>()
);
component.set_function("new", sol::factories([](std::string _name, sol::table _table) {
return std::make_pair(new Wrapper(_table), _name);
}));
lua.set_function("_internal_to_Wrapper", [] (ecs::Component* component) {
return (Wrapper*)component;
});
return component;
};
}
}