feat: add app.save_world() function and update documentation

This commit is contained in:
MihailRis 2024-12-25 15:15:11 +03:00
parent 96577ee041
commit ed7dc1f901
8 changed files with 48 additions and 7 deletions

View File

@ -83,6 +83,12 @@ app.reopen_world()
Reopens the world. Reopens the world.
```lua
app.save_world()
```
Saves the world.
```lua ```lua
app.close_world( app.close_world(
-- save the world before closing -- save the world before closing

View File

@ -83,6 +83,12 @@ app.reopen_world()
Переоткрывает мир. Переоткрывает мир.
```lua
app.save_world()
```
Сохраняет мир.
```lua ```lua
app.close_world( app.close_world(
-- сохранить мир перед закрытием -- сохранить мир перед закрытием

View File

@ -27,6 +27,7 @@ if app then
app.script = __VC_SCRIPT_NAME app.script = __VC_SCRIPT_NAME
app.new_world = core.new_world app.new_world = core.new_world
app.open_world = core.open_world app.open_world = core.open_world
app.save_world = core.save_world
app.close_world = core.close_world app.close_world = core.close_world
app.reopen_world = core.reopen_world app.reopen_world = core.reopen_world
app.delete_world = core.delete_world app.delete_world = core.delete_world

View File

@ -63,6 +63,15 @@ static int l_reopen_world(lua::State*) {
return 0; return 0;
} }
/// @brief Save world
static int l_save_world(lua::State* L) {
if (controller == nullptr) {
throw std::runtime_error("no world open");
}
controller->saveWorld();
return 0;
}
/// @brief Close world /// @brief Close world
/// @param flag Save world (bool) /// @param flag Save world (bool)
static int l_close_world(lua::State* L) { static int l_close_world(lua::State* L) {
@ -246,6 +255,7 @@ const luaL_Reg corelib[] = {
{"new_world", lua::wrap<l_new_world>}, {"new_world", lua::wrap<l_new_world>},
{"open_world", lua::wrap<l_open_world>}, {"open_world", lua::wrap<l_open_world>},
{"reopen_world", lua::wrap<l_reopen_world>}, {"reopen_world", lua::wrap<l_reopen_world>},
{"save_world", lua::wrap<l_save_world>},
{"close_world", lua::wrap<l_close_world>}, {"close_world", lua::wrap<l_close_world>},
{"delete_world", lua::wrap<l_delete_world>}, {"delete_world", lua::wrap<l_delete_world>},
{"reconfig_packs", lua::wrap<l_reconfig_packs>}, {"reconfig_packs", lua::wrap<l_reconfig_packs>},

View File

@ -8,6 +8,7 @@
#include "constants.hpp" #include "constants.hpp"
#include "lighting/Lightmap.hpp" #include "lighting/Lightmap.hpp"
#include "util/SmallHeap.hpp" #include "util/SmallHeap.hpp"
#include "maths/aabb.hpp"
#include "voxel.hpp" #include "voxel.hpp"
inline constexpr int CHUNK_DATA_LEN = CHUNK_VOL * 4; inline constexpr int CHUNK_DATA_LEN = CHUNK_VOL * 4;
@ -75,4 +76,11 @@ public:
bool decode(const ubyte* data); bool decode(const ubyte* data);
static void convert(ubyte* data, const ContentReport* report); static void convert(ubyte* data, const ContentReport* report);
AABB getAABB() const {
return AABB(
glm::vec3(x * CHUNK_W, -INFINITY, z * CHUNK_D),
glm::vec3((x + 1) * CHUNK_W, INFINITY, (z + 1) * CHUNK_D)
);
}
}; };

View File

@ -24,6 +24,10 @@ GlobalChunks::GlobalChunks(Level* level)
chunksMap.max_load_factor(CHUNKS_MAP_MAX_LOAD_FACTOR); chunksMap.max_load_factor(CHUNKS_MAP_MAX_LOAD_FACTOR);
} }
void GlobalChunks::setOnUnload(consumer<Chunk&> onUnload) {
this->onUnload = std::move(onUnload);
}
std::shared_ptr<Chunk> GlobalChunks::fetch(int x, int z) { std::shared_ptr<Chunk> GlobalChunks::fetch(int x, int z) {
const auto& found = chunksMap.find(keyfrom(x, z)); const auto& found = chunksMap.find(keyfrom(x, z));
if (found == chunksMap.end()) { if (found == chunksMap.end()) {
@ -160,6 +164,9 @@ void GlobalChunks::decref(Chunk* chunk) {
ekey.pos[0] = chunk->x; ekey.pos[0] = chunk->x;
ekey.pos[1] = chunk->z; ekey.pos[1] = chunk->z;
if (onUnload) {
onUnload(*chunk);
}
save(chunk); save(chunk);
chunksMap.erase(ekey.key); chunksMap.erase(ekey.key);
refCounters.erase(found); refCounters.erase(found);
@ -170,17 +177,11 @@ void GlobalChunks::save(Chunk* chunk) {
if (chunk == nullptr) { if (chunk == nullptr) {
return; return;
} }
AABB aabb( AABB aabb = chunk->getAABB();
glm::vec3(chunk->x * CHUNK_W, -INFINITY, chunk->z * CHUNK_D),
glm::vec3(
(chunk->x + 1) * CHUNK_W, INFINITY, (chunk->z + 1) * CHUNK_D
)
);
auto entities = level->entities->getAllInside(aabb); auto entities = level->entities->getAllInside(aabb);
auto root = dv::object(); auto root = dv::object();
root["data"] = level->entities->serialize(entities); root["data"] = level->entities->serialize(entities);
if (!entities.empty()) { if (!entities.empty()) {
level->entities->despawn(std::move(entities));
chunk->flags.entities = true; chunk->flags.entities = true;
} }
level->getWorld()->wfile->getRegions().put( level->getWorld()->wfile->getRegions().put(

View File

@ -8,6 +8,7 @@
#include <glm/gtx/hash.hpp> #include <glm/gtx/hash.hpp>
#include "voxel.hpp" #include "voxel.hpp"
#include "delegates.hpp"
class Chunk; class Chunk;
class Level; class Level;
@ -30,10 +31,14 @@ class GlobalChunks {
std::unordered_map<uint64_t, std::shared_ptr<Chunk>> chunksMap; std::unordered_map<uint64_t, std::shared_ptr<Chunk>> chunksMap;
std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> pinnedChunks; std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> pinnedChunks;
std::unordered_map<ptrdiff_t, int> refCounters; std::unordered_map<ptrdiff_t, int> refCounters;
consumer<Chunk&> onUnload;
public: public:
GlobalChunks(Level* level); GlobalChunks(Level* level);
~GlobalChunks() = default; ~GlobalChunks() = default;
void setOnUnload(consumer<Chunk&> onUnload);
std::shared_ptr<Chunk> fetch(int x, int z); std::shared_ptr<Chunk> fetch(int x, int z);
std::shared_ptr<Chunk> create(int x, int z); std::shared_ptr<Chunk> create(int x, int z);

View File

@ -58,6 +58,10 @@ Level::Level(
events->listen(LevelEventType::EVT_CHUNK_HIDDEN, [this](LevelEventType, Chunk* chunk) { events->listen(LevelEventType::EVT_CHUNK_HIDDEN, [this](LevelEventType, Chunk* chunk) {
chunks->decref(chunk); chunks->decref(chunk);
}); });
chunks->setOnUnload([this](const Chunk& chunk) {
AABB aabb = chunk.getAABB();
entities->despawn(entities->getAllInside(aabb));
});
inventories = std::make_unique<Inventories>(*this); inventories = std::make_unique<Inventories>(*this);
} }