basic save for game server
This commit is contained in:
parent
2a36485b1b
commit
98ee910ce1
3 changed files with 38 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/data
|
33
src/lib.rs
33
src/lib.rs
|
@ -7,17 +7,24 @@ use game::{
|
|||
entry::{ActionDefinition, DiceRoll},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tokio::{
|
||||
sync::{broadcast, mpsc},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
pub mod api;
|
||||
pub mod game;
|
||||
pub mod pathfinder2r_impl;
|
||||
pub mod user;
|
||||
|
||||
pub const GAME_SAVE_FILE: &str = "data/game.json";
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GameServer {
|
||||
game: Game<pathfinder2r_impl::Pathfinder2rCharacterSheet, pathfinder2r_impl::entry::Entry>,
|
||||
chat: Vec<(String, ChatMessage)>,
|
||||
#[serde(skip, default = "default_last_save_time")]
|
||||
last_save_time: Instant,
|
||||
// we dont want to save the logged users as it will always be empty when the server restarts
|
||||
#[serde(skip)]
|
||||
/// Logged in users, bool value used to know if the user is an admin or not
|
||||
|
@ -25,6 +32,10 @@ pub struct GameServer {
|
|||
// TODO: JEESH REPLACE THIS WITH A DATABASE AND PROPER SECURITY ONCE ITS DONE PLEASE GOD
|
||||
creds: HashMap<String, String>,
|
||||
}
|
||||
/// This is needed for the default value in GameServer.last_save_time
|
||||
fn default_last_save_time() -> Instant {
|
||||
Instant::now()
|
||||
}
|
||||
impl GameServer {
|
||||
pub fn new() -> Self {
|
||||
let mut creds = HashMap::new();
|
||||
|
@ -51,11 +62,19 @@ impl GameServer {
|
|||
)))
|
||||
.with_action(ActionDefinition::new("Attack -1".to_string())),
|
||||
)],
|
||||
last_save_time: Instant::now(),
|
||||
users: HashMap::new(),
|
||||
creds,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save(&self) {
|
||||
let _ = tokio::fs::create_dir("data").await;
|
||||
if let Ok(json) = serde_json::to_string(self) {
|
||||
let _ = tokio::fs::write(GAME_SAVE_FILE, json.as_bytes()).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn server_loop(
|
||||
mut self,
|
||||
mut msgs: mpsc::Receiver<(String, api::Request)>,
|
||||
|
@ -206,7 +225,11 @@ impl GameServer {
|
|||
}
|
||||
_ = broadcast.send((Some(id), api::Response::Shutdown));
|
||||
}
|
||||
api::Request::Shutdown => break,
|
||||
api::Request::Shutdown => {
|
||||
if *self.users.get(&id).unwrap_or(&false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
api::Request::CharacterDisplay { id: _ } => {}
|
||||
api::Request::CharacterInputs { id: _ } => todo!(),
|
||||
api::Request::CharacterGetField { id: _, field: _ } => todo!(),
|
||||
|
@ -217,8 +240,14 @@ impl GameServer {
|
|||
} => todo!(),
|
||||
api::Request::CharacterAssign { id: _, user: _ } => todo!(),
|
||||
}
|
||||
// Auto save every 5 minutes, once a request is received
|
||||
// TODO: Export the auto save time
|
||||
if self.last_save_time.elapsed().as_secs() > 5 * 60 {
|
||||
self.save().await;
|
||||
}
|
||||
}
|
||||
_ = broadcast.send((None, api::Response::Shutdown));
|
||||
self.save().await; // Save the game one last time :)
|
||||
}
|
||||
|
||||
fn get_scene_list(&self, id: &str) -> api::Response {
|
||||
|
|
|
@ -30,7 +30,12 @@ async fn main() {
|
|||
);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3001").await.unwrap();
|
||||
let game = open_tavern::GameServer::new();
|
||||
let game = tokio::fs::read_to_string(open_tavern::GAME_SAVE_FILE)
|
||||
.await
|
||||
.map(|s| serde_json::from_str(&s).ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(open_tavern::GameServer::new());
|
||||
tokio::spawn(game.server_loop(mrecv, bsend));
|
||||
|
||||
println!("Server is running at http://localhost:3001");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue