diff --git a/deerith_client/src/world/player_movment.cpp b/deerith_client/src/world/player_movment.cpp index 0c69a5a..5b98b2d 100644 --- a/deerith_client/src/world/player_movment.cpp +++ b/deerith_client/src/world/player_movment.cpp @@ -23,17 +23,18 @@ void deerith::process_player_input() movment = glm::vec2(0, 0); } - component_player_sync_input_t &entity_sync_position = get_component(self_entity); + component_client_sync_character_t &entity_sync_position = get_component(self_entity); - entity_sync_position.move_input = movment; - entity_sync_position.position = entity_sync_position.position.read_value() + movment * 0.1f; + glm::vec3 movment_3d = glm::vec3(movment.x, 0, movment.y); + entity_sync_position.move_input = movment_3d; + entity_sync_position.position = entity_sync_position.position.read_value() + movment_3d * 0.1f; } void deerith::send_player_input() { if (self_entity == entt::null) return; - component_player_sync_input_t &entity_sync_position = get_component(self_entity); + component_client_sync_character_t &entity_sync_position = get_component(self_entity); packet_update_player_input_t packet{}; packet.input_transport.load(entity_sync_position.move_input); diff --git a/deerith_client/src/world/server_communication.cpp b/deerith_client/src/world/server_communication.cpp index c159207..f21cee0 100644 --- a/deerith_client/src/world/server_communication.cpp +++ b/deerith_client/src/world/server_communication.cpp @@ -3,6 +3,8 @@ #include #include #include +#include + #include #include @@ -16,6 +18,8 @@ void deerith::setup_base_protocols() router_add_packet_processor(); router_add_packet_processor(); router_add_packet_processor(); + router_add_packet_processor(); + router_add_packet_processor(); } template <> @@ -29,7 +33,7 @@ template <> void deerith::process_packet(deerith::packet_create_player_entity_t &packet, client_t *client) { self_entity = create_entity(); - add_component(self_entity); + add_component(self_entity); } template <> @@ -88,4 +92,16 @@ void deerith::process_packet(deerith::packet_voxel_data_definition_t &packet, cl deerith_trace("recive voxel data definition with {} materials and {} types", packet.voxel_materials.size(), packet.voxel_types.size()); set_voxel_materials(packet.voxel_materials); set_voxel_types(packet.voxel_types); +} + +template <> +void deerith::process_packet(deerith::packet_surface_data_t &packet, client_t *client) +{ + set_surface_height_raw_data(*packet.__surface_data, packet.surface_id); +} + +template <> +void deerith::process_packet(deerith::packet_cluster_data_t &packet, client_t *client) +{ + set_cluster_voxel_type_id_raw_data(*packet.__cluster_data, packet.surface_id, packet.cluster_height_id); } \ No newline at end of file diff --git a/deerith_client/src/world/world_render.cpp b/deerith_client/src/world/world_render.cpp index c56f1eb..b014931 100644 --- a/deerith_client/src/world/world_render.cpp +++ b/deerith_client/src/world/world_render.cpp @@ -22,14 +22,14 @@ void deerith::render_world() set_transform_to_shader(glm::vec3(0, 0, 0), glm::identity(), glm::vec3(1, 1, 1), get_lit_shader()); get_grid_mesh()->draw_lines(); - auto entities_view = get_entity_registry().view(entt::exclude); + auto entities_view = get_entity_registry().view(entt::exclude); for (auto [entity, sync_coords] : entities_view.each()) { - glm::vec2 chords; + glm::vec3 chords; if (sync_coords.position.read_synced(chords)) { - glm::vec3 position = glm::vec3(chords.x, 0, chords.y); + glm::vec3 position = chords; glm::quat rotation = glm::identity(); glm::vec3 scale = glm::vec3(1, 1, 1); @@ -42,7 +42,7 @@ void deerith::render_world() } // we should expect only one registry - auto self_view = get_entity_registry().view(); + auto self_view = get_entity_registry().view(); for (auto [entity, sync_coords, client_sync_coords] : self_view.each()) { diff --git a/deerith_engine_core/include/deerith/engine.h b/deerith_engine_core/include/deerith/engine.h index c2d21a5..ee623e8 100644 --- a/deerith_engine_core/include/deerith/engine.h +++ b/deerith_engine_core/include/deerith/engine.h @@ -16,4 +16,7 @@ namespace deerith bool execute_client(const char *server_executable_path, int port); void shutdown_executing_servers(); + + void start_chrono(); + float get_chrono_ms(); } \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/network/packets.h b/deerith_engine_core/include/deerith/network/packets.h index 249cc8f..ce4ba7a 100644 --- a/deerith_engine_core/include/deerith/network/packets.h +++ b/deerith_engine_core/include/deerith/network/packets.h @@ -31,8 +31,8 @@ namespace deerith static constexpr uint16_t packet_id = 3; static constexpr bool reliable = false; - sync_variable_transport_t position_transport; - sync_variable_transport_t input_transport; + sync_variable_transport_t position_transport; + sync_variable_transport_t input_transport; template void serialize(Archive &archive) @@ -80,7 +80,7 @@ namespace deerith static constexpr bool reliable = false; std::vector entities_ids; - std::vector> positions_to_update; + std::vector> positions_to_update; template void serialize(Archive &archive) diff --git a/deerith_engine_core/include/deerith/network/packets_voxel.h b/deerith_engine_core/include/deerith/network/packets_voxel.h index e31bee6..812a7e7 100644 --- a/deerith_engine_core/include/deerith/network/packets_voxel.h +++ b/deerith_engine_core/include/deerith/network/packets_voxel.h @@ -1,9 +1,13 @@ #pragma once #include #include +#include #include #include +#include + +#include // VOXEL SPECIFIC PACKETS 1xxx @@ -24,4 +28,58 @@ namespace deerith archive(voxel_types); } }; + + struct packet_surface_data_t + { + static constexpr uint16_t packet_id = 1002; + static constexpr bool reliable = true; + + glm::ivec2 surface_id; + std::unique_ptr __surface_data; + + template + void save(Archive &archive) const + { + archive(surface_id); + archive(*__surface_data); + } + + template + void load(Archive &archive) + { + archive(surface_id); + + __surface_data = std::make_unique(); + archive(*__surface_data); + } + }; + + struct packet_cluster_data_t + { + static constexpr uint16_t packet_id = 1003; + static constexpr bool reliable = true; + + glm::ivec2 surface_id; + size_t cluster_height_id; + + std::unique_ptr __cluster_data; + + template + void save(Archive &archive) const + { + archive(surface_id); + archive(cluster_height_id); + archive(*__cluster_data); + } + + template + void load(Archive &archive) + { + archive(surface_id); + archive(cluster_height_id); + + __cluster_data = std::make_unique(); + archive(*__cluster_data); + } + }; } \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/network/serialization_ext.h b/deerith_engine_core/include/deerith/network/serialization_ext.h index 7d880cf..62edea9 100644 --- a/deerith_engine_core/include/deerith/network/serialization_ext.h +++ b/deerith_engine_core/include/deerith/network/serialization_ext.h @@ -15,4 +15,17 @@ namespace cereal { archive(vec.x, vec.y, vec.z); } + + template + void serialize(Archive &archive, glm::ivec3 &vec) + { + archive(vec.x, vec.y, vec.z); + } + + template + void serialize(Archive &archive, glm::ivec2 &vec) + { + archive(vec.x, vec.y); + } + } \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/world/components.h b/deerith_engine_core/include/deerith/world/components.h index d0b322d..2d28554 100644 --- a/deerith_engine_core/include/deerith/world/components.h +++ b/deerith_engine_core/include/deerith/world/components.h @@ -16,14 +16,14 @@ namespace deerith }; // struct for linking a entity to a client - struct component_player_sync_input_t + struct component_client_sync_character_t { - sync_variable_t move_input; - sync_variable_t position; + sync_variable_t move_input; + sync_variable_t position; }; struct component_sync_coordinates_t { - sync_variable_t position; + sync_variable_t position; }; } \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/world/environment.h b/deerith_engine_core/include/deerith/world/environment.h index 28549a0..f512814 100644 --- a/deerith_engine_core/include/deerith/world/environment.h +++ b/deerith_engine_core/include/deerith/world/environment.h @@ -1,16 +1,67 @@ #pragma once +#include #include #include namespace deerith { - using voxel_coordinates_t = glm::ivec3; - using surface_coordinates_t = glm::ivec2; + inline constexpr int CLUSTER_SIZE = 32; + inline constexpr int MAX_CLUSTER_IN_SURFACE = 16; + inline constexpr int STARTING_CLUSTER_HEIGHT = -8; - // This sets the terrain layer for default comosition y > height -> 0; y <= height -> 1 - void set_surface_height(surface_coordinates_t surface_pos, int height); - void set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinates); + using surface_height_t = int16_t; + using surface_height_data_t = std::array, CLUSTER_SIZE>; + using cluster_voxel_type_id_data_t = std::array, CLUSTER_SIZE>, CLUSTER_SIZE>; - voxel_type_id_t get_voxel_id(voxel_coordinates_t coordinates); - const voxel_type_t &get_voxel(voxel_coordinates_t coordinates); + void set_surface_height(glm::ivec2 surface_pos, surface_height_t height); + + void set_voxel(voxel_type_id_t voxel_id, glm::ivec3 coordinates); + voxel_type_id_t get_voxel_id(glm::ivec3 coordinates); + const voxel_type_t &get_voxel(glm::ivec3 coordinates); + + void get_surface_height_raw_data(surface_height_data_t &data, glm::ivec2 surface_id); + void set_surface_height_raw_data(const surface_height_data_t &data, glm::ivec2 surface_id); + + void get_cluster_voxel_type_id_raw_data(cluster_voxel_type_id_data_t &data, glm::ivec2 surface_id, size_t cluster_height_id); + void set_cluster_voxel_type_id_raw_data(const cluster_voxel_type_id_data_t &data, glm::ivec2 surface_id, size_t cluster_height_id); + + int32_t get_cluster_last_tick_update(glm::ivec2 surface_id, size_t height_id); +} + +// UTILS +namespace deerith +{ + struct environment_settings_t + { + voxel_type_id_t default_air = 0; + voxel_type_id_t default_surface = 1; + surface_height_t default_height = 0; + }; + + struct surface_pos_hash_t + { + std::size_t operator()(const glm::ivec2 &id) const noexcept + { + const std::size_t h1 = std::hash{}(id.x); + const std::size_t h2 = std::hash{}(id.y); + + return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); + } + }; + + struct world_pos_hash_t + { + std::size_t operator()(const glm::ivec3 &pos) const noexcept + { + const std::size_t h1 = std::hash{}(pos.x); + const std::size_t h2 = std::hash{}(pos.y); + const std::size_t h3 = std::hash{}(pos.z); + + std::size_t seed = h1; + seed ^= h2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= h3 + 0x9e3779b9 + (seed << 6) + (seed >> 2); + + return seed; + } + }; } \ No newline at end of file diff --git a/deerith_engine_core/src/core/tick.cpp b/deerith_engine_core/src/core/tick.cpp index 933ee31..a9da017 100644 --- a/deerith_engine_core/src/core/tick.cpp +++ b/deerith_engine_core/src/core/tick.cpp @@ -6,6 +6,8 @@ namespace deerith { uint32_t tick_id = 0; + + std::chrono::steady_clock::time_point __chrono_start; } void deerith::set_tick(uint32_t v) @@ -41,4 +43,14 @@ void deerith::wait_till_next_tick() last_tick = clock::now(); tick_id++; +} + +void deerith::start_chrono() +{ + __chrono_start = std::chrono::steady_clock::now(); +} + +float deerith::get_chrono_ms() +{ + return std::chrono::duration(std::chrono::steady_clock::now() - __chrono_start).count(); } \ No newline at end of file diff --git a/deerith_engine_core/src/world/environment.cpp b/deerith_engine_core/src/world/environment.cpp index fc3a842..03628b6 100644 --- a/deerith_engine_core/src/world/environment.cpp +++ b/deerith_engine_core/src/world/environment.cpp @@ -1,47 +1,46 @@ #include +#include #include #include +#include #include #include #include -#define CLUSTER_SIZE 32 -#define MAX_CLUSTER_IN_SURFACE 16 -#define STARTING_CLUSTER_HEIGHT 8 - namespace deerith { - using surface_id_t = glm::ivec2; - using internal_voxel_id_t = glm::ivec3; - struct voxel_cluster_t { - voxel_type_id_t data[CLUSTER_SIZE][CLUSTER_SIZE][CLUSTER_SIZE] = {}; + voxel_cluster_t() : last_update_tick_id(get_world_tick()) {} + + uint32_t last_update_tick_id; + cluster_voxel_type_id_data_t data = {}; }; struct surface_t { - surface_id_t surface_id; + glm::ivec2 surface_id; - int layer_height[CLUSTER_SIZE][CLUSTER_SIZE] = {}; + surface_height_data_t __layer_height = {}; std::unique_ptr voxel_clusters[MAX_CLUSTER_IN_SURFACE] = {}; }; std::vector> surfaces; - std::unordered_map surface_id_index_map; + std::unordered_map surface_id_index_map; - voxel_type_id_t get_default_voxel(voxel_coordinates_t); + voxel_type_id_t get_default_voxel(glm::ivec3); - surface_id_t get_surface_id(voxel_coordinates_t coords); - internal_voxel_id_t get_internal_voxel_coords(voxel_coordinates_t coords); - internal_voxel_id_t get_internal_voxel_coords(surface_coordinates_t coords, int height = 0); + glm::ivec2 get_surface_id(glm::ivec3 coords); + glm::ivec2 get_surface_id(glm::ivec2 coords); + glm::ivec3 get_internal_voxel_coords(glm::ivec3 coords); + glm::ivec3 get_internal_voxel_coords(glm::ivec2 coords, int height = 0); size_t get_voxel_cluster_height_id(int height); - surface_t *create_surface(surface_id_t); + surface_t *create_surface(glm::ivec2); } -deerith::surface_t *deerith::create_surface(surface_id_t surface_id) +deerith::surface_t *deerith::create_surface(glm::ivec2 surface_id) { std::unique_ptr new_surface = std::make_unique(); size_t surface_index = surfaces.size(); @@ -52,7 +51,7 @@ deerith::surface_t *deerith::create_surface(surface_id_t surface_id) return surfaces.back().get(); } -deerith::voxel_type_id_t get_default_voxel(deerith::voxel_coordinates_t coords) +deerith::voxel_type_id_t deerith::get_default_voxel(glm::ivec3 coords) { if (coords.y > 0) { @@ -78,10 +77,10 @@ size_t deerith::get_voxel_cluster_height_id(int height) return cluster_height_id; } -deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(voxel_coordinates_t coords) +glm::ivec3 deerith::get_internal_voxel_coords(glm::ivec3 coords) { // this will invert negatives coords but we don't mind - internal_voxel_id_t ic = {}; + glm::ivec3 ic = {}; ic.x = std::abs(coords.x % (CLUSTER_SIZE)); ic.y = std::abs(coords.y % (CLUSTER_SIZE)); ic.z = std::abs(coords.z % (CLUSTER_SIZE)); @@ -89,10 +88,10 @@ deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(voxel_coordinate return ic; } -deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(surface_coordinates_t coords, int height = 0) +glm::ivec3 deerith::get_internal_voxel_coords(glm::ivec2 coords, int height) { // this will invert negatives coords but we don't mind - internal_voxel_id_t ic = {}; + glm::ivec3 ic = {}; ic.x = std::abs(coords.x % (CLUSTER_SIZE)); ic.y = std::abs(height % (CLUSTER_SIZE)); ic.z = std::abs(coords.y % (CLUSTER_SIZE)); @@ -100,18 +99,18 @@ deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(surface_coordina return ic; } -deerith::surface_id_t deerith::get_surface_id(voxel_coordinates_t coords) +glm::ivec2 deerith::get_surface_id(glm::ivec3 coords) { - surface_id_t surface_id = {}; + glm::ivec2 surface_id = {}; surface_id.x = std::floor(static_cast(coords.x) / static_cast(CLUSTER_SIZE)); surface_id.y = std::floor(static_cast(coords.z) / static_cast(CLUSTER_SIZE)); return surface_id; } -deerith::surface_id_t deerith::get_surface_id(surface_coordinates_t coords) +glm::ivec2 deerith::get_surface_id(glm::ivec2 coords) { - surface_id_t surface_id = {}; + glm::ivec2 surface_id = {}; surface_id.x = std::floor(static_cast(coords.x) / static_cast(CLUSTER_SIZE)); surface_id.y = std::floor(static_cast(coords.y) / static_cast(CLUSTER_SIZE)); @@ -119,9 +118,9 @@ deerith::surface_id_t deerith::get_surface_id(surface_coordinates_t coords) } // This sets the terrain layer for default comosition y > height -> 0; y <= height -> 1 -void deerith::set_surface_height(surface_coordinates_t surface_pos, int height) +void deerith::set_surface_height(glm::ivec2 surface_pos, surface_height_t height) { - surface_id_t surface_id = get_surface_id(surface_pos); + glm::ivec2 surface_id = get_surface_id(surface_pos); surface_t *surface = nullptr; if (surface_id_index_map.contains(surface_id)) @@ -135,13 +134,13 @@ void deerith::set_surface_height(surface_coordinates_t surface_pos, int height) surface = create_surface(surface_id); } - internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(surface_pos, height); - surface->layer_height[internal_voxel_id.x][internal_voxel_id.z] = height; + glm::ivec3 internal_voxel_id = get_internal_voxel_coords(surface_pos, height); + surface->__layer_height[internal_voxel_id.x][internal_voxel_id.z] = height; } -void deerith::set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinates) +void deerith::set_voxel(voxel_type_id_t voxel_id, glm::ivec3 coordinates) { - surface_id_t surface_id = get_surface_id(coordinates); + glm::ivec2 surface_id = get_surface_id(coordinates); surface_t *surface = nullptr; if (surface_id_index_map.contains(surface_id)) @@ -155,7 +154,7 @@ void deerith::set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinate surface = create_surface(surface_id); } - internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(coordinates); + glm::ivec3 internal_voxel_id = get_internal_voxel_coords(coordinates); size_t cluster_height_id = get_voxel_cluster_height_id(coordinates.y); if (cluster_height_id >= MAX_CLUSTER_IN_SURFACE) @@ -171,12 +170,13 @@ void deerith::set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinate cluster = surface->voxel_clusters[cluster_height_id].get(); } + cluster->last_update_tick_id = get_world_tick(); cluster->data[internal_voxel_id.x][internal_voxel_id.y][internal_voxel_id.z] = voxel_id; } -deerith::voxel_type_id_t deerith::get_voxel_id(voxel_coordinates_t coordinates) +deerith::voxel_type_id_t deerith::get_voxel_id(glm::ivec3 coordinates) { - surface_id_t surface_id = get_surface_id(coordinates); + glm::ivec2 surface_id = get_surface_id(coordinates); if (!surface_id_index_map.contains(surface_id)) { @@ -197,11 +197,11 @@ deerith::voxel_type_id_t deerith::get_voxel_id(voxel_coordinates_t coordinates) return get_default_voxel(coordinates); } - internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(coordinates); + glm::ivec3 internal_voxel_id = get_internal_voxel_coords(coordinates); voxel_cluster_t *cluster = surface->voxel_clusters[cluster_height_id].get(); if (cluster == nullptr) { - if (coordinates.y <= surface->layer_height[internal_voxel_id.x][internal_voxel_id.y]) + if (coordinates.y <= surface->__layer_height[internal_voxel_id.x][internal_voxel_id.y]) { return 1; } @@ -214,7 +214,138 @@ deerith::voxel_type_id_t deerith::get_voxel_id(voxel_coordinates_t coordinates) return cluster->data[internal_voxel_id.x][internal_voxel_id.y][internal_voxel_id.z]; } -const deerith::voxel_type_t &deerith::get_voxel(voxel_coordinates_t coordinates) +const deerith::voxel_type_t &deerith::get_voxel(glm::ivec3 coordinates) { return get_voxel_type(get_voxel_id(coordinates)); +} + +void deerith::get_surface_height_raw_data(surface_height_data_t &data, glm::ivec2 surface_pos) +{ + glm::ivec2 surface_id = get_surface_id(surface_pos); + + surface_t *surface = nullptr; + + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + std::memcpy(data.data(), surface->__layer_height.data(), sizeof(data)); +} + +void deerith::set_surface_height_raw_data(const surface_height_data_t &data, glm::ivec2 surface_pos) +{ + glm::ivec2 surface_id = get_surface_id(surface_pos); + + surface_t *surface = nullptr; + + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + std::memcpy(surface->__layer_height.data(), data.data(), sizeof(data)); +} + +int32_t deerith::get_cluster_last_tick_update(glm::ivec2 surface_id, size_t height_id) +{ + if (!surface_id_index_map.contains(surface_id)) + { + return -1; + } + + size_t surface_index = surface_id_index_map[surface_id]; + surface_t *surface = surfaces[surface_index].get(); + + if (surface == nullptr) + { + return -1; + } + + if (height_id >= MAX_CLUSTER_IN_SURFACE) + { + return -1; + } + + voxel_cluster_t *cluster = surface->voxel_clusters[height_id].get(); + if (cluster == nullptr) + { + return -1; + } + + return cluster->last_update_tick_id; +} + +void deerith::get_cluster_voxel_type_id_raw_data(cluster_voxel_type_id_data_t &data, glm::ivec2 surface_id, size_t cluster_height_id) +{ + if (cluster_height_id >= MAX_CLUSTER_IN_SURFACE) + { + deerith_warn("tried to read voxel data out of bounds"); + return; + } + + surface_t *surface = nullptr; + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + voxel_cluster_t *cluster = surface->voxel_clusters[cluster_height_id].get(); + if (cluster == nullptr) + { + surface->voxel_clusters[cluster_height_id] = std::make_unique(); + cluster = surface->voxel_clusters[cluster_height_id].get(); + } + + data = cluster->data; +} + +void deerith::set_cluster_voxel_type_id_raw_data(const cluster_voxel_type_id_data_t &data, glm::ivec2 surface_id, size_t cluster_height_id) +{ + if (cluster_height_id >= MAX_CLUSTER_IN_SURFACE) + { + deerith_warn("tried to write voxel data out of bounds"); + return; + } + + surface_t *surface = nullptr; + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + voxel_cluster_t *cluster = surface->voxel_clusters[cluster_height_id].get(); + + if (cluster == nullptr) + { + surface->voxel_clusters[cluster_height_id] = std::make_unique(); + cluster = surface->voxel_clusters[cluster_height_id].get(); + } + + cluster->data = data; + cluster->last_update_tick_id = get_world_tick(); } \ No newline at end of file diff --git a/deerith_engine_server/include/deerith/server/network/network_internals.h b/deerith_engine_server/include/deerith/server/internals/network.h similarity index 57% rename from deerith_engine_server/include/deerith/server/network/network_internals.h rename to deerith_engine_server/include/deerith/server/internals/network.h index 414efe5..b491512 100644 --- a/deerith_engine_server/include/deerith/server/network/network_internals.h +++ b/deerith_engine_server/include/deerith/server/internals/network.h @@ -1,14 +1,8 @@ #pragma once -#include -#include namespace deerith { - int init_network(); - void shutdown_network(); - bool init_server(int port); void flush_network_events(); - void load_base_protocols(); } \ No newline at end of file diff --git a/deerith_engine_server/include/deerith/server/world/world_internals.h b/deerith_engine_server/include/deerith/server/internals/world.h similarity index 71% rename from deerith_engine_server/include/deerith/server/world/world_internals.h rename to deerith_engine_server/include/deerith/server/internals/world.h index 6985615..78c106c 100644 --- a/deerith_engine_server/include/deerith/server/world/world_internals.h +++ b/deerith_engine_server/include/deerith/server/internals/world.h @@ -4,17 +4,21 @@ namespace deerith { - void update_players_characters(); + // Client lifecycle void client_connects(client_t *client); void client_disconnects(client_t *client); - void send_entity_data(); - - void send_create_entity_to_all_clients(entity_t ent); + // Entity management void send_create_entity_to_client(entity_t ent, client_t *client); - void send_create_actual_entities_to_client(client_t *client); - - void send_voxel_data_to_client(client_t *client); - + void send_create_entity_to_all_clients(entity_t ent); + void send_create_all_entities_to_client(client_t *client); void send_delete_entity_to_all_clients(entity_t ent); + + // Player updates + void update_players_characters(); + + // Data synchronization + void send_entity_data(); + void send_voxel_data_to_client(client_t *client); + void send_clients_environment_data(); } \ No newline at end of file diff --git a/deerith_engine_server/include/deerith/server/network.h b/deerith_engine_server/include/deerith/server/network.h new file mode 100644 index 0000000..8c882c7 --- /dev/null +++ b/deerith_engine_server/include/deerith/server/network.h @@ -0,0 +1,7 @@ +#pragma once + +namespace deerith +{ + int init_network(); + void shutdown_network(); +} \ No newline at end of file diff --git a/deerith_engine_server/src/core.cpp b/deerith_engine_server/src/core.cpp index f257967..676ad15 100644 --- a/deerith_engine_server/src/core.cpp +++ b/deerith_engine_server/src/core.cpp @@ -1,6 +1,6 @@ #include -#include +#include namespace deerith { diff --git a/deerith_engine_server/src/network/network.cpp b/deerith_engine_server/src/network/network.cpp index 67bd929..331f7a7 100644 --- a/deerith_engine_server/src/network/network.cpp +++ b/deerith_engine_server/src/network/network.cpp @@ -1,9 +1,13 @@ -#include +#include + #include #include #include #include +#include +#include +#include #include @@ -11,33 +15,15 @@ #include #include -#include -#include - namespace deerith { ENetHost *server; - std::vector> clients; void create_client(ENetPeer *peer); void delete_client(client_t *client); } -void deerith::delete_client(client_t *client) -{ - auto it = std::find_if( - clients.begin(), - clients.end(), - [client](const std::unique_ptr &ptr) - { return ptr.get() == client; }); - - if (it != clients.end()) - { - clients.erase(it); - } -} - bool deerith::init_server(int port) { ENetAddress address = {0}; @@ -111,4 +97,16 @@ void deerith::create_client(ENetPeer *peer) clients.push_back(std::move(client)); client_connects((client_t *)peer->data); +} + +void deerith::delete_client(client_t *client) +{ + for (auto it = clients.begin(); it != clients.end(); ++it) + { + if (it->get() == client) + { + clients.erase(it); + return; + } + } } \ No newline at end of file diff --git a/deerith_engine_server/src/world/client_managment.cpp b/deerith_engine_server/src/world/client_managment.cpp index 32d64b7..60225f9 100644 --- a/deerith_engine_server/src/world/client_managment.cpp +++ b/deerith_engine_server/src/world/client_managment.cpp @@ -6,8 +6,8 @@ #include -#include -#include +#include +#include void deerith::client_connects(client_t *client) { @@ -21,7 +21,7 @@ void deerith::client_connects(client_t *client) // create entity player entity entity_t entity = create_entity(); - component_player_sync_input_t &position_sync = add_component(entity); + component_client_sync_character_t &position_sync = add_component(entity); packet_create_player_entity_t create_player_entity; router_send_packet(create_player_entity, client); @@ -32,12 +32,12 @@ void deerith::client_connects(client_t *client) send_create_entity_to_all_clients(entity); - // we do this the last to avoid send_create_entity_to_all_clients send_create_actual_entities_to_client create the same entity for the player + // we do this the last to avoid send_create_entity_to_all_clients send_create_all_entities_to_client create the same entity for the player component_client_link_t &link = add_component(entity); client->entity_id = entity; link.client = client; - send_create_actual_entities_to_client(client); + send_create_all_entities_to_client(client); } void deerith::client_disconnects(client_t *client) diff --git a/deerith_engine_server/src/world/player_communication.cpp b/deerith_engine_server/src/world/player_communication.cpp index d4bb6d4..7f0da5e 100644 --- a/deerith_engine_server/src/world/player_communication.cpp +++ b/deerith_engine_server/src/world/player_communication.cpp @@ -1,18 +1,13 @@ #include + #include #include #include #include -#include +#include +#include -#include -#include - -namespace deerith -{ - -} void deerith::load_base_protocols() { router_add_packet_processor(); @@ -22,7 +17,7 @@ template <> void deerith::process_packet(packet_update_player_input_t &packet, client_t *client) { entity_t entity = client->entity_id; - component_player_sync_input_t &sync_client = get_component(entity); + component_client_sync_character_t &sync_client = get_component(entity); packet.input_transport.recive(sync_client.move_input); packet.position_transport.recive(sync_client.position); @@ -74,7 +69,7 @@ void deerith::send_delete_entity_to_all_clients(entity_t ent) } } -void deerith::send_create_actual_entities_to_client(client_t *client) +void deerith::send_create_all_entities_to_client(client_t *client) { auto entities_view = get_entity_registry().view(); diff --git a/deerith_engine_server/src/world/voxel_data_managment.cpp b/deerith_engine_server/src/world/voxel_data_managment.cpp index 06573ab..c9b4087 100644 --- a/deerith_engine_server/src/world/voxel_data_managment.cpp +++ b/deerith_engine_server/src/world/voxel_data_managment.cpp @@ -1,10 +1,23 @@ -#include +#include + +#include #include #include +#include namespace deerith { + struct component_client_environment_knowledge_t + { + std::unordered_map surface_knowledge; + 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 *, component_client_environment_knowledge_t &knowledge, glm::ivec2 position); + + void send_surface_info_to_client(client_t *, glm::ivec2); + void send_cluster_info_to_client(client_t *, glm::ivec2, size_t); } void deerith::send_voxel_data_to_client(client_t *client) @@ -14,4 +27,107 @@ void deerith::send_voxel_data_to_client(client_t *client) 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}; + + if (knowledge.surface_knowledge.contains(surface_id) && knowledge.surface_knowledge[surface_id] == true) + { + if (check_client_cluster_knowledge(client, knowledge, surface_id)) + { + return; + } + } + + if (!knowledge.surface_knowledge.contains(surface_id) || knowledge.surface_knowledge[surface_id] == false) + { + knowledge.surface_knowledge[surface_id] = true; + send_surface_info_to_client(client, surface_id); + return; + } + } + } +} + +void deerith::send_surface_info_to_client(client_t *client, glm::ivec2 surface_id) +{ + start_chrono(); + packet_surface_data_t surface_data; + surface_data.surface_id = surface_id; + surface_data.__surface_data = std::make_unique(); + + get_surface_height_raw_data(*surface_data.__surface_data, surface_id); + + router_send_packet(surface_data, client); +} + +bool deerith::check_client_cluster_knowledge(client_t *client, component_client_environment_knowledge_t &knowledge, glm::ivec2 position) +{ + for (int y = 0; y < MAX_CLUSTER_IN_SURFACE; y++) + { + int32_t cluster_last_update = get_cluster_last_tick_update(position, y); + if (cluster_last_update < 0) + { + continue; + } + + glm::ivec3 cluster_pos = glm::ivec3(position.x, y, position.y); + int32_t actual_cluster_kknowledge = -1; + if (knowledge.cluster_knowledge.contains(cluster_pos)) + { + actual_cluster_kknowledge = knowledge.cluster_knowledge[cluster_pos]; + } + + if (actual_cluster_kknowledge < cluster_last_update) + { + knowledge.cluster_knowledge[cluster_pos] = cluster_last_update; + send_cluster_info_to_client(client, position, y); + return true; + } + } + + return false; +} + +void deerith::send_cluster_info_to_client(client_t *client, glm::ivec2 surface_pos, size_t cluster_height_id) +{ + start_chrono(); + packet_cluster_data_t cluster_data; + cluster_data.surface_id = surface_pos; + cluster_data.cluster_height_id = cluster_height_id; + cluster_data.__cluster_data = std::make_unique(); + + get_cluster_voxel_type_id_raw_data(*cluster_data.__cluster_data, surface_pos, cluster_height_id); + + router_send_packet(cluster_data, client); + deerith_trace("sent cluster data to client in {}ms", get_chrono_ms()); } \ No newline at end of file diff --git a/deerith_engine_server/src/world/world.cpp b/deerith_engine_server/src/world/world.cpp index 3ac7cd5..93084c5 100644 --- a/deerith_engine_server/src/world/world.cpp +++ b/deerith_engine_server/src/world/world.cpp @@ -1,37 +1,16 @@ +#include #include -#include -#include -#include -#include - -#include -#include - -#include -#include +#include +#include namespace deerith { - int world_tick = 0; - void world_simulation(); - - std::atomic running = true; - - void create_client(ENetPeer *peer); - void handle_signal(int signal); -} - -void deerith::handle_signal(int signal) -{ - if (signal == SIGTERM) - running = false; + void server_loop(); } void deerith::run_world(int port) { - std::signal(SIGTERM, handle_signal); - if (!init_server(port)) { deerith_error("could not init server"); @@ -39,13 +18,13 @@ void deerith::run_world(int port) } deerith_trace("server init on port {}", port); - while (running) + while (true) { - world_simulation(); + server_loop(); } } -void deerith::world_simulation() +void deerith::server_loop() { flush_network_events(); @@ -54,6 +33,8 @@ void deerith::world_simulation() if (get_world_tick() % 2 == 0) { + send_clients_environment_data(); + send_entity_data(); } diff --git a/deerith_engine_server/src/world/world_simulation.cpp b/deerith_engine_server/src/world/world_simulation.cpp index 1318466..bd466b6 100644 --- a/deerith_engine_server/src/world/world_simulation.cpp +++ b/deerith_engine_server/src/world/world_simulation.cpp @@ -1,17 +1,16 @@ -#include +#include -#include #include #include #include void deerith::update_players_characters() { - auto view = get_entity_registry().view(); + auto view = get_entity_registry().view(); for (auto [entity, position_input, client, sync_coords] : view.each()) { - glm::vec2 ps{}; + glm::vec3 ps{}; if (position_input.position.read_synced(ps)) { sync_coords.position = ps; @@ -32,7 +31,7 @@ void deerith::send_entity_data() { sync_entities_coordinates.entities_ids.push_back(network_id.network_id); sync_entities_coordinates.positions_to_update.push_back({}); - sync_variable_transport_t &position_trasport = sync_entities_coordinates.positions_to_update.back(); + sync_variable_transport_t &position_trasport = sync_entities_coordinates.positions_to_update.back(); position_trasport.load(sync_coords.position); } diff --git a/sandbox/src/build_world.cpp b/sandbox/src/build_world.cpp index e69de29..a34f022 100644 --- a/sandbox/src/build_world.cpp +++ b/sandbox/src/build_world.cpp @@ -0,0 +1,14 @@ +#include "world.h" + +#include + +namespace deerith +{ + +} + +void sandbox::build_world() +{ + deerith::set_surface_height(glm::ivec2(2, 2), 5); + deerith::set_voxel(1, glm::vec3(2, 2, 2)); +} \ No newline at end of file diff --git a/sandbox/src/main.cpp b/sandbox/src/main.cpp index b558749..d5774d0 100644 --- a/sandbox/src/main.cpp +++ b/sandbox/src/main.cpp @@ -18,7 +18,7 @@ int main(int argc, const char **argv) sandbox::define_voxel_materials(); sandbox::define_voxels_types(); - // sandbox::build_world(); + sandbox::build_world(); #ifdef DEBUG if (cmdl[{"-s", "--single"}] && !deerith::execute_client("../deerith_client/DeerithClient", port))