@@ -533,6 +533,7 @@ pub const Command = struct { // MARK: Command
533533 drop = 5 ,
534534 fillFromCreative = 6 ,
535535 depositOrDrop = 7 ,
536+ depositToAny = 11 ,
536537 clear = 8 ,
537538 updateBlock = 9 ,
538539 addHealth = 10 ,
@@ -546,6 +547,7 @@ pub const Command = struct { // MARK: Command
546547 drop : Drop ,
547548 fillFromCreative : FillFromCreative ,
548549 depositOrDrop : DepositOrDrop ,
550+ depositToAny : DepositToAny ,
549551 clear : Clear ,
550552 updateBlock : UpdateBlock ,
551553 addHealth : AddHealth ,
@@ -1082,13 +1084,12 @@ pub const Command = struct { // MARK: Command
10821084 return true ;
10831085 }
10841086
1085- fn tryCraftingTo (self : * Command , allocator : NeverFailingAllocator , dest : InventoryAndSlot , source : InventoryAndSlot , side : Side , user : ? * main.server.User ) void { // MARK: tryCraftingTo()
1087+ fn tryCraftingTo (self : * Command , allocator : NeverFailingAllocator , dest : Inventory , source : InventoryAndSlot , side : Side , user : ? * main.server.User ) void { // MARK: tryCraftingTo()
10861088 std .debug .assert (source .inv .type == .crafting );
1087- std .debug .assert (dest .inv . type == .normal );
1089+ std .debug .assert (dest .type == .normal );
10881090 if (source .slot != source .inv ._items .len - 1 ) return ;
1089- if (dest . ref (). item != null and ! std . meta . eql ( dest .ref (). item , source .ref ().item )) return ;
1091+ if (! dest .canHold ( source .ref ().* )) return ;
10901092 if (source .ref ().item == null ) return ; // Can happen if the we didn't receive the inventory information from the server yet.
1091- if (dest .ref ().amount + source .ref ().amount > source .ref ().item .? .stackSize ()) return ;
10921093
10931094 const playerInventory : Inventory = switch (side ) {
10941095 .client = > main .game .Player .inventory ,
@@ -1138,11 +1139,21 @@ pub const Command = struct { // MARK: Command
11381139 }
11391140 std .debug .assert (remainingAmount == 0 );
11401141 }
1141- self .executeBaseOperation (allocator , .{.create = .{
1142- .dest = dest ,
1143- .amount = source .ref ().amount ,
1144- .item = source .ref ().item ,
1145- }}, side );
1142+
1143+ var remainingAmount : u16 = source .ref ().amount ;
1144+ for (dest ._items , 0.. ) | * destStack , destSlot | {
1145+ if (std .meta .eql (destStack .item , source .ref ().item ) or destStack .item == null ) {
1146+ const amount = @min (source .ref ().item .? .stackSize () - destStack .amount , remainingAmount );
1147+ self .executeBaseOperation (allocator , .{.create = .{
1148+ .dest = .{.inv = dest , .slot = @intCast (destSlot )},
1149+ .amount = amount ,
1150+ .item = source .ref ().item ,
1151+ }}, side );
1152+ remainingAmount -= amount ;
1153+ if (remainingAmount == 0 ) break ;
1154+ }
1155+ }
1156+ std .debug .assert (remainingAmount == 0 );
11461157 }
11471158
11481159 const Open = struct { // MARK: Open
@@ -1281,7 +1292,7 @@ pub const Command = struct { // MARK: Command
12811292 return ;
12821293 }
12831294 if (self .dest .inv .type == .crafting ) {
1284- cmd .tryCraftingTo (allocator , self .source , self .dest , side , user );
1295+ cmd .tryCraftingTo (allocator , self .source . inv , self .dest , side , user );
12851296 return ;
12861297 }
12871298 if (self .dest .inv .type == .workbench and self .dest .slot != 25 and self .dest .inv .type .workbench .slotInfos ()[self .dest .slot ].disabled ) return ;
@@ -1392,7 +1403,7 @@ pub const Command = struct { // MARK: Command
13921403 return ;
13931404 }
13941405 if (self .source .inv .type == .crafting ) {
1395- cmd .tryCraftingTo (allocator , self .dest , self .source , side , user );
1406+ cmd .tryCraftingTo (allocator , self .dest . inv , self .source , side , user );
13961407 return ;
13971408 }
13981409 if (self .source .inv .type == .workbench and self .source .slot != 25 and self .source .inv .type .workbench .slotInfos ()[self .source .slot ].disabled ) return ;
@@ -1458,7 +1469,7 @@ pub const Command = struct { // MARK: Command
14581469 .source = undefined ,
14591470 .callbacks = .{},
14601471 };
1461- cmd .tryCraftingTo (allocator , .{. inv = temp , . slot = 0 } , self .source , side , user );
1472+ cmd .tryCraftingTo (allocator , temp , self .source , side , user );
14621473 std .debug .assert (cmd .baseOperations .pop ().create .dest .inv ._items .ptr == temp ._items .ptr ); // Remove the extra step from undo list (we cannot undo dropped items)
14631474 if (_items [0 ].item != null ) {
14641475 if (side == .server ) {
@@ -1613,6 +1624,55 @@ pub const Command = struct { // MARK: Command
16131624 }
16141625 };
16151626
1627+ const DepositToAny = struct { // MARK: DepositToAny
1628+ dest : Inventory ,
1629+ source : InventoryAndSlot ,
1630+ amount : u16 ,
1631+
1632+ fn run (self : DepositToAny , allocator : NeverFailingAllocator , cmd : * Command , side : Side , user : ? * main.server.User , _ : Gamemode ) error {serverFailure }! void {
1633+ if (self .dest .type == .creative ) return ;
1634+ if (self .dest .type == .crafting ) return ;
1635+ if (self .dest .type == .workbench ) return ;
1636+ if (self .source .inv .type == .crafting ) {
1637+ cmd .tryCraftingTo (allocator , self .dest , self .source , side , user );
1638+ return ;
1639+ }
1640+ const sourceStack = self .source .ref ();
1641+ if (sourceStack .item == null ) return ;
1642+ if (self .amount > sourceStack .amount ) return ;
1643+ if (! self .dest .canHold (.{.item = sourceStack .item , .amount = self .amount })) return ;
1644+
1645+ var remainingAmount = self .amount ;
1646+ for (self .dest ._items , 0.. ) | * destStack , destSlot | {
1647+ if (std .meta .eql (destStack .item , sourceStack .item ) or destStack .item == null ) {
1648+ const amount = @min (sourceStack .item .? .stackSize () - destStack .amount , remainingAmount );
1649+ cmd .executeBaseOperation (allocator , .{.move = .{
1650+ .dest = .{.inv = self .dest , .slot = @intCast (destSlot )},
1651+ .source = self .source ,
1652+ .amount = amount ,
1653+ }}, side );
1654+ remainingAmount -= amount ;
1655+ if (remainingAmount == 0 ) break ;
1656+ }
1657+ }
1658+ }
1659+
1660+ fn serialize (self : DepositToAny , writer : * utils.BinaryWriter ) void {
1661+ writer .writeEnum (InventoryId , self .dest .id );
1662+ self .source .write (writer );
1663+ writer .writeInt (u16 , self .amount );
1664+ }
1665+
1666+ fn deserialize (reader : * utils.BinaryReader , side : Side , user : ? * main.server.User ) ! DepositToAny {
1667+ const destId = try reader .readEnum (InventoryId );
1668+ return .{
1669+ .dest = Sync .getInventory (destId , side , user ) orelse return error .InventoryNotFound ,
1670+ .source = try InventoryAndSlot .read (reader , side , user ),
1671+ .amount = try reader .readInt (u16 ),
1672+ };
1673+ }
1674+ };
1675+
16161676 const Clear = struct { // MARK: Clear
16171677 inv : Inventory ,
16181678
@@ -2014,6 +2074,10 @@ pub fn depositOrDrop(dest: Inventory, source: Inventory) void {
20142074 Sync .ClientSide .executeCommand (.{.depositOrDrop = .{.dest = dest , .source = source }});
20152075}
20162076
2077+ pub fn depositToAny (source : Inventory , sourceSlot : u32 , dest : Inventory , amount : u16 ) void {
2078+ Sync .ClientSide .executeCommand (.{.depositToAny = .{.dest = dest , .source = .{.inv = source , .slot = sourceSlot }, .amount = amount }});
2079+ }
2080+
20172081pub fn dropStack (source : Inventory , sourceSlot : u32 ) void {
20182082 Sync .ClientSide .executeCommand (.{.drop = .{.source = .{.inv = source , .slot = sourceSlot }}});
20192083}
@@ -2054,6 +2118,20 @@ pub fn getAmount(self: Inventory, slot: usize) u16 {
20542118 return self ._items [slot ].amount ;
20552119}
20562120
2121+ pub fn canHold (self : Inventory , sourceStack : ItemStack ) bool {
2122+ if (sourceStack .amount == 0 ) return true ;
2123+
2124+ var remainingAmount = sourceStack .amount ;
2125+ for (self ._items ) | * destStack | {
2126+ if (std .meta .eql (destStack .item , sourceStack .item ) or destStack .item == null ) {
2127+ const amount = @min (sourceStack .item .? .stackSize () - destStack .amount , remainingAmount );
2128+ remainingAmount -= amount ;
2129+ if (remainingAmount == 0 ) return true ;
2130+ }
2131+ }
2132+ return false ;
2133+ }
2134+
20572135// TODO: Remove after #480
20582136pub fn loadFromZon (self : Inventory , zon : ZonElement ) void {
20592137 for (self ._items , 0.. ) | * stack , i | {
0 commit comments