diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..937bb3a --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,45 @@ +name: Rust Release Build + +on: + push: + tags: + - 'v*.*.*' + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + default: true + override: true + + - name: Build + run: cargo build --release + + - name: Run tests + run: cargo test --verbose + + - name: Strip + run: strip target/release/snake + + - name: Compress + run: tar cvzf snake.tar.gz LICENSE target/release/snake + + - name: Release + uses: softprops/action-gh-release@v1 + with: + files: | + snake.tar.gz + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml new file mode 100644 index 0000000..0f95efc --- /dev/null +++ b/.github/workflows/rust.yaml @@ -0,0 +1,22 @@ +name: Rust Build Test + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/.gitignore b/.gitignore index 96ef6c0..ea8c4bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ /target -Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 8d97fe6..9e61240 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,40 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "cc" version = "1.0.66" @@ -8,26 +43,80 @@ checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "getrandom" -version = "0.2.0" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ + "autocfg", "cfg-if", - "libc", - "wasi", + "lazy_static", ] [[package]] -name = "libc" -version = "0.2.81" +name = "dirs" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.1+wasi-snapshot-preview1", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "ncurses" @@ -53,10 +142,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] -name = "rand" -version = "0.8.0" +name = "proc-macro2" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e" dependencies = [ "libc", "rand_chacha", @@ -76,11 +183,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8b34ba8cfb21243bd8df91854c830ff0d785fff2e82ebd4434c2644cb9ada18" +checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" dependencies = [ - "getrandom", + "getrandom 0.2.2", ] [[package]] @@ -92,16 +199,122 @@ dependencies = [ "rand_core", ] +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "serde" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6159e3c76cab06f6bc466244d43b35e77e9500cd685da87620addadc2a4c40b1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3fcab8778dc651bc65cfab2e4eb64996f3c912b74002fb379c94517e1f27c46" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "snake" version = "0.2.1" dependencies = [ + "dirs", "ncurses", "rand", + "serde", + "toml", ] +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index fcc0f7d..eabd376 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,9 @@ edition = "2018" [dependencies] ncurses = "5.100.0" +serde = { version = "1.0.121", features = ["derive"] } +# serde = "1.0.121" +# serde_derive = "1.0.121" +toml = "0.5.8" rand = "0.8.0" +dirs = "3.0.1" diff --git a/src/game/backend.rs b/src/game/backend.rs index 51fd9fd..e4464ac 100644 --- a/src/game/backend.rs +++ b/src/game/backend.rs @@ -1,32 +1,43 @@ extern crate rand; +use crate::settings::Config; use core::iter::Iterator; use rand::Rng; +use serde::{Deserialize, Serialize}; use std::collections::LinkedList; use std::ops::Sub; use std::thread::sleep; use std::time::Duration; -#[derive(Debug)] + +#[derive(Serialize, Deserialize, Clone, Copy)] +#[serde(tag = "type", content = "value")] +pub enum Difficulty { + Linear(f32), + Flat, +} + +#[derive(Debug, Clone, Copy)] pub enum Direction { Up, Down, Left, Right, } -impl Copy for Direction {} -impl Clone for Direction { - fn clone(&self) -> Self { - *self - } -} impl PartialEq for Direction { fn eq(&self, other: &Self) -> bool { - match (self, other) { - (&Self::Up, &Self::Up) => true, - (&Self::Down, &Self::Down) => true, - (&Self::Left, &Self::Left) => true, - (&Self::Right, &Self::Right) => true, - _ => false, - } + // match (self, other) { + // (&Self::Up, &Self::Up) => true, + // (&Self::Down, &Self::Down) => true, + // (&Self::Left, &Self::Left) => true, + // (&Self::Right, &Self::Right) => true, + // _ => false, + // } + matches!( + (self, other), + (&Self::Up, &Self::Up) + | (&Self::Down, &Self::Down) + | (&Self::Left, &Self::Left) + | (&Self::Right, &Self::Right) + ) } } @@ -41,46 +52,29 @@ impl Direction { } } #[derive(Debug)] -// impl std::fmt::Debug for Direction { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// // write!(f,) -// write!( -// f, -// "{}", -// match *self { -// Self::Up => (), -// _ => (), -// } -// ); -// } -// } - pub enum CellType { Food, Snake, - Empty, + // Empty, } +#[derive(Debug)] pub struct Cell { line: u32, col: u32, - ctype: CellType, + _ctype: CellType, } impl PartialEq for Cell { fn eq(&self, other: &Cell) -> bool { - if (self.line == other.line) && (self.col == other.col) { - return true; - } else { - return false; - } + (self.line == other.line) && (self.col == other.col) } } impl Sub for Cell { type Output = (i32, i32); fn sub(self, rhs: Cell) -> (i32, i32) { - return ( + ( self.line as i32 - rhs.line as i32, self.col as i32 - rhs.col as i32, - ); + ) } } impl Cell { @@ -88,7 +82,7 @@ impl Cell { Cell { line: l, col: c, - ctype: t, + _ctype: t, } } pub fn random(lines: u32, cols: u32) -> Cell { @@ -100,16 +94,16 @@ impl Cell { ) } pub fn posyx(&self) -> (u32, u32) { - return (self.line, self.col); + (self.line, self.col) } pub fn posy(&self) -> u32 { - return self.line; + self.line } pub fn posx(&self) -> u32 { - return self.col; + self.col } - pub fn chtype(&mut self, ctype: CellType) { - self.ctype = ctype; + pub fn _chtype(&mut self, ctype: CellType) { + self._ctype = ctype; } pub fn is_adjacent(&self, other: &Cell) -> Option { match *self - *other { @@ -135,17 +129,20 @@ impl Clone for Cell { } } +#[derive(Debug)] enum FailState { Wall, Snake, } +#[derive(Debug)] enum GameState { Failed(FailState), Ready, // Playing, } +#[derive(Debug)] pub struct Board { maxlines: u32, maxcols: u32, @@ -165,10 +162,9 @@ impl Board { } pub fn check_collision(&mut self, snake: &Snake) -> bool { let (snake_line, snake_col): (u32, u32) = snake.posyx(); - if (snake_line >= self.maxlines - 1) - || (snake_col >= self.maxcols - 1) - || (snake_line <= 0) - || (snake_col <= 0) + if (snake_line >= self.maxlines - 1) || (snake_col >= self.maxcols - 1) + // || (snake_line <= 0) + // || (snake_col <= 0) { self.gamestate = GameState::Failed(FailState::Wall); return true; @@ -182,17 +178,13 @@ impl Board { return true; } } - return false; + false } pub fn check_food(&self, snake: &Snake) -> bool { - if self.food_posyx() == snake.posyx() { - return true; - } else { - return false; - } + self.food_posyx() == snake.posyx() } pub fn food_posyx(&self) -> (u32, u32) { - return self.food.posyx(); + self.food.posyx() } // pub fn food_posy(&self) -> u32 { // return self.food.line; @@ -205,11 +197,11 @@ impl Board { pub fn spawn_food(&mut self, snake: &Snake) { let mut food: Cell = Cell::random(self.maxlines, self.maxcols); let mut spawned_food = false; - while spawned_food != true { + while !spawned_food { // check for colliosions with the snake body until a free spot is found and spawn the food there spawned_food = true; - let mut snake_iter = snake.iter(); - for snake_cell in snake_iter.next() { + let snake_iter = snake.iter(); + for snake_cell in snake_iter { if *snake_cell == food { // O(n) ; I think this is nessacary/ I don't know how to reduce the order // if food collides with the snake body then set food to a new random position and set spawned food to false @@ -228,26 +220,27 @@ pub struct Snake { head: Cell, body: LinkedList, direction: Direction, + difficulty: Difficulty, grow: bool, speed: u32, last_tail: Option, } impl Snake { - pub fn new(head: Cell) -> Snake { + pub fn new(head: Cell, config: &Config) -> Snake { let mut temp_body: LinkedList = LinkedList::new(); temp_body.push_front(head); Snake { head, body: temp_body, - // length: 1, + difficulty: config.difficulty, direction: Direction::Right, - grow: false, - speed: 15, + grow: true, + speed: config.speed, last_tail: Some(head), } } pub fn posyx(&self) -> (u32, u32) { - return (self.head.line, self.head.col); + (self.head.line, self.head.col) } pub fn smove(&mut self, _direction: Direction) { // smove because move is already a keyword @@ -257,7 +250,7 @@ impl Snake { } else { direction = _direction } - if self.grow == false { + if !self.grow { self.last_tail = Some(self.body.pop_back().unwrap()); // self.grow = false; @@ -285,16 +278,20 @@ impl Snake { sleep(Duration::from_millis((1000 / self.speed) as u64)); self.smove(self.direction); } + pub fn scale_difficulty(&mut self) { + match self.difficulty { + Difficulty::Flat => (), + Difficulty::Linear(scale) => self.speed = (self.speed as f32 * scale) as u32, + } + } pub fn grow(&mut self) { + self.scale_difficulty(); self.grow = true; } pub fn iter(&self) -> impl Iterator { - return self.body.iter(); + self.body.iter() } pub fn remove(&self) -> Option { - return self.last_tail; - } - pub fn set_speed(&mut self, speed: u32) { - self.speed = speed; + self.last_tail } } diff --git a/src/game/frontend.rs b/src/game/frontend.rs index 63cf414..0a07f2e 100644 --- a/src/game/frontend.rs +++ b/src/game/frontend.rs @@ -27,6 +27,11 @@ pub fn destroy_window(win: WINDOW) { delwin(win); // delete the window } +pub fn clear_window(win: WINDOW) { + wmove(win, 0, 0); + wclrtobot(win); +} + pub fn draw_snake(snake: &Snake, game_win: WINDOW) { // let mut snake_iter = snake.iter(); let (mut prev, mut current, _next): (&Cell, &Cell, &Cell); @@ -45,12 +50,10 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) { prev.posx() as i32, &format!("{}", std::char::from_u32(0x0298).unwrap_or('O')), ); - match snake.remove() { - Some(tail) => { - mvwaddstr(game_win, tail.posy() as i32, tail.posx() as i32, " "); - } - None => (), + if let Some(tail) = snake.remove() { + mvwaddstr(game_win, tail.posy() as i32, tail.posx() as i32, " "); } + let _current = snake_iter.next(); current = match _current { Some(cell) => cell, diff --git a/src/game/mod.rs b/src/game/mod.rs index f19b4bc..b72c81d 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,24 +1,28 @@ mod backend; mod frontend; use crate::menu; +use crate::settings::Config; // use ncurses::*; +pub use backend::Difficulty; use backend::{Board, Cell, Snake}; use ncurses::{ getmaxyx, nodelay, stdscr, wgetch, wrefresh, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_UP, WINDOW, }; -pub fn start() { +pub fn start(config: &Config) { let (mut mlines, mut mcols): (i32, i32) = (0, 0); let game_win: WINDOW; let mut ch: i32; let (vmargin, hmargin): (u32, u32) = (5, 10); getmaxyx(stdscr(), &mut mlines, &mut mcols); - game_win = frontend::game_window(mlines as u32, mcols as u32, vmargin, hmargin); - let mut snake = Snake::new(Cell::new( - mlines as u32 / 2 - vmargin, - mcols as u32 / 2 - hmargin, - backend::CellType::Snake, - )); //Initialise snake in the middle of the screen + let mut snake = Snake::new( + Cell::new( + mlines as u32 / 2 - vmargin, + mcols as u32 / 2 - hmargin, + backend::CellType::Snake, + ), + config, + ); //Initialise snake in the middle of the screen let mut board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2); nodelay(game_win, true); loop { @@ -46,15 +50,20 @@ pub fn start() { //112 is keycode for 'p' 0 => (), //resume 1 => { - snake = Snake::new(Cell::new( - mlines as u32 / 2, - mcols as u32 / 2, - backend::CellType::Snake, - )); //Initialise snake in the middle of the screen - board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2); - } //restart + snake = Snake::new( + Cell::new( + mlines as u32 / 2 - vmargin, + mcols as u32 / 2 - hmargin, + backend::CellType::Snake, + ), + config, + ); //Initialise snake in the middle of the screen + + board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2); //restart + frontend::clear_window(game_win); + } 2 => break, //exit - _ => (), //other charachters just in case + _ => (), //other charachters just in case } wrefresh(game_win); nodelay(game_win, true); diff --git a/src/main.rs b/src/main.rs index 55434c9..476b95d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate ncurses; mod game; mod highscore; mod menu; +mod settings; // use game::{Cell, Snake}; // use ncurses::*; use ncurses::{ @@ -12,6 +13,7 @@ use ncurses::{ fn main() { // let (lines, cols): (i32, i32) = (0, 0); setlocale(LcCategory::all, ""); + let config = settings::Config::new().unwrap(); initscr(); raw(); keypad(stdscr(), true); @@ -27,11 +29,12 @@ fn main() { } loop { match menu::main_menu_control() { - 0 => game::start(), + 0 => game::start(&config), 1 => highscore::show(), _ => break, } } refresh(); endwin(); + config.write(); } diff --git a/src/settings/backend.rs b/src/settings/backend.rs new file mode 100644 index 0000000..600efdb --- /dev/null +++ b/src/settings/backend.rs @@ -0,0 +1,77 @@ +extern crate dirs; +extern crate serde; +// extern crate serde_derive; +extern crate toml; +use serde::{Deserialize, Serialize}; +// use serde_derive::{Deserialize, Serialize}; +use crate::game::Difficulty; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::PathBuf; +use std::thread::sleep; + +#[derive(Serialize, Deserialize)] +pub struct Config { + pub difficulty: Difficulty, + pub speed: u32, +} + +impl Config { + pub fn new() -> Result { + let config_path = Config::config_path().unwrap(); + if config_path.exists() { + let mut config_file = File::open(config_path).unwrap(); + let mut config_file_str: String = String::new(); + config_file.read_to_string(&mut config_file_str).unwrap(); + // let config: Config = toml::from_str(&config_file_str).expect("Error in config file"); + let config: Config = match toml::from_str(&config_file_str) { + Ok(config) => config, + Err(e) => { + eprintln!( + "Error in parsing config file {} due to {}", + Config::config_path().unwrap().to_str().unwrap(), + e, + ); + eprintln!("Falling back to using the default values"); + sleep(std::time::Duration::from_millis(3000)); + Config::default() + } + }; + + Ok(config) + } else { + Ok(Config::default()) + } + } + fn default() -> Self { + Self { + difficulty: Difficulty::Flat, //Default set to ten blocks per second + speed: 10, + } + } + pub fn write(&self) { + let config_file_str: String = toml::to_string(self).unwrap(); + let config_path = Config::config_path().unwrap(); + let mut config_file: File = + File::create(config_path).expect("Couldn't open config file to write"); + config_file + .write_all(config_file_str.as_bytes()) + .expect("Couldn't write to file"); + } + fn config_path() -> Result { + let config_path: PathBuf = match dirs::config_dir() { + Some(mut path) => { + path.push("snake"); + path.push("snake.toml"); + path + } + None => { + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "snake.toml not found", + )); + } + }; + Ok(config_path) + } +} diff --git a/src/settings/mod.rs b/src/settings/mod.rs new file mode 100644 index 0000000..1db929d --- /dev/null +++ b/src/settings/mod.rs @@ -0,0 +1,2 @@ +mod backend; +pub use backend::Config;