553 lines
9.9 KiB
C
553 lines
9.9 KiB
C
#define P_MaxFrameSnapshotFragments Kibi(4)
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Key types
|
|
|
|
#define P_NilKey ((P_Key) { 0 })
|
|
|
|
Struct(P_Key)
|
|
{
|
|
u64 v;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Shape types
|
|
|
|
Struct(P_ShapeDesc)
|
|
{
|
|
f32 radius;
|
|
f32 mass;
|
|
i32 count;
|
|
Vec2 points[8];
|
|
};
|
|
|
|
Struct(P_Shape)
|
|
{
|
|
f32 mass;
|
|
Vec2 centroid;
|
|
Vec2 center_of_mass;
|
|
|
|
f32 radius;
|
|
i32 points_count;
|
|
Vec2 points[8];
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Debug visualization types
|
|
|
|
Enum(P_DebugDrawKind)
|
|
{
|
|
P_DebugDrawKind_Point,
|
|
P_DebugDrawKind_Line,
|
|
P_DebugDrawKind_Rect,
|
|
P_DebugDrawKind_Shape,
|
|
};
|
|
|
|
Struct(P_DebugDrawNode)
|
|
{
|
|
P_DebugDrawNode *next;
|
|
P_DebugDrawKind kind;
|
|
u32 srgb32;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
Vec2 p;
|
|
} point;
|
|
struct
|
|
{
|
|
Vec2 p0;
|
|
Vec2 p1;
|
|
} line;
|
|
Rng2 rect;
|
|
P_Shape shape;
|
|
};
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Ent types
|
|
|
|
// TODO: Move boolean fields into bitwise property flags
|
|
|
|
// TODO: Pack efficiently, deduplicate redundant fields
|
|
|
|
#define P_MinPlayerNameLen 1
|
|
#define P_MaxPlayerNameLen 24
|
|
|
|
Struct(P_Control)
|
|
{
|
|
i64 tick;
|
|
i64 orig_tick; // Will differ from tick if this control was propagated from the control of another tick
|
|
|
|
// TODO: Move this to client-only code
|
|
i64 produced_at_ns;
|
|
|
|
Vec2 move;
|
|
Vec2 look;
|
|
f32 fire_held;
|
|
f32 fire_presses;
|
|
};
|
|
|
|
Struct(P_Ent)
|
|
{
|
|
//- Internal world state
|
|
|
|
P_Ent *next;
|
|
P_Ent *prev;
|
|
|
|
P_Ent *next_in_bin;
|
|
P_Ent *prev_in_bin;
|
|
|
|
//- Persistent data
|
|
|
|
P_Key key;
|
|
u64 rand_seq;
|
|
i64 created_at_ns;
|
|
|
|
//- Build data
|
|
|
|
f32 exists;
|
|
|
|
b32 is_guy;
|
|
b32 is_dummy;
|
|
f32 health;
|
|
|
|
Xform prev_xf;
|
|
Xform xf;
|
|
|
|
// TODO: Remove this (weapon testing)
|
|
i64 last_fire_ns;
|
|
b32 has_weapon;
|
|
|
|
P_Key bullet_firer;
|
|
b32 is_bullet;
|
|
Vec2 bullet_start;
|
|
Vec2 bullet_end;
|
|
|
|
b32 has_hit;
|
|
Vec2 hit_entry;
|
|
Vec2 hit_entry_normal;
|
|
|
|
//- Player / Guy
|
|
|
|
P_Control control;
|
|
|
|
//- Player
|
|
|
|
b32 is_player;
|
|
P_Key guy;
|
|
|
|
f32 ping;
|
|
u8 string_len;
|
|
u8 string_text[P_MaxPlayerNameLen + 8];
|
|
|
|
//- Solver
|
|
|
|
Vec2 solved_v;
|
|
f32 solved_w;
|
|
};
|
|
|
|
Struct(P_EntListNode)
|
|
{
|
|
P_EntListNode *next;
|
|
P_Ent ent;
|
|
};
|
|
|
|
Struct(P_EntList)
|
|
{
|
|
P_EntListNode *first;
|
|
P_EntListNode *last;
|
|
i64 count;
|
|
};
|
|
|
|
Struct(P_EntBin)
|
|
{
|
|
P_Ent *first;
|
|
P_Ent *last;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Animation types
|
|
|
|
Struct(P_Anim)
|
|
{
|
|
i64 frame_seq;
|
|
SPR_SpanKey span;
|
|
SPR_SheetKey sheet;
|
|
SPR_SheetKey wep_sheet;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Constraint types
|
|
|
|
Enum(P_ConstraintFlag)
|
|
{
|
|
P_ConstraintFlag_None = 0,
|
|
P_ConstraintFlag_Solid = (1 << 0),
|
|
P_ConstraintFlag_Gentle = (1 << 1),
|
|
P_ConstraintFlag_NoWarmStart = (1 << 2),
|
|
};
|
|
|
|
Struct(P_ContactPoint)
|
|
{
|
|
Vec2 vcp0;
|
|
Vec2 vcp1;
|
|
f32 starting_separation;
|
|
f32 inv_normal_mass;
|
|
f32 inv_tangent_mass;
|
|
u32 id;
|
|
|
|
f32 solved_normal_impulse;
|
|
f32 solved_tangent_impulse;
|
|
};
|
|
|
|
Struct(P_Constraint)
|
|
{
|
|
P_ConstraintFlag flags;
|
|
|
|
i64 last_touched_tick;
|
|
P_Key ent0;
|
|
P_Key ent1;
|
|
|
|
Vec2 static_center0;
|
|
Vec2 static_center1;
|
|
|
|
f32 inv_m0;
|
|
f32 inv_m1;
|
|
f32 inv_i0;
|
|
f32 inv_i1;
|
|
|
|
Vec2 normal;
|
|
f32 friction;
|
|
|
|
i32 points_count;
|
|
P_ContactPoint points[2];
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ World types
|
|
|
|
Struct(P_Frame)
|
|
{
|
|
//////////////////////////////
|
|
//- Internal world state
|
|
|
|
struct P_World *world;
|
|
|
|
P_Frame *next;
|
|
P_Frame *prev;
|
|
|
|
P_Frame *next_in_bin;
|
|
P_Frame *prev_in_bin;
|
|
|
|
//////////////////////////////
|
|
//- Frame state
|
|
|
|
i64 tick;
|
|
i64 time_ns;
|
|
|
|
i64 ents_count;
|
|
P_Ent *first_ent;
|
|
P_Ent *last_ent;
|
|
|
|
i64 ent_bins_count;
|
|
P_EntBin *ent_bins;
|
|
|
|
i64 constraints_cap;
|
|
i64 constraints_count;
|
|
P_Constraint *constraints;
|
|
|
|
//////////////////////////////
|
|
//- Snapshot-assembly state
|
|
|
|
u64 fragments_count;
|
|
u64 received_fragments_count;
|
|
u64 received_fragment_bits[(P_MaxFrameSnapshotFragments + 63) / 64];
|
|
};
|
|
|
|
Struct(P_FrameBin)
|
|
{
|
|
P_Frame *first;
|
|
P_Frame *last;
|
|
};
|
|
|
|
Struct(P_World)
|
|
{
|
|
Arena *arena;
|
|
Arena *frames_arena;
|
|
Arena *statics_arena;
|
|
|
|
u64 seed;
|
|
RandState rand;
|
|
|
|
P_Ent *first_free_ent;
|
|
|
|
P_Frame *first_frame;
|
|
P_Frame *last_frame;
|
|
P_Frame *first_free_frame;
|
|
i64 frame_bins_count;
|
|
P_FrameBin *frame_bins;
|
|
|
|
u64 tiles_hash;
|
|
u8 *tiles;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Message types
|
|
|
|
Enum(P_MsgKind)
|
|
{
|
|
P_MsgKind_None,
|
|
P_MsgKind_Raw,
|
|
|
|
// Server <-> Client
|
|
P_MsgKind_Chat,
|
|
P_MsgKind_Connect,
|
|
|
|
// Client -> Server
|
|
P_MsgKind_SaveWorld,
|
|
P_MsgKind_ResetWorld,
|
|
P_MsgKind_TileEdit,
|
|
P_MsgKind_EntEdit,
|
|
P_MsgKind_Delete,
|
|
|
|
// Server -> Client
|
|
P_MsgKind_Tiles,
|
|
};
|
|
|
|
Struct(P_Msg)
|
|
{
|
|
P_MsgKind kind;
|
|
NET_Key src;
|
|
NET_Key dst;
|
|
|
|
b32 affect_dummies;
|
|
|
|
P_TileKind tile_kind;
|
|
Rng2I32 tile_range;
|
|
u64 tiles_hash;
|
|
|
|
P_Key key;
|
|
Xform xf;
|
|
|
|
String data;
|
|
};
|
|
|
|
Struct(P_MsgNode)
|
|
{
|
|
P_MsgNode *next;
|
|
P_MsgNode *prev;
|
|
P_Msg msg;
|
|
};
|
|
|
|
Struct(P_MsgList)
|
|
{
|
|
P_MsgNode *first;
|
|
P_MsgNode *last;
|
|
i64 count;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Collision types
|
|
|
|
Struct(P_SupportPoint)
|
|
{
|
|
Vec2 p;
|
|
u32 id; // Index of the originating piont in the shape
|
|
};
|
|
|
|
Struct(P_CollisionPoint)
|
|
{
|
|
Vec2 p;
|
|
f32 separation;
|
|
u32 id; // Based on polygon edge-to-edge
|
|
};
|
|
|
|
Struct(P_MenkowskiPoint)
|
|
{
|
|
Vec2 p; // Menkowski difference point
|
|
P_SupportPoint s0; // Support point of first shape in dir
|
|
P_SupportPoint s1; // Support point of second shape in -dir
|
|
};
|
|
|
|
Struct(P_MenkowskiSimplex)
|
|
{
|
|
i32 count;
|
|
P_MenkowskiPoint a, b, c;
|
|
};
|
|
|
|
Struct(P_ClippedLine)
|
|
{
|
|
Vec2 a0_clipped, b0_clipped;
|
|
Vec2 a1_clipped, b1_clipped;
|
|
};
|
|
|
|
Struct(P_CollisionResult)
|
|
{
|
|
// Collision manifold
|
|
i32 collision_points_count;
|
|
P_CollisionPoint collision_points[2];
|
|
Vec2 collision_normal;
|
|
|
|
// Closest points
|
|
Vec2 closest_p0;
|
|
Vec2 closest_p1;
|
|
};
|
|
|
|
Struct(P_RaycastResult)
|
|
{
|
|
b32 is_intersecting;
|
|
Vec2 p;
|
|
Vec2 normal;
|
|
};
|
|
////////////////////////////////////////////////////////////
|
|
//~ State types
|
|
|
|
Struct(P_Ctx)
|
|
{
|
|
// Sim -> Vis state
|
|
TicketMutex s2v_tm;
|
|
struct
|
|
{
|
|
i64 gen;
|
|
Arena *arena;
|
|
i64 debug_draw_nodes_count;
|
|
P_DebugDrawNode *first_debug_draw_node;
|
|
P_DebugDrawNode *last_debug_draw_node;
|
|
|
|
NET_PipeStatistics pipe_stats;
|
|
} s2v;
|
|
};
|
|
|
|
Struct(P_ThreadLocalCtx)
|
|
{
|
|
b32 is_predicting;
|
|
P_Key local_player;
|
|
|
|
//- Per-thread debug info
|
|
Arena *debug_arena;
|
|
b32 debug_draw_enabled;
|
|
Vec4 debug_tint;
|
|
P_DebugDrawNode *first_debug_draw_node;
|
|
P_DebugDrawNode *last_debug_draw_node;
|
|
i64 debug_draw_nodes_count;
|
|
|
|
//- Per-thread outbound messages
|
|
Arena *out_msgs_arena;
|
|
P_MsgList out_msgs;
|
|
};
|
|
|
|
extern P_Ctx P;
|
|
extern ThreadLocal P_ThreadLocalCtx P_tl;
|
|
|
|
extern Readonly P_Ent P_NilEnt;
|
|
extern Readonly P_Frame P_NilFrame;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Bootstrap
|
|
|
|
void P_Bootstrap(void);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Nil helpers
|
|
|
|
b32 P_IsKeyNil(P_Key key);
|
|
b32 P_IsEntNil(P_Ent *ent);
|
|
b32 P_IsFrameNil(P_Frame *frame);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Key helpers
|
|
|
|
b32 P_MatchKey(P_Key a, P_Key b);
|
|
P_Key P_RandKey(void);
|
|
u64 P_RandU64FromEnt(P_Ent *ent);
|
|
|
|
#define P_FmtKey(key) FmtHandle((key).v)
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ String helpers
|
|
|
|
String P_StringFromEnt(P_Ent *ent);
|
|
void P_SetEntString(P_Ent *ent, String str);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Tile helpers
|
|
|
|
String P_NameFromTileKind(P_TileKind kind);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Shape helpers
|
|
|
|
P_Shape P_ShapeFromDescEx(P_ShapeDesc desc);
|
|
#define P_ShapeFromDesc(...) P_ShapeFromDescEx((P_ShapeDesc) { __VA_ARGS__ })
|
|
|
|
P_Shape P_MulXformShape(Xform xf, P_Shape shape);
|
|
Rng2 P_BoundingBoxFromShape(P_Shape shape);
|
|
|
|
P_Shape P_LocalShapeFromEnt(P_Ent *ent);
|
|
P_Shape P_WorldShapeFromEnt(P_Ent *ent);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Animation helpers
|
|
|
|
P_Anim P_AnimFromEnt(P_Ent *ent, i64 time_ns);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Collision
|
|
|
|
P_SupportPoint P_SupportPointFromShapeEx(P_Shape shape, Vec2 dir, i32 ignore_idx);
|
|
P_SupportPoint P_SupportPointFromShape(P_Shape shape, Vec2 dir);
|
|
P_MenkowskiPoint P_MenkowskiPointFromShapes(P_Shape shape0, P_Shape shape1, Vec2 dir);
|
|
P_ClippedLine P_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal);
|
|
Vec2 P_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal);
|
|
|
|
P_CollisionResult P_CollisionResultFromShapes(P_Shape shape0, P_Shape shape1);
|
|
P_RaycastResult P_RaycastShape(P_Shape shape, Vec2 ray_start, Vec2 ray_dir);
|
|
|
|
Vec2 P_EdgePointFromShape(P_Shape shape, Vec2 dir);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Lookup helpers
|
|
|
|
P_Ent *P_EntFromKey(P_Frame *frame, P_Key key);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Iteration helpers
|
|
|
|
P_Ent *P_FirstEnt(P_Frame *frame);
|
|
P_Ent *P_NextEnt(P_Ent *e);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ List helpers
|
|
|
|
P_Ent *P_PushTempEnt(Arena *arena, P_EntList *list);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Debug draw
|
|
|
|
void P_DebugDrawPoint(Vec2 p, Vec4 srgb);
|
|
void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
|
|
void P_DebugDrawRect(Rng2 rect, Vec4 srgb);
|
|
void P_DebugDrawShape(P_Shape shape, Vec4 srgb);
|
|
void P_DebugDrawFrame(P_Frame *frame);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Msg
|
|
|
|
P_Msg *P_PushMsg(P_MsgKind kind, String data);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ World
|
|
|
|
P_World *P_AcquireWorld(void);
|
|
void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents);
|
|
|
|
P_Frame *P_FrameFromTick(P_World *world, i64 tick);
|
|
void P_ClearFrames(P_World *world, i64 tick_min, i64 tick_max);
|
|
P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick);
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Step
|
|
|
|
void P_StepFrame(P_Frame *frame);
|