From b8bfad3b021910cbddfcb0d5c00c6f542d447e6d Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Mon, 12 Jan 2026 10:54:58 -0600 Subject: [PATCH 01/13] fix: add type spec to Sessions::create_with --- src/debug.rs | 11 ++++++----- src/main.rs | 17 ++++++++++------- src/profiler.rs | 2 +- src/sessions.rs | 6 +++--- src/ui/pause_menu.rs | 2 +- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/debug.rs b/src/debug.rs index 10cd923f2..421d586b9 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -7,11 +7,12 @@ use bones_framework::debug::frame_time_diagnostics_plugin; use bones_framework::networking::debug::network_debug_window; pub fn game_plugin(game: &mut Game) { - game.sessions.create_with(SessionNames::DEBUG, |builder| { - builder - .install_plugin(session_plugin) - .install_plugin(frame_time_diagnostics_plugin); - }); + game.sessions + .create_with(SessionNames::DEBUG, |builder: &mut SessionBuilder| { + builder + .install_plugin(session_plugin) + .install_plugin(frame_time_diagnostics_plugin); + }); } fn session_plugin(session: &mut SessionBuilder) { diff --git a/src/main.rs b/src/main.rs index aecf82253..cb3305184 100644 --- a/src/main.rs +++ b/src/main.rs @@ -174,7 +174,7 @@ fn main() { // Create a new session for the pause menu, which sits in the background by default and only // does anything while the game is running. game.sessions - .create_with(SessionNames::PAUSE_MENU, |builder| { + .create_with(SessionNames::PAUSE_MENU, |builder: &mut SessionBuilder| { builder.install_plugin(ui::pause_menu::session_plugin); }); @@ -185,15 +185,18 @@ fn main() { .priority = 1; // Scoring menu plugin, activated by game between round tarnsitions when appropriate - game.sessions.create_with(SessionNames::SCORING, |builder| { - builder.install_plugin(ui::scoring::session_plugin); - }); + game.sessions + .create_with(SessionNames::SCORING, |builder: &mut SessionBuilder| { + builder.install_plugin(ui::scoring::session_plugin); + }); // session for pop-ups / nofication UI - game.sessions - .create_with(SessionNames::NOTIFICATION, |builder| { + game.sessions.create_with( + SessionNames::NOTIFICATION, + |builder: &mut SessionBuilder| { builder.install_plugin(ui::notification::session_plugin); - }); + }, + ); // Create a bevy renderer for the bones game and run it. BonesBevyRenderer { diff --git a/src/profiler.rs b/src/profiler.rs index fde22b692..1bfe68f42 100644 --- a/src/profiler.rs +++ b/src/profiler.rs @@ -6,7 +6,7 @@ use crate::prelude::*; pub fn game_plugin(game: &mut Game) { game.systems.add_before_system(mark_new_frame); game.sessions - .create_with(SessionNames::PROFILER, |builder| { + .create_with(SessionNames::PROFILER, |builder: &mut SessionBuilder| { builder.install_plugin(session_plugin); }); } diff --git a/src/sessions.rs b/src/sessions.rs index 4d99eb9d0..2bdc66975 100644 --- a/src/sessions.rs +++ b/src/sessions.rs @@ -23,7 +23,7 @@ pub trait SessionExt { impl SessionExt for Sessions { fn start_menu(&mut self) { - self.create_with(SessionNames::MAIN_MENU, |builder| { + self.create_with(SessionNames::MAIN_MENU, |builder: &mut SessionBuilder| { builder.install_plugin(crate::ui::main_menu::session_plugin); }); } @@ -74,7 +74,7 @@ impl SessionExt for Sessions { score }; - self.create_with(SessionNames::GAME, |builder| { + self.create_with(SessionNames::GAME, |builder: &mut SessionBuilder| { builder.install_plugin(crate::core::MatchPlugin { maps: map_pool, player_info, @@ -89,7 +89,7 @@ impl SessionExt for Sessions { } fn start_game(&mut self, match_plugin: crate::core::MatchPlugin) { - self.create_with(SessionNames::GAME, |builder| { + self.create_with(SessionNames::GAME, |builder: &mut SessionBuilder| { builder.install_plugin(match_plugin); }); } diff --git a/src/ui/pause_menu.rs b/src/ui/pause_menu.rs index ed9874665..c52db4ae0 100644 --- a/src/ui/pause_menu.rs +++ b/src/ui/pause_menu.rs @@ -137,7 +137,7 @@ fn pause_menu_system( .deref() .clone(); sessions.end_game(); - sessions.create_with(SessionNames::GAME, |builder| { + sessions.create_with(SessionNames::GAME, |builder: &mut SessionBuilder| { builder.install_plugin(crate::core::MatchPlugin { maps, player_info: std::array::from_fn(|i| PlayerInput { From d297b749ee4501b7358c55b66bb0bf31f6e3a0e9 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Mon, 12 Jan 2026 10:55:14 -0600 Subject: [PATCH 02/13] fix: specify lan service type --- src/ui/network_game.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/network_game.rs b/src/ui/network_game.rs index 89a841bbf..89e6b81c0 100644 --- a/src/ui/network_game.rs +++ b/src/ui/network_game.rs @@ -9,6 +9,9 @@ use super::main_menu::MenuPage; /// Game id for matchmaking const GAME_ID: &str = "jumpy"; +/// The jumpy mdns service type for lan games. +const JUMPY_LAN_SERVICE_TYPE: &str = "_jumpy._udp.local."; + #[derive(Clone, Debug, Default)] pub enum NetworkGameAction { #[default] @@ -270,7 +273,7 @@ pub fn network_game_menu( lan::stop_server(&service_info); *status = NetworkGameStatus::Idle; } - lan::prepare_to_join(lan_servers, lan_service_discovery_recv, ping_update_timer); + lan::prepare_to_join(JUMPY_LAN_SERVICE_TYPE, lan_servers, lan_service_discovery_recv, ping_update_timer); if *status != NetworkGameStatus::Joining { ui.label( @@ -384,7 +387,7 @@ pub fn network_game_menu( }); let (is_recreated, service_info) = RUNTIME.block_on(async { - lan::prepare_to_host(host_info, service_name).await + lan::prepare_to_host(host_info, JUMPY_LAN_SERVICE_TYPE, service_name).await }); if is_recreated { *status = NetworkGameStatus::Idle; From cf6ef36340490eb6b3415850cd7eb97557e3c0ea Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Mon, 12 Jan 2026 11:00:05 -0600 Subject: [PATCH 03/13] fix: satisfy InputCollector trait requirements --- src/core.rs | 10 +--------- src/input.rs | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/core.rs b/src/core.rs index e5e702ad1..9fb33e307 100644 --- a/src/core.rs +++ b/src/core.rs @@ -130,15 +130,7 @@ impl SessionRunner for JumpyDefaultMatchRunner { let last_run = self.last_run.unwrap_or(frame_start); let delta = (frame_start - last_run).as_secs_f64(); - { - let keyboard = world.resource::(); - let gamepad = world.resource::(); - self.input_collector.apply_inputs( - &world.resource::(), - &keyboard, - &gamepad, - ); - } + self.input_collector.apply_inputs(world); let mut run = || { // Advance the world time diff --git a/src/input.rs b/src/input.rs index 761a13c3d..3011a66e1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -32,7 +32,7 @@ fn collect_player_controls(game: &mut Game) { }; let keyboard = game.shared_resource::().unwrap(); let gamepad = game.shared_resource::().unwrap(); - collector.apply_inputs(&mapping, &keyboard, &gamepad); + collector.apply_inputs_inner(&mapping, &keyboard, &gamepad); collector.update_just_pressed(); collector.advance_frame(); GlobalPlayerControls( @@ -287,7 +287,21 @@ impl<'a> /// Update the internal state with new inputs. This must be called every render frame with the /// input events. - fn apply_inputs( + fn apply_inputs(&mut self, world: &World) { + let keyboard = world.resource::(); + let gamepad = world.resource::(); + let mapping = world.resource::(); + self.apply_inputs_inner(&mapping, &keyboard, &gamepad); + } + + // TODO: Fix bones Trait definition, player_idx not relevant + fn get_control(&self, _player_idx: usize, control_source: ControlSource) -> &PlayerControl { + self.current_controls.get(&control_source).unwrap() + } +} + +impl PlayerInputCollector { + fn apply_inputs_inner( &mut self, mapping: &PlayerControlMapping, keyboard: &KeyboardInputs, @@ -404,11 +418,6 @@ impl<'a> } } } - - // TODO: Fix bones Trait definition, player_idx not relevant - fn get_control(&self, _player_idx: usize, control_source: ControlSource) -> &PlayerControl { - self.current_controls.get(&control_source).unwrap() - } } #[cfg(not(target_arch = "wasm32"))] From e7140d773568f397a448ae088c5d0a86a13dbb02 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Mon, 12 Jan 2026 12:10:32 -0600 Subject: [PATCH 04/13] fix: remove unused import --- src/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.rs b/src/core.rs index 9fb33e307..13d4b2b13 100644 --- a/src/core.rs +++ b/src/core.rs @@ -28,7 +28,7 @@ pub const MAX_PLAYERS: u32 = 4; use std::time::Duration; -use crate::{prelude::*, settings::PlayerControlMapping}; +use crate::prelude::*; pub mod prelude { pub use super::{ From c0e4a3108a542b8ff3b56e6b079f805447f6215d Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Mon, 12 Jan 2026 12:10:56 -0600 Subject: [PATCH 05/13] update Cargo.lock --- Cargo.lock | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e9f721b4..92b9fbe3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1249,7 +1249,7 @@ dependencies = [ [[package]] name = "bones_asset" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "anyhow", "append-only-vec", @@ -1283,7 +1283,7 @@ dependencies = [ [[package]] name = "bones_bevy_renderer" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "anyhow", "bevy", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "bones_ecs" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "anyhow", "atomicell", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "bones_ecs_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "bones_ecs_macros_core", "proc-macro2", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "bones_ecs_macros_core" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "proc-macro2", "quote", @@ -1338,7 +1338,7 @@ dependencies = [ [[package]] name = "bones_framework" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "anyhow", "async-channel", @@ -1394,7 +1394,7 @@ dependencies = [ [[package]] name = "bones_lib" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "bones_ecs", "instant", @@ -1405,7 +1405,7 @@ dependencies = [ [[package]] name = "bones_matchmaker_proto" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "iroh", "serde", @@ -1414,7 +1414,7 @@ dependencies = [ [[package]] name = "bones_schema" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "append-only-vec", "bones_schema_macros", @@ -1435,7 +1435,7 @@ dependencies = [ [[package]] name = "bones_schema_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "proc-macro2", "quote", @@ -1445,7 +1445,7 @@ dependencies = [ [[package]] name = "bones_scripting" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "async-channel", "bevy_tasks", @@ -1464,7 +1464,7 @@ dependencies = [ [[package]] name = "bones_utils" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "bones_utils_macros", "fxhash", @@ -1479,7 +1479,7 @@ dependencies = [ [[package]] name = "bones_utils_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#fc00c0c9aeceea2c2836c6568bdcf7b202c20694" +source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" dependencies = [ "quote", "venial", @@ -3218,6 +3218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" dependencies = [ "bytemuck", + "libm", "serde", ] From c30db8011dd685bb3bb10bfa38206bace475f210 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 10:59:28 -0600 Subject: [PATCH 06/13] update rust-toolchain --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ea3769f29..cf9202f5e 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.81 +1.93.0 \ No newline at end of file From 487d80919e1295932aeded94ab0210c6c312d095 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 11:16:55 -0600 Subject: [PATCH 07/13] fix: update shared_resource usage --- src/fullscreen.rs | 2 +- src/input.rs | 14 +++++++------- src/settings.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/fullscreen.rs b/src/fullscreen.rs index eee8f237a..4ab600c62 100644 --- a/src/fullscreen.rs +++ b/src/fullscreen.rs @@ -14,7 +14,7 @@ fn update_fullscreen(game: &mut Game) { let mut storage = storage.borrow_mut().unwrap(); let window = game.shared_resource_cell::().unwrap(); let mut window = window.borrow_mut().unwrap(); - let keyboard = game.shared_resource::().unwrap(); + let keyboard = game.shared_resource::(); let f11_pressed = keyboard .key_events diff --git a/src/input.rs b/src/input.rs index 3011a66e1..52a9e3d67 100644 --- a/src/input.rs +++ b/src/input.rs @@ -18,7 +18,7 @@ pub fn game_plugin(game: &mut Game) { // collector. fn load_controler_mapping(game: &mut Game) { let control_mapping = { - let storage = game.shared_resource::().unwrap(); + let storage = game.shared_resource::(); storage.get::().unwrap().player_controls.clone() }; game.insert_shared_resource(control_mapping); @@ -26,12 +26,12 @@ fn load_controler_mapping(game: &mut Game) { fn collect_player_controls(game: &mut Game) { let controls = 'controls: { - let mut collector = game.shared_resource_mut::().unwrap(); - let Some(mapping) = game.shared_resource::() else { + let mut collector = game.shared_resource_mut::(); + let Some(mapping) = game.get_shared_resource::() else { break 'controls default(); }; - let keyboard = game.shared_resource::().unwrap(); - let gamepad = game.shared_resource::().unwrap(); + let keyboard = game.shared_resource::(); + let gamepad = game.shared_resource::(); collector.apply_inputs_inner(&mapping, &keyboard, &gamepad); collector.update_just_pressed(); collector.advance_frame(); @@ -63,7 +63,7 @@ pub fn handle_egui_input(game: &mut Game, egui_input: &mut egui::RawInput) { // available immediately to egui, and then available to the rest of the systems that run after. collect_player_controls(game); - let ctx = game.shared_resource::().unwrap(); + let ctx = game.shared_resource::(); let settings = ctx.get_state::(); let events = &mut egui_input.events; @@ -74,7 +74,7 @@ pub fn handle_egui_input(game: &mut Game, egui_input: &mut egui::RawInput) { // Forward gamepad events to egui if not disabled. if !settings.disable_gamepad_input { - let controls = game.shared_resource::().unwrap(); + let controls = game.shared_resource::(); let push_key = |events: &mut Vec, key| { events.push(egui::Event::Key { diff --git a/src/settings.rs b/src/settings.rs index 0962e28b8..52fb0796e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -10,11 +10,11 @@ pub fn game_plugin(game: &mut Game) { /// Startup system to load the game settings or use the default settings specified in the game meta. fn load_settings(game: &mut Game) { let default_settings = { - let assets = game.shared_resource::().unwrap(); + let assets = game.shared_resource::(); let settings = &assets.root::().default_settings; settings.clone() }; - let mut storage = game.shared_resource_mut::().unwrap(); + let mut storage = game.shared_resource_mut::(); if storage.get::().is_none() { storage.insert(default_settings); } From 1a80506e071da6bc408776b18998a4e10991c07e Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 11:43:54 -0600 Subject: [PATCH 08/13] fix: update names and imports for new bones --- src/core/input.rs | 5 ++--- src/input.rs | 15 +++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/core/input.rs b/src/core/input.rs index 5cebdfcd6..81c7bf3cb 100644 --- a/src/core/input.rs +++ b/src/core/input.rs @@ -2,7 +2,7 @@ use std::array; -use bones_framework::input::PlayerControls; +use bones_framework::input::Controls; use crate::{prelude::*, MAX_PLAYERS}; @@ -23,8 +23,7 @@ impl Default for MatchInputs { } } } - -impl PlayerControls<'_, PlayerControl> for MatchInputs { +impl Controls<'_, PlayerControl> for MatchInputs { type ControlSource = ControlSource; type ControlMapping = PlayerControlMapping; type InputCollector = PlayerInputCollector; diff --git a/src/input.rs b/src/input.rs index 52a9e3d67..c1a658357 100644 --- a/src/input.rs +++ b/src/input.rs @@ -3,8 +3,6 @@ use crate::{ settings::{InputKind, PlayerControlMapping, Settings}, }; -#[cfg(not(target_arch = "wasm32"))] -use bones_framework::networking::{input::NetworkPlayerControl, proto::DenseMoveDirection}; use strum::EnumIter; pub fn game_plugin(game: &mut Game) { @@ -214,10 +212,7 @@ impl Default for PlayerInputCollector { } } -impl<'a> - bones_framework::input::InputCollector<'a, PlayerControlMapping, ControlSource, PlayerControl> - for PlayerInputCollector -{ +impl<'a> bones_framework::input::InputCollector<'a, PlayerControl> for PlayerInputCollector { fn update_just_pressed(&mut self) { self.current_controls .iter_mut() @@ -421,7 +416,7 @@ impl PlayerInputCollector { } #[cfg(not(target_arch = "wasm32"))] -impl NetworkPlayerControl for PlayerControl { +impl DenseControl for PlayerControl { fn get_dense_input(&self) -> DensePlayerControl { let mut dense_control = DensePlayerControl::default(); dense_control.set_jump_pressed(self.jump_pressed); @@ -471,7 +466,7 @@ bitfield::bitfield! { pub grab_pressed, set_grab_pressed: 2; pub slide_pressed, set_slide_pressed: 3; pub ragdoll_pressed, set_ragdoll_pressed: 4; - pub from into DenseMoveDirection, move_direction, set_move_direction: 16, 5; + pub from into proto::DenseMoveDirection, move_direction, set_move_direction: 16, 5; } #[cfg(not(target_arch = "wasm32"))] @@ -488,9 +483,9 @@ impl Default for DensePlayerControl { pub struct NetworkInputConfig; #[cfg(not(target_arch = "wasm32"))] -impl<'a> bones_framework::networking::input::NetworkInputConfig<'a> for NetworkInputConfig { +impl<'a> DenseInputConfig<'a> for NetworkInputConfig { type Dense = DensePlayerControl; type Control = PlayerControl; - type PlayerControls = MatchInputs; + type Controls = MatchInputs; type InputCollector = PlayerInputCollector; } From 5163247464b6e589fc8512d5ceab80a059cd591d Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 14:35:18 -0600 Subject: [PATCH 09/13] fix: update `Controls` trait impl for new bones This moves `get_control_source` out of the `Controls` trait implementation and removes the unused `update_controls` function from the trait. --- src/core/input.rs | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/core/input.rs b/src/core/input.rs index 81c7bf3cb..313a2e0d2 100644 --- a/src/core/input.rs +++ b/src/core/input.rs @@ -15,7 +15,11 @@ pub fn install(session: &mut SessionBuilder) { pub struct MatchInputs { pub players: [PlayerInput; MAX_PLAYERS as usize], } - +impl MatchInputs { + pub fn get_control_source(&self, player_idx: usize) -> Option { + self.players.get(player_idx).unwrap().control_source + } +} impl Default for MatchInputs { fn default() -> Self { Self { @@ -24,23 +28,6 @@ impl Default for MatchInputs { } } impl Controls<'_, PlayerControl> for MatchInputs { - type ControlSource = ControlSource; - type ControlMapping = PlayerControlMapping; - type InputCollector = PlayerInputCollector; - - fn update_controls(&mut self, collector: &mut PlayerInputCollector) { - (0..MAX_PLAYERS as usize).for_each(|i| { - let player_input = &mut self.players[i]; - if let Some(source) = &player_input.control_source { - player_input.control = *collector.get_control(i, *source); - } - }); - } - - fn get_control_source(&self, player_idx: usize) -> Option { - self.players.get(player_idx).unwrap().control_source - } - fn get_control(&self, player_idx: usize) -> &PlayerControl { &self.players.get(player_idx).unwrap().control } From dccd9da3fc9422752819a6c0869d7eb669968936 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 15:36:20 -0600 Subject: [PATCH 10/13] fix: update input collector for new bones In short, control source is now specific to jumpy so I put a similar code set to what was dropped in bones, and put it in the jumpy collector's `apply_inputs` function which will be called at the same time as the code that was dropped from bones. This update makes jumpy function the same way minimally without making any major changes to organize the structure to work with bones super cleanly. --- src/input.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/input.rs b/src/input.rs index c1a658357..aff338fe2 100644 --- a/src/input.rs +++ b/src/input.rs @@ -183,6 +183,8 @@ pub struct PlayerControl { #[derive(HasSchema, Clone)] pub struct PlayerInputCollector { + /// The local player's [`ControlSource`] in an online / lan game. + control_source: ControlSource, current_controls: HashMap, last_controls: HashMap, } @@ -206,6 +208,7 @@ impl Default for PlayerInputCollector { m }; Self { + control_source: ControlSource::Keyboard1, current_controls: def_controls(), last_controls: def_controls(), } @@ -287,11 +290,30 @@ impl<'a> bones_framework::input::InputCollector<'a, PlayerControl> for PlayerInp let gamepad = world.resource::(); let mapping = world.resource::(); self.apply_inputs_inner(&mapping, &keyboard, &gamepad); + + #[cfg(not(target_arch = "wasm32"))] + // Get the first local player control source which should be the only + // local player in an online game. + if let Some(user_control_source) = world + .resource::() + .players + .iter() + .find_map(|player| player.control_source) + { + // `self.control_source` is only used in online / lan games to + // tell the `GgrsSessionRunner` which controls to grab for the + // one local player via `InputCollecter::get_control`. + self.control_source = user_control_source; + + // `apply_inputs` is called before `get_control` so this will + // always update the source in time. + } else { + panic!("no local player control source") + } } - // TODO: Fix bones Trait definition, player_idx not relevant - fn get_control(&self, _player_idx: usize, control_source: ControlSource) -> &PlayerControl { - self.current_controls.get(&control_source).unwrap() + fn get_control(&self) -> &PlayerControl { + self.current_controls.get(&self.control_source).unwrap() } } From b46454cb75a62d4ba510c24d737ca3fdf06b873a Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 15:48:29 -0600 Subject: [PATCH 11/13] fix: run clippy fix & cargo fmt --- src/core/map.rs | 92 +++++++++++++++++-------------- src/core/scoring.rs | 5 +- src/ui/main_menu/player_select.rs | 2 +- src/ui/pause_menu.rs | 2 +- 4 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/core/map.rs b/src/core/map.rs index 0e477b019..061ef223f 100644 --- a/src/core/map.rs +++ b/src/core/map.rs @@ -472,13 +472,15 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, above3l2, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(-1.0, 0.0), - jump_just_pressed: true, - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(-1.0, 0.0), + jump_just_pressed: true, + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), distance: node.distance(&above3l2), }, @@ -496,13 +498,15 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, above3l3, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(-1.0, 0.0), - jump_just_pressed: true, - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(-1.0, 0.0), + jump_just_pressed: true, + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), distance: node.distance(&above3l3), }, @@ -519,13 +523,15 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, above3r2, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(1.0, 0.0), - jump_just_pressed: true, - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(1.0, 0.0), + jump_just_pressed: true, + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), distance: node.distance(&above3r2), }, @@ -543,13 +549,15 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, above3r3, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(1.0, 0.0), - jump_just_pressed: true, - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(1.0, 0.0), + jump_just_pressed: true, + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), distance: node.distance(&above3r3), }, @@ -708,12 +716,14 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, far_right_below, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(1.0, 0.0), - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(1.0, 0.0), + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), // Bias against using this move because it doesn't always work, by adding an // extra distance. @@ -735,12 +745,14 @@ fn create_nav_graph(meta: &MapMeta) -> Arc { node, far_left_below, NavGraphEdge { - inputs: std::iter::repeat(PlayerControl { - move_direction: vec2(-1.0, 0.0), - jump_pressed: true, - ..default() - }) - .take(20) + inputs: std::iter::repeat_n( + PlayerControl { + move_direction: vec2(-1.0, 0.0), + jump_pressed: true, + ..default() + }, + 20, + ) .collect(), // Bias against using this move because it doesn't always work, by adding an // extra distance. diff --git a/src/core/scoring.rs b/src/core/scoring.rs index 9c68d206e..1295efbfb 100644 --- a/src/core/scoring.rs +++ b/src/core/scoring.rs @@ -194,7 +194,10 @@ pub fn round_end( } if round_transition_synchronized { - if score.rounds_completed % meta.core.config.rounds_between_intermission == 0 { + if score + .rounds_completed + .is_multiple_of(meta.core.config.rounds_between_intermission) + { scoring_menu.active = true; scoring_menu.match_score = score.clone(); scoring_menu.next_maps = state.next_maps.clone(); diff --git a/src/ui/main_menu/player_select.rs b/src/ui/main_menu/player_select.rs index 2e4b03df6..aecf2f723 100644 --- a/src/ui/main_menu/player_select.rs +++ b/src/ui/main_menu/player_select.rs @@ -609,7 +609,7 @@ fn player_select_panel( .slots .iter() .enumerate() - .any(|(i, slot)| (slot.control_source().is_none() && i == slot_id as usize)); + .any(|(i, slot)| slot.control_source().is_none() && i == slot_id as usize); #[cfg(target_arch = "wasm32")] let (network_local_player_slot, slot_allows_new_player) = (None::, is_next_open_slot); diff --git a/src/ui/pause_menu.rs b/src/ui/pause_menu.rs index c52db4ae0..fccfc1ef0 100644 --- a/src/ui/pause_menu.rs +++ b/src/ui/pause_menu.rs @@ -42,7 +42,7 @@ fn pause_menu_system( let is_online = session .world .get_resource::() - .map_or(false, |x| x.is_online()); + .is_some_and(|x| x.is_online()); #[cfg(target_arch = "wasm32")] let is_online = false; From d6b41056a50b2bcf8ea557366414de991acdb1ef Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Wed, 28 Jan 2026 15:50:06 -0600 Subject: [PATCH 12/13] fix: doc with unneeded path extension --- src/core/editor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/editor.rs b/src/core/editor.rs index 51f95c3ad..49b9e2712 100644 --- a/src/core/editor.rs +++ b/src/core/editor.rs @@ -19,7 +19,7 @@ impl_system_param! { /// running. This can be used both for manual map editing, and by algorithms for generating or /// randomizing maps. /// - /// Map generators implement the [`MapConstructor`][crate::core::map_constructor::MapConstructor] + /// Map generators implement the [`MapConstructor`] /// trait, which is given a [`MapManager`] to make its changes with. pub struct MapManager<'a> { commands: Commands<'a>, From 7e86467436a310f7834c9cef563480baef85cbb7 Mon Sep 17 00:00:00 2001 From: Tekhnae Raav Date: Fri, 30 Jan 2026 09:31:20 -0600 Subject: [PATCH 13/13] update Cargo.lock --- Cargo.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92b9fbe3c..67bb22591 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1249,7 +1249,7 @@ dependencies = [ [[package]] name = "bones_asset" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "anyhow", "append-only-vec", @@ -1283,7 +1283,7 @@ dependencies = [ [[package]] name = "bones_bevy_renderer" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "anyhow", "bevy", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "bones_ecs" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "anyhow", "atomicell", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "bones_ecs_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "bones_ecs_macros_core", "proc-macro2", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "bones_ecs_macros_core" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "proc-macro2", "quote", @@ -1338,7 +1338,7 @@ dependencies = [ [[package]] name = "bones_framework" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "anyhow", "async-channel", @@ -1394,7 +1394,7 @@ dependencies = [ [[package]] name = "bones_lib" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "bones_ecs", "instant", @@ -1405,7 +1405,7 @@ dependencies = [ [[package]] name = "bones_matchmaker_proto" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "iroh", "serde", @@ -1414,7 +1414,7 @@ dependencies = [ [[package]] name = "bones_schema" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "append-only-vec", "bones_schema_macros", @@ -1435,7 +1435,7 @@ dependencies = [ [[package]] name = "bones_schema_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "proc-macro2", "quote", @@ -1445,7 +1445,7 @@ dependencies = [ [[package]] name = "bones_scripting" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "async-channel", "bevy_tasks", @@ -1464,7 +1464,7 @@ dependencies = [ [[package]] name = "bones_utils" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "bones_utils_macros", "fxhash", @@ -1479,7 +1479,7 @@ dependencies = [ [[package]] name = "bones_utils_macros" version = "0.4.0" -source = "git+https://github.com/fishfolk/bones#87147027376852646f03d3e422c969deb969102c" +source = "git+https://github.com/fishfolk/bones#7e1d92578e1b35256debfb95492d0a519d8c796e" dependencies = [ "quote", "venial",