Skip to content

Commit

Permalink
Fix key mapping + Fix crash due to missing resource (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
terrarier2111 authored Mar 9, 2024
1 parent 2c5e7ec commit af64a4d
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 38 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion src/render/hud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -2448,6 +2449,15 @@ pub struct InventoryContextResource(pub Arc<RwLock<InventoryContext>>);
#[derive(Resource)]
pub struct RenderCtxResource(pub Arc<RenderCtx>);

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,
Expand Down
26 changes: 13 additions & 13 deletions src/settings/default_keybinds.rs
Original file line number Diff line number Diff line change
@@ -1,91 +1,91 @@
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",
action: Actionkey::Forward,
},
),
(
KeyCode::KeyS,
Key::Character(SmolStr::new_inline("s")),
Keybind {
name: "keybind_backward",
description: "Keybinding for moving backward",
action: Actionkey::Backward,
},
),
(
KeyCode::KeyA,
Key::Character(SmolStr::new_inline("a")),
Keybind {
name: "keybind_left",
description: "Keybinding for moving to the left",
action: Actionkey::Left,
},
),
(
KeyCode::KeyD,
Key::Character(SmolStr::new_inline("d")),
Keybind {
name: "keybind_right",
description: "Keybinding for moving to the right",
action: Actionkey::Right,
},
),
(
KeyCode::KeyE,
Key::Character(SmolStr::new_inline("e")),
Keybind {
name: "keybind_open_inv",
description: "Keybinding for opening the inventory",
action: Actionkey::OpenInv,
},
),
(
KeyCode::ShiftLeft,
Key::Named(NamedKey::Shift),
Keybind {
name: "keybind_sneak",
description: "Keybinding for sneaking",
action: Actionkey::Sneak,
},
),
(
KeyCode::ControlLeft,
Key::Named(NamedKey::Control),
Keybind {
name: "keybind_sprint",
description: "Keybinding for sprinting",
action: Actionkey::Sprint,
},
),
(
KeyCode::Space,
Key::Named(NamedKey::Space),
Keybind {
name: "keybind_jump",
description: "Keybinding for jumping",
action: Actionkey::Jump,
},
),
(
KeyCode::F1,
Key::Named(NamedKey::F1),
Keybind {
name: "keybind_toggle_hud",
description: "Keybinding for toggeling the hud",
action: Actionkey::ToggleHud,
},
),
(
KeyCode::F3,
Key::Named(NamedKey::F3),
Keybind {
name: "keybind_toggle_debug_info",
description: "Keybinding for toggeling the debug info",
action: Actionkey::ToggleDebug,
},
),
(
KeyCode::KeyT,
Key::Character(SmolStr::new_inline("t")),
Keybind {
name: "keybind_toggle_chat",
description: "Keybinding for toggeling the chat",
Expand Down
82 changes: 59 additions & 23 deletions src/settings/keybinds.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -18,32 +21,63 @@ pub struct Keybind {
pub action: Actionkey,
}

pub struct KeybindStore(Mutex<HashMap<i32, Keybind>>);
pub struct KeybindStore {
key_cache: ArcSwap<HashMap<Key, Keybind>>,
mapping_cache: ArcSwap<HashMap<u32, Keybind>>,
}

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<Keybind> {
self.0.lock().get(&(key as i32)).copied()
pub fn get(&self, code: KeyCode, key: &Key) -> Option<Keybind> {
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::<Vec<_>>();
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();
}

Expand All @@ -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}");
}
}
}
Expand All @@ -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!(
Expand All @@ -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
Expand All @@ -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<i32> {
match input.parse::<i32>() {
fn deserialize_key(input: &str) -> Option<Key> {
match serde_json::from_str(input) {
Ok(num) => Some(num),
Err(err) => {
warn!("couldnt deserialize keybind: {err}, {input}");
Expand Down

0 comments on commit af64a4d

Please sign in to comment.