diff --git a/Cargo.lock b/Cargo.lock index fe33dfff..b5b87633 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,17 @@ version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -48,6 +59,12 @@ dependencies = [ "syn", ] +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "async-recursion" version = "1.0.0" @@ -142,6 +159,7 @@ dependencies = [ "rand", "rand_distr", "ring", + "rust_decimal", "serde", "serde_json", "serde_yaml", @@ -201,6 +219,51 @@ dependencies = [ "cipher", ] +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate", + "proc-macro2", + "syn", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "buf_redux" version = "0.8.4" @@ -217,6 +280,27 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "bytecheck" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" +dependencies = [ + "bytecheck_derive", + "ptr_meta", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -601,11 +685,23 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "headers" @@ -766,7 +862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -1183,6 +1279,15 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1216,6 +1321,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1306,6 +1431,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "rend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +dependencies = [ + "bytecheck", +] + [[package]] name = "retain_mut" version = "0.1.9" @@ -1327,6 +1461,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "rkyv" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +dependencies = [ + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rust_decimal" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" +dependencies = [ + "arrayvec", + "borsh", + "bytecheck", + "byteorder", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -1375,6 +1552,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "semver" version = "1.0.14" @@ -1776,6 +1959,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.2" diff --git a/blastmud_game/Cargo.toml b/blastmud_game/Cargo.toml index f796cb57..1df208cf 100644 --- a/blastmud_game/Cargo.toml +++ b/blastmud_game/Cargo.toml @@ -38,3 +38,4 @@ rand = "0.8.5" async-recursion = "1.0.0" rand_distr = "0.4.3" humantime = "2.1.0" +rust_decimal = "1.28.0" diff --git a/blastmud_game/src/language.rs b/blastmud_game/src/language.rs index b5fb985d..547a8637 100644 --- a/blastmud_game/src/language.rs +++ b/blastmud_game/src/language.rs @@ -1,4 +1,5 @@ use once_cell::sync::OnceCell; +use rust_decimal::Decimal; struct PluralRule<'l> { match_suffix: &'l str, @@ -69,6 +70,14 @@ pub fn join_words(words: &[&str]) -> String { } } +pub fn weight(grams: u64) -> String { + if grams > 999 { + format!("{} kg", Decimal::from_i128_with_scale(grams as i128, 3).normalize()) + } else { + format!("{} g", grams) + } +} + #[cfg(test)] mod test { #[test] @@ -117,4 +126,11 @@ mod test { assert_eq!(super::join_words(&inp[..]), outp); } } + + #[test] + fn weight_works() { + assert_eq!(super::weight(100), "100 g"); + assert_eq!(super::weight(1000), "1 kg"); + assert_eq!(super::weight(1100), "1.1 kg"); + } } diff --git a/blastmud_game/src/message_handler/user_commands.rs b/blastmud_game/src/message_handler/user_commands.rs index 01b74f4b..389d03e7 100644 --- a/blastmud_game/src/message_handler/user_commands.rs +++ b/blastmud_game/src/message_handler/user_commands.rs @@ -15,6 +15,7 @@ mod buy; mod describe; mod help; mod ignore; +mod inventory; mod less_explicit_mode; mod list; mod login; @@ -102,6 +103,9 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { // Other commands (alphabetical except aliases grouped): "attack" => attack::VERB, "buy" => buy::VERB, + "inventory" => inventory::VERB, + "inv" => inventory::VERB, + "i" => inventory::VERB, "kill" => attack::VERB, "k" => attack::VERB, diff --git a/blastmud_game/src/message_handler/user_commands/inventory.rs b/blastmud_game/src/message_handler/user_commands/inventory.rs new file mode 100644 index 00000000..b20302e6 --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/inventory.rs @@ -0,0 +1,58 @@ +use super::{ + VerbContext, UserVerb, UserVerbRef, UResult, + get_player_item_or_fail, +}; +use crate::{ + language::weight, + static_content::possession_type::{ + possession_data, + PossessionType + }, + models::item::Item, +}; +use async_trait::async_trait; +use itertools::Itertools; +use std::sync::Arc; + +pub struct Verb; +#[async_trait] +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?; + if player_item.is_dead { + ctx.trans.queue_for_session(ctx.session, Some("The dead don't really have an inventory.\n")).await?; + } + let inv = ctx.trans.find_items_by_location(&format!("{}/{}", + &player_item.item_type, + &player_item.item_code)).await?; + let all_groups: Vec>> = inv + .iter() + .group_by(|i| i.display_for_sentence(true, 1, false)) + .into_iter() + .map(|(_, g)|g.collect::>>()) + .collect::>>>(); + let mut response = String::new(); + for items in all_groups { + let item = items[0]; + if item.item_type != "possession" { + continue; + } + if let Some(posdat) = possession_data().get( + &item.possession_type.as_ref().unwrap_or(&PossessionType::AntennaWhip)) { + response.push_str(&format!("{} [{}]\n", + item.display_for_sentence( + !ctx.session_dat.less_explicit_mode, + items.len(), + true + ), weight(posdat.weight))); + } + } + if response == "" { + response.push_str("You aren't carrying anything.\n"); + } + ctx.trans.queue_for_session(ctx.session, Some(&response)).await?; + Ok(()) + } +} +static VERB_INT: Verb = Verb; +pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; diff --git a/blastmud_game/src/static_content/possession_type.rs b/blastmud_game/src/static_content/possession_type.rs index f155a357..38ac549d 100644 --- a/blastmud_game/src/static_content/possession_type.rs +++ b/blastmud_game/src/static_content/possession_type.rs @@ -61,6 +61,7 @@ pub struct PossessionData { pub details_less_explicit: Option<&'static str>, pub aliases: Vec<&'static str>, pub max_health: u64, + pub weight: u64, } impl Default for PossessionData { @@ -73,6 +74,7 @@ impl Default for PossessionData { details_less_explicit: None, aliases: vec!(), max_health: 10, + weight: 100, } } }