feat: loading entities (WIP)
This commit is contained in:
parent
08cc78289d
commit
c8666910ce
@ -6,15 +6,21 @@ inair = true
|
||||
ready = false
|
||||
target = -1
|
||||
|
||||
local dropitem = ARGS.item
|
||||
ARGS = ARGS or {}
|
||||
local dropitem = ARGS.item or {}
|
||||
if SAVED_DATA.item then
|
||||
dropitem.id = item.index(SAVED_DATA.item)
|
||||
dropitem.count = SAVED_DATA.count
|
||||
end
|
||||
|
||||
local scale = {1, 1, 1}
|
||||
local rotation = mat4.rotate({
|
||||
math.random(), math.random(), math.random()
|
||||
}, 360)
|
||||
|
||||
function on_save()
|
||||
SAVED_DATA.test = 5
|
||||
print("SAVE ENTITY")
|
||||
SAVED_DATA.item = item.name(dropitem.id)
|
||||
SAVED_DATA.count = dropitem.count
|
||||
end
|
||||
|
||||
do -- setup visuals
|
||||
|
||||
@ -144,7 +144,7 @@ void ContentLoader::loadBlock(Block& def, const std::string& name, const fs::pat
|
||||
else if (model == "custom") {
|
||||
def.model = BlockModel::custom;
|
||||
if (root->has("model-primitives")) {
|
||||
loadCustomBlockModel(def, root->map("model-primitives"));
|
||||
loadCustomBlockModel(def, root->map("model-primitives").get());
|
||||
} else {
|
||||
logger.error() << name << ": no 'model-primitives' found";
|
||||
}
|
||||
|
||||
@ -55,9 +55,9 @@ integer_t List::integer(size_t index) const {
|
||||
}
|
||||
}
|
||||
|
||||
Map* List::map(size_t index) const {
|
||||
const Map_sptr& List::map(size_t index) const {
|
||||
if (auto* val = std::get_if<Map_sptr>(&values[index])) {
|
||||
return val->get();
|
||||
return *val;
|
||||
} else {
|
||||
throw std::runtime_error("type error");
|
||||
}
|
||||
@ -192,11 +192,11 @@ void Map::num(const std::string& key, uint& dst) const {
|
||||
dst = get(key, static_cast<integer_t>(dst));
|
||||
}
|
||||
|
||||
Map* Map::map(const std::string& key) const {
|
||||
Map_sptr Map::map(const std::string& key) const {
|
||||
auto found = values.find(key);
|
||||
if (found != values.end()) {
|
||||
if (auto* val = std::get_if<Map_sptr>(&found->second)) {
|
||||
return val->get();
|
||||
return *val;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@ -47,7 +47,7 @@ namespace dynamic {
|
||||
std::string str(size_t index) const;
|
||||
number_t num(size_t index) const;
|
||||
integer_t integer(size_t index) const;
|
||||
Map* map(size_t index) const;
|
||||
const Map_sptr& map(size_t index) const;
|
||||
List* list(size_t index) const;
|
||||
bool flag(size_t index) const;
|
||||
|
||||
@ -114,7 +114,7 @@ namespace dynamic {
|
||||
void num(const std::string& key, uint64_t& dst) const;
|
||||
void num(const std::string& key, ubyte& dst) const;
|
||||
void num(const std::string& key, double& dst) const;
|
||||
Map* map(const std::string& key) const;
|
||||
Map_sptr map(const std::string& key) const;
|
||||
List* list(const std::string& key) const;
|
||||
void flag(const std::string& key, bool& dst) const;
|
||||
|
||||
|
||||
@ -25,6 +25,15 @@ namespace dynamic {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template<int n>
|
||||
void get_vec(const dynamic::Map_sptr& root, const std::string& name, glm::vec<n, float>& vec) {
|
||||
if (const auto& list = root->list(name)) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
vec[i] = list->num(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DATA_DYNAMIC_UTIL_HPP_
|
||||
|
||||
@ -435,6 +435,15 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) {
|
||||
return meta;
|
||||
}
|
||||
|
||||
dynamic::Map_sptr WorldRegions::fetchEntities(int x, int z) {
|
||||
uint32_t bytesSize;
|
||||
const ubyte* data = getData(x, z, REGION_LAYER_ENTITIES, bytesSize);
|
||||
if (data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return json::from_binary(data, bytesSize);
|
||||
}
|
||||
|
||||
void WorldRegions::processRegionVoxels(int x, int z, const regionproc& func) {
|
||||
if (getRegion(x, z, REGION_LAYER_VOXELS)) {
|
||||
throw std::runtime_error("not implemented for in-memory regions");
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "../typedefs.hpp"
|
||||
#include "../util/BufferPool.hpp"
|
||||
#include "../voxels/Chunk.hpp"
|
||||
#include "../data/dynamic_fwd.hpp"
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
@ -185,6 +186,7 @@ public:
|
||||
std::unique_ptr<ubyte[]> getChunk(int x, int z);
|
||||
std::unique_ptr<light_t[]> getLights(int x, int z);
|
||||
chunk_inventories_map fetchInventories(int x, int z);
|
||||
dynamic::Map_sptr fetchEntities(int x, int z);
|
||||
|
||||
void processRegionVoxels(int x, int z, const regionproc& func);
|
||||
|
||||
|
||||
@ -37,7 +37,10 @@ static int l_spawn(lua::State* L) {
|
||||
if (lua::gettop(L) > 2) {
|
||||
args = lua::tovalue(L, 3);
|
||||
}
|
||||
level->entities->spawn(scripting::engine->getAssets(), def, pos, args);
|
||||
Transform transform {
|
||||
pos, glm::vec3(1.0f), glm::mat3(1.0f), {}, true
|
||||
};
|
||||
level->entities->spawn(scripting::engine->getAssets(), def, transform, args);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -276,7 +276,8 @@ void scripting::on_entity_spawn(
|
||||
const EntityDef& def,
|
||||
entityid_t eid,
|
||||
const std::vector<std::unique_ptr<UserComponent>>& components,
|
||||
dynamic::Value args
|
||||
dynamic::Value args,
|
||||
dynamic::Map_sptr saved
|
||||
) {
|
||||
auto L = lua::get_main_thread();
|
||||
lua::requireglobal(L, STDCOMP);
|
||||
@ -296,7 +297,15 @@ void scripting::on_entity_spawn(
|
||||
lua::pushvalue(L, args);
|
||||
lua::setfield(L, "ARGS");
|
||||
|
||||
lua::createtable(L, 0, 0);
|
||||
if (saved == nullptr) {
|
||||
lua::createtable(L, 0, 0);
|
||||
} else {
|
||||
if (auto datamap = saved->map(component->name)) {
|
||||
lua::pushvalue(L, datamap);
|
||||
} else {
|
||||
lua::createtable(L, 0, 0);
|
||||
}
|
||||
}
|
||||
lua::setfield(L, "SAVED_DATA");
|
||||
|
||||
lua::setfenv(L);
|
||||
|
||||
@ -81,7 +81,8 @@ namespace scripting {
|
||||
const EntityDef& def,
|
||||
entityid_t eid,
|
||||
const std::vector<std::unique_ptr<UserComponent>>& components,
|
||||
dynamic::Value args
|
||||
dynamic::Value args,
|
||||
dynamic::Map_sptr saved
|
||||
);
|
||||
bool on_entity_despawn(const EntityDef& def, const Entity& entity);
|
||||
bool on_entity_grounded(const Entity& entity, float force);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
#include "Entities.hpp"
|
||||
|
||||
#include "../debug/Logger.hpp"
|
||||
#include "../data/dynamic_util.hpp"
|
||||
#include "../assets/Assets.hpp"
|
||||
#include "../world/Level.hpp"
|
||||
#include "../content/Content.hpp"
|
||||
#include "../physics/Hitbox.hpp"
|
||||
#include "../physics/PhysicsSolver.hpp"
|
||||
#include "../graphics/render/ModelBatch.hpp"
|
||||
@ -12,9 +14,12 @@
|
||||
#include "../objects/EntityDef.hpp"
|
||||
#include "../objects/rigging.hpp"
|
||||
#include "../logic/scripting/scripting.hpp"
|
||||
#include "../engine.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
|
||||
static debug::Logger logger("entities");
|
||||
|
||||
void Transform::refresh() {
|
||||
combined = glm::mat4(1.0f);
|
||||
combined = glm::translate(combined, pos);
|
||||
@ -57,20 +62,26 @@ static triggercallback create_trigger_callback(Entities* entities) {
|
||||
entityid_t Entities::spawn(
|
||||
Assets* assets,
|
||||
EntityDef& def,
|
||||
glm::vec3 pos,
|
||||
dynamic::Value args)
|
||||
Transform transform,
|
||||
dynamic::Value args,
|
||||
dynamic::Map_sptr saved,
|
||||
entityid_t uid)
|
||||
{
|
||||
auto rig = assets->get<rigging::RigConfig>(def.rigName);
|
||||
if (rig == nullptr) {
|
||||
throw std::runtime_error("rig "+def.rigName+" not found");
|
||||
}
|
||||
auto entity = registry.create();
|
||||
glm::vec3 size(1);
|
||||
auto id = nextID++;
|
||||
entityid_t id;
|
||||
if (uid == 0) {
|
||||
id = nextID++;
|
||||
} else {
|
||||
id = uid;
|
||||
}
|
||||
registry.emplace<EntityId>(entity, static_cast<entityid_t>(id), def);
|
||||
registry.emplace<Transform>(entity, pos, size, glm::mat3(1.0f));
|
||||
registry.emplace<Transform>(entity, transform);
|
||||
auto& body = registry.emplace<Rigidbody>(
|
||||
entity, true, Hitbox {pos, def.hitbox}, std::vector<Trigger>{});
|
||||
entity, true, Hitbox {transform.pos, def.hitbox}, std::vector<Trigger>{});
|
||||
|
||||
body.triggers.resize(def.radialTriggers.size() + def.boxTriggers.size());
|
||||
for (auto& [i, box] : def.boxTriggers) {
|
||||
@ -98,7 +109,8 @@ entityid_t Entities::spawn(
|
||||
componentName, entity_funcs_set {}, nullptr);
|
||||
scripting.components.emplace_back(std::move(component));
|
||||
}
|
||||
scripting::on_entity_spawn(def, id, scripting.components, std::move(args));
|
||||
scripting::on_entity_spawn(
|
||||
def, id, scripting.components, std::move(args), std::move(saved));
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -112,6 +124,37 @@ void Entities::despawn(entityid_t id) {
|
||||
}
|
||||
}
|
||||
|
||||
void Entities::loadEntity(const dynamic::Map_sptr& map) {
|
||||
entityid_t uid = 0;
|
||||
std::string defname;
|
||||
map->num("uid", uid);
|
||||
map->str("def", defname);
|
||||
if (uid == 0) {
|
||||
throw std::runtime_error("could not read entity - invalid UID");
|
||||
}
|
||||
auto& def = level->content->entities.require(defname);
|
||||
Transform transform {
|
||||
glm::vec3(), glm::vec3(1.0f), glm::mat3(1.0f), {}, true
|
||||
};
|
||||
if (auto tsfmap = map->map("transform")) {
|
||||
dynamic::get_vec(tsfmap, "pos", transform.pos);
|
||||
}
|
||||
dynamic::Map_sptr savedMap = map->map("comps");
|
||||
auto assets = scripting::engine->getAssets();
|
||||
spawn(assets, def, transform, dynamic::NONE, savedMap, uid);
|
||||
}
|
||||
|
||||
void Entities::loadEntities(dynamic::Map_sptr root) {
|
||||
auto list = root->list("data");
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
try {
|
||||
loadEntity(list->map(i));
|
||||
} catch (const std::runtime_error& err) {
|
||||
logger.error() << "could not read entity: " << err.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entities::onSave(const Entity& entity) {
|
||||
scripting::on_entity_save(entity);
|
||||
}
|
||||
@ -129,7 +172,9 @@ dynamic::Value Entities::serialize(const Entity& entity) {
|
||||
if (transform.size != glm::vec3(1.0f)) {
|
||||
tsfmap.put("size", dynamic::to_value(transform.size));
|
||||
}
|
||||
tsfmap.put("rot", dynamic::to_value(transform.rot));
|
||||
if (transform.rot != glm::mat3(1.0f)) {
|
||||
tsfmap.put("rot", dynamic::to_value(transform.rot));
|
||||
}
|
||||
}
|
||||
{
|
||||
auto& rigidbody = entity.getRigidbody();
|
||||
@ -166,6 +211,7 @@ dynamic::Value Entities::serialize(const Entity& entity) {
|
||||
auto data = scripting::get_component_value(comp->env, "SAVED_DATA");
|
||||
compsMap.put(comp->name, data);
|
||||
}
|
||||
std::cout << root << std::endl;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -172,8 +172,10 @@ public:
|
||||
entityid_t spawn(
|
||||
Assets* assets,
|
||||
EntityDef& def,
|
||||
glm::vec3 pos,
|
||||
dynamic::Value args=dynamic::NONE);
|
||||
Transform transform,
|
||||
dynamic::Value args=dynamic::NONE,
|
||||
dynamic::Map_sptr saved=nullptr,
|
||||
entityid_t uid=0);
|
||||
|
||||
std::optional<Entity> get(entityid_t id) {
|
||||
const auto& found = entities.find(id);
|
||||
@ -183,6 +185,8 @@ public:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void loadEntities(dynamic::Map_sptr map);
|
||||
void loadEntity(const dynamic::Map_sptr& map);
|
||||
void onSave(const Entity& entity);
|
||||
std::vector<Entity> getAllInside(AABB aabb);
|
||||
void despawn(entityid_t id);
|
||||
|
||||
@ -251,10 +251,9 @@ void Player::deserialize(dynamic::Map *src) {
|
||||
src->flag("flight", flight);
|
||||
src->flag("noclip", noclip);
|
||||
setChosenSlot(src->get("chosen-slot", getChosenSlot()));
|
||||
|
||||
auto invmap = src->map("inventory");
|
||||
if (invmap) {
|
||||
getInventory()->deserialize(invmap);
|
||||
|
||||
if (auto invmap = src->map("inventory")) {
|
||||
getInventory()->deserialize(invmap.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,16 +263,14 @@ void Player::convert(dynamic::Map* data, const ContentLUT* lut) {
|
||||
if (players) {
|
||||
for (uint i = 0; i < players->size(); i++) {
|
||||
auto playerData = players->map(i);
|
||||
auto inventory = playerData->map("inventory");
|
||||
if (inventory) {
|
||||
Inventory::convert(inventory, lut);
|
||||
if (auto inventory = playerData->map("inventory")) {
|
||||
Inventory::convert(inventory.get(), lut);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
auto inventory = data->map("inventory");
|
||||
if (inventory) {
|
||||
Inventory::convert(inventory, lut);
|
||||
if (auto inventory = data->map("inventory")) {
|
||||
Inventory::convert(inventory.get(), lut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,8 +94,8 @@ static std::tuple<size_t, std::unique_ptr<RigNode>> read_node(
|
||||
size_t count = 1;
|
||||
if (auto nodesList = root->list("nodes")) {
|
||||
for (size_t i = 0; i < nodesList->size(); i++) {
|
||||
if (auto map = nodesList->map(i)) {
|
||||
auto [subcount, subNode] = read_node(map, index+count);
|
||||
if (const auto& map = nodesList->map(i)) {
|
||||
auto [subcount, subNode] = read_node(map.get(), index+count);
|
||||
subcount += count;
|
||||
subnodes.push_back(std::move(subNode));
|
||||
}
|
||||
@ -114,6 +114,6 @@ std::unique_ptr<RigConfig> RigConfig::parse(
|
||||
if (rootNodeMap == nullptr) {
|
||||
throw std::runtime_error("missing 'root' element");
|
||||
}
|
||||
auto [count, rootNode] = read_node(rootNodeMap, 0);
|
||||
auto [count, rootNode] = read_node(rootNodeMap.get(), 0);
|
||||
return std::make_unique<RigConfig>(std::string(name), std::move(rootNode), count);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "Block.hpp"
|
||||
#include "../content/Content.hpp"
|
||||
#include "../files/WorldFiles.hpp"
|
||||
#include "../objects/Entities.hpp"
|
||||
#include "../world/Level.hpp"
|
||||
#include "../world/World.hpp"
|
||||
#include "../maths/voxmaths.hpp"
|
||||
@ -63,6 +64,10 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
||||
chunk->setBlockInventories(std::move(invs));
|
||||
|
||||
if (auto map = regions.fetchEntities(chunk->x, chunk->z)) {
|
||||
level->entities->loadEntities(std::move(map));
|
||||
}
|
||||
|
||||
chunk->flags.loaded = true;
|
||||
for(auto& entry : chunk->inventories) {
|
||||
level->inventories->store(entry.second);
|
||||
|
||||
@ -110,7 +110,7 @@ std::unique_ptr<Level> World::load(
|
||||
DEF_PLAYER_SPEED,
|
||||
level->inventories->create(DEF_PLAYER_INVENTORY_SIZE)
|
||||
);
|
||||
player->deserialize(players->map(i));
|
||||
player->deserialize(players->map(i).get());
|
||||
level->inventories->store(player->getInventory());
|
||||
}
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user