rename 'game' -> 'sim'

This commit is contained in:
jacob 2025-02-08 09:45:32 -06:00
parent b9ec028bfa
commit 4cbc6b6d59
9 changed files with 305 additions and 305 deletions

View File

@ -5,7 +5,7 @@
#include "sys.h" #include "sys.h"
#include "work.h" #include "work.h"
#include "user.h" #include "user.h"
#include "game.h" #include "sim.h"
#include "playback.h" #include "playback.h"
#include "log.h" #include "log.h"
#include "resource.h" #include "resource.h"
@ -139,8 +139,8 @@ void app_entry_point(void)
{ {
/* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */ /* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */
#if !PROFILING && !RTC #if !PROFILING && !RTC
/* 1. User thread, Input thread /* 1. User thread
* 2. Game thread * 2. Sim thread
* 3. Playback thread * 3. Playback thread
*/ */
u32 num_reserved_cores = 3; u32 num_reserved_cores = 3;
@ -223,8 +223,8 @@ void app_entry_point(void)
struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr); struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr);
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr); struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
struct phys_startup_receipt phys_sr = phys_startup(); struct phys_startup_receipt phys_sr = phys_startup();
struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr, &host_sr); struct sim_startup_receipt sim_sr = sim_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr, &host_sr);
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &game_sr, &asset_cache_sr, &mixer_sr, &host_sr, &window); struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &sim_sr, &asset_cache_sr, &mixer_sr, &host_sr, &window);
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr); struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
(UNUSED)user_sr; (UNUSED)user_sr;

View File

@ -34,26 +34,26 @@
#define SPACE_CELL_SIZE 1.0f #define SPACE_CELL_SIZE 1.0f
#define GAME_FPS 50.0 #define SIM_FPS 50.0
#define GAME_TIMESCALE 1 #define SIM_TIMESCALE 1
#define GAME_PHYSICS_SUBSTEPS 4 #define SIM_PHYSICS_SUBSTEPS 4
#define GAME_PHYSICS_ENABLE_WARM_STARTING 1 #define SIM_PHYSICS_ENABLE_WARM_STARTING 1
#define GAME_PHYSICS_ENABLE_RELAXATION 1 #define SIM_PHYSICS_ENABLE_RELAXATION 1
#define GAME_PHYSICS_ENABLE_TOI 1 #define SIM_PHYSICS_ENABLE_TOI 1
#define GAME_PHYSICS_ENABLE_COLLISION 1 #define SIM_PHYSICS_ENABLE_COLLISION 1
#define GAME_SPAWN_TESTENT 0 #define SIM_SPAWN_TESTENT 0
#define GAME_PLAYER_AIM 1 #define SIM_PLAYER_AIM 1
//#define GAME_MAX_LINEAR_VELOCITY 500 //#define SIM_MAX_LINEAR_VELOCITY 500
//#define GAME_MAX_ANGULAR_VELOCITY (TAU * 20) //#define SIM_MAX_ANGULAR_VELOCITY (TAU * 20)
#define GAME_MAX_LINEAR_VELOCITY F32_INFINITY #define SIM_MAX_LINEAR_VELOCITY F32_INFINITY
#define GAME_MAX_ANGULAR_VELOCITY F32_INFINITY #define SIM_MAX_ANGULAR_VELOCITY F32_INFINITY
/* How many ticks back in time should the user blend between? /* How many ticks back in time should the user blend between?
* <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate> * <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Sim tick rate>
* E.g: At 1.5, the user thread will render 75ms back in time (if game thread runs at 50FPS) * E.g: At 1.5, the user thread will render 75ms back in time (if sim thread runs at 50FPS)
*/ */
#define USER_INTERP_OFFSET_TICK_RATIO 1.1 #define USER_INTERP_OFFSET_TICK_RATIO 1.1
#define USER_INTERP_ENABLED 1 #define USER_INTERP_ENABLED 1

View File

@ -391,8 +391,8 @@ void entity_set_xform(struct entity *ent, struct xform xf);
void entity_set_local_xform(struct entity *ent, struct xform xf); void entity_set_local_xform(struct entity *ent, struct xform xf);
/* Movement */ /* Movement */
INLINE void entity_set_linear_velocity(struct entity *ent, struct v2 velocity) { ent->linear_velocity = v2_clamp_len(velocity, GAME_MAX_LINEAR_VELOCITY); } INLINE void entity_set_linear_velocity(struct entity *ent, struct v2 velocity) { ent->linear_velocity = v2_clamp_len(velocity, SIM_MAX_LINEAR_VELOCITY); }
INLINE void entity_set_angular_velocity(struct entity *ent, f32 velocity) { ent->angular_velocity = clamp_f32(velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY); } INLINE void entity_set_angular_velocity(struct entity *ent, f32 velocity) { ent->angular_velocity = clamp_f32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY); }
void entity_apply_linear_impulse(struct entity *ent, struct v2 impulse, struct v2 world_point); void entity_apply_linear_impulse(struct entity *ent, struct v2 impulse, struct v2 world_point);
void entity_apply_linear_impulse_to_center(struct entity *ent, struct v2 impulse); void entity_apply_linear_impulse_to_center(struct entity *ent, struct v2 impulse);
void entity_apply_force_to_center(struct entity *ent, struct v2 force); void entity_apply_force_to_center(struct entity *ent, struct v2 force);

View File

@ -1,135 +0,0 @@
#ifndef GAME_H
#define GAME_H
#include "host.h"
struct world;
struct mixer_startup_receipt;
struct sprite_startup_receipt;
struct sound_startup_receipt;
struct phys_startup_receipt;
struct host_startup_receipt;
/* Absolute layers */
#define GAME_LAYER_FLOOR_DECALS -300
#define GAME_LAYER_BULLETS -200
#define GAME_LAYER_TRACERS -100
#define GAME_LAYER_SHOULDERS 0
/* Relative layers */
#define GAME_LAYER_RELATIVE_DEFAULT 0
#define GAME_LAYER_RELATIVE_WEAPON 1
struct game_startup_receipt { i32 _; };
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr,
struct sound_startup_receipt *sound_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr);
/* ========================== *
* Game cmd
* ========================== */
enum game_cmd_state {
GAME_CMD_STATE_STOP = -1,
GAME_CMD_STATE_NO_CHANGE = 0,
GAME_CMD_STATE_START = 1
};
enum game_cmd_kind {
GAME_CMD_KIND_NONE,
GAME_CMD_KIND_PLAYER_MOVE,
GAME_CMD_KIND_PLAYER_FIRE,
GAME_CMD_KIND_CLIENT_CONNECT,
GAME_CMD_KIND_CLIENT_DISCONNECT,
/* Testing */
GAME_CMD_KIND_CLEAR_ALL,
GAME_CMD_KIND_SPAWN_TEST,
GAME_CMD_KIND_PAUSE,
GAME_CMD_KIND_STEP,
GAME_CMD_KIND_DRAG_OBJECT,
GAME_CMD_KIND_CURSOR_MOVE,
GAME_CMD_KIND_COUNT
};
struct game_cmd {
enum game_cmd_kind kind;
enum game_cmd_state state;
struct host_channel_id channel_id;
/* GAME_CMD_KIND_PLAYER_MOVE */
struct v2 move_dir;
struct v2 aim_dir;
/* GAME_CMD_KIND_CURSOR_MOVE */
struct v2 cursor_pos;
/* GAME_CMD_KIND_PLAYER_DISCONNECT */
struct string disconnect_reason;
#if RTC
u32 collider_gjk_steps;
#endif
struct game_cmd *next;
};
struct game_cmd_list {
struct game_cmd *first;
struct game_cmd *last;
};
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds);
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out);
/* ========================== *
* Game event
* ========================== */
enum game_event_kind {
GAME_EVENT_KIND_NONE,
GAME_EVENT_KIND_CONNECT,
GAME_EVENT_KIND_DISCONNECT,
GAME_EVENT_KIND_SNAPSHOT_FULL,
//GAME_EVENT_KIND_ENTITY_UPDATE,
//GAME_EVENT_KIND_ENTITY_CREATE,
//GAME_EVENT_KIND_ENTITY_DESTROY
};
struct game_event {
enum game_event_kind kind;
struct host_channel_id channel_id;
struct string snapshot_data;
struct string disconnect_reason;
//struct entity_handle entity;
//struct string update_data;
struct game_event *next;
};
struct game_event_list {
struct game_event *first;
struct game_event *last;
};
struct string game_string_from_events(struct arena *arena, struct game_event_list events);
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out);
/* ========================== *
* Snapshot
* ========================== */
struct string game_string_from_tick(struct arena *arena, struct world *tick);
void game_tick_from_string(struct string str, struct world *tick_out);
#endif

View File

@ -19,7 +19,7 @@ GLOBAL struct {
struct phys_startup_receipt phys_startup(void) struct phys_startup_receipt phys_startup(void)
{ {
/* Initialize constants */ /* Initialize constants */
const f32 substep_dt = (1.f / ((f32)GAME_FPS * (f32)GAME_PHYSICS_SUBSTEPS)); const f32 substep_dt = (1.f / ((f32)SIM_FPS * (f32)SIM_PHYSICS_SUBSTEPS));
const f32 contact_frequency = (1.f / substep_dt) / 8.f; const f32 contact_frequency = (1.f / substep_dt) / 8.f;
const f32 contact_damping_ratio = 10; const f32 contact_damping_ratio = 10;
@ -354,7 +354,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration)
contact->inv_tangent_mass = k > 0.0f ? 1.0f / k : 0.0f; contact->inv_tangent_mass = k > 0.0f ? 1.0f / k : 0.0f;
} }
#if !GAME_PHYSICS_ENABLE_WARM_STARTING #if !SIM_PHYSICS_ENABLE_WARM_STARTING
contact->normal_impulse = 0; contact->normal_impulse = 0;
contact->tangent_impulse = 0; contact->tangent_impulse = 0;
#endif #endif
@ -646,7 +646,7 @@ void phys_prepare_motor_joints(struct phys_ctx *ctx)
joint->angular_mass = 1.f / (inv_i0 + inv_i1); joint->angular_mass = 1.f / (inv_i0 + inv_i1);
#if !GAME_PHYSICS_ENABLE_WARM_STARTING #if !SIM_PHYSICS_ENABLE_WARM_STARTING
joint->linear_impulse = V2(0, 0); joint->linear_impulse = V2(0, 0);
joint->angular_impulse = 0; joint->angular_impulse = 0;
#endif #endif
@ -874,7 +874,7 @@ void phys_prepare_mouse_joints(struct phys_ctx *ctx)
linear_mass_xf.by.y = inv_m + inv_i * vcp.x * vcp.x; linear_mass_xf.by.y = inv_m + inv_i * vcp.x * vcp.x;
joint->linear_mass_xf = xform_invert(linear_mass_xf); joint->linear_mass_xf = xform_invert(linear_mass_xf);
#if !GAME_PHYSICS_ENABLE_WARM_STARTING #if !SIM_PHYSICS_ENABLE_WARM_STARTING
joint->linear_impulse = V2(0, 0); joint->linear_impulse = V2(0, 0);
joint->angular_impulse = 0; joint->angular_impulse = 0;
#endif #endif
@ -1150,7 +1150,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
/* TOI */ /* TOI */
f32 step_dt = remaining_dt; f32 step_dt = remaining_dt;
{ {
#if GAME_PHYSICS_ENABLE_TOI #if SIM_PHYSICS_ENABLE_TOI
const f32 min_toi = 0.000001f; const f32 min_toi = 0.000001f;
const f32 tolerance = 0.0001f; const f32 tolerance = 0.0001f;
const u32 max_iterations = 16; const u32 max_iterations = 16;
@ -1175,19 +1175,19 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
ctx->pre_solve_callback(collision_data); ctx->pre_solve_callback(collision_data);
} }
f32 substep_dt = step_dt / GAME_PHYSICS_SUBSTEPS; f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
for (u32 i = 0; i < GAME_PHYSICS_SUBSTEPS; ++i) { for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) {
__profscope(substep); __profscope(substep);
/* Warm start */ /* Warm start */
#if GAME_PHYSICS_ENABLE_WARM_STARTING #if SIM_PHYSICS_ENABLE_WARM_STARTING
phys_warm_start_contacts(ctx); phys_warm_start_contacts(ctx);
phys_warm_start_motor_joints(ctx); phys_warm_start_motor_joints(ctx);
phys_warm_start_mouse_joints(ctx); phys_warm_start_mouse_joints(ctx);
#endif #endif
/* Solve */ /* Solve */
#if GAME_PHYSICS_ENABLE_COLLISION #if SIM_PHYSICS_ENABLE_COLLISION
phys_solve_contacts(ctx, substep_dt, true); phys_solve_contacts(ctx, substep_dt, true);
#endif #endif
phys_solve_motor_joints(ctx, substep_dt); phys_solve_motor_joints(ctx, substep_dt);
@ -1197,7 +1197,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
phys_integrate_velocities(ctx, substep_dt); phys_integrate_velocities(ctx, substep_dt);
/* Relaxation solve */ /* Relaxation solve */
#if GAME_PHYSICS_ENABLE_COLLISION && GAME_PHYSICS_ENABLE_RELAXATION #if SIM_PHYSICS_ENABLE_COLLISION && SIM_PHYSICS_ENABLE_RELAXATION
phys_solve_contacts(ctx, substep_dt, false); phys_solve_contacts(ctx, substep_dt, false);
#endif #endif
} }

View File

@ -1,4 +1,4 @@
#include "game.h" #include "sim.h"
#include "sys.h" #include "sys.h"
#include "util.h" #include "util.h"
#include "world.h" #include "world.h"
@ -19,8 +19,8 @@
#include "host.h" #include "host.h"
GLOBAL struct { GLOBAL struct {
struct atomic_i32 game_thread_shutdown; struct atomic_i32 sim_thread_shutdown;
struct sys_thread game_thread; struct sys_thread sim_thread;
u64 last_phys_iteration; u64 last_phys_iteration;
@ -47,17 +47,17 @@ GLOBAL struct {
/* Tick */ /* Tick */
struct world tick; struct world tick;
} G = ZI, DEBUG_ALIAS(G, G_game); } G = ZI, DEBUG_ALIAS(G, G_sim);
/* ========================== * /* ========================== *
* Startup * Startup
* ========================== */ * ========================== */
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown); INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown);
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg); INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg);
INTERNAL void reset_world(void); INTERNAL void reset_world(void);
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr, struct sim_startup_receipt sim_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr, struct sprite_startup_receipt *sheet_sr,
struct sound_startup_receipt *sound_sr, struct sound_startup_receipt *sound_sr,
struct phys_startup_receipt *phys_sr, struct phys_startup_receipt *phys_sr,
@ -77,17 +77,17 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
/* Initialize empty world */ /* Initialize empty world */
reset_world(); reset_world();
G.game_thread = sys_thread_alloc(&game_thread_entry_point, NULL, LIT("[P2] Game thread")); G.sim_thread = sys_thread_alloc(&sim_thread_entry_point, NULL, LIT("[P2] Sim thread"));
app_register_exit_callback(&game_shutdown); app_register_exit_callback(&sim_shutdown);
return (struct game_startup_receipt) { 0 }; return (struct sim_startup_receipt) { 0 };
} }
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown) INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown)
{ {
__prof; __prof;
atomic_i32_eval_exchange(&G.game_thread_shutdown, true); atomic_i32_eval_exchange(&G.sim_thread_shutdown, true);
sys_thread_wait_release(&G.game_thread); sys_thread_wait_release(&G.sim_thread);
} }
/* ========================== * /* ========================== *
@ -116,7 +116,7 @@ INTERNAL void reset_world(void)
/* Re-create world */ /* Re-create world */
world_alloc(&G.tick); world_alloc(&G.tick);
G.tick.timescale = GAME_TIMESCALE; G.tick.timescale = SIM_TIMESCALE;
} }
/* ========================== * /* ========================== *
@ -174,7 +174,7 @@ INTERNAL void spawn_test_entities(void)
//e->sprite_span_name = LIT("idle.unarmed"); //e->sprite_span_name = LIT("idle.unarmed");
//e->sprite_span_name = LIT("idle.one_handed"); //e->sprite_span_name = LIT("idle.one_handed");
e->sprite_span_name = LIT("idle.two_handed"); e->sprite_span_name = LIT("idle.two_handed");
e->layer = GAME_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
//xf.bx.y = -1.f; //xf.bx.y = -1.f;
@ -207,7 +207,7 @@ INTERNAL void spawn_test_entities(void)
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase")); e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
e->sprite_collider_slice = LIT("shape"); e->sprite_collider_slice = LIT("shape");
e->layer = GAME_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
e->mass_unscaled = 10; e->mass_unscaled = 10;
@ -230,7 +230,7 @@ INTERNAL void spawn_test_entities(void)
e->sprite = sprite_tag_from_path(LIT("res/graphics/box.ase")); e->sprite = sprite_tag_from_path(LIT("res/graphics/box.ase"));
e->sprite_collider_slice = LIT("shape"); e->sprite_collider_slice = LIT("shape");
e->layer = GAME_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
e->mass_unscaled = 100; e->mass_unscaled = 100;
@ -253,7 +253,7 @@ INTERNAL void spawn_test_entities(void)
e->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase")); e->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase"));
e->sprite_collider_slice = LIT("shape"); e->sprite_collider_slice = LIT("shape");
e->layer = GAME_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
e->mass_unscaled = 0.5; e->mass_unscaled = 0.5;
@ -269,7 +269,7 @@ INTERNAL void spawn_test_entities(void)
entity_enable_prop(e, ENTITY_PROP_ATTACHED); entity_enable_prop(e, ENTITY_PROP_ATTACHED);
e->attach_slice = LIT("attach.wep"); e->attach_slice = LIT("attach.wep");
e->layer = GAME_LAYER_RELATIVE_WEAPON; e->layer = SIM_LAYER_RELATIVE_WEAPON;
entity_enable_prop(e, ENTITY_PROP_WEAPON); entity_enable_prop(e, ENTITY_PROP_WEAPON);
//e->trigger_delay = 1.0f / 10.0f; //e->trigger_delay = 1.0f / 10.0f;
@ -406,7 +406,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
struct entity *decal = entity_alloc(root); struct entity *decal = entity_alloc(root);
decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase")); decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase"));
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f); decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
decal->layer = GAME_LAYER_FLOOR_DECALS; decal->layer = SIM_LAYER_FLOOR_DECALS;
entity_set_xform(decal, xf); entity_set_xform(decal, xf);
f32 perp_range = 0.5; f32 perp_range = 0.5;
@ -433,7 +433,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
* Update * Update
* ========================== */ * ========================== */
INTERNAL void game_update(void) INTERNAL void sim_update(void)
{ {
__prof; __prof;
@ -456,7 +456,7 @@ INTERNAL void game_update(void)
++G.tick.tick_id; ++G.tick.tick_id;
G.tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale)); G.tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / SIM_FPS) * G.tick.timescale));
G.tick.time_ns += G.tick.dt_ns; G.tick.time_ns += G.tick.dt_ns;
f64 dt = SECONDS_FROM_NS(G.tick.dt_ns); f64 dt = SECONDS_FROM_NS(G.tick.dt_ns);
@ -525,48 +525,48 @@ INTERNAL void game_update(void)
} }
/* ========================== * /* ========================== *
* Process host events into game cmds * Process host events into sim cmds
* ========================== */ * ========================== */
struct game_cmd_list game_cmds = ZI; struct sim_cmd_list sim_cmds = ZI;
{ {
struct host_event_array host_events = host_pop_events(scratch.arena, G.host); struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
game_cmds_from_host_events(scratch.arena, host_events, &game_cmds); sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
} }
/* ========================== * /* ========================== *
* Process game cmds * Process sim cmds
* ========================== */ * ========================== */
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) { for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
enum game_cmd_kind kind = cmd->kind; enum sim_cmd_kind kind = cmd->kind;
struct host_channel_id channel_id = cmd->channel_id; struct host_channel_id channel_id = cmd->channel_id;
struct client *client = client_from_channel_id(G.client_store, channel_id); struct client *client = client_from_channel_id(G.client_store, channel_id);
if (client->valid || host_channel_id_is_nil(channel_id)) { if (client->valid || host_channel_id_is_nil(channel_id)) {
switch (kind) { switch (kind) {
/* Cursor */ /* Cursor */
case GAME_CMD_KIND_CURSOR_MOVE: case SIM_CMD_KIND_CURSOR_MOVE:
{ {
G.user_cursor = cmd->cursor_pos; G.user_cursor = cmd->cursor_pos;
} break; } break;
/* Clear level */ /* Clear level */
case GAME_CMD_KIND_CLEAR_ALL: case SIM_CMD_KIND_CLEAR_ALL:
{ {
G.should_reset_level = true; G.should_reset_level = true;
} break; } break;
/* Spawn test */ /* Spawn test */
case GAME_CMD_KIND_SPAWN_TEST: case SIM_CMD_KIND_SPAWN_TEST:
{ {
logf_info("Spawning (test)"); logf_info("Spawning (test)");
spawn_test_entities(); spawn_test_entities();
} break; } break;
/* Disconnect client */ /* Disconnect client */
case GAME_CMD_KIND_CLIENT_DISCONNECT: case SIM_CMD_KIND_CLIENT_DISCONNECT:
{ {
if (client->valid) { if (client->valid) {
struct entity *client_ent = entity_from_handle(entity_store, client->ent); struct entity *client_ent = entity_from_handle(entity_store, client->ent);
@ -581,7 +581,7 @@ INTERNAL void game_update(void)
default: break; default: break;
}; };
} else if (kind == GAME_CMD_KIND_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) { } else if (kind == SIM_CMD_KIND_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) {
/* Connect client */ /* Connect client */
client = client_alloc(G.client_store, channel_id); client = client_alloc(G.client_store, channel_id);
struct entity *client_ent = entity_alloc(root); struct entity *client_ent = entity_alloc(root);
@ -724,21 +724,21 @@ INTERNAL void game_update(void)
struct v2 focus = ent->control.focus; struct v2 focus = ent->control.focus;
b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED); b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED);
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) { for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
b32 start = cmd->state == GAME_CMD_STATE_START; b32 start = cmd->state == SIM_CMD_STATE_START;
b32 stop = cmd->state == GAME_CMD_STATE_STOP; b32 stop = cmd->state == SIM_CMD_STATE_STOP;
/* TODO: Combine movement from multiple inputs? E.G. a sudden /* TODO: Combine movement from multiple inputs? E.G. a sudden
* start and immediate stop cmd should still move the player a * start and immediate stop cmd should still move the player a
* tad. */ * tad. */
switch (cmd->kind) { switch (cmd->kind) {
case GAME_CMD_KIND_PLAYER_MOVE: case SIM_CMD_KIND_PLAYER_MOVE:
{ {
move = cmd->move_dir; move = cmd->move_dir;
focus = cmd->aim_dir; focus = cmd->aim_dir;
} break; } break;
case GAME_CMD_KIND_PLAYER_FIRE: case SIM_CMD_KIND_PLAYER_FIRE:
{ {
if (start) { if (start) {
firing = true; firing = true;
@ -871,7 +871,7 @@ INTERNAL void game_update(void)
bullet->bullet_knockback = 10; bullet->bullet_knockback = 10;
bullet->mass_unscaled = 0.04f; bullet->mass_unscaled = 0.04f;
bullet->inertia_unscaled = 0.00001f; bullet->inertia_unscaled = 0.00001f;
bullet->layer = GAME_LAYER_BULLETS; bullet->layer = SIM_LAYER_BULLETS;
#if 1 #if 1
/* Point collider */ /* Point collider */
@ -890,7 +890,7 @@ INTERNAL void game_update(void)
{ {
struct entity *tracer = entity_alloc(root); struct entity *tracer = entity_alloc(root);
tracer->tracer_fade_duration = 0.025f; tracer->tracer_fade_duration = 0.025f;
tracer->layer = GAME_LAYER_TRACERS; tracer->layer = SIM_LAYER_TRACERS;
entity_enable_prop(tracer, ENTITY_PROP_TRACER); entity_enable_prop(tracer, ENTITY_PROP_TRACER);
bullet->bullet_tracer = tracer->handle; bullet->bullet_tracer = tracer->handle;
@ -947,7 +947,7 @@ INTERNAL void game_update(void)
* Create forces from control focus (aim) * Create forces from control focus (aim)
* ========================== */ * ========================== */
#if GAME_PLAYER_AIM #if SIM_PLAYER_AIM
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) { for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index]; struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue; if (!entity_is_valid_and_active(ent)) continue;
@ -1082,11 +1082,11 @@ INTERNAL void game_update(void)
/* Mouse drag */ /* Mouse drag */
ctx.dbg_cursor_pos = G.user_cursor; ctx.dbg_cursor_pos = G.user_cursor;
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) { for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
if (cmd->kind == GAME_CMD_KIND_DRAG_OBJECT) { if (cmd->kind == SIM_CMD_KIND_DRAG_OBJECT) {
if (cmd->state == GAME_CMD_STATE_START) { if (cmd->state == SIM_CMD_STATE_START) {
ctx.dbg_start_dragging = true; ctx.dbg_start_dragging = true;
} else if (cmd->state == GAME_CMD_STATE_STOP) { } else if (cmd->state == SIM_CMD_STATE_STOP) {
ctx.dbg_stop_dragging = true; ctx.dbg_stop_dragging = true;
} }
} }
@ -1279,7 +1279,7 @@ INTERNAL void game_update(void)
* Update sound emitters * Update sound emitters
* ========================== */ * ========================== */
/* TODO: Sound entities should be created by game thread, but played by the /* TODO: Sound entities should be created by sim thread, but played by the
* user thread. This is so sounds play at the correct time on the user * user thread. This is so sounds play at the correct time on the user
* thread regardless of interp delay. */ * thread regardless of interp delay. */
@ -1318,14 +1318,14 @@ INTERNAL void game_update(void)
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
/* TODO: Not like this */ /* TODO: Not like this */
struct game_event snapshot_event = ZI; struct sim_event snapshot_event = ZI;
snapshot_event.kind = GAME_EVENT_KIND_SNAPSHOT_FULL; snapshot_event.kind = SIM_EVENT_KIND_SNAPSHOT_FULL;
snapshot_event.snapshot_data = game_string_from_tick(temp.arena, &G.tick); snapshot_event.snapshot_data = sim_string_from_tick(temp.arena, &G.tick);
struct game_event_list l = ZI; struct sim_event_list l = ZI;
l.first = &snapshot_event; l.first = &snapshot_event;
l.last = &snapshot_event; l.last = &snapshot_event;
struct string msg = game_string_from_events(temp.arena, l); struct string msg = sim_string_from_events(temp.arena, l);
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, msg, 0); host_queue_write(G.host, HOST_CHANNEL_ID_ALL, msg, 0);
@ -1333,7 +1333,7 @@ INTERNAL void game_update(void)
} }
host_update(G.host); host_update(G.host);
__profframe("Game"); __profframe("Sim");
/* ========================== * /* ========================== *
* End frame cache scopes * End frame cache scopes
@ -1345,15 +1345,15 @@ INTERNAL void game_update(void)
} }
/* ========================== * /* ========================== *
* Game cmd * Sim cmd
* ========================== */ * ========================== */
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds) struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds)
{ {
__prof; __prof;
struct byte_writer bw = bw_from_arena(arena); struct byte_writer bw = bw_from_arena(arena);
for (struct game_cmd *cmd = cmds.first; cmd; cmd = cmd->next) { for (struct sim_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64)); struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw); u64 start = bw_pos(&bw);
@ -1365,13 +1365,13 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
#endif #endif
switch (cmd->kind) { switch (cmd->kind) {
case GAME_CMD_KIND_PLAYER_MOVE: case SIM_CMD_KIND_PLAYER_MOVE:
{ {
bw_write_v2(&bw, cmd->move_dir); bw_write_v2(&bw, cmd->move_dir);
bw_write_v2(&bw, cmd->aim_dir); bw_write_v2(&bw, cmd->aim_dir);
} break; } break;
case GAME_CMD_KIND_CURSOR_MOVE: case SIM_CMD_KIND_CURSOR_MOVE:
{ {
bw_write_v2(&bw, cmd->cursor_pos); bw_write_v2(&bw, cmd->cursor_pos);
} break; } break;
@ -1386,7 +1386,7 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
return bw_get_written(&bw); return bw_get_written(&bw);
} }
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out) void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out)
{ {
__prof; __prof;
for (u64 i = 0; i < host_events.count; ++i) { for (u64 i = 0; i < host_events.count; ++i) {
@ -1395,8 +1395,8 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
switch (host_event_kind) { switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED: case HOST_EVENT_KIND_CHANNEL_OPENED:
{ {
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd); struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = GAME_CMD_KIND_CLIENT_CONNECT; cmd->kind = SIM_CMD_KIND_CLIENT_CONNECT;
cmd->channel_id = host_event.channel_id; cmd->channel_id = host_event.channel_id;
if (cmds_out->last) { if (cmds_out->last) {
cmds_out->last->next = cmd; cmds_out->last->next = cmd;
@ -1408,8 +1408,8 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
case HOST_EVENT_KIND_CHANNEL_CLOSED: case HOST_EVENT_KIND_CHANNEL_CLOSED:
{ {
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd); struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = GAME_CMD_KIND_CLIENT_DISCONNECT; cmd->kind = SIM_CMD_KIND_CLIENT_DISCONNECT;
cmd->disconnect_reason = LIT("Connection lost"); cmd->disconnect_reason = LIT("Connection lost");
if (cmds_out->last) { if (cmds_out->last) {
cmds_out->last->next = cmd; cmds_out->last->next = cmd;
@ -1423,7 +1423,7 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
{ {
struct byte_reader br = br_from_buffer(host_event.msg); struct byte_reader br = br_from_buffer(host_event.msg);
while (br_bytes_left(&br) > 0) { while (br_bytes_left(&br) > 0) {
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd); struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
u64 cmd_size = br_read_u64(&br); u64 cmd_size = br_read_u64(&br);
u64 cmd_pos_end = br_pos(&br) + cmd_size; u64 cmd_pos_end = br_pos(&br) + cmd_size;
cmd->kind = br_read_i8(&br); cmd->kind = br_read_i8(&br);
@ -1433,13 +1433,13 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
#endif #endif
switch (cmd->kind) { switch (cmd->kind) {
case GAME_CMD_KIND_PLAYER_MOVE: case SIM_CMD_KIND_PLAYER_MOVE:
{ {
cmd->move_dir = br_read_v2(&br); cmd->move_dir = br_read_v2(&br);
cmd->aim_dir = br_read_v2(&br); cmd->aim_dir = br_read_v2(&br);
} break; } break;
case GAME_CMD_KIND_CURSOR_MOVE: case SIM_CMD_KIND_CURSOR_MOVE:
{ {
cmd->cursor_pos = br_read_v2(&br); cmd->cursor_pos = br_read_v2(&br);
} break; } break;
@ -1465,20 +1465,20 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
} }
/* ========================== * /* ========================== *
* Game event * Sim event
* ========================== */ * ========================== */
struct string game_string_from_events(struct arena *arena, struct game_event_list events) struct string sim_string_from_events(struct arena *arena, struct sim_event_list events)
{ {
__prof; __prof;
struct byte_writer bw = bw_from_arena(arena); struct byte_writer bw = bw_from_arena(arena);
for (struct game_event *event = events.first; event; event = event->next) { for (struct sim_event *event = events.first; event; event = event->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64)); struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw); u64 start = bw_pos(&bw);
bw_write_i8(&bw, event->kind); bw_write_i8(&bw, event->kind);
switch (event->kind) { switch (event->kind) {
case GAME_EVENT_KIND_SNAPSHOT_FULL: case SIM_EVENT_KIND_SNAPSHOT_FULL:
{ {
bw_write_string(&bw, event->snapshot_data); bw_write_string(&bw, event->snapshot_data);
} break; } break;
@ -1492,24 +1492,24 @@ struct string game_string_from_events(struct arena *arena, struct game_event_lis
return bw_get_written(&bw); return bw_get_written(&bw);
} }
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out) void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out)
{ {
__prof; __prof;
for (u64 i = 0; i < host_events.count; ++i) { for (u64 i = 0; i < host_events.count; ++i) {
struct game_event *game_event = arena_push_zero(arena, struct game_event); struct sim_event *sim_event = arena_push_zero(arena, struct sim_event);
struct host_event host_event = host_events.events[i]; struct host_event host_event = host_events.events[i];
enum host_event_kind host_event_kind = host_event.kind; enum host_event_kind host_event_kind = host_event.kind;
game_event->channel_id = host_event.channel_id; sim_event->channel_id = host_event.channel_id;
switch (host_event_kind) { switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED: case HOST_EVENT_KIND_CHANNEL_OPENED:
{ {
game_event->kind = GAME_EVENT_KIND_CONNECT; sim_event->kind = SIM_EVENT_KIND_CONNECT;
} break; } break;
case HOST_EVENT_KIND_CHANNEL_CLOSED: case HOST_EVENT_KIND_CHANNEL_CLOSED:
{ {
game_event->kind = GAME_EVENT_KIND_DISCONNECT; sim_event->kind = SIM_EVENT_KIND_DISCONNECT;
game_event->disconnect_reason = LIT("Connection lost"); sim_event->disconnect_reason = LIT("Connection lost");
} break; } break;
case HOST_EVENT_KIND_MSG: case HOST_EVENT_KIND_MSG:
@ -1519,11 +1519,11 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
u64 event_size = br_read_u64(&br); u64 event_size = br_read_u64(&br);
u64 event_pos_end = br_pos(&br) + event_size; u64 event_pos_end = br_pos(&br) + event_size;
game_event->kind = br_read_i8(&br); sim_event->kind = br_read_i8(&br);
switch (game_event->kind) { switch (sim_event->kind) {
case GAME_EVENT_KIND_SNAPSHOT_FULL: case SIM_EVENT_KIND_SNAPSHOT_FULL:
{ {
game_event->snapshot_data = br_read_string(arena, &br); sim_event->snapshot_data = br_read_string(arena, &br);
} break; } break;
default: break; default: break;
@ -1538,11 +1538,11 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
} }
if (events_out->last) { if (events_out->last) {
events_out->last->next = game_event; events_out->last->next = sim_event;
} else { } else {
events_out->first = game_event; events_out->first = sim_event;
} }
events_out->last = game_event; events_out->last = sim_event;
} }
} }
@ -1550,7 +1550,7 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
* Snapshot * Snapshot
* ========================== */ * ========================== */
struct string game_string_from_tick(struct arena *arena, struct world *tick) struct string sim_string_from_tick(struct arena *arena, struct world *tick)
{ {
__prof; __prof;
struct byte_writer bw = bw_from_arena(arena); struct byte_writer bw = bw_from_arena(arena);
@ -1574,7 +1574,7 @@ struct string game_string_from_tick(struct arena *arena, struct world *tick)
return bw_get_written(&bw); return bw_get_written(&bw);
} }
void game_tick_from_string(struct string str, struct world *tick_out) void sim_tick_from_string(struct string str, struct world *tick_out)
{ {
__prof; __prof;
struct byte_reader br = br_from_buffer(str); struct byte_reader br = br_from_buffer(str);
@ -1606,19 +1606,19 @@ void game_tick_from_string(struct string str, struct world *tick_out)
} }
/* ========================== * /* ========================== *
* Game thread * Sim thread
* ========================== */ * ========================== */
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg) INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg)
{ {
(UNUSED)arg; (UNUSED)arg;
i64 last_frame_ns = 0; i64 last_frame_ns = 0;
i64 target_dt_ns = NS_FROM_SECONDS(GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0); i64 target_dt_ns = NS_FROM_SECONDS(SIM_FPS > (0) ? (1.0 / SIM_FPS) : 0);
while (!atomic_i32_eval(&G.game_thread_shutdown)) { while (!atomic_i32_eval(&G.sim_thread_shutdown)) {
__profscope(game_update_w_sleep); __profscope(sim_update_w_sleep);
sleep_frame(last_frame_ns, target_dt_ns); sleep_frame(last_frame_ns, target_dt_ns);
last_frame_ns = sys_time_ns(); last_frame_ns = sys_time_ns();
game_update(); sim_update();
} }
} }

135
src/sim.h Normal file
View File

@ -0,0 +1,135 @@
#ifndef SIM_H
#define SIM_H
#include "host.h"
struct world;
struct mixer_startup_receipt;
struct sprite_startup_receipt;
struct sound_startup_receipt;
struct phys_startup_receipt;
struct host_startup_receipt;
/* 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
struct sim_startup_receipt { i32 _; };
struct sim_startup_receipt sim_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr,
struct sound_startup_receipt *sound_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr);
/* ========================== *
* Sim cmd
* ========================== */
enum sim_cmd_state {
SIM_CMD_STATE_STOP = -1,
SIM_CMD_STATE_NO_CHANGE = 0,
SIM_CMD_STATE_START = 1
};
enum sim_cmd_kind {
SIM_CMD_KIND_NONE,
SIM_CMD_KIND_PLAYER_MOVE,
SIM_CMD_KIND_PLAYER_FIRE,
SIM_CMD_KIND_CLIENT_CONNECT,
SIM_CMD_KIND_CLIENT_DISCONNECT,
/* Testing */
SIM_CMD_KIND_CLEAR_ALL,
SIM_CMD_KIND_SPAWN_TEST,
SIM_CMD_KIND_PAUSE,
SIM_CMD_KIND_STEP,
SIM_CMD_KIND_DRAG_OBJECT,
SIM_CMD_KIND_CURSOR_MOVE,
SIM_CMD_KIND_COUNT
};
struct sim_cmd {
enum sim_cmd_kind kind;
enum sim_cmd_state state;
struct host_channel_id channel_id;
/* SIM_CMD_KIND_PLAYER_MOVE */
struct v2 move_dir;
struct v2 aim_dir;
/* SIM_CMD_KIND_CURSOR_MOVE */
struct v2 cursor_pos;
/* SIM_CMD_KIND_PLAYER_DISCONNECT */
struct string disconnect_reason;
#if RTC
u32 collider_gjk_steps;
#endif
struct sim_cmd *next;
};
struct sim_cmd_list {
struct sim_cmd *first;
struct sim_cmd *last;
};
struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds);
void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out);
/* ========================== *
* Sim event
* ========================== */
enum sim_event_kind {
SIM_EVENT_KIND_NONE,
SIM_EVENT_KIND_CONNECT,
SIM_EVENT_KIND_DISCONNECT,
SIM_EVENT_KIND_SNAPSHOT_FULL,
//SIM_EVENT_KIND_ENTITY_UPDATE,
//SIM_EVENT_KIND_ENTITY_CREATE,
//SIM_EVENT_KIND_ENTITY_DESTROY
};
struct sim_event {
enum sim_event_kind kind;
struct host_channel_id channel_id;
struct string snapshot_data;
struct string disconnect_reason;
//struct entity_handle entity;
//struct string update_data;
struct sim_event *next;
};
struct sim_event_list {
struct sim_event *first;
struct sim_event *last;
};
struct string sim_string_from_events(struct arena *arena, struct sim_event_list events);
void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out);
/* ========================== *
* Snapshot
* ========================== */
struct string sim_string_from_tick(struct arena *arena, struct world *tick);
void sim_tick_from_string(struct string str, struct world *tick_out);
#endif

View File

@ -6,7 +6,7 @@
#include "draw.h" #include "draw.h"
#include "intrinsics.h" #include "intrinsics.h"
#include "app.h" #include "app.h"
#include "game.h" #include "sim.h"
#include "asset_cache.h" #include "asset_cache.h"
#include "string.h" #include "string.h"
#include "scratch.h" #include "scratch.h"
@ -148,7 +148,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct font_startup_receipt *font_sr, struct font_startup_receipt *font_sr,
struct sprite_startup_receipt *sprite_sr, struct sprite_startup_receipt *sprite_sr,
struct draw_startup_receipt *draw_sr, struct draw_startup_receipt *draw_sr,
struct game_startup_receipt *game_sr, struct sim_startup_receipt *sim_sr,
struct asset_cache_startup_receipt *asset_cache_sr, struct asset_cache_startup_receipt *asset_cache_sr,
struct mixer_startup_receipt *mixer_sr, struct mixer_startup_receipt *mixer_sr,
struct host_startup_receipt *host_sr, struct host_startup_receipt *host_sr,
@ -159,7 +159,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
(UNUSED)font_sr; (UNUSED)font_sr;
(UNUSED)sprite_sr; (UNUSED)sprite_sr;
(UNUSED)draw_sr; (UNUSED)draw_sr;
(UNUSED)game_sr; (UNUSED)sim_sr;
(UNUSED)asset_cache_sr; (UNUSED)asset_cache_sr;
(UNUSED)mixer_sr; (UNUSED)mixer_sr;
(UNUSED)host_sr; (UNUSED)host_sr;
@ -227,7 +227,7 @@ INTERNAL SYS_WINDOW_EVENT_CALLBACK_FUNC_DEF(window_event_callback, event)
} }
/* ========================== * /* ========================== *
* Game -> user communication * Sim -> user communication
* ========================== */ * ========================== */
#if 0 #if 0
@ -293,12 +293,12 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
struct world *from_tick; struct world *from_tick;
struct world *to_tick; struct world *to_tick;
if (newest_tick && game_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) { if (newest_tick && sim_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
/* Pull new tick from game thread if necessary */ /* Pull new tick from sim thread if necessary */
if (!newest_tick || game_get_latest_tick_id() > newest_tick->tick_id) { if (!newest_tick || sim_get_latest_tick_id() > newest_tick->tick_id) {
struct blend_tick *latest_bt = blend_tick_alloc(); struct blend_tick *latest_bt = blend_tick_alloc();
newest_tick = &latest_bt->world; newest_tick = &latest_bt->world;
game_get_latest_tick(newest_tick); sim_get_latest_tick(newest_tick);
} }
/* Find oldest tick */ /* Find oldest tick */
@ -365,7 +365,7 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
/* Allocate new blend tick */ /* Allocate new blend tick */
struct blend_tick *bt = blend_tick_alloc(); struct blend_tick *bt = blend_tick_alloc();
struct world *tick = &bt->world; struct world *tick = &bt->world;
game_get_latest_tick(tick); sim_get_latest_tick(tick);
from_tick = tick; from_tick = tick;
to_tick = tick; to_tick = tick;
@ -472,9 +472,9 @@ INTERNAL SORT_COMPARE_FUNC_DEF(entity_draw_order_cmp, arg_a, arg_b, udata)
INTERNAL void queue_game_cmd(struct arena *arena, struct game_cmd_list *list, struct game_cmd src) INTERNAL void queue_sim_cmd(struct arena *arena, struct sim_cmd_list *list, struct sim_cmd src)
{ {
struct game_cmd *cmd = arena_push(arena, struct game_cmd); struct sim_cmd *cmd = arena_push(arena, struct sim_cmd);
*cmd = src; *cmd = src;
if (list->last) { if (list->last) {
list->last->next = cmd; list->last->next = cmd;
@ -519,19 +519,19 @@ INTERNAL void user_update(void)
struct entity_store *store = G.world.entity_store; struct entity_store *store = G.world.entity_store;
struct sprite_scope *sprite_frame_scope = sprite_scope_begin(); struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
struct game_cmd_list cmd_list = ZI; struct sim_cmd_list cmd_list = ZI;
#if 0 #if 0
/* ========================== * /* ========================== *
* Interpolate between game ticks * Interpolate between sim ticks
* ========================== */ * ========================== */
{ {
__profscope(interpolate_ticks); __profscope(interpolate_ticks);
#if USER_INTERP_ENABLED #if USER_INTERP_ENABLED
/* TODO: Use actual fps of game thread (will differ from GAME_FPS if game thread is lagging) to hide lag with slow-motion? */ /* TODO: Use actual fps of sim thread (will differ from SIM_FPS if sim thread is lagging) to hide lag with slow-motion? */
i64 blend_time_offset_ns = NS_FROM_SECONDS((1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO); i64 blend_time_offset_ns = NS_FROM_SECONDS((1.0 / SIM_FPS) * USER_INTERP_OFFSET_TICK_RATIO);
i64 blend_time_ns = G.time_ns > blend_time_offset_ns ? G.time_ns - blend_time_offset_ns : 0; i64 blend_time_ns = G.time_ns > blend_time_offset_ns ? G.time_ns - blend_time_offset_ns : 0;
/* Pull ticks */ /* Pull ticks */
@ -573,7 +573,7 @@ INTERNAL void user_update(void)
e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, tick_blend); e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, tick_blend);
if (e->is_top) { if (e->is_top) {
/* TODO: Cache parent & child xforms in game thread */ /* TODO: Cache parent & child xforms in sim thread */
struct xform e0_xf = entity_get_xform(e0); struct xform e0_xf = entity_get_xform(e0);
struct xform e1_xf = entity_get_xform(e1); struct xform e1_xf = entity_get_xform(e1);
entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend)); entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend));
@ -610,17 +610,17 @@ INTERNAL void user_update(void)
#endif #endif
/* ========================== * /* ========================== *
* Process host events into game events * Process host events into sim events
* ========================== */ * ========================== */
struct game_event_list game_events = ZI; struct sim_event_list sim_events = ZI;
{ {
struct host_event_array host_events = host_pop_events(scratch.arena, G.host); struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
game_events_from_host_events(scratch.arena, host_events, &game_events); sim_events_from_host_events(scratch.arena, host_events, &sim_events);
} }
/* ========================== * /* ========================== *
* Process game events * Process sim events
* ========================== */ * ========================== */
{ {
@ -632,24 +632,24 @@ INTERNAL void user_update(void)
last_try_connect = now; last_try_connect = now;
} }
for (struct game_event *event = game_events.first; event; event = event->next) { for (struct sim_event *event = sim_events.first; event; event = event->next) {
enum game_event_kind kind = event->kind; enum sim_event_kind kind = event->kind;
switch (kind) { switch (kind) {
case GAME_EVENT_KIND_CONNECT: case SIM_EVENT_KIND_CONNECT:
{ {
last_try_connect = F64_INFINITY; last_try_connect = F64_INFINITY;
} break; } break;
case GAME_EVENT_KIND_DISCONNECT: case SIM_EVENT_KIND_DISCONNECT:
{ {
last_try_connect = 0; last_try_connect = 0;
} break; } break;
case GAME_EVENT_KIND_SNAPSHOT_FULL: case SIM_EVENT_KIND_SNAPSHOT_FULL:
{ {
struct string snapshot_data = event->snapshot_data; struct string snapshot_data = event->snapshot_data;
game_tick_from_string(snapshot_data, &G.world); sim_tick_from_string(snapshot_data, &G.world);
} break; } break;
default: break; default: break;
@ -759,8 +759,8 @@ INTERNAL void user_update(void)
{ {
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR]; struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
if (state.num_presses) { if (state.num_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_CLEAR_ALL .kind = SIM_CMD_KIND_CLEAR_ALL
}); });
} }
} }
@ -769,8 +769,8 @@ INTERNAL void user_update(void)
{ {
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE]; struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
if (state.num_presses) { if (state.num_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_PAUSE .kind = SIM_CMD_KIND_PAUSE
}); });
} }
} }
@ -779,8 +779,8 @@ INTERNAL void user_update(void)
{ {
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP]; struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) { for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_STEP .kind = SIM_CMD_KIND_STEP
}); });
} }
} }
@ -789,8 +789,8 @@ INTERNAL void user_update(void)
{ {
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN]; struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
if (state.num_presses) { if (state.num_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_SPAWN_TEST .kind = SIM_CMD_KIND_SPAWN_TEST
}); });
} }
} }
@ -1554,15 +1554,15 @@ INTERNAL void user_update(void)
struct v2 input_aim_dir = v2_sub(G.world_cursor, entity_get_xform(active_player).og); struct v2 input_aim_dir = v2_sub(G.world_cursor, entity_get_xform(active_player).og);
/* Queue cursor move cmd */ /* Queue cursor move cmd */
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_CURSOR_MOVE, .kind = SIM_CMD_KIND_CURSOR_MOVE,
.cursor_pos = G.world_cursor .cursor_pos = G.world_cursor
}); });
/* Queue player input cmd */ /* Queue player input cmd */
if (!G.debug_camera) { if (!G.debug_camera) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_PLAYER_MOVE, .kind = SIM_CMD_KIND_PLAYER_MOVE,
.move_dir = input_move_dir, .move_dir = input_move_dir,
.aim_dir = input_aim_dir .aim_dir = input_aim_dir
}); });
@ -1571,18 +1571,18 @@ INTERNAL void user_update(void)
/* Queue player fire cmd */ /* Queue player fire cmd */
i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases; i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases;
if (!G.debug_camera && fire_presses) { if (!G.debug_camera && fire_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_PLAYER_FIRE, .kind = SIM_CMD_KIND_PLAYER_FIRE,
.state = fire_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP .state = fire_presses > 0 ? SIM_CMD_STATE_START : SIM_CMD_STATE_STOP
}); });
} }
/* Queue physics drag cmd */ /* Queue physics drag cmd */
i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases; i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases;
if (drag_presses) { if (drag_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = GAME_CMD_KIND_DRAG_OBJECT, .kind = SIM_CMD_KIND_DRAG_OBJECT,
.state = drag_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP .state = drag_presses > 0 ? SIM_CMD_STATE_START : SIM_CMD_STATE_STOP
}); });
} }
@ -1689,11 +1689,11 @@ INTERNAL void user_update(void)
} }
/* Publish game cmds */ /* Publish sim cmds */
{ {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
struct string cmds_str = game_string_from_cmds(temp.arena, cmd_list); struct string cmds_str = sim_string_from_cmds(temp.arena, cmd_list);
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, cmds_str, 0); host_queue_write(G.host, HOST_CHANNEL_ID_ALL, cmds_str, 0);
arena_temp_end(temp); arena_temp_end(temp);

View File

@ -7,7 +7,7 @@ struct renderer_startup_receipt;
struct font_startup_receipt; struct font_startup_receipt;
struct sprite_startup_receipt; struct sprite_startup_receipt;
struct draw_startup_receipt; struct draw_startup_receipt;
struct game_startup_receipt; struct sim_startup_receipt;
struct asset_cache_startup_receipt; struct asset_cache_startup_receipt;
struct mixer_startup_receipt; struct mixer_startup_receipt;
struct host_startup_receipt; struct host_startup_receipt;
@ -54,7 +54,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct font_startup_receipt *font_sr, struct font_startup_receipt *font_sr,
struct sprite_startup_receipt *sprite_sr, struct sprite_startup_receipt *sprite_sr,
struct draw_startup_receipt *draw_sr, struct draw_startup_receipt *draw_sr,
struct game_startup_receipt *game_sr, struct sim_startup_receipt *sim_sr,
struct asset_cache_startup_receipt *asset_cache_sr, struct asset_cache_startup_receipt *asset_cache_sr,
struct mixer_startup_receipt *mixer_sr, struct mixer_startup_receipt *mixer_sr,
struct host_startup_receipt *host_sr, struct host_startup_receipt *host_sr,