2026-07-18 14:31:15 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "ZoneProxy.hpp"
|
|
|
|
|
#include "interest_management/FixedGrid.hpp"
|
|
|
|
|
#include "network/SessionId.hpp"
|
|
|
|
|
#include "systems/Interest.hpp"
|
|
|
|
|
#include "systems/InterestSystem.hpp"
|
|
|
|
|
#include "world/JoltPhysicsWorld.hpp"
|
|
|
|
|
#include "world/World.hpp"
|
|
|
|
|
|
|
|
|
|
#include "PlayerMove.pb.h"
|
|
|
|
|
|
|
|
|
|
#include <entt/entt.hpp>
|
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace tw::net {
|
|
|
|
|
|
|
|
|
|
using SpatialBackendType = im::FixedGrid<500, 500>;
|
|
|
|
|
|
|
|
|
|
static constexpr float kNeighborBorderOverlap = 100.0f;
|
|
|
|
|
|
2026-08-03 23:30:18 +02:00
|
|
|
/**
|
|
|
|
|
* Manages one zone: contains state of all entities inside and does logic for them.
|
|
|
|
|
*/
|
2026-07-18 14:31:15 +02:00
|
|
|
class ZoneManager : public ZoneProxy {
|
|
|
|
|
struct NeighborEntry {
|
|
|
|
|
ZoneProxy* proxy;
|
|
|
|
|
im::InterestId interest_id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<World> m_world;
|
|
|
|
|
JoltPhysicsWorld m_physics_world;
|
|
|
|
|
std::unique_ptr<SpatialBackendType> m_spatial_backend;
|
|
|
|
|
std::unique_ptr<im::InterestSystem<SpatialBackendType>> m_interest_system;
|
|
|
|
|
|
|
|
|
|
std::unordered_map<im::InterestId, entt::entity> m_client_entities;
|
2026-08-03 23:30:18 +02:00
|
|
|
std::unordered_map<entt::entity, im::InterestId> m_entity_sessions;
|
|
|
|
|
std::unordered_map<im::InterestId, uint32_t> m_session_input_frame;
|
|
|
|
|
std::unordered_map<im::InterestId, uint32_t> m_session_acked_frame;
|
2026-07-18 14:31:15 +02:00
|
|
|
std::vector<NeighborEntry> m_neighbors;
|
|
|
|
|
uint32_t m_next_neighbor_id = 0x80000000u;
|
|
|
|
|
|
|
|
|
|
entt::entity client_entity(im::InterestId interest_id) const;
|
|
|
|
|
void check_neighbor_transfers();
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
entt::registry& registry() { return m_world->registry(); }
|
|
|
|
|
|
|
|
|
|
im::InterestSystem<SpatialBackendType>* interest() const {
|
|
|
|
|
return m_interest_system.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZoneManager(im::AreaBounds zone_bounds);
|
|
|
|
|
|
|
|
|
|
im::AreaBounds area() const override;
|
|
|
|
|
|
|
|
|
|
void transfer_entity(EntityInfo&& info) override;
|
|
|
|
|
|
|
|
|
|
entt::entity spawn_entity(EntityInfo&& info);
|
|
|
|
|
|
|
|
|
|
void add_client(im::InterestId interest_id, entt::entity entity);
|
|
|
|
|
|
|
|
|
|
void on_player_move(SessionId session_id, mmo::PlayerMoveMessage&& message);
|
|
|
|
|
|
|
|
|
|
void register_neighbor_zone(ZoneProxy* neighbor);
|
|
|
|
|
|
|
|
|
|
const im::Interest* get_interest(im::InterestId id) const;
|
|
|
|
|
|
2026-07-22 17:34:44 +02:00
|
|
|
uint32_t acked_input_frame(im::InterestId interest_id) const;
|
|
|
|
|
|
2026-08-03 23:30:18 +02:00
|
|
|
void update(uint32_t frame_idx, float delta_time);
|
2026-07-18 14:31:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace tw::net
|