//////////////////////////////////////////////////////////// //~ Ent props Enum(PP_Prop) { PP_Prop_Active, PP_Prop_Release, PP_Prop_SyncSrc, /* This entity is networked to other clients */ PP_Prop_SyncDst, /* This entity is not locally created, and will sync with incoming net src ents */ PP_Prop_Player, PP_Prop_IsMaster, PP_Prop_Cmd, PP_Prop_TileChunk, PP_Prop_Wall, /* Physics collision */ PP_Prop_Sensor, /* This entity's collisions generate contacts */ PP_Prop_Solid, /* This entity's collisions generate contacts to be solved by the physics system (overrides PP_Prop_Sensor) */ PP_Prop_Toi, /* This entity's collisions are processed using TOI (time of impact) for precise collisions */ /* Physics movement */ PP_Prop_Kinematic, /* This entity reacts to velocity */ PP_Prop_Dynamic, /* This entity reacts to velocity and forces (overrides PP_Prop_Kinematic) */ PP_Prop_Controlled, PP_Prop_CollisionDebug, PP_Prop_ContactConstraint, PP_Prop_MotorJoint, PP_Prop_MouseJoint, PP_Prop_WeldJoint, PP_Prop_Camera, PP_Prop_ActiveCamera, PP_Prop_Bullet, PP_Prop_Smg, PP_Prop_Launcher, PP_Prop_Chucker, PP_Prop_ChuckerZone, PP_Prop_Explosion, PP_Prop_Tracer, PP_Prop_Quake, PP_Prop_Attached, /* Test props */ PP_Prop_Test, PP_Prop_SoundEmitterTest, PP_Prop_LightTest, PP_Prop_Count }; //////////////////////////////////////////////////////////// //~ Ent Struct(PP_Ent) { PP_Snapshot *ss; //- Metadata b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */ PP_EntKey key; u64 props[(PP_Prop_Count + 63) / 64]; u64 continuity_gen; /* Is this the root ent */ b32 is_root; /* Is ent a child of the root ent */ b32 is_top; /* The key of the top level parent of the ent tree (if ent is top then this point to itself) */ PP_EntKey top; /* Tree */ PP_EntKey parent; PP_EntKey next; PP_EntKey prev; PP_EntKey first; PP_EntKey last; /* Lists keyed by index in snapshot ent array */ u32 next_in_id_bin; u32 prev_in_id_bin; u32 next_free; //- Sync /* PP_Prop_SyncSrc */ /* PP_Prop_SyncDst */ /* Key of the player that owns simulation for this entity */ PP_EntKey owner; /* Key of the player that should predict simulation of this this entity locally */ PP_EntKey predictor; //- Position /* Use xform getters & setters to access. */ Xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */ Xform _xform; /* Calculated from ent tree */ b32 _is_xform_dirty; //- Activation /* If 0, the ent will auto activate at start of next tick if not already active. */ u64 activation_tick; //- Layer i32 layer; i32 final_layer; /* Calculated each tick from ent tree */ //- Cmd /* PP_Prop_Cmd */ PP_CmdKind cmd_kind; PP_EntKey cmd_player; /* FIXME: Lerp */ /* Control cmd */ PP_ControlData cmd_control; PP_EntKey cmd_control_hovered_ent; /* Chat cmd */ //String cmd_chat_msg; //- Chat /* PP_Prop_Chat */ PP_EntKey chat_player; //String chat_msg; //- Tile /* PP_Prop_TileChunk */ /* FIXME: Move out of here */ u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT]; Vec2I32 tile_chunk_index; //- Client /* PP_Prop_Player */ /* FIXME: Lerp */ PP_ClientKey player_client_key; /* The client key on the master sim's machine */ PP_ControlData player_control; Vec2 player_cursor_pos; PP_EntKey player_hovered_ent; PP_EntKey player_control_ent; PP_EntKey player_camera_ent; PP_EntKey player_dbg_drag_joint_ent; b32 player_dbg_drag_start; b32 player_dbg_drag_stop; /* Client round-trip-time to server */ i64 player_last_rtt_ns; f64 player_average_rtt_seconds; //- Collider Vec2 collision_dir; /* If set, then only collisions coming from this direction will generate contacts (used for walls to prevent ghost collisions) */ CLD_Shape local_collider; #if COLLIDER_DEBUG ContactDebugData collision_debug_data; #endif PP_SpaceEntryKey space_key; //- Constraints / joints /* PP_Prop_ContactConstraint */ PP_ContactConstraint contact_constraint_data; /* PP_Prop_MotorJoint */ PP_MotorJoint motor_joint_data; /* PP_Prop_MouseJoint */ PP_MouseJoint mouse_joint_data; /* PP_Prop_WeldJoint */ PP_WeldJoint weld_joint_data; //- Control /* PP_Prop_Controlled */ PP_EntKey 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) */ f32 control_torque; /* How much torque is applied when turning towards desired focus */ PP_ControlData control; PP_EntKey move_joint; PP_EntKey aim_joint; //- Physics /* PP_Prop_Dynamic */ //f32 density; /* Density in kg/m^2 */ f32 friction; f32 mass_unscaled; /* Mass of ent in kg before any transformations */ f32 inertia_unscaled; /* Inertia of ent in kg*m^2 before any transformations */ PP_EntKey ground_friction_joint; f32 linear_ground_friction; f32 angular_ground_friction; /* Use PP_SetLinearVelocity & PP_SetAngularVelocity to set */ Vec2 linear_velocity; /* m/s */ f32 angular_velocity; /* rad/s */ Vec2 force; f32 torque; f32 linear_damping; f32 angular_damping; //- Sprite ResourceKey sprite; SPR_SpanKey sprite_span_key; u32 sprite_tint; Vec3 sprite_emittance; SPR_SliceKey sprite_collider_slice_key; /* Collider will sync to bounds of this slice if set */ Xform sprite_local_xform; /* Sprite transform in relation to ent */ //- Animation /* PP_Prop_Animating */ i64 animation_last_frame_change_time_ns; u32 animation_frame; //- Attachment /* PP_Prop_Attached */ /* Slice on the parent ent's sprite to attach to */ SPR_SliceKey attach_slice_key; //- Equip PP_EntKey equipped; //- Chucker /* PP_Prop_Chucker */ PP_EntKey chucker_zone; PP_EntKey chucker_joint; //- Chucker zone /* PP_Prop_ChuckerZone */ PP_EntKey chucker_zone_ent; u64 chucker_zone_ent_tick; //- Triggerable i32 num_primary_triggers; i32 num_secondary_triggers; f32 primary_fire_delay; f32 secondary_fire_delay; i64 last_primary_fire_ns; i64 last_secondary_fire_ns; //- Trigger /* How many times has this trigger been triggered this tick */ i64 triggered_count; /* Other triggers to activate when this entity has been triggered */ //PP_EntKey trigger_out_left; //PP_EntKey trigger_out_right; //- Bullet PP_EntKey bullet_src; PP_EntKey bullet_tracer; Vec2 bullet_src_pos; Vec2 bullet_src_dir; f32 bullet_launch_velocity; f32 bullet_knockback; f32 bullet_explosion_strength; f32 bullet_explosion_radius; b32 bullet_has_hit; //- Explosion f32 explosion_strength; f32 explosion_radius; //- Tracer /* PP_Prop_Tracer */ Vec2 tracer_start; Vec2 tracer_start_velocity; f32 tracer_fade_duration; /* Time for tracer to fade from opacity of 1 to 0 */ /* calculated each frame */ Vec2 tracer_gradient_start; Vec2 tracer_gradient_end; //- Quake /* PP_Prop_Quake */ f32 quake_intensity; f32 quake_frequency; f32 quake_fade; /* How much intensity to lose per second */ //- Testing /* PP_Prop_Test */ b32 test_initialized; Xform test_start_local_xform; Xform test_start_sprite_xform; /* PP_Prop_SoundEmitterTest */ // String sound_name; // MIX_TrackDesc sound_desc; // MIX_Handle sound_handle; //- Camera /* PP_Prop_Camera */ PP_EntKey camera_follow; Xform camera_quad_xform; f32 camera_lerp; /* Rate at which camera xform approaches target xform */ u32 camera_lerp_continuity_gen; Xform camera_xform_target; /* Calculated from camera_follow */ u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */ f32 shake; }; Struct(PP_EntArray) { PP_Ent *ents; u64 count; }; Struct(PP_PropArray) { PP_Prop *props; u64 count; }; Struct(PP_EntBin) { u32 first; u32 last; }; Inline PP_Ent *PP_NilEnt(void) { extern Readonly PP_Ent **PP_nil_ent; return *PP_nil_ent; } //////////////////////////////////////////////////////////// //~ Key types #define PP_NilEntKey ((PP_EntKey) { UID(0, 0) }) #define PP_RootEntKey ((PP_EntKey) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) }) /* Key magic number constants (to be used in conjunction with ent ids in deterministic key combinations) */ #define PP_TileChunkBasisUid (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a)) #define PP_ContactBasisUid (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af)) #define PP_CollisionDebugBasisUid (UID(0x302c01182013bb02, 0x570bd270399d11a5)) //////////////////////////////////////////////////////////// //~ Key helpers Inline b32 PP_EqEntKey(PP_EntKey a, PP_EntKey b) { return EqUid(a.uid, b.uid); } Inline b32 PP_IsNilEntKey(PP_EntKey key) { return EqUid(key.uid, PP_NilEntKey.uid); } //////////////////////////////////////////////////////////// //~ Property helpers Inline void PP_EnableProp(PP_Ent *ent, PP_Prop prop) { u64 index = prop / 64; u64 bit = prop % 64; ent->props[index] |= ((u64)1 << bit); } Inline void PP_DisableProp(PP_Ent *ent, PP_Prop prop) { u64 index = prop / 64; u64 bit = prop % 64; ent->props[index] &= ~((u64)1 << bit); } Inline b32 PP_HasProp(PP_Ent *ent, PP_Prop prop) { u64 index = prop / 64; u64 bit = prop % 64; return !!(ent->props[index] & ((u64)1 << bit)); } Inline b32 PP_IsValidAndActive(PP_Ent *ent) { return ent->valid && PP_HasProp(ent, PP_Prop_Active); } Inline b32 PP_ShouldPredict(PP_Ent *ent) { return PP_EqEntKey(ent->predictor, ent->ss->local_player); } Inline b32 PP_IsOwner(PP_Ent *ent) { return PP_EqEntKey(ent->owner, ent->ss->local_player); } Inline b32 PP_ShouldSimulate(PP_Ent *ent) { b32 result = 0; if (PP_IsValidAndActive(ent)) { result = 1; if (PP_HasProp(ent, PP_Prop_SyncDst)) { PP_EntKey local_player = ent->ss->local_player; result = PP_EqEntKey(local_player, ent->owner) || PP_EqEntKey(local_player, ent->predictor); } } return result; } //////////////////////////////////////////////////////////// //~ Acquire operations PP_Ent *PP_AcquireRawEnt(PP_Snapshot *ss, PP_Ent *parent, PP_EntKey key); PP_Ent *PP_AcquireLocalEnt(PP_Ent *parent); PP_Ent *PP_AcquireLocalEntWithKey(PP_Ent *parent, PP_EntKey key); PP_Ent *PP_AcquireSyncSrcEnt(PP_Ent *parent); PP_Ent *PP_AcquireSyncSrcEntWithKey(PP_Ent *parent, PP_EntKey key); PP_Ent *PP_AcquireSyncDstEnt(PP_Ent *parent, PP_EntKey ent_id, PP_EntKey owner_id); //////////////////////////////////////////////////////////// //~ Release operations void PP_ReleaseRawEnt(PP_Ent *ent); void PP_Release(PP_Ent *ent); void PP_ReleaseAllWithProp(PP_Snapshot *ss, PP_Prop prop); //////////////////////////////////////////////////////////// //~ Activate operations void PP_ActivateEnt(PP_Ent *ent, u64 current_tick); //////////////////////////////////////////////////////////// //~ Key operations u32 PP_IndexFromEnt(PP_Snapshot *ss, PP_Ent *ent); PP_Ent *PP_EntFromIndex(PP_Snapshot *ss, u32 index); PP_EntBin *PP_EntBinFromKey(PP_Snapshot *ss, PP_EntKey key); void PP_SetEntKey(PP_Ent *ent, PP_EntKey key); PP_Ent *PP_EntFromKey(PP_Snapshot *ss, PP_EntKey key); PP_EntKey PP_RandomKey(void); PP_EntKey PP_ContactConstraintKeyFromContactingKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1); PP_EntKey PP_CollisionDebugKeyFromKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1); PP_EntKey PP_TileChunkKeyFromIndex(Vec2I32 chunk_start); //////////////////////////////////////////////////////////// //~ Query operations PP_Ent *PP_FirstWithProp(PP_Snapshot *ss, PP_Prop prop); PP_Ent *PP_FirstWithAllProps(PP_Snapshot *ss, PP_PropArray props); //////////////////////////////////////////////////////////// //~ Tree operations void PP_Link(PP_Ent *parent, PP_Ent *child); void PP_Unlink(PP_Ent *ent); //////////////////////////////////////////////////////////// //~ Xform operations void PP_MarkChildXformsDirty(PP_Snapshot *ss, PP_Ent *ent); Xform PP_XformFromEnt_(PP_Snapshot *ss, PP_Ent *ent); Xform PP_XformFromEnt(PP_Ent *ent); Xform PP_LocalXformFromEnt(PP_Ent *ent); void PP_SetXform(PP_Ent *ent, Xform xf); void PP_SetLocalXform(PP_Ent *ent, Xform xf); //////////////////////////////////////////////////////////// //~ Movement operations void PP_SetLinearVelocity(PP_Ent *ent, Vec2 velocity); void PP_SetAngularVelocity(PP_Ent *ent, f32 velocity); void PP_ApplyLinearImpulse(PP_Ent *ent, Vec2 impulse, Vec2 world_point); void PP_ApplyLinearImpulseToCenter(PP_Ent *ent, Vec2 impulse); void PP_ApplyForceToCenter(PP_Ent *ent, Vec2 force); void PP_ApplyAngularImpulse(PP_Ent *ent, f32 impulse); void PP_ApplyTorque(PP_Ent *ent, f32 torque); //////////////////////////////////////////////////////////// //~ Tile operations PP_Ent *PP_TileChunkFromChunkIndex(PP_Snapshot *ss, Vec2I32 chunk_index); PP_Ent *PP_TileChunkFromWorldTileIndex(PP_Snapshot *ss, Vec2I32 world_tile_index); PP_TileKind PP_TileKindFromChunk(PP_Ent *chunk_ent, Vec2I32 local_tile_index); //////////////////////////////////////////////////////////// //~ Lerp operations void PP_LerpEnt(PP_Ent *e, PP_Ent *e0, PP_Ent *e1, f64 blend); //////////////////////////////////////////////////////////// //~ Sync operations void PP_CreateMissingEntsFromSnapshots(PP_Ent *local_parent, PP_Ent *remote, PP_EntKey remote_player); void PP_SyncEnt(PP_Ent *local, PP_Ent *remote); //////////////////////////////////////////////////////////// //~ Encode void PP_EncodeEnt(BB_Writer *bw, PP_Ent *e0, PP_Ent *e1); //////////////////////////////////////////////////////////// //~ Decode void PP_DecodeEnt(BB_Reader *br, PP_Ent *e);