#include #include #include #include #include namespace deerith { struct component_client_environment_knowledge_t { std::unordered_map 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(entt::exclude); for (auto [entity, client_link] : no_surface_knowledge_component_clients.each()) { add_component(entity); } } auto update_surface_knowledge_to_clients = get_entity_registry().view(); 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(std::floor(position.x / CLUSTER_SIZE)); const int surface_z = static_cast(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_data.__cluster_data = cluster->__data; router_send_packet(cluster_data, client); deerith_trace("sent cluster data to client in {} ms", get_chrono_ms()); }