pkt: action-based entity stream throttling
parent
28987c36d9
commit
c7d251eb44
|
@ -12,6 +12,7 @@ uint64_t entity_spawn(uint16_t class_id) {
|
||||||
ecs_entity_t e = ecs_new(world_ecs(), 0);
|
ecs_entity_t e = ecs_new(world_ecs(), 0);
|
||||||
|
|
||||||
ecs_set(world_ecs(), e, Classify, { .id = class_id });
|
ecs_set(world_ecs(), e, Classify, { .id = class_id });
|
||||||
|
entity_wake(e);
|
||||||
|
|
||||||
if (class_id != EKIND_SERVER) {
|
if (class_id != EKIND_SERVER) {
|
||||||
ecs_set(world_ecs(), e, Velocity, {0});
|
ecs_set(world_ecs(), e, Velocity, {0});
|
||||||
|
@ -43,3 +44,39 @@ void entity_despawn(uint64_t ent_id) {
|
||||||
librg_entity_untrack(world_tracker(), ent_id);
|
librg_entity_untrack(world_tracker(), ent_id);
|
||||||
ecs_delete(world_ecs(), ent_id);
|
ecs_delete(world_ecs(), ent_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void entity_wake(uint64_t ent_id) {
|
||||||
|
StreamInfo *si = ecs_get_mut(world_ecs(), ent_id, StreamInfo);
|
||||||
|
si->tick_delay = 0.0f;
|
||||||
|
si->last_update = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ecs_query_t *ecs_streaminfo = NULL;
|
||||||
|
|
||||||
|
void entity_update_action_timers() {
|
||||||
|
static double last_update_time = 0.0f;
|
||||||
|
if (!ecs_streaminfo) {
|
||||||
|
ecs_streaminfo = ecs_query_new(world_ecs(), "components.StreamInfo");
|
||||||
|
last_update_time = zpl_time_rel();
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs_iter_t it = ecs_query_iter(world_ecs(), ecs_streaminfo);
|
||||||
|
|
||||||
|
while (ecs_query_next(&it)) {
|
||||||
|
StreamInfo *si = ecs_field(&it, StreamInfo, 1);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < it.count; i++) {
|
||||||
|
if (si[i].last_update < zpl_time_rel()) {
|
||||||
|
si[i].last_update = zpl_time_rel() + si[i].tick_delay;
|
||||||
|
si[i].tick_delay += (zpl_time_rel() - last_update_time) * 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_update_time = zpl_time_rel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool entity_can_stream(uint64_t ent_id) {
|
||||||
|
StreamInfo *si = ecs_get_mut(world_ecs(), ent_id, StreamInfo);
|
||||||
|
return (si->last_update < zpl_time_rel());
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
|
#define ENTITY_ACTION_VELOCITY_THRESHOLD 0.05f
|
||||||
|
|
||||||
uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */);
|
uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */);
|
||||||
void entity_batch_despawn(uint64_t *ids, size_t num_ids);
|
void entity_batch_despawn(uint64_t *ids, size_t num_ids);
|
||||||
void entity_despawn(uint64_t ent_id);
|
void entity_despawn(uint64_t ent_id);
|
||||||
|
|
||||||
|
// NOTE(zaklaus): action-based entity stream throttling
|
||||||
|
void entity_wake(uint64_t ent_id);
|
||||||
|
void entity_update_action_timers();
|
||||||
|
bool entity_can_stream(uint64_t ent_id);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
#include "packets/pkt_send_librg_update.h"
|
#include "packets/pkt_send_librg_update.h"
|
||||||
|
|
||||||
|
@ -134,6 +135,13 @@ int32_t tracker_write_update(librg_world *w, librg_event *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE(zaklaus): action-based updates
|
||||||
|
{
|
||||||
|
if (view.kind != EKIND_CHUNK && !entity_can_stream(entity_id)) {
|
||||||
|
return LIBRG_WRITE_REJECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (int32_t)entity_view_pack_struct(buffer, actual_length, view);
|
return (int32_t)entity_view_pack_struct(buffer, actual_length, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +341,7 @@ int32_t world_update() {
|
||||||
world_tracker_update(1, normal_ms, 2);
|
world_tracker_update(1, normal_ms, 2);
|
||||||
world_tracker_update(2, slow_ms, 3);
|
world_tracker_update(2, slow_ms, 3);
|
||||||
|
|
||||||
|
entity_update_action_timers();
|
||||||
debug_replay_update();
|
debug_replay_update();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ ECS_COMPONENT_DECLARE(IsInVehicle);
|
||||||
ECS_COMPONENT_DECLARE(ItemDrop);
|
ECS_COMPONENT_DECLARE(ItemDrop);
|
||||||
ECS_COMPONENT_DECLARE(Inventory);
|
ECS_COMPONENT_DECLARE(Inventory);
|
||||||
ECS_COMPONENT_DECLARE(DemoNPC);
|
ECS_COMPONENT_DECLARE(DemoNPC);
|
||||||
|
ECS_COMPONENT_DECLARE(StreamInfo);
|
||||||
|
|
||||||
void ComponentsImport(ecs_world_t *ecs) {
|
void ComponentsImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, Components);
|
ECS_MODULE(ecs, Components);
|
||||||
|
@ -32,4 +33,5 @@ void ComponentsImport(ecs_world_t *ecs) {
|
||||||
ECS_COMPONENT_DEFINE(ecs, ItemDrop);
|
ECS_COMPONENT_DEFINE(ecs, ItemDrop);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
||||||
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
|
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,11 @@ typedef struct {
|
||||||
float pickup_time;
|
float pickup_time;
|
||||||
} Inventory;
|
} Inventory;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double last_update;
|
||||||
|
double tick_delay;
|
||||||
|
} StreamInfo;
|
||||||
|
|
||||||
typedef struct {char _unused;} DemoNPC;
|
typedef struct {char _unused;} DemoNPC;
|
||||||
|
|
||||||
extern ECS_COMPONENT_DECLARE(Vector2D);
|
extern ECS_COMPONENT_DECLARE(Vector2D);
|
||||||
|
@ -112,5 +117,6 @@ extern ECS_COMPONENT_DECLARE(IsInVehicle);
|
||||||
extern ECS_COMPONENT_DECLARE(ItemDrop);
|
extern ECS_COMPONENT_DECLARE(ItemDrop);
|
||||||
extern ECS_COMPONENT_DECLARE(Inventory);
|
extern ECS_COMPONENT_DECLARE(Inventory);
|
||||||
extern ECS_COMPONENT_DECLARE(DemoNPC);
|
extern ECS_COMPONENT_DECLARE(DemoNPC);
|
||||||
|
extern ECS_COMPONENT_DECLARE(StreamInfo);
|
||||||
|
|
||||||
void ComponentsImport(ecs_world_t *ecs);
|
void ComponentsImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -114,6 +114,7 @@ void RegenerateHP(ecs_iter_t *it) {
|
||||||
h[i].heal_time = HP_REGEN_TIME;
|
h[i].heal_time = HP_REGEN_TIME;
|
||||||
h[i].hp += HP_REGEN_RECOVERY;
|
h[i].hp += HP_REGEN_RECOVERY;
|
||||||
h[i].hp = zpl_min(h[i].max_hp, h[i].hp);
|
h[i].hp = zpl_min(h[i].max_hp, h[i].hp);
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
} else {
|
} else {
|
||||||
h[i].heal_time -= safe_dt(it);
|
h[i].heal_time -= safe_dt(it);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ void PickItem(ecs_iter_t *it) {
|
||||||
item->quantity += picked_count;
|
item->quantity += picked_count;
|
||||||
drop->quantity -= picked_count;
|
drop->quantity -= picked_count;
|
||||||
item->kind = drop->kind;
|
item->kind = drop->kind;
|
||||||
|
entity_wake(ents[j]);
|
||||||
|
|
||||||
if (drop->quantity == 0)
|
if (drop->quantity == 0)
|
||||||
item_despawn(ents[j]);
|
item_despawn(ents[j]);
|
||||||
|
@ -42,6 +43,7 @@ void PickItem(ecs_iter_t *it) {
|
||||||
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
||||||
p2->x = zpl_lerp(p2->x, p[i].x, ITEM_ATTRACT_FORCE*it->delta_time);
|
p2->x = zpl_lerp(p2->x, p[i].x, ITEM_ATTRACT_FORCE*it->delta_time);
|
||||||
p2->y = zpl_lerp(p2->y, p[i].y, ITEM_ATTRACT_FORCE*it->delta_time);
|
p2->y = zpl_lerp(p2->y, p[i].y, ITEM_ATTRACT_FORCE*it->delta_time);
|
||||||
|
entity_wake(ents[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,5 +224,7 @@ void UseItem(ecs_iter_t *it) {
|
||||||
|
|
||||||
in[i].num_placements = 0;
|
in[i].num_placements = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
#define PLR_MOVE_SPEED 800.0f
|
#define PLR_MOVE_SPEED 800.0f
|
||||||
#define PLR_MOVE_SPEED_MULT 1.5f
|
#define PLR_MOVE_SPEED_MULT 1.5f
|
||||||
|
|
||||||
|
@ -12,5 +14,10 @@ void MovementImpulse(ecs_iter_t *it) {
|
||||||
float speed = PLR_MOVE_SPEED * (in[i].sprint ? PLR_MOVE_SPEED_MULT : 1.0f);
|
float speed = PLR_MOVE_SPEED * (in[i].sprint ? PLR_MOVE_SPEED_MULT : 1.0f);
|
||||||
v[i].x += in[i].x*speed*drag*safe_dt(it);
|
v[i].x += in[i].x*speed*drag*safe_dt(it);
|
||||||
v[i].y -= in[i].y*speed*drag*safe_dt(it);
|
v[i].y -= in[i].y*speed*drag*safe_dt(it);
|
||||||
|
|
||||||
|
if ( zpl_abs(v[i].x) > ENTITY_ACTION_VELOCITY_THRESHOLD
|
||||||
|
|| zpl_abs(v[i].y) > ENTITY_ACTION_VELOCITY_THRESHOLD) {
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "debug_draw.h"
|
#include "debug_draw.h"
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
#define VEH_ENTER_RADIUS 45.0f
|
#define VEH_ENTER_RADIUS 45.0f
|
||||||
|
|
||||||
|
@ -158,9 +159,14 @@ void VehicleHandling(ecs_iter_t *it) {
|
||||||
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity);
|
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity);
|
||||||
*p2 = p[i];
|
*p2 = p[i];
|
||||||
*v2 = v[i];
|
*v2 = v[i];
|
||||||
|
entity_wake(pe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zpl_abs(car->force) > ENTITY_ACTION_VELOCITY_THRESHOLD) {
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
debug_v2 b2 = {p[i].x + zpl_cos(car->heading)*(car->wheel_base), p[i].y + zpl_sin(car->heading)*(car->wheel_base)};
|
debug_v2 b2 = {p[i].x + zpl_cos(car->heading)*(car->wheel_base), p[i].y + zpl_sin(car->heading)*(car->wheel_base)};
|
||||||
debug_push_line((debug_v2){p[i].x, p[i].y}, b2, 0x0000FFFF);
|
debug_push_line((debug_v2){p[i].x, p[i].y}, b2, 0x0000FFFF);
|
||||||
|
|
Loading…
Reference in New Issue