diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 62b79a41..24c3dfe4 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -559,11 +559,11 @@ bool WorldFiles::readWorldInfo(World* world) { return true; } -void WorldFiles::writePlayer(Player* player) { +void WorldFiles::writePlayer(std::shared_ptr player) { files::write_json(getPlayerFile(), player->serialize().release()); } -bool WorldFiles::readPlayer(Player* player) { +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; diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 34203b97..a3a9a483 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -143,13 +143,13 @@ public: chunk_inventories_map fetchInventories(int x, int z); bool readWorldInfo(World* world); - bool readPlayer(Player* player); + bool readPlayer(std::shared_ptr player); void writeRegion(int x, int y, WorldRegion* entry, fs::path file, int layer); - void writePlayer(Player* player); + void writePlayer(std::shared_ptr player); /* @param world world info to save (nullable) */ void write(const World* world, const Content* content); void writePacks(const World* world); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 860131a2..c2fec154 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -645,6 +645,6 @@ void Hud::setPause(bool pause) { menu->setVisible(pause); } -Player* Hud::getPlayer() const { +std::shared_ptr Hud::getPlayer() const { return frontend->getLevel()->player; } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index 7e9e2153..5a5b8914 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -118,7 +118,7 @@ public: void remove(HudElement& element); void remove(std::shared_ptr node); - Player* getPlayer() const; + std::shared_ptr getPlayer() const; }; #endif /* SRC_HUD_H_ */ diff --git a/src/interfaces/Object.h b/src/interfaces/Object.h new file mode 100644 index 00000000..5ffe1cb6 --- /dev/null +++ b/src/interfaces/Object.h @@ -0,0 +1,25 @@ +#ifndef OBJECT_H +#define OBJECT_H + +#include "stdlib.h" +#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() { } +}; + +#endif /* OBJECT_H */ \ No newline at end of file diff --git a/src/interfaces/Serializable.h b/src/interfaces/Serializable.h index a1c0d4e2..ee75498b 100644 --- a/src/interfaces/Serializable.h +++ b/src/interfaces/Serializable.h @@ -4,12 +4,11 @@ #include #include "../coders/json.h" -class Serializable -{ +class Serializable { public: virtual ~Serializable() { } virtual std::unique_ptr serialize() const = 0; virtual void deserialize(dynamic::Map* src) = 0; }; -#endif \ No newline at end of file +#endif /* SERIALIZABLE_H */ \ No newline at end of file diff --git a/src/items/Inventory.h b/src/items/Inventory.h index 677f8d9a..69f6e173 100644 --- a/src/items/Inventory.h +++ b/src/items/Inventory.h @@ -13,7 +13,7 @@ class ContentLUT; class ContentIndices; -class Inventory : Serializable { +class Inventory : public Serializable { int64_t id; std::vector slots; public: diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 826204ca..94a82062 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -6,6 +6,7 @@ #include "ChunksController.h" #include "scripting/scripting.h" +#include "../interfaces/Object.h" LevelController::LevelController(EngineSettings& settings, Level* level) : settings(settings), level(level) { @@ -23,7 +24,20 @@ void LevelController::update(float delta, bool input, bool pause) { player->update(delta, input, pause); level->update(); chunks->update(settings.chunks.loadSpeed); + + // erease null pointers + level->objects.remove_if([](auto obj) { return obj == nullptr; }); + if (!pause) { + // update all objects that needed + for(auto obj : level->objects) + { + if(obj) { + if(obj->shouldUpdate) { + obj->update(delta); + } + } + } blocks->update(delta); } } diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 482b5b01..ab44336e 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -31,7 +31,7 @@ const float C_ZOOM = 0.1f; const float CROUCH_SHIFT_Y = -0.2f; -CameraControl::CameraControl(Player* player, const CameraSettings& settings) +CameraControl::CameraControl(std::shared_ptr player, const CameraSettings& settings) : player(player), camera(player->camera), currentViewCamera(player->currentCamera), @@ -202,13 +202,13 @@ void PlayerController::resetKeyboard() { } void PlayerController::updateControls(float delta){ - player->update(level, input, delta); + player->updateInput(level, input, delta); } void PlayerController::updateInteraction(){ auto indices = level->content->getIndices(); Chunks* chunks = level->chunks; - Player* player = level->player; + Player* player = level->player.get(); Lighting* lighting = level->lighting; Camera* camera = player->camera.get(); glm::vec3 end; diff --git a/src/logic/PlayerController.h b/src/logic/PlayerController.h index d9d002d6..a1479820 100644 --- a/src/logic/PlayerController.h +++ b/src/logic/PlayerController.h @@ -12,7 +12,7 @@ class Level; class BlocksController; class CameraControl { - Player* player; + std::shared_ptr player; std::shared_ptr camera, currentViewCamera; const CameraSettings& settings; glm::vec3 offset; @@ -20,7 +20,7 @@ class CameraControl { float shakeTimer = 0.0f; glm::vec3 interpVel {0.0f}; public: - CameraControl(Player* player, const CameraSettings& settings); + CameraControl(std::shared_ptr player, const CameraSettings& settings); void updateMouse(PlayerInput& input); void update(PlayerInput& input, float delta, Chunks* chunks); void refresh(); @@ -28,7 +28,7 @@ public: class PlayerController { Level* level; - Player* player; + std::shared_ptr player; PlayerInput input; CameraControl camControl; BlocksController* blocksController; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 39268de6..62c9d712 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -33,7 +33,7 @@ Player::Player(glm::vec3 position, float speed, std::shared_ptr inv) Player::~Player() { } -void Player::update( +void Player::updateInput( Level* level, PlayerInput& input, float delta) { diff --git a/src/objects/Player.h b/src/objects/Player.h index f49a9fc2..bea94c2b 100644 --- a/src/objects/Player.h +++ b/src/objects/Player.h @@ -8,6 +8,7 @@ #include "../voxels/voxel.h" #include "../settings.h" #include "../interfaces/Serializable.h" +#include "../interfaces/Object.h" class Camera; class Hitbox; @@ -32,7 +33,7 @@ struct PlayerInput { bool flight; }; -class Player : Serializable { +class Player : public Object, public Serializable { float speed; int chosenSlot; glm::vec3 spawnpoint {}; @@ -52,7 +53,7 @@ public: ~Player(); void teleport(glm::vec3 position); - void update(Level* level, PlayerInput& input, float delta); + void updateInput(Level* level, PlayerInput& input, float delta); void attemptToFindSpawnpoint(Level* level); diff --git a/src/world/Level.cpp b/src/world/Level.cpp index 90d0df46..287607ed 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -8,19 +8,27 @@ #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" -Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings) + +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), - player(player), chunksStorage(new ChunksStorage(this)), events(new LevelEvents()) , settings(settings) { + objCounter = 0; physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0)); + auto inv = std::make_shared(world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE); + player = spawnObject(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv); uint matrixSize = (settings.chunks.loadDistance+ settings.chunks.padding) * 2; @@ -33,15 +41,20 @@ Level::Level(World* world, const Content* content, Player* player, EngineSetting }); inventories = std::make_unique(*this); + inventories->store(player->getInventory()); } Level::~Level(){ delete chunks; delete events; delete physics; - delete player; delete lighting; delete chunksStorage; + + for(auto obj : objects) + { + obj.reset(); + } } void Level::update() { @@ -58,3 +71,18 @@ void Level::update() { 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 e670422f..fbf9d283 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -5,10 +5,14 @@ #include "../typedefs.h" #include "../settings.h" +#include +#include +#include class Content; class World; class Player; +class Object; class Chunks; class Inventory; class Inventories; @@ -18,10 +22,13 @@ class PhysicsSolver; class ChunksStorage; class Level { +private: + int objCounter; public: std::unique_ptr world; const Content* const content; - Player* player; + std::list> objects; + std::shared_ptr player; Chunks* chunks; ChunksStorage* chunksStorage; std::unique_ptr inventories; @@ -34,13 +41,18 @@ public: Level(World* world, const Content* content, - Player* player, EngineSettings& settings); ~Level(); void update(); World* getWorld(); + + // 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); }; #endif /* WORLD_LEVEL_H_ */ diff --git a/src/world/World.cpp b/src/world/World.cpp index 8851767a..fce0b05c 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -64,10 +64,6 @@ void World::write(Level* level) { wfile->writePlayer(level->player); } -const float DEF_PLAYER_Y = 100.0f; -const float DEF_PLAYER_SPEED = 4.0f; -const int DEF_PLAYER_INVENTORY_SIZE = 40; - Level* World::create(std::string name, fs::path directory, uint64_t seed, @@ -75,12 +71,7 @@ Level* World::create(std::string name, const Content* content, const std::vector& packs) { auto world = new World(name, directory, seed, settings, content, packs); - auto inv = std::make_shared(world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE); - auto player = new Player( - glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv - ); - auto level = new Level(world, content, player, settings); - level->inventories->store(player->getInventory()); + auto level = new Level(world, content, settings); return level; } @@ -97,13 +88,8 @@ Level* World::load(fs::path directory, throw world_load_error("could not to find world.json"); } - auto inv = std::make_shared(0, DEF_PLAYER_INVENTORY_SIZE); - auto player = new Player( - glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv - ); - auto level = new Level(world.get(), content, player, settings); - wfile->readPlayer(player); - level->inventories->store(player->getInventory()); + auto level = new Level(world.get(), content, settings); + wfile->readPlayer(level->player); world.release(); return level; } diff --git a/src/world/World.h b/src/world/World.h index ca242d60..faf142e7 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -26,7 +26,7 @@ public: world_load_error(std::string message); }; -class World : Serializable { +class World : public Serializable { std::string name; uint64_t seed; EngineSettings& settings;