Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix key mapping + Fix crash due to missing resource #321

Merged
merged 2 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading