233 lines
8.4 KiB
Rust
233 lines
8.4 KiB
Rust
use std::collections::HashMap;
|
|
use std::io::Write;
|
|
use std::sync::Mutex;
|
|
use std::{env, io};
|
|
use lazy_static::lazy_static;
|
|
use serde_json::{Map, Value};
|
|
use terminal_size::{Width, Height, terminal_size};
|
|
use signal_hook::consts::signal::SIGWINCH;
|
|
use signal_hook::iterator::Signals;
|
|
use text_io::read;
|
|
|
|
mod utils;
|
|
use utils::os::*;
|
|
|
|
mod tui;
|
|
use tui::interface::draw_interface;
|
|
use tui::interface::clear_input;
|
|
|
|
mod parser;
|
|
use parser::nlp::parse_command;
|
|
|
|
mod structs;
|
|
|
|
use crate::parser::nlp::get_available_commands;
|
|
use crate::structs::json::MapData;
|
|
use crate::structs::save::SaveData;
|
|
use crate::tui::interface::draw_player_data;
|
|
use crate::tui::map::{draw_map, draw_tile};
|
|
use crate::tui::menu::display_splash_screen;
|
|
|
|
mod game;
|
|
|
|
lazy_static! {
|
|
static ref MAP_PACK: Mutex<String> = Mutex::new("".to_string());
|
|
static ref PLAYER_NAME: Mutex<String> = Mutex::new("Player".to_string());
|
|
static ref PLAYER_HEALTH: Mutex<u32> = Mutex::new(100);
|
|
static ref PLAYER_STAMINA: Mutex<u32> = Mutex::new(50);
|
|
static ref PLAYER_COORDS: Mutex<HashMap<String, (u8, u8)>> = Mutex::new(HashMap::new());
|
|
static ref PLAYER_INVENTORY: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
|
static ref FLAGS: Mutex<HashMap<String, bool>> = Mutex::new(HashMap::new());
|
|
static ref MAPS: Mutex<Vec<MapData>> = Mutex::new(Vec::new());
|
|
static ref CURRENT_MAP_ID: Mutex<String> = Mutex::new("default".to_string());
|
|
static ref LINES_OF_TEXT: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
|
}
|
|
|
|
fn main() {
|
|
set_terminal_title("Twoja Stara: The Game");
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
if args.len() > 1 && args[1] == "-d" {
|
|
return;
|
|
}
|
|
|
|
let mut signals = Signals::new(&[SIGWINCH]).expect("Failed to set up signal handling");
|
|
|
|
let min_width = 100;
|
|
let min_height = 30;
|
|
// let width: u16;
|
|
let height: u16;
|
|
|
|
loop {
|
|
clear_console();
|
|
let size = terminal_size();
|
|
if let Some((Width(w), Height(h))) = size {
|
|
if w >= min_width && h >= min_height {
|
|
// width = w;
|
|
height = h;
|
|
|
|
break;
|
|
}
|
|
|
|
println!("Terminal size is too small. Minimum size is {}x{}, but current size is {}x{}.", min_width, min_height, w, h);
|
|
|
|
signals.forever().find(|&signal| signal == SIGWINCH);
|
|
}
|
|
}
|
|
|
|
// display_splash_screen();
|
|
|
|
enum GameState {
|
|
New,
|
|
Loaded
|
|
}
|
|
|
|
let mut error = "";
|
|
let game_state: GameState;
|
|
let map_name: String;
|
|
|
|
loop {
|
|
clear_console();
|
|
display_splash_screen();
|
|
// move_cursor(0, 0);
|
|
println!("1. Start new game\n2. Load from save.json{}", error);
|
|
let choice: String = read!("{}\n");
|
|
match choice.as_str() {
|
|
"1" => {
|
|
game_state = GameState::New;
|
|
|
|
map_name = "map".to_string();
|
|
|
|
*PLAYER_NAME.lock().unwrap() = "Player".to_string();
|
|
*PLAYER_HEALTH.lock().unwrap() = 100;
|
|
*PLAYER_STAMINA.lock().unwrap() = 50;
|
|
*PLAYER_COORDS.lock().unwrap() = HashMap::new();
|
|
*PLAYER_INVENTORY.lock().unwrap() = Vec::new();
|
|
*FLAGS.lock().unwrap() = HashMap::new();
|
|
*CURRENT_MAP_ID.lock().unwrap() = map_name.to_string();
|
|
|
|
let mut lines = Vec::new();
|
|
lines.push("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
|
|
*LINES_OF_TEXT.lock().unwrap() = Vec::new();
|
|
|
|
break;
|
|
}
|
|
"2" => {
|
|
let save = utils::json::load_json("save.json");
|
|
match save {
|
|
Ok(data) => {
|
|
game_state = GameState::Loaded;
|
|
|
|
let save_data: SaveData = serde_json::from_value(data).unwrap();
|
|
let mut lines = save_data.lines_of_text;
|
|
lines.push("#(00FF00)Progress restored".to_string());
|
|
|
|
*PLAYER_NAME.lock().unwrap() = save_data.player_name;
|
|
*PLAYER_HEALTH.lock().unwrap() = save_data.health;
|
|
*PLAYER_STAMINA.lock().unwrap() = save_data.stamina;
|
|
*PLAYER_COORDS.lock().unwrap() = save_data.coords.iter().map(|(k, v)| (k.to_string(), (v[0], v[1]))).collect();
|
|
*PLAYER_INVENTORY.lock().unwrap() = save_data.inventory;
|
|
*FLAGS.lock().unwrap() = save_data.flags;
|
|
*CURRENT_MAP_ID.lock().unwrap() = save_data.current_map_id.clone();
|
|
*LINES_OF_TEXT.lock().unwrap() = lines;
|
|
|
|
map_name = save_data.map_pack;
|
|
|
|
break;
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Error loading save file: {}", e);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
_ => {
|
|
error = "\nPlease select either 1 or 2";
|
|
}
|
|
}
|
|
}
|
|
|
|
println!("Loading map: {}.json", map_name);
|
|
let json_data = utils::json::load_json(format!("{}.json", map_name).as_str());
|
|
*MAP_PACK.lock().unwrap() = map_name;
|
|
|
|
match json_data {
|
|
Ok(data) => {
|
|
let maps: Vec<MapData> = data.get("maps")
|
|
.and_then(|v| v.as_array())
|
|
.unwrap_or(&Vec::new())
|
|
.iter()
|
|
.filter_map(|v| v.as_object().cloned())
|
|
.collect::<Vec<Map<String, Value>>>()
|
|
.iter()
|
|
.filter_map(|map| {
|
|
print!("{:?}, ", map.get("id"));
|
|
serde_json::from_value(Value::Object(map.clone())).ok()
|
|
})
|
|
.collect();
|
|
*MAPS.lock().unwrap() = maps.clone();
|
|
println!("asdf{:?}", MAPS.lock().unwrap());
|
|
|
|
if matches!(game_state, GameState::New) {
|
|
let current_map_id = maps.iter()
|
|
.find(|map| map.default)
|
|
.and_then(|map| Some(map.id.clone()))
|
|
.unwrap()
|
|
.to_string();
|
|
|
|
*CURRENT_MAP_ID.lock().unwrap() = current_map_id.clone();
|
|
|
|
let mut coords = PLAYER_COORDS.lock().unwrap();
|
|
|
|
for(_, map) in maps.iter().enumerate() {
|
|
coords.insert(map.id.clone(), (
|
|
*map.starting_location.get(0).unwrap(),
|
|
*map.starting_location.get(1).unwrap()
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
// let starting_location = data.get("data")
|
|
// .and_then(|v| v.as_object())
|
|
// .and_then(|obj| obj.get("starting_location"))
|
|
// .and_then(|v| v.as_array())
|
|
// .unwrap();
|
|
|
|
// let mut a = PLAYER_COORDS.lock().unwrap();
|
|
// a.insert(current_map_id, (
|
|
// starting_location.get(0).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0),
|
|
// starting_location.get(1).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0)
|
|
// ));
|
|
|
|
// PLAYER_COORDS.lock().unwrap().0 = starting_location.get(0).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0);
|
|
// PLAYER_COORDS.lock().unwrap().1 = starting_location.get(1).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0);
|
|
// draw_map(map_data);
|
|
|
|
},
|
|
Err(e) => eprintln!("Error loading JSON data: {}", e),
|
|
}
|
|
|
|
draw_interface();
|
|
|
|
loop {
|
|
if PLAYER_INVENTORY.lock().unwrap().clone().iter().find(|x| x == &"map").is_some() { draw_map() }
|
|
move_cursor(2, height - 2);
|
|
set_cursor_visibility(true);
|
|
|
|
let line: String = read!("{}\n");
|
|
parse_command(&line);
|
|
draw_tile();
|
|
get_available_commands();
|
|
io::stdout().flush().expect("Failed to flush stdout");
|
|
// thread::sleep(std::time::Duration::from_millis(1000));
|
|
clear_input();
|
|
draw_player_data();
|
|
}
|
|
|
|
|
|
|
|
// move_cursor(width - 1, height - 1);
|
|
// loop {}
|
|
}
|