user layer refactor progress
This commit is contained in:
parent
f1776dedaf
commit
d93bed029e
@ -37,7 +37,7 @@ Global struct {
|
||||
ClientStore *nil_client_store;
|
||||
Client *nil_client;
|
||||
Snapshot *nil_snapshot;
|
||||
Ent *nil_ent;
|
||||
Entity *nil_ent;
|
||||
} G = ZI, DebugAlias(G, G_sim);
|
||||
|
||||
/* Accessed via `sim_client_store_nil()` */
|
||||
@ -50,7 +50,7 @@ Readonly Client **_g_sim_client_nil = &G.nil_client;
|
||||
Readonly Snapshot **_g_sim_snapshot_nil = &G.nil_snapshot;
|
||||
|
||||
/* Accessed via `sim_ent_nil()` */
|
||||
Readonly Ent **_g_sim_ent_nil = &G.nil_ent;
|
||||
Readonly Entity **_g_sim_ent_nil = &G.nil_ent;
|
||||
|
||||
SimStartupReceipt sim_startup(void)
|
||||
{
|
||||
@ -72,7 +72,7 @@ SimStartupReceipt sim_startup(void)
|
||||
G.nil_snapshot->client = sim_client_nil();
|
||||
|
||||
/* Nil ent */
|
||||
G.nil_ent = PushStruct(G.nil_arena, Ent);
|
||||
G.nil_ent = PushStruct(G.nil_arena, Entity);
|
||||
G.nil_ent->ss = sim_snapshot_nil();
|
||||
G.nil_ent->valid = 0;
|
||||
G.nil_ent->id = SIM_ENT_NIL_ID;
|
||||
@ -325,20 +325,20 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
ss->first_free_ent = src->first_free_ent;
|
||||
ss->num_ents_allocated = src->num_ents_allocated;
|
||||
ss->num_ents_reserved = src->num_ents_reserved;
|
||||
ss->ents = PushStructsNoZero(ss->ents_arena, Ent, ss->num_ents_reserved);
|
||||
ss->ents = PushStructsNoZero(ss->ents_arena, Entity, ss->num_ents_reserved);
|
||||
if (ss->num_ents_reserved == 0) {
|
||||
/* Copying from nil snapshot, need to create blank & root entity */
|
||||
|
||||
/* PushStruct blank ent at index 0 (because index 0 is never valid anyway since it maps to sim_ent_nil()) */
|
||||
{
|
||||
PushStruct(ss->ents_arena, Ent);
|
||||
PushStruct(ss->ents_arena, Entity);
|
||||
++ss->num_ents_allocated;
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
|
||||
/* PushStruct root ent with constant id */
|
||||
{
|
||||
Ent *root = PushStructNoZero(ss->ents_arena, Ent);
|
||||
Entity *root = PushStructNoZero(ss->ents_arena, Entity);
|
||||
*root = *sim_ent_nil();
|
||||
root->ss = ss;
|
||||
root->valid = 1;
|
||||
@ -351,8 +351,8 @@ Snapshot *sim_snapshot_alloc(Client *client, Snapshot *src, u64 tick)
|
||||
}
|
||||
} else {
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *dst_ent = &ss->ents[i];
|
||||
Ent *src_ent = &src->ents[i];
|
||||
Entity *dst_ent = &ss->ents[i];
|
||||
Entity *src_ent = &src->ents[i];
|
||||
*dst_ent = *src_ent;
|
||||
dst_ent->ss = ss;
|
||||
}
|
||||
@ -593,10 +593,10 @@ void sim_snapshot_set_tile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile
|
||||
{
|
||||
Vec2I32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||
|
||||
EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
Ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
EntityId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
Entity *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
if (!chunk_ent->valid) {
|
||||
Ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
Entity *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
chunk_ent = sim_ent_alloc_sync_src_with_id(root, chunk_id);
|
||||
sim_ent_enable_prop(chunk_ent, SEPROP_TILE_CHUNK);
|
||||
chunk_ent->tile_chunk_index = chunk_index;
|
||||
@ -645,9 +645,9 @@ Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *
|
||||
__profn("Lerp snapshot entities");
|
||||
u64 num_entities = MinU64(ss0->num_ents_reserved, ss1->num_ents_reserved);
|
||||
for (u64 i = 0; i < num_entities; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Ent *e0 = &ss0->ents[i];
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
Entity *e0 = &ss0->ents[i];
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
sim_ent_lerp(e, e0, e1, blend);
|
||||
}
|
||||
}
|
||||
@ -661,7 +661,7 @@ Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *
|
||||
* ========================== */
|
||||
|
||||
/* Syncs entity data between snapshots */
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remote_player, u32 sync_flags)
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -670,24 +670,24 @@ void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remot
|
||||
* - Determine new UUids for newly created ents
|
||||
*/
|
||||
|
||||
Ent *local_root = sim_ent_from_id(local_ss, SIM_ENT_ROOT_ID);
|
||||
Ent *remote_root = sim_ent_from_id(remote_ss, SIM_ENT_ROOT_ID);
|
||||
Entity *local_root = sim_ent_from_id(local_ss, SIM_ENT_ROOT_ID);
|
||||
Entity *remote_root = sim_ent_from_id(remote_ss, SIM_ENT_ROOT_ID);
|
||||
|
||||
/* Create new ents from remote */
|
||||
for (Ent *remote_top = sim_ent_from_id(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_id(remote_ss, remote_top->next)) {
|
||||
for (Entity *remote_top = sim_ent_from_id(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_id(remote_ss, remote_top->next)) {
|
||||
sim_ent_sync_alloc_tree(local_root, remote_top, remote_player);
|
||||
}
|
||||
|
||||
/* Sync ents with remote, skipping index 0 (nil) & index 1 (root) */
|
||||
for (u64 i = 2; i < local_ss->num_ents_reserved; ++i) {
|
||||
Ent *local_ent = &local_ss->ents[i];
|
||||
Entity *local_ent = &local_ss->ents[i];
|
||||
if (local_ent->valid && sim_ent_has_prop(local_ent, SEPROP_SYNC_DST)) {
|
||||
b32 should_sync = sim_ent_id_eq(local_ent->owner, remote_player) || sim_ent_id_is_nil(remote_player);
|
||||
if ((sync_flags & SIM_SYNC_FLAG_NOSYNC_PREDICTABLES) && sim_ent_id_eq(local_ent->predictor, local_ss->local_player)) {
|
||||
should_sync = 0;
|
||||
}
|
||||
if (should_sync) {
|
||||
Ent *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
Entity *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
if (remote_ent->valid) {
|
||||
/* Copy all ent data from remote */
|
||||
sim_ent_sync(local_ent, remote_ent);
|
||||
@ -774,11 +774,11 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho
|
||||
BB_WriteDebugMarker(bw, StringFromStruct(&ss1->num_ents_reserved));
|
||||
|
||||
for (u64 i = 1; i < ss1->num_ents_reserved; ++i) {
|
||||
Ent *e0 = sim_ent_nil();
|
||||
Entity *e0 = sim_ent_nil();
|
||||
if (i < ss0->num_ents_reserved) {
|
||||
e0 = &ss0->ents[i];
|
||||
}
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
sim_ent_encode(bw, e0, e1);
|
||||
}
|
||||
|
||||
@ -801,7 +801,7 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
ss->continuity_gen = BB_ReadUV(br);
|
||||
ss->phys_iteration = BB_ReadUV(br);
|
||||
|
||||
ss->local_player = (EntId) { .uid = BB_ReadUid(br) };
|
||||
ss->local_player = (EntityId) { .uid = BB_ReadUid(br) };
|
||||
|
||||
/* Id bins */
|
||||
/* TODO: Don't decode these, determine them implicitly from decoded ents */
|
||||
@ -838,9 +838,9 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = BB_ReadUV(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
PushStructsNoZero(ss->ents_arena, Ent, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -854,7 +854,7 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
BB_ReadDebugMarker(br, Lit("SNAPSHOT ENTS"));
|
||||
BB_ReadDebugMarker(br, StringFromStruct(&ss->num_ents_reserved));
|
||||
for (u64 i = 1; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
sim_ent_decode(br, e);
|
||||
}
|
||||
@ -901,7 +901,7 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho
|
||||
|
||||
BB_AlignWriter(bw);
|
||||
for (u64 i = 0; i < ss1->num_ents_reserved; ++i) {
|
||||
Ent *e0 = sim_ent_nil();
|
||||
Entity *e0 = sim_ent_nil();
|
||||
if (i < ss0->num_ents_reserved) {
|
||||
e0 = &ss0->ents[i];
|
||||
}
|
||||
@ -917,7 +917,7 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho
|
||||
}
|
||||
|
||||
if (e1->valid) {
|
||||
Ent *e1 = &ss1->ents[i];
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
sim_ent_encode(bw, e0, e1);
|
||||
}
|
||||
}
|
||||
@ -947,7 +947,7 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
ss->continuity_gen = BB_ReadUV(br);
|
||||
ss->phys_iteration = BB_ReadUV(br);
|
||||
|
||||
ss->local_player = (EntId) { .uid = BB_ReadUid(br) };
|
||||
ss->local_player = (EntityId) { .uid = BB_ReadUid(br) };
|
||||
|
||||
#if 1
|
||||
|
||||
@ -959,9 +959,9 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = BB_ReadUV(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
PushStructsNoZero(ss->ents_arena, Ent, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -978,11 +978,11 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
b32 released = 0;
|
||||
|
||||
u32 alloc_parent_index = ZI;
|
||||
EntId alloc_ent_id = ZI;
|
||||
EntityId alloc_ent_id = ZI;
|
||||
if (allocation_changed) {
|
||||
released = BB_ReadBit(br);
|
||||
if (released) {
|
||||
Ent *e = sim_ent_from_index(ss, e);
|
||||
Entity *e = sim_ent_from_index(ss, e);
|
||||
Assert(e->valid); /* An entity that we don't have allocated should never have been marked for release */
|
||||
if (e->valid) {
|
||||
sim_ent_enable_prop(e, SEPROP_RELEASE);
|
||||
@ -1019,11 +1019,11 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
||||
if (n->is_new) {
|
||||
u32 index = n->index;
|
||||
Ent *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
Entity *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
Assert(!sim_ent_from_index(ss, index)->valid && !sim_ent_from_id(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */
|
||||
Assert(parent->valid); /* Parent for new entity allocation should always be valid */
|
||||
if (parent->valid && index < ss->num_ents_reserved) {
|
||||
Ent *ent = &ss->ents[index];
|
||||
Entity *ent = &ss->ents[index];
|
||||
ent->valid = 1;
|
||||
sim_ent_set_id(ent, n->alloc_ent_id);
|
||||
sim_ent_link_parent(parent, ent);
|
||||
@ -1038,7 +1038,7 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
||||
BB_Reader ent_br = n->br;
|
||||
u32 index = n->index;
|
||||
Ent *e = sim_ent_from_index(ss, index);
|
||||
Entity *e = sim_ent_from_index(ss, index);
|
||||
if (e->valid) {
|
||||
sim_ent_decode(&ent_br, e);
|
||||
} else {
|
||||
@ -1056,9 +1056,9 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
ss->num_ents_reserved = BB_ReadUV(br);
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0) {
|
||||
PushStructsNoZero(ss->ents_arena, Ent, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *sim_ent_nil();
|
||||
e->ss = ss;
|
||||
}
|
||||
@ -1077,7 +1077,7 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss)
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *e = &ss->ents[i];
|
||||
Entity *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
|
||||
b32 valid_changed = BB_ReadBit(br);
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#define SIM_LAYER_RELATIVE_DEFAULT (0)
|
||||
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
||||
|
||||
Struct(EntId) {
|
||||
Struct(EntityId) {
|
||||
Uid uid;
|
||||
};
|
||||
|
||||
@ -88,7 +88,7 @@ Struct(Client) {
|
||||
ClientHandle prev_in_bin;
|
||||
|
||||
/* The client's player entity id in the master sim (if relevant) */
|
||||
EntId player_id;
|
||||
EntityId player_id;
|
||||
|
||||
/* This is the highest confirmed tick of ours that we know this client has received */
|
||||
u64 ack;
|
||||
@ -202,7 +202,7 @@ Struct(Snapshot) {
|
||||
u64 phys_iteration;
|
||||
|
||||
/* The id of the receiver's player in the snapshot */
|
||||
EntId local_player;
|
||||
EntityId local_player;
|
||||
|
||||
/* Id lookup */
|
||||
struct EntBin *id_bins;
|
||||
@ -210,7 +210,7 @@ Struct(Snapshot) {
|
||||
|
||||
/* Entities */
|
||||
Arena *ents_arena;
|
||||
struct Ent *ents;
|
||||
struct Entity *ents;
|
||||
u32 first_free_ent;
|
||||
u32 num_ents_allocated;
|
||||
u32 num_ents_reserved;
|
||||
@ -244,7 +244,7 @@ void sim_snapshot_set_tile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile
|
||||
Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntId remote_player, u32 sync_flags);
|
||||
void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags);
|
||||
|
||||
/* Encode / decode */
|
||||
void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1);
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
#define SIM_ENT_COLLISION_DEBUG_BASIS_Uid (UID(0x302c01182013bb02, 0x570bd270399d11a5))
|
||||
#define SIM_ENT_TILE_CHUNK_BASIS_Uid (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
||||
|
||||
internal u32 index_from_ent(Snapshot *ss, Ent *ent)
|
||||
internal u32 index_from_ent(Snapshot *ss, Entity *ent)
|
||||
{
|
||||
return ent - ss->ents;
|
||||
}
|
||||
|
||||
internal Ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
internal Entity *ent_from_index(Snapshot *ss, u32 index)
|
||||
{
|
||||
if (index > 0 && index < ss->num_ents_reserved) {
|
||||
return &ss->ents[index];
|
||||
@ -18,22 +18,22 @@ internal Ent *ent_from_index(Snapshot *ss, u32 index)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent allocation
|
||||
* Entity allocation
|
||||
* ========================== */
|
||||
|
||||
Ent *sim_ent_alloc_raw(Snapshot *ss, Ent *parent, EntId id)
|
||||
Entity *sim_ent_alloc_raw(Snapshot *ss, Entity *parent, EntityId id)
|
||||
{
|
||||
Assert(parent->valid);
|
||||
Assert(ss->valid);
|
||||
Assert(ss == parent->ss);
|
||||
Ent *ent;
|
||||
Entity *ent;
|
||||
if (ss->first_free_ent > 0 && ss->first_free_ent < ss->num_ents_reserved) {
|
||||
/* Reuse from free list */
|
||||
ent = &ss->ents[ss->first_free_ent];
|
||||
ss->first_free_ent = ent->next_free;
|
||||
} else {
|
||||
/* Make new */
|
||||
ent = PushStructNoZero(ss->ents_arena, Ent);
|
||||
ent = PushStructNoZero(ss->ents_arena, Entity);
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
*ent = *sim_ent_nil();
|
||||
@ -50,58 +50,58 @@ Ent *sim_ent_alloc_raw(Snapshot *ss, Ent *parent, EntId id)
|
||||
}
|
||||
|
||||
/* Allocates a new entity that will not sync */
|
||||
Ent *sim_ent_alloc_local(Ent *parent)
|
||||
Entity *sim_ent_alloc_local(Entity *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
Entity *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
Ent *sim_ent_alloc_local_with_id(Ent *parent, EntId id)
|
||||
Entity *sim_ent_alloc_local_with_id(Entity *parent, EntityId id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
Entity *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Allocates a new entity to be synced to clients */
|
||||
Ent *sim_ent_alloc_sync_src(Ent *parent)
|
||||
Entity *sim_ent_alloc_sync_src(Entity *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
Entity *e = sim_ent_alloc_raw(ss, parent, sim_ent_random_id());
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_SRC);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
Ent *sim_ent_alloc_sync_src_with_id(Ent *parent, EntId id)
|
||||
Entity *sim_ent_alloc_sync_src_with_id(Entity *parent, EntityId id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
Entity *e = sim_ent_alloc_raw(ss, parent, id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_SRC);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Allocates a new entity that will sync with incoming net src ents containing id, and coming from the specified owner */
|
||||
Ent *sim_ent_alloc_sync_dst(Ent *parent, EntId ent_id, EntId owner_id)
|
||||
Entity *sim_ent_alloc_sync_dst(Entity *parent, EntityId ent_id, EntityId owner_id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Ent *e = sim_ent_alloc_raw(ss, parent, ent_id);
|
||||
Entity *e = sim_ent_alloc_raw(ss, parent, ent_id);
|
||||
sim_ent_enable_prop(e, SEPROP_SYNC_DST);
|
||||
e->owner = owner_id;
|
||||
return e;
|
||||
}
|
||||
|
||||
void sim_ent_release_raw(Ent *ent)
|
||||
void sim_ent_release_raw(Entity *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
/* Release children */
|
||||
Ent *child = sim_ent_from_id(ss, ent->first);
|
||||
Entity *child = sim_ent_from_id(ss, ent->first);
|
||||
while (child->valid) {
|
||||
Ent *next = sim_ent_from_id(ss, child->next);
|
||||
Entity *next = sim_ent_from_id(ss, child->next);
|
||||
sim_ent_release_raw(child);
|
||||
child = next;
|
||||
}
|
||||
@ -116,10 +116,10 @@ void sim_ent_release_raw(Ent *ent)
|
||||
--ss->num_ents_allocated;
|
||||
}
|
||||
|
||||
void sim_ent_release(Ent *ent)
|
||||
void sim_ent_release(Entity *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (parent->valid) {
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
}
|
||||
@ -130,12 +130,12 @@ void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop)
|
||||
{
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
|
||||
Ent **ents_to_release = PushDry(scratch.arena, Ent *);
|
||||
Entity **ents_to_release = PushDry(scratch.arena, Entity *);
|
||||
u64 ents_to_release_count = 0;
|
||||
for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &ss->ents[ent_index];
|
||||
Entity *ent = &ss->ents[ent_index];
|
||||
if (ent->valid && sim_ent_has_prop(ent, prop)) {
|
||||
*PushStructNoZero(scratch.arena, Ent *) = ent;
|
||||
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
||||
++ents_to_release_count;
|
||||
}
|
||||
}
|
||||
@ -144,7 +144,7 @@ void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop)
|
||||
/* TODO: Breadth first iteration to only release parent entities (since
|
||||
* child entities will be released along with parent anyway) */
|
||||
for (u64 i = 0; i < ents_to_release_count; ++i) {
|
||||
Ent *ent = ents_to_release[i];
|
||||
Entity *ent = ents_to_release[i];
|
||||
if (ent->valid && !ent->is_root && !sim_ent_has_prop(ent, SEPROP_CMD) && !sim_ent_has_prop(ent, SEPROP_PLAYER)) {
|
||||
sim_ent_release(ent);
|
||||
}
|
||||
@ -157,7 +157,7 @@ void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop)
|
||||
* Activate
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_activate(Ent *ent, u64 current_tick)
|
||||
void sim_ent_activate(Entity *ent, u64 current_tick)
|
||||
{
|
||||
sim_ent_enable_prop(ent, SEPROP_ACTIVE);
|
||||
ent->activation_tick = current_tick;
|
||||
@ -165,19 +165,19 @@ void sim_ent_activate(Ent *ent, u64 current_tick)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent id
|
||||
* Entity id
|
||||
* ========================== */
|
||||
|
||||
internal EntBin *bin_from_id(Snapshot *ss, EntId id)
|
||||
internal EntBin *bin_from_id(Snapshot *ss, EntityId id)
|
||||
{
|
||||
return &ss->id_bins[id.uid.lo % ss->num_id_bins];
|
||||
}
|
||||
|
||||
/* NOTE: This should only really happen during ent allocation (it doesn't make sense for an allocated ent's id to change) */
|
||||
void sim_ent_set_id(Ent *ent, EntId id)
|
||||
void sim_ent_set_id(Entity *ent, EntityId id)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
EntId old_id = ent->id;
|
||||
EntityId old_id = ent->id;
|
||||
if (!sim_ent_id_eq(old_id, id)) {
|
||||
/* Release old from lookup */
|
||||
if (!sim_ent_id_is_nil(old_id)) {
|
||||
@ -185,9 +185,9 @@ void sim_ent_set_id(Ent *ent, EntId id)
|
||||
u32 prev_index = 0;
|
||||
u32 next_index = 0;
|
||||
u32 search_index = bin->first;
|
||||
Ent *prev = sim_ent_nil();
|
||||
Ent *next = sim_ent_nil();
|
||||
Ent *search = ent_from_index(ss, search_index);
|
||||
Entity *prev = sim_ent_nil();
|
||||
Entity *next = sim_ent_nil();
|
||||
Entity *search = ent_from_index(ss, search_index);
|
||||
while (search->valid) {
|
||||
next_index = search->next_in_id_bin;
|
||||
next = ent_from_index(ss, next_index);
|
||||
@ -220,7 +220,7 @@ void sim_ent_set_id(Ent *ent, EntId id)
|
||||
if (!sim_ent_id_is_nil(id)) {
|
||||
#if RtcIsEnabled
|
||||
{
|
||||
Ent *existing = sim_ent_from_id(ss, id);
|
||||
Entity *existing = sim_ent_from_id(ss, id);
|
||||
/* Collision should be extremely unlikely under normal circumstances, there's probably a logic error somewhere. */
|
||||
Assert(!existing->valid);
|
||||
}
|
||||
@ -228,7 +228,7 @@ void sim_ent_set_id(Ent *ent, EntId id)
|
||||
|
||||
EntBin *bin = bin_from_id(ss, id);
|
||||
u32 ent_index = index_from_ent(ss, ent);
|
||||
Ent *last = ent_from_index(ss, bin->last);
|
||||
Entity *last = ent_from_index(ss, bin->last);
|
||||
if (last->valid) {
|
||||
last->next_in_id_bin = ent_index;
|
||||
ent->prev_in_id_bin = bin->last;
|
||||
@ -244,12 +244,12 @@ void sim_ent_set_id(Ent *ent, EntId id)
|
||||
|
||||
}
|
||||
|
||||
Ent *sim_ent_from_id(Snapshot *ss, EntId id)
|
||||
Entity *sim_ent_from_id(Snapshot *ss, EntityId id)
|
||||
{
|
||||
Ent *result = sim_ent_nil();
|
||||
Entity *result = sim_ent_nil();
|
||||
if (!sim_ent_id_is_nil(id) && ss->valid) {
|
||||
EntBin *bin = bin_from_id(ss, id);
|
||||
for (Ent *e = ent_from_index(ss, bin->first); e->valid; e = ent_from_index(ss, e->next_in_id_bin)) {
|
||||
for (Entity *e = ent_from_index(ss, bin->first); e->valid; e = ent_from_index(ss, e->next_in_id_bin)) {
|
||||
if (sim_ent_id_eq(e->id, id)) {
|
||||
result = e;
|
||||
break;
|
||||
@ -259,17 +259,17 @@ Ent *sim_ent_from_id(Snapshot *ss, EntId id)
|
||||
return result;
|
||||
}
|
||||
|
||||
EntId sim_ent_random_id(void)
|
||||
EntityId sim_ent_random_id(void)
|
||||
{
|
||||
EntId result = ZI;
|
||||
EntityId result = ZI;
|
||||
result.uid = UidFromTrueRand();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId id0, EntId id1)
|
||||
EntityId sim_ent_contact_constraint_id_from_contacting_ids(EntityId player_id, EntityId id0, EntityId id1)
|
||||
{
|
||||
EntId result = ZI;
|
||||
EntityId result = ZI;
|
||||
result.uid = SIM_ENT_CONTACT_BASIS_Uid;
|
||||
result.uid = CombineUid(result.uid, player_id.uid);
|
||||
result.uid = CombineUid(result.uid, id0.uid);
|
||||
@ -278,9 +278,9 @@ EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId i
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the debug contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1)
|
||||
EntityId sim_ent_collision_debug_id_from_ids(EntityId player_id, EntityId id0, EntityId id1)
|
||||
{
|
||||
EntId result = ZI;
|
||||
EntityId result = ZI;
|
||||
result.uid = SIM_ENT_COLLISION_DEBUG_BASIS_Uid;
|
||||
result.uid = CombineUid(result.uid, player_id.uid);
|
||||
result.uid = CombineUid(result.uid, id0.uid);
|
||||
@ -289,24 +289,24 @@ EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1)
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
|
||||
EntId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_index)
|
||||
EntityId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_index)
|
||||
{
|
||||
EntId result = ZI;
|
||||
EntityId result = ZI;
|
||||
result.uid = SIM_ENT_TILE_CHUNK_BASIS_Uid;
|
||||
result.uid = CombineUid(result.uid, UID(RandU64FromSeed(chunk_index.x), RandU64FromSeed(chunk_index.y)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent query
|
||||
* Entity query
|
||||
* ========================== */
|
||||
|
||||
Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop)
|
||||
Entity *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
Ent *entities = ss->ents;
|
||||
Entity *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index) {
|
||||
Ent *ent = &entities[ent_index];
|
||||
Entity *ent = &entities[ent_index];
|
||||
if (ent->valid && sim_ent_has_prop(ent, prop)) {
|
||||
return ent;
|
||||
}
|
||||
@ -314,12 +314,12 @@ Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop)
|
||||
return sim_ent_nil();
|
||||
}
|
||||
|
||||
Ent *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props)
|
||||
Entity *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
Ent *entities = ss->ents;
|
||||
Entity *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index) {
|
||||
Ent *ent = &entities[ent_index];
|
||||
Entity *ent = &entities[ent_index];
|
||||
if (ent->valid) {
|
||||
b32 all = 1;
|
||||
for (u64 i = 0; i < props.count; ++i) {
|
||||
@ -337,22 +337,22 @@ Ent *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent tree
|
||||
* Entity tree
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_link_parent(Ent *ent, Ent *parent)
|
||||
void sim_ent_link_parent(Entity *ent, Entity *parent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
Ent *old_parent = sim_ent_from_id(ss, ent->parent);
|
||||
Entity *old_parent = sim_ent_from_id(ss, ent->parent);
|
||||
if (old_parent->valid) {
|
||||
/* Unlink from current parent */
|
||||
sim_ent_unlink_from_parent(ent);
|
||||
}
|
||||
|
||||
EntId ent_id = ent->id;
|
||||
EntId last_child_id = parent->last;
|
||||
Ent *last_child = sim_ent_from_id(ss, last_child_id);
|
||||
EntityId ent_id = ent->id;
|
||||
EntityId last_child_id = parent->last;
|
||||
Entity *last_child = sim_ent_from_id(ss, last_child_id);
|
||||
if (last_child->valid) {
|
||||
ent->prev = last_child_id;
|
||||
last_child->next = ent_id;
|
||||
@ -372,14 +372,14 @@ void sim_ent_link_parent(Ent *ent, Ent *parent)
|
||||
}
|
||||
|
||||
/* NOTE: Entity will be dangling after calling this, should re-link to root ent. */
|
||||
void sim_ent_unlink_from_parent(Ent *ent)
|
||||
void sim_ent_unlink_from_parent(Entity *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
|
||||
EntId parent_id = ent->parent;
|
||||
Ent *parent = sim_ent_from_id(ss, parent_id);
|
||||
Ent *prev = sim_ent_from_id(ss, ent->prev);
|
||||
Ent *next = sim_ent_from_id(ss, ent->next);
|
||||
EntityId parent_id = ent->parent;
|
||||
Entity *parent = sim_ent_from_id(ss, parent_id);
|
||||
Entity *prev = sim_ent_from_id(ss, ent->prev);
|
||||
Entity *next = sim_ent_from_id(ss, ent->next);
|
||||
|
||||
/* Unlink from parent & siblings */
|
||||
if (prev->valid) {
|
||||
@ -397,12 +397,12 @@ void sim_ent_unlink_from_parent(Ent *ent)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent xform
|
||||
* Entity xform
|
||||
* ========================== */
|
||||
|
||||
internal void sim_ent_mark_child_xforms_dirty(Snapshot *ss, Ent *ent)
|
||||
internal void sim_ent_mark_child_xforms_dirty(Snapshot *ss, Entity *ent)
|
||||
{
|
||||
for (Ent *child = sim_ent_from_id(ss, ent->first); child->valid; child = sim_ent_from_id(ss, child->next)) {
|
||||
for (Entity *child = sim_ent_from_id(ss, ent->first); child->valid; child = sim_ent_from_id(ss, child->next)) {
|
||||
if (child->_is_xform_dirty) {
|
||||
break;
|
||||
} else {
|
||||
@ -412,14 +412,14 @@ internal void sim_ent_mark_child_xforms_dirty(Snapshot *ss, Ent *ent)
|
||||
}
|
||||
}
|
||||
|
||||
internal Xform sim_ent_get_xform_internal(Snapshot *ss, Ent *ent)
|
||||
internal Xform sim_ent_get_xform_internal(Snapshot *ss, Entity *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty) {
|
||||
if (ent->is_top) {
|
||||
xf = ent->_local_xform;
|
||||
} else {
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(ss, ent->parent);
|
||||
xf = sim_ent_get_xform_internal(ss, parent);
|
||||
xf = MulXform(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
@ -433,7 +433,7 @@ internal Xform sim_ent_get_xform_internal(Snapshot *ss, Ent *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform sim_ent_get_xform(Ent *ent)
|
||||
Xform sim_ent_get_xform(Entity *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty) {
|
||||
@ -441,7 +441,7 @@ Xform sim_ent_get_xform(Ent *ent)
|
||||
xf = ent->_local_xform;
|
||||
} else {
|
||||
Snapshot *ss = ent->ss;
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(ss, ent->parent);
|
||||
xf = sim_ent_get_xform_internal(ss, parent);
|
||||
xf = MulXform(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
@ -455,12 +455,12 @@ Xform sim_ent_get_xform(Ent *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform sim_ent_get_local_xform(Ent *ent)
|
||||
Xform sim_ent_get_local_xform(Entity *ent)
|
||||
{
|
||||
return ent->_local_xform;
|
||||
}
|
||||
|
||||
void sim_ent_set_xform(Ent *ent, Xform xf)
|
||||
void sim_ent_set_xform(Entity *ent, Xform xf)
|
||||
{
|
||||
if (!EqXform(xf, ent->_xform)) {
|
||||
Snapshot *ss = ent->ss;
|
||||
@ -468,7 +468,7 @@ void sim_ent_set_xform(Ent *ent, Xform xf)
|
||||
if (ent->is_top) {
|
||||
ent->_local_xform = xf;
|
||||
} else {
|
||||
Ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(ss, ent->parent);
|
||||
Xform parent_global = sim_ent_get_xform_internal(ss, parent);
|
||||
ent->_local_xform = MulXform(InvertXform(parent_global), xf);
|
||||
}
|
||||
@ -478,7 +478,7 @@ void sim_ent_set_xform(Ent *ent, Xform xf)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_set_local_xform(Ent *ent, Xform xf)
|
||||
void sim_ent_set_local_xform(Entity *ent, Xform xf)
|
||||
{
|
||||
if (!EqXform(xf, ent->_local_xform)) {
|
||||
ent->_local_xform = xf;
|
||||
@ -488,24 +488,24 @@ void sim_ent_set_local_xform(Ent *ent, Xform xf)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent movement
|
||||
* Entity movement
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_set_linear_velocity(Ent *ent, Vec2 velocity)
|
||||
void sim_ent_set_linear_velocity(Entity *ent, Vec2 velocity)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->linear_velocity = ClampVec2Len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_set_angular_velocity(Ent *ent, f32 velocity)
|
||||
void sim_ent_set_angular_velocity(Entity *ent, f32 velocity)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->angular_velocity = ClampF32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_linear_impulse(Ent *ent, Vec2 impulse, Vec2 point)
|
||||
void sim_ent_apply_linear_impulse(Entity *ent, Vec2 impulse, Vec2 point)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -520,7 +520,7 @@ void sim_ent_apply_linear_impulse(Ent *ent, Vec2 impulse, Vec2 point)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_linear_impulse_to_center(Ent *ent, Vec2 impulse)
|
||||
void sim_ent_apply_linear_impulse_to_center(Entity *ent, Vec2 impulse)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -531,14 +531,14 @@ void sim_ent_apply_linear_impulse_to_center(Ent *ent, Vec2 impulse)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_force_to_center(Ent *ent, Vec2 force)
|
||||
void sim_ent_apply_force_to_center(Entity *ent, Vec2 force)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->force = AddVec2(ent->force, force);
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse)
|
||||
void sim_ent_apply_angular_impulse(Entity *ent, f32 impulse)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -548,7 +548,7 @@ void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse)
|
||||
}
|
||||
}
|
||||
|
||||
void sim_ent_apply_torque(Ent *ent, f32 torque)
|
||||
void sim_ent_apply_torque(Entity *ent, f32 torque)
|
||||
{
|
||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||
ent->torque += torque;
|
||||
@ -559,31 +559,31 @@ void sim_ent_apply_torque(Ent *ent, f32 torque)
|
||||
* Tile
|
||||
* ========================== */
|
||||
|
||||
Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, Vec2I32 chunk_index)
|
||||
Entity *sim_tile_chunk_from_chunk_index(Snapshot *ss, Vec2I32 chunk_index)
|
||||
{
|
||||
EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
Ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
EntityId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||
Entity *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, Vec2I32 world_tile_index)
|
||||
Entity *sim_tile_chunk_from_world_tile_index(Snapshot *ss, Vec2I32 world_tile_index)
|
||||
{
|
||||
Vec2I32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||
Ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
||||
Entity *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
TileKind sim_get_chunk_tile(Ent *chunk_ent, Vec2I32 local_tile_index)
|
||||
TileKind sim_get_chunk_tile(Entity *chunk_ent, Vec2I32 local_tile_index)
|
||||
{
|
||||
TileKind result = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent lerp
|
||||
* Entity lerp
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend)
|
||||
void sim_ent_lerp(Entity *e, Entity *e0, Entity *e1, f64 blend)
|
||||
{
|
||||
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)
|
||||
&& sim_ent_id_eq(e0->id, e1->id)
|
||||
@ -620,32 +620,32 @@ void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent sync
|
||||
* Entity sync
|
||||
* ========================== */
|
||||
|
||||
/* Walks a local & remote ent tree and allocates any missing net dst ents from remote src ents */
|
||||
void sim_ent_sync_alloc_tree(Ent *local_parent, Ent *remote, EntId remote_player)
|
||||
void sim_ent_sync_alloc_tree(Entity *local_parent, Entity *remote, EntityId remote_player)
|
||||
{
|
||||
__prof;
|
||||
if (sim_ent_has_prop(remote, SEPROP_SYNC_SRC)) {
|
||||
Snapshot *local_ss = local_parent->ss;
|
||||
Snapshot *remote_ss = remote->ss;
|
||||
|
||||
EntId id = remote->id;
|
||||
Ent *local_ent = sim_ent_from_id(local_ss, id);
|
||||
EntityId id = remote->id;
|
||||
Entity *local_ent = sim_ent_from_id(local_ss, id);
|
||||
if (!local_ent->valid) {
|
||||
local_ent = sim_ent_alloc_sync_dst(local_parent, id, remote_player);
|
||||
}
|
||||
for (Ent *remote_child = sim_ent_from_id(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_id(remote_ss, remote_child->next)) {
|
||||
for (Entity *remote_child = sim_ent_from_id(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_id(remote_ss, remote_child->next)) {
|
||||
sim_ent_sync_alloc_tree(local_ent, remote_child, remote_player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copies data between two synced entities */
|
||||
void sim_ent_sync(Ent *local, Ent *remote)
|
||||
void sim_ent_sync(Entity *local, Entity *remote)
|
||||
{
|
||||
Ent old = *local;
|
||||
Entity old = *local;
|
||||
CopyStruct(local, remote);
|
||||
|
||||
/* Why would 2 ents w/ different uids ever be synced? */
|
||||
@ -684,10 +684,10 @@ void sim_ent_sync(Ent *local, Ent *remote)
|
||||
#if 1
|
||||
|
||||
/* ========================== *
|
||||
* Ent encode
|
||||
* Entity encode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_encode(BB_Writer *bw, Ent *e0, Ent *e1)
|
||||
void sim_ent_encode(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
||||
@ -711,10 +711,10 @@ void sim_ent_encode(BB_Writer *bw, Ent *e0, Ent *e1)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent decode
|
||||
* Entity decode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_decode(BB_Reader *br, Ent *e)
|
||||
void sim_ent_decode(BB_Reader *br, Entity *e)
|
||||
{
|
||||
Snapshot *old_ss = e->ss;
|
||||
{
|
||||
@ -736,10 +736,10 @@ void sim_ent_decode(BB_Reader *br, Ent *e)
|
||||
#else
|
||||
|
||||
/* ========================== *
|
||||
* Ent encode
|
||||
* Entity encode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_encode(BB_Writer *bw, Ent *e0, Ent *e1)
|
||||
void sim_ent_encode(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
|
||||
@ -769,12 +769,12 @@ void sim_ent_encode(BB_Writer *bw, Ent *e0, Ent *e1)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent decode
|
||||
* Entity decode
|
||||
* ========================== */
|
||||
|
||||
void sim_ent_decode(BB_Reader *br, Ent *e)
|
||||
void sim_ent_decode(BB_Reader *br, Entity *e)
|
||||
{
|
||||
Ent decoded = *e;
|
||||
Entity decoded = *e;
|
||||
{
|
||||
u64 pos = 0;
|
||||
while (pos < sizeof(decoded)) {
|
||||
@ -789,8 +789,8 @@ void sim_ent_decode(BB_Reader *br, Ent *e)
|
||||
}
|
||||
decoded.ss = e->ss;
|
||||
|
||||
EntId old_id = e->id;
|
||||
EntId new_id = decoded.id;
|
||||
EntityId old_id = e->id;
|
||||
EntityId new_id = decoded.id;
|
||||
CopyStruct(e, &decoded);
|
||||
e->id = old_id;
|
||||
if (!sim_ent_id_eq(old_id, new_id)) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#define SIM_ENT_NIL_ID ((EntId) { UID(0, 0) })
|
||||
#define SIM_ENT_ROOT_ID ((EntId) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
#define SIM_ENT_NIL_ID ((EntityId) { UID(0, 0) })
|
||||
#define SIM_ENT_ROOT_ID ((EntityId) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
|
||||
typedef i32 EntProp; enum {
|
||||
SEPROP_ACTIVE,
|
||||
@ -60,14 +60,14 @@ typedef i32 EntProp; enum {
|
||||
SEPROP_COUNT
|
||||
};
|
||||
|
||||
Struct(Ent) {
|
||||
Struct(Entity) {
|
||||
Snapshot *ss;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Metadata */
|
||||
|
||||
b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */
|
||||
EntId id;
|
||||
EntityId id;
|
||||
u64 props[(SEPROP_COUNT + 63) / 64];
|
||||
u64 continuity_gen;
|
||||
|
||||
@ -78,14 +78,14 @@ Struct(Ent) {
|
||||
b32 is_top;
|
||||
|
||||
/* The id of the top level parent of the ent tree (if ent is top then this point to itself) */
|
||||
EntId top;
|
||||
EntityId top;
|
||||
|
||||
/* Tree */
|
||||
EntId parent;
|
||||
EntId next;
|
||||
EntId prev;
|
||||
EntId first;
|
||||
EntId last;
|
||||
EntityId parent;
|
||||
EntityId next;
|
||||
EntityId prev;
|
||||
EntityId first;
|
||||
EntityId last;
|
||||
|
||||
/* Lists keyed by index in snapshot ent array */
|
||||
u32 next_in_id_bin;
|
||||
@ -99,10 +99,10 @@ Struct(Ent) {
|
||||
/* SEPROP_SYNC_DST */
|
||||
|
||||
/* Id of the player that owns simulation for this entity */
|
||||
EntId owner;
|
||||
EntityId owner;
|
||||
|
||||
/* Id of the player that should predict simulation of this this entity locally */
|
||||
EntId predictor;
|
||||
EntityId predictor;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Position */
|
||||
@ -130,13 +130,13 @@ Struct(Ent) {
|
||||
/* SEPROP_CMD */
|
||||
|
||||
CmdKind cmd_kind;
|
||||
EntId cmd_player;
|
||||
EntityId cmd_player;
|
||||
|
||||
/* FIXME: Lerp */
|
||||
|
||||
/* Control cmd */
|
||||
ControlData cmd_control;
|
||||
EntId cmd_control_hovered_ent;
|
||||
EntityId cmd_control_hovered_ent;
|
||||
|
||||
/* Chat cmd */
|
||||
//String cmd_chat_msg;
|
||||
@ -146,7 +146,7 @@ Struct(Ent) {
|
||||
|
||||
/* SEPROP_CHAT */
|
||||
|
||||
EntId chat_player;
|
||||
EntityId chat_player;
|
||||
//String chat_msg;
|
||||
|
||||
|
||||
@ -171,11 +171,11 @@ Struct(Ent) {
|
||||
ControlData player_control;
|
||||
Vec2 player_cursor_pos;
|
||||
|
||||
EntId player_hovered_ent;
|
||||
EntId player_control_ent;
|
||||
EntId player_camera_ent;
|
||||
EntityId player_hovered_ent;
|
||||
EntityId player_control_ent;
|
||||
EntityId player_camera_ent;
|
||||
|
||||
EntId player_dbg_drag_joint_ent;
|
||||
EntityId player_dbg_drag_joint_ent;
|
||||
b32 player_dbg_drag_start;
|
||||
b32 player_dbg_drag_stop;
|
||||
|
||||
@ -215,7 +215,7 @@ Struct(Ent) {
|
||||
|
||||
/* SEPROP_CONTROLLED */
|
||||
|
||||
EntId controlling_player;
|
||||
EntityId controlling_player;
|
||||
|
||||
f32 control_force; /* How much force is applied to achieve desired control movement */
|
||||
f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */
|
||||
@ -224,8 +224,8 @@ Struct(Ent) {
|
||||
|
||||
ControlData control;
|
||||
|
||||
EntId move_joint;
|
||||
EntId aim_joint;
|
||||
EntityId move_joint;
|
||||
EntityId aim_joint;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Physics */
|
||||
@ -239,7 +239,7 @@ Struct(Ent) {
|
||||
f32 mass_unscaled; /* Mass of ent in kg before any transformations */
|
||||
f32 inertia_unscaled; /* Inertia of ent in kg*m^2 before any transformations */
|
||||
|
||||
EntId ground_friction_joint;
|
||||
EntityId ground_friction_joint;
|
||||
f32 linear_ground_friction;
|
||||
f32 angular_ground_friction;
|
||||
|
||||
@ -282,22 +282,22 @@ Struct(Ent) {
|
||||
/* ====================================================================== */
|
||||
/* Equip */
|
||||
|
||||
EntId equipped;
|
||||
EntityId equipped;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Chucker */
|
||||
|
||||
/* SEPROP_WEAPON_CHUCKER */
|
||||
|
||||
EntId chucker_zone;
|
||||
EntId chucker_joint;
|
||||
EntityId chucker_zone;
|
||||
EntityId chucker_joint;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Chucker zone */
|
||||
|
||||
/* SEPROP_CHUCKER_ZONE */
|
||||
|
||||
EntId chucker_zone_ent;
|
||||
EntityId chucker_zone_ent;
|
||||
u64 chucker_zone_ent_tick;
|
||||
|
||||
/* ====================================================================== */
|
||||
@ -319,14 +319,14 @@ Struct(Ent) {
|
||||
i64 triggered_count;
|
||||
|
||||
/* Other triggers to activate when this entity has been triggered */
|
||||
//EntId trigger_out_left;
|
||||
//EntId trigger_out_right;
|
||||
//EntityId trigger_out_left;
|
||||
//EntityId trigger_out_right;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Bullet */
|
||||
|
||||
EntId bullet_src;
|
||||
EntId bullet_tracer;
|
||||
EntityId bullet_src;
|
||||
EntityId bullet_tracer;
|
||||
Vec2 bullet_src_pos;
|
||||
Vec2 bullet_src_dir;
|
||||
f32 bullet_launch_velocity;
|
||||
@ -380,7 +380,7 @@ Struct(Ent) {
|
||||
/* Camera */
|
||||
|
||||
/* SEPROP_CAMERA */
|
||||
EntId camera_follow;
|
||||
EntityId camera_follow;
|
||||
Xform camera_quad_xform;
|
||||
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
||||
|
||||
@ -392,7 +392,7 @@ Struct(Ent) {
|
||||
};
|
||||
|
||||
Struct(EntArray) {
|
||||
Ent *ents;
|
||||
Entity *ents;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
@ -410,9 +410,9 @@ Struct(EntBin) {
|
||||
* Nil
|
||||
* ========================== */
|
||||
|
||||
Inline Ent *sim_ent_nil(void)
|
||||
Inline Entity *sim_ent_nil(void)
|
||||
{
|
||||
extern Readonly Ent **_g_sim_ent_nil;
|
||||
extern Readonly Entity **_g_sim_ent_nil;
|
||||
return *_g_sim_ent_nil;
|
||||
}
|
||||
|
||||
@ -420,12 +420,12 @@ Inline Ent *sim_ent_nil(void)
|
||||
* Id helpers
|
||||
* ========================== */
|
||||
|
||||
Inline b32 sim_ent_id_eq(EntId a, EntId b)
|
||||
Inline b32 sim_ent_id_eq(EntityId a, EntityId b)
|
||||
{
|
||||
return EqUid(a.uid, b.uid);
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_id_is_nil(EntId id)
|
||||
Inline b32 sim_ent_id_is_nil(EntityId id)
|
||||
{
|
||||
return EqUid(id.uid, SIM_ENT_NIL_ID.uid);
|
||||
}
|
||||
@ -434,49 +434,49 @@ Inline b32 sim_ent_id_is_nil(EntId id)
|
||||
* Property helpers
|
||||
* ========================== */
|
||||
|
||||
Inline void sim_ent_enable_prop(Ent *ent, EntProp prop)
|
||||
Inline void sim_ent_enable_prop(Entity *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] |= ((u64)1 << bit);
|
||||
}
|
||||
|
||||
Inline void sim_ent_disable_prop(Ent *ent, EntProp prop)
|
||||
Inline void sim_ent_disable_prop(Entity *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] &= ~((u64)1 << bit);
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_has_prop(Ent *ent, EntProp prop)
|
||||
Inline b32 sim_ent_has_prop(Entity *ent, EntProp prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
return !!(ent->props[index] & ((u64)1 << bit));
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_is_valid_and_active(Ent *ent)
|
||||
Inline b32 sim_ent_is_valid_and_active(Entity *ent)
|
||||
{
|
||||
return ent->valid && sim_ent_has_prop(ent, SEPROP_ACTIVE);
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_should_predict(Ent *ent)
|
||||
Inline b32 sim_ent_should_predict(Entity *ent)
|
||||
{
|
||||
return sim_ent_id_eq(ent->predictor, ent->ss->local_player);
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_is_owner(Ent *ent)
|
||||
Inline b32 sim_ent_is_owner(Entity *ent)
|
||||
{
|
||||
return sim_ent_id_eq(ent->owner, ent->ss->local_player);
|
||||
}
|
||||
|
||||
Inline b32 sim_ent_should_simulate(Ent *ent)
|
||||
Inline b32 sim_ent_should_simulate(Entity *ent)
|
||||
{
|
||||
b32 result = 0;
|
||||
if (sim_ent_is_valid_and_active(ent)) {
|
||||
result = 1;
|
||||
if (sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
EntId local_player = ent->ss->local_player;
|
||||
EntityId local_player = ent->ss->local_player;
|
||||
result = sim_ent_id_eq(local_player, ent->owner) || sim_ent_id_eq(local_player, ent->predictor);
|
||||
}
|
||||
}
|
||||
@ -484,67 +484,67 @@ Inline b32 sim_ent_should_simulate(Ent *ent)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Ent functions
|
||||
* Entity functions
|
||||
* ========================== */
|
||||
|
||||
/* Alloc */
|
||||
Ent *sim_ent_alloc_raw(Snapshot *ss, Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_local(Ent *parent);
|
||||
Ent *sim_ent_alloc_local_with_id(Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_sync_src(Ent *parent);
|
||||
Ent *sim_ent_alloc_sync_src_with_id(Ent *parent, EntId id);
|
||||
Ent *sim_ent_alloc_sync_dst(Ent *parent, EntId ent_id, EntId owner_id);
|
||||
Entity *sim_ent_alloc_raw(Snapshot *ss, Entity *parent, EntityId id);
|
||||
Entity *sim_ent_alloc_local(Entity *parent);
|
||||
Entity *sim_ent_alloc_local_with_id(Entity *parent, EntityId id);
|
||||
Entity *sim_ent_alloc_sync_src(Entity *parent);
|
||||
Entity *sim_ent_alloc_sync_src_with_id(Entity *parent, EntityId id);
|
||||
Entity *sim_ent_alloc_sync_dst(Entity *parent, EntityId ent_id, EntityId owner_id);
|
||||
|
||||
void sim_ent_release_raw(Ent *ent);
|
||||
void sim_ent_release(Ent *ent);
|
||||
void sim_ent_release_raw(Entity *ent);
|
||||
void sim_ent_release(Entity *ent);
|
||||
void sim_ent_release_all_with_prop(Snapshot *ss, EntProp prop);
|
||||
|
||||
/* Activate */
|
||||
void sim_ent_activate(Ent *ent, u64 current_tick);
|
||||
void sim_ent_activate(Entity *ent, u64 current_tick);
|
||||
|
||||
/* Id */
|
||||
void sim_ent_set_id(Ent *ent, EntId id);
|
||||
Ent *sim_ent_from_id(Snapshot *ss, EntId id);
|
||||
EntId sim_ent_random_id(void);
|
||||
EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId id0, EntId id1);
|
||||
EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1);
|
||||
EntId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_start);
|
||||
void sim_ent_set_id(Entity *ent, EntityId id);
|
||||
Entity *sim_ent_from_id(Snapshot *ss, EntityId id);
|
||||
EntityId sim_ent_random_id(void);
|
||||
EntityId sim_ent_contact_constraint_id_from_contacting_ids(EntityId player_id, EntityId id0, EntityId id1);
|
||||
EntityId sim_ent_collision_debug_id_from_ids(EntityId player_id, EntityId id0, EntityId id1);
|
||||
EntityId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_start);
|
||||
|
||||
/* Query */
|
||||
Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop);
|
||||
Ent *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props);
|
||||
Entity *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop);
|
||||
Entity *sim_ent_find_first_match_all(Snapshot *ss, EntPropArray props);
|
||||
|
||||
/* Tree */
|
||||
void sim_ent_link_parent(Ent *parent, Ent *child);
|
||||
void sim_ent_unlink_from_parent(Ent *ent);
|
||||
void sim_ent_link_parent(Entity *parent, Entity *child);
|
||||
void sim_ent_unlink_from_parent(Entity *ent);
|
||||
|
||||
/* Xform */
|
||||
Xform sim_ent_get_xform(Ent *ent);
|
||||
Xform sim_ent_get_local_xform(Ent *ent);
|
||||
void sim_ent_set_xform(Ent *ent, Xform xf);
|
||||
void sim_ent_set_local_xform(Ent *ent, Xform xf);
|
||||
Xform sim_ent_get_xform(Entity *ent);
|
||||
Xform sim_ent_get_local_xform(Entity *ent);
|
||||
void sim_ent_set_xform(Entity *ent, Xform xf);
|
||||
void sim_ent_set_local_xform(Entity *ent, Xform xf);
|
||||
|
||||
/* Movement */
|
||||
void sim_ent_set_linear_velocity(Ent *ent, Vec2 velocity);
|
||||
void sim_ent_set_angular_velocity(Ent *ent, f32 velocity);
|
||||
void sim_ent_apply_linear_impulse(Ent *ent, Vec2 impulse, Vec2 world_point);
|
||||
void sim_ent_apply_linear_impulse_to_center(Ent *ent, Vec2 impulse);
|
||||
void sim_ent_apply_force_to_center(Ent *ent, Vec2 force);
|
||||
void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse);
|
||||
void sim_ent_apply_torque(Ent *ent, f32 torque);
|
||||
void sim_ent_set_linear_velocity(Entity *ent, Vec2 velocity);
|
||||
void sim_ent_set_angular_velocity(Entity *ent, f32 velocity);
|
||||
void sim_ent_apply_linear_impulse(Entity *ent, Vec2 impulse, Vec2 world_point);
|
||||
void sim_ent_apply_linear_impulse_to_center(Entity *ent, Vec2 impulse);
|
||||
void sim_ent_apply_force_to_center(Entity *ent, Vec2 force);
|
||||
void sim_ent_apply_angular_impulse(Entity *ent, f32 impulse);
|
||||
void sim_ent_apply_torque(Entity *ent, f32 torque);
|
||||
|
||||
/* Tile */
|
||||
Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, Vec2I32 chunk_index);
|
||||
Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, Vec2I32 world_tile_index);
|
||||
TileKind sim_get_chunk_tile(Ent *chunk_ent, Vec2I32 local_tile_index);
|
||||
Entity *sim_tile_chunk_from_chunk_index(Snapshot *ss, Vec2I32 chunk_index);
|
||||
Entity *sim_tile_chunk_from_world_tile_index(Snapshot *ss, Vec2I32 world_tile_index);
|
||||
TileKind sim_get_chunk_tile(Entity *chunk_ent, Vec2I32 local_tile_index);
|
||||
|
||||
/* Lerp */
|
||||
void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend);
|
||||
void sim_ent_lerp(Entity *e, Entity *e0, Entity *e1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_ent_sync_alloc_tree(Ent *local_parent, Ent *remote, EntId remote_player);
|
||||
void sim_ent_sync(Ent *local, Ent *remote);
|
||||
void sim_ent_sync_alloc_tree(Entity *local_parent, Entity *remote, EntityId remote_player);
|
||||
void sim_ent_sync(Entity *local, Entity *remote);
|
||||
|
||||
/* Encode / decode */
|
||||
void sim_ent_encode(BB_Writer *bw, Ent *e0, Ent *e1);
|
||||
void sim_ent_decode(BB_Reader *br, Ent *e);
|
||||
void sim_ent_encode(BB_Writer *bw, Entity *e0, Entity *e1);
|
||||
void sim_ent_decode(BB_Reader *br, Entity *e);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* Contact
|
||||
* ========================== */
|
||||
|
||||
internal b32 can_contact(Ent *e0, Ent *e1)
|
||||
internal b32 can_contact(Entity *e0, Entity *e1)
|
||||
{
|
||||
b32 result = 0;
|
||||
result = e0 != e1 &&
|
||||
@ -20,14 +20,14 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
SimStepCtx *sim_step_ctx = ctx->sim_step_ctx;
|
||||
Snapshot *ss = sim_step_ctx->world;
|
||||
Space *space = sim_step_ctx->accel->space;
|
||||
EntId local_player = ss->local_player;
|
||||
EntityId local_player = ss->local_player;
|
||||
phys_collision_callback_func *collision_callback = ctx->collision_callback;
|
||||
|
||||
Ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
Entity *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
|
||||
u64 tick = ss->tick;
|
||||
|
||||
for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) {
|
||||
Ent *check0 = &ss->ents[check0_index];
|
||||
Entity *check0 = &ss->ents[check0_index];
|
||||
if (!sim_ent_is_valid_and_active(check0)) continue;
|
||||
if (!(sim_ent_has_prop(check0, SEPROP_SOLID) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue;
|
||||
if (check0->local_collider.count <= 0) continue;
|
||||
@ -39,15 +39,15 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
SpaceIter iter = space_iter_begin_aabb(space, aabb);
|
||||
SpaceEntry *space_entry;
|
||||
while ((space_entry = space_iter_next(&iter)) != 0) {
|
||||
Ent *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||
Entity *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||
if (!sim_ent_is_valid_and_active(check1)) continue;
|
||||
if (!(sim_ent_has_prop(check1, SEPROP_SOLID) || sim_ent_has_prop(check1, SEPROP_SENSOR))) continue;
|
||||
if (check1->local_collider.count <= 0) continue;
|
||||
if (!can_contact(check0, check1)) continue;
|
||||
|
||||
/* Deterministic order based on entity id */
|
||||
Ent *e0;
|
||||
Ent *e1;
|
||||
Entity *e0;
|
||||
Entity *e1;
|
||||
Xform e0_xf;
|
||||
Xform e1_xf;
|
||||
CLD_Shape e0_collider;
|
||||
@ -68,8 +68,8 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
e1_collider = check0_collider;
|
||||
}
|
||||
|
||||
EntId constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(local_player, e0->id, e1->id);
|
||||
Ent *constraint_ent = sim_ent_from_id(ss, constraint_id);
|
||||
EntityId constraint_id = sim_ent_contact_constraint_id_from_contacting_ids(local_player, e0->id, e1->id);
|
||||
Entity *constraint_ent = sim_ent_from_id(ss, constraint_id);
|
||||
|
||||
if (constraint_ent->valid) {
|
||||
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) {
|
||||
@ -228,8 +228,8 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
|
||||
/* TODO: Remove this (debugging) */
|
||||
#if COLLIDER_DEBUG && COLLIDER_DEBUG_DETAILED
|
||||
{
|
||||
EntId dbg_ent_id = sim_ent_collision_debug_id_from_ids(local_player, e0->id, e1->id);
|
||||
Ent *dbg_ent = sim_ent_from_id(ss, dbg_ent_id);
|
||||
EntityId dbg_ent_id = sim_ent_collision_debug_id_from_ids(local_player, e0->id, e1->id);
|
||||
Entity *dbg_ent = sim_ent_from_id(ss, dbg_ent_id);
|
||||
if (!dbg_ent->valid) {
|
||||
/* FIXME: Entity never released */
|
||||
dbg_ent = sim_ent_alloc_local_with_id(root, dbg_ent_id);
|
||||
@ -271,15 +271,15 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
||||
Vec2 normal = constraint->normal;
|
||||
Vec2 tangent = PerpVec2(normal);
|
||||
@ -355,13 +355,13 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
|
||||
#if COLLIDER_DEBUG
|
||||
/* Remove collision debug ents */
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *dbg_ent = &ss->ents[sim_ent_index];
|
||||
Entity *dbg_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(dbg_ent)) continue;
|
||||
if (!sim_ent_has_prop(dbg_ent, SEPROP_COLLISION_DEBUG)) continue;
|
||||
|
||||
CollisionDebugData *dbg = &dbg_ent->collision_debug_data;
|
||||
Ent *e0 = sim_ent_from_id(ss, dbg->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, dbg->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, dbg->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, dbg->e1);
|
||||
|
||||
if (!(sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) ||
|
||||
!(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR)) ||
|
||||
@ -380,15 +380,15 @@ void phys_warm_start_contacts(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
u32 num_points = constraint->num_points;
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
|
||||
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve && !constraint->wrong_dir) {
|
||||
f32 inv_m0 = constraint->inv_m0;
|
||||
@ -432,14 +432,14 @@ void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *constraint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(constraint_ent)) continue;
|
||||
if (!sim_ent_has_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT)) continue;
|
||||
|
||||
ContactConstraint *constraint = &constraint_ent->contact_constraint_data;
|
||||
|
||||
Ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||
|
||||
Vec2 v0 = e0->linear_velocity;
|
||||
Vec2 v1 = e1->linear_velocity;
|
||||
@ -570,14 +570,14 @@ void phys_prepare_motor_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
@ -634,14 +634,14 @@ void phys_warm_start_motor_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -666,14 +666,14 @@ void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOTOR_JOINT)) continue;
|
||||
|
||||
MotorJoint *joint = &joint_ent->motor_joint_data;
|
||||
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -772,12 +772,12 @@ void phys_prepare_mouse_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Entity *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -819,12 +819,12 @@ void phys_warm_start_mouse_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Entity *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
f32 inv_m = joint->inv_m;
|
||||
f32 inv_i = joint->inv_i;
|
||||
@ -841,12 +841,12 @@ void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_MOUSE_JOINT)) continue;
|
||||
|
||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||
Ent *ent = sim_ent_from_id(ss, joint->target);
|
||||
Entity *ent = sim_ent_from_id(ss, joint->target);
|
||||
if (sim_ent_should_simulate(ent)) {
|
||||
Vec2 v = ent->linear_velocity;
|
||||
f32 w = ent->angular_velocity;
|
||||
@ -937,15 +937,15 @@ void phys_prepare_weld_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
/* TODO: Lookup and disable collision for any contacts between e0 & e1? */
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform e0_xf = sim_ent_get_xform(e0);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
@ -986,14 +986,14 @@ void phys_warm_start_weld_joints(PhysStepCtx *ctx)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
|
||||
#if 0
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
if (sim_ent_should_simulate(e0)) {
|
||||
f32 inv_m = joint->inv_m0;
|
||||
f32 inv_i = joint->inv_i0;
|
||||
@ -1005,7 +1005,7 @@ void phys_warm_start_weld_joints(PhysStepCtx *ctx)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e1)) {
|
||||
f32 inv_m = joint->inv_m1;
|
||||
f32 inv_i = joint->inv_i1;
|
||||
@ -1023,13 +1023,13 @@ void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *joint_ent = &ss->ents[sim_ent_index];
|
||||
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(joint_ent)) continue;
|
||||
if (!sim_ent_has_prop(joint_ent, SEPROP_WELD_JOINT)) continue;
|
||||
|
||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||
Ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
Entity *e0 = sim_ent_from_id(ss, joint->e0);
|
||||
Entity *e1 = sim_ent_from_id(ss, joint->e1);
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
Xform xf0 = sim_ent_get_xform(e0);
|
||||
Xform xf1 = sim_ent_get_xform(e1);
|
||||
@ -1086,7 +1086,7 @@ void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
|
||||
* Integration
|
||||
* ========================== */
|
||||
|
||||
internal Xform get_derived_xform(Ent *ent, f32 dt)
|
||||
internal Xform get_derived_xform(Entity *ent, f32 dt)
|
||||
{
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -1103,7 +1103,7 @@ void phys_integrate_forces(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
Entity *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_DYNAMIC);
|
||||
@ -1145,7 +1145,7 @@ void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt)
|
||||
__prof;
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
Entity *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_KINEMATIC)) continue;
|
||||
|
||||
@ -1166,7 +1166,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
|
||||
f32 smallest_t = 1;
|
||||
|
||||
for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) {
|
||||
Ent *e0 = &ss->ents[e0_index];
|
||||
Entity *e0 = &ss->ents[e0_index];
|
||||
if (!sim_ent_should_simulate(e0)) continue;
|
||||
if (!(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR))) continue;
|
||||
if (!sim_ent_has_prop(e0, SEPROP_TOI)) continue;
|
||||
@ -1184,7 +1184,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
|
||||
SpaceIter iter = space_iter_begin_aabb(space, combined_aabb);
|
||||
SpaceEntry *entry;
|
||||
while ((entry = space_iter_next(&iter)) != 0) {
|
||||
Ent *e1 = sim_ent_from_id(ss, entry->ent);
|
||||
Entity *e1 = sim_ent_from_id(ss, entry->ent);
|
||||
if (!sim_ent_should_simulate(e1)) continue;
|
||||
if (!(sim_ent_has_prop(e1, SEPROP_SOLID) || sim_ent_has_prop(e1, SEPROP_SENSOR))) continue;
|
||||
if (e1->local_collider.count <= 0) continue;
|
||||
@ -1215,7 +1215,7 @@ void phys_update_aabbs(PhysStepCtx *ctx)
|
||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||
Space *space = ctx->sim_step_ctx->accel->space;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
Entity *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
if (ent->local_collider.count > 0) {
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
typedef struct CollisionData CollisionData;
|
||||
struct CollisionData {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
Vec2 point;
|
||||
Vec2 normal; /* Normal of the collision from e0 to e1 */
|
||||
Vec2 vrel; /* Relative velocity at point of collision */
|
||||
@ -56,8 +56,8 @@ struct ContactConstraint {
|
||||
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
|
||||
b32 skip_solve;
|
||||
b32 wrong_dir;
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
@ -75,8 +75,8 @@ struct ContactConstraint {
|
||||
|
||||
typedef struct CollisionDebugData CollisionDebugData;
|
||||
struct CollisionDebugData {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
CLD_CollisionData collision_result;
|
||||
|
||||
ContactPoint points[2];
|
||||
@ -100,8 +100,8 @@ void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
|
||||
|
||||
typedef struct MotorJointDesc MotorJointDesc;
|
||||
struct MotorJointDesc {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
@ -109,8 +109,8 @@ struct MotorJointDesc {
|
||||
|
||||
typedef struct MotorJoint MotorJoint;
|
||||
struct MotorJoint {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
@ -142,7 +142,7 @@ void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
typedef struct MouseJointDesc MouseJointDesc;
|
||||
struct MouseJointDesc {
|
||||
EntId target;
|
||||
EntityId target;
|
||||
Vec2 point_local_start;
|
||||
Vec2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -154,7 +154,7 @@ struct MouseJointDesc {
|
||||
|
||||
typedef struct MouseJoint MouseJoint;
|
||||
struct MouseJoint {
|
||||
EntId target;
|
||||
EntityId target;
|
||||
Vec2 point_local_start;
|
||||
Vec2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -184,8 +184,8 @@ void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
typedef struct WeldJointDesc WeldJointDesc;
|
||||
struct WeldJointDesc {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
|
||||
/* The xform that transforms a point in e0's space into the desired e1 space
|
||||
* (IE `xf` * VEC2(0, 0) should evaluate to the local point that e1's origin will lie) */
|
||||
@ -199,8 +199,8 @@ struct WeldJointDesc {
|
||||
|
||||
typedef struct WeldJoint WeldJoint;
|
||||
struct WeldJoint {
|
||||
EntId e0;
|
||||
EntId e1;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
Xform xf0_to_xf1;
|
||||
|
||||
f32 linear_spring_hz;
|
||||
|
||||
@ -267,7 +267,7 @@ SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle)
|
||||
return entry;
|
||||
}
|
||||
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntId ent)
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntityId ent)
|
||||
{
|
||||
SpaceEntry *entry = 0;
|
||||
SpaceEntryHandle handle = ZI;
|
||||
|
||||
@ -14,7 +14,7 @@ struct SpaceEntry {
|
||||
SpaceCellNode *last_node;
|
||||
|
||||
Aabb aabb;
|
||||
EntId ent;
|
||||
EntityId ent;
|
||||
|
||||
SpaceEntry *next_free;
|
||||
};
|
||||
@ -131,7 +131,7 @@ SpaceCell *space_get_cell(Space *space, Vec2I32 cell_pos);
|
||||
* ========================== */
|
||||
|
||||
SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle);
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntId entity);
|
||||
SpaceEntry *space_entry_alloc(Space *space, EntityId entity);
|
||||
void space_entry_release(SpaceEntry *entry);
|
||||
void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel)
|
||||
|
||||
/* Reset ent space handles */
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
Ent *ent = &ss->ents[sim_ent_index];
|
||||
Entity *ent = &ss->ents[sim_ent_index];
|
||||
if (ent->valid) {
|
||||
ZeroStruct(&ent->space_handle);
|
||||
}
|
||||
@ -33,9 +33,9 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel)
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
internal Ent *test_spawn_smg(Ent *parent)
|
||||
internal Entity *test_spawn_smg(Entity *parent)
|
||||
{
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
e->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_ATTACHED);
|
||||
@ -49,9 +49,9 @@ internal Ent *test_spawn_smg(Ent *parent)
|
||||
return e;
|
||||
}
|
||||
|
||||
internal Ent *test_spawn_launcher(Ent *parent)
|
||||
internal Entity *test_spawn_launcher(Entity *parent)
|
||||
{
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
e->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_ATTACHED);
|
||||
@ -65,9 +65,9 @@ internal Ent *test_spawn_launcher(Ent *parent)
|
||||
return e;
|
||||
}
|
||||
|
||||
internal Ent *test_spawn_chucker(Ent *parent)
|
||||
internal Entity *test_spawn_chucker(Entity *parent)
|
||||
{
|
||||
Ent *chucker = sim_ent_alloc_sync_src(parent);
|
||||
Entity *chucker = sim_ent_alloc_sync_src(parent);
|
||||
chucker->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
|
||||
|
||||
sim_ent_enable_prop(chucker, SEPROP_ATTACHED);
|
||||
@ -80,7 +80,7 @@ internal Ent *test_spawn_chucker(Ent *parent)
|
||||
|
||||
/* Chucker zone */
|
||||
{
|
||||
Ent *zone = sim_ent_alloc_sync_src(chucker);
|
||||
Entity *zone = sim_ent_alloc_sync_src(chucker);
|
||||
|
||||
sim_ent_enable_prop(zone, SEPROP_CHUCKER_ZONE);
|
||||
|
||||
@ -100,13 +100,13 @@ internal Ent *test_spawn_chucker(Ent *parent)
|
||||
return chucker;
|
||||
}
|
||||
|
||||
internal Ent *test_spawn_employee(Ent *parent)
|
||||
internal Entity *test_spawn_employee(Entity *parent)
|
||||
{
|
||||
/* Player */
|
||||
Ent *employee = sim_ent_nil();
|
||||
Entity *employee = sim_ent_nil();
|
||||
{
|
||||
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
Vec2 pos = VEC2(1, -1);
|
||||
|
||||
@ -174,7 +174,7 @@ internal Ent *test_spawn_employee(Ent *parent)
|
||||
(UNUSED)test_spawn_launcher;
|
||||
(UNUSED)test_spawn_chucker;
|
||||
|
||||
Ent *e = test_spawn_chucker(employee);
|
||||
Entity *e = test_spawn_chucker(employee);
|
||||
employee->equipped = e->id;
|
||||
|
||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||
@ -184,9 +184,9 @@ internal Ent *test_spawn_employee(Ent *parent)
|
||||
return employee;
|
||||
}
|
||||
|
||||
internal Ent *test_spawn_camera(Ent *parent, Ent *follow)
|
||||
internal Entity *test_spawn_camera(Entity *parent, Entity *follow)
|
||||
{
|
||||
Ent *camera_ent = sim_ent_nil();
|
||||
Entity *camera_ent = sim_ent_nil();
|
||||
if (follow->valid) {
|
||||
camera_ent = sim_ent_alloc_sync_src(parent);
|
||||
sim_ent_set_xform(camera_ent, XformIdentity);
|
||||
@ -203,9 +203,9 @@ internal Ent *test_spawn_camera(Ent *parent, Ent *follow)
|
||||
return camera_ent;
|
||||
}
|
||||
|
||||
internal Ent *test_spawn_explosion(Ent *parent, Vec2 pos, f32 strength, f32 radius)
|
||||
internal Entity *test_spawn_explosion(Entity *parent, Vec2 pos, f32 strength, f32 radius)
|
||||
{
|
||||
Ent *ent = sim_ent_alloc_sync_src(parent);
|
||||
Entity *ent = sim_ent_alloc_sync_src(parent);
|
||||
sim_ent_set_xform(ent, XformFromPos(pos));
|
||||
|
||||
sim_ent_enable_prop(ent, SEPROP_EXPLOSION);
|
||||
@ -219,7 +219,7 @@ internal Ent *test_spawn_explosion(Ent *parent, Vec2 pos, f32 strength, f32 radi
|
||||
return ent;
|
||||
}
|
||||
|
||||
internal void test_teleport(Ent *ent, Vec2 pos)
|
||||
internal void test_teleport(Entity *ent, Vec2 pos)
|
||||
{
|
||||
//++ent->continuity_gen;
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
@ -227,28 +227,28 @@ internal void test_teleport(Ent *ent, Vec2 pos)
|
||||
sim_ent_set_xform(ent, xf);
|
||||
}
|
||||
|
||||
internal void test_spawn_entities1(Ent *parent, Vec2 pos)
|
||||
internal void test_spawn_entities1(Entity *parent, Vec2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Enemy */
|
||||
{
|
||||
Ent *e = test_spawn_employee(parent);
|
||||
Entity *e = test_spawn_employee(parent);
|
||||
Xform xf = sim_ent_get_xform(e);
|
||||
xf.og = pos;
|
||||
sim_ent_set_xform(e, xf);
|
||||
}
|
||||
}
|
||||
|
||||
internal void test_spawn_entities2(Ent *parent, Vec2 pos)
|
||||
internal void test_spawn_entities2(Entity *parent, Vec2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Small Box */
|
||||
#if 1
|
||||
{
|
||||
//Ent *e = sim_ent_alloc_local(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
//Entity *e = sim_ent_alloc_local(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 rot = 0;
|
||||
Vec2 size = VEC2(0.125, 0.125);
|
||||
@ -290,7 +290,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos)
|
||||
/* Tiny box */
|
||||
#if 0
|
||||
{
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = Pi / 4;
|
||||
Vec2 size = VEC2(0.5, 0.25);
|
||||
@ -311,14 +311,14 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos)
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void test_spawn_entities3(Ent *parent, Vec2 pos)
|
||||
internal void test_spawn_entities3(Entity *parent, Vec2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Heavy box */
|
||||
{
|
||||
//Ent *e = sim_ent_alloc_local(parent);
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
//Entity *e = sim_ent_alloc_local(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = 0;
|
||||
Vec2 size = VEC2(1, 1);
|
||||
@ -336,12 +336,12 @@ internal void test_spawn_entities3(Ent *parent, Vec2 pos)
|
||||
}
|
||||
}
|
||||
|
||||
internal void test_spawn_entities4(Ent *parent, Vec2 pos)
|
||||
internal void test_spawn_entities4(Entity *parent, Vec2 pos)
|
||||
{
|
||||
(UNUSED)pos;
|
||||
|
||||
/* Light box */
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
f32 r = 0;
|
||||
Vec2 size = VEC2(2, 1);
|
||||
@ -361,7 +361,7 @@ internal void test_spawn_entities4(Ent *parent, Vec2 pos)
|
||||
internal void test_spawn_tile(Snapshot *world, Vec2 world_pos)
|
||||
{
|
||||
#if 0
|
||||
Ent *e = sim_ent_alloc_sync_src(parent);
|
||||
Entity *e = sim_ent_alloc_sync_src(parent);
|
||||
|
||||
i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0);
|
||||
i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0);
|
||||
@ -407,8 +407,8 @@ internal void test_spawn_tile(Snapshot *world, Vec2 world_pos)
|
||||
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_x, arg_a, arg_b, _)
|
||||
{
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
Entity *a = *(Entity **)arg_a;
|
||||
Entity *b = *(Entity **)arg_b;
|
||||
i32 a_x = a->tile_chunk_index.x;
|
||||
i32 b_x = b->tile_chunk_index.x;
|
||||
|
||||
@ -419,8 +419,8 @@ internal MergesortCompareFuncDef(tile_chunk_sort_x, arg_a, arg_b, _)
|
||||
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_y, arg_a, arg_b, _)
|
||||
{
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
Entity *a = *(Entity **)arg_a;
|
||||
Entity *b = *(Entity **)arg_b;
|
||||
i32 a_y = a->tile_chunk_index.y;
|
||||
i32 b_y = b->tile_chunk_index.y;
|
||||
|
||||
@ -433,29 +433,29 @@ internal void test_generate_walls(Snapshot *world)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Entity *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
|
||||
/* Release existing walls and gather tile chunks.
|
||||
* NOTE: We sort tile chunks before iterating so that chunk-edge tiles only
|
||||
* need to check for adjacent walls to merge with in one direction */
|
||||
Ent **x_sorted_tile_chunks = 0;
|
||||
Ent **y_sorted_tile_chunks = 0;
|
||||
Entity **x_sorted_tile_chunks = 0;
|
||||
Entity **y_sorted_tile_chunks = 0;
|
||||
u64 sorted_tile_chunks_count = 0;
|
||||
{
|
||||
x_sorted_tile_chunks = PushDry(scratch.arena, Ent *);
|
||||
x_sorted_tile_chunks = PushDry(scratch.arena, Entity *);
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!ent->valid) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
|
||||
/* Append chunk to array */
|
||||
*PushStructNoZero(scratch.arena, Ent *) = ent;
|
||||
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
||||
++sorted_tile_chunks_count;
|
||||
} else if (sim_ent_has_prop(ent, SEPROP_WALL)) {
|
||||
/* Release existing wall */
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
}
|
||||
y_sorted_tile_chunks = PushStructsNoZero(scratch.arena, Ent *, sorted_tile_chunks_count);
|
||||
y_sorted_tile_chunks = PushStructsNoZero(scratch.arena, Entity *, sorted_tile_chunks_count);
|
||||
CopyBytes(y_sorted_tile_chunks, x_sorted_tile_chunks, sizeof(*x_sorted_tile_chunks) * sorted_tile_chunks_count);
|
||||
|
||||
/* NOTE: We sort x & y separately because it's possible that a wall
|
||||
@ -480,10 +480,10 @@ internal void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Generate horizontal wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
Ent *chunk = x_sorted_tile_chunks[sorted_index];
|
||||
Entity *chunk = x_sorted_tile_chunks[sorted_index];
|
||||
Vec2I32 chunk_index = chunk->tile_chunk_index;
|
||||
Ent *top_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x, chunk_index.y - 1));
|
||||
Ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x, chunk_index.y + 1));
|
||||
Entity *top_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x, chunk_index.y - 1));
|
||||
Entity *bottom_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x, chunk_index.y + 1));
|
||||
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
@ -569,10 +569,10 @@ internal void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Generate vertical wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
Ent *chunk = y_sorted_tile_chunks[sorted_index];
|
||||
Entity *chunk = y_sorted_tile_chunks[sorted_index];
|
||||
Vec2I32 chunk_index = chunk->tile_chunk_index;
|
||||
Ent *left_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x - 1, chunk_index.y));
|
||||
Ent *right_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x + 1, chunk_index.y));
|
||||
Entity *left_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x - 1, chunk_index.y));
|
||||
Entity *right_chunk = sim_tile_chunk_from_chunk_index(world, VEC2I32(chunk_index.x + 1, chunk_index.y));
|
||||
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
||||
@ -659,7 +659,7 @@ internal void test_generate_walls(Snapshot *world)
|
||||
|
||||
/* Create wall entities */
|
||||
for (struct wall_node *node = first_wall; node; node = node->next) {
|
||||
Ent *wall_ent = sim_ent_alloc_sync_src(root);
|
||||
Entity *wall_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(wall_ent, SEPROP_WALL);
|
||||
|
||||
Vec2 start = sim_pos_from_world_tile_index(node->start);
|
||||
@ -697,7 +697,7 @@ internal void test_clear_level(SimStepCtx *ctx)
|
||||
{
|
||||
Snapshot *world = ctx->world;
|
||||
for (u64 j = 0; j < world->num_ents_reserved; ++j) {
|
||||
Ent *ent = &world->ents[j];
|
||||
Entity *ent = &world->ents[j];
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
@ -711,9 +711,9 @@ internal void test_clear_level(SimStepCtx *ctx)
|
||||
internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
{
|
||||
Snapshot *world = step_ctx->world;
|
||||
Ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Entity *e0 = sim_ent_from_id(world, data->e0);
|
||||
Entity *e1 = sim_ent_from_id(world, data->e1);
|
||||
Entity *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
b32 skip_solve = 0;
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
@ -722,16 +722,16 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
Vec2 normal = data->normal; /* Impact normal */
|
||||
Vec2 vrel = data->vrel; /* Impact velocity */
|
||||
|
||||
Ent *bullet = e0;
|
||||
Ent *target = e1;
|
||||
Ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
Entity *bullet = e0;
|
||||
Entity *target = e1;
|
||||
Entity *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
|
||||
/* Process collision if bullet already spent or * target share same top level parent */
|
||||
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top) && sim_ent_has_prop(target, SEPROP_SOLID)) {
|
||||
Vec2 point = data->point;
|
||||
|
||||
/* Update tracer */
|
||||
Ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
||||
Entity *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
||||
if (sim_ent_should_simulate(tracer)) {
|
||||
Xform xf = sim_ent_get_xform(tracer);
|
||||
xf.og = point;
|
||||
@ -747,7 +747,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
/* TODO: Remove this */
|
||||
{
|
||||
Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau)));
|
||||
Ent *decal = sim_ent_alloc_sync_src(root);
|
||||
Entity *decal = sim_ent_alloc_sync_src(root);
|
||||
decal->sprite = S_TagFromPath(Lit("sprite/blood.ase"));
|
||||
decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f);
|
||||
decal->layer = SIM_LAYER_FLOOR_DECALS;
|
||||
@ -781,8 +781,8 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
|
||||
/* Explosion blast collision */
|
||||
if (sim_ent_has_prop(e0, SEPROP_EXPLOSION)) {
|
||||
Ent *exp = e0;
|
||||
Ent *victim = e1;
|
||||
Entity *exp = e0;
|
||||
Entity *victim = e1;
|
||||
|
||||
Xform xf = sim_ent_get_xform(exp);
|
||||
|
||||
@ -860,7 +860,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
S_Scope *sprite_frame_scope = S_BeginScope();
|
||||
|
||||
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
Entity *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
root->owner = world->client->player_id;
|
||||
|
||||
/* ========================== *
|
||||
@ -872,7 +872,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
|
||||
Client *client = &client_store->clients[client_index];
|
||||
if (client->valid && client != master_client && client != world_client && client != publish_client) {
|
||||
Ent *player = sim_ent_from_id(world, client->player_id);
|
||||
Entity *player = sim_ent_from_id(world, client->player_id);
|
||||
|
||||
/* Create player if necessary */
|
||||
if (is_master && !player->valid) {
|
||||
@ -912,7 +912,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark all incoming ents as sync dsts */
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
Ent *ent = &world->ents[i];
|
||||
Entity *ent = &world->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_SYNC_SRC) && !sim_ent_id_eq(ent->owner, world_client->player_id)) {
|
||||
sim_ent_disable_prop(ent, SEPROP_SYNC_SRC);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_DST);
|
||||
@ -921,7 +921,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark incoming cmds with correct client */
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
Ent *ent = &world->ents[i];
|
||||
Entity *ent = &world->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_CMD) && sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
ent->cmd_player = ent->owner;
|
||||
}
|
||||
@ -930,7 +930,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* Mark any locally created CMDs as sync sources */
|
||||
if (!is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
Ent *ent = &world->ents[i];
|
||||
Entity *ent = &world->ents[i];
|
||||
if (sim_ent_is_valid_and_active(ent) && sim_ent_has_prop(ent, SEPROP_CMD)) {
|
||||
if (!sim_ent_id_is_nil(ent->cmd_player) && sim_ent_id_eq(ent->cmd_player, world->local_player)) {
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
@ -952,7 +952,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!ent->valid) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_SYNC_DST) && !sim_ent_is_owner(ent) && !sim_ent_should_predict(ent)) continue;
|
||||
|
||||
@ -969,11 +969,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *cmd_ent = &world->ents[ent_index];
|
||||
Entity *cmd_ent = &world->ents[ent_index];
|
||||
if (!is_master && !sim_ent_should_simulate(cmd_ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(cmd_ent, SEPROP_CMD)) {
|
||||
Ent *player = sim_ent_from_id(world, cmd_ent->cmd_player);
|
||||
Entity *player = sim_ent_from_id(world, cmd_ent->cmd_player);
|
||||
if (sim_ent_should_simulate(player)) {
|
||||
b32 persist_cmd = 0;
|
||||
if (!is_master && !sim_ent_id_eq(player->id, world->local_player)) {
|
||||
@ -1017,7 +1017,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_DELETE) {
|
||||
Ent *ent = sim_ent_from_id(world, player->player_hovered_ent);
|
||||
Entity *ent = sim_ent_from_id(world, player->player_hovered_ent);
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_RELEASE);
|
||||
}
|
||||
@ -1088,7 +1088,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
struct sim_data_key msg_key = cmd_ent->cmd_chat_msg;
|
||||
String msg = sim_data_from_key(sim_data_store, msg_key);
|
||||
if (msg.len > 0) {
|
||||
Ent *chat_ent = sim_ent_alloc_sync_src(root);
|
||||
Entity *chat_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(chat_ent, SEPROP_CHAT);
|
||||
chat_ent->chat_player = player->id;
|
||||
chat_ent->chat_msg = msg_key;
|
||||
@ -1116,11 +1116,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
Ent *player = sim_ent_from_id(world, ent->controlling_player);
|
||||
Entity *player = sim_ent_from_id(world, ent->controlling_player);
|
||||
if (player->valid) {
|
||||
ent->control = player->player_control;
|
||||
}
|
||||
@ -1133,11 +1133,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
if (is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
Ent *ent = &world->ents[i];
|
||||
Entity *ent = &world->ents[i];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (sim_ent_has_prop(ent, SEPROP_PLAYER)) {
|
||||
/* FIXME: Ents never released when client disconnects */
|
||||
Ent *control_ent = sim_ent_from_id(world, ent->player_control_ent);
|
||||
Entity *control_ent = sim_ent_from_id(world, ent->player_control_ent);
|
||||
if (!control_ent->valid) {
|
||||
control_ent = test_spawn_employee(root);
|
||||
control_ent->predictor = ent->id;
|
||||
@ -1145,13 +1145,13 @@ void sim_step(SimStepCtx *ctx)
|
||||
ent->player_control_ent = control_ent->id;
|
||||
control_ent->controlling_player = ent->id;
|
||||
}
|
||||
Ent *camera_ent = sim_ent_from_id(world, ent->player_camera_ent);
|
||||
Entity *camera_ent = sim_ent_from_id(world, ent->player_camera_ent);
|
||||
if (!camera_ent->valid) {
|
||||
camera_ent = test_spawn_camera(root, control_ent);
|
||||
camera_ent->predictor = ent->id;
|
||||
ent->player_camera_ent = camera_ent->id;
|
||||
}
|
||||
Ent *camera_follow = sim_ent_from_id(world, camera_ent->camera_follow);
|
||||
Entity *camera_follow = sim_ent_from_id(world, camera_ent->camera_follow);
|
||||
if (!camera_follow->valid) {
|
||||
camera_ent->camera_follow = control_ent->id;
|
||||
}
|
||||
@ -1164,7 +1164,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (S_IsTagNil(ent->sprite)) continue;
|
||||
|
||||
@ -1266,11 +1266,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_ATTACHED)) continue;
|
||||
|
||||
Ent *parent = sim_ent_from_id(world, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(world, ent->parent);
|
||||
S_Tag parent_sprite = parent->sprite;
|
||||
S_Sheet *parent_sheet = S_SheetFromTagAwait(sprite_frame_scope, parent_sprite);
|
||||
|
||||
@ -1291,20 +1291,20 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
ControlData *control = &ent->control;
|
||||
u32 flags = control->flags;
|
||||
if (flags & SIM_CONTROL_FLAG_FIRE) {
|
||||
Ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
Entity *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
if (equipped->valid) {
|
||||
++equipped->num_primary_triggers;
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_FIRE_ALT) {
|
||||
Ent *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
Entity *equipped = sim_ent_from_id(world, ent->equipped);
|
||||
if (equipped->valid) {
|
||||
++equipped->num_secondary_triggers;
|
||||
}
|
||||
@ -1320,7 +1320,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
b32 primary_triggered = ent->num_primary_triggers > 0;
|
||||
@ -1357,7 +1357,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
/* Spawn bullet */
|
||||
Ent *bullet;
|
||||
Entity *bullet;
|
||||
{
|
||||
bullet = sim_ent_alloc_sync_src(root);
|
||||
|
||||
@ -1382,7 +1382,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn tracer */
|
||||
{
|
||||
Ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
Entity *tracer = sim_ent_alloc_sync_src(root);
|
||||
tracer->tracer_fade_duration = 0.025f;
|
||||
tracer->layer = SIM_LAYER_TRACERS;
|
||||
sim_ent_enable_prop(tracer, SEPROP_TRACER);
|
||||
@ -1404,7 +1404,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir);
|
||||
|
||||
/* Spawn bullet */
|
||||
Ent *bullet;
|
||||
Entity *bullet;
|
||||
{
|
||||
bullet = sim_ent_alloc_sync_src(root);
|
||||
|
||||
@ -1428,7 +1428,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn tracer */
|
||||
{
|
||||
Ent *tracer = sim_ent_alloc_sync_src(root);
|
||||
Entity *tracer = sim_ent_alloc_sync_src(root);
|
||||
tracer->tracer_fade_duration = 0.025f;
|
||||
tracer->layer = SIM_LAYER_TRACERS;
|
||||
sim_ent_enable_prop(tracer, SEPROP_TRACER);
|
||||
@ -1443,12 +1443,12 @@ void sim_step(SimStepCtx *ctx)
|
||||
if (primary_triggered) {
|
||||
}
|
||||
if (secondary_triggered) {
|
||||
Ent *zone = sim_ent_from_id(world, ent->chucker_zone);
|
||||
Ent *target = sim_ent_from_id(world, zone->chucker_zone_ent);
|
||||
Ent *old_joint_ent = sim_ent_from_id(world, ent->chucker_joint);
|
||||
Entity *zone = sim_ent_from_id(world, ent->chucker_zone);
|
||||
Entity *target = sim_ent_from_id(world, zone->chucker_zone_ent);
|
||||
Entity *old_joint_ent = sim_ent_from_id(world, ent->chucker_joint);
|
||||
if (sim_ent_is_valid_and_active(target) && zone->chucker_zone_ent_tick == world->tick - 1) {
|
||||
if (!sim_ent_id_eq(old_joint_ent->weld_joint_data.e1, target->id)) {
|
||||
Ent *joint_ent = sim_ent_alloc_sync_src(root);
|
||||
Entity *joint_ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
||||
|
||||
Xform xf0 = sim_ent_get_xform(ent);
|
||||
@ -1481,11 +1481,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->move_joint);
|
||||
Entity *joint_ent = sim_ent_from_id(world, ent->move_joint);
|
||||
if (is_master && !sim_ent_is_valid_and_active(joint_ent)) {
|
||||
joint_ent = sim_ent_alloc_sync_src(root);
|
||||
joint_ent->predictor = ent->predictor;
|
||||
@ -1518,7 +1518,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
#if SIM_PLAYER_AIM
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||
@ -1526,7 +1526,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
Xform sprite_xf = MulXform(xf, ent->sprite_local_xform);
|
||||
|
||||
/* Retrieve / create aim joint */
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
||||
Entity *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
||||
if (is_master && !sim_ent_is_valid_and_active(joint_ent)) {
|
||||
joint_ent = sim_ent_alloc_sync_src(root);
|
||||
joint_ent->predictor = ent->predictor;
|
||||
@ -1616,11 +1616,11 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
#if 1
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC)) continue;
|
||||
|
||||
Ent *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint);
|
||||
Entity *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint);
|
||||
|
||||
MotorJointDesc def = phys_motor_joint_def_init();
|
||||
def.e0 = root->id;
|
||||
@ -1647,7 +1647,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
if (is_master) {
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
Ent *player = &world->ents[i];
|
||||
Entity *player = &world->ents[i];
|
||||
if (!sim_ent_should_simulate(player)) continue;
|
||||
if (!sim_ent_has_prop(player, SEPROP_PLAYER)) continue;
|
||||
|
||||
@ -1655,8 +1655,8 @@ void sim_step(SimStepCtx *ctx)
|
||||
b32 start_dragging = player->player_dbg_drag_start;
|
||||
b32 stop_dragging = player->player_dbg_drag_stop;
|
||||
|
||||
Ent *joint_ent = sim_ent_from_id(world, player->player_dbg_drag_joint_ent);
|
||||
Ent *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target);
|
||||
Entity *joint_ent = sim_ent_from_id(world, player->player_dbg_drag_joint_ent);
|
||||
Entity *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target);
|
||||
|
||||
if (stop_dragging) {
|
||||
target_ent = sim_ent_nil();
|
||||
@ -1712,7 +1712,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION)) continue;
|
||||
|
||||
@ -1725,7 +1725,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_TRACER)) continue;
|
||||
|
||||
@ -1749,12 +1749,12 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_BULLET)) continue;
|
||||
|
||||
if (ent->activation_tick == world->tick) {
|
||||
Ent *src = sim_ent_from_id(world, ent->bullet_src);
|
||||
Entity *src = sim_ent_from_id(world, ent->bullet_src);
|
||||
Xform src_xf = sim_ent_get_xform(src);
|
||||
|
||||
/* Activate collision */
|
||||
@ -1769,7 +1769,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* Add shooter velocity to bullet */
|
||||
{
|
||||
/* TODO: Add angular velocity as well? */
|
||||
Ent *top = sim_ent_from_id(ss_blended, src->top);
|
||||
Entity *top = sim_ent_from_id(ss_blended, src->top);
|
||||
impulse = AddVec2(impulse, MulVec2(top->linear_velocity, dt));
|
||||
}
|
||||
#endif
|
||||
@ -1781,7 +1781,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
sim_ent_set_linear_velocity(ent, vel);
|
||||
|
||||
/* Initialize tracer */
|
||||
Ent *tracer = sim_ent_from_id(world, ent->bullet_tracer);
|
||||
Entity *tracer = sim_ent_from_id(world, ent->bullet_tracer);
|
||||
if (sim_ent_should_simulate(tracer)) {
|
||||
sim_ent_set_xform(tracer, xf);
|
||||
sim_ent_enable_prop(tracer, SEPROP_KINEMATIC);
|
||||
@ -1794,7 +1794,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Spawn quake */
|
||||
{
|
||||
Ent *quake = sim_ent_alloc_sync_src(root);
|
||||
Entity *quake = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(quake, XformFromPos(pos));
|
||||
quake->quake_intensity = 0.2f;
|
||||
quake->quake_fade = quake->quake_intensity / 0.1f;
|
||||
@ -1808,7 +1808,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_CAMERA)) continue;
|
||||
|
||||
@ -1816,7 +1816,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Camera follow */
|
||||
{
|
||||
Ent *follow = sim_ent_from_id(world, ent->camera_follow);
|
||||
Entity *follow = sim_ent_from_id(world, ent->camera_follow);
|
||||
|
||||
f32 aspect_ratio = 1.0;
|
||||
{
|
||||
@ -1849,7 +1849,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
/* TODO: Update based on distance to quake */
|
||||
ent->shake = 0;
|
||||
for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) {
|
||||
Ent *quake = &world->ents[quake_ent_index];
|
||||
Entity *quake = &world->ents[quake_ent_index];
|
||||
if (!sim_ent_should_simulate(quake)) continue;
|
||||
if (!sim_ent_has_prop(quake, SEPROP_QUAKE)) continue;
|
||||
ent->shake += quake->quake_intensity;
|
||||
@ -1864,7 +1864,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &world->ents[ent_index];
|
||||
Entity *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
if (!sim_ent_has_prop(ent, SEPROP_QUAKE)) continue;
|
||||
|
||||
@ -1881,20 +1881,20 @@ void sim_step(SimStepCtx *ctx)
|
||||
{
|
||||
TempArena temp = BeginTempArena(scratch.arena);
|
||||
|
||||
Ent **stack = PushStructNoZero(temp.arena, Ent *);
|
||||
Entity **stack = PushStructNoZero(temp.arena, Entity *);
|
||||
u64 stack_count = 1;
|
||||
*stack = root;
|
||||
|
||||
while (stack_count > 0) {
|
||||
Ent *parent;
|
||||
PopStruct(temp.arena, Ent *, &parent);
|
||||
Entity *parent;
|
||||
PopStruct(temp.arena, Entity *, &parent);
|
||||
--stack_count;
|
||||
|
||||
i32 parent_layer = parent->final_layer;
|
||||
for (Ent *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) {
|
||||
for (Entity *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) {
|
||||
if (sim_ent_should_simulate(child)) {
|
||||
child->final_layer = parent_layer + child->layer;
|
||||
*PushStructNoZero(temp.arena, Ent *) = child;
|
||||
*PushStructNoZero(temp.arena, Entity *) = child;
|
||||
++stack_count;
|
||||
}
|
||||
}
|
||||
@ -1922,7 +1922,7 @@ void sim_step(SimStepCtx *ctx)
|
||||
|
||||
/* Mark all synced ents as both sync dsts & sync srcs */
|
||||
for (u64 ent_index = 2; ent_index < pub_world->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &pub_world->ents[ent_index];
|
||||
Entity *ent = &pub_world->ents[ent_index];
|
||||
if (ent->valid) {
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_DST);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
|
||||
@ -431,11 +431,11 @@ P_JobDef(S_LoadSpriteJob, job)
|
||||
|
||||
switch (ref.e->kind)
|
||||
{
|
||||
case CACHE_ENTRY_KIND_TEXTURE:
|
||||
case S_CacheEntryKind_Texture:
|
||||
{
|
||||
S_LoadCacheEntryTexture(ref, cmd->tag);
|
||||
} break;
|
||||
case CACHE_ENTRY_KIND_SHEET:
|
||||
case S_CacheEntryKind_Sheet:
|
||||
{
|
||||
S_LoadCacheEntrySheet(ref, cmd->tag);
|
||||
} break;
|
||||
@ -496,7 +496,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
S_CacheEntry *e = ref.e;
|
||||
|
||||
Atomic32FetchSet(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||
Atomic32FetchSet(&e->state, S_CacheEntryState_Working);
|
||||
String path = tag.path;
|
||||
|
||||
P_LogInfoF("Loading sprite texture [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
||||
@ -504,7 +504,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
Assert(StringEndsWith(path, Lit(".ase")));
|
||||
Assert(e->kind == CACHE_ENTRY_KIND_TEXTURE);
|
||||
Assert(e->kind == S_CacheEntryKind_Texture);
|
||||
|
||||
/* TODO: Replace arena allocs w/ buddy allocator */
|
||||
/* TODO: Arena probably overkill. Just using it to store texture struct. */
|
||||
@ -553,7 +553,7 @@ void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag)
|
||||
FmtUint(e->memory_usage));
|
||||
}
|
||||
|
||||
Atomic32FetchSet(&e->state, CACHE_ENTRY_STATE_LOADED);
|
||||
Atomic32FetchSet(&e->state, S_CacheEntryState_Loaded);
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
||||
@ -581,14 +581,14 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
S_CacheEntry *e = ref.e;
|
||||
|
||||
Atomic32FetchSet(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||
Atomic32FetchSet(&e->state, S_CacheEntryState_Working);
|
||||
String path = tag.path;
|
||||
|
||||
P_LogInfoF("Loading sprite sheet [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path));
|
||||
b32 success = 0;
|
||||
i64 start_ns = P_TimeNs();
|
||||
|
||||
Assert(e->kind == CACHE_ENTRY_KIND_SHEET);
|
||||
Assert(e->kind == S_CacheEntryKind_Sheet);
|
||||
|
||||
/* TODO: Replace arena allocs w/ buddy allocator */
|
||||
e->arena = AllocArena(S_SheetArenaReserve);
|
||||
@ -636,7 +636,7 @@ void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag)
|
||||
FmtUint(e->memory_usage));
|
||||
}
|
||||
|
||||
Atomic32FetchSet(&e->state, CACHE_ENTRY_STATE_LOADED);
|
||||
Atomic32FetchSet(&e->state, S_CacheEntryState_Loaded);
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
S_CacheEntryBin *bin = &g->cache.bins[e->hash.v % S_CacheBinsCount];
|
||||
@ -808,13 +808,13 @@ S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock
|
||||
* newest entry rather than the first one that exists since
|
||||
* there may be more than one matching entry in the cache */
|
||||
S_CacheEntry *match = 0;
|
||||
S_CacheEntryState match_state = CACHE_ENTRY_STATE_NONE;
|
||||
S_CacheEntryState match_state = S_CacheEntryState_None;
|
||||
for (S_CacheEntry *entry = bin->first; entry; entry = entry->next_in_bin)
|
||||
{
|
||||
if (entry->hash.v == hash.v)
|
||||
{
|
||||
S_CacheEntryState entry_state = Atomic32Fetch(&entry->state);
|
||||
if (!match || entry_state > match_state || (entry_state == CACHE_ENTRY_STATE_LOADED && match_state == CACHE_ENTRY_STATE_LOADED && entry->load_time_ns > match->load_time_ns))
|
||||
if (!match || entry_state > match_state || (entry_state == S_CacheEntryState_Loaded && match_state == S_CacheEntryState_Loaded && entry->load_time_ns > match->load_time_ns))
|
||||
{
|
||||
match = entry;
|
||||
match_state = entry_state;
|
||||
@ -944,8 +944,8 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
|
||||
void *result = 0;
|
||||
switch (kind)
|
||||
{
|
||||
case CACHE_ENTRY_KIND_TEXTURE: { result = g->loading_texture; } break;
|
||||
case CACHE_ENTRY_KIND_SHEET: { result = g->loading_sheet; } break;
|
||||
case S_CacheEntryKind_Texture: { result = g->loading_texture; } break;
|
||||
case S_CacheEntryKind_Sheet: { result = g->loading_sheet; } break;
|
||||
default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break;
|
||||
}
|
||||
|
||||
@ -953,31 +953,31 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
|
||||
S_CacheEntryRef ref = scope_ref->ref;
|
||||
|
||||
S_CacheEntryState state = Atomic32Fetch(&ref.e->state);
|
||||
if (state == CACHE_ENTRY_STATE_LOADED)
|
||||
if (state == S_CacheEntryState_Loaded)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case CACHE_ENTRY_KIND_TEXTURE: { result = ref.e->texture; } break;
|
||||
case CACHE_ENTRY_KIND_SHEET: { result = ref.e->sheet; } break;
|
||||
case S_CacheEntryKind_Texture: { result = ref.e->texture; } break;
|
||||
case S_CacheEntryKind_Sheet: { result = ref.e->sheet; } break;
|
||||
default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break;
|
||||
}
|
||||
}
|
||||
else if (state == CACHE_ENTRY_STATE_NONE)
|
||||
else if (state == S_CacheEntryState_None)
|
||||
{
|
||||
/* If entry is new, load texture */
|
||||
if (Atomic32FetchTestSet(&ref.e->state, CACHE_ENTRY_STATE_NONE, CACHE_ENTRY_STATE_QUEUED) == CACHE_ENTRY_STATE_NONE)
|
||||
if (Atomic32FetchTestSet(&ref.e->state, S_CacheEntryState_None, S_CacheEntryState_Queued) == S_CacheEntryState_None)
|
||||
{
|
||||
/* If caller is awaiting result then just load now on the calling thread. Otherwise spawn a work task. */
|
||||
if (await)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case CACHE_ENTRY_KIND_TEXTURE:
|
||||
case S_CacheEntryKind_Texture:
|
||||
{
|
||||
S_LoadCacheEntryTexture(ref, tag);
|
||||
result = ref.e->texture;
|
||||
} break;
|
||||
case CACHE_ENTRY_KIND_SHEET:
|
||||
case S_CacheEntryKind_Sheet:
|
||||
{
|
||||
S_LoadCacheEntrySheet(ref, tag);
|
||||
result = ref.e->sheet;
|
||||
@ -994,9 +994,9 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
|
||||
}
|
||||
|
||||
/* Spinlock until result is ready */
|
||||
if (await && state != CACHE_ENTRY_STATE_LOADED)
|
||||
if (await && state != S_CacheEntryState_Loaded)
|
||||
{
|
||||
while (Atomic32Fetch(&ref.e->state) != CACHE_ENTRY_STATE_LOADED)
|
||||
while (Atomic32Fetch(&ref.e->state) != S_CacheEntryState_Loaded)
|
||||
{
|
||||
IxPause();
|
||||
}
|
||||
@ -1010,18 +1010,18 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
|
||||
|
||||
S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (S_Texture *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 1);
|
||||
return (S_Texture *)S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 1);
|
||||
}
|
||||
|
||||
S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (S_Texture *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0);
|
||||
return (S_Texture *)S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 0);
|
||||
}
|
||||
|
||||
|
||||
void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0);
|
||||
S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@ -1029,17 +1029,17 @@ void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag)
|
||||
|
||||
S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (S_Sheet *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 1);
|
||||
return (S_Sheet *)S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 1);
|
||||
}
|
||||
|
||||
S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
return (S_Sheet *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 0);
|
||||
return (S_Sheet *)S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 0);
|
||||
}
|
||||
|
||||
void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag)
|
||||
{
|
||||
S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 0);
|
||||
S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@ -1157,7 +1157,7 @@ W_CallbackFuncDef(S_WatchSpriteCallback, name)
|
||||
}
|
||||
|
||||
S_Tag tag = S_TagFromPath(name);
|
||||
for (S_CacheEntryKind kind = 0; kind < NUM_CACHE_ENTRY_KINDS; ++kind)
|
||||
for (S_CacheEntryKind kind = 0; kind < S_CacheEntryKind_Count; ++kind)
|
||||
{
|
||||
S_ReloadSpriteFromTag(scope, tag, kind);
|
||||
}
|
||||
@ -1323,7 +1323,7 @@ P_JobDef(S_EvictorJob, _)
|
||||
for (S_EvictorNode *en = first_evicted; en; en = en->next_evicted)
|
||||
{
|
||||
S_CacheEntry *n = en->cache_entry;
|
||||
if (n->kind == CACHE_ENTRY_KIND_TEXTURE && n->texture->valid)
|
||||
if (n->kind == S_CacheEntryKind_Texture && n->texture->valid)
|
||||
{
|
||||
GPU_ReleaseResourceFenced(n->texture->gp_texture);
|
||||
}
|
||||
|
||||
@ -95,18 +95,18 @@ Struct(S_Sheet)
|
||||
|
||||
typedef i32 S_CacheEntryKind; enum
|
||||
{
|
||||
CACHE_ENTRY_KIND_TEXTURE,
|
||||
CACHE_ENTRY_KIND_SHEET,
|
||||
S_CacheEntryKind_Texture,
|
||||
S_CacheEntryKind_Sheet,
|
||||
|
||||
NUM_CACHE_ENTRY_KINDS
|
||||
S_CacheEntryKind_Count
|
||||
};
|
||||
|
||||
typedef i32 S_CacheEntryState; enum
|
||||
{
|
||||
CACHE_ENTRY_STATE_NONE,
|
||||
CACHE_ENTRY_STATE_QUEUED,
|
||||
CACHE_ENTRY_STATE_WORKING,
|
||||
CACHE_ENTRY_STATE_LOADED
|
||||
S_CacheEntryState_None,
|
||||
S_CacheEntryState_Queued,
|
||||
S_CacheEntryState_Working,
|
||||
S_CacheEntryState_Loaded
|
||||
};
|
||||
|
||||
Struct(S_Refcount)
|
||||
@ -214,19 +214,11 @@ Struct(S_EvictorNode)
|
||||
////////////////////////////////
|
||||
//~ Cache constants
|
||||
|
||||
/* The evictor will begin evicting once cache usage is > threshold.
|
||||
* It will entries until the budget has shrunk < target. */
|
||||
#define S_CacheMemoryBudgetThreshold (Mebi(256))
|
||||
#define S_CacheMemoryBudgetTarget (Mebi(128))
|
||||
StaticAssert(S_CacheMemoryBudgetThreshold >= S_CacheMemoryBudgetTarget);
|
||||
|
||||
#define S_CacheBinsCount 1024
|
||||
|
||||
#define S_MaxScopeReferences 1024
|
||||
|
||||
/* Texture arena only used to store texture struct at the moment. Actual image data is allocated on GPU. */
|
||||
#define S_TextureArenaReserve Mebi(1)
|
||||
|
||||
#define S_CacheBinsCount 1024
|
||||
#define S_MaxScopeReferences 1024
|
||||
#define S_SheetArenaReserve Mebi(64)
|
||||
#define S_SheetSpanLookupTableBinRatio 2.0
|
||||
#define S_SliceLookupTableBinRatio 2.0
|
||||
@ -237,6 +229,12 @@ StaticAssert(S_CacheMemoryBudgetThreshold >= S_CacheMemoryBudgetTarget);
|
||||
/* How many cycles a cache entry spends unused until it's considered evictable */
|
||||
#define S_EvictorGracePeriodCycles (NsFromSeconds(10.000) / S_EvictorCycleIntervalNs)
|
||||
|
||||
/* The evictor will begin evicting once cache usage is > threshold.
|
||||
* It will entries until the budget has shrunk < target. */
|
||||
#define S_CacheMemoryBudgetThreshold (Mebi(256))
|
||||
#define S_CacheMemoryBudgetTarget (Mebi(128))
|
||||
StaticAssert(S_CacheMemoryBudgetThreshold >= S_CacheMemoryBudgetTarget);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
|
||||
@ -1,183 +1,7 @@
|
||||
struct bind_state {
|
||||
b32 is_held; /* Is this bind held down this frame */
|
||||
u32 num_presses; /* How many times was this bind's pressed since last frame */
|
||||
u32 num_repeats; /* How many times was this bind's key repeated since last frame */
|
||||
u32 num_presses_and_repeats; /* Same as `num_presses` but includes key repeats as well */
|
||||
u32 num_releases; /* How many times was this bind released since last frame */
|
||||
};
|
||||
|
||||
struct second_stat {
|
||||
u64 last_second_start;
|
||||
u64 last_second_end;
|
||||
u64 last_second;
|
||||
};
|
||||
|
||||
struct console_log {
|
||||
String msg;
|
||||
i32 level;
|
||||
i32 color_index;
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
Rect bounds;
|
||||
struct console_log *prev;
|
||||
struct console_log *next;
|
||||
};
|
||||
|
||||
Global struct {
|
||||
Atomic32 shutdown;
|
||||
P_Counter shutdown_job_counters;
|
||||
P_Window *window;
|
||||
GPU_Swapchain *swapchain;
|
||||
|
||||
struct sim_ctx *local_sim_ctx;
|
||||
|
||||
Arena *arena;
|
||||
String connect_address_str;
|
||||
|
||||
ClientStore *user_client_store;
|
||||
Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
|
||||
/* Usage stats */
|
||||
i64 last_second_reset_ns;
|
||||
struct second_stat net_bytes_read;
|
||||
struct second_stat net_bytes_sent;
|
||||
|
||||
/* Gpu resources */
|
||||
GPU_RenderSig *render_sig;
|
||||
|
||||
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
||||
|
||||
/* Debug camera */
|
||||
EntId debug_following;
|
||||
b32 debug_camera;
|
||||
b32 debug_camera_panning;
|
||||
Vec2 debug_camera_pan_start;
|
||||
b32 debug_draw;
|
||||
|
||||
/* Debug console */
|
||||
P_Mutex console_logs_mutex;
|
||||
Arena *console_logs_arena;
|
||||
struct console_log *first_console_log;
|
||||
struct console_log *last_console_log;
|
||||
i32 console_log_color_indices[P_LogLevel_Count];
|
||||
f32 console_logs_height;
|
||||
b32 debug_console;
|
||||
|
||||
/* Window -> user */
|
||||
P_Mutex sys_window_events_mutex;
|
||||
Arena *sys_window_events_arena;
|
||||
|
||||
/* User -> local sim */
|
||||
P_Mutex user_sim_cmd_mutex;
|
||||
ControlData user_sim_cmd_control;
|
||||
EntId user_hovered_ent;
|
||||
u64 last_user_sim_cmd_gen;
|
||||
u64 user_sim_cmd_gen;
|
||||
|
||||
Atomic32 user_paused;
|
||||
Atomic32 user_paused_steps;
|
||||
|
||||
/* Local sim -> user */
|
||||
P_Mutex local_to_user_client_mutex;
|
||||
ClientStore *local_to_user_client_store;
|
||||
Client *local_to_user_client;
|
||||
i64 local_to_user_client_publish_dt_ns;
|
||||
i64 local_to_user_client_publish_time_ns;
|
||||
|
||||
/* Rolling window of local sim -> user publish time deltas */
|
||||
i64 last_local_to_user_snapshot_published_at_ns;
|
||||
i64 average_local_to_user_snapshot_publish_dt_ns;
|
||||
|
||||
i64 local_sim_predicted_time_ns; /* Calculated from <last local sim to user pubilsh time> + <time since last local sim to user publish> */
|
||||
i64 render_time_target_ns; /* Claculated from <local_sim_rpedicted_time_ns> - <render interp delay> */
|
||||
i64 render_time_ns; /* Incremented at a constant rate based on average local to user publish delta, but snaps to render_time_target_ns if it gets too distant */
|
||||
|
||||
u64 local_sim_last_known_tick;
|
||||
i64 local_sim_last_known_time_ns;
|
||||
|
||||
i64 real_dt_ns;
|
||||
i64 real_time_ns;
|
||||
|
||||
/* Per-frame */
|
||||
|
||||
Vec2 screen_size;
|
||||
Vec2 screen_cursor;
|
||||
|
||||
Xform ui_to_screen_xf;
|
||||
Vec2 ui_size;
|
||||
Vec2 ui_cursor;
|
||||
|
||||
Xform render_to_ui_xf;
|
||||
Vec2 render_size;
|
||||
|
||||
Xform world_to_render_xf;
|
||||
Xform world_to_ui_xf;
|
||||
Vec2 world_cursor;
|
||||
|
||||
Vec2 focus_send;
|
||||
} G = ZI, DebugAlias(G, G_user);
|
||||
|
||||
/* ========================== *
|
||||
* Bind state
|
||||
* ========================== */
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
Global Readonly enum user_bind_kind g_binds[P_Btn_Count] = {
|
||||
[P_Btn_W] = USER_BIND_KIND_MOVE_UP,
|
||||
[P_Btn_S] = USER_BIND_KIND_MOVE_DOWN,
|
||||
[P_Btn_A] = USER_BIND_KIND_MOVE_LEFT,
|
||||
[P_Btn_D] = USER_BIND_KIND_MOVE_RIGHT,
|
||||
//[P_Btn_Alt] = USER_BIND_KIND_WALK,
|
||||
[P_Btn_M1] = USER_BIND_KIND_FIRE,
|
||||
[P_Btn_M2] = USER_BIND_KIND_FIRE_ALT,
|
||||
|
||||
/* Testing */
|
||||
|
||||
[P_Btn_Z] = USER_BIND_KIND_TILE_TEST,
|
||||
|
||||
[P_Btn_M5] = USER_BIND_KIND_DEBUG_DRAG,
|
||||
[P_Btn_M4] = USER_BIND_KIND_DEBUG_DELETE,
|
||||
[P_Btn_F] = USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
[P_Btn_T] = USER_BIND_KIND_DEBUG_TELEPORT,
|
||||
[P_Btn_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[P_Btn_1] = USER_BIND_KIND_DEBUG_SPAWN1,
|
||||
[P_Btn_2] = USER_BIND_KIND_DEBUG_SPAWN2,
|
||||
[P_Btn_3] = USER_BIND_KIND_DEBUG_SPAWN3,
|
||||
[P_Btn_4] = USER_BIND_KIND_DEBUG_SPAWN4,
|
||||
[P_Btn_G] = USER_BIND_KIND_DEBUG_WALLS,
|
||||
[P_Btn_N] = USER_BIND_KIND_DEBUG_STEP,
|
||||
[P_Btn_Q] = USER_BIND_KIND_DEBUG_FOLLOW,
|
||||
[P_Btn_F1] = USER_BIND_KIND_DEBUG_PAUSE,
|
||||
[P_Btn_F2] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||
[P_Btn_F3] = USER_BIND_KIND_DEBUG_DRAW,
|
||||
[P_Btn_F4] = USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST,
|
||||
[P_Btn_GraveAccent] = USER_BIND_KIND_DEBUG_CONSOLE,
|
||||
[P_Btn_Alt] = USER_BIND_KIND_FULLSCREEN_MOD,
|
||||
[P_Btn_Enter] = USER_BIND_KIND_FULLSCREEN,
|
||||
[P_Btn_MWheelUp] = USER_BIND_KIND_ZOOM_IN,
|
||||
[P_Btn_MWheelDown] = USER_BIND_KIND_ZOOM_OUT,
|
||||
[P_Btn_M3] = USER_BIND_KIND_PAN,
|
||||
|
||||
#if RtcIsEnabled
|
||||
/* Debug */
|
||||
[P_Btn_ForwardSlash] = USER_BIND_KIND_RESET_DEBUG_STEPS,
|
||||
[P_Btn_Comma] = USER_BIND_KIND_DECR_DEBUG_STEPS,
|
||||
[P_Btn_Period] = USER_BIND_KIND_INCR_DEBUG_STEPS
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
internal P_ExitFuncDef(user_shutdown);
|
||||
internal P_LogEventCallbackFuncDef(debug_console_log_callback, log);
|
||||
internal P_JobDef(user_update_job, _);
|
||||
internal P_JobDef(local_sim_job , _);
|
||||
|
||||
struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
S_StartupReceipt *sprite_sr,
|
||||
D_StartupReceipt *draw_sr,
|
||||
@ -273,7 +97,7 @@ internal void debug_draw_xform(Xform xf, u32 color_x, u32 color_y)
|
||||
//D_DrawQuad(G.render_sig, quad, color);
|
||||
}
|
||||
|
||||
internal void debug_draw_movement(Ent *ent)
|
||||
internal void debug_draw_movement(Entity *ent)
|
||||
{
|
||||
f32 thickness = 2.f;
|
||||
f32 arrow_len = 15.f;
|
||||
@ -291,7 +115,7 @@ internal void debug_draw_movement(Ent *ent)
|
||||
}
|
||||
}
|
||||
|
||||
internal String get_ent_debug_text(Arena *arena, Ent *ent)
|
||||
internal String get_ent_debug_text(Arena *arena, Entity *ent)
|
||||
{
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
Snapshot *ss = ent->ss;
|
||||
@ -361,7 +185,7 @@ internal String get_ent_debug_text(Arena *arena, Ent *ent)
|
||||
|
||||
/* Children */
|
||||
if (!sim_ent_id_is_nil(ent->first) || !sim_ent_id_is_nil(ent->last)) {
|
||||
Ent *child = sim_ent_from_id(ss, ent->first);
|
||||
Entity *child = sim_ent_from_id(ss, ent->first);
|
||||
if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) {
|
||||
result.len += StringFormat(arena, Lit("first child: [%F]\n"), FmtUid(ent->first.uid)).len;
|
||||
result.len += StringFormat(arena, Lit("last child: [%F]\n"), FmtUid(ent->last.uid)).len;
|
||||
@ -508,8 +332,8 @@ internal void draw_debug_console(i32 level, b32 minimized)
|
||||
|
||||
internal MergesortCompareFuncDef(ent_draw_order_cmp, arg_a, arg_b, _)
|
||||
{
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
Entity *a = *(Entity **)arg_a;
|
||||
Entity *b = *(Entity **)arg_b;
|
||||
|
||||
i32 result = 0;
|
||||
|
||||
@ -740,15 +564,15 @@ internal void user_update(P_Window *window)
|
||||
* Find local entities
|
||||
* ========================== */
|
||||
|
||||
Ent *local_player = sim_ent_from_id(G.ss_blended, G.ss_blended->local_player);
|
||||
Ent *local_control = sim_ent_from_id(G.ss_blended, local_player->player_control_ent);
|
||||
Ent *local_camera = sim_ent_from_id(G.ss_blended, local_player->player_camera_ent);
|
||||
Entity *local_player = sim_ent_from_id(G.ss_blended, G.ss_blended->local_player);
|
||||
Entity *local_control = sim_ent_from_id(G.ss_blended, local_player->player_control_ent);
|
||||
Entity *local_camera = sim_ent_from_id(G.ss_blended, local_player->player_camera_ent);
|
||||
|
||||
/* ========================== *
|
||||
* Find hovered entity
|
||||
* ========================== */
|
||||
|
||||
Ent *hovered_ent = sim_ent_nil();
|
||||
Entity *hovered_ent = sim_ent_nil();
|
||||
{
|
||||
Xform mouse_xf = XformFromPos(G.world_cursor);
|
||||
CLD_Shape mouse_shape = ZI;
|
||||
@ -756,7 +580,7 @@ internal void user_update(P_Window *window)
|
||||
mouse_shape.count = 1;
|
||||
mouse_shape.radius = 0.01f;
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Entity *ent = &G.ss_blended->ents[ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
|
||||
CLD_Shape ent_collider = ent->local_collider;
|
||||
@ -811,11 +635,11 @@ internal void user_update(P_Window *window)
|
||||
}
|
||||
}
|
||||
if (!sim_ent_id_is_nil(G.debug_following)) {
|
||||
Ent *follow_ent = sim_ent_from_id(G.ss_blended, G.debug_following);
|
||||
Ent *follow_camera = sim_ent_nil();
|
||||
Entity *follow_ent = sim_ent_from_id(G.ss_blended, G.debug_following);
|
||||
Entity *follow_camera = sim_ent_nil();
|
||||
for (u64 i = 0; i < G.ss_blended->num_ents_reserved; ++i) {
|
||||
Ent *ent = &G.ss_blended->ents[i];
|
||||
Ent *ent_camera_follow = sim_ent_from_id(G.ss_blended, ent->camera_follow);
|
||||
Entity *ent = &G.ss_blended->ents[i];
|
||||
Entity *ent_camera_follow = sim_ent_from_id(G.ss_blended, ent->camera_follow);
|
||||
if (ent_camera_follow->valid && ent_camera_follow == follow_ent) {
|
||||
follow_camera = ent;
|
||||
break;
|
||||
@ -834,7 +658,7 @@ internal void user_update(P_Window *window)
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Entity *ent = &G.ss_blended->ents[ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
|
||||
/* How much time between camera shakes */
|
||||
@ -1039,7 +863,7 @@ internal void user_update(P_Window *window)
|
||||
/* Alloc entries from new sim chunks */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
Ent *chunk_ent = &G.ss_blended->ents[ent_index];
|
||||
Entity *chunk_ent = &G.ss_blended->ents[ent_index];
|
||||
if (sim_ent_is_valid_and_active(chunk_ent) && sim_ent_has_prop(chunk_ent, SEPROP_TILE_CHUNK)) {
|
||||
struct user_tile_cache_entry *entry = user_tile_cache_entry_from_chunk_pos(chunk_ent->tile_chunk_pos);
|
||||
if (!entry->valid) {
|
||||
@ -1053,7 +877,7 @@ internal void user_update(P_Window *window)
|
||||
for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) {
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(entry->pos);
|
||||
Entity *chunk_ent = sim_ent_from_chunk_pos(entry->pos);
|
||||
if (!chunk_ent->valid) {
|
||||
user_tile_cache_entry_release(entry);
|
||||
}
|
||||
@ -1068,7 +892,7 @@ internal void user_update(P_Window *window)
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
Vec2I32 chunk_pos = entry->pos;
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
Entity *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
|
||||
entry->applied_dirty_gen = chunk_ent->dirty_gen;
|
||||
/* TODO: Autotiling */
|
||||
@ -1092,7 +916,7 @@ internal void user_update(P_Window *window)
|
||||
struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index];
|
||||
if (entry->valid) {
|
||||
Vec2I32 chunk_pos = entry->pos;
|
||||
Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
Entity *chunk_ent = sim_ent_from_chunk_pos(chunk_pos);
|
||||
if (entry->applied_dirty_gen != chunk_ent->dirty_gen) {
|
||||
entry->applied_dirty_gen = chunk_ent->dirty_gen;
|
||||
|
||||
@ -1109,14 +933,14 @@ internal void user_update(P_Window *window)
|
||||
Vec2I32 chunk_pos_bl = VEC2I32(chunk_pos.x - 1, chunk_pos.y + 1);
|
||||
Vec2I32 chunk_pos_b = VEC2I32(chunk_pos.x, chunk_pos.y + 1);
|
||||
Vec2I32 chunk_pos_br = VEC2I32(chunk_pos.x + 1, chunk_pos.y + 1);
|
||||
Ent *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl);
|
||||
Ent *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t);
|
||||
Ent *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr);
|
||||
Ent *chunk_ent_l = sim_ent_from_chunk_pos(chunk_pos_l);
|
||||
Ent *chunk_ent_r = sim_ent_from_chunk_pos(chunk_pos_r);
|
||||
Ent *chunk_ent_bl = sim_ent_from_chunk_pos(chunk_pos_bl);
|
||||
Ent *chunk_ent_b = sim_ent_from_chunk_pos(chunk_pos_b);
|
||||
Ent *chunk_ent_br = sim_ent_from_chunk_pos(chunk_pos_br);
|
||||
Entity *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl);
|
||||
Entity *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t);
|
||||
Entity *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr);
|
||||
Entity *chunk_ent_l = sim_ent_from_chunk_pos(chunk_pos_l);
|
||||
Entity *chunk_ent_r = sim_ent_from_chunk_pos(chunk_pos_r);
|
||||
Entity *chunk_ent_bl = sim_ent_from_chunk_pos(chunk_pos_bl);
|
||||
Entity *chunk_ent_b = sim_ent_from_chunk_pos(chunk_pos_b);
|
||||
Entity *chunk_ent_br = sim_ent_from_chunk_pos(chunk_pos_br);
|
||||
|
||||
String data = sim_ent_get_chunk_tile_data(chunk_ent);
|
||||
|
||||
@ -1131,16 +955,16 @@ internal void user_update(P_Window *window)
|
||||
* Sort drawable entities
|
||||
* ========================== */
|
||||
|
||||
Ent **sorted = PushDry(scratch.arena, Ent *);
|
||||
Entity **sorted = PushDry(scratch.arena, Entity *);
|
||||
u64 sorted_count = 0;
|
||||
{
|
||||
/* Copy valid entities */
|
||||
{
|
||||
__profn("Build ents list for sorting");
|
||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||
Ent *ent = &G.ss_blended->ents[ent_index];
|
||||
Entity *ent = &G.ss_blended->ents[ent_index];
|
||||
if (sim_ent_is_valid_and_active(ent)) {
|
||||
*PushStructNoZero(scratch.arena, Ent *) = ent;
|
||||
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
||||
++sorted_count;
|
||||
}
|
||||
}
|
||||
@ -1159,13 +983,13 @@ internal void user_update(P_Window *window)
|
||||
{
|
||||
__profn("Draw entities");
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
|
||||
Ent *ent = sorted[sorted_index];
|
||||
Entity *ent = sorted[sorted_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
//if (S_IsTagNil(ent->sprite)) continue;
|
||||
|
||||
S_Tag sprite = ent->sprite;
|
||||
|
||||
Ent *parent = sim_ent_from_id(G.ss_blended, ent->parent);
|
||||
Entity *parent = sim_ent_from_id(G.ss_blended, ent->parent);
|
||||
|
||||
Xform xf = sim_ent_get_xform(ent);
|
||||
Xform parent_xf = sim_ent_get_xform(parent);
|
||||
@ -1337,7 +1161,7 @@ internal void user_update(P_Window *window)
|
||||
/* Draw weld joint */
|
||||
#if 0
|
||||
if (sim_ent_has_prop(ent, SEPROP_WELD_JOINT)) {
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, ent->weld_joint_data.e1);
|
||||
Entity *e1 = sim_ent_from_id(G.ss_blended, ent->weld_joint_data.e1);
|
||||
Xform e1_xf = sim_ent_get_xform(e1);
|
||||
|
||||
u32 color = ColorYellow;
|
||||
@ -1352,7 +1176,7 @@ internal void user_update(P_Window *window)
|
||||
|
||||
/* Draw mouse joint */
|
||||
if (sim_ent_has_prop(ent, SEPROP_MOUSE_JOINT)) {
|
||||
Ent *target = sim_ent_from_id(G.ss_blended, ent->mouse_joint_data.target);
|
||||
Entity *target = sim_ent_from_id(G.ss_blended, ent->mouse_joint_data.target);
|
||||
Xform target_xf = sim_ent_get_xform(target);
|
||||
u32 color = ColorWhite;
|
||||
Vec2 point_start = MulXformV2(target_xf, ent->mouse_joint_data.point_local_start);
|
||||
@ -1402,8 +1226,8 @@ internal void user_update(P_Window *window)
|
||||
/* Draw contact constraint */
|
||||
if (sim_ent_has_prop(ent, SEPROP_CONTACT_CONSTRAINT)) {
|
||||
ContactConstraint *data = &ent->contact_constraint_data;
|
||||
Ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
Entity *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Entity *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
(UNUSED)e0;
|
||||
(UNUSED)e1;
|
||||
|
||||
@ -1472,8 +1296,8 @@ internal void user_update(P_Window *window)
|
||||
if (sim_ent_has_prop(ent, SEPROP_COLLISION_DEBUG)) {
|
||||
CollisionDebugData *data = &ent->collision_debug_data;
|
||||
CLD_CollisionData collision_reuslt = data->collision_result;
|
||||
Ent *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Ent *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
Entity *e0 = sim_ent_from_id(G.ss_blended, data->e0);
|
||||
Entity *e1 = sim_ent_from_id(G.ss_blended, data->e1);
|
||||
CLD_Shape e0_collider = e0->local_collider;
|
||||
CLD_Shape e1_collider = e1->local_collider;
|
||||
(UNUSED)e0_collider;
|
||||
@ -1896,7 +1720,7 @@ internal void user_update(P_Window *window)
|
||||
* ========================== */
|
||||
|
||||
if (G.debug_draw && hovered_ent->valid) {
|
||||
Ent *ent = hovered_ent;
|
||||
Entity *ent = hovered_ent;
|
||||
|
||||
Vec2 pos = AddVec2(G.ui_cursor, VEC2(15, 15));
|
||||
F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f);
|
||||
@ -2117,9 +1941,9 @@ internal void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
{
|
||||
Snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
|
||||
Snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, tick);
|
||||
Ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
|
||||
Entity *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
|
||||
/* Find / create local control cmd ent */
|
||||
Ent *control_cmd = sim_ent_find_first_match_one(user_input_ss, SEPROP_CMD);
|
||||
Entity *control_cmd = sim_ent_find_first_match_one(user_input_ss, SEPROP_CMD);
|
||||
if (!control_cmd->valid) {
|
||||
control_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
control_cmd->cmd_kind = SIM_CMD_KIND_CONTROL;
|
||||
@ -2137,7 +1961,7 @@ internal void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
#if 0
|
||||
/* Create chat cmd */
|
||||
if (G.user_sim_cmd_chat.len > 0) {
|
||||
Ent *chat_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
Entity *chat_cmd = sim_ent_alloc_sync_src(user_input_root);
|
||||
chat_cmd->cmd_kind = SIM_CMD_KIND_CHAT;
|
||||
//chat_cmd->chat_msg = ZI
|
||||
}
|
||||
@ -2400,7 +2224,7 @@ internal P_JobDef(local_sim_job, _)
|
||||
|
||||
/* Assume all incoming ents want to be sync srcs */
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
|
||||
Ent *ent = &ss->ents[i];
|
||||
Entity *ent = &ss->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
||||
sim_ent_disable_prop(ent, SEPROP_SYNC_DST);
|
||||
sim_ent_enable_prop(ent, SEPROP_SYNC_SRC);
|
||||
@ -2602,7 +2426,7 @@ internal P_JobDef(local_sim_job, _)
|
||||
}
|
||||
|
||||
if (master_ss->valid) {
|
||||
Ent *master_player = sim_ent_find_first_match_one(master_ss, SEPROP_PLAYER_IS_MASTER);
|
||||
Entity *master_player = sim_ent_find_first_match_one(master_ss, SEPROP_PLAYER_IS_MASTER);
|
||||
|
||||
/* Update ent id from master */
|
||||
{
|
||||
|
||||
@ -48,6 +48,320 @@ enum user_bind_kind {
|
||||
};
|
||||
|
||||
struct user_startup_receipt { i32 _; };
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct bind_state
|
||||
{
|
||||
b32 is_held; /* Is this bind held down this frame */
|
||||
u32 num_presses; /* How many times was this bind's pressed since last frame */
|
||||
u32 num_repeats; /* How many times was this bind's key repeated since last frame */
|
||||
u32 num_presses_and_repeats; /* Same as `num_presses` but includes key repeats as well */
|
||||
u32 num_releases; /* How many times was this bind released since last frame */
|
||||
};
|
||||
|
||||
struct second_stat
|
||||
{
|
||||
u64 last_second_start;
|
||||
u64 last_second_end;
|
||||
u64 last_second;
|
||||
};
|
||||
|
||||
struct console_log
|
||||
{
|
||||
String msg;
|
||||
i32 level;
|
||||
i32 color_index;
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
Rect bounds;
|
||||
struct console_log *prev;
|
||||
struct console_log *next;
|
||||
};
|
||||
|
||||
struct sim_ss_decode_node
|
||||
{
|
||||
Client *client;
|
||||
u64 tick;
|
||||
u64 base_tick;
|
||||
String tmp_encoded;
|
||||
struct sim_ss_decode_node *next;
|
||||
};
|
||||
|
||||
struct sim_decode_queue
|
||||
{
|
||||
struct sim_ss_decode_node *first;
|
||||
struct sim_ss_decode_node *last;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Global struct
|
||||
{
|
||||
Atomic32 shutdown;
|
||||
P_Counter shutdown_job_counters;
|
||||
P_Window *window;
|
||||
GPU_Swapchain *swapchain;
|
||||
|
||||
struct sim_ctx *local_sim_ctx;
|
||||
|
||||
Arena *arena;
|
||||
String connect_address_str;
|
||||
|
||||
ClientStore *user_client_store;
|
||||
Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
|
||||
/* Usage stats */
|
||||
i64 last_second_reset_ns;
|
||||
struct second_stat net_bytes_read;
|
||||
struct second_stat net_bytes_sent;
|
||||
|
||||
/* Gpu resources */
|
||||
GPU_RenderSig *render_sig;
|
||||
|
||||
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
||||
|
||||
/* Debug camera */
|
||||
EntityId debug_following;
|
||||
b32 debug_camera;
|
||||
b32 debug_camera_panning;
|
||||
Vec2 debug_camera_pan_start;
|
||||
b32 debug_draw;
|
||||
|
||||
/* Debug console */
|
||||
P_Mutex console_logs_mutex;
|
||||
Arena *console_logs_arena;
|
||||
struct console_log *first_console_log;
|
||||
struct console_log *last_console_log;
|
||||
i32 console_log_color_indices[P_LogLevel_Count];
|
||||
f32 console_logs_height;
|
||||
b32 debug_console;
|
||||
|
||||
/* Window -> user */
|
||||
P_Mutex sys_window_events_mutex;
|
||||
Arena *sys_window_events_arena;
|
||||
|
||||
/* User -> local sim */
|
||||
P_Mutex user_sim_cmd_mutex;
|
||||
ControlData user_sim_cmd_control;
|
||||
EntityId user_hovered_ent;
|
||||
u64 last_user_sim_cmd_gen;
|
||||
u64 user_sim_cmd_gen;
|
||||
|
||||
Atomic32 user_paused;
|
||||
Atomic32 user_paused_steps;
|
||||
|
||||
/* Local sim -> user */
|
||||
P_Mutex local_to_user_client_mutex;
|
||||
ClientStore *local_to_user_client_store;
|
||||
Client *local_to_user_client;
|
||||
i64 local_to_user_client_publish_dt_ns;
|
||||
i64 local_to_user_client_publish_time_ns;
|
||||
|
||||
/* Rolling window of local sim -> user publish time deltas */
|
||||
i64 last_local_to_user_snapshot_published_at_ns;
|
||||
i64 average_local_to_user_snapshot_publish_dt_ns;
|
||||
|
||||
i64 local_sim_predicted_time_ns; /* Calculated from <last local sim to user pubilsh time> + <time since last local sim to user publish> */
|
||||
i64 render_time_target_ns; /* Claculated from <local_sim_rpedicted_time_ns> - <render interp delay> */
|
||||
i64 render_time_ns; /* Incremented at a constant rate based on average local to user publish delta, but snaps to render_time_target_ns if it gets too distant */
|
||||
|
||||
u64 local_sim_last_known_tick;
|
||||
i64 local_sim_last_known_time_ns;
|
||||
|
||||
i64 real_dt_ns;
|
||||
i64 real_time_ns;
|
||||
|
||||
/* Per-frame */
|
||||
|
||||
Vec2 screen_size;
|
||||
Vec2 screen_cursor;
|
||||
|
||||
Xform ui_to_screen_xf;
|
||||
Vec2 ui_size;
|
||||
Vec2 ui_cursor;
|
||||
|
||||
Xform render_to_ui_xf;
|
||||
Vec2 render_size;
|
||||
|
||||
Xform world_to_render_xf;
|
||||
Xform world_to_ui_xf;
|
||||
Vec2 world_cursor;
|
||||
|
||||
Vec2 focus_send;
|
||||
} G = ZI, DebugAlias(G, G_user);
|
||||
|
||||
/* ========================== *
|
||||
* Bind state
|
||||
* ========================== */
|
||||
|
||||
/* TODO: Remove this */
|
||||
|
||||
Global Readonly enum user_bind_kind g_binds[P_Btn_Count] = {
|
||||
[P_Btn_W] = USER_BIND_KIND_MOVE_UP,
|
||||
[P_Btn_S] = USER_BIND_KIND_MOVE_DOWN,
|
||||
[P_Btn_A] = USER_BIND_KIND_MOVE_LEFT,
|
||||
[P_Btn_D] = USER_BIND_KIND_MOVE_RIGHT,
|
||||
//[P_Btn_Alt] = USER_BIND_KIND_WALK,
|
||||
[P_Btn_M1] = USER_BIND_KIND_FIRE,
|
||||
[P_Btn_M2] = USER_BIND_KIND_FIRE_ALT,
|
||||
|
||||
/* Testing */
|
||||
|
||||
[P_Btn_Z] = USER_BIND_KIND_TILE_TEST,
|
||||
|
||||
[P_Btn_M5] = USER_BIND_KIND_DEBUG_DRAG,
|
||||
[P_Btn_M4] = USER_BIND_KIND_DEBUG_DELETE,
|
||||
[P_Btn_F] = USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
[P_Btn_T] = USER_BIND_KIND_DEBUG_TELEPORT,
|
||||
[P_Btn_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[P_Btn_1] = USER_BIND_KIND_DEBUG_SPAWN1,
|
||||
[P_Btn_2] = USER_BIND_KIND_DEBUG_SPAWN2,
|
||||
[P_Btn_3] = USER_BIND_KIND_DEBUG_SPAWN3,
|
||||
[P_Btn_4] = USER_BIND_KIND_DEBUG_SPAWN4,
|
||||
[P_Btn_G] = USER_BIND_KIND_DEBUG_WALLS,
|
||||
[P_Btn_N] = USER_BIND_KIND_DEBUG_STEP,
|
||||
[P_Btn_Q] = USER_BIND_KIND_DEBUG_FOLLOW,
|
||||
[P_Btn_F1] = USER_BIND_KIND_DEBUG_PAUSE,
|
||||
[P_Btn_F2] = USER_BIND_KIND_DEBUG_CAMERA,
|
||||
[P_Btn_F3] = USER_BIND_KIND_DEBUG_DRAW,
|
||||
[P_Btn_F4] = USER_BIND_KIND_DEBUG_TOGGLE_TOPMOST,
|
||||
[P_Btn_GraveAccent] = USER_BIND_KIND_DEBUG_CONSOLE,
|
||||
[P_Btn_Alt] = USER_BIND_KIND_FULLSCREEN_MOD,
|
||||
[P_Btn_Enter] = USER_BIND_KIND_FULLSCREEN,
|
||||
[P_Btn_MWheelUp] = USER_BIND_KIND_ZOOM_IN,
|
||||
[P_Btn_MWheelDown] = USER_BIND_KIND_ZOOM_OUT,
|
||||
[P_Btn_M3] = USER_BIND_KIND_PAN,
|
||||
|
||||
#if RtcIsEnabled
|
||||
/* Debug */
|
||||
[P_Btn_ForwardSlash] = USER_BIND_KIND_RESET_DEBUG_STEPS,
|
||||
[P_Btn_Comma] = USER_BIND_KIND_DECR_DEBUG_STEPS,
|
||||
[P_Btn_Period] = USER_BIND_KIND_INCR_DEBUG_STEPS
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
S_StartupReceipt *sprite_sr,
|
||||
D_StartupReceipt *draw_sr,
|
||||
@ -55,4 +369,73 @@ struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||
SND_StartupReceipt *sound_sr,
|
||||
MIX_StartupReceipt *mixer_sr,
|
||||
SimStartupReceipt *sim_sr,
|
||||
String connect_address_str);
|
||||
String connect_address_str)
|
||||
|
||||
internal P_ExitFuncDef(user_shutdown)
|
||||
|
||||
/* ========================== *
|
||||
* Debug draw
|
||||
* ========================== */
|
||||
|
||||
/* TODO: remove this (testing) */
|
||||
internal void debug_draw_xform(Xform xf, u32 color_x, u32 color_y)
|
||||
|
||||
internal void debug_draw_movement(Entity *ent)
|
||||
|
||||
internal String get_ent_debug_text(Arena *arena, Entity *ent)
|
||||
|
||||
/* ========================== *
|
||||
* Debug console
|
||||
* ========================== */
|
||||
|
||||
internal P_LogEventCallbackFuncDef(debug_console_log_callback, log)
|
||||
|
||||
internal void draw_debug_console(i32 level, b32 minimized)
|
||||
|
||||
/* ========================== *
|
||||
* Sort entities
|
||||
* ========================== */
|
||||
|
||||
internal MergesortCompareFuncDef(ent_draw_order_cmp, arg_a, arg_b, _)
|
||||
|
||||
/* ========================== *
|
||||
* Update
|
||||
* ========================== */
|
||||
|
||||
internal void user_update(P_Window *window)
|
||||
|
||||
internal P_JobDef(user_update_job, _)
|
||||
|
||||
|
||||
|
||||
|
||||
/* ========================== *
|
||||
* Local sim thread
|
||||
* ========================== */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
internal void generate_user_input_cmds(Client *user_input_client, u64 tick)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
internal P_JobDef(local_sim_job, _)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user