use std::collections::HashMap; use std::str::FromStr; use mio::Token; use crate::actions::look; use crate::command::Command; use crate::database::Db; use crate::queue::SendQueue; use crate::world::{Direction, Exit, Room}; use crate::{try_option_send_error, try_send_error}; /// Look at the room. Provide room name, description, and exits. pub fn dig(command: &Command, args: String, token: Token, db: &mut Db) -> SendQueue { let mut send_queue = SendQueue::new(); // find the player let mut player = try_option_send_error!(token, db.get_connected_player(token)); // get the direction to dig let direction = match Direction::from_str(&args) { Ok(d) => d, Err(e) => { send_queue.push(token, format!("{}", e), true); return send_queue; } }; // get starting room let mut start_room = try_option_send_error!(token, db.load_room(player.location)); // make sure exit doesn't already exist if start_room.exits.contains_key(&direction) { send_queue.push(token, "Exit already exists", true); return send_queue; } // get starting zone let mut zone = try_option_send_error!(token, db.load_zone(start_room.zone)); let new_room_id = try_send_error!(token, db.new_area_id()); // create a new, empty room let mut new_room = Room { id: new_room_id, zone: start_room.zone, name: format!("New Room {}", new_room_id), description: Vec::new(), users_visible: true, exits: HashMap::new(), }; // add exit from start room to new room let _ = start_room.exits.insert( direction, Exit { target: new_room.id, direction, }, ); // add exit from new room to start room let _ = new_room.exits.insert( direction.opposite(), Exit { target: start_room.id, direction: direction.opposite(), }, ); // add new room to zone let _ = zone.areas.insert(new_room.id); // save the new room if db.save_room(&new_room).is_ok() { send_queue.push(token, "New room saved\n", false); } else { send_queue.push(token, "Unable to save new room", true); return send_queue; } // save the start room if db.save_room(&start_room).is_ok() { send_queue.push(token, "Start room saved\n", false); } else { send_queue.push(token, "Unable to save start room", true); return send_queue; } // save the zone if db.save_zone(&zone).is_ok() { send_queue.push(token, "Zone saved\n", false); } else { send_queue.push(token, "Unable to save zone", true); return send_queue; } // move and save the player player.location = new_room.id; if db.save_player(&player).is_ok() { if db.save_connected_player(token, &player).is_ok() { send_queue.push(token, format!("You dig {}.\n\n", direction.long()), false); } else { send_queue.push(token, "Unable to save connected player", true); } } else { send_queue.push(token, "Unable to save player", true); return send_queue; } // inform people about what just took place for (neighbor_token, _) in try_send_error!(token, db.find_connected_players_by_location(start_room.id)) { if neighbor_token != token { send_queue.push( neighbor_token, format!("{} digs {}.", player.name, direction.long()), true, ); } } send_queue.append(&mut look(&command, args, token, db)); send_queue }