562 lines
16 KiB
C
562 lines
16 KiB
C
#ifndef SIM_ENT_H
|
|
#define SIM_ENT_H
|
|
|
|
#include "sim.h"
|
|
#include "sprite.h"
|
|
#include "mixer.h"
|
|
#include "phys.h"
|
|
|
|
#define SIM_ENT_NIL_ID ((struct sim_ent_id) { UID(0, 0) })
|
|
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
|
|
|
struct bitbuff_writer;
|
|
struct bitbuff_reader;
|
|
|
|
enum sim_ent_prop {
|
|
SEPROP_ACTIVE,
|
|
SEPROP_RELEASE,
|
|
|
|
SEPROP_SYNC_SRC, /* This entity is networked to other clients */
|
|
SEPROP_SYNC_DST, /* This entity is not locally created, and will sync with incoming net src ents */
|
|
|
|
SEPROP_PLAYER,
|
|
SEPROP_PLAYER_IS_MASTER,
|
|
|
|
SEPROP_CMD,
|
|
|
|
SEPROP_TILE_CHUNK,
|
|
SEPROP_WALL,
|
|
|
|
/* Physics collision */
|
|
SEPROP_SENSOR, /* This entity's collisions generate contacts */
|
|
SEPROP_SOLID, /* This entity's collisions generate contacts to be solved by the physics system (overrides SEPROP_SENSOR) */
|
|
SEPROP_TOI, /* This entity's collisions are processed using TOI (time of impact) for precise collisions */
|
|
|
|
/* Physics movement */
|
|
SEPROP_KINEMATIC, /* This entity reacts to velocity */
|
|
SEPROP_DYNAMIC, /* This entity reacts to velocity and forces (overrides SEPROP_KINEMATIC) */
|
|
|
|
SEPROP_CONTROLLED,
|
|
|
|
SEPROP_COLLISION_DEBUG,
|
|
SEPROP_CONTACT_CONSTRAINT,
|
|
SEPROP_MOTOR_JOINT,
|
|
SEPROP_MOUSE_JOINT,
|
|
SEPROP_WELD_JOINT,
|
|
|
|
SEPROP_CAMERA,
|
|
SEPROP_CAMERA_ACTIVE,
|
|
|
|
SEPROP_BULLET,
|
|
SEPROP_WEAPON_SMG,
|
|
SEPROP_WEAPON_LAUNCHER,
|
|
SEPROP_WEAPON_CHUCKER,
|
|
|
|
SEPROP_CHUCKER_ZONE,
|
|
|
|
SEPROP_EXPLOSION,
|
|
|
|
SEPROP_TRACER,
|
|
|
|
SEPROP_QUAKE,
|
|
|
|
SEPROP_ATTACHED,
|
|
|
|
/* Test props */
|
|
|
|
SEPROP_TEST,
|
|
SEPROP_TEST_SOUND_EMITTER,
|
|
|
|
SEPROP_COUNT
|
|
};
|
|
|
|
struct sim_ent {
|
|
struct sim_snapshot *ss;
|
|
|
|
/* ====================================================================== */
|
|
/* Metadata */
|
|
|
|
b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */
|
|
struct sim_ent_id id;
|
|
u64 props[(SEPROP_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 id of the top level parent of the ent tree (if ent is top then this point to itself) */
|
|
struct sim_ent_id top;
|
|
|
|
/* Tree */
|
|
struct sim_ent_id parent;
|
|
struct sim_ent_id next;
|
|
struct sim_ent_id prev;
|
|
struct sim_ent_id first;
|
|
struct sim_ent_id last;
|
|
|
|
/* Lists keyed by index in snapshot ent array */
|
|
u32 next_in_id_bin;
|
|
u32 prev_in_id_bin;
|
|
u32 next_free;
|
|
|
|
/* ====================================================================== */
|
|
/* Sync */
|
|
|
|
/* SEPROP_SYNC_SRC */
|
|
/* SEPROP_SYNC_DST */
|
|
|
|
/* Id of the player that owns simulation for this entity */
|
|
struct sim_ent_id owner;
|
|
|
|
/* Id of the player that should predict simulation of this this entity locally */
|
|
struct sim_ent_id predictor;
|
|
|
|
/* ====================================================================== */
|
|
/* Position */
|
|
|
|
/* Use xform getters & setters to access. */
|
|
struct xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */
|
|
struct 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 */
|
|
|
|
/* SEPROP_CMD */
|
|
|
|
enum sim_cmd_kind cmd_kind;
|
|
struct sim_ent_id cmd_player;
|
|
|
|
/* FIXME: Lerp */
|
|
|
|
/* Control cmd */
|
|
struct sim_control cmd_control;
|
|
struct sim_ent_id cmd_control_hovered_ent;
|
|
|
|
/* Chat cmd */
|
|
//struct string cmd_chat_msg;
|
|
|
|
/* ====================================================================== */
|
|
/* Chat */
|
|
|
|
/* SEPROP_CHAT */
|
|
|
|
struct sim_ent_id chat_player;
|
|
//struct string chat_msg;
|
|
|
|
|
|
/* ====================================================================== */
|
|
/* Tile */
|
|
|
|
/* SEPROP_TILE_CHUNK */
|
|
|
|
/* FIXME: Move out of here */
|
|
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
|
struct v2i32 tile_chunk_index;
|
|
|
|
/* ====================================================================== */
|
|
/* Client */
|
|
|
|
/* SEPROP_PLAYER */
|
|
|
|
/* FIXME: Lerp */
|
|
|
|
struct sim_client_handle player_client_handle; /* The client handle on the master sim's machine */
|
|
|
|
struct sim_control player_control;
|
|
struct v2 player_cursor_pos;
|
|
|
|
struct sim_ent_id player_hovered_ent;
|
|
struct sim_ent_id player_control_ent;
|
|
struct sim_ent_id player_camera_ent;
|
|
|
|
struct sim_ent_id 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 */
|
|
|
|
struct v2 collision_dir; /* If set, then only collisions coming from this direction will generate contacts (used for walls to prevent ghost collisions) */
|
|
struct collider_shape local_collider;
|
|
|
|
#if COLLIDER_DEBUG
|
|
struct phys_collision_debug collision_debug_data;
|
|
#endif
|
|
|
|
struct space_entry_handle space_handle;
|
|
|
|
/* ====================================================================== */
|
|
/* Constraints / joints */
|
|
|
|
/* SEPROP_CONSTRAINT_CONTACT */
|
|
struct phys_contact_constraint contact_constraint_data;
|
|
|
|
/* SEPROP_MOTOR_JOINT */
|
|
struct phys_motor_joint motor_joint_data;
|
|
|
|
/* SEPROP_MOUSE_JOINT */
|
|
struct phys_mouse_joint mouse_joint_data;
|
|
|
|
/* SEPROP_WELD_JOINT */
|
|
struct phys_weld_joint weld_joint_data;
|
|
|
|
/* ====================================================================== */
|
|
/* Control */
|
|
|
|
/* SEPROP_CONTROLLED */
|
|
|
|
struct sim_ent_id 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 */
|
|
|
|
struct sim_control control;
|
|
|
|
struct sim_ent_id move_joint;
|
|
struct sim_ent_id aim_joint;
|
|
|
|
/* ====================================================================== */
|
|
/* Physics */
|
|
|
|
/* SEPROP_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 */
|
|
|
|
struct sim_ent_id ground_friction_joint;
|
|
f32 linear_ground_friction;
|
|
f32 angular_ground_friction;
|
|
|
|
/* Use sim_ent_set_linear_velocity & sim_ent_set_angular_velocity to set */
|
|
struct v2 linear_velocity; /* m/s */
|
|
f32 angular_velocity; /* rad/s */
|
|
|
|
struct v2 force;
|
|
f32 torque;
|
|
|
|
f32 linear_damping;
|
|
f32 angular_damping;
|
|
|
|
/* ====================================================================== */
|
|
/* Sprite */
|
|
|
|
struct sprite_tag sprite;
|
|
struct string sprite_span_name;
|
|
u32 sprite_tint;
|
|
|
|
struct string sprite_collider_slice; /* Collider will sync to bounds of this slice if set */
|
|
|
|
struct xform sprite_local_xform; /* Sprite transform in relation to ent */
|
|
|
|
/* ====================================================================== */
|
|
/* Animation */
|
|
|
|
/* SEPROP_ANIMATING */
|
|
i64 animation_last_frame_change_time_ns;
|
|
u32 animation_frame;
|
|
|
|
/* ====================================================================== */
|
|
/* Attachment */
|
|
|
|
/* SEPROP_ATTACHED */
|
|
/* Slice name on the parent ent's sprite to attach to */
|
|
struct string attach_slice;
|
|
|
|
/* ====================================================================== */
|
|
/* Equip */
|
|
|
|
struct sim_ent_id equipped;
|
|
|
|
/* ====================================================================== */
|
|
/* Chucker */
|
|
|
|
/* SEPROP_WEAPON_CHUCKER */
|
|
|
|
struct sim_ent_id chucker_zone;
|
|
struct sim_ent_id chucker_joint;
|
|
|
|
/* ====================================================================== */
|
|
/* Chucker zone */
|
|
|
|
/* SEPROP_CHUCKER_ZONE */
|
|
|
|
struct sim_ent_id 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 */
|
|
//struct sim_ent_id trigger_out_left;
|
|
//struct sim_ent_id trigger_out_right;
|
|
|
|
/* ====================================================================== */
|
|
/* Bullet */
|
|
|
|
struct sim_ent_id bullet_src;
|
|
struct sim_ent_id bullet_tracer;
|
|
struct v2 bullet_src_pos;
|
|
struct v2 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 */
|
|
|
|
/* SEPROP_TRACER */
|
|
|
|
struct v2 tracer_start;
|
|
struct v2 tracer_start_velocity;
|
|
f32 tracer_fade_duration; /* Time for tracer to fade from opacity of 1 to 0 */
|
|
|
|
/* calculated each frame */
|
|
struct v2 tracer_gradient_start;
|
|
struct v2 tracer_gradient_end;
|
|
|
|
/* ====================================================================== */
|
|
/* Quake */
|
|
|
|
/* SEPROP_QUAKE */
|
|
|
|
f32 quake_intensity;
|
|
f32 quake_frequency;
|
|
f32 quake_fade; /* How much intensity to lose per second */
|
|
|
|
/* ====================================================================== */
|
|
/* Testing */
|
|
|
|
/* SEPROP_TEST */
|
|
b32 test_initialized;
|
|
struct xform test_start_local_xform;
|
|
struct xform test_start_sprite_xform;
|
|
|
|
/* SEPROP_TEST_SOUND_EMITTER */
|
|
struct string sound_name;
|
|
struct mixer_desc sound_desc;
|
|
struct mixer_track_handle sound_handle;
|
|
|
|
/* ====================================================================== */
|
|
/* Camera */
|
|
|
|
/* SEPROP_CAMERA */
|
|
struct sim_ent_id camera_follow;
|
|
struct xform camera_quad_xform;
|
|
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
|
|
|
u32 camera_lerp_continuity_gen;
|
|
struct xform camera_xform_target; /* Calculated from camera_follow */
|
|
u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */
|
|
|
|
f32 shake;
|
|
};
|
|
|
|
struct sim_ent_array {
|
|
struct sim_ent *ents;
|
|
u64 count;
|
|
};
|
|
|
|
struct sim_ent_prop_array {
|
|
enum sim_ent_prop *props;
|
|
u64 count;
|
|
};
|
|
|
|
struct sim_ent_bin {
|
|
u32 first;
|
|
u32 last;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Nil
|
|
* ========================== */
|
|
|
|
INLINE struct sim_ent *sim_ent_nil(void)
|
|
{
|
|
extern READONLY struct sim_ent **_g_sim_ent_nil;
|
|
return *_g_sim_ent_nil;
|
|
}
|
|
|
|
/* ========================== *
|
|
* Id helpers
|
|
* ========================== */
|
|
|
|
INLINE b32 sim_ent_id_eq(struct sim_ent_id a, struct sim_ent_id b)
|
|
{
|
|
return uid_eq(a.uid, b.uid);
|
|
}
|
|
|
|
INLINE b32 sim_ent_id_is_nil(struct sim_ent_id id)
|
|
{
|
|
return uid_eq(id.uid, SIM_ENT_NIL_ID.uid);
|
|
}
|
|
|
|
/* ========================== *
|
|
* Property helpers
|
|
* ========================== */
|
|
|
|
INLINE void sim_ent_enable_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
|
{
|
|
u64 index = prop / 64;
|
|
u64 bit = prop % 64;
|
|
ent->props[index] |= ((u64)1 << bit);
|
|
}
|
|
|
|
INLINE void sim_ent_disable_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
|
{
|
|
u64 index = prop / 64;
|
|
u64 bit = prop % 64;
|
|
ent->props[index] &= ~((u64)1 << bit);
|
|
}
|
|
|
|
INLINE b32 sim_ent_has_prop(struct sim_ent *ent, enum sim_ent_prop prop)
|
|
{
|
|
u64 index = prop / 64;
|
|
u64 bit = prop % 64;
|
|
return !!(ent->props[index] & ((u64)1 << bit));
|
|
}
|
|
|
|
INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
|
|
{
|
|
return ent->valid && sim_ent_has_prop(ent, SEPROP_ACTIVE);
|
|
}
|
|
|
|
INLINE b32 sim_ent_should_predict(struct sim_ent *ent)
|
|
{
|
|
return sim_ent_id_eq(ent->predictor, ent->ss->local_player);
|
|
}
|
|
|
|
INLINE b32 sim_ent_is_owner(struct sim_ent *ent)
|
|
{
|
|
return sim_ent_id_eq(ent->owner, ent->ss->local_player);
|
|
}
|
|
|
|
INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
|
|
{
|
|
b32 res = false;
|
|
if (sim_ent_is_valid_and_active(ent)) {
|
|
res = true;
|
|
if (sim_ent_has_prop(ent, SEPROP_SYNC_DST)) {
|
|
struct sim_ent_id local_player = ent->ss->local_player;
|
|
res = sim_ent_id_eq(local_player, ent->owner) || sim_ent_id_eq(local_player, ent->predictor);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/* ========================== *
|
|
* Ent functions
|
|
* ========================== */
|
|
|
|
/* Alloc */
|
|
struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss, struct sim_ent *parent, struct sim_ent_id id);
|
|
struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent);
|
|
struct sim_ent *sim_ent_alloc_local_with_id(struct sim_ent *parent, struct sim_ent_id id);
|
|
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent);
|
|
struct sim_ent *sim_ent_alloc_sync_src_with_id(struct sim_ent *parent, struct sim_ent_id id);
|
|
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_ent_id ent_id, struct sim_ent_id owner_id);
|
|
|
|
void sim_ent_release_raw(struct sim_ent *ent);
|
|
void sim_ent_release(struct sim_ent *ent);
|
|
void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
|
|
|
/* Activate */
|
|
void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
|
|
|
|
/* Id */
|
|
void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id);
|
|
struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
|
|
struct sim_ent_id sim_ent_random_id(void);
|
|
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
|
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
|
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(struct v2i32 chunk_start);
|
|
|
|
/* Query */
|
|
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
|
struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim_ent_prop_array props);
|
|
|
|
/* Tree */
|
|
void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child);
|
|
void sim_ent_unlink_from_parent(struct sim_ent *ent);
|
|
|
|
/* Xform */
|
|
struct xform sim_ent_get_xform(struct sim_ent *ent);
|
|
struct xform sim_ent_get_local_xform(struct sim_ent *ent);
|
|
void sim_ent_set_xform(struct sim_ent *ent, struct xform xf);
|
|
void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf);
|
|
|
|
/* Movement */
|
|
void sim_ent_set_linear_velocity(struct sim_ent *ent, struct v2 velocity);
|
|
void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity);
|
|
void sim_ent_apply_linear_impulse(struct sim_ent *ent, struct v2 impulse, struct v2 world_point);
|
|
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, struct v2 impulse);
|
|
void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force);
|
|
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
|
|
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
|
|
|
/* Tile */
|
|
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, struct v2i32 chunk_index);
|
|
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, struct v2i32 world_tile_index);
|
|
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, struct v2i32 local_tile_index);
|
|
|
|
/* Lerp */
|
|
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
|
|
|
/* Sync */
|
|
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, struct sim_ent_id remote_player);
|
|
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote);
|
|
|
|
/* Encode / decode */
|
|
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1);
|
|
void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e);
|
|
|
|
#endif
|