#pragma once #include #include #include "../../core/world/Universe.hpp" #include "../../core/data/math.hpp" #include "../../core/data/safe_queue.hpp" #include "../../core/data/safe_priority_queue.hpp" #include "../../core/data/file.hpp" #include "../../core/net/Server.hpp" #include "Area.hpp" namespace buffer { class Abstract; } using namespace data; /// Universe data namespace world::server { class Chunk; /// Whole universe container in abstract server class Universe: public world::Universe { public: /// Server config struct options: world::Universe::options { /// Storage path std::string folderPath = "world"; net::connection connection = net::connection{"localhost", 4242}; int maxPlayers = 1; }; Universe(const options &); virtual ~Universe(); /// Update physics void update(float deltaTime); /// Apply new options void setOptions(const options &); /// Set voxel at pos std::optional set(const area_ &pos, const Voxel &val); /// Set cube of voxel with pos as center /// MAYBE: allow set multi area ItemList setCube(const area_ &pos, const Voxel &val, int radius); /// Set sphere of voxel with pos as center /// MAYBE: allow set multi area ItemList setSphere(const area_ &pos, const Voxel &val, int radius); /// Instante entity entity_instance_id addEntity(entity_id type, const Entity::Instance &instance); Entity::Instance* findEntity(entity_id type, entity_id id); /// Move player bool movePlayer(data::generational::id id, glm::ifvec3 pos); /// Get nearest voxel colliding ray /// @note ray in world scale ray_result raycast(const geometry::Ray &ray) const override; bool isAreaFree(const area_ &pos, geometry::Shape shape, uint16_t radius) const override; /// Check for collision on destination bool collide_end(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius) const; /// Check for collision at position bool collide_point(const glm::ifvec3 &pos, const glm::vec3 &vel, int density) const; protected: /// Save all chunks (saveThread uses virtual calls) void saveAll(bool remove); /// Handle networking requests void pullNetwork(); void broadcastAreas(); net::packet_t* serializeChunk(const robin_hood::pair, std::shared_ptr> &); virtual void broadcastMessage(const std::string &); using area_map = robin_hood::unordered_map>; virtual std::shared_ptr createChunk(const chunk_pos &pos, const std::unique_ptr &rnd) const; virtual std::shared_ptr createChunk(std::istream &str) const; virtual void updateChunk(area_map::iterator&, world::ChunkContainer::iterator&, chunk_pos, float deltaTime); virtual void loadChunk(area_, chunk_pos, const world::ChunkContainer &); robin_hood::unordered_set movedPlayers; voxel_pos spawnPoint; /// Alive areas containing chunks area_map areas; using area_it_t = robin_hood::pair>; /// Dead areas data::generational::vector far_areas; void saveAreas() const; data::generational::vector entities; bool running = true; std::vector workers; safe_priority_queue_map, std::shared_ptr, int, area_hash> loadQueue; //NOTE: consider Area const (getRegion uses mutex) safe_queue, std::shared_ptr>> loadedQueue; using save_task_t = std::pair>>; data::safe_queue saveQueue; //NOTE: consider Area and Chunk const ushort loadDistance; ushort keepDistance; std::string folderPath; net::Server host; data::file_content dict_content; zstd::dict_set dicts; zstd::write_ctx dict_write_ctx; }; }