diff --git a/src/engine.cpp b/src/engine.cpp index 6bcd2542..a21bd8f7 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -261,4 +261,4 @@ EnginePaths* Engine::getPaths() { std::shared_ptr Engine::getScreen() { return screen; -} \ No newline at end of file +} diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 11729085..e2d3a6ad 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -559,21 +559,6 @@ bool WorldFiles::readWorldInfo(World* world) { return true; } -void WorldFiles::writePlayer(std::shared_ptr player) { - files::write_json(getPlayerFile(), player->serialize().release()); -} - -bool WorldFiles::readPlayer(std::shared_ptr player) { - fs::path file = getPlayerFile(); - if (!fs::is_regular_file(file)) { - std::cerr << "warning: player.json does not exists" << std::endl; - return false; - } - - player->deserialize(files::read_json(file).get()); - return true; -} - void WorldFiles::addPack(const World* world, const std::string& id) { fs::path file = getPacksFile(); if (!fs::is_regular_file(file)) { diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 3269d4dd..c519c8bc 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -139,14 +139,9 @@ public: chunk_inventories_map fetchInventories(int x, int z); bool readWorldInfo(World* world); - bool readPlayer(std::shared_ptr player); void writeRegion(int x, int y, WorldRegion* entry, fs::path file, int layer); - /// @brief Write player data to world files - /// @param player target player - void writePlayer(std::shared_ptr player); - /// @brief Write all unsaved data to world files /// @param world target world /// @param content world content @@ -169,4 +164,4 @@ public: static const char* WORLD_FILE; }; -#endif /* FILES_WORLDFILES_H_ */ \ No newline at end of file +#endif /* FILES_WORLDFILES_H_ */ diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 109de8f5..ed1744ab 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -34,9 +34,10 @@ #include "graphics/Skybox.h" #include "graphics/ChunksRenderer.h" -WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend) +WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player) : engine(engine), - level(frontend->getLevel()) + level(frontend->getLevel()), + player(player) { frustumCulling = std::make_unique(); lineBatch = std::make_unique(); @@ -174,7 +175,6 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible shader->uniform3f("u_cameraPos", camera->position); shader->uniform1i("u_cubemap", 1); { - auto player = level->player; auto inventory = player->getInventory(); ItemStack& stack = inventory->getSlot(player->getChosenSlot()); ItemDef* item = indices->getItemDef(stack.getItemId()); @@ -191,7 +191,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible skybox->bind(); atlas->getTexture()->bind(); - drawChunks(level->chunks, camera, shader); + drawChunks(level->chunks.get(), camera, shader); // Selected block if (PlayerController::selectedBlockId != -1 && hudVisible){ @@ -213,7 +213,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible const glm::vec3 center = pos + hitbox.center(); const glm::vec3 size = hitbox.size(); lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f)); - if (level->player->debug) { + if (player->debug) { lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)); } } @@ -222,7 +222,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible skybox->unbind(); } - if (hudVisible && level->player->debug) { + if (hudVisible && player->debug) { GfxContext ctx = pctx.sub(); ctx.depthTest(true); @@ -230,7 +230,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible if (settings.debug.showChunkBorders){ linesShader->uniformMatrix("u_projview", camera->getProjView()); - glm::vec3 coord = level->player->camera->position; + glm::vec3 coord = player->camera->position; if (coord.x < 0) coord.x--; if (coord.z < 0) coord.z--; int cx = floordiv((int)coord.x, CHUNK_W); diff --git a/src/frontend/WorldRenderer.h b/src/frontend/WorldRenderer.h index 289f3b2f..2359f139 100644 --- a/src/frontend/WorldRenderer.h +++ b/src/frontend/WorldRenderer.h @@ -14,6 +14,7 @@ #include "../graphics/GfxContext.h" class Level; +class Player; class Camera; class Batch3D; class LineBatch; @@ -29,6 +30,7 @@ class Skybox; class WorldRenderer { Engine* engine; Level* level; + Player* player; std::unique_ptr frustumCulling; std::unique_ptr lineBatch; std::unique_ptr renderer; @@ -37,7 +39,7 @@ class WorldRenderer { bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling); void drawChunks(Chunks* chunks, Camera* camera, Shader* shader); public: - WorldRenderer(Engine* engine, LevelFrontend* frontend); + WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player); ~WorldRenderer(); void draw(const GfxContext& context, Camera* camera, bool hudVisible); diff --git a/src/frontend/graphics/ChunksRenderer.cpp b/src/frontend/graphics/ChunksRenderer.cpp index fee415fe..6753bca5 100644 --- a/src/frontend/graphics/ChunksRenderer.cpp +++ b/src/frontend/graphics/ChunksRenderer.cpp @@ -84,14 +84,14 @@ void ChunksRenderer::threadLoop(int index) { } void ChunksRenderer::process(std::shared_ptr chunk, BlocksRenderer& renderer) { - renderer.build(chunk.get(), level->chunksStorage); + renderer.build(chunk.get(), level->chunksStorage.get()); } std::shared_ptr ChunksRenderer::render(std::shared_ptr chunk, bool important) { chunk->setModified(false); if (important) { - Mesh* mesh = renderer->render(chunk.get(), level->chunksStorage); + Mesh* mesh = renderer->render(chunk.get(), level->chunksStorage.get()); auto sptr = std::shared_ptr(mesh); meshes[glm::ivec2(chunk->x, chunk->z)] = sptr; return sptr; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 41584ab3..8ea22a2b 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -40,6 +40,7 @@ #include "gui/UINode.h" #include "gui/GUI.h" #include "ContentGfxCache.h" +#include "menu/menu.h" #include "screens.h" #include "WorldRenderer.h" #include "BlocksPreview.h" @@ -122,11 +123,10 @@ std::shared_ptr Hud::createDebugPanel(Engine* engine) { L" visible: "+std::to_wstring(level->chunks->visible); })); panel->add(create_label([=](){ - auto player = level->player; auto* indices = level->content->getIndices(); auto def = indices->getBlockDef(player->selectedVoxel.id); std::wstringstream stream; - stream << std::hex << level->player->selectedVoxel.states; + stream << std::hex << player->selectedVoxel.states; if (def) { stream << L" (" << util::str2wstr_utf8(def->name) << L")"; } @@ -151,19 +151,19 @@ std::shared_ptr Hud::createDebugPanel(Engine* engine) { // Coord input auto box = std::make_shared(L""); box->setTextSupplier([=]() { - Hitbox* hitbox = level->player->hitbox.get(); + Hitbox* hitbox = player->hitbox.get(); return util::to_wstring(hitbox->position[ax], 2); }); box->setTextConsumer([=](std::wstring text) { try { - glm::vec3 position = level->player->hitbox->position; + glm::vec3 position = player->hitbox->position; position[ax] = std::stoi(text); - level->player->teleport(position); + player->teleport(position); } catch (std::invalid_argument& _){ } }); box->setOnEditStart([=](){ - Hitbox* hitbox = level->player->hitbox.get(); + Hitbox* hitbox = player->hitbox.get(); box->setText(std::to_wstring(int(hitbox->position[ax]))); }); box->setSize(glm::vec2(230, 27)); @@ -212,7 +212,6 @@ std::shared_ptr Hud::createContentAccess() { auto level = frontend->getLevel(); auto content = level->content; auto indices = content->getIndices(); - auto player = level->player; auto inventory = player->getInventory(); int itemsCount = indices->countItemDefs(); @@ -239,8 +238,6 @@ std::shared_ptr Hud::createContentAccess() { } std::shared_ptr Hud::createHotbar() { - auto level = frontend->getLevel(); - auto player = level->player; auto inventory = player->getInventory(); SlotLayout slotLayout(-1, glm::vec2(), false, false, nullptr, nullptr); @@ -254,10 +251,12 @@ std::shared_ptr Hud::createHotbar() { return view; } -Hud::Hud(Engine* engine, LevelFrontend* frontend) - : assets(engine->getAssets()), +Hud::Hud(Engine* engine, LevelFrontend* frontend, Player* player) + : engine(engine), + assets(engine->getAssets()), gui(engine->getGUI()), - frontend(frontend) + frontend(frontend), + player(player) { auto menu = gui->getMenu(); @@ -335,7 +334,6 @@ void Hud::cleanup() { void Hud::update(bool visible) { auto level = frontend->getLevel(); - auto player = level->player; auto menu = gui->getMenu(); debugPanel->setVisible(player->debug && visible); @@ -419,8 +417,6 @@ void Hud::update(bool visible) { * Show inventory on the screen and turn on inventory mode blocking movement */ void Hud::openInventory() { - auto level = frontend->getLevel(); - auto player = level->player; auto inventory = player->getInventory(); inventoryOpen = true; @@ -472,8 +468,6 @@ void Hud::openPermanent(UiDocument* doc) { auto invview = std::dynamic_pointer_cast(root); if (invview) { - auto level = frontend->getLevel(); - auto player = level->player; auto inventory = player->getInventory(); invview->bind(inventory, frontend, interaction.get()); } @@ -548,9 +542,6 @@ void Hud::remove(std::shared_ptr node) { } void Hud::draw(const GfxContext& ctx){ - auto level = frontend->getLevel(); - auto player = level->player; - const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); const uint height = viewport.getHeight(); @@ -568,7 +559,7 @@ void Hud::draw(const GfxContext& ctx){ hotbarView->setSelected(player->getChosenSlot()); // Crosshair - if (!pause && Events::_cursor_locked && !level->player->debug) { + if (!pause && Events::_cursor_locked && !player->debug) { GfxContext chctx = ctx.sub(); chctx.blendMode(blendmode::inversion); auto texture = assets->getTexture("gui/crosshair"); @@ -583,7 +574,7 @@ void Hud::draw(const GfxContext& ctx){ } // Delta-time visualizer - if (level->player->debug) { + if (player->debug) { batch->texture(nullptr); const int dmwidth = 256; const float dmscale = 4000.0f; @@ -648,6 +639,7 @@ void Hud::setPause(bool pause) { auto menu = gui->getMenu(); if (pause) { + menus::create_pause_panel(engine, frontend->getLevel()); menu->setPage("pause"); } else { menu->reset(); @@ -656,6 +648,6 @@ void Hud::setPause(bool pause) { menu->setVisible(pause); } -std::shared_ptr Hud::getPlayer() const { - return frontend->getLevel()->player; +Player* Hud::getPlayer() const { + return player; } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index 02e3e2bb..e9171eeb 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -65,6 +65,7 @@ public: }; class Hud { + Engine* engine; Assets* assets; std::unique_ptr uicamera; @@ -84,6 +85,7 @@ class Hud { std::shared_ptr grabbedItemView; gui::GUI* gui; LevelFrontend* frontend; + Player* player; std::vector elements; @@ -98,7 +100,7 @@ class Hud { void cleanup(); public: - Hud(Engine* engine, LevelFrontend* frontend); + Hud(Engine* engine, LevelFrontend* frontend, Player* player); ~Hud(); void update(bool hudVisible); @@ -118,7 +120,7 @@ public: void remove(HudElement& element); void remove(std::shared_ptr node); - std::shared_ptr getPlayer() const; + Player* getPlayer() const; }; #endif /* SRC_HUD_H_ */ diff --git a/src/frontend/menu/menu.h b/src/frontend/menu/menu.h index a5bd6bfa..d1b8b9bf 100644 --- a/src/frontend/menu/menu.h +++ b/src/frontend/menu/menu.h @@ -19,4 +19,4 @@ namespace menus { void refresh_menus(Engine* engine); } -#endif // FRONTEND_MENU_MENU_H_ \ No newline at end of file +#endif // FRONTEND_MENU_MENU_H_ diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index c2d761f1..8427c000 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -87,17 +87,15 @@ void MenuScreen::draw(float delta) { static bool backlight; -LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine), level(level){ - menus::create_pause_panel(engine, level); - +LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) { auto& settings = engine->getSettings(); auto assets = engine->getAssets(); controller = std::make_unique(settings, level); frontend = std::make_unique(level, assets); - worldRenderer = std::make_unique(engine, frontend.get()); - hud = std::make_unique(engine, frontend.get()); - + worldRenderer = std::make_unique(engine, frontend.get(), controller->getPlayer()); + hud = std::make_unique(engine, frontend.get(), controller->getPlayer()); + backlight = settings.graphics.backlight; animator = std::make_unique(); @@ -119,8 +117,8 @@ LevelScreen::~LevelScreen() { std::cout << "-- writing world" << std::endl; scripting::on_frontend_close(); controller->onWorldSave(); - auto world = level->getWorld(); - world->write(level.get()); + auto world = controller->getLevel()->getWorld(); + world->write(controller->getLevel()); controller->onWorldQuit(); engine->getPaths()->setWorldFolder(fs::path()); } @@ -134,10 +132,10 @@ void LevelScreen::updateHotkeys() { hudVisible = !hudVisible; } if (Events::jpressed(keycode::F3)) { - level->player->debug = !level->player->debug; + controller->getPlayer()->debug = !controller->getPlayer()->debug; } if (Events::jpressed(keycode::F5)) { - level->chunks->saveAndClear(); + controller->getLevel()->chunks->saveAndClear(); } } @@ -153,14 +151,14 @@ void LevelScreen::update(float delta) { // TODO: subscribe for setting change EngineSettings& settings = engine->getSettings(); - level->player->camera->setFov(glm::radians(settings.camera.fov)); + controller->getPlayer()->camera->setFov(glm::radians(settings.camera.fov)); if (settings.graphics.backlight != backlight) { - level->chunks->saveAndClear(); + controller->getLevel()->chunks->saveAndClear(); backlight = settings.graphics.backlight; } if (!hud->isPause()) { - level->world->updateTimers(delta); + controller->getLevel()->world->updateTimers(delta); animator->update(delta); } controller->update(delta, !inputLocked, hud->isPause()); @@ -168,7 +166,7 @@ void LevelScreen::update(float delta) { } void LevelScreen::draw(float delta) { - auto camera = level->player->currentCamera; + auto camera = controller->getPlayer()->currentCamera; Viewport viewport(Window::width, Window::height); GfxContext ctx(nullptr, viewport, batch.get()); @@ -177,12 +175,8 @@ void LevelScreen::draw(float delta) { if (hudVisible) { hud->draw(ctx); - if (level->player->debug) { + if (controller->getPlayer()->debug) { hud->drawDebug(1 / delta); } } } - -Level* LevelScreen::getLevel() const { - return level.get(); -} diff --git a/src/frontend/screens.h b/src/frontend/screens.h index 464b7489..126b736d 100644 --- a/src/frontend/screens.h +++ b/src/frontend/screens.h @@ -38,7 +38,6 @@ public: }; class LevelScreen : public Screen { - std::unique_ptr level; std::unique_ptr frontend; std::unique_ptr hud; std::unique_ptr worldRenderer; @@ -53,8 +52,6 @@ public: void update(float delta) override; void draw(float delta) override; - - Level* getLevel() const; }; #endif // FRONTEND_SCREENS_H_ diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index b3d9bfd1..f95e5ac0 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -53,8 +53,8 @@ int Clock::getTickId() const { BlocksController::BlocksController(Level* level, uint padding) : level(level), - chunks(level->chunks), - lighting(level->lighting), + chunks(level->chunks.get()), + lighting(level->lighting.get()), randTickClock(20, 3), blocksTickClock(20, 1), padding(padding) { diff --git a/src/logic/BlocksController.h b/src/logic/BlocksController.h index bb837938..00934617 100644 --- a/src/logic/BlocksController.h +++ b/src/logic/BlocksController.h @@ -28,6 +28,7 @@ public: int getTickId() const; }; +/* BlocksController manages block updates and block data (aka inventories) */ class BlocksController { Level* level; Chunks* chunks; diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index ed4bc7c8..7eefe0ab 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -24,8 +24,8 @@ const uint MIN_SURROUNDING = 9; ChunksController::ChunksController(Level* level, uint padding) : level(level), - chunks(level->chunks), - lighting(level->lighting), + chunks(level->chunks.get()), + lighting(level->lighting.get()), padding(padding), generator(WorldGenerators::createGenerator(level->getWorld()->getGenerator(), level->content)) { } @@ -131,4 +131,4 @@ void ChunksController::createChunk(int x, int z) { } chunk->setLoaded(true); chunk->setReady(true); -} \ No newline at end of file +} diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 94a82062..4e938dec 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -1,32 +1,32 @@ #include "LevelController.h" #include "../world/Level.h" - -#include "PlayerController.h" -#include "BlocksController.h" -#include "ChunksController.h" +#include "../physics/Hitbox.h" #include "scripting/scripting.h" #include "../interfaces/Object.h" LevelController::LevelController(EngineSettings& settings, Level* level) - : settings(settings), level(level) { - blocks = std::make_unique(level, settings.chunks.padding); - chunks = std::make_unique(level, settings.chunks.padding); - player = std::make_unique(level, settings, blocks.get()); + : settings(settings), level(level), + blocks(std::make_unique(level, settings.chunks.padding)), + chunks(std::make_unique(level, settings.chunks.padding)), + player(std::make_unique(level, settings, blocks.get())) { scripting::on_world_load(level, blocks.get()); } -LevelController::~LevelController() { -} - void LevelController::update(float delta, bool input, bool pause) { player->update(delta, input, pause); - level->update(); + glm::vec3 position = player->getPlayer()->hitbox->position; + level->loadMatrix(position.x, position.z, settings.chunks.loadDistance + settings.chunks.padding * 2); chunks->update(settings.chunks.loadSpeed); // erease null pointers - level->objects.remove_if([](auto obj) { return obj == nullptr; }); + level->objects.erase( + std::remove_if( + level->objects.begin(), level->objects.end(), + [](auto obj) { return obj == nullptr; }), + level->objects.end() + ); if (!pause) { // update all objects that needed @@ -49,3 +49,11 @@ void LevelController::onWorldSave() { void LevelController::onWorldQuit() { scripting::on_world_quit(); } + +Level* LevelController::getLevel() { + return level.get(); +} + +Player* LevelController::getPlayer() { + return player->getPlayer(); +} diff --git a/src/logic/LevelController.h b/src/logic/LevelController.h index bd5ce183..d70d49a0 100644 --- a/src/logic/LevelController.h +++ b/src/logic/LevelController.h @@ -4,22 +4,23 @@ #include #include "../settings.h" +#include "PlayerController.h" +#include "BlocksController.h" +#include "ChunksController.h" + class Level; -class BlocksController; -class ChunksController; -class PlayerController; +class Player; /* LevelController manages other controllers */ class LevelController { EngineSettings& settings; - Level* level; + std::unique_ptr level; // Sub-controllers std::unique_ptr blocks; std::unique_ptr chunks; std::unique_ptr player; public: LevelController(EngineSettings& settings, Level* level); - ~LevelController(); /* @param delta time elapsed since the last update @@ -32,6 +33,9 @@ public: void onWorldSave(); void onWorldQuit(); + + Level* getLevel(); + Player* getPlayer(); }; #endif // LOGIC_LEVEL_CONTROLLER_H_ diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index ab44336e..5ff48153 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -142,8 +142,8 @@ PlayerController::PlayerController( const EngineSettings& settings, BlocksController* blocksController) : level(level), - player(level->player), - camControl(level->player, settings.camera), + player(level->getObject(0)), + camControl(player, settings.camera), blocksController(blocksController) { } @@ -186,7 +186,7 @@ void PlayerController::updateCamera(float delta, bool movement) { if (movement) { camControl.updateMouse(input); } - camControl.update(input, delta, level->chunks); + camControl.update(input, delta, level->chunks.get()); } void PlayerController::resetKeyboard() { @@ -207,9 +207,8 @@ void PlayerController::updateControls(float delta){ void PlayerController::updateInteraction(){ auto indices = level->content->getIndices(); - Chunks* chunks = level->chunks; - Player* player = level->player.get(); - Lighting* lighting = level->lighting; + Chunks* chunks = level->chunks.get(); + Lighting* lighting = level->lighting.get(); Camera* camera = player->camera.get(); glm::vec3 end; glm::ivec3 iend; @@ -269,24 +268,24 @@ void PlayerController::updateInteraction(){ if (lclick) { if (!input.shift && item->rt.funcsset.on_block_break_by) { - if (scripting::on_item_break_block(player, item, x, y, z)) + if (scripting::on_item_break_block(player.get(), item, x, y, z)) return; } } Block* target = indices->getBlockDef(vox->id); if (lclick && target->breakable){ - blocksController->breakBlock(player, target, x, y, z); + blocksController->breakBlock(player.get(), target, x, y, z); } if (rclick) { if (!input.shift && item->rt.funcsset.on_use_on_block) { - if (scripting::on_item_use_on_block(player, item, x, y, z)) + if (scripting::on_item_use_on_block(player.get(), item, x, y, z)) return; } } if (def && rclick){ if (!input.shift && target->rt.funcsset.oninteract) { - if (scripting::on_block_interact(player, target, x, y, z)) + if (scripting::on_block_interact(player.get(), target, x, y, z)) return; } if (!target->replaceable){ @@ -310,7 +309,7 @@ void PlayerController::updateInteraction(){ chunks->set(x, y, z, chosenBlock, states); lighting->onBlockSet(x,y,z, chosenBlock); if (def->rt.funcsset.onplaced) { - scripting::on_block_placed(player, def, x, y, z); + scripting::on_block_placed(player.get(), def, x, y, z); } blocksController->updateSides(x, y, z); } @@ -337,3 +336,7 @@ void PlayerController::updateInteraction(){ selectedBlockStates = 0; } } + +Player* PlayerController::getPlayer() { + return player.get(); +} diff --git a/src/logic/PlayerController.h b/src/logic/PlayerController.h index a1479820..2bf3c437 100644 --- a/src/logic/PlayerController.h +++ b/src/logic/PlayerController.h @@ -49,6 +49,8 @@ public: const EngineSettings& settings, BlocksController* blocksController); void update(float delta, bool input, bool pause); + + Player* getPlayer(); }; #endif /* PLAYER_CONTROL_H_ */ diff --git a/src/logic/scripting/lua/libplayer.cpp b/src/logic/scripting/lua/libplayer.cpp index f51c3e06..05e70635 100644 --- a/src/logic/scripting/lua/libplayer.cpp +++ b/src/logic/scripting/lua/libplayer.cpp @@ -11,9 +11,9 @@ /* == player library ==*/ int l_player_get_pos(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; - glm::vec3 pos = scripting::level->player->hitbox->position; + auto player = scripting::level->getObject(playerid); + if (!player) return 0; + glm::vec3 pos = player->hitbox->position; lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); lua_pushnumber(L, pos.z); @@ -22,20 +22,19 @@ int l_player_get_pos(lua_State* L) { int l_player_set_pos(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; lua::luanumber x = lua_tonumber(L, 2); lua::luanumber y = lua_tonumber(L, 3); lua::luanumber z = lua_tonumber(L, 4); - scripting::level->player->hitbox->position = glm::vec3(x, y, z); + auto player = scripting::level->getObject(playerid); + if (player) player->hitbox->position = glm::vec3(x, y, z); return 0; } int l_player_get_vel(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; - glm::vec3 vel = scripting::level->player->hitbox->velocity; + auto player = scripting::level->getObject(playerid); + if (!player) return 0; + glm::vec3 vel = player->hitbox->velocity; lua_pushnumber(L, vel.x); lua_pushnumber(L, vel.y); lua_pushnumber(L, vel.z); @@ -44,20 +43,19 @@ int l_player_get_vel(lua_State* L) { int l_player_set_vel(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; lua::luanumber x = lua_tonumber(L, 2); lua::luanumber y = lua_tonumber(L, 3); lua::luanumber z = lua_tonumber(L, 4); - scripting::level->player->hitbox->velocity = glm::vec3(x, y, z); + auto player = scripting::level->getObject(playerid); + if (player) player->hitbox->velocity = glm::vec3(x, y, z); return 0; } int l_player_get_rot(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; - glm::vec2 rot = scripting::level->player->cam; + auto player = scripting::level->getObject(playerid); + if (!player) return 0; + glm::vec2 rot = player->cam; lua_pushnumber(L, rot.x); lua_pushnumber(L, rot.y); return 2; @@ -65,11 +63,11 @@ int l_player_get_rot(lua_State* L) { int l_player_set_rot(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; + auto player = scripting::level->getObject(playerid); + if (!player) return 0; lua::luanumber x = lua_tonumber(L, 2); lua::luanumber y = lua_tonumber(L, 3); - glm::vec2& cam = scripting::level->player->cam; + glm::vec2& cam = player->cam; cam.x = x; cam.y = y; return 0; @@ -77,9 +75,8 @@ int l_player_set_rot(lua_State* L) { int l_player_get_inv(lua_State* L) { int playerid = lua_tointeger(L, 1); - if (playerid != 1) - return 0; - auto player = scripting::level->player; + auto player = scripting::level->getObject(playerid); + if (!player) return 0; lua_pushinteger(L, player->getInventory()->getId()); lua_pushinteger(L, player->getChosenSlot()); return 2; diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 6ea8da5b..b659be19 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -8,6 +8,7 @@ #include "../../files/files.h" #include "../../util/timeutil.h" #include "../../world/Level.h" +#include "../../objects/Player.h" #include "../../voxels/Block.h" #include "../../items/ItemDef.h" #include "../../items/Inventory.h" @@ -160,7 +161,7 @@ void scripting::on_block_placed(Player* player, const Block* block, int x, int y std::string name = block->name+".placed"; if (state->getglobal(name)) { state->pushivec3(x, y, z); - state->pushinteger(1); // playerid placeholder + state->pushinteger(player->getId()); state->callNoThrow(4); } } @@ -169,7 +170,7 @@ void scripting::on_block_broken(Player* player, const Block* block, int x, int y std::string name = block->name+".broken"; if (state->getglobal(name)) { state->pushivec3(x, y, z); - state->pushinteger(1); // playerid placeholder + state->pushinteger(player->getId()); state->callNoThrow(4); } } @@ -178,7 +179,7 @@ bool scripting::on_block_interact(Player* player, const Block* block, int x, int std::string name = block->name+".interact"; if (state->getglobal(name)) { state->pushivec3(x, y, z); - state->pushinteger(1); // playerid placeholder + state->pushinteger(player->getId()); if (state->callNoThrow(4)) { return state->toboolean(-1); } @@ -190,7 +191,7 @@ bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, std::string name = item->name+".useon"; if (state->getglobal(name)) { state->pushivec3(x, y, z); - state->pushinteger(1); // playerid placeholder + state->pushinteger(player->getId()); if (state->callNoThrow(4)) { return state->toboolean(-1); } @@ -202,7 +203,7 @@ bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, std::string name = item->name+".blockbreakby"; if (state->getglobal(name)) { state->pushivec3(x, y, z); - state->pushinteger(1); // playerid placeholder + state->pushinteger(player->getId()); if (state->callNoThrow(4)) { return state->toboolean(-1); } diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 62c9d712..93b294cd 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -78,7 +78,7 @@ void Player::updateInput( float vel = std::max(glm::length(hitbox->velocity * 0.25f), 1.0f); int substeps = int(delta * vel * 1000); substeps = std::min(100, std::max(1, substeps)); - level->physics->step(level->chunks, hitbox.get(), + level->physics->step(level->chunks.get(), hitbox.get(), delta, substeps, crouch, flight ? 0.0f : 1.0f, !noclip); diff --git a/src/objects/Player.h b/src/objects/Player.h index bea94c2b..05020637 100644 --- a/src/objects/Player.h +++ b/src/objects/Player.h @@ -73,7 +73,7 @@ public: static void convert(dynamic::Map* data, const ContentLUT* lut); inline int getId() const { - return 1; + return objectUID; } }; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index e65230b8..3a16b127 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -17,8 +17,8 @@ #include #include -Chunks::Chunks(int w, int d, - int ox, int oz, +Chunks::Chunks(uint32_t w, uint32_t d, + int32_t ox, int32_t oz, WorldFiles* wfile, LevelEvents* events, const Content* content) @@ -32,7 +32,7 @@ Chunks::Chunks(int w, int d, chunksCount = 0; } -voxel* Chunks::get(int x, int y, int z){ +voxel* Chunks::get(int32_t x, int32_t y, int32_t z) { x -= ox * CHUNK_W; z -= oz * CHUNK_D; int cx = floordiv(x, CHUNK_W); @@ -71,28 +71,28 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){ return nullptr; } -bool Chunks::isSolidBlock(int x, int y, int z) { +bool Chunks::isSolidBlock(int32_t x, int32_t y, int32_t z) { voxel* v = get(x, y, z); if (v == nullptr) return false; return contentIds->getBlockDef(v->id)->rt.solid; } -bool Chunks::isReplaceableBlock(int x, int y, int z) { +bool Chunks::isReplaceableBlock(int32_t x, int32_t y, int32_t z) { voxel* v = get(x, y, z); if (v == nullptr) return false; return contentIds->getBlockDef(v->id)->replaceable; } -bool Chunks::isObstacleBlock(int x, int y, int z) { +bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) { voxel* v = get(x, y, z); if (v == nullptr) return false; return contentIds->getBlockDef(v->id)->obstacle; } -ubyte Chunks::getLight(int x, int y, int z, int channel){ +ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel){ x -= ox * CHUNK_W; z -= oz * CHUNK_D; int cx = floordiv(x, CHUNK_W); @@ -106,10 +106,10 @@ ubyte Chunks::getLight(int x, int y, int z, int channel){ int lx = x - cx * CHUNK_W; int ly = y - cy * CHUNK_H; int lz = z - cz * CHUNK_D; - return chunk->lightmap.get(lx,ly,lz, channel); + return chunk->lightmap.get(lx, ly, lz, channel); } -light_t Chunks::getLight(int x, int y, int z){ +light_t Chunks::getLight(int32_t x, int32_t y, int32_t z){ x -= ox * CHUNK_W; z -= oz * CHUNK_D; int cx = floordiv(x, CHUNK_W); @@ -126,7 +126,7 @@ light_t Chunks::getLight(int x, int y, int z){ return chunk->lightmap.get(lx,ly,lz); } -Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ +Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z){ if (y < 0 || y >= CHUNK_H) return nullptr; x -= ox * CHUNK_W; @@ -146,7 +146,7 @@ Chunk* Chunks::getChunk(int x, int z){ return chunks[z * w + x].get(); } -void Chunks::set(int x, int y, int z, int id, uint8_t states){ +void Chunks::set(int32_t x, int32_t y, int32_t z, uint32_t id, uint8_t states){ if (y < 0 || y >= CHUNK_H) return; x -= ox * CHUNK_W; @@ -396,7 +396,7 @@ glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDis } -void Chunks::setCenter(int x, int z) { +void Chunks::setCenter(int32_t x, int32_t z) { int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); cx -= ox + w / 2; @@ -406,7 +406,7 @@ void Chunks::setCenter(int x, int z) { } } -void Chunks::translate(int dx, int dz){ +void Chunks::translate(int32_t dx, int32_t dz) { for (uint i = 0; i < volume; i++){ chunksSecond[i] = nullptr; } @@ -433,7 +433,7 @@ void Chunks::translate(int dx, int dz){ oz += dz; } -void Chunks::resize(int newW, int newD) { +void Chunks::resize(uint32_t newW, uint32_t newD) { if (newW < w) { int delta = w - newW; translate(delta / 2, 0); @@ -461,7 +461,7 @@ void Chunks::resize(int newW, int newD) { chunksSecond = std::move(newChunksSecond); } -void Chunks::_setOffset(int x, int z){ +void Chunks::_setOffset(int32_t x, int32_t z) { ox = x; oz = z; } diff --git a/src/voxels/Chunks.h b/src/voxels/Chunks.h index 305650b4..b129ba71 100644 --- a/src/voxels/Chunks.h +++ b/src/voxels/Chunks.h @@ -26,23 +26,23 @@ public: size_t volume; size_t chunksCount; size_t visible; - int w,d; - int ox,oz; + uint32_t w, d; + int32_t ox, oz; WorldFiles* worldFiles; LevelEvents* events; - Chunks(int w, int d, int ox, int oz, + Chunks(uint32_t w, uint32_t d, int32_t ox, int32_t oz, WorldFiles* worldFiles, LevelEvents* events, const Content* content); ~Chunks() = default; bool putChunk(std::shared_ptr chunk); - Chunk* getChunk(int x, int z); - Chunk* getChunkByVoxel(int x, int y, int z); - voxel* get(int x, int y, int z); - light_t getLight(int x, int y, int z); - ubyte getLight(int x, int y, int z, int channel); - void set(int x, int y, int z, int id, uint8_t states); + Chunk* getChunk(int32_t x, int32_t z); + Chunk* getChunkByVoxel(int32_t x, int32_t y, int32_t z); + voxel* get(int32_t x, int32_t y, int32_t z); + light_t getLight(int32_t x, int32_t y, int32_t z); + ubyte getLight(int32_t x, int32_t y, int32_t z, int channel); + void set(int32_t x, int32_t y, int32_t z, uint32_t id, uint8_t states); voxel* rayCast(glm::vec3 start, glm::vec3 dir, @@ -54,16 +54,16 @@ public: glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist); const AABB* isObstacleAt(float x, float y, float z); - bool isSolidBlock(int x, int y, int z); - bool isReplaceableBlock(int x, int y, int z); - bool isObstacleBlock(int x, int y, int z); + bool isSolidBlock(int32_t x, int32_t y, int32_t z); + bool isReplaceableBlock(int32_t x, int32_t y, int32_t z); + bool isObstacleBlock(int32_t x, int32_t y, int32_t z); // does not move chunks inside - void _setOffset(int x, int z); + void _setOffset(int32_t x, int32_t z); - void setCenter(int x, int z); - void translate(int x, int z); - void resize(int newW, int newD); + void setCenter(int32_t x, int32_t z); + void translate(int32_t x, int32_t z); + void resize(uint32_t newW, uint32_t newD); void saveAndClear(); }; diff --git a/src/world/Level.cpp b/src/world/Level.cpp index e1b49712..4707908a 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -8,33 +8,25 @@ #include "../voxels/ChunksStorage.h" #include "../physics/Hitbox.h" #include "../physics/PhysicsSolver.h" -#include "../interfaces/Object.h" #include "../objects/Player.h" #include "../items/Inventory.h" #include "../items/Inventories.h" - -const float DEF_PLAYER_Y = 100.0f; -const float DEF_PLAYER_SPEED = 4.0f; -const int DEF_PLAYER_INVENTORY_SIZE = 40; - Level::Level(World* world, const Content* content, EngineSettings& settings) : world(world), content(content), - chunksStorage(new ChunksStorage(this)), - events(new LevelEvents()) , + chunksStorage(std::make_unique(this)), + physics(std::make_unique(glm::vec3(0, -22.6f, 0))), + events(std::make_unique()), settings(settings) { - objCounter = 0; - physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0)); - auto inv = std::make_shared(0, DEF_PLAYER_INVENTORY_SIZE); - player = spawnObject(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv); + auto inv = std::make_shared(world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE); + auto player = spawnObject(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv); - uint matrixSize = (settings.chunks.loadDistance+ - settings.chunks.padding) * 2; - chunks = new Chunks(matrixSize, matrixSize, 0, 0, - world->wfile.get(), events, content); - lighting = new Lighting(content, chunks); + uint matrixSize = (settings.chunks.loadDistance + settings.chunks.padding) * 2; + chunks = std::make_unique(matrixSize, matrixSize, 0, 0, + world->wfile.get(), events.get(), content); + lighting = std::make_unique(content, chunks.get()); events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) { this->chunksStorage->remove(chunk->x, chunk->z); @@ -45,26 +37,16 @@ Level::Level(World* world, const Content* content, EngineSettings& settings) } Level::~Level(){ - delete chunks; - delete events; - delete physics; - delete lighting; - delete chunksStorage; - - for(auto obj : objects) - { + for(auto obj : objects) { obj.reset(); } } -void Level::update() { - glm::vec3 position = player->hitbox->position; - chunks->setCenter(position.x, position.z); - - int matrixSize = (settings.chunks.loadDistance+ - settings.chunks.padding) * 2; - if (chunks->w != matrixSize) { - chunks->resize(matrixSize, matrixSize); +void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) { + chunks->setCenter(x, z); + radius = std::min(radius, settings.chunks.loadDistance + settings.chunks.padding * 2); + if (chunks->w != radius) { + chunks->resize(radius, radius); } } @@ -72,17 +54,3 @@ World* Level::getWorld() { return world.get(); } - -template -std::shared_ptr Level::spawnObject(Args&&... args) -{ - static_assert(std::is_base_of::value, "T must be a derived of Object class"); - std::shared_ptr tObj = std::make_shared(args...); - - std::shared_ptr obj = std::dynamic_pointer_cast(tObj); - objects.push_back(obj); - obj->objectUID = objCounter; - obj->spawned(); - objCounter += 1; - return tObj; -} diff --git a/src/world/Level.h b/src/world/Level.h index fbf9d283..7708921f 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -3,16 +3,17 @@ #include -#include "../typedefs.h" #include "../settings.h" -#include +#include "../interfaces/Object.h" #include -#include + +const float DEF_PLAYER_Y = 100.0f; +const float DEF_PLAYER_SPEED = 4.0f; +const int DEF_PLAYER_INVENTORY_SIZE = 40; class Content; class World; class Player; -class Object; class Chunks; class Inventory; class Inventories; @@ -21,21 +22,19 @@ class Lighting; class PhysicsSolver; class ChunksStorage; +/* A level, contains chunks and objects */ class Level { -private: - int objCounter; public: std::unique_ptr world; const Content* const content; - std::list> objects; - std::shared_ptr player; - Chunks* chunks; - ChunksStorage* chunksStorage; + std::vector> objects; + std::unique_ptr chunks; + std::unique_ptr chunksStorage; std::unique_ptr inventories; - PhysicsSolver* physics; - Lighting* lighting; - LevelEvents* events; + std::unique_ptr physics; + std::unique_ptr lighting; + std::unique_ptr events; const EngineSettings& settings; @@ -44,7 +43,7 @@ public: EngineSettings& settings); ~Level(); - void update(); + void loadMatrix(int32_t x, int32_t z, uint32_t radius); World* getWorld(); @@ -52,7 +51,24 @@ public: // @param T class that derives the Object class // @param args pass arguments needed for T class constructor template - std::shared_ptr spawnObject(Args&&... args); + std::shared_ptr spawnObject(Args&&... args) { + static_assert(std::is_base_of::value, "T must be a derived of Object class"); + std::shared_ptr tObj = std::make_shared(args...); + + std::shared_ptr obj = std::dynamic_pointer_cast(tObj); + obj->objectUID = objects.size(); + objects.push_back(obj); + obj->spawned(); + return tObj; + } + + template + std::shared_ptr getObject(uint64_t id) { + static_assert(std::is_base_of::value, "T must be a derived of Object class"); + if (id >= objects.size()) return nullptr; + std::shared_ptr object = std::dynamic_pointer_cast(objects[id]); + return object; + } }; #endif /* WORLD_LEVEL_H_ */ diff --git a/src/world/World.cpp b/src/world/World.cpp index 5cb6cc59..800518df 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -50,7 +50,7 @@ void World::updateTimers(float delta) { void World::write(Level* level) { const Content* content = level->content; - Chunks* chunks = level->chunks; + Chunks* chunks = level->chunks.get(); for (size_t i = 0; i < chunks->volume; i++) { auto chunk = chunks->chunks[i]; @@ -64,7 +64,16 @@ void World::write(Level* level) { } wfile->write(this, content); - wfile->writePlayer(level->player); + auto playerFile = dynamic::Map(); + { + auto& players = playerFile.putList("players"); + for (auto object : level->objects) { + if (std::shared_ptr player = std::dynamic_pointer_cast(object)) { + players.put(player->serialize().release()); + } + } + } + files::write_json(wfile->getPlayerFile(), &playerFile); } Level* World::create(std::string name, @@ -77,9 +86,6 @@ Level* World::create(std::string name, ) { auto world = new World(name, generator, directory, seed, settings, content, packs); auto level = new Level(world, content, settings); - auto inventory = level->player->getInventory(); - inventory->setId(world->getNextInventoryId()); - level->inventories->store(inventory); return level; } @@ -97,9 +103,28 @@ Level* World::load(fs::path directory, } auto level = new Level(world.get(), content, settings); - wfile->readPlayer(level->player); - level->inventories->store(level->player->getInventory()); - world.release(); + { + fs::path file = wfile->getPlayerFile(); + if (!fs::is_regular_file(file)) { + std::cerr << "warning: player.json does not exists" << std::endl; + } else { + auto playerFile = files::read_json(file); + if (playerFile->has("players")) { + level->objects.clear(); + auto players = playerFile->list("players"); + for (size_t i = 0; i < players->size(); i++) { + auto player = level->spawnObject(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, level->inventories->create(DEF_PLAYER_INVENTORY_SIZE)); + player->deserialize(players->map(i)); + level->inventories->store(player->getInventory()); + } + } else { + auto player = level->getObject(0); + player->deserialize(playerFile.get()); + level->inventories->store(player->getInventory()); + } + } + } + (void)world.release(); return level; } @@ -193,4 +218,4 @@ std::unique_ptr World::serialize() const { root->put("next-inventory-id", nextInventoryId); return root; -} \ No newline at end of file +} diff --git a/src/world/World.h b/src/world/World.h index c23ec03d..63c322d9 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -27,6 +27,7 @@ public: world_load_error(std::string message); }; +/* World - holds all world data except the level (chunks and objects) */ class World : Serializable { std::string name; std::string generator; @@ -35,7 +36,7 @@ class World : Serializable { const Content* const content; std::vector packs; - int64_t nextInventoryId = 1; + int64_t nextInventoryId = 0; public: std::unique_ptr wfile; @@ -157,4 +158,4 @@ public: void deserialize(dynamic::Map *src) override; }; -#endif /* WORLD_WORLD_H_ */ \ No newline at end of file +#endif /* WORLD_WORLD_H_ */