migrate sim global state to ctx structure

This commit is contained in:
jacob 2025-02-08 12:00:27 -06:00
parent 5f75b765c3
commit ed66382fd6
13 changed files with 525 additions and 510 deletions

View File

@ -223,8 +223,7 @@ void app_entry_point(void)
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 phys_startup_receipt phys_sr = phys_startup();
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, &sim_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, &asset_cache_sr, &sound_sr, &mixer_sr, &phys_sr, &host_sr, &window);
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
(UNUSED)user_sr;

View File

@ -33,7 +33,6 @@
#define SPACE_CELL_BUCKETS_SQRT (256)
#define SPACE_CELL_SIZE 1.0f
#define SIM_FPS 50.0
#define SIM_TIMESCALE 1

View File

@ -1172,7 +1172,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
if (ctx->pre_solve_callback) {
__profscope(pre_solve_callback);
ctx->pre_solve_callback(collision_data);
ctx->pre_solve_callback(collision_data, ctx->pre_solve_callback_udata);
}
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
@ -1204,7 +1204,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
if (ctx->post_solve_callback) {
__profscope(post_solve_callback);
ctx->post_solve_callback(collision_data);
ctx->post_solve_callback(collision_data, ctx->post_solve_callback_udata);
}
scratch_end(scratch);

View File

@ -25,8 +25,8 @@ struct phys_collision_data_array {
};
struct phys_collision_data;
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg) void name(struct phys_collision_data_array arg)
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, data);
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_udata) void name(struct phys_collision_data_array arg_collision_data, void *arg_udata)
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, udata);
/* Structure containing data used for a single physics step */
struct phys_ctx {
@ -37,6 +37,8 @@ struct phys_ctx {
phys_collision_callback_func *pre_solve_callback;
phys_collision_callback_func *post_solve_callback;
void *pre_solve_callback_udata;
void *post_solve_callback_udata;
struct sim_ent_lookup *debug_lookup;
struct v2 dbg_cursor_pos;

461
src/sim.c
View File

@ -1,12 +1,11 @@
#include "sim.h"
#include "sim_ent.h"
#include "sim_client.h"
#include "sim_msg.h"
#include "sys.h"
#include "util.h"
#include "world.h"
#include "sprite.h"
#include "sound.h"
#include "mixer.h"
#include "math.h"
#include "scratch.h"
#include "atomic.h"
@ -19,7 +18,8 @@
#include "byteio.h"
#include "host.h"
GLOBAL struct {
struct sim_ctx {
struct arena arena;
struct atomic_i32 sim_thread_shutdown;
struct sys_thread sim_thread;
@ -48,76 +48,75 @@ GLOBAL struct {
/* Tick */
struct world tick;
} G = ZI, DEBUG_ALIAS(G, G_sim);
};
/* ========================== *
* Startup
* Ctx
* ========================== */
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown);
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg);
INTERNAL void reset_world(void);
INTERNAL void reset_world(struct sim_ctx *ctx);
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)
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr,
u16 host_port)
{
(UNUSED)mixer_sr;
(UNUSED)sheet_sr;
(UNUSED)sound_sr;
struct arena arena = arena_alloc(GIGABYTE(64));
struct sim_ctx *ctx = arena_push_zero(&arena, struct sim_ctx);
ctx->arena = arena;
(UNUSED)sprite_sr;
(UNUSED)phys_sr;
(UNUSED)host_sr;
G.client_store = client_store_alloc();
ctx->client_store = sim_client_store_alloc();
/* Intialize host */
G.host = host_alloc(12345);
ctx->host = host_alloc(host_port);
/* Initialize empty world */
reset_world();
reset_world(ctx);
G.sim_thread = sys_thread_alloc(&sim_thread_entry_point, NULL, LIT("[P2] Sim thread"));
app_register_exit_callback(&sim_shutdown);
ctx->sim_thread = sys_thread_alloc(&sim_thread_entry_point, ctx, LIT("[P2] Sim thread"));
return (struct sim_startup_receipt) { 0 };
return ctx;
}
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown)
void sim_ctx_release(struct sim_ctx *ctx)
{
__prof;
atomic_i32_eval_exchange(&G.sim_thread_shutdown, true);
sys_thread_wait_release(&G.sim_thread);
atomic_i32_eval_exchange(&ctx->sim_thread_shutdown, true);
sys_thread_wait_release(&ctx->sim_thread);
}
/* ========================== *
* Reset
* ========================== */
INTERNAL void reset_world(void)
INTERNAL void reset_world(struct sim_ctx *ctx)
{
if (G.tick.ent_store) {
if (ctx->tick.ent_store) {
/* Release world */
world_release(&G.tick);
world_release(&ctx->tick);
/* Release bookkeeping */
space_release(G.space);
space_release(ctx->space);
#if COLLIDER_DEBUG
sim_ent_lookup_release(&G.collision_debug_lookup);
sim_ent_lookup_release(&ctx->collision_debug_lookup);
#endif
sim_ent_lookup_release(&G.contact_lookup);
sim_ent_lookup_release(&ctx->contact_lookup);
}
/* Create bookkeeping */
G.contact_lookup = sim_ent_lookup_alloc(4096);
ctx->contact_lookup = sim_ent_lookup_alloc(4096);
#if COLLIDER_DEBUG
G.collision_debug_lookup = sim_ent_lookup_alloc(4096);
ctx->collision_debug_lookup = sim_ent_lookup_alloc(4096);
#endif
G.space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BUCKETS_SQRT);
ctx->space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BUCKETS_SQRT);
/* Re-create world */
world_alloc(&G.tick);
G.tick.timescale = SIM_TIMESCALE;
world_alloc(&ctx->tick);
ctx->tick.timescale = SIM_TIMESCALE;
}
/* ========================== *
@ -126,15 +125,15 @@ INTERNAL void reset_world(void)
/* TODO: Remove this */
INTERNAL void spawn_test_entities(void)
INTERNAL void spawn_test_entities(struct sim_ctx *ctx)
{
struct sim_ent *root = sim_ent_from_handle(G.tick.ent_store, G.tick.ent_store->root);
struct sim_ent *root = sim_ent_from_handle(ctx->tick.ent_store, ctx->tick.ent_store->root);
root->mass_unscaled = F32_INFINITY;
root->inertia_unscaled = F32_INFINITY;
/* Player */
struct sim_ent *player_ent = sim_ent_nil();
//if (!G.extra_spawn) {
//if (!ctx->extra_spawn) {
{
struct sim_ent *e = sim_ent_alloc(root);
@ -148,7 +147,7 @@ INTERNAL void spawn_test_entities(void)
//f32 r = PI / 4;
f32 r = 0;
if (!G.extra_spawn) {
if (!ctx->extra_spawn) {
sim_ent_enable_prop(e, SIM_ENT_PROP_PLAYER_CONTROLLED);
sim_ent_enable_prop(e, SIM_ENT_PROP_TEST);
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
@ -280,7 +279,7 @@ INTERNAL void spawn_test_entities(void)
}
/* Camera */
if (!G.extra_spawn && player_ent->valid) {
if (!ctx->extra_spawn && player_ent->valid) {
struct sim_ent *e = sim_ent_alloc(root);
sim_ent_set_xform(e, XFORM_IDENT);
@ -293,18 +292,18 @@ INTERNAL void spawn_test_entities(void)
e->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
}
G.extra_spawn = true;
ctx->extra_spawn = true;
}
/* ========================== *
* Release entities
* ========================== */
INTERNAL void release_entities_with_prop(enum sim_ent_prop prop)
INTERNAL void release_entities_with_prop(struct sim_ctx *ctx, enum sim_ent_prop prop)
{
struct temp_arena scratch = scratch_begin_no_conflict();
struct sim_ent_store *store = G.tick.ent_store;
struct space *space = G.space;
struct sim_ent_store *store = ctx->tick.ent_store;
struct space *space = ctx->space;
struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *);
u64 ents_to_release_count = 0;
@ -347,13 +346,14 @@ INTERNAL void release_entities_with_prop(enum sim_ent_prop prop)
* Respond to physics collisions
* ========================== */
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, udata)
{
struct sim_ent_store *store = G.tick.ent_store;
struct sim_ctx *ctx = (struct sim_ctx *)udata;
struct sim_ent_store *store = ctx->tick.ent_store;
struct sim_ent *root = sim_ent_from_handle(store, store->root);
for (u64 i = 0; i < array.count; ++i) {
struct phys_collision_data *data = &array.a[i];
for (u64 i = 0; i < collision_data_array.count; ++i) {
struct phys_collision_data *data = &collision_data_array.a[i];
struct phys_contact_constraint *constraint = data->constraint;
struct sim_ent *e0 = sim_ent_from_handle(store, data->e0);
@ -434,7 +434,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
* Update
* ========================== */
INTERNAL void sim_update(void)
INTERNAL void sim_update(struct sim_ctx *ctx)
{
__prof;
@ -444,31 +444,31 @@ INTERNAL void sim_update(void)
* Reset level if necessary
* ========================== */
if (G.should_reset_level) {
if (ctx->should_reset_level) {
logf_info("Clearing level");
G.should_reset_level = false;
G.extra_spawn = false;
reset_world();
ctx->should_reset_level = false;
ctx->extra_spawn = false;
reset_world(ctx);
}
/* ========================== *
* Begin frame
* ========================== */
++G.tick.tick_id;
++ctx->tick.tick_id;
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;
ctx->tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / SIM_FPS) * ctx->tick.timescale));
ctx->tick.time_ns += ctx->tick.dt_ns;
f64 dt = SECONDS_FROM_NS(G.tick.dt_ns);
f64 time = SECONDS_FROM_NS(G.tick.time_ns);
G.sprite_frame_scope = sprite_scope_begin();
G.root = sim_ent_from_handle(G.tick.ent_store, G.tick.ent_store->root);
f64 dt = SECONDS_FROM_NS(ctx->tick.dt_ns);
f64 time = SECONDS_FROM_NS(ctx->tick.time_ns);
ctx->sprite_frame_scope = sprite_scope_begin();
ctx->root = sim_ent_from_handle(ctx->tick.ent_store, ctx->tick.ent_store->root);
struct sim_ent *root = G.root;
struct sim_ent_store *ent_store = G.tick.ent_store;
struct space *space = G.space;
struct sprite_scope *sprite_frame_scope = G.sprite_frame_scope;
struct sim_ent *root = ctx->root;
struct sim_ent_store *ent_store = ctx->tick.ent_store;
struct space *space = ctx->space;
struct sprite_scope *sprite_frame_scope = ctx->sprite_frame_scope;
(UNUSED)dt;
(UNUSED)time;
@ -483,7 +483,7 @@ INTERNAL void sim_update(void)
static b32 run = 0;
if (!run) {
run = 1;
spawn_test_entities();
spawn_test_entities(ctx);
}
}
@ -491,7 +491,7 @@ INTERNAL void sim_update(void)
* Release entities
* ========================== */
release_entities_with_prop(SIM_ENT_PROP_RELEASE_NEXT_TICK);
release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE_NEXT_TICK);
/* ========================== *
* Activate entities
@ -503,8 +503,8 @@ INTERNAL void sim_update(void)
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) {
u64 atick = ent->activation_tick;
if (atick != 0 || G.tick.tick_id >= atick) {
sim_ent_activate(ent, G.tick.tick_id);
if (atick != 0 || ctx->tick.tick_id >= atick) {
sim_ent_activate(ent, ctx->tick.tick_id);
}
}
}
@ -532,7 +532,7 @@ INTERNAL void sim_update(void)
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, ctx->host);
sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
}
@ -544,26 +544,26 @@ INTERNAL void sim_update(void)
enum sim_cmd_kind kind = cmd->kind;
struct host_channel_id channel_id = cmd->channel_id;
struct sim_client *client = client_from_channel_id(G.client_store, channel_id);
struct sim_client *client = sim_client_from_channel_id(ctx->client_store, channel_id);
if (client->valid || host_channel_id_is_nil(channel_id)) {
switch (kind) {
/* Cursor */
case SIM_CMD_KIND_CURSOR_MOVE:
{
G.user_cursor = cmd->cursor_pos;
ctx->user_cursor = cmd->cursor_pos;
} break;
/* Clear level */
case SIM_CMD_KIND_CLEAR_ALL:
{
G.should_reset_level = true;
ctx->should_reset_level = true;
} break;
/* Spawn test */
case SIM_CMD_KIND_SPAWN_TEST:
{
logf_info("Spawning (test)");
spawn_test_entities();
spawn_test_entities(ctx);
} break;
/* Disconnect client */
@ -574,9 +574,9 @@ INTERNAL void sim_update(void)
if (client_ent->valid) {
sim_ent_disable_prop(client_ent, SIM_ENT_PROP_PLAYER_CONTROLLED);
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_RELEASE_NEXT_TICK);
host_queue_disconnect(G.host, channel_id);
host_queue_disconnect(ctx->host, channel_id);
}
client_release(client);
sim_client_release(client);
}
} break;
@ -584,7 +584,7 @@ INTERNAL void sim_update(void)
};
} else if (kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) {
/* Connect client */
client = client_alloc(G.client_store, channel_id);
client = sim_client_alloc(ctx->client_store, channel_id);
struct sim_ent *client_ent = sim_ent_alloc(root);
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_PLAYER_CONTROLLED);
client_ent->controlling_client = client->handle;
@ -676,7 +676,7 @@ INTERNAL void sim_update(void)
#endif
ent->local_collider.count = 3;
ent->local_collider.radius = 0.25;
//ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3);
//ent->local_collider.radius = math_fabs(math_sin(ctx->tick.time) / 3);
#else
//ent->local_collider.radius = 0.5;
ent->local_collider.radius = 0.25;
@ -729,7 +729,7 @@ INTERNAL void sim_update(void)
b32 start = cmd->state == SIM_CMD_STATE_START;
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.ctx-> a sudden
* start and immediate stop cmd should still move the player a
* tad. */
switch (cmd->kind) {
@ -1071,30 +1071,31 @@ INTERNAL void sim_update(void)
* ========================== */
{
struct phys_ctx ctx = ZI;
ctx.tick_id = G.tick.tick_id;
ctx.store = ent_store;
ctx.space = space;
ctx.contact_lookup = &G.contact_lookup;
ctx.pre_solve_callback = on_collision;
struct phys_ctx phys = ZI;
phys.tick_id = ctx->tick.tick_id;
phys.store = ent_store;
phys.space = space;
phys.contact_lookup = &ctx->contact_lookup;
phys.pre_solve_callback = on_collision;
phys.pre_solve_callback_udata = ctx;
#if COLLIDER_DEBUG
ctx.debug_lookup = &G.collision_debug_lookup;
phys.debug_lookup = &phys->collision_debug_lookup;
#endif
/* Mouse drag */
ctx.dbg_cursor_pos = G.user_cursor;
phys.dbg_cursor_pos = ctx->user_cursor;
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
if (cmd->kind == SIM_CMD_KIND_DRAG_OBJECT) {
if (cmd->state == SIM_CMD_STATE_START) {
ctx.dbg_start_dragging = true;
phys.dbg_start_dragging = true;
} else if (cmd->state == SIM_CMD_STATE_STOP) {
ctx.dbg_stop_dragging = true;
phys.dbg_stop_dragging = true;
}
}
}
/* Step */
G.last_phys_iteration = phys_step(&ctx, dt, G.last_phys_iteration);
ctx->last_phys_iteration = phys_step(&phys, dt, ctx->last_phys_iteration);
}
/* ========================== *
@ -1130,7 +1131,7 @@ INTERNAL void sim_update(void)
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue;
if (ent->activation_tick == G.tick.tick_id) {
if (ent->activation_tick == ctx->tick.tick_id) {
struct sim_ent *src = sim_ent_from_handle(ent_store, ent->bullet_src);
struct xform src_xf = sim_ent_get_xform(src);
@ -1276,6 +1277,7 @@ INTERNAL void sim_update(void)
arena_temp_end(temp);
}
#if 0
/* ========================== *
* Update sound emitters
* ========================== */
@ -1290,7 +1292,7 @@ INTERNAL void sim_update(void)
if (sim_ent_has_prop(ent, SIM_ENT_PROP_TEST_SOUND_EMITTER)) {
struct mixer_desc desc = ent->sound_desc;
desc.speed = G.tick.timescale;
desc.speed = ctx->tick.timescale;
desc.pos = sim_ent_get_xform(ent).og;
struct sound *sound = sound_load_async(ent->sound_name, 0);
@ -1304,12 +1306,13 @@ INTERNAL void sim_update(void)
}
}
}
#endif
/* ========================== *
* Release entities
* ========================== */
release_entities_with_prop(SIM_ENT_PROP_RELEASE_THIS_TICK);
release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE_THIS_TICK);
/* ========================== *
* Publish tick
@ -1321,19 +1324,19 @@ INTERNAL void sim_update(void)
/* TODO: Not like this */
struct sim_event snapshot_event = ZI;
snapshot_event.kind = SIM_EVENT_KIND_SNAPSHOT_FULL;
snapshot_event.snapshot_data = sim_string_from_tick(temp.arena, &G.tick);
snapshot_event.snapshot_data = sim_string_from_tick(temp.arena, &ctx->tick);
struct sim_event_list l = ZI;
l.first = &snapshot_event;
l.last = &snapshot_event;
struct string msg = sim_string_from_events(temp.arena, l);
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, msg, 0);
host_queue_write(ctx->host, HOST_CHANNEL_ID_ALL, msg, 0);
arena_temp_end(temp);
}
host_update(G.host);
host_update(ctx->host);
__profframe("Sim");
/* ========================== *
@ -1345,281 +1348,19 @@ INTERNAL void sim_update(void)
scratch_end(scratch);
}
/* ========================== *
* Sim cmd
* ========================== */
struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
for (struct sim_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw);
bw_write_i8(&bw, cmd->kind);
bw_write_i8(&bw, cmd->state);
#if COLLIDER_DEBUG
bw_write_u32(&bw, cmd->collider_gjk_steps);
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
{
bw_write_v2(&bw, cmd->move_dir);
bw_write_v2(&bw, cmd->aim_dir);
} break;
case SIM_CMD_KIND_CURSOR_MOVE:
{
bw_write_v2(&bw, cmd->cursor_pos);
} break;
default: break;
}
u64 size = bw_pos(&bw) - start;
bw_write_u64(&bw_size, size);
}
return bw_get_written(&bw);
}
void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out)
{
__prof;
for (u64 i = 0; i < host_events.count; ++i) {
struct host_event host_event = host_events.events[i];
enum host_event_kind host_event_kind = host_event.kind;
switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED:
{
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = SIM_CMD_KIND_SIM_CLIENT_CONNECT;
cmd->channel_id = host_event.channel_id;
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
} break;
case HOST_EVENT_KIND_CHANNEL_CLOSED:
{
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = SIM_CMD_KIND_SIM_CLIENT_DISCONNECT;
cmd->disconnect_reason = LIT("Connection lost");
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
} break;
case HOST_EVENT_KIND_MSG:
{
struct byte_reader br = br_from_buffer(host_event.msg);
while (br_bytes_left(&br) > 0) {
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
u64 cmd_size = br_read_u64(&br);
u64 cmd_pos_end = br_pos(&br) + cmd_size;
cmd->kind = br_read_i8(&br);
cmd->state = br_read_i8(&br);
#if COLLIDER_DEBUG
cmd->collider_gjk_steps = br_read_u32(&br);
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
{
cmd->move_dir = br_read_v2(&br);
cmd->aim_dir = br_read_v2(&br);
} break;
case SIM_CMD_KIND_CURSOR_MOVE:
{
cmd->cursor_pos = br_read_v2(&br);
} break;
default: break;
}
ASSERT(br_pos(&br) == cmd_pos_end);
br_seek_to(&br, cmd_pos_end);
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
}
} break;
default: break;
}
}
}
/* ========================== *
* Sim event
* ========================== */
struct string sim_string_from_events(struct arena *arena, struct sim_event_list events)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
for (struct sim_event *event = events.first; event; event = event->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw);
bw_write_i8(&bw, event->kind);
switch (event->kind) {
case SIM_EVENT_KIND_SNAPSHOT_FULL:
{
bw_write_string(&bw, event->snapshot_data);
} break;
default: break;
}
u64 size = bw_pos(&bw) - start;
bw_write_u64(&bw_size, size);
}
return bw_get_written(&bw);
}
void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out)
{
__prof;
for (u64 i = 0; i < host_events.count; ++i) {
struct sim_event *sim_event = arena_push_zero(arena, struct sim_event);
struct host_event host_event = host_events.events[i];
enum host_event_kind host_event_kind = host_event.kind;
sim_event->channel_id = host_event.channel_id;
switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED:
{
sim_event->kind = SIM_EVENT_KIND_CONNECT;
} break;
case HOST_EVENT_KIND_CHANNEL_CLOSED:
{
sim_event->kind = SIM_EVENT_KIND_DISCONNECT;
sim_event->disconnect_reason = LIT("Connection lost");
} break;
case HOST_EVENT_KIND_MSG:
{
struct byte_reader br = br_from_buffer(host_event.msg);
while (br_bytes_left(&br) > 0) {
u64 event_size = br_read_u64(&br);
u64 event_pos_end = br_pos(&br) + event_size;
sim_event->kind = br_read_i8(&br);
switch (sim_event->kind) {
case SIM_EVENT_KIND_SNAPSHOT_FULL:
{
sim_event->snapshot_data = br_read_string(arena, &br);
} break;
default: break;
}
ASSERT(br_pos(&br) == event_pos_end);
br_seek_to(&br, event_pos_end);
}
} break;
default: break;
}
if (events_out->last) {
events_out->last->next = sim_event;
} else {
events_out->first = sim_event;
}
events_out->last = sim_event;
}
}
/* ========================== *
* Snapshot
* ========================== */
struct string sim_string_from_tick(struct arena *arena, struct world *tick)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
bw_write_var_uint(&bw, tick->continuity_gen);
bw_write_var_uint(&bw, tick->tick_id);
bw_write_var_sint(&bw, tick->publishtime_ns);
bw_write_f64(&bw, tick->timescale);
bw_write_var_sint(&bw, tick->dt_ns);
bw_write_var_sint(&bw, tick->time_ns);
u64 num_entities = tick->ent_store->num_reserved;
bw_write_var_uint(&bw, num_entities);
struct string entities_src = ZI;
entities_src.text = (u8 *)tick->ent_store->entities;
entities_src.len = sizeof(struct sim_ent) * num_entities;
br_write_bytes(&bw, entities_src);
return bw_get_written(&bw);
}
void sim_tick_from_string(struct string str, struct world *tick_out)
{
__prof;
struct byte_reader br = br_from_buffer(str);
tick_out->continuity_gen = br_read_var_uint(&br);
tick_out->tick_id = br_read_var_uint(&br);
tick_out->publishtime_ns = br_read_var_sint(&br);
tick_out->timescale = br_read_f64(&br);
tick_out->dt_ns = br_read_var_sint(&br);
tick_out->time_ns = br_read_var_sint(&br);
u64 num_entities = br_read_var_uint(&br);
arena_push_array(&tick_out->ent_store->arena, struct sim_ent, num_entities - tick_out->ent_store->num_reserved);
tick_out->ent_store->num_reserved = num_entities;
tick_out->ent_store->num_allocated = 0;
struct sim_ent *entities_src = br_seek(&br, num_entities * sizeof(struct sim_ent));
if (entities_src) {
for (u64 i = 0; i < num_entities; ++i) {
struct sim_ent *src = &entities_src[i];
struct sim_ent *dst = &tick_out->ent_store->entities[i];
if (dst->valid) {
++tick_out->ent_store->num_allocated;
}
*dst = *src;
}
}
}
/* ========================== *
* Sim thread
* ========================== */
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg)
{
(UNUSED)arg;
struct sim_ctx *ctx = (struct sim_ctx *)arg;
i64 last_frame_ns = 0;
i64 target_dt_ns = NS_FROM_SECONDS(SIM_FPS > (0) ? (1.0 / SIM_FPS) : 0);
while (!atomic_i32_eval(&G.sim_thread_shutdown)) {
while (!atomic_i32_eval(&ctx->sim_thread_shutdown)) {
__profscope(sim_update_w_sleep);
sleep_frame(last_frame_ns, target_dt_ns);
last_frame_ns = sys_time_ns();
sim_update();
sim_update(ctx);
}
}

121
src/sim.h
View File

@ -1,12 +1,8 @@
#ifndef SIM_H
#define SIM_H
#include "host.h"
struct world;
struct mixer_startup_receipt;
struct sim_ctx;
struct sprite_startup_receipt;
struct sound_startup_receipt;
struct phys_startup_receipt;
struct host_startup_receipt;
@ -20,116 +16,13 @@ struct host_startup_receipt;
#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);
/* TODO: Get rid of startup receipts */
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr,
u16 host_port);
void sim_ctx_release(struct sim_ctx *ctx);
/* ========================== *
* 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_SIM_CLIENT_CONNECT,
SIM_CMD_KIND_SIM_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 sim_ent_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

@ -17,7 +17,7 @@ READONLY struct sim_client_store _g_sim_client_store_nil = { .valid = false };
* Store
* ========================== */
struct sim_client_store *client_store_alloc(void)
struct sim_client_store *sim_client_store_alloc(void)
{
struct arena arena = arena_alloc(GIGABYTE(64));
u64 num_channel_lookup_buckets = CHANNEL_LOOKUP_BUCKETS;
@ -34,7 +34,7 @@ struct sim_client_store *client_store_alloc(void)
return store;
}
void client_store_release(struct sim_client_store *store)
void sim_client_store_release(struct sim_client_store *store)
{
arena_release(&store->arena);
}
@ -60,7 +60,7 @@ INTERNAL u64 hash_from_channel_id(struct host_channel_id channel_id)
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&channel_id));
}
struct sim_client *client_from_handle(struct sim_client_store *store, struct client_handle handle)
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct client_handle handle)
{
if (handle.gen != 0 && handle.idx < store->clients_reserved) {
struct sim_client *client = &store->clients[handle.idx];
@ -71,7 +71,7 @@ struct sim_client *client_from_handle(struct sim_client_store *store, struct cli
return client_nil();
}
struct sim_client *client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id)
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id)
{
struct sim_client *res = client_nil();
u64 channel_hash = hash_from_channel_id(channel_id);
@ -86,7 +86,7 @@ struct sim_client *client_from_channel_id(struct sim_client_store *store, struct
return res;
}
struct sim_client *client_alloc(struct sim_client_store *store, struct host_channel_id channel_id)
struct sim_client *sim_client_alloc(struct sim_client_store *store, struct host_channel_id channel_id)
{
struct sim_client *client = NULL;
struct client_handle handle = ZI;
@ -122,7 +122,7 @@ struct sim_client *client_alloc(struct sim_client_store *store, struct host_chan
return client;
}
void client_release(struct sim_client *client)
void sim_client_release(struct sim_client *client)
{
struct sim_client_store *store = client_store_from_client(client);
client->valid = false;

View File

@ -50,12 +50,12 @@ INLINE struct sim_client_store *client_store_nil(void)
return &_g_sim_client_store_nil;
}
struct sim_client_store *client_store_alloc(void);
void client_store_release(struct sim_client_store *store);
struct sim_client_store *sim_client_store_alloc(void);
void sim_client_store_release(struct sim_client_store *store);
struct sim_client_store *client_store_from_client(struct sim_client *client);
struct sim_client *client_from_handle(struct sim_client_store *store, struct client_handle handle);
struct sim_client *client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id);
struct sim_client *client_alloc(struct sim_client_store *store, struct host_channel_id channel_id);
void client_release(struct sim_client *client);
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct client_handle handle);
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id);
struct sim_client *sim_client_alloc(struct sim_client_store *store, struct host_channel_id channel_id);
void sim_client_release(struct sim_client *client);
#endif

265
src/sim_msg.c Normal file
View File

@ -0,0 +1,265 @@
#include "sim_msg.h"
#include "arena.h"
#include "byteio.h"
#include "world.h"
/* ========================== *
* Sim cmd
* ========================== */
struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
for (struct sim_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw);
bw_write_i8(&bw, cmd->kind);
bw_write_i8(&bw, cmd->state);
#if COLLIDER_DEBUG
bw_write_u32(&bw, cmd->collider_gjk_steps);
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
{
bw_write_v2(&bw, cmd->move_dir);
bw_write_v2(&bw, cmd->aim_dir);
} break;
case SIM_CMD_KIND_CURSOR_MOVE:
{
bw_write_v2(&bw, cmd->cursor_pos);
} break;
default: break;
}
u64 size = bw_pos(&bw) - start;
bw_write_u64(&bw_size, size);
}
return bw_get_written(&bw);
}
void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out)
{
__prof;
for (u64 i = 0; i < host_events.count; ++i) {
struct host_event host_event = host_events.events[i];
enum host_event_kind host_event_kind = host_event.kind;
switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED:
{
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = SIM_CMD_KIND_SIM_CLIENT_CONNECT;
cmd->channel_id = host_event.channel_id;
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
} break;
case HOST_EVENT_KIND_CHANNEL_CLOSED:
{
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
cmd->kind = SIM_CMD_KIND_SIM_CLIENT_DISCONNECT;
cmd->disconnect_reason = LIT("Connection lost");
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
} break;
case HOST_EVENT_KIND_MSG:
{
struct byte_reader br = br_from_buffer(host_event.msg);
while (br_bytes_left(&br) > 0) {
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
u64 cmd_size = br_read_u64(&br);
u64 cmd_pos_end = br_pos(&br) + cmd_size;
cmd->kind = br_read_i8(&br);
cmd->state = br_read_i8(&br);
#if COLLIDER_DEBUG
cmd->collider_gjk_steps = br_read_u32(&br);
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
{
cmd->move_dir = br_read_v2(&br);
cmd->aim_dir = br_read_v2(&br);
} break;
case SIM_CMD_KIND_CURSOR_MOVE:
{
cmd->cursor_pos = br_read_v2(&br);
} break;
default: break;
}
ASSERT(br_pos(&br) == cmd_pos_end);
br_seek_to(&br, cmd_pos_end);
if (cmds_out->last) {
cmds_out->last->next = cmd;
} else {
cmds_out->first = cmd;
}
cmds_out->last = cmd;
}
} break;
default: break;
}
}
}
/* ========================== *
* Sim event
* ========================== */
struct string sim_string_from_events(struct arena *arena, struct sim_event_list events)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
for (struct sim_event *event = events.first; event; event = event->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw);
bw_write_i8(&bw, event->kind);
switch (event->kind) {
case SIM_EVENT_KIND_SNAPSHOT_FULL:
{
bw_write_string(&bw, event->snapshot_data);
} break;
default: break;
}
u64 size = bw_pos(&bw) - start;
bw_write_u64(&bw_size, size);
}
return bw_get_written(&bw);
}
void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out)
{
__prof;
for (u64 i = 0; i < host_events.count; ++i) {
struct sim_event *sim_event = arena_push_zero(arena, struct sim_event);
struct host_event host_event = host_events.events[i];
enum host_event_kind host_event_kind = host_event.kind;
sim_event->channel_id = host_event.channel_id;
switch (host_event_kind) {
case HOST_EVENT_KIND_CHANNEL_OPENED:
{
sim_event->kind = SIM_EVENT_KIND_CONNECT;
} break;
case HOST_EVENT_KIND_CHANNEL_CLOSED:
{
sim_event->kind = SIM_EVENT_KIND_DISCONNECT;
sim_event->disconnect_reason = LIT("Connection lost");
} break;
case HOST_EVENT_KIND_MSG:
{
struct byte_reader br = br_from_buffer(host_event.msg);
while (br_bytes_left(&br) > 0) {
u64 event_size = br_read_u64(&br);
u64 event_pos_end = br_pos(&br) + event_size;
sim_event->kind = br_read_i8(&br);
switch (sim_event->kind) {
case SIM_EVENT_KIND_SNAPSHOT_FULL:
{
sim_event->snapshot_data = br_read_string(arena, &br);
} break;
default: break;
}
ASSERT(br_pos(&br) == event_pos_end);
br_seek_to(&br, event_pos_end);
}
} break;
default: break;
}
if (events_out->last) {
events_out->last->next = sim_event;
} else {
events_out->first = sim_event;
}
events_out->last = sim_event;
}
}
/* ========================== *
* Snapshot
* ========================== */
struct string sim_string_from_tick(struct arena *arena, struct world *tick)
{
__prof;
struct byte_writer bw = bw_from_arena(arena);
bw_write_var_uint(&bw, tick->continuity_gen);
bw_write_var_uint(&bw, tick->tick_id);
bw_write_var_sint(&bw, tick->publishtime_ns);
bw_write_f64(&bw, tick->timescale);
bw_write_var_sint(&bw, tick->dt_ns);
bw_write_var_sint(&bw, tick->time_ns);
u64 num_entities = tick->ent_store->num_reserved;
bw_write_var_uint(&bw, num_entities);
struct string entities_src = ZI;
entities_src.text = (u8 *)tick->ent_store->entities;
entities_src.len = sizeof(struct sim_ent) * num_entities;
br_write_bytes(&bw, entities_src);
return bw_get_written(&bw);
}
void sim_tick_from_string(struct string str, struct world *tick_out)
{
__prof;
struct byte_reader br = br_from_buffer(str);
tick_out->continuity_gen = br_read_var_uint(&br);
tick_out->tick_id = br_read_var_uint(&br);
tick_out->publishtime_ns = br_read_var_sint(&br);
tick_out->timescale = br_read_f64(&br);
tick_out->dt_ns = br_read_var_sint(&br);
tick_out->time_ns = br_read_var_sint(&br);
u64 num_entities = br_read_var_uint(&br);
arena_push_array(&tick_out->ent_store->arena, struct sim_ent, num_entities - tick_out->ent_store->num_reserved);
tick_out->ent_store->num_reserved = num_entities;
tick_out->ent_store->num_allocated = 0;
struct sim_ent *entities_src = br_seek(&br, num_entities * sizeof(struct sim_ent));
if (entities_src) {
for (u64 i = 0; i < num_entities; ++i) {
struct sim_ent *src = &entities_src[i];
struct sim_ent *dst = &tick_out->ent_store->entities[i];
if (dst->valid) {
++tick_out->ent_store->num_allocated;
}
*dst = *src;
}
}
}

112
src/sim_msg.h Normal file
View File

@ -0,0 +1,112 @@
#ifndef SIM_MSG_H
#define SIM_MSG_H
#include "host.h"
struct world;
/* ========================== *
* 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_SIM_CLIENT_CONNECT,
SIM_CMD_KIND_SIM_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 sim_ent_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

@ -8,13 +8,8 @@ enum sock_address_family {
SOCK_ADDRESS_FAMILY_IPV6
};
struct sock {
i32 _;
};
struct sock_signal {
i32 _;
};
struct sock;
struct sock_signal;
struct sock_array {
struct sock **socks;

View File

@ -2,6 +2,7 @@
#include "app.h"
#include "sim.h"
#include "sim_ent.h"
#include "sim_msg.h"
#include "renderer.h"
#include "font.h"
#include "sprite.h"
@ -46,9 +47,8 @@ GLOBAL struct {
struct sys_thread user_thread;
struct arena arena;
struct sys_window *window;
struct sim_ctx *sim_ctx;
struct host *host;
/* Usage stats */
@ -148,9 +148,10 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct font_startup_receipt *font_sr,
struct sprite_startup_receipt *sprite_sr,
struct draw_startup_receipt *draw_sr,
struct sim_startup_receipt *sim_sr,
struct asset_cache_startup_receipt *asset_cache_sr,
struct sound_startup_receipt *sound_sr,
struct mixer_startup_receipt *mixer_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr,
struct sys_window *window)
{
@ -159,9 +160,10 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
(UNUSED)font_sr;
(UNUSED)sprite_sr;
(UNUSED)draw_sr;
(UNUSED)sim_sr;
(UNUSED)asset_cache_sr;
(UNUSED)sound_sr;
(UNUSED)mixer_sr;
(UNUSED)phys_sr;
(UNUSED)host_sr;
G.arena = arena_alloc(GIGABYTE(64));
@ -170,8 +172,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
world_alloc(&G.world);
//struct sock_address bind_addr = sock_address_from_any_local_interface_with_dynamic_port();
//G.host = host_alloc(0);
G.host = host_alloc(5920);
G.host = host_alloc(0);
G.world_to_ui_xf = XFORM_IDENT;
G.world_cmd_buffer = renderer_cmd_buffer_alloc();
@ -182,6 +183,8 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
G.window = window;
sys_window_register_event_callback(G.window, &window_event_callback);
G.sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, 12345);
G.debug_draw = true;
G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, LIT("[P1] User thread"));
@ -195,6 +198,10 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(user_shutdown)
__prof;
atomic_i32_eval_exchange(&G.user_thread_shutdown, true);
sys_thread_wait_release(&G.user_thread);
if (G.sim_ctx) {
sim_ctx_release(G.sim_ctx);
}
}
/* ========================== *
@ -1620,10 +1627,10 @@ INTERNAL void user_update(void)
pos.y += spacing;
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Client data read: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_read.last_second * 8 / 1024 / 1024, 2)));
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Client data read: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_read.last_second * 8 / 1000 / 1000, 2)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Client data sent: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_sent.last_second * 8 / 1024 / 1024, 2)));
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Client data sent: %F mbit/s"), FMT_FLOAT_P((f64)G.client_bytes_sent.last_second * 8 / 1000 / 1000, 2)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Memory usage: %F MiB"), FMT_FLOAT_P((f64)atomic_u64_eval(&app_statistics()->memory_committed) / 1024 / 1024, 2)));

View File

@ -7,9 +7,10 @@ struct renderer_startup_receipt;
struct font_startup_receipt;
struct sprite_startup_receipt;
struct draw_startup_receipt;
struct sim_startup_receipt;
struct asset_cache_startup_receipt;
struct sound_startup_receipt;
struct mixer_startup_receipt;
struct phys_startup_receipt;
struct host_startup_receipt;
enum user_bind_kind {
@ -54,9 +55,10 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct font_startup_receipt *font_sr,
struct sprite_startup_receipt *sprite_sr,
struct draw_startup_receipt *draw_sr,
struct sim_startup_receipt *sim_sr,
struct asset_cache_startup_receipt *asset_cache_sr,
struct sound_startup_receipt *sound_sr,
struct mixer_startup_receipt *mixer_sr,
struct phys_startup_receipt *phys_sr,
struct host_startup_receipt *host_sr,
struct sys_window *window);