diff --git a/src/wormhole/session/item/mod.rs b/src/wormhole/session/item/mod.rs index a3bf7fb..31b06a4 100644 --- a/src/wormhole/session/item/mod.rs +++ b/src/wormhole/session/item/mod.rs @@ -1,5 +1,6 @@ use super::{strerr, HandledAskKind, SessSend}; use crate::wormhole::server; +use hcor::id::ItemId; use hcor::wormhole::{ AskedNote::*, ItemAsk::{self, *}, @@ -11,6 +12,9 @@ use spawn::spawn; mod hatch; use hatch::hatch; +mod rename_gotchi; +use rename_gotchi::rename; + pub(super) fn handle_ask(ss: &mut SessSend, ask: ItemAsk) -> HandledAskKind { HandledAskKind::Direct(match ask { Spawn { item_conf, amount } => ItemSpawnResult(strerr(spawn(ss, item_conf, amount))), @@ -26,5 +30,8 @@ pub(super) fn handle_ask(ss: &mut SessSend, ask: ItemAsk) -> HandledAskKind { })) } Hatch { hatchable_item_id } => ItemHatchResult(strerr(hatch(ss, hatchable_item_id))), + GotchiNickname { item_id, new_name } => { + GotchiNicknameResult(strerr(rename(ss, item_id, new_name))) + } }) } diff --git a/src/wormhole/session/item/rename_gotchi.rs b/src/wormhole/session/item/rename_gotchi.rs new file mode 100644 index 0000000..1b7291d --- /dev/null +++ b/src/wormhole/session/item/rename_gotchi.rs @@ -0,0 +1,72 @@ +use super::SessSend; +use hcor::id::ItemId; +use hcor::{id, item, Item}; +use std::fmt; + +#[derive(Debug)] +pub enum Error { + NoSuch(id::NoSuch), +} +use Error::*; + +impl From for Error { + fn from(ns: id::NoSuch) -> Error { + Error::NoSuch(ns) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "couldn't spawn items: ")?; + match self { + NoSuch(e) => write!(f, "no such item: {}", e), + } + } +} + +pub fn rename(ss: &mut SessSend, item_id: ItemId, new_name: String) -> Result { + let item = ss.item_mut(item_id)?; + let gotchi = item.gotchi_mut()?; + gotchi.nickname = new_name.clone(); + Ok(new_name.clone()) +} + +#[cfg(all(test, features = "hcor_client"))] +mod test { + #[actix_rt::test] + /// NOTE: requires that at least one item exists in the config! + async fn spawn() -> hcor::ClientResult<()> { + use super::test::{ITEM_ARCHETYPE, ITEM_SPAWN_COUNT}; + use hcor::Hackstead; + use log::*; + + // attempt to establish logging, do nothing if it fails + // (it probably fails because it's already been established in another test) + drop(pretty_env_logger::try_init()); + + let (_, seed_arch) = hcor::CONFIG + .seeds() + .next() + .expect("No items in config that are seeds?"); + + debug!("create bob's stead"); + let mut bobstead = Hackstead::register().await?; + debug!("spawn bob some items and refresh his stead"); + + let seed_item = seed_arch.spawn().await?; + let open_tile = bobstead.free_tile().expect("New hackstead no open land?"); + + let plant = open_tile.plant_seed(seed_item).await?; + plant.rename("bob's plant jr").await?; + + //Refresh stead + bobstead = Hackstead::fetch(&bobstead).await?; + + assert_eq!(bobstead.plant(&plant).name, "bob's plant jr"); + + debug!("kill bob so he's not left in the database"); + bobstead.slaughter().await?; + + Ok(()) + } +} diff --git a/src/wormhole/session/tile/plant/nickname.rs b/src/wormhole/session/tile/plant/nickname.rs new file mode 100644 index 0000000..71527d6 --- /dev/null +++ b/src/wormhole/session/tile/plant/nickname.rs @@ -0,0 +1,151 @@ +use super::SessSend; +use hcor::{id, plant, Item, ItemId, Plant, TileId}; +use log::*; +use std::fmt; + +#[derive(Debug)] +pub enum Error { + NoSuch(id::NoSuch), +} +use Error::*; + +impl From for Error { + fn from(ns: id::NoSuch) -> Error { + Error::NoSuch(ns) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "couldn't rename plant: ")?; + match self { + NoSuch(ns) => write!(f, "{}", ns), + } + } +} + +pub fn nickname(ss: &mut SessSend, tile_id: TileId, new_name: String) -> Result { + let plant = ss.plant_mut(tile_id)?; + plant.nickname = new_name.clone(); + + Ok(new_name.clone()) +} + +#[cfg(all(feature = "hcor_client", test))] +mod test { + #[actix_rt::test] + /// NOTE: relies on item/spawn! + async fn summon() -> hcor::ClientResult<()> { + use hcor::{Hackstead, Item, Tile}; + use log::*; + + // attempt to establish logging, do nothing if it fails + // (it probably fails because it's already been established in another test) + drop(pretty_env_logger::try_init()); + + let (_, seed_arch) = hcor::CONFIG + .seeds() + .next() + .expect("no items in config that are seeds?"); + let not_seed_arch = hcor::CONFIG + .possession_archetypes + .iter() + .find(|a| a.seed.is_none()) + .expect("no items in config that aren't seeds?"); + + // create bob's stead! + let mut bobstead = Hackstead::register().await?; + + let seed_item = seed_arch.spawn().await?; + let not_seed_item = not_seed_arch.spawn().await?; + let open_tile = bobstead.free_tile().expect("fresh hackstead no open land?"); + + struct NewPlantAssumptions { + expected_success: bool, + item_consumed: bool, + } + + async fn new_plant_assuming( + bobstead: &mut Hackstead, + tile: &Tile, + seed_item: &Item, + assumptions: NewPlantAssumptions, + ) -> hcor::ClientResult<()> { + let requested_plant = tile.plant_seed(seed_item).await; + + match (assumptions.expected_success, requested_plant) { + (true, Ok(plant)) => { + assert_eq!( + plant.tile_id, tile.tile_id, + "plant planted for bob is on a different tile than expected: {:#?}", + plant + ); + assert_eq!( + seed_item.seed.as_ref().unwrap().grows_into, + plant.name, + "seed grew into unexpected type of plant" + ); + } + (false, Err(e)) => info!("/plant/new failed as expected: {}", e), + (true, Err(e)) => panic!("/plant/new unexpectedly failed: {}", e), + (false, Ok(tile)) => panic!("/plant/new unexpectedly returned plant: {:#?}", tile), + }; + + *bobstead = Hackstead::fetch(&*bobstead).await?; + + assert_eq!( + assumptions.item_consumed, + !bobstead.has_item(seed_item), + "bob's seed item was unexpectedly {}", + if assumptions.item_consumed { + "not consumed" + } else { + "consumed" + } + ); + + Ok(()) + } + + // try to plant this non-seed item + new_plant_assuming( + &mut bobstead, + &open_tile, + ¬_seed_item, + NewPlantAssumptions { + expected_success: false, + item_consumed: false, + }, + ) + .await?; + + // try and redeem an item that's actually a seed, this should actually work + new_plant_assuming( + &mut bobstead, + &open_tile, + &seed_item, + NewPlantAssumptions { + expected_success: true, + item_consumed: true, + }, + ) + .await?; + + // try and redeem the item that's already been consumed + new_plant_assuming( + &mut bobstead, + &open_tile, + &seed_item, + NewPlantAssumptions { + expected_success: false, + item_consumed: true, + }, + ) + .await?; + + // kill bob so he's not left + bobstead.slaughter().await?; + + Ok(()) + } +}