Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Inventory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub const ServerSide = struct { // MARK: ServerSide
if(self.managed == .internallyManaged) {
if(self.inv.type.shouldDepositToUserOnClose()) {
const playerInventory = getInventoryFromSource(.{.playerInventory = user.id}) orelse @panic("Could not find player inventory");
sync.ServerSide.executeCommand(.{.depositOrDrop = .{.dest = playerInventory, .source = self.inv, .dropLocation = user.player.pos}}, null);
sync.ServerSide.executeCommand(.{.depositOrDrop = .init(&.{playerInventory}, self.inv, user.player.pos)}, null);
}
inventoryCreationMutex.lock();
defer inventoryCreationMutex.unlock();
Expand Down Expand Up @@ -502,8 +502,8 @@ pub fn distribute(carried: Inventory, destinationInventories: []const Inventory,
}
}

pub fn depositOrDrop(dest: Inventory, source: Inventory) void {
main.sync.ClientSide.executeCommand(.{.depositOrDrop = .{.dest = dest, .source = source, .dropLocation = undefined}});
pub fn depositOrDrop(source: Inventory, destinations: []const Inventory) void {
main.sync.ClientSide.executeCommand(.{.depositOrDrop = .init(destinations, source, undefined)});
}

pub fn depositToAny(source: Inventory, sourceSlot: u32, destinations: []const Inventory, amount: u16) void {
Expand Down
2 changes: 1 addition & 1 deletion src/gui/gui.zig
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ pub fn toggleGameMenu() void {
if(!main.Window.grabbed) {
hideGui = false;
} else { // Take of the currently held item stack and close some windows
main.game.Player.inventory.depositOrDrop(inventory.carried);
inventory.carried.depositOrDrop(&.{main.game.Player.inventory});
hoveredItemSlot = null;
var i: usize = 0;
while(i < openWindows.items.len) {
Expand Down
83 changes: 64 additions & 19 deletions src/sync.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1284,40 +1284,72 @@ pub const Command = struct { // MARK: Command
};

const DepositOrDrop = struct { // MARK: DepositOrDrop
dest: Inventory,
destinations: []const Inventory,
source: Inventory,
dropLocation: Vec3d,

pub fn init(destinations: []const Inventory, source: Inventory, dropLocation: Vec3d) DepositOrDrop {
return .{
.destinations = main.globalAllocator.dupe(Inventory, destinations),
.source = source,
.dropLocation = dropLocation,
};
}

fn finalize(self: DepositOrDrop, _: Side, _: *BinaryReader) !void {
main.globalAllocator.free(self.destinations);
}

pub fn run(self: DepositOrDrop, ctx: Context) error{serverFailure}!void {
std.debug.assert(self.dest.type == .normal);
for(self.destinations) |dest| {
std.debug.assert(dest.type == .normal);
}
if(self.source.type == .creative) return;
if(self.source.type == .crafting) return;
var sourceItems = self.source._items;
if(self.source.type == .workbench) sourceItems = self.source._items[0..25];
outer: for(sourceItems, 0..) |*sourceStack, sourceSlot| {
if(sourceStack.item == .null) continue;
for(self.dest._items, 0..) |*destStack, destSlot| {
if(std.meta.eql(destStack.item, sourceStack.item)) {
const amount = @min(destStack.item.stackSize() - destStack.amount, sourceStack.amount);
ctx.execute(.{.move = .{
.dest = .{.inv = self.dest, .slot = @intCast(destSlot)},
.source = .{.inv = self.source, .slot = @intCast(sourceSlot)},
.amount = amount,
}});
if(sourceStack.amount == 0) {
continue :outer;
var selectedEmptySlot: ?u32 = null;
var selectedEmptyInv: ?Inventory = null;
for(self.destinations) |dest| {
var emptySlot: ?u32 = null;
var hasItem = false;
for(dest._items, 0..) |*destStack, destSlot| {
if(destStack.item == .null and emptySlot == null) {
emptySlot = @intCast(destSlot);
if(selectedEmptySlot == null) {
selectedEmptySlot = emptySlot;
selectedEmptyInv = dest;
}
}
if(std.meta.eql(destStack.item, sourceStack.item)) {
hasItem = true;
const amount = @min(sourceStack.item.stackSize() - destStack.amount, sourceStack.amount);
if(amount == 0) continue;
ctx.execute(.{.move = .{
.dest = .{.inv = dest, .slot = @intCast(destSlot)},
.source = .{.inv = self.source, .slot = @intCast(sourceSlot)},
.amount = amount,
}});
if(sourceStack.amount == 0) continue :outer;
}
}
}
for(self.dest._items, 0..) |*destStack, destSlot| {
if(destStack.item == .null) {
if(emptySlot != null and hasItem) {
ctx.execute(.{.swap = .{
.dest = .{.inv = self.dest, .slot = @intCast(destSlot)},
.dest = .{.inv = dest, .slot = emptySlot.?},
.source = .{.inv = self.source, .slot = @intCast(sourceSlot)},
}});
continue :outer;
}
}
if(selectedEmptySlot != null) {
ctx.execute(.{.swap = .{
.dest = .{.inv = selectedEmptyInv.?, .slot = selectedEmptySlot.?},
.source = .{.inv = self.source, .slot = @intCast(sourceSlot)},
}});
continue :outer;
}
if(ctx.side == .server) {
const direction = if(ctx.user) |_user| vec.rotateZ(vec.rotateX(Vec3f{0, 1, 0}, -_user.player.rot[0]), -_user.player.rot[2]) else Vec3f{0, 0, 0};
main.server.world.?.drop(sourceStack.clone(), self.dropLocation, direction, 20);
Expand All @@ -1330,15 +1362,28 @@ pub const Command = struct { // MARK: Command
}

fn serialize(self: DepositOrDrop, writer: *BinaryWriter) void {
writer.writeEnum(InventoryId, self.dest.id);
writer.writeVarInt(usize, self.destinations.len);
for(self.destinations) |dest| {
writer.writeEnum(InventoryId, dest.id);
}
writer.writeEnum(InventoryId, self.source.id);
}

fn deserialize(reader: *BinaryReader, side: Side, user: ?*main.server.User) !DepositOrDrop {
const destId = try reader.readEnum(InventoryId);
const destinationsSize = try reader.readVarInt(usize);
if(destinationsSize == 0) return error.Invalid;
if(destinationsSize*@sizeOf(InventoryId) >= reader.remaining.len) return error.Invalid;

const destinations = main.globalAllocator.alloc(Inventory, destinationsSize);
errdefer main.globalAllocator.free(destinations);

for(destinations) |*dest| {
const invId = try reader.readEnum(InventoryId);
dest.* = Inventory.getInventory(invId, side, user) orelse return error.InventoryNotFound;
}
const sourceId = try reader.readEnum(InventoryId);
return .{
.dest = Inventory.getInventory(destId, side, user) orelse return error.InventoryNotFound,
.destinations = destinations[0..],
.source = Inventory.getInventory(sourceId, side, user) orelse return error.InventoryNotFound,
.dropLocation = (user orelse return error.Invalid).player.pos,
};
Expand Down