mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fix bug collecting items into full inventory
When the inventory is full and a player tries to reclaim an item from a block, collecting always failed. If the item is stackable and already present inside the inventory it should be collected though. The collect case now behaves more like the pickup case, using inventory's 'push' method to add the item and implicitly check for available space.
This commit is contained in:
parent
5d1f7d7a0a
commit
f05c120fab
@ -249,10 +249,14 @@ impl State {
|
||||
self.ecs.write_resource::<BlockChange>().set(pos, block);
|
||||
}
|
||||
|
||||
/// Set a block in this state's terrain. Will return `None` if the block has
|
||||
/// already been modified this tick.
|
||||
pub fn try_set_block(&mut self, pos: Vec3<i32>, block: Block) -> Option<()> {
|
||||
self.ecs.write_resource::<BlockChange>().try_set(pos, block)
|
||||
/// Check if the block at given position `pos` has already been modified
|
||||
/// this tick.
|
||||
pub fn can_set_block(&mut self, pos: Vec3<i32>) -> bool {
|
||||
!self
|
||||
.ecs
|
||||
.write_resource::<BlockChange>()
|
||||
.blocks
|
||||
.contains_key(&pos)
|
||||
}
|
||||
|
||||
/// Removes every chunk of the terrain.
|
||||
|
@ -100,23 +100,54 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
let block = state.terrain().get(pos).ok().copied();
|
||||
|
||||
if let Some(block) = block {
|
||||
let has_inv_space = state
|
||||
.ecs()
|
||||
.read_storage::<comp::Inventory>()
|
||||
.get(entity)
|
||||
.map(|inv| !inv.is_full())
|
||||
.unwrap_or(false);
|
||||
|
||||
if !has_inv_space {
|
||||
state.write_component(
|
||||
entity,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::CollectFailed),
|
||||
if block.is_collectible() && state.can_set_block(pos) {
|
||||
if let Some(item) = comp::Item::try_reclaim_from_block(block) {
|
||||
let (event, item_was_added) = if let Some(inv) = state
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
{
|
||||
match inv.push(item.clone()) {
|
||||
None => (
|
||||
Some(comp::InventoryUpdate::new(
|
||||
comp::InventoryUpdateEvent::Collected(item),
|
||||
)),
|
||||
true,
|
||||
),
|
||||
Some(_) => (
|
||||
Some(comp::InventoryUpdate::new(
|
||||
comp::InventoryUpdateEvent::CollectFailed,
|
||||
)),
|
||||
false,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
"Can't add item to inventory: entity has no inventory ({:?})",
|
||||
entity
|
||||
);
|
||||
(None, false)
|
||||
};
|
||||
if let Some(event) = event {
|
||||
state.write_component(entity, event);
|
||||
if item_was_added {
|
||||
// we made sure earlier the block was not already modified this tick
|
||||
state.set_block(pos, Block::empty())
|
||||
};
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
"Failed to reclaim item from block at pos={} or entity had no \
|
||||
inventory",
|
||||
pos
|
||||
)
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
"Can't reclaim item from block at pos={}: block is not collectable or was \
|
||||
already set this tick.",
|
||||
pos
|
||||
);
|
||||
} else if block.is_collectible()
|
||||
&& state.try_set_block(pos, Block::empty()).is_some()
|
||||
{
|
||||
comp::Item::try_reclaim_from_block(block)
|
||||
.map(|item| state.give_item(entity, item));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -18,8 +18,6 @@ use tracing::warn;
|
||||
use vek::*;
|
||||
|
||||
pub trait StateExt {
|
||||
/// Push an item into the provided entity's inventory
|
||||
fn give_item(&mut self, entity: EcsEntity, item: comp::Item) -> bool;
|
||||
/// Updates a component associated with the entity based on the `Effect`
|
||||
fn apply_effect(&mut self, entity: EcsEntity, effect: Effect);
|
||||
/// Build a non-player character
|
||||
@ -56,22 +54,6 @@ pub trait StateExt {
|
||||
}
|
||||
|
||||
impl StateExt for State {
|
||||
fn give_item(&mut self, entity: EcsEntity, item: comp::Item) -> bool {
|
||||
let success = self
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.map(|inv| inv.push(item.clone()).is_none())
|
||||
.unwrap_or(false);
|
||||
if success {
|
||||
self.write_component(
|
||||
entity,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Collected(item)),
|
||||
);
|
||||
}
|
||||
success
|
||||
}
|
||||
|
||||
fn apply_effect(&mut self, entity: EcsEntity, effect: Effect) {
|
||||
match effect {
|
||||
Effect::Health(change) => {
|
||||
|
Loading…
Reference in New Issue
Block a user