Overflow slots as slots

This commit is contained in:
Sam 2023-08-18 14:00:57 -04:00
parent 93ca630a13
commit d01997ca56
11 changed files with 109 additions and 1 deletions

View File

@ -9,5 +9,5 @@ ItemDef(
), ),
quality: Debug, quality: Debug,
tags: [], tags: [],
slots: 900, slots: 1,
) )

View File

@ -1119,6 +1119,13 @@ impl Client {
pub fn swap_slots(&mut self, a: Slot, b: Slot) { pub fn swap_slots(&mut self, a: Slot, b: Slot) {
match (a, b) { match (a, b) {
(Slot::Overflow(o), Slot::Inventory(inv))
| (Slot::Inventory(inv), Slot::Overflow(o)) => {
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent(
InventoryEvent::OverflowMove(o, inv),
)));
},
(Slot::Overflow(_), _) | (_, Slot::Overflow(_)) => {},
(Slot::Equip(equip), slot) | (slot, Slot::Equip(equip)) => self.control_action( (Slot::Equip(equip), slot) | (slot, Slot::Equip(equip)) => self.control_action(
ControlAction::InventoryAction(InventoryAction::Swap(equip, slot)), ControlAction::InventoryAction(InventoryAction::Swap(equip, slot)),
), ),
@ -1138,6 +1145,9 @@ impl Client {
Slot::Inventory(inv) => self.send_msg(ClientGeneral::ControlEvent( Slot::Inventory(inv) => self.send_msg(ClientGeneral::ControlEvent(
ControlEvent::InventoryEvent(InventoryEvent::Drop(inv)), ControlEvent::InventoryEvent(InventoryEvent::Drop(inv)),
)), )),
Slot::Overflow(o) => self.send_msg(ClientGeneral::ControlEvent(
ControlEvent::InventoryEvent(InventoryEvent::OverflowDrop(o)),
)),
} }
} }
@ -1173,6 +1183,7 @@ impl Client {
InventoryEvent::SplitSwap(inv1, inv2), InventoryEvent::SplitSwap(inv1, inv2),
))) )))
}, },
(Slot::Overflow(_), _) | (_, Slot::Overflow(_)) => {},
} }
} }
@ -1184,6 +1195,9 @@ impl Client {
Slot::Inventory(inv) => self.send_msg(ClientGeneral::ControlEvent( Slot::Inventory(inv) => self.send_msg(ClientGeneral::ControlEvent(
ControlEvent::InventoryEvent(InventoryEvent::SplitDrop(inv)), ControlEvent::InventoryEvent(InventoryEvent::SplitDrop(inv)),
)), )),
Slot::Overflow(o) => self.send_msg(ClientGeneral::ControlEvent(
ControlEvent::InventoryEvent(InventoryEvent::OverflowSplitDrop(o)),
)),
} }
} }
@ -1393,6 +1407,7 @@ impl Client {
if let Some(item) = match item { if let Some(item) = match item {
Slot::Equip(equip_slot) => inv.equipped(equip_slot), Slot::Equip(equip_slot) => inv.equipped(equip_slot),
Slot::Inventory(invslot) => inv.get(invslot), Slot::Inventory(invslot) => inv.get(invslot),
Slot::Overflow(_) => None,
} { } {
item.has_durability() item.has_durability()
} else { } else {

View File

@ -31,6 +31,9 @@ pub enum InventoryEvent {
craft_event: CraftEvent, craft_event: CraftEvent,
craft_sprite: Option<VolumePos>, craft_sprite: Option<VolumePos>,
}, },
OverflowMove(usize, InvSlotId),
OverflowDrop(usize),
OverflowSplitDrop(usize),
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -86,6 +89,11 @@ impl From<InventoryEvent> for InventoryManip {
craft_event, craft_event,
craft_sprite, craft_sprite,
}, },
InventoryEvent::OverflowMove(o, inv) => {
Self::Swap(Slot::Overflow(o), Slot::Inventory(inv))
},
InventoryEvent::OverflowDrop(o) => Self::Drop(Slot::Overflow(o)),
InventoryEvent::OverflowSplitDrop(o) => Self::SplitDrop(Slot::Overflow(o)),
} }
} }
} }

View File

@ -524,11 +524,38 @@ impl Inventory {
*self.slot_mut(b).unwrap() = slot_a; *self.slot_mut(b).unwrap() = slot_a;
} }
/// Moves an item from an overflow slot to an inventory slot
pub fn move_overflow_item(&mut self, overflow: usize, inv_slot: InvSlotId) {
match self.slot(inv_slot) {
Some(Some(_)) => {
warn!("Attempted to move from overflow slot to a filled inventory slot");
return;
},
None => {
warn!("Attempted to move from overflow slot to a non-existent inventory slot");
return;
},
Some(None) => {},
};
let item = self.overflow_items.remove(overflow);
*self.slot_mut(inv_slot).unwrap() = Some(item);
}
/// Remove an item from the slot /// Remove an item from the slot
pub fn remove(&mut self, inv_slot_id: InvSlotId) -> Option<Item> { pub fn remove(&mut self, inv_slot_id: InvSlotId) -> Option<Item> {
self.slot_mut(inv_slot_id).and_then(|item| item.take()) self.slot_mut(inv_slot_id).and_then(|item| item.take())
} }
/// Remove an item from an overflow slot
pub fn overflow_remove(&mut self, overflow_slot: usize) -> Option<Item> {
if overflow_slot < self.overflow_items.len() {
Some(self.overflow_items.remove(overflow_slot))
} else {
None
}
}
/// Remove just one item from the slot /// Remove just one item from the slot
pub fn take( pub fn take(
&mut self, &mut self,
@ -579,6 +606,34 @@ impl Inventory {
} }
} }
/// Takes half of the items from an overflow slot
pub fn overflow_take_half(
&mut self,
overflow_slot: usize,
ability_map: &AbilityMap,
msm: &MaterialStatManifest,
) -> Option<Item> {
if let Some(item) = self.overflow_items.get_mut(overflow_slot) {
if item.is_stackable() && item.amount() > 1 {
let mut return_item = item.duplicate(ability_map, msm);
let returning_amount = item.amount() / 2;
item.decrease_amount(returning_amount).ok()?;
return_item.set_amount(returning_amount).expect(
"return_item.amount() = item.amount() / 2 < item.amount() (since \
item.amount() 1) item.max_amount() = return_item.max_amount(), since \
return_item is a duplicate of item",
);
Some(return_item)
} else if overflow_slot < self.overflow_items.len() {
Some(self.overflow_items.remove(overflow_slot))
} else {
None
}
} else {
None
}
}
/// Takes all items from the inventory /// Takes all items from the inventory
pub fn drain(&mut self) -> impl Iterator<Item = Item> + '_ { pub fn drain(&mut self) -> impl Iterator<Item = Item> + '_ {
self.slots_mut() self.slots_mut()
@ -781,6 +836,15 @@ impl Inventory {
self.loadout.swap_slots(slot_a, slot_b, time); self.loadout.swap_slots(slot_a, slot_b, time);
Vec::new() Vec::new()
}, },
(Slot::Overflow(overflow_slot), Slot::Inventory(inv_slot))
| (Slot::Inventory(inv_slot), Slot::Overflow(overflow_slot)) => {
self.move_overflow_item(overflow_slot, inv_slot);
Vec::new()
},
// Items from overflow slots cannot be equipped until moved into a real inventory slot
(Slot::Overflow(_), Slot::Equip(_)) | (Slot::Equip(_), Slot::Overflow(_)) => Vec::new(),
// Items cannot be moved between overflow slots
(Slot::Overflow(_), Slot::Overflow(_)) => Vec::new(),
} }
} }
@ -976,6 +1040,8 @@ impl Inventory {
self.loadout self.loadout
.repair_item_at_slot(equip_slot, ability_map, msm); .repair_item_at_slot(equip_slot, ability_map, msm);
}, },
// Items in overflow slots cannot be repaired until they are moved to a real slot
Slot::Overflow(_) => {},
} }
} }

View File

@ -15,6 +15,7 @@ pub enum SlotError {
pub enum Slot { pub enum Slot {
Inventory(InvSlotId), Inventory(InvSlotId),
Equip(EquipSlot), Equip(EquipSlot),
Overflow(usize),
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
@ -111,6 +112,7 @@ impl Slot {
match (self, item_kind) { match (self, item_kind) {
(Self::Inventory(_), _) => true, (Self::Inventory(_), _) => true,
(Self::Equip(slot), item_kind) => slot.can_hold(item_kind), (Self::Equip(slot), item_kind) => slot.can_hold(item_kind),
(Self::Overflow(_), _) => true,
} }
} }
} }

View File

@ -1030,6 +1030,8 @@ impl RepairRecipeBook {
if let Some(item) = match item { if let Some(item) = match item {
Slot::Equip(slot) => inv.equipped(slot), Slot::Equip(slot) => inv.equipped(slot),
Slot::Inventory(slot) => inv.get(slot), Slot::Inventory(slot) => inv.get(slot),
// Items in overflow slots cannot be repaired until item is moved to a real slot
Slot::Overflow(_) => None,
} { } {
if let Some(repair_recipe) = self.repair_recipe(item) { if let Some(repair_recipe) = self.repair_recipe(item) {
repair_recipe repair_recipe

View File

@ -1141,6 +1141,9 @@ pub fn handle_manipulate_loadout(
let inv_manip = InventoryManip::Use(slot); let inv_manip = InventoryManip::Use(slot);
output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip));
}, },
InventoryAction::Use(Slot::Overflow(_)) => {
// Items in overflow slots cannot be used until moved to a real slot
},
InventoryAction::ToggleSpriteLight(pos, enable) => { InventoryAction::ToggleSpriteLight(pos, enable) => {
if matches!(pos.kind, Volume::Terrain) { if matches!(pos.kind, Volume::Terrain) {
let sprite_interact = sprite_interact::SpriteInteractKind::ToggleLight(enable); let sprite_interact = sprite_interact::SpriteInteractKind::ToggleLight(enable);

View File

@ -559,6 +559,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
} }
Some(InventoryUpdateEvent::Used) Some(InventoryUpdateEvent::Used)
}, },
// Items in overflow slots cannot be used
Slot::Overflow(_) => None,
}; };
drop(inventories); drop(inventories);
@ -663,6 +665,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
let item = match slot { let item = match slot {
Slot::Inventory(slot) => inventory.take_half(slot, &ability_map, &msm), Slot::Inventory(slot) => inventory.take_half(slot, &ability_map, &msm),
Slot::Equip(_) => None, Slot::Equip(_) => None,
Slot::Overflow(_) => None,
}; };
if let Some(item) = item { if let Some(item) = item {
@ -686,6 +689,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
let item = match slot { let item = match slot {
Slot::Inventory(slot) => inventory.remove(slot), Slot::Inventory(slot) => inventory.remove(slot),
Slot::Equip(slot) => inventory.replace_loadout_item(slot, None, time), Slot::Equip(slot) => inventory.replace_loadout_item(slot, None, time),
Slot::Overflow(slot) => inventory.overflow_remove(slot),
}; };
// FIXME: We should really require the drop and write to be atomic! // FIXME: We should really require the drop and write to be atomic!
@ -717,6 +721,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
let item = match slot { let item = match slot {
Slot::Inventory(slot) => inventory.take_half(slot, ability_map, &msm), Slot::Inventory(slot) => inventory.take_half(slot, ability_map, &msm),
Slot::Equip(_) => None, Slot::Equip(_) => None,
Slot::Overflow(o) => inventory.overflow_take_half(o, ability_map, &msm),
}; };
// FIXME: We should really require the drop and write to be atomic! // FIXME: We should really require the drop and write to be atomic!

View File

@ -1576,6 +1576,7 @@ impl<'a> Widget for Crafting<'a> {
modifier: craft_slot_2.and_then(|slot| match slot { modifier: craft_slot_2.and_then(|slot| match slot {
Slot::Inventory(slot) => Some(slot), Slot::Inventory(slot) => Some(slot),
Slot::Equip(_) => None, Slot::Equip(_) => None,
Slot::Overflow(_) => None,
}), }),
}); });
} }
@ -1736,6 +1737,7 @@ impl<'a> Widget for Crafting<'a> {
.and_then(|slot| match slot { .and_then(|slot| match slot {
Slot::Inventory(slot) => self.inventory.get(slot), Slot::Inventory(slot) => self.inventory.get(slot),
Slot::Equip(_) => None, Slot::Equip(_) => None,
Slot::Overflow(_) => None,
}) })
.and_then(|item| item.item_definition_id().itemdef_id().map(String::from)) .and_then(|item| item.item_definition_id().itemdef_id().map(String::from))
{ {
@ -1746,6 +1748,7 @@ impl<'a> Widget for Crafting<'a> {
.and_then(|slot| match slot { .and_then(|slot| match slot {
Slot::Inventory(slot) => self.inventory.get(slot), Slot::Inventory(slot) => self.inventory.get(slot),
Slot::Equip(_) => None, Slot::Equip(_) => None,
Slot::Overflow(_) => None,
}) })
.and_then(|item| { .and_then(|item| {
item.item_definition_id().itemdef_id().map(String::from) item.item_definition_id().itemdef_id().map(String::from)
@ -1769,6 +1772,7 @@ impl<'a> Widget for Crafting<'a> {
if let Some(item) = match craft_slot_1 { if let Some(item) = match craft_slot_1 {
Some(Slot::Inventory(slot)) => self.inventory.get(slot), Some(Slot::Inventory(slot)) => self.inventory.get(slot),
Some(Slot::Equip(slot)) => self.inventory.equipped(slot), Some(Slot::Equip(slot)) => self.inventory.equipped(slot),
Some(Slot::Overflow(_)) => None,
None => None, None => None,
} { } {
if let Some(recipe) = self.client.repair_recipe_book().repair_recipe(item) { if let Some(recipe) = self.client.repair_recipe_book().repair_recipe(item) {

View File

@ -286,6 +286,7 @@ impl CraftSlot {
match self.slot { match self.slot {
Some(Slot::Inventory(slot)) => inv.get(slot), Some(Slot::Inventory(slot)) => inv.get(slot),
Some(Slot::Equip(slot)) => inv.equipped(slot), Some(Slot::Equip(slot)) => inv.equipped(slot),
Some(Slot::Overflow(_)) => None,
None => None, None => None,
} }
} }

View File

@ -1753,6 +1753,7 @@ impl PlayState for SessionState {
move_allowed = false; move_allowed = false;
} }
}, },
Slot::Overflow(_) => {},
} }
}; };
} }
@ -2021,6 +2022,7 @@ impl PlayState for SessionState {
let item = match item { let item = match item {
Slot::Equip(slot) => inventory.equipped(slot), Slot::Equip(slot) => inventory.equipped(slot),
Slot::Inventory(slot) => inventory.get(slot), Slot::Inventory(slot) => inventory.get(slot),
Slot::Overflow(_) => None,
}?; }?;
let repair_recipe = let repair_recipe =
client.repair_recipe_book().repair_recipe(item)?; client.repair_recipe_book().repair_recipe(item)?;