1
0
Fork 0
Univerxel/src/server/world/Universe.hpp

113 lines
3.9 KiB
C++

#pragma once
#include <string>
#include <thread>
#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<Item> set(const area_<voxel_pos> &pos, const Voxel &val);
/// Set cube of voxel with pos as center
/// MAYBE: allow set multi area
ItemList setCube(const area_<voxel_pos> &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;
/// 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<area_<chunk_pos>, std::shared_ptr<Chunk>> &);
using area_map = robin_hood::unordered_map<area_id, std::shared_ptr<Area>>;
virtual std::shared_ptr<Chunk> createChunk(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd) const;
virtual std::shared_ptr<Chunk> createChunk(std::istream &str) const;
virtual void updateChunk(area_map::iterator&, world::ChunkContainer::iterator&, chunk_pos, float deltaTime);
virtual void loadChunk(area_<chunk_pos>, chunk_pos, const world::ChunkContainer &);
std::vector<data::generational::id> movedPlayers;
voxel_pos spawnPoint;
/// Alive areas containing chunks
area_map areas;
using area_it_t = robin_hood::pair<area_id, std::shared_ptr<Area>>;
/// Dead areas
data::generational::vector<Area::params> far_areas;
void saveAreas() const;
data::generational::vector<Entity> entities;
bool running = true;
std::vector<std::thread> workers;
safe_priority_queue_map<area_<chunk_pos>, std::shared_ptr<Area>, int, area_hash> loadQueue; //NOTE: consider Area const (getRegion uses mutex)
safe_queue<robin_hood::pair<area_<chunk_pos>, std::shared_ptr<Chunk>>> loadedQueue;
using save_task_t = std::pair<area_it_t, robin_hood::pair<chunk_pos, std::shared_ptr<world::server::Chunk>>>;
data::safe_queue<save_task_t> 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;
};
}