re-add networked debug drag

This commit is contained in:
jacob 2025-02-09 11:13:36 -06:00
parent eee5945954
commit 6fa3517d7a
13 changed files with 298 additions and 325 deletions

View File

@ -501,6 +501,11 @@ struct sim_ent_handle {
u64 gen;
};
struct sim_client_handle {
u32 idx;
u32 gen;
};
struct space_entry_handle {
u64 idx;
u64 gen;

View File

@ -681,7 +681,7 @@ void host_update(struct host *host)
{
/* A foreign host is trying to connect to us */
if (!channel->valid) {
logf_info("Received conection attempt from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
logf_info("Host received conection attempt from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
channel = host_channel_alloc(host, address);
}
@ -694,7 +694,7 @@ void host_update(struct host *host)
{
/* We successfully connected to a foreign host and they are ready to receive messages */
if (channel->valid && !channel->connected) {
logf_info("Received connection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
logf_info("Host received connection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
struct host_queued_event *queued_event = host_queued_event_alloc_and_append(host);
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_OPENED;
queued_event->event.channel_id = channel->id;
@ -706,7 +706,7 @@ void host_update(struct host *host)
{
/* A foreign host disconnected from us */
if (channel->valid) {
logf_info("Received disconnection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
logf_info("Host received disconnection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
struct host_queued_event *queued_event = host_queued_event_alloc_and_append(host);
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
queued_event->event.channel_id = channel->id;

View File

@ -9,7 +9,6 @@ GLOBAL struct {
struct math_spring_result contact_softness;
struct math_spring_result mouse_joint_linear_softness;
struct math_spring_result mouse_joint_angular_softness;
f32 mouse_joint_max_force;
} G = ZI, DEBUG_ALIAS(G, G_phys);
/* ========================== *
@ -29,7 +28,6 @@ struct phys_startup_receipt phys_startup(void)
const f32 mouse_joint_linear_damping_ratio = 0.7f;
const f32 mouse_joint_angular_frequency = 0.5f;
const f32 mouse_joint_angular_damping_ratio = 0.1f;
G.mouse_joint_max_force = 1000;
G.mouse_joint_linear_softness = math_spring(mouse_joint_linear_frequency, mouse_joint_linear_damping_ratio, substep_dt);
G.mouse_joint_angular_softness = math_spring(mouse_joint_angular_frequency, mouse_joint_angular_damping_ratio, substep_dt);
@ -583,7 +581,7 @@ void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias)
* Motor joint
* ========================== */
struct phys_motor_joint motor_joint_from_def(struct phys_motor_joint_def def)
struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def def)
{
struct phys_motor_joint res = ZI;
res.e0 = def.e0;
@ -771,72 +769,16 @@ void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt)
* Mouse joint
* ========================== */
void phys_create_mouse_joints(struct phys_ctx *ctx)
struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def def)
{
__prof;
struct sim_ent_store *store = ctx->store;
struct v2 cursor = ctx->dbg_cursor_pos;
b32 start_dragging = ctx->dbg_start_dragging;
b32 stop_dragging = ctx->dbg_stop_dragging;
struct sim_ent *root = sim_ent_from_handle(store, store->root);
struct sim_ent *joint_ent = sim_ent_find_first_match_one(store, SIM_ENT_PROP_MOUSE_JOINT);
struct sim_ent *target_ent = sim_ent_from_handle(store, joint_ent->mouse_joint_data.target);
if (start_dragging) {
struct xform mouse_xf = xform_from_pos(cursor);
struct collider_shape mouse_shape = ZI;
mouse_shape.points[0] = V2(0, 0);
mouse_shape.count = 1;
for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) {
struct sim_ent *ent = &store->entities[sim_ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue;
struct collider_shape ent_collider = ent->local_collider;
if (ent_collider.count > 0) {
struct xform ent_xf = sim_ent_get_xform(ent);
/* TODO: Can just use boolean GJK */
struct collider_collision_points_result res = collider_collision_points(&ent_collider, &mouse_shape, ent_xf, mouse_xf);
if (res.num_points > 0) {
target_ent = ent;
break;
}
}
}
} else if (stop_dragging) {
target_ent = sim_ent_nil();
}
if (sim_ent_is_valid_and_active(target_ent)) {
if (!sim_ent_is_valid_and_active(joint_ent)) {
joint_ent = sim_ent_alloc(root);
joint_ent->mass_unscaled = F32_INFINITY;
joint_ent->inertia_unscaled = F32_INFINITY;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
}
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
struct xform xf = sim_ent_get_xform(target_ent);
f32 mass = target_ent->mass_unscaled * math_fabs(xform_get_determinant(xf));
if (!sim_ent_handle_eq(joint->target, target_ent->handle)) {
joint->point_local_start = xform_invert_mul_v2(xf, cursor);
joint->target = target_ent->handle;
}
joint->point_local_end = xform_invert_mul_v2(xf, cursor);
joint->linear_softness = G.mouse_joint_linear_softness;
joint->angular_softness = G.mouse_joint_angular_softness;
joint->max_force = G.mouse_joint_max_force * mass;
} else {
if (sim_ent_is_valid_and_active(joint_ent)) {
joint_ent->mouse_joint_data.target = sim_ent_handle_nil();
}
}
struct phys_mouse_joint res = ZI;
res.target = def.target;
res.point_local_start = def.point_local_start;
res.point_local_end = def.point_local_end;
res.linear_softness = G.mouse_joint_linear_softness;
res.angular_softness = G.mouse_joint_angular_softness;
res.max_force = def.max_force;
return res;
}
void phys_prepare_mouse_joints(struct phys_ctx *ctx)
@ -1164,7 +1106,6 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
}
struct phys_collision_data_array collision_data = phys_create_and_update_contacts(scratch.arena, ctx, timestep - remaining_dt, phys_iteration);
phys_create_mouse_joints(ctx);
phys_prepare_contacts(ctx, phys_iteration);
phys_prepare_motor_joints(ctx);

View File

@ -41,9 +41,6 @@ struct phys_ctx {
void *post_solve_callback_udata;
struct sim_ent_lookup *debug_lookup;
struct v2 dbg_cursor_pos;
b32 dbg_start_dragging;
b32 dbg_stop_dragging;
};
@ -152,7 +149,7 @@ struct phys_motor_joint {
f32 angular_mass;
};
struct phys_motor_joint motor_joint_from_def(struct phys_motor_joint_def def);
struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def def);
void phys_prepare_motor_joints(struct phys_ctx *ctx);
void phys_warm_start_motor_joints(struct phys_ctx *ctx);
void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt);
@ -161,6 +158,13 @@ void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt);
* Mouse joint
* ========================== */
struct phys_mouse_joint_def {
struct sim_ent_handle target;
struct v2 point_local_start;
struct v2 point_local_end;
f32 max_force;
};
struct phys_mouse_joint {
struct sim_ent_handle target;
struct v2 point_local_start;
@ -178,7 +182,7 @@ struct phys_mouse_joint {
struct xform linear_mass_xf;
};
void phys_create_mouse_joints(struct phys_ctx *ctx);
struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def def);
void phys_prepare_mouse_joints(struct phys_ctx *ctx);
void phys_warm_start_mouse_joints(struct phys_ctx *ctx);
void phys_solve_mouse_joints(struct phys_ctx *ctx, f32 dt);

View File

@ -88,6 +88,8 @@ f64 rng_rand_f64(f64 range_start, f64 range_end)
* NOTE: Noise pattern repeats after period depending on how much noise data exists in noise.dat
* ========================== */
/* TODO: Use deterministic prng rather than embedded data */
u32 rng_noise_u32(u32 seed)
{
return (u32)G.noise[seed % G.noise_count];

365
src/sim.c
View File

@ -546,107 +546,144 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
* Process host events into sim cmds
* ========================== */
struct sim_cmd_list sim_cmds = ZI;
struct sim_cmd_list *client_cmds;
{
struct sim_cmd_list sim_cmds = ZI;
struct host_event_array host_events = host_pop_events(scratch.arena, ctx->host);
sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
/* Create connecting clients */
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
enum sim_cmd_kind kind = cmd->kind;
struct host_channel_id channel_id = cmd->channel_id;
struct sim_client *client = sim_client_from_channel_id(ctx->tick.client_store, channel_id);
if (!client->valid && kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id)) {
client = sim_client_alloc(ctx->tick.client_store, channel_id);
/* TODO: Create player ent not here */
/* FIXME: Player ent never released upon disconnect */
struct sim_ent *player_ent = spawn_test_player(ctx);
sim_ent_enable_prop(player_ent, SIM_ENT_PROP_CONTROLLED);
struct sim_ent *camera_ent = spawn_test_player_camera(ctx, player_ent);
client->control_ent = player_ent->handle;
client->camera_ent = camera_ent->handle;
player_ent->controlling_client = client->handle;
}
}
/* Split cmds by client */
client_cmds = arena_push_array_zero(scratch.arena, struct sim_cmd_list, ctx->tick.client_store->num_reserved);
{
struct sim_cmd *cmd = sim_cmds.first;
while (cmd) {
struct sim_cmd *next = cmd->next;
struct host_channel_id channel_id = cmd->channel_id;
struct sim_client *client = sim_client_from_channel_id(ctx->tick.client_store, channel_id);
if (client->valid) {
struct sim_cmd_list *cmd_list = &client_cmds[client->handle.idx];
if (cmd_list->last) {
cmd_list->last->next = cmd;
} else {
cmd_list->first = cmd;
}
cmd_list->last = cmd;
cmd->next = NULL;
}
cmd = next;
}
}
}
/* ========================== *
* Process sim cmds
* ========================== */
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
enum sim_cmd_kind kind = cmd->kind;
struct host_channel_id channel_id = cmd->channel_id;
struct sim_client *client = sim_client_from_channel_id(ctx->tick.client_store, channel_id);
/* Process client cmds */
for (u64 i = 0; i < ctx->tick.client_store->num_reserved; ++i) {
struct sim_client *client = &ctx->tick.client_store->clients[i];
if (client->valid) {
struct sim_ent *player_ent = sim_ent_from_handle(ctx->tick.ent_store, client->control_ent);
b32 start = cmd->state == SIM_CMD_STATE_START;
b32 stop = cmd->state == SIM_CMD_STATE_STOP;
switch (kind) {
/* TODO: Combine movement from multiple inputs? E.ctx-> a sudden
* start and immediate stop cmd should still move the player a
* tad. */
case SIM_CMD_KIND_PLAYER_MOVE:
{
if (player_ent->valid) {
struct host_channel_id channel_id = client->channel_id;
struct sim_cmd_list cmds = client_cmds[client->handle.idx];
struct sim_control *control = &client->control;
client->dbg_drag_start = false;
client->dbg_drag_stop = false;
for (struct sim_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
enum sim_cmd_kind kind = cmd->kind;
b32 start = cmd->state == SIM_CMD_STATE_START;
b32 stop = cmd->state == SIM_CMD_STATE_STOP;
switch (kind) {
/* TODO: Combine movement from multiple inputs? E.ctx-> a sudden
* start and immediate stop cmd should still move the player a
* tad. */
case SIM_CMD_KIND_PLAYER_CONTROL:
{
struct v2 move = cmd->move_dir;
struct v2 focus = cmd->aim_dir;
if (v2_len_sq(move) > 1) {
/* Cap movement vector magnitude at 1 */
move = v2_norm(move);
}
player_ent->control.move = move;
player_ent->control.focus = focus;
}
} break;
control->move = move;
control->focus = focus;
} break;
case SIM_CMD_KIND_PLAYER_FIRE:
{
if (player_ent->valid) {
b32 firing = sim_ent_has_prop(player_ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
case SIM_CMD_KIND_PLAYER_FIRE:
{
/* TODO: Allow sub-tick firing (start & stop on same tick should still fire for one tick */
b32 firing = control->firing;
if (start) {
firing = true;
} else if (stop) {
}
if (stop) {
firing = false;
}
if (firing) {
sim_ent_enable_prop(player_ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
} else {
sim_ent_disable_prop(player_ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
control->firing = firing;
} break;
/* Cursor */
case SIM_CMD_KIND_CURSOR_MOVE:
{
client->cursor_pos = cmd->cursor_pos;
} break;
case SIM_CMD_KIND_DRAG_OBJECT:
{
if (cmd->state == SIM_CMD_STATE_START) {
client->dbg_drag_start = true;
} else if (cmd->state == SIM_CMD_STATE_STOP) {
client->dbg_drag_stop = true;
}
}
} break;
} break;
/* Cursor */
case SIM_CMD_KIND_CURSOR_MOVE:
{
client->cursor_pos = cmd->cursor_pos;
} break;
/* Clear level */
case SIM_CMD_KIND_CLEAR_ALL:
{
ctx->should_reset_level = true;
} break;
/* Clear level */
case SIM_CMD_KIND_CLEAR_ALL:
{
ctx->should_reset_level = true;
} break;
/* Spawn test */
case SIM_CMD_KIND_SPAWN_TEST:
{
logf_info("Spawning (test)");
spawn_test_entities(ctx);
} break;
/* Spawn test */
case SIM_CMD_KIND_SPAWN_TEST:
{
logf_info("Spawning (test)");
spawn_test_entities(ctx);
} break;
/* Disconnect client */
case SIM_CMD_KIND_SIM_CLIENT_DISCONNECT:
{
if (player_ent->valid) {
sim_ent_enable_prop(player_ent, SIM_ENT_PROP_RELEASE_NEXT_TICK);
/* Disconnect client */
case SIM_CMD_KIND_SIM_CLIENT_DISCONNECT:
{
host_queue_disconnect(ctx->host, channel_id);
}
sim_client_release(client);
} break;
sim_client_release(client);
} break;
default: break;
};
} else if (kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) {
/* Connect client */
client = sim_client_alloc(ctx->tick.client_store, channel_id);
struct sim_ent *player_ent = spawn_test_player(ctx);
sim_ent_enable_prop(player_ent, SIM_ENT_PROP_CONTROLLED);
struct sim_ent *camera_ent = spawn_test_player_camera(ctx, player_ent);
client->control_ent = player_ent->handle;
client->camera_ent = camera_ent->handle;;
player_ent->controlling_client = client->handle;
default: break;
};
}
}
}
#if 0
/* ========================== *
* Update entity movement from control
* Update entity control from client control
* ========================== */
for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) {
@ -654,52 +691,18 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
if (!sim_ent_is_valid_and_active(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
/* Process cmds */
struct v2 move = ent->control.move;
struct v2 focus = ent->control.focus;
b32 firing = sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
/* 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) {
case SIM_CMD_KIND_PLAYER_MOVE:
{
move = cmd->move_dir;
focus = cmd->aim_dir;
} break;
case SIM_CMD_KIND_PLAYER_FIRE:
{
if (start) {
firing = true;
} else if (stop) {
firing = false;
}
} break;
default: break;
struct sim_client *client = sim_client_from_handle(ctx->tick.client_store, ent->controlling_client);
if (client->valid) {
ent->control = client->control;
/* TODO: Move this */
if (ent->control.firing) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
} else {
sim_ent_disable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
}
}
/* Movement */
if (v2_len_sq(move) > 1) {
/* Cap movement vector magnitude at 1 */
move = v2_norm(move);
}
ent->control.move = move;
ent->control.focus = focus;
/* Firing */
if (firing) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
} else {
sim_ent_disable_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED);
}
}
}
#endif
/* ========================== *
* Update entities from sprite
@ -952,21 +955,9 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
}
/* ========================== *
* Create forces from control move
* Create motor joints from control move
* ========================== */
#if 0
for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) {
struct sim_ent *ent = &ent_store->entities[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_PLAYER_CONTROLLED)) {
struct v2 move = ent->control.move;
struct v2 force = v2_mul(move, ent->control_force);
sim_ent_apply_force_to_center(ent, force);
}
}
#else
for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) {
struct sim_ent *ent = &ent_store->entities[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
@ -987,17 +978,16 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
def.correction_rate = 0;
def.max_force = ent->control_force;
def.max_torque = 0;
joint_ent->motor_joint_data = motor_joint_from_def(def);
joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
}
sim_ent_set_xform(joint_ent, XFORM_IDENT); /* Reset joint ent position */
sim_ent_set_linear_velocity(joint_ent, v2_mul(v2_clamp_len(ent->control.move, 1), ent->control_force_max_speed));
}
}
#endif
/* ========================== *
* Create forces from control focus (aim)
* Create motor joints from control focus (aim)
* ========================== */
#if SIM_PLAYER_AIM
@ -1025,7 +1015,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
def.e1 = ent->handle;
def.max_force = 0;
def.max_torque = ent->control_torque;
joint_ent->motor_joint_data = motor_joint_from_def(def);
joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
}
/* Set correction rate dynamically since motor velocity is only set for one frame */
@ -1091,7 +1081,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
#endif
/* ========================== *
* Create ground friction force (gravity)
* Create motor joints from ground friction (gravity)
* ========================== */
for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) {
@ -1112,12 +1102,80 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
joint_ent = sim_ent_alloc(root);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
joint_ent->motor_joint_data = motor_joint_from_def(def);
joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
ent->ground_friction_joint = joint_ent->handle;
}
}
}
/* ========================== *
* Create mouse joints from client debug drag
* ========================== */
for (u64 i = 0; i < ctx->tick.client_store->num_reserved; ++i) {
struct sim_client *client = &ctx->tick.client_store->clients[i];
if (client->valid) {
struct v2 cursor = client->cursor_pos;
b32 start_dragging = client->dbg_drag_start;
b32 stop_dragging = client->dbg_drag_stop;
struct sim_ent *joint_ent = sim_ent_from_handle(ent_store, client->dbg_drag_joint_ent);
struct sim_ent *target_ent = sim_ent_from_handle(ent_store, joint_ent->mouse_joint_data.target);
if (start_dragging) {
struct xform mouse_xf = xform_from_pos(cursor);
struct collider_shape mouse_shape = ZI;
mouse_shape.points[0] = V2(0, 0);
mouse_shape.count = 1;
for (u64 sim_ent_index = 0; sim_ent_index < ent_store->num_reserved; ++sim_ent_index) {
struct sim_ent *ent = &ent_store->entities[sim_ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue;
struct collider_shape ent_collider = ent->local_collider;
if (ent_collider.count > 0) {
struct xform ent_xf = sim_ent_get_xform(ent);
/* TODO: Can just use boolean GJK */
struct collider_collision_points_result res = collider_collision_points(&ent_collider, &mouse_shape, ent_xf, mouse_xf);
if (res.num_points > 0) {
target_ent = ent;
break;
}
}
}
}
if (stop_dragging) {
target_ent = sim_ent_nil();
}
if (sim_ent_is_valid_and_active(target_ent)) {
if (!sim_ent_is_valid_and_active(joint_ent)) {
/* FIXME: Joint ent never released */
joint_ent = sim_ent_alloc(root);
joint_ent->mass_unscaled = F32_INFINITY;
joint_ent->inertia_unscaled = F32_INFINITY;
client->dbg_drag_joint_ent = joint_ent->handle;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
}
struct xform xf = sim_ent_get_xform(target_ent);
f32 mass = target_ent->mass_unscaled * math_fabs(xform_get_determinant(xf));
struct phys_mouse_joint_def def = ZI;
def.target = target_ent->handle;
if (!sim_ent_handle_eq(joint_ent->mouse_joint_data.target, target_ent->handle)) {
def.point_local_start = xform_invert_mul_v2(xf, cursor);
}
def.point_local_end = xform_invert_mul_v2(xf, cursor);
def.max_force = mass * 1000;
joint_ent->mouse_joint_data = phys_mouse_joint_from_def(def);
} else if (sim_ent_is_valid_and_active(joint_ent)) {
joint_ent->mouse_joint_data.target = target_ent->handle;
}
}
}
/* ========================== *
* Physics
* ========================== */
@ -1134,20 +1192,6 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
phys.debug_lookup = &phys->collision_debug_lookup;
#endif
#if 0
/* Mouse drag */
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) {
phys.dbg_start_dragging = true;
} else if (cmd->state == SIM_CMD_STATE_STOP) {
phys.dbg_stop_dragging = true;
}
}
}
#endif
/* Step */
ctx->last_phys_iteration = phys_step(&phys, dt, ctx->last_phys_iteration);
}
@ -1331,37 +1375,6 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
arena_temp_end(temp);
}
#if 0
/* ========================== *
* Update sound emitters
* ========================== */
/* 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
* thread regardless of interp delay. */
for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) {
struct sim_ent *ent = &ent_store->entities[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_TEST_SOUND_EMITTER)) {
struct mixer_desc desc = ent->sound_desc;
desc.speed = ctx->tick.timescale;
desc.pos = sim_ent_get_xform(ent).og;
struct sound *sound = sound_load_async(ent->sound_name, 0);
b32 played = ent->sound_handle.gen != 0;
if (sound) {
if (!played) {
ent->sound_handle = mixer_play_ex(sound, desc);
} else {
mixer_track_set(ent->sound_handle, desc);
}
}
}
}
#endif
/* ========================== *
* Release entities
* ========================== */

View File

@ -1,12 +1,9 @@
#ifndef SIM_CLIENT_H
#define SIM_CLIENT_H
struct sim_client_channel_lookup_bucket;
#include "sim_ent.h"
struct sim_client_handle {
u32 idx;
u32 gen;
};
struct sim_client_channel_lookup_bucket;
struct sim_client {
b32 valid;
@ -22,6 +19,12 @@ struct sim_client {
struct v2 cursor_pos;
struct sim_ent_handle camera_ent;
struct sim_ent_handle control_ent;
struct sim_control control;
b32 dbg_drag_start;
b32 dbg_drag_stop;
struct sim_ent_handle dbg_drag_joint_ent;
};
struct sim_client_store {

View File

@ -381,8 +381,8 @@ void sim_ent_unlink_from_parent(struct sim_ent *ent)
} else {
parent->last = prev->handle;
}
ent->prev = sim_ent_handle_nil();
ent->next = sim_ent_handle_nil();
ent->prev = sim_ent_nil()->handle;
ent->next = sim_ent_nil()->handle;
}
/* ========================== *

View File

@ -4,7 +4,6 @@
#include "sprite.h"
#include "mixer.h"
#include "phys.h"
#include "sim_client.h"
enum sim_ent_prop {
SIM_ENT_PROP_NONE,
@ -81,6 +80,12 @@ struct sim_ent_lookup {
struct sim_ent_lookup_entry *first_free_entry;
};
struct sim_control {
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
struct v2 focus; /* Focus direction vector (where should the entity look) */
b32 firing;
};
struct sim_ent {
/* ====================================================================== */
/* Metadata */
@ -168,10 +173,7 @@ struct sim_ent {
f32 control_torque; /* How much torque is applied when turning towards desired focus */
struct {
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
struct v2 focus; /* Focus direction vector (where should the entity look) */
} control;
struct sim_control control;
struct sim_ent_handle move_joint;
struct sim_ent_handle aim_joint;
@ -314,11 +316,6 @@ struct sim_ent_prop_array {
* Handle helpers
* ========================== */
INLINE struct sim_ent_handle sim_ent_handle_nil(void)
{
return (struct sim_ent_handle) { 0 };
}
INLINE b32 sim_ent_handle_eq(struct sim_ent_handle a, struct sim_ent_handle b)
{
return a.gen == b.gen && a.idx == b.idx;

View File

@ -24,7 +24,7 @@ struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
case SIM_CMD_KIND_PLAYER_CONTROL:
{
bw_write_v2(&bw, cmd->move_dir);
bw_write_v2(&bw, cmd->aim_dir);
@ -93,7 +93,7 @@ void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host
#endif
switch (cmd->kind) {
case SIM_CMD_KIND_PLAYER_MOVE:
case SIM_CMD_KIND_PLAYER_CONTROL:
{
cmd->move_dir = br_read_v2(&br);
cmd->aim_dir = br_read_v2(&br);

View File

@ -19,7 +19,7 @@ enum sim_cmd_state {
enum sim_cmd_kind {
SIM_CMD_KIND_NONE,
SIM_CMD_KIND_PLAYER_MOVE,
SIM_CMD_KIND_PLAYER_CONTROL,
SIM_CMD_KIND_PLAYER_FIRE,
SIM_CMD_KIND_SIM_CLIENT_CONNECT,
@ -41,7 +41,7 @@ struct sim_cmd {
enum sim_cmd_state state;
struct host_channel_id channel_id;
/* SIM_CMD_KIND_PLAYER_MOVE */
/* SIM_CMD_KIND_PLAYER_CONTROL */
struct v2 move_dir;
struct v2 aim_dir;

View File

@ -86,6 +86,7 @@ INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
break;
} else if (ai_res->ai_family == AF_INET6) {
/* TODO: Enable ipv6 */
#if 0
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
res.valid = true;

View File

@ -740,15 +740,7 @@ INTERNAL void user_update(void)
}
/* ========================== *
* Find local entities
* ========================== */
struct sim_client *local_client = sim_client_from_handle(G.world.client_store, G.world.local_client);
struct sim_ent *local_player = sim_ent_from_handle(G.world.ent_store, local_client->control_ent);
struct sim_ent *local_camera = sim_ent_from_handle(G.world.ent_store, local_client->camera_ent);
/* ========================== *
* Debug commands
* Update user state from binds
* ========================== */
/* Test fullscreen */
@ -761,46 +753,6 @@ INTERNAL void user_update(void)
}
}
/* Test clear world */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_CLEAR_ALL
});
}
}
/* Test pause */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_PAUSE
});
}
}
/* Test step */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_STEP
});
}
}
/* Test spawn */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_SPAWN_TEST
});
}
}
if (G.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) {
G.debug_draw = !G.debug_draw;
}
@ -809,6 +761,14 @@ INTERNAL void user_update(void)
G.debug_camera = !G.debug_camera;
}
/* ========================== *
* Find local entities
* ========================== */
struct sim_client *local_client = sim_client_from_handle(G.world.client_store, G.world.local_client);
struct sim_ent *local_player = sim_ent_from_handle(G.world.ent_store, local_client->control_ent);
struct sim_ent *local_camera = sim_ent_from_handle(G.world.ent_store, local_client->camera_ent);
/* ========================== *
* Apply shake
* ========================== */
@ -1508,7 +1468,7 @@ INTERNAL void user_update(void)
}
/* ========================== *
* Construct player control cmd
* Queue player control cmd
* ========================== */
{
@ -1565,7 +1525,7 @@ INTERNAL void user_update(void)
/* Queue player input cmd */
if (!G.debug_camera) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_PLAYER_MOVE,
.kind = SIM_CMD_KIND_PLAYER_CONTROL,
.move_dir = input_move_dir,
.aim_dir = input_aim_dir
});
@ -1601,6 +1561,53 @@ INTERNAL void user_update(void)
#endif
}
/* ========================== *
* Queue debug cmds
* ========================== */
{
/* Test clear world */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_CLEAR_ALL
});
}
}
/* Test pause */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_PAUSE
});
}
}
/* Test step */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_STEP
});
}
}
/* Test spawn */
{
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
if (state.num_presses) {
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
.kind = SIM_CMD_KIND_SPAWN_TEST
});
}
}
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */