forked from blasthavers/blastmud
Implement resolving objects from player's perspective.
This commit is contained in:
parent
dc71999591
commit
79fea1f3b5
@ -334,6 +334,66 @@ impl DBTrans {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<()> {
|
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||||
if let Some(trans) = trans_opt {
|
if let Some(trans) = trans_opt {
|
||||||
|
@ -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<()> {
|
pub async fn describe_normal_item(ctx: &VerbContext<'_>, item: &Item) -> UResult<()> {
|
||||||
ctx.trans.queue_for_session(
|
ctx.trans.queue_for_session(
|
||||||
ctx.session,
|
ctx.session,
|
||||||
Some(&format!("{}\n{}",
|
Some(&format!("{}\n{}\n",
|
||||||
explicit_if_allowed(
|
explicit_if_allowed(
|
||||||
ctx,
|
ctx,
|
||||||
&item.display,
|
&item.display,
|
||||||
@ -147,10 +147,11 @@ impl UserVerb for Verb {
|
|||||||
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||||
let player_item = get_player_item_or_fail(ctx).await?;
|
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 (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
||||||
let (itype, icode) = if remaining == "" {
|
let (itype, icode): (String, String) = if rem_trim == "" {
|
||||||
Ok((heretype, herecode))
|
Ok((heretype.to_owned(), herecode.to_owned()))
|
||||||
} else if let Some(dir) = Direction::parse(remaining) {
|
} else if let Some(dir) = Direction::parse(&rem_trim) {
|
||||||
if heretype != "room" {
|
if heretype != "room" {
|
||||||
// Fix this when we have planes / boats / roomkits.
|
// Fix this when we have planes / boats / roomkits.
|
||||||
user_error("Navigating outside rooms not yet supported.".to_owned())
|
user_error("Navigating outside rooms not yet supported.".to_owned())
|
||||||
@ -161,7 +162,7 @@ impl UserVerb for Verb {
|
|||||||
Some(exit) => {
|
Some(exit) => {
|
||||||
match room::resolve_exit(room, exit) {
|
match room::resolve_exit(room, exit) {
|
||||||
None => user_error("There is nothing in that direction".to_owned()),
|
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())
|
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 {
|
} 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()))?;
|
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?;
|
||||||
if itype != "room" {
|
if itype != "room" {
|
||||||
describe_normal_item(ctx, &item).await?;
|
describe_normal_item(ctx, &item).await?;
|
||||||
} else {
|
} else {
|
||||||
let room =
|
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?;
|
describe_room(ctx, &room, &list_item_contents(ctx, &item).await?).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -34,6 +34,7 @@ impl UserVerb for Verb {
|
|||||||
item_type: "player".to_owned(),
|
item_type: "player".to_owned(),
|
||||||
item_code: username.to_lowercase(),
|
item_code: username.to_lowercase(),
|
||||||
display: username.to_owned(),
|
display: username.to_owned(),
|
||||||
|
details: Some("A non-descript individual".to_owned()),
|
||||||
location: "room/repro_xv_chargen".to_owned(),
|
location: "room/repro_xv_chargen".to_owned(),
|
||||||
..Item::default()
|
..Item::default()
|
||||||
}).await?;
|
}).await?;
|
||||||
|
@ -24,6 +24,8 @@ CREATE TABLE items (
|
|||||||
CREATE UNIQUE INDEX item_index ON items ((details->>'item_type'), (details->>'item_code'));
|
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_loc ON items ((details->>'location'));
|
||||||
CREATE INDEX item_by_static ON items ((cast(details->>'is_static' as boolean)));
|
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 (
|
CREATE TABLE users (
|
||||||
-- Username here is all lower case, but details has correct case version.
|
-- Username here is all lower case, but details has correct case version.
|
||||||
|
Loading…
Reference in New Issue
Block a user