solution saving and loading
This commit is contained in:
parent
c4381ac1a1
commit
0c2d241745
6 changed files with 72 additions and 21 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/user
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
logic mostly like https://git.crispypin.cc/CrispyPin/marble
|
||||
|
||||
## todo
|
||||
solution saving & loading
|
||||
cleanup: unpowered texture names x_off -> x
|
||||
input/output display
|
||||
grow grid automatically while editing
|
||||
|
|
|
@ -64,6 +64,7 @@ enum SimState {
|
|||
pub enum ExitState {
|
||||
Dont,
|
||||
ExitAndSave,
|
||||
Save,
|
||||
ExitNoSave,
|
||||
}
|
||||
|
||||
|
@ -100,18 +101,10 @@ impl Editor {
|
|||
&self.level.id()
|
||||
}
|
||||
|
||||
pub fn save(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn source_board(&self) -> &Board {
|
||||
&self.source_board
|
||||
}
|
||||
|
||||
pub fn load_board(&mut self, board: Board) {
|
||||
self.source_board = board;
|
||||
}
|
||||
|
||||
fn start_sim(&mut self) {
|
||||
self.machine.reset();
|
||||
self.machine.set_board(self.source_board.clone());
|
||||
|
@ -278,6 +271,10 @@ impl Editor {
|
|||
self.exit_menu = true;
|
||||
}
|
||||
d.draw_text("exit", 10, 10, 20, Color::WHITE);
|
||||
if simple_button(d, 90, 5, 80, 30) {
|
||||
self.exit_state = ExitState::Save;
|
||||
}
|
||||
d.draw_text("save", 95, 10, 20, Color::WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
50
src/main.rs
50
src/main.rs
|
@ -13,7 +13,6 @@ mod util;
|
|||
|
||||
use editor::{Editor, ExitState};
|
||||
use level::Level;
|
||||
use marble_engine::board::Board;
|
||||
use solution::Solution;
|
||||
use util::*;
|
||||
|
||||
|
@ -40,8 +39,6 @@ fn main() {
|
|||
|
||||
let mut game = Game::new(&mut rl, &thread);
|
||||
game.run(&mut rl, &thread);
|
||||
// let board = Board::parse(&read_to_string("boards/adder.mbl").unwrap());
|
||||
// game.load_board(board);
|
||||
}
|
||||
|
||||
impl Game {
|
||||
|
@ -52,7 +49,7 @@ impl Game {
|
|||
|
||||
Self {
|
||||
levels: get_levels(),
|
||||
solutions: HashMap::new(),
|
||||
solutions: get_solutions(),
|
||||
open_editor: None,
|
||||
textures,
|
||||
selected_level: 0,
|
||||
|
@ -69,13 +66,20 @@ impl Game {
|
|||
editor.draw(&mut d, &self.textures);
|
||||
match editor.get_exit_state() {
|
||||
ExitState::Dont => (),
|
||||
ExitState::ExitNoSave => self.open_editor = None,
|
||||
ExitState::ExitAndSave => {
|
||||
self.solutions.get_mut(editor.level_id()).unwrap()
|
||||
[self.selected_solution]
|
||||
.board = editor.source_board().to_string();
|
||||
let solution = &mut self.solutions.get_mut(editor.level_id()).unwrap()
|
||||
[self.selected_solution];
|
||||
solution.board = editor.source_board().to_string();
|
||||
solution.save();
|
||||
self.open_editor = None;
|
||||
}
|
||||
ExitState::Save => {
|
||||
let solution = &mut self.solutions.get_mut(editor.level_id()).unwrap()
|
||||
[self.selected_solution];
|
||||
solution.board = editor.source_board().to_string();
|
||||
solution.save();
|
||||
}
|
||||
ExitState::ExitNoSave => self.open_editor = None,
|
||||
}
|
||||
} else {
|
||||
self.draw(&mut d);
|
||||
|
@ -227,3 +231,33 @@ fn get_levels() -> Vec<Level> {
|
|||
levels.sort_by(|a, b| a.id().cmp(b.id()));
|
||||
levels
|
||||
}
|
||||
|
||||
fn get_solutions() -> HashMap<String, Vec<Solution>> {
|
||||
let mut levels = HashMap::new();
|
||||
let solution_dir = userdata_dir().join("solutions");
|
||||
if let Ok(dir_contents) = read_dir(solution_dir) {
|
||||
for dir in dir_contents.flatten() {
|
||||
if dir.path().is_dir() {
|
||||
let level_name = dir.file_name().to_string_lossy().to_string();
|
||||
let mut solutions = Vec::new();
|
||||
|
||||
if let Ok(files) = read_dir(dir.path()) {
|
||||
for file in files.flatten() {
|
||||
let s = read_to_string(file.path())
|
||||
.ok()
|
||||
.as_deref()
|
||||
.map(|s| serde_json::from_str(s).ok())
|
||||
.flatten();
|
||||
if let Some(solution) = s {
|
||||
solutions.push(solution)
|
||||
}
|
||||
}
|
||||
|
||||
levels.insert(level_name, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
levels
|
||||
}
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
use std::{
|
||||
fs::{self, File},
|
||||
io::Write,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::level::Level;
|
||||
use crate::{level::Level, userdata_dir};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Solution {
|
||||
// solution_id: String,
|
||||
solution_id: String,
|
||||
level_id: String, // redundant?
|
||||
pub name: String,
|
||||
pub board: String,
|
||||
#[serde(default)]
|
||||
pub score: Option<Score>,
|
||||
}
|
||||
|
||||
|
@ -21,7 +27,7 @@ pub struct Score {
|
|||
impl Solution {
|
||||
pub fn new(level: &Level, number: usize) -> Self {
|
||||
Self {
|
||||
// solution_id: format!("solution_{number}"),
|
||||
solution_id: format!("solution_{number}"),
|
||||
level_id: level.id().to_owned(),
|
||||
name: format!("Unnamed {number}"),
|
||||
board: level
|
||||
|
@ -32,6 +38,16 @@ impl Solution {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn save(&self) {
|
||||
let dir = userdata_dir().join("solutions").join(&self.level_id);
|
||||
fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join(&format!("{}.json", &self.solution_id));
|
||||
|
||||
let json = serde_json::to_string_pretty(self).unwrap();
|
||||
let mut file = File::create(path).unwrap();
|
||||
file.write_all(json.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
pub fn level_id(&self) -> &str {
|
||||
&self.level_id
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, fs::read_dir};
|
||||
use std::{collections::HashMap, fs::read_dir, path::PathBuf};
|
||||
|
||||
use raylib::prelude::*;
|
||||
|
||||
|
@ -188,3 +188,7 @@ pub fn shrink_rec(rec: Rectangle, a: f32) -> Rectangle {
|
|||
height: rec.height - a * 2.,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn userdata_dir()->PathBuf{
|
||||
PathBuf::from("user")
|
||||
}
|
Loading…
Reference in a new issue