diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c403da276..4aec553aeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- The /give_item command can now specify the amount of items. Syntax is now `/give_item [num]` - Brighter / higher contrast main-map - Removed highlighting of non-collectible sprites - Fixed /give_exp ignoring player argument diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 1f223e3ea8..6d743f90ae 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -123,6 +123,28 @@ impl Item { } } + pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> { + use ItemKind::*; + match self.kind { + Consumable { ref mut amount, .. } => { + *amount = give_amount; + Ok(()) + }, + Utility { ref mut amount, .. } => { + *amount = give_amount; + Ok(()) + }, + Ingredient { ref mut amount, .. } => { + *amount = give_amount; + Ok(()) + }, + Tool { .. } | Lantern { .. } | Armor { .. } => { + // Tools and armor don't stack + Err(assets::Error::InvalidType) + }, + } + } + pub fn name(&self) -> &str { &self.name } pub fn description(&self) -> &str { &self.description } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index dc5de4231e..9b63633afc 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -95,9 +95,9 @@ lazy_static! { pub static ref CHAT_COMMANDS: Vec = vec![ ChatCommand::new( "give_item", - "{d}", - "/give_item \n\ - Example: common/items/debug/boost", + "{} {d}", + "/give_item [num]\n\ + Example items: common/items/apple, common/items/debug/boost", true, handle_give,), ChatCommand::new( @@ -285,25 +285,68 @@ fn handle_give( client: EcsEntity, target: EcsEntity, args: String, - _action: &ChatCommand, + action: &ChatCommand, ) { - if let Ok(item) = assets::load_cloned(&args) { - server - .state - .ecs() - .write_storage::() - .get_mut(target) - .map(|inv| inv.push(item)); - let _ = server - .state - .ecs() - .write_storage::() - .insert( - target, - comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Given), + if let (Some(item_name), give_amount_opt) = scan_fmt_some!(&args, action.arg_fmt, String, u32) { + let give_amount = give_amount_opt.unwrap_or(1); + if let Ok(item) = assets::load_cloned(&item_name) { + let mut item: Item = item; + if let Ok(()) = item.set_amount(give_amount.min(2000)) { + server + .state + .ecs() + .write_storage::() + .get_mut(target) + .map(|inv| { + if inv.push(item).is_some() { + server.notify_client( + client, + ServerMsg::private(format!( + "Player inventory full. Gave 0 of {} items.", + give_amount + )), + ); + } + }); + } else { + // This item can't stack. Give each item in a loop. + server + .state + .ecs() + .write_storage::() + .get_mut(target) + .map(|inv| { + for i in 0..give_amount { + if inv.push(item.clone()).is_some() { + server.notify_client( + client, + ServerMsg::private(format!( + "Player inventory full. Gave {} of {} items.", + i, give_amount + )), + ); + break; + } + } + }); + } + + let _ = server + .state + .ecs() + .write_storage::() + .insert( + target, + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Given), + ); + } else { + server.notify_client( + client, + ServerMsg::private(format!("Invalid item: {}", item_name)), ); + } } else { - server.notify_client(client, ServerMsg::private(String::from("Invalid item!"))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } }