1
0
Fork 0
Univerxel/src/client/world/LocalUniverse.cpp

106 lines
4.0 KiB
C++

#include "LocalUniverse.hpp"
#include "../../core/data/math.hpp"
#include "../../core/data/mem.hpp"
#include "../contouring/Abstract.hpp"
#include "../Window.hpp"
#include "../../core/utils/logger.hpp"
#include "../../core/world/Area.hpp"
using namespace world::client;
LocalUniverse::LocalUniverse(server_handle *const handle, const std::string& contour): Universe(contour), handle(handle) {
assert(handle != nullptr);
for (auto i = 0; i < 500 && !handle->running; i++) {
LOG_D("Waiting local server startup");
Window::wait();
}
handle->onUpdate = std::function([&](const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data, geometry::Faces neighbors) {
contouring->onUpdate(pos, this->last_chunk - offset, data, neighbors);
});
}
LocalUniverse::~LocalUniverse() {
handle->running = false;
}
void LocalUniverse::update(voxel_pos pos, float) {
if (handle->teleport.has_value() && onTeleport) {
pos = handle->teleport.value();
onTeleport(pos);
handle->teleport = std::nullopt;
}
if (handle->message.has_value() && onMessage) {
onMessage(handle->message.value());
handle->message = std::nullopt;
}
if (handle->entityChange) {
handle->entities->iter([&](entity_id eId, const Entity &entity) {
if (entity.instances.size() == 0)
return;
if (auto area = std::get_if<Entity::area_t>(&entity.shape)) {
contouring->onEntityLoad(eId.index, glm::lvec3(1) + glm::divide(entity.size), *area);
} else {
auto model = std::get_if<Entity::model_t>(&entity.shape);
assert(model);
data::vec_istream idata(*model);
std::istream iss(&idata);
contouring->onEntityLoad(eId.index, iss);
}
});
handle->entityChange = false;
}
const auto cur_chunk = glm::divide(pos);
const auto chunkChange = cur_chunk != last_chunk;
last_chunk = cur_chunk;
if(chunkChange) {
for(const auto& area: *handle->areas) {
const chunk_pos diff = glm::divide(pos - area.second->getOffset().as_voxel());
for(const auto& chunk: area.second->getChunks()) {
contouring->onNotify(std::make_pair(area.first, chunk.first), diff, area.second->getChunks());
}
}
}
contouring->update(pos, *handle->areas);
}
void LocalUniverse::emit(const world::action::packet &packet) {
handle->emit(packet);
}
Universe::ray_result LocalUniverse::raycast(const geometry::Ray& ray) const {
return handle->raycast(ray);
}
bool LocalUniverse::isAreaFree(const area_<voxel_pos> &pos, const geometry::Shape shape, const uint16_t radius) const {
if (const auto it = handle->areas->find(pos.first); it != handle->areas->end()) {
const auto center = pos.second + it->second->getOffset().as_voxel();
return !handle->entities->contains([&](entity_id, const Entity &entity) {
return entity.instances.contains([&](entity_id, const Entity::Instance &inst) {
return geometry::InShape(shape, center, radius, inst.pos.as_voxel(), entity.size);
});
});
} else
return false;
}
void LocalUniverse::getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>& call,
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
{
std::vector<glm::mat4> mats;
handle->entities->iter([&](entity_id eId, const Entity &entity) {
entity.instances.iter([&](entity_id iId, const Entity::Instance &inst) {
if (eId.index == PLAYER_ENTITY_ID.index && iId.index == PLAYER_ENTITY_ID.index)
return;
glm::mat4 tmp;
if (contouring::Abstract::CullEntity(tmp, entity.size, entity.scale, inst.pos, frustum, offset, density))
mats.push_back(tmp);
});
if(!mats.empty()) {
call(eId.index, mats);
mats.resize(0);
}
});
}