diff --git a/src/interfaces/Object.hpp b/src/interfaces/Object.hpp deleted file mode 100644 index bb21fedb..00000000 --- a/src/interfaces/Object.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#include - -class Level; - -class Object { -private: - -public: - uint64_t objectUID; - bool shouldUpdate = true; - -public: - ~Object() { destroyed(); } - -public: - virtual void spawned() { } - virtual void update(float delta) { } - virtual void destroyed() { } -}; diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index bd8af15c..5d2ddd9b 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -5,7 +5,6 @@ #include "debug/Logger.hpp" #include "engine.hpp" #include "files/WorldFiles.hpp" -#include "interfaces/Object.hpp" #include "objects/Entities.hpp" #include "physics/Hitbox.hpp" #include "settings.hpp" @@ -26,7 +25,7 @@ LevelController::LevelController(Engine* engine, std::unique_ptr levelPtr *level, settings.chunks.padding.get() )), player(std::make_unique( - settings, this->level.get(), blocks.get() + settings, level.get(), blocks.get() )) { scripting::on_world_load(this); } @@ -45,11 +44,6 @@ void LevelController::update(float delta, bool input, bool pause) { if (!pause) { // update all objects that needed - for (const auto& obj : level->objects) { - if (obj && obj->shouldUpdate) { - obj->update(delta); - } - } blocks->update(delta); player->update(delta, input, pause); level->entities->updatePhysics(delta); @@ -57,17 +51,6 @@ void LevelController::update(float delta, bool input, bool pause) { } level->entities->clean(); player->postUpdate(delta, input, pause); - - // erease null pointers - auto& objects = level->objects; - objects.erase( - std::remove_if( - objects.begin(), - objects.end(), - [](auto obj) { return obj == nullptr; } - ), - objects.end() - ); } void LevelController::saveWorld() { diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 0ad5ef6b..5d14852b 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -40,7 +40,7 @@ const float C_ZOOM = 0.1f; const float CROUCH_SHIFT_Y = -0.2f; CameraControl::CameraControl( - const std::shared_ptr& player, const CameraSettings& settings + Player* player, const CameraSettings& settings ) : player(player), camera(player->fpCamera), @@ -193,7 +193,7 @@ PlayerController::PlayerController( BlocksController* blocksController ) : settings(settings), level(level), - player(level->getObject(0)), + player(level->getPlayer(0)), camControl(player, settings.camera), blocksController(blocksController), playerTickClock(20, 3) { @@ -215,7 +215,7 @@ void PlayerController::onFootstep(const Hitbox& hitbox) { continue; } blocksController->onBlockInteraction( - player.get(), + player, glm::ivec3(x, y, z), def, BlockInteraction::step @@ -254,7 +254,7 @@ void PlayerController::update(float delta, bool input, bool pause) { if (playerTickClock.update(delta)) { if (player->getId() % playerTickClock.getParts() == playerTickClock.getPart()) { - scripting::on_player_tick(player.get(), playerTickClock.getTickRate()); + scripting::on_player_tick(player, playerTickClock.getTickRate()); } } } @@ -390,12 +390,12 @@ voxel* PlayerController::updateSelection(float maxDistance) { if (selection.entity != prevEntity) { if (prevEntity != ENTITY_NONE) { if (auto pentity = level->entities->get(prevEntity)) { - scripting::on_aim_off(*pentity, player.get()); + scripting::on_aim_off(*pentity, player); } } if (selection.entity != ENTITY_NONE) { if (auto pentity = level->entities->get(selection.entity)) { - scripting::on_aim_on(*pentity, player.get()); + scripting::on_aim_on(*pentity, player); } } } @@ -432,8 +432,8 @@ void PlayerController::processRightClick(const Block& def, const Block& target) if (!input.shift && target.rt.funcsset.oninteract) { if (scripting::on_block_interact( - player.get(), target, selection.actualPosition - )) { + player, target, selection.actualPosition + )) { return; } } @@ -474,7 +474,7 @@ void PlayerController::processRightClick(const Block& def, const Block& target) slot.setCount(slot.getCount()-1); } blocksController->placeBlock( - player.get(), def, state, coord.x, coord.y, coord.z + player, def, state, coord.x, coord.y, coord.z ); } } @@ -488,10 +488,10 @@ void PlayerController::updateEntityInteraction( } auto entity = *entityOpt; if (lclick) { - scripting::on_attacked(entity, player.get(), player->getEntity()); + scripting::on_attacked(entity, player, player->getEntity()); } if (rclick) { - scripting::on_entity_used(entity, player.get()); + scripting::on_entity_used(entity, player); } } @@ -523,7 +523,7 @@ void PlayerController::updateInteraction(float delta) { auto vox = updateSelection(maxDistance); if (vox == nullptr) { if (rclick && item.rt.funcsset.on_use) { - scripting::on_item_use(player.get(), item); + scripting::on_item_use(player, item); } if (selection.entity) { updateEntityInteraction(selection.entity, lattack, rclick); @@ -534,7 +534,7 @@ void PlayerController::updateInteraction(float delta) { auto iend = selection.position; if (lclick && !input.shift && item.rt.funcsset.on_block_break_by) { if (scripting::on_item_break_block( - player.get(), item, iend.x, iend.y, iend.z + player, item, iend.x, iend.y, iend.z )) { return; } @@ -543,7 +543,7 @@ void PlayerController::updateInteraction(float delta) { if (lclick) { if (player->isInstantDestruction() && target.breakable) { blocksController->breakBlock( - player.get(), target, iend.x, iend.y, iend.z + player, target, iend.x, iend.y, iend.z ); } } @@ -551,10 +551,10 @@ void PlayerController::updateInteraction(float delta) { bool preventDefault = false; if (item.rt.funcsset.on_use_on_block) { preventDefault = scripting::on_item_use_on_block( - player.get(), item, iend, selection.normal + player, item, iend, selection.normal ); } else if (item.rt.funcsset.on_use) { - preventDefault = scripting::on_item_use(player.get(), item); + preventDefault = scripting::on_item_use(player, item); } if (preventDefault) { return; @@ -566,10 +566,10 @@ void PlayerController::updateInteraction(float delta) { } if (Events::jactive(BIND_PLAYER_PICK)) { auto coord = selection.actualPosition; - pick_block(indices, chunks, player.get(), coord.x, coord.y, coord.z); + pick_block(indices, chunks, player, coord.x, coord.y, coord.z); } } Player* PlayerController::getPlayer() { - return player.get(); + return player; } diff --git a/src/logic/PlayerController.hpp b/src/logic/PlayerController.hpp index 3fe3decf..8d82a3f9 100644 --- a/src/logic/PlayerController.hpp +++ b/src/logic/PlayerController.hpp @@ -18,7 +18,7 @@ struct CameraSettings; struct EngineSettings; class CameraControl { - std::shared_ptr player; + Player* player; std::shared_ptr camera; const CameraSettings& settings; glm::vec3 offset; @@ -40,7 +40,7 @@ class CameraControl { void switchCamera(); public: CameraControl( - const std::shared_ptr& player, const CameraSettings& settings + Player* player, const CameraSettings& settings ); void updateMouse(PlayerInput& input); void update(PlayerInput input, float delta, Chunks* chunks); @@ -50,7 +50,7 @@ public: class PlayerController { const EngineSettings& settings; Level* level; - std::shared_ptr player; + Player* player; PlayerInput input {}; CameraControl camControl; BlocksController* blocksController; diff --git a/src/logic/scripting/lua/libs/libblock.cpp b/src/logic/scripting/lua/libs/libblock.cpp index 20d3253d..31d7238c 100644 --- a/src/logic/scripting/lua/libs/libblock.cpp +++ b/src/logic/scripting/lua/libs/libblock.cpp @@ -350,9 +350,9 @@ static int l_place(lua::State* L) { "there is no block with index " + std::to_string(id) ); } - auto player = level->getObject(playerid); + auto player = level->getPlayer(playerid); controller->getBlocksController()->placeBlock( - player ? player.get() : nullptr, *def, int2blockstate(state), x, y, z + player, *def, int2blockstate(state), x, y, z ); return 0; } @@ -367,10 +367,8 @@ static int l_destruct(lua::State* L) { return 0; } auto& def = level->content->getIndices()->blocks.require(voxel->id); - auto player = level->getObject(playerid); - controller->getBlocksController()->breakBlock( - player ? player.get() : nullptr, def, x, y, z - ); + auto player = level->getPlayer(playerid); + controller->getBlocksController()->breakBlock(player, def, x, y, z); return 0; } diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 18b29405..3fcc457e 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -11,8 +11,8 @@ using namespace scripting; -inline std::shared_ptr get_player(lua::State* L, int idx) { - return level->getObject(lua::tointeger(L, idx)); +inline Player* get_player(lua::State* L, int idx) { + return level->getPlayer(lua::tointeger(L, idx)); } static int l_get_pos(lua::State* L) { diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 5c2a2b85..a3ddb81e 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -29,12 +29,14 @@ constexpr int SPAWN_ATTEMPTS_PER_UPDATE = 64; Player::Player( Level* level, + int64_t id, glm::vec3 position, float speed, std::shared_ptr inv, entityid_t eid ) : level(level), + id(id), speed(speed), chosenSlot(0), position(position), @@ -49,8 +51,7 @@ Player::Player( tpCamera->setFov(glm::radians(90.0f)); } -Player::~Player() { -} +Player::~Player() = default; void Player::updateEntity() { if (eid == 0) { @@ -283,6 +284,8 @@ glm::vec3 Player::getSpawnPoint() const { dv::value Player::serialize() const { auto root = dv::object(); + root["id"] = id; + root["position"] = dv::to_value(position); root["rotation"] = dv::to_value(cam); root["spawnpoint"] = dv::to_value(spawnpoint); @@ -304,6 +307,8 @@ dv::value Player::serialize() const { } void Player::deserialize(const dv::value& src) { + src.at("id").get(id); + const auto& posarr = src["position"]; dv::get_vec(posarr, position); diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 2badd9dc..ad60f1b8 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -4,7 +4,6 @@ #include #include -#include "interfaces/Object.hpp" #include "interfaces/Serializable.hpp" #include "settings.hpp" #include "voxels/voxel.hpp" @@ -40,8 +39,9 @@ struct CursorSelection { entityid_t entity = ENTITY_NONE; }; -class Player : public Object, public Serializable { +class Player : public Serializable { Level* level; + int64_t id; float speed; int chosenSlot; glm::vec3 position; @@ -52,7 +52,7 @@ class Player : public Object, public Serializable { bool infiniteItems = true; bool instantDestruction = true; entityid_t eid; - entityid_t selectedEid; + entityid_t selectedEid = 0; public: std::shared_ptr fpCamera, spCamera, tpCamera; std::shared_ptr currentCamera; @@ -62,6 +62,7 @@ public: Player( Level* level, + int64_t id, glm::vec3 position, float speed, std::shared_ptr inv, @@ -115,7 +116,7 @@ public: static void convert(dv::value& data, const ContentReport* report); - inline int getId() const { - return objectUID; + inline u64id_t getId() const { + return id; } }; diff --git a/src/window/Events.cpp b/src/window/Events.cpp index f63431cf..17b54204 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -62,9 +62,9 @@ bool Events::jclicked(int button) { void Events::toggleCursor() { cursor_drag = false; _cursor_locked = !_cursor_locked; - Window::setCursorMode( + /*Window::setCursorMode( _cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL - ); + );*/ } void Events::pollEvents() { diff --git a/src/world/Level.cpp b/src/world/Level.cpp index 9c58d0dc..ced03728 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -29,7 +29,7 @@ Level::Level( events(std::make_unique()), entities(std::make_unique(this)), settings(settings) { - auto& worldInfo = world->getInfo(); + const auto& worldInfo = world->getInfo(); auto& cameraIndices = content->getIndices(ResourceType::CAMERA); for (size_t i = 0; i < cameraIndices.size(); i++) { auto camera = std::make_shared(); @@ -54,9 +54,11 @@ Level::Level( auto inv = std::make_shared( world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE ); - auto player = spawnObject( - this, glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv, 0 + auto playerPtr = std::make_unique( + this, 0, glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv, 0 ); + auto player = playerPtr.get(); + addPlayer(std::move(playerPtr)); uint matrixSize = (settings.chunks.loadDistance.get() + settings.chunks.padding.get()) * @@ -75,9 +77,18 @@ Level::Level( } Level::~Level() { - for (auto obj : objects) { - obj.reset(); +} + +void Level::addPlayer(std::unique_ptr player) { + players[player->getId()] = std::move(player); +} + +Player* Level::getPlayer(int64_t id) const { + const auto& found = players.find(id); + if (found == players.end()) { + return nullptr; } + return found->second.get(); } void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) { diff --git a/src/world/Level.hpp b/src/world/Level.hpp index 767844cf..bf4eaaba 100644 --- a/src/world/Level.hpp +++ b/src/world/Level.hpp @@ -2,8 +2,9 @@ #include #include +#include -#include "interfaces/Object.hpp" +#include "typedefs.hpp" inline constexpr float DEF_PLAYER_Y = 100.0f; inline constexpr float DEF_PLAYER_SPEED = 4.0f; @@ -19,6 +20,7 @@ class Lighting; class PhysicsSolver; class ChunksStorage; class Camera; +class Player; struct EngineSettings; /// @brief A level, contains chunks and objects @@ -26,7 +28,7 @@ class Level { std::unique_ptr world; public: const Content* const content; - std::vector> objects; + std::unordered_map> players; std::unique_ptr chunks; std::unique_ptr chunksStorage; std::unique_ptr inventories; @@ -52,35 +54,9 @@ public: const World* getWorld() const; - /// Spawns object of class T and returns pointer to it. - /// @param T class that derives the Object class - /// @param args pass arguments needed for T class constructor - template - 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...); + void addPlayer(std::unique_ptr player); - 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) const { - 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; - } + Player* getPlayer(int64_t id) const; void onSave(); diff --git a/src/world/World.cpp b/src/world/World.cpp index 0f6ea373..1b732c69 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -71,10 +71,8 @@ void World::write(Level* level) { auto playerFile = dv::object(); auto& players = playerFile.list("players"); - for (const auto& object : level->objects) { - if (auto player = std::dynamic_pointer_cast(object)) { - players.add(player->serialize()); - } + for (const auto& [id, player] : level->players) { + players.add(player->serialize()); } files::write_json(wfile->getPlayerFile(), playerFile); @@ -94,6 +92,7 @@ std::unique_ptr World::create( info.name = name; info.generator = generator; info.seed = seed; + info.nextPlayerId = 1; auto world = std::make_unique( info, std::make_unique(directory, settings.debug), @@ -121,45 +120,42 @@ std::unique_ptr World::load( << " generator: " << info->generator; auto world = std::make_unique( - info.value(), - std::move(worldFilesPtr), - content, - packs + info.value(), std::move(worldFilesPtr), content, packs ); auto& wfile = world->wfile; wfile->readResourcesData(content); auto level = std::make_unique(std::move(world), content, settings); - { - fs::path file = wfile->getPlayerFile(); - if (!fs::is_regular_file(file)) { - logger.warning() << "player.json does not exists"; - } else { - auto playerRoot = files::read_json(file); - if (playerRoot.has("players")) { - level->objects.clear(); - const auto& players = playerRoot["players"]; - for (auto& playerMap : players) { - auto player = level->spawnObject( - level.get(), - glm::vec3(0, DEF_PLAYER_Y, 0), - DEF_PLAYER_SPEED, - level->inventories->create(DEF_PLAYER_INVENTORY_SIZE), - 0 - ); - player->deserialize(playerMap); - auto& inventory = player->getInventory(); - // invalid inventory id pre 0.25 - if (inventory->getId() == 0) { - inventory->setId(level->getWorld()->getNextInventoryId()); - } - level->inventories->store(player->getInventory()); - } - } else { - auto player = level->getObject(0); - player->deserialize(playerRoot); - level->inventories->store(player->getInventory()); + + fs::path file = wfile->getPlayerFile(); + if (!fs::is_regular_file(file)) { + logger.warning() << "player.json does not exists"; + } else { + level->players.clear(); + + auto playerRoot = files::read_json(file); + const auto& players = playerRoot["players"]; + if (!players[0].has("id")) { + world->getInfo().nextPlayerId++; + } + for (auto& playerMap : players) { + auto playerPtr = std::make_unique( + level.get(), + 0, + glm::vec3(0, DEF_PLAYER_Y, 0), + DEF_PLAYER_SPEED, + level->inventories->create(DEF_PLAYER_INVENTORY_SIZE), + 0 + ); + auto player = playerPtr.get(); + player->deserialize(playerMap); + level->addPlayer(std::move(playerPtr)); + auto& inventory = player->getInventory(); + // invalid inventory id pre 0.25 + if (inventory->getId() == 0) { + inventory->setId(level->getWorld()->getNextInventoryId()); } + level->inventories->store(player->getInventory()); } } return level; @@ -231,6 +227,7 @@ void WorldInfo::deserialize(const dv::value& root) { } nextInventoryId = root["next-inventory-id"].asInteger(2); nextEntityId = root["next-entity-id"].asInteger(1); + root.at("next-player-id").get(nextPlayerId); } dv::value WorldInfo::serialize() const { @@ -254,5 +251,6 @@ dv::value WorldInfo::serialize() const { root["next-inventory-id"] = nextInventoryId; root["next-entity-id"] = nextEntityId; + root["next-player-id"] = nextPlayerId; return root; } diff --git a/src/world/World.hpp b/src/world/World.hpp index 2f8e7fb3..24042c40 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -28,6 +28,7 @@ struct WorldInfo : public Serializable { std::string generator; uint64_t seed; int64_t nextInventoryId = 1; + int64_t nextPlayerId = 0; /// @brief Day/night loop timer in range 0..1 where /// 0.0 - is midnight and