Merge branch 'main' into debugging-client
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "voxels/Chunks.hpp"
|
||||
#include "voxels/GlobalChunks.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "world/LevelEvents.hpp"
|
||||
#include "world/World.hpp"
|
||||
#include "world/generator/WorldGenerator.hpp"
|
||||
|
||||
@@ -172,13 +173,12 @@ void ChunksController::createChunk(const Player& player, int x, int z) const {
|
||||
auto chunk = level.chunks->create(x, z);
|
||||
player.chunks->putChunk(chunk);
|
||||
auto& chunkFlags = chunk->flags;
|
||||
|
||||
if (!chunkFlags.loaded) {
|
||||
generator->generate(chunk->voxels, x, z);
|
||||
chunkFlags.unsaved = true;
|
||||
}
|
||||
chunk->updateHeights();
|
||||
|
||||
level.events->trigger(LevelEventType::CHUNK_PRESENT, chunk.get());
|
||||
if (!chunkFlags.loadedLights) {
|
||||
Lighting::prebuildSkyLight(*chunk, *level.content.getIndices());
|
||||
}
|
||||
|
||||
@@ -366,7 +366,9 @@ void EngineController::reconfigPacks(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
auto world = controller->getLevel()->getWorld();
|
||||
auto level = controller->getLevel();
|
||||
auto world = level->getWorld();
|
||||
controller->processBeforeQuit();
|
||||
controller->saveWorld();
|
||||
|
||||
auto names = PacksManager::getNames(world->getPacks());
|
||||
|
||||
@@ -27,7 +27,8 @@ LevelController::LevelController(
|
||||
: settings(engine->getSettings()),
|
||||
level(std::move(levelPtr)),
|
||||
chunks(std::make_unique<ChunksController>(*level)),
|
||||
playerTickClock(20, 3) {
|
||||
playerTickClock(20, 3),
|
||||
localPlayer(clientPlayer) {
|
||||
|
||||
level->events->listen(LevelEventType::CHUNK_PRESENT, [](auto, Chunk* chunk) {
|
||||
scripting::on_chunk_present(*chunk, chunk->flags.loaded);
|
||||
@@ -121,6 +122,13 @@ void LevelController::update(float delta, bool pause) {
|
||||
level->entities->clean();
|
||||
}
|
||||
|
||||
void LevelController::processBeforeQuit() {
|
||||
if (localPlayer) {
|
||||
localPlayer->chunks->saveAndClear();
|
||||
}
|
||||
scripting::process_before_quit();
|
||||
}
|
||||
|
||||
void LevelController::saveWorld() {
|
||||
auto world = level->getWorld();
|
||||
if (world->isNameless()) {
|
||||
|
||||
@@ -20,6 +20,7 @@ class LevelController {
|
||||
std::unique_ptr<ChunksController> chunks;
|
||||
|
||||
util::Clock playerTickClock;
|
||||
Player* localPlayer;
|
||||
public:
|
||||
LevelController(Engine* engine, std::unique_ptr<Level> level, Player* clientPlayer);
|
||||
|
||||
@@ -27,6 +28,7 @@ public:
|
||||
/// @param pause is world and player simulation paused
|
||||
void update(float delta, bool pause);
|
||||
|
||||
void processBeforeQuit();
|
||||
void saveWorld();
|
||||
|
||||
void onWorldQuit();
|
||||
|
||||
@@ -730,7 +730,7 @@ static int l_pull_register_events(lua::State* L) {
|
||||
lua::createtable(L, events.size() * 4, 0);
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
const auto& event = events[i];
|
||||
lua::pushinteger(L, static_cast<int>(event.type) | event.id << 16);
|
||||
lua::pushinteger(L, static_cast<int>(event.bits) | event.id << 16);
|
||||
lua::rawseti(L, i * 4 + 1);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
|
||||
@@ -120,6 +120,7 @@ static int l_close_world(lua::State* L) {
|
||||
if (controller == nullptr) {
|
||||
throw std::runtime_error("no world open");
|
||||
}
|
||||
controller->processBeforeQuit();
|
||||
bool save_world = lua::toboolean(L, 1);
|
||||
if (save_world) {
|
||||
controller->saveWorld();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#define VC_ENABLE_REFLECTION
|
||||
#include "lua_type_canvas.hpp"
|
||||
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "logic/scripting/lua/lua_util.hpp"
|
||||
#include "coders/imageio.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
|
||||
@@ -284,6 +286,23 @@ static int l_sub(State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_encode(State* L) {
|
||||
auto canvas = touserdata<LuaCanvas>(L, 1);
|
||||
if (canvas == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
auto format = imageio::ImageFileFormat::PNG;
|
||||
if (lua::isstring(L, 2)) {
|
||||
auto name = lua::require_string(L, 2);
|
||||
if (!imageio::ImageFileFormatMeta.getItem(name, format)) {
|
||||
throw std::runtime_error("unsupported image file format");
|
||||
}
|
||||
}
|
||||
|
||||
auto buffer = imageio::encode(format, canvas->getData());
|
||||
return lua::create_bytearray(L, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"at", lua::wrap<l_at>},
|
||||
{"set", lua::wrap<l_set>},
|
||||
@@ -296,6 +315,7 @@ static std::unordered_map<std::string, lua_CFunction> methods {
|
||||
{"mul", lua::wrap<l_mul>},
|
||||
{"add", lua::wrap<l_add>},
|
||||
{"sub", lua::wrap<l_sub>},
|
||||
{"encode", lua::wrap<l_encode>},
|
||||
{"_set_data", lua::wrap<l_set_data>},
|
||||
};
|
||||
|
||||
@@ -354,6 +374,23 @@ static int l_meta_meta_call(lua::State* L) {
|
||||
);
|
||||
}
|
||||
|
||||
static int l_canvas_decode(lua::State* L) {
|
||||
auto bytes = bytearray_as_string(L, 1);
|
||||
auto formatName = require_lstring(L, 2);
|
||||
imageio::ImageFileFormat format;
|
||||
if (!imageio::ImageFileFormatMeta.getItem(formatName, format)) {
|
||||
throw std::runtime_error("unsupported image format");
|
||||
}
|
||||
return newuserdata<LuaCanvas>(
|
||||
L,
|
||||
nullptr,
|
||||
imageio::decode(
|
||||
format,
|
||||
{reinterpret_cast<const unsigned char*>(bytes.data()), bytes.size()}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
int LuaCanvas::createMetatable(State* L) {
|
||||
createtable(L, 0, 3);
|
||||
pushcfunction(L, lua::wrap<l_meta_index>);
|
||||
@@ -365,5 +402,8 @@ int LuaCanvas::createMetatable(State* L) {
|
||||
pushcfunction(L, lua::wrap<l_meta_meta_call>);
|
||||
setfield(L, "__call");
|
||||
setmetatable(L);
|
||||
|
||||
pushcfunction(L, lua::wrap<l_canvas_decode>);
|
||||
setfield(L, "decode");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ void scripting::initialize(Engine* engine) {
|
||||
|
||||
load_script(io::path("stdlib.lua"), true);
|
||||
load_script(io::path("classes.lua"), true);
|
||||
load_script(io::path("internal_events.lua"), true);
|
||||
}
|
||||
|
||||
class LuaCoroutine : public Process {
|
||||
@@ -340,6 +341,13 @@ void scripting::on_world_save() {
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::process_before_quit() {
|
||||
auto L = lua::get_main_state();
|
||||
if (lua::getglobal(L, "__vc_process_before_quit")) {
|
||||
lua::call_nothrow(L, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::on_world_quit() {
|
||||
auto L = lua::get_main_state();
|
||||
for (auto& pack : content_control->getAllContentPacks()) {
|
||||
@@ -674,6 +682,10 @@ void scripting::load_content_script(
|
||||
register_event(env, "on_block_tick", prefix + ".blocktick");
|
||||
funcsset.onblockstick =
|
||||
register_event(env, "on_blocks_tick", prefix + ".blockstick");
|
||||
funcsset.onblockpresent =
|
||||
register_event(env, "on_block_present", prefix + ".blockpresent");
|
||||
funcsset.onblockremoved =
|
||||
register_event(env, "on_block_removed", prefix + ".blockremoved");
|
||||
}
|
||||
|
||||
void scripting::load_content_script(
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace scripting {
|
||||
void on_world_load(LevelController* controller);
|
||||
void on_world_tick(int tps);
|
||||
void on_world_save();
|
||||
void process_before_quit();
|
||||
void on_world_quit();
|
||||
void cleanup(const std::vector<std::string>& nonReset);
|
||||
void on_blocks_tick(const Block& block, int tps);
|
||||
|
||||
Reference in New Issue
Block a user