From af64a4df50a29a93d149143f696409af8884e7ff Mon Sep 17 00:00:00 2001 From: terrarier2111 <58695553+terrarier2111@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:44:29 +0100 Subject: [PATCH] Fix key mapping + Fix crash due to missing resource (#321) --- Cargo.lock | 4 ++ Cargo.toml | 2 +- src/render/hud.rs | 2 +- src/server/mod.rs | 10 ++++ src/settings/default_keybinds.rs | 26 +++++----- src/settings/keybinds.rs | 82 +++++++++++++++++++++++--------- 6 files changed, 88 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b66c2b23..d68914d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,6 +915,9 @@ name = "cursor-icon" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +dependencies = [ + "serde", +] [[package]] name = "dashmap" @@ -4147,6 +4150,7 @@ dependencies = [ "redox_syscall 0.3.5", "rustix", "sctk-adwaita", + "serde", "smithay-client-toolkit", "smol_str", "unicode-segmentation", diff --git a/Cargo.toml b/Cargo.toml index 9c9b1134..9a591cb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ split-debuginfo = "unpacked" opt-level = 1 [dependencies] -winit = { version = "0.29", features = ["rwh_05"] } +winit = { version = "0.29", features = ["rwh_05", "serde"] } raw-window-handle = "0.5.0" glow = "0.13" byteorder = "1.4" diff --git a/src/render/hud.rs b/src/render/hud.rs index a37a6ac9..63f813cc 100644 --- a/src/render/hud.rs +++ b/src/render/hud.rs @@ -498,7 +498,7 @@ impl Screen for Hud { } match key.1 { PhysicalKey::Code(code) => { - if let Some(action_key) = game.keybinds.get(code) { + if let Some(action_key) = game.keybinds.get(code, &key.0) { // if let Some(action_key) = settings::Actionkey::get_by_keycode(code, &game.vars) { game.server.as_ref().unwrap().key_press( down, diff --git a/src/server/mod.rs b/src/server/mod.rs index decf9bd0..43bf1c3b 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -908,6 +908,7 @@ impl Server { .insert_resource(InventoryContextResource(inventory_context.clone())); entities.world.insert_resource(DeltaResource(0.0)); entities.world.insert_resource(WorldData::default()); + entities.world.insert_resource(RenderCtxResource::default()); entity::add_systems(&mut entities.schedule.write()); add_systems(&mut entities.schedule.write()); @@ -2448,6 +2449,15 @@ pub struct InventoryContextResource(pub Arc>); #[derive(Resource)] pub struct RenderCtxResource(pub Arc); +impl Default for RenderCtxResource { + fn default() -> Self { + Self(Arc::new(RenderCtx { + fps: AtomicU32::new(0), + frame_start: AtomicU64::new(0), + })) + } +} + pub struct RenderCtx { pub fps: AtomicU32, pub frame_start: AtomicU64, diff --git a/src/settings/default_keybinds.rs b/src/settings/default_keybinds.rs index 1d3eb4de..6c929a0f 100644 --- a/src/settings/default_keybinds.rs +++ b/src/settings/default_keybinds.rs @@ -1,11 +1,11 @@ -use winit::keyboard::KeyCode; +use winit::keyboard::{Key, NamedKey, SmolStr}; use super::*; -pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { +pub fn create_keybinds() -> Vec<(Key, Keybind)> { vec![ ( - KeyCode::KeyW, + Key::Character(SmolStr::new_inline("w")), Keybind { name: "keybind_forward", description: "Keybinding for moving forward", @@ -13,7 +13,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::KeyS, + Key::Character(SmolStr::new_inline("s")), Keybind { name: "keybind_backward", description: "Keybinding for moving backward", @@ -21,7 +21,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::KeyA, + Key::Character(SmolStr::new_inline("a")), Keybind { name: "keybind_left", description: "Keybinding for moving to the left", @@ -29,7 +29,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::KeyD, + Key::Character(SmolStr::new_inline("d")), Keybind { name: "keybind_right", description: "Keybinding for moving to the right", @@ -37,7 +37,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::KeyE, + Key::Character(SmolStr::new_inline("e")), Keybind { name: "keybind_open_inv", description: "Keybinding for opening the inventory", @@ -45,7 +45,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::ShiftLeft, + Key::Named(NamedKey::Shift), Keybind { name: "keybind_sneak", description: "Keybinding for sneaking", @@ -53,7 +53,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::ControlLeft, + Key::Named(NamedKey::Control), Keybind { name: "keybind_sprint", description: "Keybinding for sprinting", @@ -61,7 +61,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::Space, + Key::Named(NamedKey::Space), Keybind { name: "keybind_jump", description: "Keybinding for jumping", @@ -69,7 +69,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::F1, + Key::Named(NamedKey::F1), Keybind { name: "keybind_toggle_hud", description: "Keybinding for toggeling the hud", @@ -77,7 +77,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::F3, + Key::Named(NamedKey::F3), Keybind { name: "keybind_toggle_debug_info", description: "Keybinding for toggeling the debug info", @@ -85,7 +85,7 @@ pub fn create_keybinds() -> Vec<(KeyCode, Keybind)> { }, ), ( - KeyCode::KeyT, + Key::Character(SmolStr::new_inline("t")), Keybind { name: "keybind_toggle_chat", description: "Keybinding for toggeling the chat", diff --git a/src/settings/keybinds.rs b/src/settings/keybinds.rs index 11d03da3..383ddbf9 100644 --- a/src/settings/keybinds.rs +++ b/src/settings/keybinds.rs @@ -1,11 +1,14 @@ +use arc_swap::ArcSwap; use log::{info, warn}; -use parking_lot::Mutex; use std::collections::HashMap; use std::fs; use std::io::{BufRead, BufReader, BufWriter, Write}; +use std::ops::Deref; use std::str::FromStr; +use std::sync::Arc; +use winit::platform::scancode::PhysicalKeyExtScancode; -use winit::keyboard::KeyCode; +use winit::keyboard::{Key, KeyCode}; use crate::paths; @@ -18,32 +21,63 @@ pub struct Keybind { pub action: Actionkey, } -pub struct KeybindStore(Mutex>); +pub struct KeybindStore { + key_cache: ArcSwap>, + mapping_cache: ArcSwap>, +} impl KeybindStore { pub fn new() -> Self { - let mut store = KeybindStore(Mutex::new(HashMap::new())); + let mut store = KeybindStore { + key_cache: ArcSwap::new(Arc::new(HashMap::new())), + mapping_cache: ArcSwap::new(Arc::new(HashMap::new())), + }; store.load_defaults(); store.load_config(); store.save_config(); store } - pub fn get(&self, key: KeyCode) -> Option { - self.0.lock().get(&(key as i32)).copied() + pub fn get(&self, code: KeyCode, key: &Key) -> Option { + if let Some(cache) = self + .mapping_cache + .load() + .get(&code.to_scancode().unwrap()) + .copied() + { + return Some(cache); + } + if let Some(cached) = self.key_cache.load().get(key) { + let mut cache = self.mapping_cache.load().deref().deref().clone(); + cache.insert(code.to_scancode().unwrap(), *cached); + return Some(*cached); + } + None } - pub fn set(&self, key: i32, action: Actionkey) { - let old_key = *self - .0 - .lock() + pub fn set(&self, key: Key, action: Actionkey) { + let old_key = self + .key_cache + .load() .iter() .find(|(_, v)| v.action == action) .expect("a action was not bound to a key?") - .0; + .0 + .clone(); + let old_mapping = self.mapping_cache.load(); + let old_raw_keys = old_mapping + .iter() + .filter(|(_, v)| v.action == action) + .collect::>(); + let mut mapping = self.mapping_cache.load().deref().deref().clone(); + for key in old_raw_keys { + mapping.remove(key.0); + } - let old_val = self.0.lock().remove(&old_key).unwrap(); - self.0.lock().insert(key, old_val); + let mut cache = self.key_cache.load().deref().deref().clone(); + let old_val = cache.remove(&old_key).unwrap(); + cache.insert(key, old_val); + self.key_cache.store(Arc::new(cache)); self.save_config(); } @@ -66,23 +100,24 @@ impl KeybindStore { if !name.starts_with("keybind_") { continue; } - let mut store = self.0.lock(); + let mut store = self.key_cache.load().deref().deref().clone(); if let Some(action) = store .values() .find(|v| Actionkey::from_str(name).is_ok_and(|k| k == v.action)) { if let Some(new_key) = deserialize_key(arg) { - let key = *store + let key = store .iter() .find(|(_, v)| v.action == action.action) .expect("a action was not bound to a key?") - .0; + .0 + .clone(); let old_val = store.remove(&key).unwrap(); store.insert(new_key, old_val); } } else { - info!("a unknown keybind was specified: {name}"); + info!("an unknown keybind was specified: {name}"); } } } @@ -91,7 +126,7 @@ impl KeybindStore { fn save_config(&self) { let mut file = BufWriter::new(fs::File::create(paths::get_config_dir().join("keybinds.cfg")).unwrap()); - for (key, keybind) in self.0.lock().iter() { + for (key, keybind) in self.key_cache.load().iter() { for line in keybind.description.lines() { if let Err(err) = writeln!(file, "# {}", line) { warn!( @@ -100,7 +135,7 @@ impl KeybindStore { ); } } - if let Err(err) = write!(file, "{} {}\n\n", keybind.name, *key) { + if let Err(err) = write!(file, "{} {:?}\n\n", keybind.name, key.clone()) { warn!( "couldnt write a keybind to config file {err}, {}", keybind.name @@ -110,15 +145,16 @@ impl KeybindStore { } fn load_defaults(&self) { - let mut s = self.0.lock(); + let mut s = self.key_cache.load().deref().deref().clone(); for bind in create_keybinds() { - s.insert(bind.0 as i32, bind.1); + s.insert(bind.0, bind.1); } + self.key_cache.store(Arc::new(s)); } } -fn deserialize_key(input: &str) -> Option { - match input.parse::() { +fn deserialize_key(input: &str) -> Option { + match serde_json::from_str(input) { Ok(num) => Some(num), Err(err) => { warn!("couldnt deserialize keybind: {err}, {input}");