Add basic cvar saving and loading
This commit is contained in:
parent
12a88b07b9
commit
4a3fc19713
|
@ -16,6 +16,8 @@ use std::marker::PhantomData;
|
|||
use std::collections::HashMap;
|
||||
use std::any::Any;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::fs;
|
||||
use std::io::{BufWriter, Write, BufRead, BufReader};
|
||||
use log;
|
||||
|
||||
use ui;
|
||||
|
@ -31,13 +33,28 @@ pub struct CVar<T: Sized + Any + 'static> {
|
|||
pub default: &'static Fn() -> T,
|
||||
}
|
||||
|
||||
impl Var for CVar<String> {}
|
||||
impl Var for CVar<String> {
|
||||
fn serialize(&self, val: &Box<Any>) -> String {
|
||||
format!("\"{}\"", val.downcast_ref::<String>().unwrap())
|
||||
}
|
||||
|
||||
fn deserialize(&self, input: &String) -> Box<Any> {
|
||||
Box::new((&input[1..input.len() - 1]).to_owned())
|
||||
}
|
||||
|
||||
fn description(&self) -> &'static str { self.description }
|
||||
fn can_serialize(&self) -> bool { self.serializable }
|
||||
}
|
||||
|
||||
pub trait Var {
|
||||
|
||||
fn serialize(&self, val: &Box<Any>) -> String;
|
||||
fn deserialize(&self, input: &String) -> Box<Any>;
|
||||
fn description(&self) -> &'static str;
|
||||
fn can_serialize(&self) -> bool;
|
||||
}
|
||||
|
||||
pub struct Console {
|
||||
names: HashMap<String, &'static str>,
|
||||
vars: HashMap<&'static str, Box<Var>>,
|
||||
var_values: HashMap<&'static str, Box<Any>>,
|
||||
|
||||
|
@ -51,6 +68,7 @@ pub struct Console {
|
|||
impl Console {
|
||||
pub fn new() -> Console {
|
||||
let mut con = Console {
|
||||
names: HashMap::new(),
|
||||
vars: HashMap::new(),
|
||||
var_values: HashMap::new(),
|
||||
|
||||
|
@ -72,6 +90,7 @@ impl Console {
|
|||
if self.vars.contains_key(var.name) {
|
||||
panic!("Key registered twice {}", var.name);
|
||||
}
|
||||
self.names.insert(var.name.to_owned(), var.name);
|
||||
self.var_values.insert(var.name, Box::new((var.default)()));
|
||||
self.vars.insert(var.name, Box::new(var));
|
||||
}
|
||||
|
@ -83,6 +102,7 @@ impl Console {
|
|||
|
||||
pub fn set<T: Sized + Any>(&mut self, var: CVar<T>, val: T) where CVar<T> : Var {
|
||||
self.var_values.insert(var.name, Box::new(val));
|
||||
self.save_config();
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
|
@ -145,6 +165,42 @@ impl Console {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load_config(&mut self) {
|
||||
if let Ok(file) = fs::File::open("conf.cfg") {
|
||||
let reader = BufReader::new(file);
|
||||
for line in reader.lines() {
|
||||
let line = line.unwrap();
|
||||
if line.starts_with("#") || line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let parts = line.splitn(2, ' ').map(|v| v.to_owned()).collect::<Vec<String>>();
|
||||
let (name, arg) = (&parts[0], &parts[1]);
|
||||
if let Some(var_name) = self.names.get(name) {
|
||||
let var = self.vars.get(var_name).unwrap();
|
||||
let val = var.deserialize(&arg);
|
||||
if var.can_serialize() {
|
||||
self.var_values.insert(var_name, val);
|
||||
}
|
||||
} else {
|
||||
println!("Missing prop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_config(&self) {
|
||||
let mut file = BufWriter::new(fs::File::create("conf.cfg").unwrap());
|
||||
for (name, var) in &self.vars {
|
||||
if !var.can_serialize() {
|
||||
continue;
|
||||
}
|
||||
for line in var.description().lines() {
|
||||
write!(file, "# {}\n", line).unwrap();
|
||||
}
|
||||
write!(file, "{} {}\n\n", name, var.serialize(self.var_values.get(name).unwrap())).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn log(&mut self, record: &log::LogRecord) {
|
||||
let mut file = record.location().file();
|
||||
if let Some(pos) = file.rfind("src/") {
|
||||
|
@ -213,4 +269,4 @@ impl log::Log for ConsoleProxy {
|
|||
}
|
||||
|
||||
unsafe impl Send for ConsoleProxy {}
|
||||
unsafe impl Sync for ConsoleProxy {}
|
||||
unsafe impl Sync for ConsoleProxy {}
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -45,7 +45,8 @@ use glfw::{Action, Context, Key};
|
|||
const CL_BRAND: console::CVar<String> = console::CVar {
|
||||
ty: PhantomData,
|
||||
name: "cl_brand",
|
||||
description: "cl_brand has the value of the clients current 'brand'. e.g. \"Steven\" or \"Vanilla\"",
|
||||
description: "cl_brand has the value of the clients current 'brand'. \
|
||||
e.g. \"Steven\" or \"Vanilla\"",
|
||||
mutable: false,
|
||||
serializable: false,
|
||||
default: &|| "steven".to_owned(),
|
||||
|
@ -60,7 +61,12 @@ pub struct Game {
|
|||
|
||||
fn main() {
|
||||
let con = Arc::new(Mutex::new(console::Console::new()));
|
||||
con.lock().unwrap().register(CL_BRAND);
|
||||
{
|
||||
let mut con = con.lock().unwrap();
|
||||
con.register(CL_BRAND);
|
||||
con.load_config();
|
||||
con.save_config();
|
||||
}
|
||||
let proxy = console::ConsoleProxy::new(con.clone());
|
||||
log::set_logger(|max_log_level| {
|
||||
max_log_level.set(log::LogLevelFilter::Trace);
|
||||
|
|
Loading…
Reference in New Issue