feat: saving entities (WIP)
This commit is contained in:
parent
019a88ef84
commit
f0270d3391
@ -6,5 +6,7 @@
|
|||||||
"triggers": [
|
"triggers": [
|
||||||
["aabb", -0.2, -0.2, -0.2, 0.2, 0.2, 0.2],
|
["aabb", -0.2, -0.2, -0.2, 0.2, 0.2, 0.2],
|
||||||
["radius", 1.6]
|
["radius", 1.6]
|
||||||
]
|
],
|
||||||
|
"save-rig-textures": true,
|
||||||
|
"save-rig-pose": true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,6 @@ function on_hud_open()
|
|||||||
count=1
|
count=1
|
||||||
}})
|
}})
|
||||||
local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL))
|
local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL))
|
||||||
drop.get_component("rigidbody"):set_vel(velocity)
|
drop.rigidbody:set_vel(velocity)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -74,6 +74,7 @@ return {
|
|||||||
if callback then
|
if callback then
|
||||||
local result, err = pcall(callback)
|
local result, err = pcall(callback)
|
||||||
if err then
|
if err then
|
||||||
|
--// TODO: replace with error logging
|
||||||
print(err)
|
print(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -238,7 +238,7 @@ assetload::postfunc assetload::rig(
|
|||||||
auto path = paths->find(file+".json");
|
auto path = paths->find(file+".json");
|
||||||
auto text = files::read_string(path);
|
auto text = files::read_string(path);
|
||||||
try {
|
try {
|
||||||
auto rig = rigging::RigConfig::parse(text, path.u8string()).release();
|
auto rig = rigging::RigConfig::parse(text, path.u8string(), name).release();
|
||||||
return [=](Assets* assets) {
|
return [=](Assets* assets) {
|
||||||
// TODO: add models loading
|
// TODO: add models loading
|
||||||
assets->store(std::unique_ptr<rigging::RigConfig>(rig), name);
|
assets->store(std::unique_ptr<rigging::RigConfig>(rig), name);
|
||||||
|
|||||||
@ -83,6 +83,13 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ubyte> json::to_binary(const Value& value, bool compress) {
|
||||||
|
if (auto map = std::get_if<Map_sptr>(&value)) {
|
||||||
|
return to_binary(map->get(), compress);
|
||||||
|
}
|
||||||
|
throw std::runtime_error("map is only supported as the root element");
|
||||||
|
}
|
||||||
|
|
||||||
static Value value_from_binary(ByteReader& reader) {
|
static Value value_from_binary(ByteReader& reader) {
|
||||||
ubyte typecode = reader.get();
|
ubyte typecode = reader.get();
|
||||||
switch (typecode) {
|
switch (typecode) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#ifndef CODERS_BINARY_JSON_HPP_
|
#ifndef CODERS_BINARY_JSON_HPP_
|
||||||
#define CODERS_BINARY_JSON_HPP_
|
#define CODERS_BINARY_JSON_HPP_
|
||||||
|
|
||||||
#include "../typedefs.hpp"
|
#include "../data/dynamic_fwd.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -26,8 +26,9 @@ namespace json {
|
|||||||
inline constexpr int BJSON_TYPE_NULL = 0xC;
|
inline constexpr int BJSON_TYPE_NULL = 0xC;
|
||||||
inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
|
inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
|
||||||
|
|
||||||
extern std::vector<ubyte> to_binary(const dynamic::Map* obj, bool compress=false);
|
std::vector<ubyte> to_binary(const dynamic::Map* obj, bool compress=false);
|
||||||
extern std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
std::vector<ubyte> to_binary(const dynamic::Value& obj, bool compress=false);
|
||||||
|
std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_BINARY_JSON_HPP_
|
#endif // CODERS_BINARY_JSON_HPP_
|
||||||
|
|||||||
@ -337,7 +337,9 @@ void ContentLoader::loadEntity(EntityDef& def, const std::string& name, const fs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "loading entity " << name << " from " << file.u8string() << std::endl;
|
root->flag("save", def.save.enabled);
|
||||||
|
root->flag("save-rig-pose", def.save.rig.pose);
|
||||||
|
root->flag("save-rig-textures", def.save.rig.textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadEntity(EntityDef& def, const std::string& full, const std::string& name) {
|
void ContentLoader::loadEntity(EntityDef& def, const std::string& full, const std::string& name) {
|
||||||
|
|||||||
@ -1,42 +1,22 @@
|
|||||||
#ifndef DATA_DYNAMIC_HPP_
|
#ifndef DATA_DYNAMIC_HPP_
|
||||||
#define DATA_DYNAMIC_HPP_
|
#define DATA_DYNAMIC_HPP_
|
||||||
|
|
||||||
#include "../typedefs.hpp"
|
#include "dynamic_fwd.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <variant>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace dynamic {
|
namespace dynamic {
|
||||||
class Map;
|
|
||||||
class List;
|
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
none=0, map, list, string, number, boolean, integer
|
none=0, map, list, string, number, boolean, integer
|
||||||
};
|
};
|
||||||
|
|
||||||
using Map_sptr = std::shared_ptr<Map>;
|
|
||||||
using List_sptr = std::shared_ptr<List>;
|
|
||||||
|
|
||||||
struct none {};
|
|
||||||
|
|
||||||
inline constexpr none NONE = {};
|
|
||||||
|
|
||||||
using Value = std::variant<
|
|
||||||
none,
|
|
||||||
Map_sptr,
|
|
||||||
List_sptr,
|
|
||||||
std::string,
|
|
||||||
number_t,
|
|
||||||
bool,
|
|
||||||
integer_t
|
|
||||||
>;
|
|
||||||
|
|
||||||
const std::string& type_name(const Value& value);
|
const std::string& type_name(const Value& value);
|
||||||
List_sptr create_list(std::initializer_list<Value> values={});
|
List_sptr create_list(std::initializer_list<Value> values={});
|
||||||
Map_sptr create_map(std::initializer_list<std::pair<const std::string, Value>> entries={});
|
Map_sptr create_map(std::initializer_list<std::pair<const std::string, Value>> entries={});
|
||||||
@ -153,6 +133,9 @@ namespace dynamic {
|
|||||||
Map& put(std::string key, int64_t value) {
|
Map& put(std::string key, int64_t value) {
|
||||||
return put(key, Value(static_cast<integer_t>(value)));
|
return put(key, Value(static_cast<integer_t>(value)));
|
||||||
}
|
}
|
||||||
|
Map& put(std::string key, uint64_t value) {
|
||||||
|
return put(key, Value(static_cast<integer_t>(value)));
|
||||||
|
}
|
||||||
Map& put(std::string key, float value) {
|
Map& put(std::string key, float value) {
|
||||||
return put(key, Value(static_cast<number_t>(value)));
|
return put(key, Value(static_cast<number_t>(value)));
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/data/dynamic_fwd.hpp
Normal file
31
src/data/dynamic_fwd.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef DATA_DYNAMIC_FWD_HPP_
|
||||||
|
#define DATA_DYNAMIC_FWD_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
namespace dynamic {
|
||||||
|
class Map;
|
||||||
|
class List;
|
||||||
|
|
||||||
|
using Map_sptr = std::shared_ptr<Map>;
|
||||||
|
using List_sptr = std::shared_ptr<List>;
|
||||||
|
|
||||||
|
struct none {};
|
||||||
|
|
||||||
|
inline constexpr none NONE = {};
|
||||||
|
|
||||||
|
using Value = std::variant<
|
||||||
|
none,
|
||||||
|
Map_sptr,
|
||||||
|
List_sptr,
|
||||||
|
std::string,
|
||||||
|
number_t,
|
||||||
|
bool,
|
||||||
|
integer_t
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DATA_DYNAMIC_FWD_HPP_
|
||||||
30
src/data/dynamic_util.hpp
Normal file
30
src/data/dynamic_util.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef DATA_DYNAMIC_UTIL_HPP_
|
||||||
|
#define DATA_DYNAMIC_UTIL_HPP_
|
||||||
|
|
||||||
|
#include "dynamic.hpp"
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace dynamic {
|
||||||
|
template<int n>
|
||||||
|
inline dynamic::List_sptr to_value(glm::vec<n, float> vec) {
|
||||||
|
auto list = dynamic::create_list();
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
list->put(vec[i]);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int n, int m>
|
||||||
|
inline dynamic::List_sptr to_value(glm::mat<n, m, float> mat) {
|
||||||
|
auto list = dynamic::create_list();
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
for (size_t j = 0; j < m; j++) {
|
||||||
|
list->put(mat[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DATA_DYNAMIC_UTIL_HPP_
|
||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define REGION_FORMAT_MAGIC ".VOXREG"
|
#define REGION_FORMAT_MAGIC ".VOXREG"
|
||||||
|
|
||||||
@ -36,17 +37,17 @@ std::unique_ptr<ubyte[]> regfile::read(int index, uint32_t& length) {
|
|||||||
|
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
file.seekg(table_offset + index * 4);
|
file.seekg(table_offset + index * 4);
|
||||||
file.read((char*)(&offset), 4);
|
file.read(reinterpret_cast<char*>(&offset), 4);
|
||||||
offset = dataio::read_int32_big((const ubyte*)(&offset), 0);
|
offset = dataio::read_int32_big(reinterpret_cast<const ubyte*>(&offset), 0);
|
||||||
if (offset == 0){
|
if (offset == 0){
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seekg(offset);
|
file.seekg(offset);
|
||||||
file.read((char*)(&offset), 4);
|
file.read(reinterpret_cast<char*>(&offset), 4);
|
||||||
length = dataio::read_int32_big((const ubyte*)(&offset), 0);
|
length = dataio::read_int32_big(reinterpret_cast<const ubyte*>(&offset), 0);
|
||||||
auto data = std::make_unique<ubyte[]>(length);
|
auto data = std::make_unique<ubyte[]>(length);
|
||||||
file.read((char*)data.get(), length);
|
file.read(reinterpret_cast<char*>(data.get()), length);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,12 +89,13 @@ uint WorldRegion::getChunkDataSize(uint x, uint z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WorldRegions::WorldRegions(const fs::path& directory) : directory(directory) {
|
WorldRegions::WorldRegions(const fs::path& directory) : directory(directory) {
|
||||||
for (uint i = 0; i < sizeof(layers)/sizeof(RegionsLayer); i++) {
|
for (size_t i = 0; i < sizeof(layers)/sizeof(RegionsLayer); i++) {
|
||||||
layers[i].layer = i;
|
layers[i].layer = i;
|
||||||
}
|
}
|
||||||
layers[REGION_LAYER_VOXELS].folder = directory/fs::path("regions");
|
layers[REGION_LAYER_VOXELS].folder = directory/fs::path("regions");
|
||||||
layers[REGION_LAYER_LIGHTS].folder = directory/fs::path("lights");
|
layers[REGION_LAYER_LIGHTS].folder = directory/fs::path("lights");
|
||||||
layers[REGION_LAYER_INVENTORIES].folder = directory/fs::path("inventories");
|
layers[REGION_LAYER_INVENTORIES].folder = directory/fs::path("inventories");
|
||||||
|
layers[REGION_LAYER_ENTITIES].folder = directory/fs::path("entities");
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRegions::~WorldRegions() {
|
WorldRegions::~WorldRegions() {
|
||||||
@ -123,7 +125,7 @@ WorldRegion* WorldRegions::getOrCreateRegion(int x, int z, int layer) {
|
|||||||
|
|
||||||
std::unique_ptr<ubyte[]> WorldRegions::compress(const ubyte* src, size_t srclen, size_t& len) {
|
std::unique_ptr<ubyte[]> WorldRegions::compress(const ubyte* src, size_t srclen, size_t& len) {
|
||||||
auto buffer = bufferPool.get();
|
auto buffer = bufferPool.get();
|
||||||
ubyte* bytes = buffer.get();
|
auto bytes = buffer.get();
|
||||||
|
|
||||||
len = extrle::encode(src, srclen, bytes);
|
len = extrle::encode(src, srclen, bytes);
|
||||||
auto data = std::make_unique<ubyte[]>(len);
|
auto data = std::make_unique<ubyte[]>(len);
|
||||||
@ -171,10 +173,7 @@ void WorldRegions::fetchChunks(WorldRegion* region, int x, int z, regfile* file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ubyte* WorldRegions::getData(
|
ubyte* WorldRegions::getData(int x, int z, int layer, uint32_t& size) {
|
||||||
int x, int z, int layer,
|
|
||||||
uint32_t& size
|
|
||||||
) {
|
|
||||||
if (generatorTestMode) {
|
if (generatorTestMode) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -301,7 +300,7 @@ void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){
|
|||||||
offset += 4 + compressedSize;
|
offset += 4 + compressedSize;
|
||||||
|
|
||||||
file.write(intbuf, 4);
|
file.write(intbuf, 4);
|
||||||
file.write((const char*)chunk, compressedSize);
|
file.write(reinterpret_cast<const char*>(chunk), compressedSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) {
|
for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) {
|
||||||
@ -313,8 +312,9 @@ void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){
|
|||||||
void WorldRegions::writeRegions(int layer) {
|
void WorldRegions::writeRegions(int layer) {
|
||||||
for (auto& it : layers[layer].regions){
|
for (auto& it : layers[layer].regions){
|
||||||
WorldRegion* region = it.second.get();
|
WorldRegion* region = it.second.get();
|
||||||
if (region->getChunks() == nullptr || !region->isUnsaved())
|
if (region->getChunks() == nullptr || !region->isUnsaved()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
glm::ivec2 key = it.first;
|
glm::ivec2 key = it.first;
|
||||||
writeRegion(key[0], key[1], layer, region);
|
writeRegion(key[0], key[1], layer, region);
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ static std::unique_ptr<ubyte[]> write_inventories(Chunk* chunk, uint& datasize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Store chunk data (voxels and lights) in region (existing or new)
|
/// @brief Store chunk data (voxels and lights) in region (existing or new)
|
||||||
void WorldRegions::put(Chunk* chunk){
|
void WorldRegions::put(Chunk* chunk, std::vector<ubyte> entitiesData){
|
||||||
assert(chunk != nullptr);
|
assert(chunk != nullptr);
|
||||||
if (!chunk->flags.lighted) {
|
if (!chunk->flags.lighted) {
|
||||||
return;
|
return;
|
||||||
@ -382,6 +382,15 @@ void WorldRegions::put(Chunk* chunk){
|
|||||||
put(chunk->x, chunk->z, REGION_LAYER_INVENTORIES,
|
put(chunk->x, chunk->z, REGION_LAYER_INVENTORIES,
|
||||||
std::move(data), datasize, false);
|
std::move(data), datasize, false);
|
||||||
}
|
}
|
||||||
|
// Writing entities
|
||||||
|
if (!entitiesData.empty()) {
|
||||||
|
auto data = std::make_unique<ubyte[]>(entitiesData.size());
|
||||||
|
for (size_t i = 0; i < entitiesData.size(); i++) {
|
||||||
|
data[i] = entitiesData[i];
|
||||||
|
}
|
||||||
|
put(chunk->x, chunk->z, REGION_LAYER_ENTITIES,
|
||||||
|
std::move(data), entitiesData.size(), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ubyte[]> WorldRegions::getChunk(int x, int z){
|
std::unique_ptr<ubyte[]> WorldRegions::getChunk(int x, int z){
|
||||||
@ -398,8 +407,9 @@ std::unique_ptr<ubyte[]> WorldRegions::getChunk(int x, int z){
|
|||||||
std::unique_ptr<light_t[]> WorldRegions::getLights(int x, int z) {
|
std::unique_ptr<light_t[]> WorldRegions::getLights(int x, int z) {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
auto* bytes = getData(x, z, REGION_LAYER_LIGHTS, size);
|
auto* bytes = getData(x, z, REGION_LAYER_LIGHTS, size);
|
||||||
if (bytes == nullptr)
|
if (bytes == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
auto data = decompress(bytes, size, LIGHTMAP_DATA_LEN);
|
auto data = decompress(bytes, size, LIGHTMAP_DATA_LEN);
|
||||||
return Lightmap::decode(data.get());
|
return Lightmap::decode(data.get());
|
||||||
}
|
}
|
||||||
@ -412,7 +422,7 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) {
|
|||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
ByteReader reader(data, bytesSize);
|
ByteReader reader(data, bytesSize);
|
||||||
int count = reader.getInt32();
|
auto count = reader.getInt32();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
uint index = reader.getInt32();
|
uint index = reader.getInt32();
|
||||||
uint size = reader.getInt32();
|
uint size = reader.getInt32();
|
||||||
@ -439,8 +449,9 @@ void WorldRegions::processRegionVoxels(int x, int z, const regionproc& func) {
|
|||||||
int gz = cz + z * REGION_SIZE;
|
int gz = cz + z * REGION_SIZE;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
auto data = readChunkData(gx, gz, length, regfile.get());
|
auto data = readChunkData(gx, gz, length, regfile.get());
|
||||||
if (data == nullptr)
|
if (data == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
data = decompress(data.get(), length, CHUNK_DATA_LEN);
|
data = decompress(data.get(), length, CHUNK_DATA_LEN);
|
||||||
if (func(data.get())) {
|
if (func(data.get())) {
|
||||||
put(gx, gz, REGION_LAYER_VOXELS, std::move(data), CHUNK_DATA_LEN, true);
|
put(gx, gz, REGION_LAYER_VOXELS, std::move(data), CHUNK_DATA_LEN, true);
|
||||||
|
|||||||
@ -24,6 +24,7 @@ inline constexpr uint REGION_HEADER_SIZE = 10;
|
|||||||
inline constexpr uint REGION_LAYER_VOXELS = 0;
|
inline constexpr uint REGION_LAYER_VOXELS = 0;
|
||||||
inline constexpr uint REGION_LAYER_LIGHTS = 1;
|
inline constexpr uint REGION_LAYER_LIGHTS = 1;
|
||||||
inline constexpr uint REGION_LAYER_INVENTORIES = 2;
|
inline constexpr uint REGION_LAYER_INVENTORIES = 2;
|
||||||
|
inline constexpr uint REGION_LAYER_ENTITIES = 3;
|
||||||
|
|
||||||
inline constexpr uint REGION_SIZE_BIT = 5;
|
inline constexpr uint REGION_SIZE_BIT = 5;
|
||||||
inline constexpr uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
inline constexpr uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
||||||
@ -119,7 +120,7 @@ class WorldRegions {
|
|||||||
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
||||||
std::mutex regFilesMutex;
|
std::mutex regFilesMutex;
|
||||||
std::condition_variable regFilesCv;
|
std::condition_variable regFilesCv;
|
||||||
RegionsLayer layers[3] {};
|
RegionsLayer layers[4] {};
|
||||||
util::BufferPool<ubyte> bufferPool {
|
util::BufferPool<ubyte> bufferPool {
|
||||||
std::max(CHUNK_DATA_LEN, LIGHTMAP_DATA_LEN) * 2
|
std::max(CHUNK_DATA_LEN, LIGHTMAP_DATA_LEN) * 2
|
||||||
};
|
};
|
||||||
@ -170,7 +171,7 @@ public:
|
|||||||
~WorldRegions();
|
~WorldRegions();
|
||||||
|
|
||||||
/// @brief Put all chunk data to regions
|
/// @brief Put all chunk data to regions
|
||||||
void put(Chunk* chunk);
|
void put(Chunk* chunk, std::vector<ubyte> entitiesData);
|
||||||
|
|
||||||
/// @brief Store data in specified region
|
/// @brief Store data in specified region
|
||||||
/// @param x chunk.x
|
/// @param x chunk.x
|
||||||
|
|||||||
@ -295,6 +295,7 @@ void scripting::on_entity_spawn(
|
|||||||
funcsset.on_despawn = lua::hasfield(L, "on_despawn");
|
funcsset.on_despawn = lua::hasfield(L, "on_despawn");
|
||||||
funcsset.on_trigger_enter = lua::hasfield(L, "on_trigger_enter");
|
funcsset.on_trigger_enter = lua::hasfield(L, "on_trigger_enter");
|
||||||
funcsset.on_trigger_exit = lua::hasfield(L, "on_trigger_exit");
|
funcsset.on_trigger_exit = lua::hasfield(L, "on_trigger_exit");
|
||||||
|
funcsset.on_save = lua::hasfield(L, "on_save");
|
||||||
lua::pop(L, 2);
|
lua::pop(L, 2);
|
||||||
|
|
||||||
component->env = compenv;
|
component->env = compenv;
|
||||||
@ -355,6 +356,16 @@ bool scripting::on_entity_fall(const Entity& entity) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool scripting::on_entity_save(const Entity& entity) {
|
||||||
|
const auto& script = entity.getScripting();
|
||||||
|
for (auto& component : script.components) {
|
||||||
|
if (component->funcsset.on_save) {
|
||||||
|
process_entity_callback(component->env, "on_save", nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void scripting::on_trigger_enter(const Entity& entity, size_t index, entityid_t oid) {
|
void scripting::on_trigger_enter(const Entity& entity, size_t index, entityid_t oid) {
|
||||||
const auto& script = entity.getScripting();
|
const auto& script = entity.getScripting();
|
||||||
for (auto& component : script.components) {
|
for (auto& component : script.components) {
|
||||||
|
|||||||
@ -85,6 +85,7 @@ namespace scripting {
|
|||||||
bool on_entity_despawn(const EntityDef& def, const Entity& entity);
|
bool on_entity_despawn(const EntityDef& def, const Entity& entity);
|
||||||
bool on_entity_grounded(const Entity& entity, float force);
|
bool on_entity_grounded(const Entity& entity, float force);
|
||||||
bool on_entity_fall(const Entity& entity);
|
bool on_entity_fall(const Entity& entity);
|
||||||
|
bool on_entity_save(const Entity& entity);
|
||||||
void on_entities_update();
|
void on_entities_update();
|
||||||
void on_trigger_enter(const Entity& entity, size_t index, entityid_t oid);
|
void on_trigger_enter(const Entity& entity, size_t index, entityid_t oid);
|
||||||
void on_trigger_exit(const Entity& entity, size_t index, entityid_t oid);
|
void on_trigger_exit(const Entity& entity, size_t index, entityid_t oid);
|
||||||
|
|||||||
@ -13,7 +13,7 @@ struct AABB {
|
|||||||
AABB(glm::vec3 size) : a(0.0f), b(size) {
|
AABB(glm::vec3 size) : a(0.0f), b(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB(glm::vec3 pos, glm::vec3 size) : a(pos), b(size) {
|
AABB(glm::vec3 a, glm::vec3 b) : a(a), b(b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get AABB point with minimal x,y,z
|
/// @brief Get AABB point with minimal x,y,z
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "Entities.hpp"
|
#include "Entities.hpp"
|
||||||
|
|
||||||
|
#include "../data/dynamic_util.hpp"
|
||||||
#include "../assets/Assets.hpp"
|
#include "../assets/Assets.hpp"
|
||||||
#include "../world/Level.hpp"
|
#include "../world/Level.hpp"
|
||||||
#include "../physics/Hitbox.hpp"
|
#include "../physics/Hitbox.hpp"
|
||||||
@ -78,8 +79,7 @@ entityid_t Entities::spawn(
|
|||||||
body.triggers[i] = Trigger {
|
body.triggers[i] = Trigger {
|
||||||
true, TriggerType::AABB, i, id, params, params, {}, {},
|
true, TriggerType::AABB, i, id, params, params, {}, {},
|
||||||
create_trigger_callback<scripting::on_trigger_enter>(this),
|
create_trigger_callback<scripting::on_trigger_enter>(this),
|
||||||
create_trigger_callback<scripting::on_trigger_exit>(this)
|
create_trigger_callback<scripting::on_trigger_exit>(this)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
for (auto& [i, radius] : def.radialTriggers) {
|
for (auto& [i, radius] : def.radialTriggers) {
|
||||||
TriggerParams params {};
|
TriggerParams params {};
|
||||||
@ -87,11 +87,11 @@ entityid_t Entities::spawn(
|
|||||||
body.triggers[i] = Trigger {
|
body.triggers[i] = Trigger {
|
||||||
true, TriggerType::RADIUS, i, id, params, params, {}, {},
|
true, TriggerType::RADIUS, i, id, params, params, {}, {},
|
||||||
create_trigger_callback<scripting::on_trigger_enter>(this),
|
create_trigger_callback<scripting::on_trigger_enter>(this),
|
||||||
create_trigger_callback<scripting::on_trigger_exit>(this)
|
create_trigger_callback<scripting::on_trigger_exit>(this)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
auto& scripting = registry.emplace<ScriptComponents>(entity);
|
auto& scripting = registry.emplace<ScriptComponents>(entity);
|
||||||
entities[id] = entity;
|
entities[id] = entity;
|
||||||
|
uids[entity] = id;
|
||||||
registry.emplace<rigging::Rig>(entity, rig->instance());
|
registry.emplace<rigging::Rig>(entity, rig->instance());
|
||||||
for (auto& componentName : def.components) {
|
for (auto& componentName : def.components) {
|
||||||
auto component = std::make_unique<UserComponent>(
|
auto component = std::make_unique<UserComponent>(
|
||||||
@ -112,11 +112,59 @@ void Entities::despawn(entityid_t id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dynamic::Value Entities::serialize(const Entity& entity) {
|
||||||
|
auto root = dynamic::create_map();
|
||||||
|
auto& eid = entity.getID();
|
||||||
|
auto& def = eid.def;
|
||||||
|
root->put("def", def.name);
|
||||||
|
root->put("uid", eid.uid);
|
||||||
|
{
|
||||||
|
auto& transform = entity.getTransform();
|
||||||
|
auto& tsfmap = root->putMap("transform");
|
||||||
|
tsfmap.put("pos", dynamic::to_value(transform.pos));
|
||||||
|
if (transform.size != glm::vec3(1.0f)) {
|
||||||
|
tsfmap.put("size", dynamic::to_value(transform.size));
|
||||||
|
}
|
||||||
|
tsfmap.put("rot", dynamic::to_value(transform.rot));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto& rigidbody = entity.getRigidbody();
|
||||||
|
auto& bodymap = root->putMap("rigidbody");
|
||||||
|
if (!rigidbody.enabled) {
|
||||||
|
bodymap.put("enabled", rigidbody.enabled);
|
||||||
|
}
|
||||||
|
bodymap.put("vel", dynamic::to_value(rigidbody.hitbox.velocity));
|
||||||
|
bodymap.put("damping", rigidbody.hitbox.linearDamping);
|
||||||
|
}
|
||||||
|
auto& rig = entity.getModeltree();
|
||||||
|
if (rig.config->getName() != def.rigName) {
|
||||||
|
root->put("rig", rig.config->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def.save.rig.pose || def.save.rig.textures) {
|
||||||
|
auto& rigmap = root->putMap("rig");
|
||||||
|
if (def.save.rig.textures) {
|
||||||
|
auto& map = rigmap.putMap("textures");
|
||||||
|
for (auto& entry : rig.textures) {
|
||||||
|
map.put(entry.first, entry.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (def.save.rig.pose) {
|
||||||
|
auto& list = rigmap.putList("pose");
|
||||||
|
for (auto& mat : rig.pose.matrices) {
|
||||||
|
list.put(dynamic::to_value(mat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
void Entities::clean() {
|
void Entities::clean() {
|
||||||
for (auto it = entities.begin(); it != entities.end();) {
|
for (auto it = entities.begin(); it != entities.end();) {
|
||||||
if (!registry.get<EntityId>(it->second).destroyFlag) {
|
if (!registry.get<EntityId>(it->second).destroyFlag) {
|
||||||
++it;
|
++it;
|
||||||
} else {
|
} else {
|
||||||
|
uids.erase(it->second);
|
||||||
registry.destroy(it->second);
|
registry.destroy(it->second);
|
||||||
it = entities.erase(it);
|
it = entities.erase(it);
|
||||||
}
|
}
|
||||||
@ -249,3 +297,20 @@ void Entities::render(Assets* assets, ModelBatch& batch, const Frustum& frustum)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Entity> Entities::getAllInside(AABB aabb) {
|
||||||
|
std::vector<Entity> collected;
|
||||||
|
auto view = registry.view<Transform>();
|
||||||
|
for (auto [entity, transform] : view.each()) {
|
||||||
|
if (aabb.contains(transform.pos)) {
|
||||||
|
const auto& found = uids.find(entity);
|
||||||
|
if (found == uids.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (auto entity = get(found->second)) {
|
||||||
|
collected.push_back(*entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collected;
|
||||||
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ struct entity_funcs_set {
|
|||||||
bool on_fall : 1;
|
bool on_fall : 1;
|
||||||
bool on_trigger_enter : 1;
|
bool on_trigger_enter : 1;
|
||||||
bool on_trigger_exit : 1;
|
bool on_trigger_exit : 1;
|
||||||
|
bool on_save : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityDef;
|
struct EntityDef;
|
||||||
@ -154,6 +155,7 @@ class Entities {
|
|||||||
entt::registry registry;
|
entt::registry registry;
|
||||||
Level* level;
|
Level* level;
|
||||||
std::unordered_map<entityid_t, entt::entity> entities;
|
std::unordered_map<entityid_t, entt::entity> entities;
|
||||||
|
std::unordered_map<entt::entity, entityid_t> uids;
|
||||||
entityid_t nextID = 1;
|
entityid_t nextID = 1;
|
||||||
|
|
||||||
void preparePhysics();
|
void preparePhysics();
|
||||||
@ -181,7 +183,9 @@ public:
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Entity> getAllInside(AABB aabb);
|
||||||
void despawn(entityid_t id);
|
void despawn(entityid_t id);
|
||||||
|
dynamic::Value serialize(const Entity& entity);
|
||||||
|
|
||||||
inline size_t size() const {
|
inline size_t size() const {
|
||||||
return entities.size();
|
return entities.size();
|
||||||
|
|||||||
@ -23,6 +23,14 @@ struct EntityDef {
|
|||||||
std::vector<std::pair<size_t, float>> radialTriggers {};
|
std::vector<std::pair<size_t, float>> radialTriggers {};
|
||||||
std::string rigName = name.substr(name.find(":")+1);
|
std::string rigName = name.substr(name.find(":")+1);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool enabled = true;
|
||||||
|
struct {
|
||||||
|
bool textures = false;
|
||||||
|
bool pose = false;
|
||||||
|
} rig;
|
||||||
|
} save {};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
entityid_t id;
|
entityid_t id;
|
||||||
rigging::RigConfig* rig;
|
rigging::RigConfig* rig;
|
||||||
|
|||||||
@ -30,8 +30,8 @@ static void get_all_nodes(std::vector<RigNode*>& nodes, RigNode* node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RigConfig::RigConfig(std::unique_ptr<RigNode> root, size_t nodesCount)
|
RigConfig::RigConfig(const std::string& name, std::unique_ptr<RigNode> root, size_t nodesCount)
|
||||||
: root(std::move(root)), nodes(nodesCount) {
|
: name(name), root(std::move(root)), nodes(nodesCount) {
|
||||||
get_all_nodes(nodes, this->root.get());
|
get_all_nodes(nodes, this->root.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,8 @@ static std::tuple<size_t, std::unique_ptr<RigNode>> read_node(
|
|||||||
|
|
||||||
std::unique_ptr<RigConfig> RigConfig::parse(
|
std::unique_ptr<RigConfig> RigConfig::parse(
|
||||||
std::string_view src,
|
std::string_view src,
|
||||||
std::string_view file
|
std::string_view file,
|
||||||
|
std::string_view name
|
||||||
) {
|
) {
|
||||||
auto root = json::parse(file, src);
|
auto root = json::parse(file, src);
|
||||||
auto rootNodeMap = root->map("root");
|
auto rootNodeMap = root->map("root");
|
||||||
@ -114,5 +115,5 @@ std::unique_ptr<RigConfig> RigConfig::parse(
|
|||||||
throw std::runtime_error("missing 'root' element");
|
throw std::runtime_error("missing 'root' element");
|
||||||
}
|
}
|
||||||
auto [count, rootNode] = read_node(rootNodeMap, 0);
|
auto [count, rootNode] = read_node(rootNodeMap, 0);
|
||||||
return std::make_unique<RigConfig>(std::move(rootNode), count);
|
return std::make_unique<RigConfig>(std::string(name), std::move(rootNode), count);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,6 +68,7 @@ namespace rigging {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class RigConfig {
|
class RigConfig {
|
||||||
|
std::string name;
|
||||||
std::unique_ptr<RigNode> root;
|
std::unique_ptr<RigNode> root;
|
||||||
std::unordered_map<std::string, size_t> indices;
|
std::unordered_map<std::string, size_t> indices;
|
||||||
|
|
||||||
@ -85,7 +86,8 @@ namespace rigging {
|
|||||||
RigNode* node,
|
RigNode* node,
|
||||||
glm::mat4 matrix) const;
|
glm::mat4 matrix) const;
|
||||||
public:
|
public:
|
||||||
RigConfig(std::unique_ptr<RigNode> root, size_t nodesCount);
|
RigConfig(const std::string& name, std::unique_ptr<RigNode> root,
|
||||||
|
size_t nodesCount);
|
||||||
|
|
||||||
void update(Rig& rig, glm::mat4 matrix) const;
|
void update(Rig& rig, glm::mat4 matrix) const;
|
||||||
void setup(const Assets* assets, RigNode* node=nullptr) const;
|
void setup(const Assets* assets, RigNode* node=nullptr) const;
|
||||||
@ -103,12 +105,17 @@ namespace rigging {
|
|||||||
|
|
||||||
static std::unique_ptr<RigConfig> parse(
|
static std::unique_ptr<RigConfig> parse(
|
||||||
std::string_view src,
|
std::string_view src,
|
||||||
std::string_view file
|
std::string_view file,
|
||||||
|
std::string_view name
|
||||||
);
|
);
|
||||||
|
|
||||||
const std::vector<RigNode*>& getNodes() const {
|
const std::vector<RigNode*>& getNodes() const {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& getName() const {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,14 @@
|
|||||||
#include "../lighting/Lightmap.hpp"
|
#include "../lighting/Lightmap.hpp"
|
||||||
#include "../files/WorldFiles.hpp"
|
#include "../files/WorldFiles.hpp"
|
||||||
#include "../world/LevelEvents.hpp"
|
#include "../world/LevelEvents.hpp"
|
||||||
|
#include "../world/Level.hpp"
|
||||||
|
#include "../objects/Entities.hpp"
|
||||||
#include "../graphics/core/Mesh.hpp"
|
#include "../graphics/core/Mesh.hpp"
|
||||||
#include "../maths/voxmaths.hpp"
|
#include "../maths/voxmaths.hpp"
|
||||||
#include "../maths/aabb.hpp"
|
#include "../maths/aabb.hpp"
|
||||||
#include "../maths/rays.hpp"
|
#include "../maths/rays.hpp"
|
||||||
|
#include "../coders/byte_utils.hpp"
|
||||||
|
#include "../coders/json.hpp"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -21,14 +25,13 @@ Chunks::Chunks(
|
|||||||
uint32_t w, uint32_t d,
|
uint32_t w, uint32_t d,
|
||||||
int32_t ox, int32_t oz,
|
int32_t ox, int32_t oz,
|
||||||
WorldFiles* wfile,
|
WorldFiles* wfile,
|
||||||
LevelEvents* events,
|
Level* level
|
||||||
const Content* content
|
) : level(level),
|
||||||
) : indices(content->getIndices()),
|
indices(level->content->getIndices()),
|
||||||
chunks(w*d),
|
chunks(w*d),
|
||||||
chunksSecond(w*d),
|
chunksSecond(w*d),
|
||||||
w(w), d(d), ox(ox), oz(oz),
|
w(w), d(d), ox(ox), oz(oz),
|
||||||
worldFiles(wfile),
|
worldFiles(wfile)
|
||||||
events(events)
|
|
||||||
{
|
{
|
||||||
volume = static_cast<size_t>(w)*static_cast<size_t>(d);
|
volume = static_cast<size_t>(w)*static_cast<size_t>(d);
|
||||||
chunksCount = 0;
|
chunksCount = 0;
|
||||||
@ -517,9 +520,9 @@ voxel* Chunks::rayCast(
|
|||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist) {
|
glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist) {
|
||||||
float px = start.x;
|
const float px = start.x;
|
||||||
float py = start.y;
|
const float py = start.y;
|
||||||
float pz = start.z;
|
const float pz = start.z;
|
||||||
|
|
||||||
float dx = dir.x;
|
float dx = dir.x;
|
||||||
float dy = dir.y;
|
float dy = dir.y;
|
||||||
@ -620,7 +623,6 @@ void Chunks::setCenter(int32_t x, int32_t z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::translate(int32_t dx, int32_t dz) {
|
void Chunks::translate(int32_t dx, int32_t dz) {
|
||||||
auto& regions = worldFiles->getRegions();
|
|
||||||
for (uint i = 0; i < volume; i++){
|
for (uint i = 0; i < volume; i++){
|
||||||
chunksSecond[i] = nullptr;
|
chunksSecond[i] = nullptr;
|
||||||
}
|
}
|
||||||
@ -631,9 +633,9 @@ void Chunks::translate(int32_t dx, int32_t dz) {
|
|||||||
int nz = z - dz;
|
int nz = z - dz;
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
if (nx < 0 || nz < 0 || nx >= int(w) || nz >= int(d)) {
|
if (nx < 0 || nz < 0 || nx >= static_cast<int>(w) || nz >= static_cast<int>(d)) {
|
||||||
events->trigger(EVT_CHUNK_HIDDEN, chunk.get());
|
level->events->trigger(EVT_CHUNK_HIDDEN, chunk.get());
|
||||||
regions.put(chunk.get());
|
save(chunk.get());
|
||||||
chunksCount--;
|
chunksCount--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -662,8 +664,8 @@ void Chunks::resize(uint32_t newW, uint32_t newD) {
|
|||||||
const int newVolume = newW * newD;
|
const int newVolume = newW * newD;
|
||||||
std::vector<std::shared_ptr<Chunk>> newChunks(newVolume);
|
std::vector<std::shared_ptr<Chunk>> newChunks(newVolume);
|
||||||
std::vector<std::shared_ptr<Chunk>> newChunksSecond(newVolume);
|
std::vector<std::shared_ptr<Chunk>> newChunksSecond(newVolume);
|
||||||
for (int z = 0; z < int(d) && z < int(newD); z++) {
|
for (int z = 0; z < static_cast<int>(d) && z < static_cast<int>(newD); z++) {
|
||||||
for (int x = 0; x < int(w) && x < int(newW); x++) {
|
for (int x = 0; x < static_cast<int>(w) && x < static_cast<int>(newW); x++) {
|
||||||
newChunks[z * newW + x] = chunks[z * w + x];
|
newChunks[z * newW + x] = chunks[z * w + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,21 +686,46 @@ bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
|
|||||||
int z = chunk->z;
|
int z = chunk->z;
|
||||||
x -= ox;
|
x -= ox;
|
||||||
z -= oz;
|
z -= oz;
|
||||||
if (x < 0 || z < 0 || x >= int(w) || z >= int(d))
|
if (x < 0 || z < 0 || x >= static_cast<int>(w) || z >= static_cast<int>(d)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
chunks[z * w + x] = chunk;
|
chunks[z * w + x] = chunk;
|
||||||
chunksCount++;
|
chunksCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::saveAndClear() {
|
void Chunks::saveAndClear() {
|
||||||
auto& regions = worldFiles->getRegions();
|
|
||||||
for (size_t i = 0; i < volume; i++){
|
for (size_t i = 0; i < volume; i++){
|
||||||
Chunk* chunk = chunks[i].get();
|
auto chunk = chunks[i].get();
|
||||||
chunks[i] = nullptr;
|
chunks[i] = nullptr;
|
||||||
if (chunk) {
|
save(chunk);
|
||||||
regions.put(chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
chunksCount = 0;
|
chunksCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Chunks::save(Chunk* chunk) {
|
||||||
|
if (chunk != nullptr) {
|
||||||
|
AABB aabb (
|
||||||
|
glm::vec3(chunk->x * CHUNK_W, -16, chunk->z * CHUNK_D),
|
||||||
|
glm::vec3((chunk->x+1) * CHUNK_W, CHUNK_H+32, (chunk->z + 1) * CHUNK_D)
|
||||||
|
);
|
||||||
|
auto entities = level->entities->getAllInside(aabb);
|
||||||
|
auto root = dynamic::create_map();
|
||||||
|
auto& list = root->putList("data");
|
||||||
|
for (auto& entity : entities) {
|
||||||
|
list.put(level->entities->serialize(entity));
|
||||||
|
}
|
||||||
|
if (!entities.empty()) {
|
||||||
|
chunk->flags.unsaved = true;
|
||||||
|
}
|
||||||
|
worldFiles->getRegions().put(chunk, json::to_binary(root, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunks::saveAll() {
|
||||||
|
for (size_t i = 0; i < volume; i++) {
|
||||||
|
if (auto& chunk = chunks[i]) {
|
||||||
|
save(chunk.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -18,9 +18,11 @@ class Chunk;
|
|||||||
class WorldFiles;
|
class WorldFiles;
|
||||||
class LevelEvents;
|
class LevelEvents;
|
||||||
class Block;
|
class Block;
|
||||||
|
class Level;
|
||||||
|
|
||||||
/* Player-centred chunks matrix */
|
/// Player-centred chunks matrix
|
||||||
class Chunks {
|
class Chunks {
|
||||||
|
Level* level;
|
||||||
const ContentIndices* const indices;
|
const ContentIndices* const indices;
|
||||||
|
|
||||||
void eraseSegments(const Block* def, blockstate state, int x, int y, int z);
|
void eraseSegments(const Block* def, blockstate state, int x, int y, int z);
|
||||||
@ -35,10 +37,9 @@ public:
|
|||||||
uint32_t w, d;
|
uint32_t w, d;
|
||||||
int32_t ox, oz;
|
int32_t ox, oz;
|
||||||
WorldFiles* worldFiles;
|
WorldFiles* worldFiles;
|
||||||
LevelEvents* events;
|
|
||||||
|
|
||||||
Chunks(uint32_t w, uint32_t d, int32_t ox, int32_t oz,
|
Chunks(uint32_t w, uint32_t d, int32_t ox, int32_t oz,
|
||||||
WorldFiles* worldFiles, LevelEvents* events, const Content* content);
|
WorldFiles* worldFiles, Level* level);
|
||||||
~Chunks() = default;
|
~Chunks() = default;
|
||||||
|
|
||||||
bool putChunk(const std::shared_ptr<Chunk>& chunk);
|
bool putChunk(const std::shared_ptr<Chunk>& chunk);
|
||||||
@ -95,6 +96,8 @@ public:
|
|||||||
void resize(uint32_t newW, uint32_t newD);
|
void resize(uint32_t newW, uint32_t newD);
|
||||||
|
|
||||||
void saveAndClear();
|
void saveAndClear();
|
||||||
|
void save(Chunk* chunk);
|
||||||
|
void saveAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VOXELS_CHUNKS_HPP_
|
#endif // VOXELS_CHUNKS_HPP_
|
||||||
|
|||||||
@ -38,7 +38,7 @@ Level::Level(
|
|||||||
settings.chunks.padding.get()
|
settings.chunks.padding.get()
|
||||||
) * 2;
|
) * 2;
|
||||||
chunks = std::make_unique<Chunks>(
|
chunks = std::make_unique<Chunks>(
|
||||||
matrixSize, matrixSize, 0, 0, this->world->wfile.get(), events.get(), content
|
matrixSize, matrixSize, 0, 0, this->world->wfile.get(), this
|
||||||
);
|
);
|
||||||
lighting = std::make_unique<Lighting>(content, chunks.get());
|
lighting = std::make_unique<Lighting>(content, chunks.get());
|
||||||
|
|
||||||
|
|||||||
@ -51,14 +51,7 @@ void World::updateTimers(float delta) {
|
|||||||
|
|
||||||
void World::write(Level* level) {
|
void World::write(Level* level) {
|
||||||
const Content* content = level->content;
|
const Content* content = level->content;
|
||||||
Chunks* chunks = level->chunks.get();
|
level->chunks->saveAll();
|
||||||
auto& regions = wfile->getRegions();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < chunks->volume; i++) {
|
|
||||||
if (auto chunk = chunks->chunks[i]) {
|
|
||||||
regions.put(chunk.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wfile->write(this, content);
|
wfile->write(this, content);
|
||||||
auto playerFile = dynamic::Map();
|
auto playerFile = dynamic::Map();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user