225 lines
6.4 KiB
C
225 lines
6.4 KiB
C
#ifndef SIM_H
|
|
#define SIM_H
|
|
|
|
#define SIM_CLIENT_NIL_HANDLE ((struct sim_client_handle) { .gen = 0, .idx = 0 })
|
|
|
|
/* UID magic number bases (to be used in conjunction with random UIDs in deterministic UID combinations) */
|
|
#define SIM_ENT_BASIS_UID_CONTACT (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
|
|
|
|
/* Absolute layers */
|
|
#define SIM_LAYER_FLOOR_DECALS (-300)
|
|
#define SIM_LAYER_BULLETS (-200)
|
|
#define SIM_LAYER_TRACERS (-100)
|
|
#define SIM_LAYER_SHOULDERS (0)
|
|
|
|
/* Relative layers */
|
|
#define SIM_LAYER_RELATIVE_DEFAULT (0)
|
|
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
|
|
|
/* ========================== *
|
|
* Startup
|
|
* ========================== */
|
|
|
|
struct sim_startup_receipt { i32 _; };
|
|
struct sim_startup_receipt sim_startup(void);
|
|
|
|
/* ========================== *
|
|
* Client store
|
|
* ========================== */
|
|
|
|
struct sim_client_lookup_bucket {
|
|
struct sim_client_handle first;
|
|
struct sim_client_handle last;
|
|
};
|
|
|
|
struct sim_client_store {
|
|
b32 valid;
|
|
struct arena arena;
|
|
|
|
/* Client lookup */
|
|
struct sim_client_lookup_bucket *client_lookup_buckets;
|
|
u64 num_client_lookup_buckets;
|
|
|
|
/* Clients */
|
|
struct arena clients_arena;
|
|
struct sim_client *clients;
|
|
struct sim_client_handle first_free_client;
|
|
u64 num_clients_allocated;
|
|
u64 num_clients_reserved;
|
|
};
|
|
|
|
INLINE struct sim_client_store *sim_client_store_nil(void)
|
|
{
|
|
extern READONLY struct sim_client_store **_g_sim_client_store_nil;
|
|
return *_g_sim_client_store_nil;
|
|
}
|
|
|
|
struct sim_client_store *sim_client_store_alloc(void);
|
|
void sim_client_store_release(struct sim_client_store *store);
|
|
|
|
/* ========================== *
|
|
* Client
|
|
* ========================== */
|
|
|
|
struct sim_snapshot;
|
|
|
|
struct sim_snapshot_lookup_bucket {
|
|
struct sim_snapshot *first;
|
|
struct sim_snapshot *last;
|
|
};
|
|
|
|
struct sim_client {
|
|
b32 valid;
|
|
struct sim_client_handle handle;
|
|
struct sim_client_store *store;
|
|
|
|
struct arena snapshots_arena;
|
|
|
|
struct host_channel_id channel_id;
|
|
u64 channel_hash;
|
|
|
|
struct sim_client_handle next_free;
|
|
struct sim_client_handle next_in_bucket;
|
|
struct sim_client_handle prev_in_bucket;
|
|
|
|
/* The client entity's uid in the master sim (if relevant) */
|
|
struct uid ent_uid;
|
|
|
|
/* This is the highest confirmed tick of ours that we know this client has received */
|
|
u64 ack;
|
|
|
|
/* This is the highest confirmed ack of ours that we know this client has received (this
|
|
* can be used to determine which client ticks will no longer be delta encoded from and
|
|
* can therefore be released) */
|
|
u64 double_ack;
|
|
|
|
/* This is the highest tick of their's that we have received */
|
|
u64 highest_received_tick;
|
|
|
|
/* Snapshots sorted by tick (low to high) */
|
|
u64 first_tick;
|
|
u64 last_tick;
|
|
u64 num_ticks;
|
|
struct sim_snapshot *first_free_snapshot;
|
|
|
|
/* Tick -> snapshot lookup */
|
|
u64 num_snapshot_lookup_buckets;
|
|
struct sim_snapshot_lookup_bucket *snapshot_lookup_buckets;
|
|
};
|
|
|
|
INLINE struct sim_client *sim_client_nil(void)
|
|
{
|
|
extern READONLY struct sim_client **_g_sim_client_nil;
|
|
return *_g_sim_client_nil;
|
|
}
|
|
|
|
INLINE b32 sim_client_handle_eq(struct sim_client_handle a, struct sim_client_handle b)
|
|
{
|
|
return a.gen == b.gen && a.idx == b.idx;
|
|
}
|
|
|
|
struct sim_client *sim_client_alloc(struct sim_client_store *store);
|
|
void sim_client_release(struct sim_client *client);
|
|
|
|
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id);
|
|
void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id channel_id);
|
|
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
|
|
|
/* ========================== *
|
|
* Snapshot
|
|
* ========================== */
|
|
|
|
enum sim_control_flag {
|
|
SIM_CONTROL_FLAG_FIRE = 1 << 0,
|
|
|
|
/* Testing */
|
|
SIM_CONTROL_FLAG_DRAG = 1 << 1,
|
|
SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 2,
|
|
SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 3,
|
|
SIM_CONTROL_FLAG_PAUSE = 1 << 4,
|
|
SIM_CONTROL_FLAG_STEP = 1 << 5
|
|
};
|
|
|
|
struct sim_control {
|
|
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
|
|
struct v2 focus; /* Focus direction vector (where does the controller want to look) */
|
|
u32 flags;
|
|
};
|
|
|
|
struct sim_ent_bucket;
|
|
|
|
struct sim_snapshot {
|
|
b32 valid;
|
|
u64 tick;
|
|
struct sim_client *client;
|
|
struct sim_snapshot *next_free;
|
|
struct sim_snapshot *next_in_bucket;
|
|
struct sim_snapshot *prev_in_bucket;
|
|
u64 prev_tick;
|
|
u64 next_tick;
|
|
|
|
struct arena arena;
|
|
|
|
/* Program time of local snapshot publish to user thread (if relevant) */
|
|
i64 publish_dt_ns;
|
|
i64 publish_time_ns;
|
|
|
|
/* Sim time (guaranteed to increase by sim_dt_ns each step) */
|
|
i64 sim_dt_ns;
|
|
i64 sim_time_ns;
|
|
|
|
/* If != previous tick's continuity then don't lerp */
|
|
u64 continuity_gen;
|
|
|
|
/* The last physics iteration (used for tracking contact lifetime) */
|
|
u64 phys_iteration;
|
|
|
|
struct uid local_client_ent_uid; /* The uid of the receiver's client ent */
|
|
|
|
/* Uid lookup */
|
|
struct sim_ent_bucket *uid_buckets;
|
|
u64 num_uid_buckets;
|
|
|
|
/* Entities */
|
|
struct arena ents_arena;
|
|
struct sim_ent *ents;
|
|
struct sim_ent_handle first_free_ent;
|
|
u64 num_ents_allocated;
|
|
u64 num_ents_reserved;
|
|
};
|
|
|
|
INLINE struct sim_snapshot *sim_snapshot_nil(void)
|
|
{
|
|
extern READONLY struct sim_snapshot **_g_sim_snapshot_nil;
|
|
return *_g_sim_snapshot_nil;
|
|
}
|
|
|
|
struct bitbuff_writer;
|
|
struct bitbuff_reader;
|
|
|
|
/* Alloc */
|
|
struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_snapshot *src, u64 tick);
|
|
void sim_snapshot_release(struct sim_snapshot *sim_snapshot);
|
|
void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u64 end);
|
|
|
|
/* Lookup */
|
|
struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick);
|
|
struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick);
|
|
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
|
|
|
|
/* Lerp */
|
|
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
|
|
|
/* Encode / decode */
|
|
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
|
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|