diff --git a/src/common.h b/src/common.h index 4378dfcb..d52077bc 100644 --- a/src/common.h +++ b/src/common.h @@ -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; diff --git a/src/host.c b/src/host.c index 83f3f2c5..83fcd285 100644 --- a/src/host.c +++ b/src/host.c @@ -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; diff --git a/src/phys.c b/src/phys.c index 4790194e..1ba1e025 100644 --- a/src/phys.c +++ b/src/phys.c @@ -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); diff --git a/src/phys.h b/src/phys.h index 4d04bdc3..6279e7b5 100644 --- a/src/phys.h +++ b/src/phys.h @@ -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); diff --git a/src/rng.c b/src/rng.c index df9853d6..daeea3b6 100644 --- a/src/rng.c +++ b/src/rng.c @@ -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]; diff --git a/src/sim.c b/src/sim.c index acb702fa..a032024f 100644 --- a/src/sim.c +++ b/src/sim.c @@ -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 * ========================== */ diff --git a/src/sim_client.h b/src/sim_client.h index 75d411ac..084be734 100644 --- a/src/sim_client.h +++ b/src/sim_client.h @@ -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 { diff --git a/src/sim_ent.c b/src/sim_ent.c index 706d1a39..dc0285f4 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -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; } /* ========================== * diff --git a/src/sim_ent.h b/src/sim_ent.h index a6f9d343..c5ab55a3 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -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; diff --git a/src/sim_msg.c b/src/sim_msg.c index e16b0203..81d6ab10 100644 --- a/src/sim_msg.c +++ b/src/sim_msg.c @@ -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); diff --git a/src/sim_msg.h b/src/sim_msg.h index 7ab968b7..fcc3fc85 100644 --- a/src/sim_msg.h +++ b/src/sim_msg.h @@ -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; diff --git a/src/sock_win32.c b/src/sock_win32.c index f1c81b6c..a3db478d 100644 --- a/src/sock_win32.c +++ b/src/sock_win32.c @@ -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; diff --git a/src/user.c b/src/user.c index bfc9e8a9..be7c8fd0 100644 --- a/src/user.c +++ b/src/user.c @@ -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 + }); + } + } + } + + /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */