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::collections::HashMap;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::fs;
|
||||||
|
use std::io::{BufWriter, Write, BufRead, BufReader};
|
||||||
use log;
|
use log;
|
||||||
|
|
||||||
use ui;
|
use ui;
|
||||||
|
@ -31,13 +33,28 @@ pub struct CVar<T: Sized + Any + 'static> {
|
||||||
pub default: &'static Fn() -> T,
|
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 {
|
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 {
|
pub struct Console {
|
||||||
|
names: HashMap<String, &'static str>,
|
||||||
vars: HashMap<&'static str, Box<Var>>,
|
vars: HashMap<&'static str, Box<Var>>,
|
||||||
var_values: HashMap<&'static str, Box<Any>>,
|
var_values: HashMap<&'static str, Box<Any>>,
|
||||||
|
|
||||||
|
@ -51,6 +68,7 @@ pub struct Console {
|
||||||
impl Console {
|
impl Console {
|
||||||
pub fn new() -> Console {
|
pub fn new() -> Console {
|
||||||
let mut con = Console {
|
let mut con = Console {
|
||||||
|
names: HashMap::new(),
|
||||||
vars: HashMap::new(),
|
vars: HashMap::new(),
|
||||||
var_values: HashMap::new(),
|
var_values: HashMap::new(),
|
||||||
|
|
||||||
|
@ -72,6 +90,7 @@ impl Console {
|
||||||
if self.vars.contains_key(var.name) {
|
if self.vars.contains_key(var.name) {
|
||||||
panic!("Key registered twice {}", 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.var_values.insert(var.name, Box::new((var.default)()));
|
||||||
self.vars.insert(var.name, Box::new(var));
|
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 {
|
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.var_values.insert(var.name, Box::new(val));
|
||||||
|
self.save_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self) -> bool {
|
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) {
|
fn log(&mut self, record: &log::LogRecord) {
|
||||||
let mut file = record.location().file();
|
let mut file = record.location().file();
|
||||||
if let Some(pos) = file.rfind("src/") {
|
if let Some(pos) = file.rfind("src/") {
|
||||||
|
|
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 {
|
const CL_BRAND: console::CVar<String> = console::CVar {
|
||||||
ty: PhantomData,
|
ty: PhantomData,
|
||||||
name: "cl_brand",
|
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,
|
mutable: false,
|
||||||
serializable: false,
|
serializable: false,
|
||||||
default: &|| "steven".to_owned(),
|
default: &|| "steven".to_owned(),
|
||||||
|
@ -60,7 +61,12 @@ pub struct Game {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let con = Arc::new(Mutex::new(console::Console::new()));
|
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());
|
let proxy = console::ConsoleProxy::new(con.clone());
|
||||||
log::set_logger(|max_log_level| {
|
log::set_logger(|max_log_level| {
|
||||||
max_log_level.set(log::LogLevelFilter::Trace);
|
max_log_level.set(log::LogLevelFilter::Trace);
|
||||||
|
|
Loading…
Reference in New Issue