Implement basic NPC creation, and improve item updating.

This commit is contained in:
Condorra 2022-12-29 23:16:52 +11:00
parent cf2798a418
commit c39803898b
3 changed files with 68 additions and 3 deletions

View File

@ -12,7 +12,7 @@ use crate::models::{session::Session, user::User, item::Item};
use tokio_postgres::types::ToSql; use tokio_postgres::types::ToSql;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use serde_json; use serde_json::{self, Value};
use futures::FutureExt; use futures::FutureExt;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -228,6 +228,28 @@ impl DBTrans {
.get("item_id")) .get("item_id"))
} }
pub async fn limited_update_static_item(self: &Self, item: &Item) -> DResult<()> {
let value = serde_json::to_value(item)?;
let obj_map = value.as_object()
.expect("Static item to be object in JSON");
let mut params: Vec<&(dyn ToSql + Sync)> = vec!(&item.item_type, &item.item_code);
let mut det_ex: String = "details".to_owned();
let mut var_id = 3;
// Only copy more permanent fields, others are supposed to change over time and shouldn't
// be reset on restart.
for to_copy in ["display", "display_less_explicit", "details", "details_less_explicit",
"total_xp", "total_stats", "total_skills"] {
det_ex = format!("jsonb_set({}, '{{{}}}', ${})", det_ex, to_copy, var_id);
params.push(obj_map.get(to_copy).unwrap_or(&Value::Null));
var_id += 1;
}
self.pg_trans()?.execute(
&("UPDATE items SET details = ".to_owned() + &det_ex +
" WHERE details->>'item_type' = $1 AND details->>'item_code' = $2"),
&params).await?;
Ok(())
}
pub async fn create_user(self: &Self, session: &ListenerSession, user_dat: &User) -> DResult<()> { pub async fn create_user(self: &Self, session: &ListenerSession, user_dat: &User) -> DResult<()> {
self.pg_trans()?.execute("INSERT INTO users (\ self.pg_trans()?.execute("INSERT INTO users (\
username, current_session, current_listener, details\ username, current_session, current_listener, details\

View File

@ -5,6 +5,7 @@ use std::collections::{BTreeSet, BTreeMap};
use log::info; use log::info;
pub mod room; pub mod room;
pub mod npc;
pub struct StaticItem { pub struct StaticItem {
pub item_code: &'static str, pub item_code: &'static str,
@ -21,7 +22,7 @@ fn static_item_registry() -> Vec<StaticItemTypeGroup> {
// Must have no duplicates. // Must have no duplicates.
StaticItemTypeGroup { StaticItemTypeGroup {
item_type: "npc", item_type: "npc",
items: || Box::new(vec!().into_iter()) items: || npc::npc_static_items()
}, },
StaticItemTypeGroup { StaticItemTypeGroup {
item_type: "room", item_type: "room",
@ -55,6 +56,11 @@ async fn refresh_static_items(pool: &DBPool) -> DResult<()> {
tx.create_item(&(expected_items.get(new_item_code) tx.create_item(&(expected_items.get(new_item_code)
.unwrap().initial_item)()).await?; .unwrap().initial_item)()).await?;
} }
for existing_item_code in expected_set.intersection(&existing_items) {
tx.limited_update_static_item(
&(expected_items.get(existing_item_code)
.unwrap().initial_item)()).await?;
}
tx.commit().await?; tx.commit().await?;
info!("Committed any changes for static_content of item_type {}", type_group.item_type); info!("Committed any changes for static_content of item_type {}", type_group.item_type);
} }

View File

@ -0,0 +1,37 @@
use super::StaticItem;
use crate::models::item::Item;
use once_cell::sync::OnceCell;
pub struct NPC {
pub code: &'static str,
pub name: &'static str,
pub description: &'static str,
pub spawn_location: &'static str,
}
static NPC_LIST: OnceCell<Vec<NPC>> = OnceCell::new();
pub fn npc_list() -> &'static Vec<NPC> {
NPC_LIST.get_or_init(|| vec!(
NPC {
code: "repro_xv_chargen_statbot",
name: "Statbot",
description: "A silvery shiny metal mechanical being. It lets out a whirring sound as it moves.",
spawn_location: "room/repro_xv_chargen"
}
))
}
pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
Box::new(npc_list().iter().map(|c| StaticItem {
item_code: c.code,
initial_item: Box::new(|| Item {
item_code: c.code.to_owned(),
item_type: "npc".to_owned(),
display: c.name.to_owned(),
details: Some(c.description.to_owned()),
location: c.spawn_location.to_owned(),
is_static: true,
..Item::default()
})
}))
}