mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
refactor(gameplay): update systems per entity with chunk check
Refactor server entity update flow to process entities individually, skipping those whose chunk is not loaded. System update methods now accept a single entity instead of iterating the full registry view, and `ServerWorld::get_chunk_ref_count` is added to determine if an entity's chunk is active.
This commit is contained in:
@@ -44,9 +44,10 @@ private:
|
||||
void handle_entity_destory(EntityID id);
|
||||
void handle_task();
|
||||
void send_all_entities(std::shared_ptr<Session>& session);
|
||||
void update_ai();
|
||||
void update_move();
|
||||
void update_send();
|
||||
void update_ai(entt::entity e);
|
||||
void update_move(entt::entity e);
|
||||
void update_send(entt::entity e,
|
||||
std::span<std::shared_ptr<Session>> sessions);
|
||||
template <typename... Args>
|
||||
EntityID create_entity_in_factory(Args&&... args) {
|
||||
auto entity = m_registry.create();
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
|
||||
std::vector<std::shared_ptr<Session>> get_all_session() const;
|
||||
|
||||
uint32_t get_chunk_ref_count(const glm::vec3& pos) const;
|
||||
|
||||
int get_block(const glm::ivec3& block_pos) const override;
|
||||
bool is_solid(const glm::ivec3& block_pos) const override;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const override;
|
||||
|
||||
@@ -8,7 +8,8 @@ class PhysicalSystem {
|
||||
public:
|
||||
static glm::vec3 get_move_distance(const TickVelocity& v);
|
||||
|
||||
static void update(ServerWorld& world, entt::registry& registry);
|
||||
static void update(ServerWorld& world, entt::registry& registry,
|
||||
entt::entity e);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
namespace Cubed {
|
||||
class SpeedSystem {
|
||||
public:
|
||||
static void update(float dt, entt::registry& registry);
|
||||
static void update(float dt, entt::registry& registry, entt::entity e);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace Cubed {
|
||||
class WanderAISystem {
|
||||
public:
|
||||
static void update(entt::registry& registry);
|
||||
static void update(entt::registry& registry, entt::entity e);
|
||||
|
||||
private:
|
||||
static void do_ai(BaseServerCreature& creature, MoveBoost& move_boost);
|
||||
|
||||
@@ -31,26 +31,40 @@ void ServerEntityManager::init() {
|
||||
}
|
||||
void ServerEntityManager::update() {
|
||||
handle_task();
|
||||
update_ai();
|
||||
update_move();
|
||||
|
||||
update_send();
|
||||
}
|
||||
|
||||
void ServerEntityManager::update_ai() { WanderAISystem::update(m_registry); }
|
||||
|
||||
void ServerEntityManager::update_move() {
|
||||
SpeedSystem::update(
|
||||
static_cast<float>(m_world.get_per_tick_time()) / 1000.0f, m_registry);
|
||||
PhysicalSystem::update(m_world, m_registry);
|
||||
}
|
||||
|
||||
void ServerEntityManager::update_send() {
|
||||
auto view = m_registry.view<BaseServerCreature>();
|
||||
auto sessions = m_world.get_all_session();
|
||||
auto view = m_registry.view<Entity, BaseServerCreature>();
|
||||
for (auto e : view) {
|
||||
const auto& c = view.get<BaseServerCreature>(e);
|
||||
if (!m_world.get_chunk_ref_count(c.transform.position.value)) {
|
||||
continue;
|
||||
}
|
||||
update_ai(e);
|
||||
update_move(e);
|
||||
update_send(e, sessions);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& e : view) {
|
||||
auto [entity, creature] = view.get<Entity, BaseServerCreature>(e);
|
||||
void ServerEntityManager::update_ai(entt::entity e) {
|
||||
WanderAISystem::update(m_registry, e);
|
||||
}
|
||||
|
||||
void ServerEntityManager::update_move(entt::entity e) {
|
||||
SpeedSystem::update(static_cast<float>(m_world.get_per_tick_time()) /
|
||||
1000.0f,
|
||||
m_registry, e);
|
||||
PhysicalSystem::update(m_world, m_registry, e);
|
||||
}
|
||||
|
||||
void ServerEntityManager::update_send(
|
||||
entt::entity e, std::span<std::shared_ptr<Session>> sessions) {
|
||||
|
||||
if (!m_registry.all_of<Entity, BaseServerCreature>(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto [entity, creature] =
|
||||
m_registry.get<Entity, BaseServerCreature>(e);
|
||||
Arena arena;
|
||||
auto* p = Arena::Create<S2CEntityUpdate>(&arena);
|
||||
p->set_id(entity.id);
|
||||
@@ -63,7 +77,6 @@ void ServerEntityManager::update_send() {
|
||||
s->send(make_packet(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerEntityManager::handle_task() {
|
||||
TaskPair pair;
|
||||
|
||||
@@ -1020,6 +1020,15 @@ std::vector<std::shared_ptr<Session>> ServerWorld::get_all_session() const {
|
||||
return sessions;
|
||||
}
|
||||
|
||||
uint32_t ServerWorld::get_chunk_ref_count(const glm::vec3& pos) const {
|
||||
ChunkPos p = get_chunk_pos(pos.x, pos.z);
|
||||
chunk_cacc cacc;
|
||||
if (!m_chunks.find(cacc, p)) {
|
||||
return 0;
|
||||
}
|
||||
return cacc->second.ref_count;
|
||||
}
|
||||
|
||||
int ServerWorld::get_block(const glm::ivec3& block_pos) const {
|
||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||
chunk_cacc cacc;
|
||||
|
||||
@@ -102,17 +102,19 @@ bool update_z(const glm::vec3& pos, const glm::vec3& distance,
|
||||
|
||||
} // namespace
|
||||
|
||||
void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) {
|
||||
void PhysicalSystem::update(ServerWorld& world, entt::registry& registry,
|
||||
entt::entity e) {
|
||||
|
||||
auto view = registry.view<BaseServerCreature>();
|
||||
for (auto e : view) {
|
||||
auto& creature = view.get<BaseServerCreature>(e);
|
||||
if (!registry.all_of<BaseServerCreature>(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& creature = registry.get<BaseServerCreature>(e);
|
||||
auto distance = get_move_distance(creature.velocity);
|
||||
auto box = HitboxManager::hitbox(creature.hitbox);
|
||||
auto& pos = creature.transform.position.value;
|
||||
auto& v = creature.velocity;
|
||||
bool ground =
|
||||
!update_y(pos, glm::vec3{0.0f, -0.1f, 0.0f}, world, box.box);
|
||||
bool ground = !update_y(pos, glm::vec3{0.0f, -0.1f, 0.0f}, world, box.box);
|
||||
bool stepped = false;
|
||||
if (update_y(pos, distance, world, box.box)) {
|
||||
pos.y += distance.y;
|
||||
@@ -159,7 +161,6 @@ void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 PhysicalSystem::get_move_distance(const TickVelocity& v) {
|
||||
return v.value; // Per-tick forward distance equals the velocity magnitud
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
void SpeedSystem::update(float dt, entt::registry& registry) {
|
||||
auto view = registry.view<BaseServerCreature, MoveBoost>();
|
||||
void SpeedSystem::update(float dt, entt::registry& registry, entt::entity e) {
|
||||
if (!registry.all_of<BaseServerCreature, MoveBoost>(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto e : view) {
|
||||
auto [creature, moveboost] = view.get<BaseServerCreature, MoveBoost>(e);
|
||||
auto [creature, moveboost] = registry.get<BaseServerCreature, MoveBoost>(e);
|
||||
auto& v = creature.velocity.value;
|
||||
if (moveboost.count <= moveboost.duration) {
|
||||
++moveboost.count;
|
||||
v += creature.transform.direction.value *
|
||||
creature.movement.acceleration;
|
||||
v +=
|
||||
creature.transform.direction.value * creature.movement.acceleration;
|
||||
} else {
|
||||
// Decelerated by friction in all directions
|
||||
auto decay = [](float& c, float d) {
|
||||
@@ -37,6 +38,5 @@ void SpeedSystem::update(float dt, entt::registry& registry) {
|
||||
v_clamp(v.y, creature.velocity.max.y);
|
||||
v_clamp(v.z, creature.velocity.max.z);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -10,20 +10,20 @@ constexpr double MOVE_PROBABILITY = 0.01;
|
||||
} // namespace
|
||||
|
||||
namespace Cubed {
|
||||
void WanderAISystem::update(entt::registry& registry) {
|
||||
auto view =
|
||||
registry.view<AIBase, WanderAITag, BaseServerCreature, MoveBoost>();
|
||||
void WanderAISystem::update(entt::registry& registry, entt::entity e) {
|
||||
if (!registry.all_of<AIBase, WanderAITag, BaseServerCreature, MoveBoost>(
|
||||
e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto e : view) {
|
||||
auto [ai, creature, move_boost] =
|
||||
view.get<AIBase, BaseServerCreature, MoveBoost>(e);
|
||||
registry.get<AIBase, BaseServerCreature, MoveBoost>(e);
|
||||
++ai.count;
|
||||
if (ai.count >= ai.interval) {
|
||||
ai.count = 0;
|
||||
do_ai(creature, move_boost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WanderAISystem::do_ai(BaseServerCreature& creature,
|
||||
MoveBoost& move_boost) {
|
||||
|
||||
Reference in New Issue
Block a user