99 lines
3.6 KiB
C++
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);
|
|
}
|