forked from blasthavers/blastmud
Implement resolving objects from player's perspective.
This commit is contained in:
parent
dc71999591
commit
79fea1f3b5
@ -333,6 +333,66 @@ impl DBTrans {
|
||||
.collect())
|
||||
|
||||
}
|
||||
|
||||
pub async fn resolve_items_by_display_name_for_player(
|
||||
self: &Self,
|
||||
from_item: &Item,
|
||||
query: &str,
|
||||
include_contents: bool,
|
||||
include_loc_contents: bool,
|
||||
include_active_players: bool,
|
||||
include_all_players: bool
|
||||
) -> DResult<Vec<Item>> {
|
||||
let mut ctes: Vec<String> = Vec::new();
|
||||
let mut include_tables: Vec<&'static str> = Vec::new();
|
||||
|
||||
let player_loc = &from_item.location;
|
||||
let player_desig = format!("{}/{}", from_item.item_type,
|
||||
from_item.item_code);
|
||||
if include_contents {
|
||||
ctes.push("contents AS (\
|
||||
SELECT details FROM items WHERE details->>'location' = $1
|
||||
)".to_owned());
|
||||
include_tables.push("SELECT details FROM contents");
|
||||
}
|
||||
if include_loc_contents {
|
||||
ctes.push("loc_contents AS (\
|
||||
SELECT details FROM items WHERE details->>'location' = $2
|
||||
)".to_owned());
|
||||
include_tables.push("SELECT details FROM loc_contents");
|
||||
}
|
||||
if include_active_players {
|
||||
ctes.push("active_players AS (\
|
||||
SELECT details FROM items WHERE details->>'item_type' = 'player' \
|
||||
AND current_session IS NOT NULL \
|
||||
)".to_owned());
|
||||
include_tables.push("SELECT details FROM active_players");
|
||||
}
|
||||
if include_all_players {
|
||||
ctes.push("all_players AS (\
|
||||
SELECT details FROM items WHERE details->>'item_type' = 'player'
|
||||
)".to_owned());
|
||||
include_tables.push("SELECT details FROM all_players");
|
||||
}
|
||||
ctes.push(format!("relevant_items AS ({})", include_tables.join(" UNION ")));
|
||||
|
||||
let cte_str: String = ctes.join(", ");
|
||||
|
||||
Ok(self.pg_trans()?.query(
|
||||
&format!(
|
||||
"WITH {} SELECT details FROM relevant_items WHERE (lower(details->>'display') LIKE $3) \
|
||||
OR (lower(details ->>'display_less_explicit') LIKE $3) \
|
||||
ORDER BY length(details->>'display') DESC \
|
||||
LIMIT 2", &cte_str),
|
||||
&[&player_desig, &player_loc,
|
||||
&(query.replace("\\", "\\\\")
|
||||
.replace("_", "\\_")
|
||||
.replace("%", "")
|
||||
.to_lowercase() + "%")]
|
||||
).await?.into_iter()
|
||||
.filter_map(|i| serde_json::from_value(i.get("details")).ok())
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||
|
@ -42,7 +42,7 @@ pub fn render_map(room: &room::Room, width: usize, height: usize) -> String {
|
||||
pub async fn describe_normal_item(ctx: &VerbContext<'_>, item: &Item) -> UResult<()> {
|
||||
ctx.trans.queue_for_session(
|
||||
ctx.session,
|
||||
Some(&format!("{}\n{}",
|
||||
Some(&format!("{}\n{}\n",
|
||||
explicit_if_allowed(
|
||||
ctx,
|
||||
&item.display,
|
||||
@ -147,10 +147,11 @@ impl UserVerb for Verb {
|
||||
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||
let player_item = get_player_item_or_fail(ctx).await?;
|
||||
|
||||
let rem_trim = remaining.trim().to_lowercase();
|
||||
let (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
||||
let (itype, icode) = if remaining == "" {
|
||||
Ok((heretype, herecode))
|
||||
} else if let Some(dir) = Direction::parse(remaining) {
|
||||
let (itype, icode): (String, String) = if rem_trim == "" {
|
||||
Ok((heretype.to_owned(), herecode.to_owned()))
|
||||
} else if let Some(dir) = Direction::parse(&rem_trim) {
|
||||
if heretype != "room" {
|
||||
// Fix this when we have planes / boats / roomkits.
|
||||
user_error("Navigating outside rooms not yet supported.".to_owned())
|
||||
@ -161,7 +162,7 @@ impl UserVerb for Verb {
|
||||
Some(exit) => {
|
||||
match room::resolve_exit(room, exit) {
|
||||
None => user_error("There is nothing in that direction".to_owned()),
|
||||
Some(room2) => Ok(("room", room2.code))
|
||||
Some(room2) => Ok(("room".to_owned(), room2.code.to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,16 +170,30 @@ impl UserVerb for Verb {
|
||||
user_error("Can't find your current location".to_owned())
|
||||
}
|
||||
}
|
||||
} else if rem_trim == "me" || rem_trim == "self" {
|
||||
Ok((player_item.item_type.clone(), player_item.item_code.clone()))
|
||||
} else {
|
||||
user_error("Sorry, I don't understand what you want to look at.".to_owned())
|
||||
match &ctx.trans.resolve_items_by_display_name_for_player(
|
||||
&player_item,
|
||||
&rem_trim,
|
||||
true, true, false, false
|
||||
).await?[..] {
|
||||
[] => user_error("Sorry, I couldn't find anything matching.".to_owned()),
|
||||
[match_it] => Ok((match_it.item_type.clone(), match_it.item_code.clone())),
|
||||
[item1, ..] if item1.display.to_lowercase() == rem_trim ||
|
||||
item1.display_less_explicit.as_ref().map(|x|x.to_lowercase()) == Some(rem_trim) =>
|
||||
Ok((item1.item_type.clone(), item1.item_code.clone())),
|
||||
_ => user_error("Sorry, that name is ambiguous, please be more specific.".to_owned())
|
||||
}
|
||||
}?;
|
||||
let item = ctx.trans.find_item_by_type_code(itype, icode).await?
|
||||
let item = ctx.trans.find_item_by_type_code(&itype, &icode).await?
|
||||
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?;
|
||||
if itype != "room" {
|
||||
describe_normal_item(ctx, &item).await?;
|
||||
} else {
|
||||
let room =
|
||||
room::room_map_by_code().get(icode).ok_or_else(|| UserError("Sorry, that room no longer exists".to_owned()))?;
|
||||
room::room_map_by_code().get(icode.as_str())
|
||||
.ok_or_else(|| UserError("Sorry, that room no longer exists".to_owned()))?;
|
||||
describe_room(ctx, &room, &list_item_contents(ctx, &item).await?).await?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -34,6 +34,7 @@ impl UserVerb for Verb {
|
||||
item_type: "player".to_owned(),
|
||||
item_code: username.to_lowercase(),
|
||||
display: username.to_owned(),
|
||||
details: Some("A non-descript individual".to_owned()),
|
||||
location: "room/repro_xv_chargen".to_owned(),
|
||||
..Item::default()
|
||||
}).await?;
|
||||
|
@ -24,7 +24,9 @@ CREATE TABLE items (
|
||||
CREATE UNIQUE INDEX item_index ON items ((details->>'item_type'), (details->>'item_code'));
|
||||
CREATE INDEX item_by_loc ON items ((details->>'location'));
|
||||
CREATE INDEX item_by_static ON items ((cast(details->>'is_static' as boolean)));
|
||||
|
||||
CREATE INDEX item_by_display ON items (lower(details->>'display'));
|
||||
CREATE INDEX item_by_display_less_explicit ON items (lower(details->>'display_less_explicit'));
|
||||
|
||||
CREATE TABLE users (
|
||||
-- Username here is all lower case, but details has correct case version.
|
||||
username TEXT NOT NULL PRIMARY KEY,
|
||||
|
Loading…
Reference in New Issue
Block a user