Add launcher engine (scopenet-core) and admin panel server
- scopenet-shared: wire types for branding, auth, instances, manifests - scopenet-core: Mojang versions/libraries/assets, automatic Java runtimes, Fabric/Quilt/Forge/NeoForge installation, file sync, launch command builder, Microsoft auth, servers.dat injection, server list ping - scopenet-panel: Axum + SQLite admin API with JWT auth, users/groups, branding, settings, instances, Modrinth/CurseForge/zip import, file hosting and launch stats Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011ARcGWxLx21FwXJ3yfGriS
This commit is contained in:
43 files changed
+9317
No files matched your search
@@ -0,0 +1,54 @@
|
||||
//! Writes player keybinds / preferences into Minecraft's `options.txt`.
|
||||
|
||||
use anyhow::Result;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
/// Merge `key_<binding>:<key>` lines into options.txt, keeping everything
|
||||
/// else the game has written. Only for 1.13+ (named key codes).
|
||||
pub fn apply_keybinds(game_dir: &Path, binds: &BTreeMap<String, String>) -> Result<()> {
|
||||
let mut values: BTreeMap<String, String> = binds.iter().map(|(k, v)| (format!("key_{k}"), v.clone())).collect();
|
||||
apply(game_dir, &mut values)
|
||||
}
|
||||
|
||||
/// Merge arbitrary `name:value` options.
|
||||
pub fn apply(game_dir: &Path, values: &mut BTreeMap<String, String>) -> Result<()> {
|
||||
if values.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let path = game_dir.join("options.txt");
|
||||
let existing = std::fs::read_to_string(&path).unwrap_or_default();
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
for line in existing.lines() {
|
||||
match line.split_once(':') {
|
||||
Some((k, _)) if values.contains_key(k) => {
|
||||
let v = values.remove(k).unwrap();
|
||||
lines.push(format!("{k}:{v}"));
|
||||
}
|
||||
_ => lines.push(line.to_string()),
|
||||
}
|
||||
}
|
||||
for (k, v) in values.iter() {
|
||||
lines.push(format!("{k}:{v}"));
|
||||
}
|
||||
std::fs::create_dir_all(game_dir)?;
|
||||
std::fs::write(path, lines.join("\n") + "\n")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn merges_keybinds() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
std::fs::write(dir.path().join("options.txt"), "version:3465\nkey_key.forward:key.keyboard.w\nfov:0.0\n").unwrap();
|
||||
let mut binds = BTreeMap::new();
|
||||
binds.insert("key.forward".to_string(), "key.keyboard.up".to_string());
|
||||
binds.insert("key.sprint".to_string(), "key.keyboard.left.control".to_string());
|
||||
apply_keybinds(dir.path(), &binds).unwrap();
|
||||
let out = std::fs::read_to_string(dir.path().join("options.txt")).unwrap();
|
||||
assert_eq!(out, "version:3465\nkey_key.forward:key.keyboard.up\nfov:0.0\nkey_key.sprint:key.keyboard.left.control\n");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user