From b271a416bcc67189bb0bb429c1e803efcc7b017e Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 17 Nov 2024 21:25:37 +0100 Subject: [PATCH] Collect item drops fixes #644 --- src/Inventory.zig | 35 ++++++++++++++++++++++++++++++++--- src/itemdrop.zig | 27 +++++++++++++++++++++++++++ src/server/world.zig | 8 ++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/Inventory.zig b/src/Inventory.zig index ff429843..73e35808 100644 --- a/src/Inventory.zig +++ b/src/Inventory.zig @@ -289,6 +289,34 @@ pub const Sync = struct { // MARK: Sync } } } + + pub fn tryCollectingToPlayerInventory(user: *main.server.User, itemStack: *ItemStack) void { + if(itemStack.item == null) return; + mutex.lock(); + defer mutex.unlock(); + var inventoryIdIterator = user.inventoryClientToServerIdMap.valueIterator(); + outer: while(inventoryIdIterator.next()) |inventoryId| { + if(inventories.items[inventoryId.*].source == .playerInventory) { + const inv = inventories.items[inventoryId.*].inv; + for(inv._items, 0..) |invStack, slot| { + if(std.meta.eql(invStack.item, itemStack.item)) { + const amount = @min(itemStack.item.?.stackSize() - invStack.amount, itemStack.amount); + executeCommand(.{.fillFromCreative = .{.dest = .{.inv = inv, .slot = @intCast(slot)}, .item = itemStack.item, .amount = invStack.amount + amount}}, null); + itemStack.amount -= amount; + if(itemStack.amount == 0) break :outer; + } + } + for(inv._items, 0..) |invStack, slot| { + if(invStack.item == null) { + executeCommand(.{.fillFromCreative = .{.dest = .{.inv = inv, .slot = @intCast(slot)}, .item = itemStack.item, .amount = itemStack.amount}}, null); + itemStack.amount = 0; + break :outer; + } + } + } + } + if(itemStack.amount == 0) itemStack.item = null; + } }; pub fn getInventory(id: u32, side: Side, user: ?*main.server.User) ?Inventory { @@ -949,7 +977,7 @@ pub const Command = struct { // MARK: Command if(_items[0].item != null) { if(side == .server) { const direction = vec.rotateZ(vec.rotateX(Vec3f{0, 1, 0}, -user.?.player.rot[0]), -user.?.player.rot[2]); - main.server.world.?.drop(_items[0].clone(), user.?.player.pos, direction, 20); + main.server.world.?.dropWithCooldown(_items[0], user.?.player.pos, direction, 20, main.server.updatesPerSec*2); } } return; @@ -957,13 +985,14 @@ pub const Command = struct { // MARK: Command if(self.source.inv.type == .workbench and self.source.slot == 25) { cmd.removeToolCraftingIngredients(allocator, self.source.inv, side); } + const amount = @min(self.source.ref().amount, self.desiredAmount); if(side == .server) { const direction = vec.rotateZ(vec.rotateX(Vec3f{0, 1, 0}, -user.?.player.rot[0]), -user.?.player.rot[2]); - main.server.world.?.drop(self.source.ref().clone(), user.?.player.pos, direction, 20); + main.server.world.?.dropWithCooldown(.{.item = self.source.ref().item.?.clone(), .amount = amount}, user.?.player.pos, direction, 20, main.server.updatesPerSec*2); } cmd.executeBaseOperation(allocator, .{.delete = .{ .source = self.source, - .amount = @min(self.source.ref().amount, self.desiredAmount), + .amount = amount, }}, side); } diff --git a/src/itemdrop.zig b/src/itemdrop.zig index 08e1dae4..bbc7f099 100644 --- a/src/itemdrop.zig +++ b/src/itemdrop.zig @@ -382,6 +382,33 @@ pub const ItemDropManager = struct { // MARK: ItemDropManager } return main.game.collision.collideWithBlock(block, blockPos[0], blockPos[1], blockPos[2], pos.*, @splat(radius), @splat(0)) != null; } + + pub fn checkEntity(self: *ItemDropManager, user: *main.server.User) void { + self.mutex.lock(); + defer self.mutex.unlock(); + var ii: u32 = 0; + while(ii < self.size) { + const i = self.indices[ii]; + if(self.list.items(.pickupCooldown)[i] > 0) { + ii += 1; + continue; + } + const hitbox = main.game.Player.outerBoundingBox; + const min = user.player.pos + hitbox.min; + const max = user.player.pos + hitbox.max; + const itemPos = self.list.items(.pos)[i]; + const dist = @max(min - itemPos, itemPos - max); + if(@reduce(.Max, dist) < radius + pickupRange) { + const itemStack = &self.list.items(.itemStack)[i]; + main.items.Inventory.Sync.ServerSide.tryCollectingToPlayerInventory(user, itemStack); + if(itemStack.amount == 0) { + self.removeLocked(i); + continue; + } + } + ii += 1; + } + } }; pub const ClientItemDropManager = struct { // MARK: ClientItemDropManager diff --git a/src/server/world.zig b/src/server/world.zig index 0c1533ff..c6564727 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -824,6 +824,14 @@ pub const ServerWorld = struct { // MARK: ServerWorld // Item Entities self.itemDropManager.update(deltaTime); + { // Collect item entities: + self.lastUnimportantDataSent = newTime; + server.mutex.lock(); + defer server.mutex.unlock(); + for(server.users.items) |user| { + self.itemDropManager.checkEntity(user); + } + } // Store chunks and regions. // Stores at least one chunk and one region per iteration.