DeerithEngine/deerith_engine_server/src/world/voxel_data_managment.cpp
2026-11-03 23:02:44 +01:00

110 lines
4.1 KiB
C++

#include <deerith/server/internals/world.h>
#include <deerith/world/environment.h>
#include <deerith/network/packets_voxel.h>
#include <deerith/network/router.h>
#include <unordered_map>
namespace deerith
{
struct component_client_environment_knowledge_t
{
std::unordered_map<glm::ivec3, int32_t, ivec3_hash_t> cluster_knowledge;
};
void check_client_surface_knowledge(client_t *, component_client_environment_knowledge_t &knowledge, glm::ivec3 position);
bool check_client_cluster_knowledge(client_t *client, component_client_environment_knowledge_t &knowledge, surface_t *surface);
void send_cluster_info_to_client(client_t *, voxel_cluster_t *);
}
void deerith::send_voxel_data_to_client(client_t *client)
{
packet_voxel_data_definition_t voxel_data_definition;
voxel_data_definition.voxel_materials = get_voxel_material_vector();
voxel_data_definition.voxel_types = get_voxel_type_vector();
router_send_packet(voxel_data_definition, client);
}
void deerith::send_clients_environment_data()
{
// temp solution to assign this component to clients that don't have it
{
auto no_surface_knowledge_component_clients = get_entity_registry().view<component_client_link_t>(entt::exclude<component_client_environment_knowledge_t>);
for (auto [entity, client_link] : no_surface_knowledge_component_clients.each())
{
add_component<component_client_environment_knowledge_t>(entity);
}
}
auto update_surface_knowledge_to_clients = get_entity_registry().view<component_client_link_t, component_sync_coordinates_t, component_client_environment_knowledge_t>();
for (auto [entity, client_link, entity_position, surface_knowledge] : update_surface_knowledge_to_clients.each())
{
check_client_surface_knowledge(client_link.client, surface_knowledge, entity_position.position.read_value());
}
}
void deerith::check_client_surface_knowledge(client_t *client, component_client_environment_knowledge_t &knowledge, glm::ivec3 position)
{
const int surface_x = static_cast<int>(std::floor(position.x / CLUSTER_SIZE));
const int surface_z = static_cast<int>(std::floor(position.z / CLUSTER_SIZE));
const int SURFACE_RADIUS = 4;
for (int x = -SURFACE_RADIUS; x <= SURFACE_RADIUS; x++)
{
for (int z = -SURFACE_RADIUS; z <= SURFACE_RADIUS; z++)
{
glm::ivec2 surface_id = {surface_x + x, surface_z + z};
surface_t *surface = get_surface(surface_id);
if (surface != nullptr)
{
if (check_client_cluster_knowledge(client, knowledge, surface))
{
return;
}
}
}
}
}
bool deerith::check_client_cluster_knowledge(client_t *client, component_client_environment_knowledge_t &knowledge, surface_t *surface)
{
for (int i = 0; i < surface->voxel_clusters.size(); i++)
{
voxel_cluster_t *cluster = surface->voxel_clusters[i].get();
int32_t cluster_last_update = cluster->last_update_tick_id;
int32_t actual_cluster_kknowledge = -1;
glm::ivec3 cluster_id = glm::ivec3(surface->surface_id.x, cluster->layer, surface->surface_id.y);
if (knowledge.cluster_knowledge.contains(cluster_id))
{
actual_cluster_kknowledge = knowledge.cluster_knowledge[cluster_id];
}
if (actual_cluster_kknowledge < cluster_last_update)
{
knowledge.cluster_knowledge[cluster_id] = cluster_last_update;
send_cluster_info_to_client(client, cluster);
return true;
}
}
return false;
}
void deerith::send_cluster_info_to_client(client_t *client, voxel_cluster_t *cluster)
{
start_chrono();
packet_cluster_data_t cluster_data;
cluster_data.surface_id = cluster->surface_id;
cluster_data.layer = cluster->layer;
cluster_data.__cluster_data = std::make_unique<cluster_voxel_type_id_data_t>();
*cluster_data.__cluster_data = cluster->__data;
router_send_packet(cluster_data, client);
deerith_trace("sent cluster data to client in {} ms", get_chrono_ms());
}