323 lines
8.3 KiB
C
323 lines
8.3 KiB
C
////////////////////////////////////////////////////////////
|
|
//~ Key types
|
|
|
|
Struct(PP_EntKey)
|
|
{
|
|
Uid uid;
|
|
};
|
|
|
|
Struct(PP_ClientKey)
|
|
{
|
|
u32 idx;
|
|
u32 gen;
|
|
};
|
|
|
|
#define PP_NilClientKey ((PP_ClientKey) { .gen = 0, .idx = 0 })
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Client store types
|
|
|
|
Struct(PP_ClientLookupBin)
|
|
{
|
|
PP_ClientKey first;
|
|
PP_ClientKey last;
|
|
};
|
|
|
|
Struct(PP_ClientStore)
|
|
{
|
|
b32 valid;
|
|
Arena *arena;
|
|
|
|
/* Client lookup */
|
|
PP_ClientLookupBin *client_lookup_bins;
|
|
u64 num_client_lookup_bins;
|
|
|
|
/* Clients */
|
|
Arena *clients_arena;
|
|
struct PP_Client *clients;
|
|
PP_ClientKey first_free_client;
|
|
u64 num_clients_allocated;
|
|
u64 num_clients_reserved;
|
|
};
|
|
|
|
Inline PP_ClientStore *PP_NilClientStore(void)
|
|
{
|
|
extern Readonly PP_ClientStore **PP_nil_client_store;
|
|
return *PP_nil_client_store;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Client types
|
|
|
|
Struct(PP_SnapshotLookupBin)
|
|
{
|
|
struct PP_Snapshot *first;
|
|
struct PP_Snapshot *last;
|
|
};
|
|
|
|
Struct(PP_Client)
|
|
{
|
|
b32 valid;
|
|
PP_ClientKey key;
|
|
PP_ClientStore *store;
|
|
|
|
Arena *snapshots_arena;
|
|
|
|
/* Round trip time of the client (if networked) */
|
|
i64 last_rtt_ns;
|
|
|
|
N_ChannelId channel_id;
|
|
u64 channel_hash;
|
|
|
|
PP_ClientKey next_free;
|
|
PP_ClientKey next_in_bin;
|
|
PP_ClientKey prev_in_bin;
|
|
|
|
/* The client's player entity key in the master sim (if relevant) */
|
|
PP_EntKey player_id;
|
|
|
|
/* 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
|
|
// therefore can 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 PP_Snapshot *first_free_snapshot;
|
|
|
|
/* Tick -> snapshot lookup */
|
|
u64 num_snapshot_lookup_bins;
|
|
PP_SnapshotLookupBin *snapshot_lookup_bins;
|
|
};
|
|
|
|
Inline PP_Client *PP_NilClient(void)
|
|
{
|
|
extern Readonly PP_Client **PP_nil_client;
|
|
return *PP_nil_client;
|
|
}
|
|
|
|
Inline b32 PP_EqClientKey(PP_ClientKey a, PP_ClientKey b)
|
|
{
|
|
return a.gen == b.gen && a.idx == b.idx;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Layer types
|
|
|
|
/* Absolute layers */
|
|
#define PP_Layer_FloorDecals (-300)
|
|
#define PP_Layer_Bullets (-200)
|
|
#define PP_Layer_Tracers (-100)
|
|
#define PP_Layer_Shoulders (0)
|
|
#define PP_Layer_Walls (100)
|
|
|
|
/* Relative layers */
|
|
#define PP_Layer_DefaultRelative (0)
|
|
#define PP_Layer_RelativeWeapon (1)
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Control types
|
|
|
|
Enum(PP_ControlFlag)
|
|
{
|
|
PP_ControlFlag_Fire = 1 << 0,
|
|
PP_ControlFlag_AltFire = 1 << 1,
|
|
|
|
/* Testing */
|
|
PP_ControlFlag_Drag = 1 << 2,
|
|
PP_ControlFlag_Delete = 1 << 3,
|
|
PP_ControlFlag_ClearAll = 1 << 4,
|
|
PP_ControlFlag_SpawnTest1 = 1 << 5,
|
|
PP_ControlFlag_SpawnTest2 = 1 << 6,
|
|
PP_ControlFlag_SpawnTest3 = 1 << 7,
|
|
PP_ControlFlag_SpawnTest4 = 1 << 8,
|
|
PP_ControlFlag_TestWalls = 1 << 9,
|
|
PP_ControlFlag_TestTiles = 1 << 10,
|
|
PP_ControlFlag_TestExplode = 1 << 11,
|
|
PP_ControlFlag_TestTeleport = 1 << 12,
|
|
};
|
|
|
|
Struct(PP_ControlData)
|
|
{
|
|
Vec2 move; /* Movement direction vector (speed of 0 -> 1) */
|
|
Vec2 focus; /* Focus direction vector (where does the controller want to look) */
|
|
Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
|
PP_ControlFlag flags;
|
|
};
|
|
|
|
Enum(PP_CmdKind)
|
|
{
|
|
PP_CmdKind_Invalid,
|
|
|
|
PP_CmdKind_Control,
|
|
PP_CmdKind_Chat
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Tile types
|
|
|
|
Enum(PP_TileKind)
|
|
{
|
|
PP_TileKind_None,
|
|
PP_TileKind_Wall,
|
|
|
|
PP_TileKind_Count
|
|
};
|
|
StaticAssert(PP_TileKind_Count < 256); /* Tile kind must fit in 8 bits */
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot types
|
|
|
|
Enum(PP_SyncFlag)
|
|
{
|
|
PP_SyncFlag_NoSyncPredictables = 1 << 0
|
|
};
|
|
|
|
Struct(PP_Snapshot)
|
|
{
|
|
b32 valid;
|
|
u64 tick;
|
|
PP_Client *client;
|
|
PP_Snapshot *next_free;
|
|
PP_Snapshot *next_in_bin;
|
|
PP_Snapshot *prev_in_bin;
|
|
u64 prev_tick;
|
|
u64 next_tick;
|
|
|
|
Arena *arena;
|
|
|
|
/* 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;
|
|
|
|
/* The key of the receiver's player in the snapshot */
|
|
PP_EntKey local_player;
|
|
|
|
/* Key lookup */
|
|
struct PP_EntBin *key_bins;
|
|
u64 num_key_bins;
|
|
|
|
/* Ents */
|
|
Arena *ents_arena;
|
|
struct PP_Ent *ents;
|
|
u32 first_free_ent;
|
|
u32 num_ents_allocated;
|
|
u32 num_ents_reserved;
|
|
};
|
|
|
|
Inline PP_Snapshot *PP_NilSnapshot(void)
|
|
{
|
|
extern Readonly PP_Snapshot **PP_nil_snapshot;
|
|
return *PP_nil_snapshot;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ State types
|
|
|
|
#define PP_ClientLookupBinsCount 127
|
|
#define PP_TickLookupBinsCount 127
|
|
#define PP_KeyLookupBinsCount 4096
|
|
|
|
Struct(PP_SharedSimCtx)
|
|
{
|
|
Arena *nil_arena;
|
|
PP_ClientStore *nil_client_store;
|
|
PP_Client *nil_client;
|
|
PP_Snapshot *nil_snapshot;
|
|
struct PP_Ent *nil_ent;
|
|
} extern PP_shared_sim_ctx;
|
|
|
|
/* Accessed via `PP_NilClientStore()` */
|
|
extern Readonly PP_ClientStore **PP_nil_client_store;
|
|
|
|
/* Accessed via `PP_NilClient()` */
|
|
extern Readonly PP_Client **PP_nil_client;
|
|
|
|
/* Accessed via `NilSnapshot()` */
|
|
extern Readonly PP_Snapshot **PP_nil_snapshot;
|
|
extern Readonly struct PP_Ent **PP_nil_ent;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Startup
|
|
|
|
void PP_StartupSim(void);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Client store acquire operations
|
|
|
|
PP_ClientStore *PP_AcquireClientStore(void);
|
|
void PP_ReleaseClientStore(PP_ClientStore *store);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Client acquire operations
|
|
|
|
PP_Client *PP_AcquireClient(PP_ClientStore *store);
|
|
void PP_ReleaseClient(PP_Client *client);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Client lookup operations
|
|
|
|
u64 PP_ClientChannelHashFromChannelId(N_ChannelId channel_id);
|
|
void PP_SetClientChannelId(PP_Client *client, N_ChannelId channel_id);
|
|
PP_Client *PP_ClientFromChannelId(PP_ClientStore *store, N_ChannelId channel_id);
|
|
PP_Client *PP_ClientFromKey(PP_ClientStore *store, PP_ClientKey key);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot acquire operations
|
|
|
|
PP_Snapshot *PP_AcquireSnapshot(PP_Client *client, PP_Snapshot *src, u64 tick);
|
|
void PP_ReleaseSnapshot(PP_Snapshot *ss);
|
|
void PP_ReleaseSnapshotsInRange(PP_Client *client, u64 start, u64 end);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot lookup operations
|
|
|
|
PP_Snapshot *PP_SnapshotFromTick(PP_Client *client, u64 tick);
|
|
PP_Snapshot *PP_SnapshotFromClosestTickLte(PP_Client *client, u64 tick);
|
|
PP_Snapshot *PP_SnapshotFromClosestTickGte(PP_Client *client, u64 tick);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Tile operations
|
|
|
|
Vec2I32 PP_WorldTileIndexFromPos(Vec2 pos);
|
|
Vec2 PP_PosFromWorldTileIndex(Vec2I32 world_tile_index);
|
|
Vec2I32 PP_LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
|
Vec2I32 PP_WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local_tile_index);
|
|
Vec2I32 PP_TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
|
void PP_SetSnapshotTile(PP_Snapshot *ss, Vec2I32 world_tile_index, PP_TileKind tile_kind);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot lerp operations
|
|
|
|
PP_Snapshot *PP_AcquireSnapshotFromLerp(PP_Client *client, PP_Snapshot *ss0, PP_Snapshot *ss1, f64 blend);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot sync operations
|
|
|
|
void PP_SyncSnapshotEnts(PP_Snapshot *local_ss, PP_Snapshot *remote_ss, PP_EntKey remote_player, u32 sync_flags);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot encode operations
|
|
|
|
void PP_EncodeSnapshot(BB_Writer *bw, PP_Client *receiver, PP_Snapshot *ss0, PP_Snapshot *ss1);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Snapshot decode operations
|
|
|
|
void PP_DecodeSnapshot(BB_Reader *br, PP_Snapshot *ss);
|