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

99 lines
3.6 KiB
C++

#include "LocalUniverse.hpp"
#include "core/geometry/math.hpp"
#include "../contouring/Abstract.hpp"
#include "../render/Window.hpp"
#include "core/utils/logger.hpp"
#include "core/world/Elements.hpp"
#include "core/utils/io.hpp"
#include <random>
#undef LOG_PREFIX
#define LOG_PREFIX "Client: "
using namespace world::client;
LocalUniverse::LocalUniverse(const Universe::login& login, server_handle *const handle, const std::string& contour): Universe(contour), handle(handle) {
assert(handle != nullptr);
handle->playerName = login.name;
for (auto i = 0; i < 500 && !handle->running; i++) {
LOG_D("Waiting local server startup");
Window::wait();
}
assert(handle->running);
}
LocalUniverse::~LocalUniverse() {
handle->running = false;
}
void LocalUniverse::update(cell_pos pos, float deltaTime) {
if (handle->teleport.has_value() && onTeleport) {
const auto &rtf = handle->teleport.value();
const auto abs = getAbsolute(rtf);
pos = abs.position;
onTeleport(rtf, abs);
handle->teleport = std::nullopt;
}
if (onMessage) {
handle->messages.extractor(onMessage);
}
const auto notifyTick = contouringNotifier.mustNotify(pos, deltaTime);
const auto lock = getElements();
const auto &elements = *lock;
const auto visibleDist2 = glm::pow2<glm::l>(contouring->getVisibleDist());
{ // Update alive areas
ZoneScopedN("World");
auto rng = std::mt19937(std::rand());
const auto contouringThreshold = UINT32_MAX / (1 + contouring->getQueueSize());
for (auto& ref: elements.areas) {
const area_id id = elements.withFlag(ref).val;
const auto node = elements.findArea(id);
assert(node);
//MAYBE: if in load range
const auto area_tf = node->absolute;
const auto area = node->get();
const auto& chunks = area->getChunks();
//MAYBE: chunk area change
for(const auto& chunk: chunks) {
//MAYBE: compute absolute manually from chunk_pos(1) * pivot
const cell_pos chunkPos = area_tf.computeChild(glm::multiply(chunk.first));
const auto chunkDist = glm::length2(glm::divide(chunkPos - pos));
if (chunkDist > visibleDist2) // FIXME: World still > 20ms with big contouring.keepDist
continue;
if(const auto neighbors = chunk.second->setEdits()->update(deltaTime, rng() < contouringThreshold)) {
contouring->onUpdate(area_chunk_pos{id, chunk.first}, chunkDist, chunks, neighbors.value());
} else if (notifyTick) {
contouring->onNotify(area_chunk_pos{id, chunk.first}, chunkDist, chunks);
}
}
}
}
if (notifyTick) {
for(const auto& ref: elements.parts) {
const part_id id = elements.withFlag(ref).val;
const auto node = elements.findPart(id);
if (node->get()->loaded()) {
const auto partDist = glm::length2(glm::divide((cell_pos)node->absolute.position - pos));
contouring->onNotify(id, partDist, node->get()->chunkSize(), node->get()->chunks, false);
}
}
elements.models.iter([&] (const model_id& id, const Model& model) {
if (!model.instances.empty()) {
io::vec_istream idata(model.dt);
std::istream iss(&idata);
contouring->onLoad(id, iss);
}
});
}
contouring->update(pos, elements);
}
void LocalUniverse::emit(const world::action::packet &packet) {
handle->emit(packet);
}