mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +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_entity_destory(EntityID id);
|
||||||
void handle_task();
|
void handle_task();
|
||||||
void send_all_entities(std::shared_ptr<Session>& session);
|
void send_all_entities(std::shared_ptr<Session>& session);
|
||||||
void update_ai();
|
void update_ai(entt::entity e);
|
||||||
void update_move();
|
void update_move(entt::entity e);
|
||||||
void update_send();
|
void update_send(entt::entity e,
|
||||||
|
std::span<std::shared_ptr<Session>> sessions);
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
EntityID create_entity_in_factory(Args&&... args) {
|
EntityID create_entity_in_factory(Args&&... args) {
|
||||||
auto entity = m_registry.create();
|
auto entity = m_registry.create();
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ public:
|
|||||||
|
|
||||||
std::vector<std::shared_ptr<Session>> get_all_session() const;
|
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;
|
int get_block(const glm::ivec3& block_pos) const override;
|
||||||
bool is_solid(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;
|
bool can_pass_block(const glm::ivec3& block_pos) const override;
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ class PhysicalSystem {
|
|||||||
public:
|
public:
|
||||||
static glm::vec3 get_move_distance(const TickVelocity& v);
|
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:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
class SpeedSystem {
|
class SpeedSystem {
|
||||||
public:
|
public:
|
||||||
static void update(float dt, entt::registry& registry);
|
static void update(float dt, entt::registry& registry, entt::entity e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
class WanderAISystem {
|
class WanderAISystem {
|
||||||
public:
|
public:
|
||||||
static void update(entt::registry& registry);
|
static void update(entt::registry& registry, entt::entity e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void do_ai(BaseServerCreature& creature, MoveBoost& move_boost);
|
static void do_ai(BaseServerCreature& creature, MoveBoost& move_boost);
|
||||||
|
|||||||
@@ -31,37 +31,50 @@ void ServerEntityManager::init() {
|
|||||||
}
|
}
|
||||||
void ServerEntityManager::update() {
|
void ServerEntityManager::update() {
|
||||||
handle_task();
|
handle_task();
|
||||||
update_ai();
|
|
||||||
update_move();
|
|
||||||
|
|
||||||
update_send();
|
auto view = m_registry.view<BaseServerCreature>();
|
||||||
}
|
|
||||||
|
|
||||||
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 sessions = m_world.get_all_session();
|
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);
|
||||||
for (auto& e : view) {
|
if (!m_world.get_chunk_ref_count(c.transform.position.value)) {
|
||||||
auto [entity, creature] = view.get<Entity, BaseServerCreature>(e);
|
continue;
|
||||||
Arena arena;
|
|
||||||
auto* p = Arena::Create<S2CEntityUpdate>(&arena);
|
|
||||||
p->set_id(entity.id);
|
|
||||||
Tools::set_net_pos(p, creature.transform.position.value);
|
|
||||||
|
|
||||||
Tools::set_net_vec3(p->mutable_direction(),
|
|
||||||
creature.transform.direction.value);
|
|
||||||
|
|
||||||
for (auto& s : sessions) {
|
|
||||||
s->send(make_packet(p));
|
|
||||||
}
|
}
|
||||||
|
update_ai(e);
|
||||||
|
update_move(e);
|
||||||
|
update_send(e, sessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
Tools::set_net_pos(p, creature.transform.position.value);
|
||||||
|
|
||||||
|
Tools::set_net_vec3(p->mutable_direction(),
|
||||||
|
creature.transform.direction.value);
|
||||||
|
|
||||||
|
for (auto& s : sessions) {
|
||||||
|
s->send(make_packet(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1020,6 +1020,15 @@ std::vector<std::shared_ptr<Session>> ServerWorld::get_all_session() const {
|
|||||||
return sessions;
|
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 {
|
int ServerWorld::get_block(const glm::ivec3& block_pos) const {
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||||
chunk_cacc cacc;
|
chunk_cacc cacc;
|
||||||
|
|||||||
@@ -102,61 +102,62 @@ bool update_z(const glm::vec3& pos, const glm::vec3& distance,
|
|||||||
|
|
||||||
} // namespace
|
} // 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>();
|
if (!registry.all_of<BaseServerCreature>(e)) {
|
||||||
for (auto e : view) {
|
return;
|
||||||
auto& creature = view.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 stepped = false;
|
|
||||||
if (update_y(pos, distance, world, box.box)) {
|
|
||||||
pos.y += distance.y;
|
|
||||||
|
|
||||||
} else {
|
auto& creature = registry.get<BaseServerCreature>(e);
|
||||||
v.value.y = 0.0f;
|
auto distance = get_move_distance(creature.velocity);
|
||||||
}
|
auto box = HitboxManager::hitbox(creature.hitbox);
|
||||||
if (update_x(pos, distance, world, box.box)) {
|
auto& pos = creature.transform.position.value;
|
||||||
pos.x += distance.x;
|
auto& v = creature.velocity;
|
||||||
|
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;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (ground && !stepped) {
|
v.value.y = 0.0f;
|
||||||
|
}
|
||||||
|
if (update_x(pos, distance, world, box.box)) {
|
||||||
|
pos.x += distance.x;
|
||||||
|
|
||||||
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
} else {
|
||||||
if (update_x(step_pos, distance, world, box.box)) {
|
if (ground && !stepped) {
|
||||||
pos.x += distance.x;
|
|
||||||
pos.y += 1.0f;
|
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
||||||
stepped = true;
|
if (update_x(step_pos, distance, world, box.box)) {
|
||||||
} else {
|
pos.x += distance.x;
|
||||||
v.value.x = 0.0f;
|
pos.y += 1.0f;
|
||||||
}
|
stepped = true;
|
||||||
} else {
|
} else {
|
||||||
v.value.x = 0.0f;
|
v.value.x = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (update_z(pos, distance, world, box.box)) {
|
|
||||||
pos.z += distance.z;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (ground && !stepped) {
|
v.value.x = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
if (update_z(pos, distance, world, box.box)) {
|
||||||
if (update_z(step_pos, distance, world, box.box)) {
|
pos.z += distance.z;
|
||||||
pos.z += distance.z;
|
|
||||||
pos.y += 1.0f;
|
} else {
|
||||||
stepped = true;
|
if (ground && !stepped) {
|
||||||
|
|
||||||
|
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
||||||
|
if (update_z(step_pos, distance, world, box.box)) {
|
||||||
|
pos.z += distance.z;
|
||||||
|
pos.y += 1.0f;
|
||||||
|
stepped = true;
|
||||||
|
|
||||||
} else {
|
|
||||||
v.value.z = 0.0f;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
v.value.z = 0.0f;
|
v.value.z = 0.0f;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
v.value.z = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,38 +5,38 @@
|
|||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
void SpeedSystem::update(float dt, entt::registry& registry) {
|
void SpeedSystem::update(float dt, entt::registry& registry, entt::entity e) {
|
||||||
auto view = registry.view<BaseServerCreature, MoveBoost>();
|
if (!registry.all_of<BaseServerCreature, MoveBoost>(e)) {
|
||||||
|
return;
|
||||||
for (auto e : view) {
|
|
||||||
auto [creature, moveboost] = view.get<BaseServerCreature, MoveBoost>(e);
|
|
||||||
auto& v = creature.velocity.value;
|
|
||||||
if (moveboost.count <= moveboost.duration) {
|
|
||||||
++moveboost.count;
|
|
||||||
v += creature.transform.direction.value *
|
|
||||||
creature.movement.acceleration;
|
|
||||||
} else {
|
|
||||||
// Decelerated by friction in all directions
|
|
||||||
auto decay = [](float& c, float d) {
|
|
||||||
if (c > 0.0f)
|
|
||||||
c = std::max(0.0f, c - d);
|
|
||||||
else if (c < 0.0f)
|
|
||||||
c = std::min(0.0f, c + d);
|
|
||||||
};
|
|
||||||
decay(v.x, creature.movement.deceleration);
|
|
||||||
decay(v.z, creature.movement.deceleration);
|
|
||||||
}
|
|
||||||
v.y += -creature.gravity.value * dt;
|
|
||||||
auto v_clamp = [](float& c, float max) {
|
|
||||||
if (max < 0.0f) {
|
|
||||||
return; //-1 = unlimited
|
|
||||||
}
|
|
||||||
c = std::clamp(c, -max, max);
|
|
||||||
};
|
|
||||||
v_clamp(v.x, creature.velocity.max.x);
|
|
||||||
v_clamp(v.y, creature.velocity.max.y);
|
|
||||||
v_clamp(v.z, creature.velocity.max.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
// Decelerated by friction in all directions
|
||||||
|
auto decay = [](float& c, float d) {
|
||||||
|
if (c > 0.0f)
|
||||||
|
c = std::max(0.0f, c - d);
|
||||||
|
else if (c < 0.0f)
|
||||||
|
c = std::min(0.0f, c + d);
|
||||||
|
};
|
||||||
|
decay(v.x, creature.movement.deceleration);
|
||||||
|
decay(v.z, creature.movement.deceleration);
|
||||||
|
}
|
||||||
|
v.y += -creature.gravity.value * dt;
|
||||||
|
auto v_clamp = [](float& c, float max) {
|
||||||
|
if (max < 0.0f) {
|
||||||
|
return; //-1 = unlimited
|
||||||
|
}
|
||||||
|
c = std::clamp(c, -max, max);
|
||||||
|
};
|
||||||
|
v_clamp(v.x, creature.velocity.max.x);
|
||||||
|
v_clamp(v.y, creature.velocity.max.y);
|
||||||
|
v_clamp(v.z, creature.velocity.max.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -10,18 +10,18 @@ constexpr double MOVE_PROBABILITY = 0.01;
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
void WanderAISystem::update(entt::registry& registry) {
|
void WanderAISystem::update(entt::registry& registry, entt::entity e) {
|
||||||
auto view =
|
if (!registry.all_of<AIBase, WanderAITag, BaseServerCreature, MoveBoost>(
|
||||||
registry.view<AIBase, WanderAITag, BaseServerCreature, MoveBoost>();
|
e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto e : view) {
|
auto [ai, creature, move_boost] =
|
||||||
auto [ai, creature, move_boost] =
|
registry.get<AIBase, BaseServerCreature, MoveBoost>(e);
|
||||||
view.get<AIBase, BaseServerCreature, MoveBoost>(e);
|
++ai.count;
|
||||||
++ai.count;
|
if (ai.count >= ai.interval) {
|
||||||
if (ai.count >= ai.interval) {
|
ai.count = 0;
|
||||||
ai.count = 0;
|
do_ai(creature, move_boost);
|
||||||
do_ai(creature, move_boost);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user