Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

feat: Allow renaming of Plants and Gotchi #18

Open
wants to merge 12 commits into
base: staging
Choose a base branch
from
7 changes: 7 additions & 0 deletions src/wormhole/session/item/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{strerr, HandledAskKind, SessSend};
use crate::wormhole::server;
use hcor::id::ItemId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would merge this with the imports below it, but ok

use hcor::wormhole::{
AskedNote::*,
ItemAsk::{self, *},
Expand All @@ -11,6 +12,9 @@ use spawn::spawn;
mod hatch;
use hatch::hatch;

mod rename_gotchi;
use rename_gotchi::rename;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would complain because all of them are named i.e. "hatch" and not "hatch_item", but because gotchi aren't items I can see why you named it "rename_gotchi". okay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the name of the Ask to NicknameGotchi, this should probably be nickname_gotchi but it really doesn't matter


pub(super) fn handle_ask(ss: &mut SessSend, ask: ItemAsk) -> HandledAskKind {
HandledAskKind::Direct(match ask {
Spawn {
Expand All @@ -28,5 +32,8 @@ pub(super) fn handle_ask(ss: &mut SessSend, ask: ItemAsk) -> HandledAskKind {
}))
}
Hatch { hatchable_item_id } => ItemHatchResult(strerr(hatch(ss, hatchable_item_id))),
GotchiRename { item_id, new_name } => {
GotchiRenameResult(strerr(rename(ss, item_id, new_name)))
}
})
}
95 changes: 95 additions & 0 deletions src/wormhole/session/item/rename_gotchi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use super::SessSend;
use hcor::id::ItemId;
use hcor::{id, item, ConfigError, Item};
use std::fmt;

#[derive(Debug)]
pub enum Error {
NoSuchItemConf(ConfigError),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how this error could occur outside of the context of spawning items ...

NoSuch(id::NoSuch),
}
use Error::*;

impl From<id::NoSuch> for Error {
fn from(ns: id::NoSuch) -> Error {
Error::NoSuch(ns)
}
}

impl From<hcor::ConfigError> for Error {
fn from(e: hcor::ConfigError) -> Error {
Error::NoSuchItemConf(e)
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "couldn't spawn items: ")?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were renaming gotchi, not spawning items?

match self {
NoSuchItemConf(e) => write!(f, "no such item conf: {}", e),
NoSuch(e) => write!(f, "no such item: {}", e),
}
}
}

pub fn rename(ss: &mut SessSend, item_id: ItemId, new_name: String) -> Result<String, Error> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, nickname would be better here just to match up with GotchiNickname (which I changed so it would be the same as PlantNickname)

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<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this probably shouldn't be named spawn

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());

debug!("create bob's stead");
let mut bobstead = Hackstead::register().await?;

// we'll need to keep track of how many items we have to see if spawning works.
fn count_relevant_items(hackstead: &Hackstead) -> usize {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this actually tests renaming things, like it claims to

hackstead
.inventory
.iter()
.filter(|i| i.archetype_handle == ITEM_ARCHETYPE)
.count()
}
let starting_item_count = count_relevant_items(&bobstead);

debug!("spawn bob some items and refresh his stead");
let items = bobstead
.spawn_items(ITEM_ARCHETYPE, ITEM_SPAWN_COUNT)
.await?;
bobstead = Hackstead::fetch(&bobstead).await?;

debug!("make sure those new items are in there");
assert_eq!(
count_relevant_items(&bobstead) - starting_item_count,
ITEM_SPAWN_COUNT
);

debug!("make sure each of the items the API says we got are in bob's inventory.");
for item in items {
assert!(
bobstead.inventory.contains(&item),
"bobstead did not contain spawned item: \nitem: {:#?}\ninventory: {:#?}",
item,
bobstead.inventory
);
}

debug!("kill bob so he's not left in the database");
bobstead.slaughter().await?;

Ok(())
}
}
6 changes: 6 additions & 0 deletions src/wormhole/session/tile/plant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use summon::summon;
mod rub;
use rub::rub;

mod nickname;
use nickname::nickname;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other one is named rename_gotchi, but this one is named "nickname". I know this is a bit of a nitpick, but could we be consistent here for maintenance's sake?


mod slaughter;

pub fn handle_ask(ss: &mut SessSend, ask: PlantAsk) -> AskedNote {
Expand All @@ -27,6 +30,9 @@ pub fn handle_ask(ss: &mut SessSend, ask: PlantAsk) -> AskedNote {
tile_id,
rub_item_id,
} => PlantRubStartResult(strerr(rub(ss, tile_id, rub_item_id))),
Nickname { tile_id, new_name } => {
PlantRenameResult(strerr(nickname(ss, tile_id, new_name)))
}
}
}
/*
Expand Down
151 changes: 151 additions & 0 deletions src/wormhole/session/tile/plant/nickname.rs
Original file line number Diff line number Diff line change
@@ -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<id::NoSuch> 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<String, Error> {
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<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't seem to test nicknaming anywhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and has a lot of summoning going on

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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to go out on a limb here and say this test doesn't test renaming plants, it tests spawning them ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest probably going off of i.e. rub_effects tests here, since those just panic if planting a plant goes wrong, whereas these go across every case, sometimes expecting errors, etc.

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,
&not_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(())
}
}