From 204b2654db8df3fb0f21451af12ad6013f3893a7 Mon Sep 17 00:00:00 2001 From: ShenMian Date: Tue, 16 Jan 2024 02:26:08 +0800 Subject: [PATCH] feat: support reading settings from settings.toml file --- .gitignore | 1 + Cargo.lock | 50 ++++++++++++++++++++++++++++++++++++++------ Cargo.toml | 7 +++++-- src/main.rs | 30 ++++++++++++++++++++------ src/resources.rs | 44 ++++++++++++++++++++++++-------------- src/solver/solver.rs | 5 +++-- src/systems/input.rs | 14 ++++++++----- 7 files changed, 114 insertions(+), 37 deletions(-) diff --git a/.gitignore b/.gitignore index 5ca0060..991e3cc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /.fleet /.idea database.db +settings.toml diff --git a/Cargo.lock b/Cargo.lock index 4c70274..c193a6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2591,7 +2591,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde8ae98d45607e4015d0b772d4a234788ebd7a41f09879f408c7f772b81e5bf" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.48", @@ -3370,11 +3370,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] @@ -3698,6 +3697,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3806,7 +3814,9 @@ dependencies = [ "leafwing-input-manager", "nalgebra", "rusqlite", + "serde", "siphasher", + "toml", "winit", ] @@ -4011,11 +4021,26 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.21.0", +] + [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -4039,6 +4064,19 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" diff --git a/Cargo.toml b/Cargo.toml index bb4de56..6bceba4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,15 @@ nalgebra = "0.32" bevy = "0.12" leafwing-input-manager = "0.11" bevy_editor_pls = "0.7" -rusqlite = { version = "0.30", features = ["bundled"] } siphasher = "1.0" +itertools = "0.12.0" +serde = { version = "1.0.195", features = ["derive"] } + +rusqlite = { version = "0.30", features = ["bundled"] } arboard = "3.3" # 系统剪切板 image = "0.24" winit = "0.28" # 版本需要与 bevy 中使用的保持一致 -itertools = "0.12.0" +toml = "0.8.8" [profile.dev.package."*"] opt-level = 3 diff --git a/src/main.rs b/src/main.rs index 470da74..29a60dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,15 @@ // #![feature(test)] +use bevy::diagnostic::FrameTimeDiagnosticsPlugin; +use bevy::prelude::*; +use leafwing_input_manager::prelude::*; + +use std::collections::VecDeque; +use std::fs; +use std::path::Path; + mod level; + use level::*; mod systems; @@ -26,15 +35,24 @@ mod movement; mod solver; mod test; -use bevy::diagnostic::FrameTimeDiagnosticsPlugin; -use bevy::prelude::*; -use leafwing_input_manager::prelude::*; - #[allow(unused_imports)] use bevy_editor_pls::prelude::*; #[bevy_main] fn main() { + const SETTINGS_FILE_PATH: &'static str = "settings.toml"; + if !Path::new(SETTINGS_FILE_PATH).is_file() { + let default_settings_toml = toml::to_string(&Settings::default()).unwrap(); + fs::write(SETTINGS_FILE_PATH, default_settings_toml); + } + let settings_toml = fs::read_to_string(SETTINGS_FILE_PATH).unwrap(); + let settings: Settings = toml::from_str(settings_toml.as_str()).unwrap(); + + let player_movement = PlayerMovement { + directions: VecDeque::new(), + timer: Timer::from_seconds(settings.player_move_speed, TimerMode::Repeating), + }; + App::new() .add_plugins(( DefaultPlugins, @@ -87,10 +105,10 @@ fn main() { .add_event::() .add_event::() .add_event::() - .insert_resource(Settings::default()) .init_resource::>() .insert_resource(Action::input_map()) - .insert_resource(PlayerMovement::default()) + .insert_resource(settings) + .insert_resource(player_movement) .insert_resource(CrateReachable::default()) .run(); } diff --git a/src/resources.rs b/src/resources.rs index 7aef488..c220b6b 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -1,22 +1,43 @@ use bevy::prelude::*; use nalgebra::Vector2; +use serde::{Deserialize, Serialize}; use crate::database; use crate::direction::Direction; use crate::level::PushState; +use crate::solver::solver::*; use std::collections::{HashMap, VecDeque}; use std::sync::Mutex; -#[derive(Resource)] +#[derive(Resource, Serialize, Deserialize)] pub struct Settings { pub instant_move: bool, + pub player_move_speed: f32, + pub solver: SolverSettings, } impl Default for Settings { fn default() -> Self { Self { instant_move: false, + player_move_speed: 0.05, + solver: SolverSettings::default(), + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct SolverSettings { + pub strategy: Strategy, + pub lower_bound_method: LowerBoundMethod, +} + +impl Default for SolverSettings { + fn default() -> Self { + Self { + strategy: Strategy::Fast, + lower_bound_method: LowerBoundMethod::PushCount, } } } @@ -27,6 +48,12 @@ pub struct Database(pub Mutex); #[derive(Resource, Deref, DerefMut)] pub struct LevelId(pub u64); +#[derive(Resource)] +pub struct PlayerMovement { + pub directions: VecDeque, + pub timer: Timer, +} + #[derive(Resource)] pub enum CrateReachable { None, @@ -41,18 +68,3 @@ impl Default for CrateReachable { Self::None } } - -#[derive(Resource)] -pub struct PlayerMovement { - pub directions: VecDeque, - pub timer: Timer, -} - -impl Default for PlayerMovement { - fn default() -> Self { - Self { - directions: VecDeque::new(), - timer: Timer::from_seconds(0.05, TimerMode::Repeating), - } - } -} diff --git a/src/solver/solver.rs b/src/solver/solver.rs index 703c887..ebac569 100644 --- a/src/solver/solver.rs +++ b/src/solver/solver.rs @@ -1,4 +1,5 @@ use nalgebra::Vector2; +use serde::{Deserialize, Serialize}; use crate::direction::Direction; use crate::level::{Level, Tile}; @@ -13,7 +14,7 @@ use std::time; use std::io::Write; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum Strategy { /// Find any solution Fast, @@ -28,7 +29,7 @@ pub enum Strategy { Mixed, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum LowerBoundMethod { PushCount, MoveCount, diff --git a/src/systems/input.rs b/src/systems/input.rs index 4833637..01cb853 100644 --- a/src/systems/input.rs +++ b/src/systems/input.rs @@ -202,7 +202,7 @@ impl Action { pub fn player_move_to( target: &Vector2, board: &mut crate::board::Board, - player_movement: &mut ResMut, + player_movement: &mut PlayerMovement, ) { if let Some(path) = find_path(&board.level.player_position, target, |position| { board @@ -222,7 +222,7 @@ pub fn player_move_to( fn player_move_or_push( direction: Direction, board: &mut crate::board::Board, - player_movement: &mut ResMut, + player_movement: &mut PlayerMovement, ) { if board.move_or_push(direction) { player_movement.directions.push_front(direction); @@ -244,9 +244,13 @@ fn print_solver_lowerbounds(solver: &Solver) { } } -fn solve_level(board: &mut crate::board::Board, player_movement: &mut ResMut) { +fn solve_level( + board: &mut crate::board::Board, + player_movement: &mut PlayerMovement, + settings: &Settings, +) { let mut solver = Solver::new(board.level.clone()); - solver.initial(Strategy::Fast, LowerBoundMethod::PushCount); + solver.initial(settings.solver.strategy, settings.solver.lower_bound_method); // print_solver_lowerbounds(&solver); let timeout = std::time::Duration::from_secs(15); @@ -364,7 +368,7 @@ pub fn action_input( any_pressed = true; } if action_state.just_pressed(Action::AutomaticSolution) { - solve_level(board, &mut player_movement); + solve_level(board, &mut player_movement, &*settings); any_pressed = true; }