Implement lmap command for dynzones.
This commit is contained in:
parent
a78b3b4892
commit
b6ed5ea487
@ -3,8 +3,11 @@ use super::{VerbContext, UserVerb, UserVerbRef, UResult, UserError, user_error,
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use ansi::{ansi, flow_around};
|
use ansi::{ansi, flow_around};
|
||||||
use crate::{
|
use crate::{
|
||||||
models::item::Item,
|
models::item::{Item, ItemSpecialData},
|
||||||
static_content::room::{self, Direction}
|
static_content::{
|
||||||
|
room::{self, Direction, GridCoords},
|
||||||
|
dynzone::self
|
||||||
|
}
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -91,7 +94,139 @@ pub fn render_lmap(room: &room::Room, width: usize, height: usize,
|
|||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn caption_lmap(captions: &Vec<(usize, &'static str, &'static str)>, width: usize, height: usize) -> String {
|
pub fn render_lmap_dynroom<'l, 'm>(
|
||||||
|
zone: &'l dynzone::Dynzone,
|
||||||
|
room: &'l dynzone::Dynroom,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
captions_needed: &'m mut Vec<(usize, &'l str, &'l str)>,
|
||||||
|
connectwhere: Option<&'l str>
|
||||||
|
) -> String {
|
||||||
|
let mut buf = String::new();
|
||||||
|
let my_loc = &room.grid_coords;
|
||||||
|
let min_x = my_loc.x - (width as i64) / 2;
|
||||||
|
let max_x = min_x + (width as i64);
|
||||||
|
let min_y = my_loc.y - (height as i64) / 2;
|
||||||
|
let max_y = min_y + (height as i64);
|
||||||
|
|
||||||
|
let main_exit_dat: Option<(GridCoords, Direction)> = zone.dyn_rooms
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(_, dr)|
|
||||||
|
dr.exits.iter()
|
||||||
|
.filter(|ex| match ex.target {
|
||||||
|
dynzone::ExitTarget::ExitZone => true,
|
||||||
|
_ => false
|
||||||
|
})
|
||||||
|
.map(|ex| (dr.grid_coords.apply(&ex.direction), ex.direction.clone()))
|
||||||
|
).next();
|
||||||
|
let main_exit = main_exit_dat.as_ref();
|
||||||
|
|
||||||
|
for y in min_y..max_y {
|
||||||
|
for x in min_x..max_x {
|
||||||
|
let coord = room::GridCoords { x, y, z: my_loc.z };
|
||||||
|
let coord_room: Option<&dynzone::Dynroom> =
|
||||||
|
zone.dyn_rooms.iter()
|
||||||
|
.find(
|
||||||
|
|(_, dr)| dr.grid_coords.x == x &&
|
||||||
|
dr.grid_coords.y == y &&
|
||||||
|
dr.grid_coords.z == my_loc.z)
|
||||||
|
.map(|(_, r)| r);
|
||||||
|
if my_loc.x == x && my_loc.y == y {
|
||||||
|
buf.push_str(ansi!("<bgblue><red> () <reset>"));
|
||||||
|
if let Some(room) = coord_room {
|
||||||
|
if room.should_caption {
|
||||||
|
captions_needed.push(
|
||||||
|
(
|
||||||
|
(((my_loc.x as i64 - room.grid_coords.x).abs() +
|
||||||
|
(my_loc.y as i64 - room.grid_coords.y).abs()) as usize),
|
||||||
|
room.short, room.name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(room) = coord_room {
|
||||||
|
if room.should_caption {
|
||||||
|
captions_needed.push(
|
||||||
|
(
|
||||||
|
(((my_loc.x as i64 - room.grid_coords.x).abs() +
|
||||||
|
(my_loc.y as i64 - room.grid_coords.y).abs()) as usize),
|
||||||
|
room.short, room.name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
buf.push('[');
|
||||||
|
buf.push_str(room.short);
|
||||||
|
buf.push(']');
|
||||||
|
match room.exits.iter().find(|ex| ex.direction == Direction::EAST) {
|
||||||
|
None => buf.push(' '),
|
||||||
|
Some(_) => buf.push('-')
|
||||||
|
}
|
||||||
|
} else if main_exit.map(|ex| &ex.0) == Some(&coord) {
|
||||||
|
buf.push_str("[<<]");
|
||||||
|
match main_exit {
|
||||||
|
Some((ex_coord, Direction::WEST)) => {
|
||||||
|
buf.push('-');
|
||||||
|
if let Some(connect) = connectwhere {
|
||||||
|
captions_needed.push((
|
||||||
|
((my_loc.x as i64 - ex_coord.x).abs() + (my_loc.y as i64 - ex_coord.y).abs())
|
||||||
|
as usize,
|
||||||
|
"<<", connect
|
||||||
|
))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => buf.push(' ')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.push_str(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for x in min_x..max_x {
|
||||||
|
let mut coord = room::GridCoords { x, y, z: my_loc.z };
|
||||||
|
let coord_room: Option<&'l dynzone::Dynroom> =
|
||||||
|
zone.dyn_rooms.iter()
|
||||||
|
.find(
|
||||||
|
|(_, dr)| dr.grid_coords.x == x &&
|
||||||
|
dr.grid_coords.y == y &&
|
||||||
|
dr.grid_coords.z == my_loc.z)
|
||||||
|
.map(|(_, r)| r);
|
||||||
|
match coord_room.and_then(
|
||||||
|
|r| r.exits.iter().find(|ex| ex.direction == Direction::SOUTH)) {
|
||||||
|
Some(_) => buf.push_str(" | "),
|
||||||
|
None if main_exit == Some(&(coord.clone(), Direction::NORTH)) =>
|
||||||
|
buf.push_str(" | "),
|
||||||
|
None => buf.push_str(" "),
|
||||||
|
}
|
||||||
|
let has_se = coord_room.and_then(
|
||||||
|
|r| r.exits.iter().find(|ex| ex.direction == Direction::SOUTHEAST))
|
||||||
|
.is_some() || (main_exit == Some(&(coord.clone(), Direction::NORTHWEST)));
|
||||||
|
coord.y += 1;
|
||||||
|
let coord_room_s =
|
||||||
|
zone.dyn_rooms.iter()
|
||||||
|
.find(
|
||||||
|
|(_, dr)| dr.grid_coords.x == x &&
|
||||||
|
dr.grid_coords.y == y &&
|
||||||
|
dr.grid_coords.z == my_loc.z)
|
||||||
|
.map(|(_, r)| r);
|
||||||
|
let has_ne = coord_room_s.and_then(
|
||||||
|
|r| r.exits.iter().find(|ex| ex.direction == Direction::NORTHEAST))
|
||||||
|
.is_some() || (main_exit == Some(&(coord, Direction::SOUTHWEST)));
|
||||||
|
if has_se && has_ne {
|
||||||
|
buf.push('X');
|
||||||
|
} else if has_se {
|
||||||
|
buf.push('\\');
|
||||||
|
} else if has_ne {
|
||||||
|
buf.push('/');
|
||||||
|
} else {
|
||||||
|
buf.push(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.push('\n');
|
||||||
|
}
|
||||||
|
captions_needed.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn caption_lmap<'l>(captions: &Vec<(usize, &'l str, &'l str)>, width: usize, height: usize) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
for room in captions.iter().take(height) {
|
for room in captions.iter().take(height) {
|
||||||
buf.push_str(&format!(ansi!("{}<bold>: {:.*}<reset>\n"), room.1, width, room.2));
|
buf.push_str(&format!(ansi!("{}<bold>: {:.*}<reset>\n"), room.1, width, room.2));
|
||||||
@ -111,6 +246,48 @@ pub async fn lmap_room(ctx: &VerbContext<'_>,
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn lmap_room_dyn<'a>(
|
||||||
|
ctx: &VerbContext<'_>,
|
||||||
|
zone: &'a dynzone::Dynzone,
|
||||||
|
room: &'a dynzone::Dynroom,
|
||||||
|
zoneref: &str
|
||||||
|
) -> UResult<()> {
|
||||||
|
let mut captions: Vec<(usize, &str, &str)> = Vec::new();
|
||||||
|
let connectwhere_name_opt: Option<String> = match zoneref.split_once("/") {
|
||||||
|
None => None,
|
||||||
|
Some((zone_t, zone_c)) => {
|
||||||
|
let zone_item: Option<Arc<Item>> = ctx.trans.find_item_by_type_code(zone_t, zone_c).await?;
|
||||||
|
match zone_item.as_ref().map(|v| v.as_ref()) {
|
||||||
|
Some(Item { special_data: Some(ItemSpecialData::DynzoneData { zone_exit: Some(zone_exit), ..}),
|
||||||
|
..}) =>
|
||||||
|
match zone_exit.split_once("/") {
|
||||||
|
None => None,
|
||||||
|
Some((ex_t, ex_c)) =>
|
||||||
|
match ctx.trans.find_item_by_type_code(ex_t, ex_c).await?.as_ref() {
|
||||||
|
Some(dest_item) => Some(
|
||||||
|
dest_item.display_for_sentence(
|
||||||
|
!ctx.session_dat.less_explicit_mode, 1, true
|
||||||
|
)),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let lmap_str =
|
||||||
|
render_lmap_dynroom(zone, room, 9, 7, &mut captions,
|
||||||
|
connectwhere_name_opt.as_ref().map(|v| v.as_str()));
|
||||||
|
ctx.trans.queue_for_session(
|
||||||
|
ctx.session,
|
||||||
|
Some(&flow_around(&lmap_str,
|
||||||
|
45, ansi!("<reset> "),
|
||||||
|
&caption_lmap(&captions, 14, 27), 31
|
||||||
|
))
|
||||||
|
).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Verb;
|
pub struct Verb;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl UserVerb for Verb {
|
impl UserVerb for Verb {
|
||||||
@ -122,13 +299,25 @@ impl UserVerb for Verb {
|
|||||||
let (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
let (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
||||||
let room_item: Arc<Item> = ctx.trans.find_item_by_type_code(heretype, herecode).await?
|
let room_item: Arc<Item> = ctx.trans.find_item_by_type_code(heretype, herecode).await?
|
||||||
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?;
|
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?;
|
||||||
if room_item.item_type != "room" {
|
if room_item.item_type == "room" {
|
||||||
user_error("Can't map here".to_owned())?;
|
|
||||||
} else {
|
|
||||||
let room =
|
let room =
|
||||||
room::room_map_by_code().get(room_item.item_code.as_str())
|
room::room_map_by_code().get(room_item.item_code.as_str())
|
||||||
.ok_or_else(|| UserError("Sorry, that room no longer exists".to_owned()))?;
|
.ok_or_else(|| UserError("Sorry, that room no longer exists".to_owned()))?;
|
||||||
lmap_room(ctx, &room).await?;
|
lmap_room(ctx, &room).await?;
|
||||||
|
} else if room_item.item_type == "dynroom" {
|
||||||
|
let (dynzone, dynroom) = match &room_item.special_data {
|
||||||
|
Some(ItemSpecialData::DynroomData { dynzone_code, dynroom_code }) => {
|
||||||
|
dynzone::DynzoneType::from_str(dynzone_code.as_str())
|
||||||
|
.and_then(|dz_t|
|
||||||
|
dynzone::dynzone_by_type().get(&dz_t))
|
||||||
|
.and_then(|dz| dz.dyn_rooms.get(dynroom_code.as_str()).map(|dr| (dz, dr)))
|
||||||
|
.ok_or_else(|| UserError("Dynamic room doesn't exist anymore.".to_owned()))?
|
||||||
|
},
|
||||||
|
_ => user_error("Expected dynroom to have DynroomData".to_owned())?
|
||||||
|
};
|
||||||
|
lmap_room_dyn(ctx, &dynzone, &dynroom, &room_item.location).await?;
|
||||||
|
} else {
|
||||||
|
user_error("Can't map here".to_owned())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ pub fn zone() -> Dynzone {
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
grid_coords: GridCoords { x: 0, y: 0, z: 0 },
|
grid_coords: GridCoords { x: 0, y: 0, z: 0 },
|
||||||
should_caption: false,
|
should_caption: true,
|
||||||
item_flags: vec!(),
|
item_flags: vec!(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
@ -52,7 +52,7 @@ pub fn zone() -> Dynzone {
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
grid_coords: GridCoords { x: 1, y: 0, z: 0 },
|
grid_coords: GridCoords { x: 1, y: 0, z: 0 },
|
||||||
should_caption: false,
|
should_caption: true,
|
||||||
item_flags: vec!(),
|
item_flags: vec!(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user