Add /clear to clear the inventory.

fixes #781
This commit is contained in:
IntegratedQuantum 2024-11-17 13:40:28 +01:00
parent ee63168add
commit 25a8e2959a
3 changed files with 89 additions and 27 deletions

View File

@ -202,21 +202,16 @@ pub const Sync = struct { // MARK: Sync
freeIdList.append(id);
}
pub fn receiveCommand(source: *main.server.User, data: []const u8) !void {
mutex.lock();
defer mutex.unlock();
const typ: Command.PayloadType = @enumFromInt(data[0]);
@setEvalBranchQuota(100000);
const payload: Command.Payload = switch(typ) {
inline else => |_typ| @unionInit(Command.Payload, @tagName(_typ), try std.meta.FieldType(Command.Payload, _typ).deserialize(data[1..], .server, source)),
};
fn executeCommand(payload: Command.Payload, source: ?*main.server.User) void {
var command = Command {
.payload = payload,
};
command.do(main.globalAllocator, .server, source);
const confirmationData = command.confirmationData(main.stackAllocator);
defer main.stackAllocator.free(confirmationData);
main.network.Protocols.inventory.sendConfirmation(source.conn, confirmationData);
if(source != null) {
const confirmationData = command.confirmationData(main.stackAllocator);
defer main.stackAllocator.free(confirmationData);
main.network.Protocols.inventory.sendConfirmation(source.?.conn, confirmationData);
}
for(command.syncOperations.items) |op| {
const syncData = op.serialize(main.stackAllocator);
defer main.stackAllocator.free(syncData);
@ -225,7 +220,7 @@ pub const Sync = struct { // MARK: Sync
main.network.Protocols.inventory.sendSyncOperation(otherUser.conn, syncData);
}
}
if(command.payload == .open) { // Send initial items
if(source != null and command.payload == .open) { // Send initial items
for(command.payload.open.inv._items, 0..) |stack, slot| {
if(stack.item != null) {
const syncOp = Command.SyncOperation {
@ -235,13 +230,24 @@ pub const Sync = struct { // MARK: Sync
};
const syncData = syncOp.serialize(main.stackAllocator);
defer main.stackAllocator.free(syncData);
main.network.Protocols.inventory.sendSyncOperation(source.conn, syncData);
main.network.Protocols.inventory.sendSyncOperation(source.?.conn, syncData);
}
}
}
command.finalize(main.globalAllocator, .server, &.{});
}
pub fn receiveCommand(source: *main.server.User, data: []const u8) !void {
mutex.lock();
defer mutex.unlock();
const typ: Command.PayloadType = @enumFromInt(data[0]);
@setEvalBranchQuota(100000);
const payload: Command.Payload = switch(typ) {
inline else => |_typ| @unionInit(Command.Payload, @tagName(_typ), try std.meta.FieldType(Command.Payload, _typ).deserialize(data[1..], .server, source)),
};
executeCommand(payload, source);
}
fn createInventory(user: *main.server.User, clientId: u32, len: usize, typ: Inventory.Type, source: Source) void {
main.utils.assertLocked(&mutex);
switch(source) {
@ -272,11 +278,18 @@ pub const Sync = struct { // MARK: Sync
const serverId = user.inventoryClientToServerIdMap.get(clientId) orelse return null;
return inventories.items[serverId].inv;
}
};
pub fn executeCommand(payload: Command.Payload) void {
ClientSide.executeCommand(payload);
}
pub fn clearPlayerInventory(user: *main.server.User) void {
mutex.lock();
defer mutex.unlock();
var inventoryIdIterator = user.inventoryClientToServerIdMap.valueIterator();
while(inventoryIdIterator.next()) |inventoryId| {
if(inventories.items[inventoryId.*].source == .playerInventory) {
executeCommand(.{.clear = .{.inv = inventories.items[inventoryId.*].inv}}, null);
}
}
}
};
pub fn getInventory(id: u32, side: Side, user: ?*main.server.User) ?Inventory {
return switch(side) {
@ -296,6 +309,7 @@ pub const Command = struct { // MARK: Command
drop = 5,
fillFromCreative = 6,
depositOrDrop = 7,
clear = 8,
};
pub const Payload = union(PayloadType) {
open: Open,
@ -306,6 +320,7 @@ pub const Command = struct { // MARK: Command
drop: Drop,
fillFromCreative: FillFromCreative,
depositOrDrop: DepositOrDrop,
clear: Clear,
};
const BaseOperationType = enum(u8) {
@ -1081,6 +1096,37 @@ pub const Command = struct { // MARK: Command
};
}
};
const Clear = struct {
inv: Inventory,
pub fn run(self: Clear, allocator: NeverFailingAllocator, cmd: *Command, side: Side, _: ?*main.server.User) void {
if(self.inv.type == .creative) return;
if(self.inv.type == .crafting) return;
var items = self.inv._items;
if(self.inv.type == .workbench) items = self.inv._items[0..25];
for(items, 0..) |stack, slot| {
if(stack.item == null) continue;
cmd.executeBaseOperation(allocator, .{.delete = .{
.source = .{.inv = self.inv, .slot = @intCast(slot)},
.amount = stack.amount,
}}, side);
}
}
fn serialize(self: Clear, data: *main.List(u8)) void {
std.mem.writeInt(u32, data.addMany(4)[0..4], self.inv.id, .big);
}
fn deserialize(data: []const u8, side: Side, user: ?*main.server.User) !Clear {
if(data.len != 4) return error.Invalid;
const invId = std.mem.readInt(u32, data[0..4], .big);
return .{
.inv = Sync.getInventory(invId, side, user) orelse return error.Invalid,
};
}
};
};
const SourceType = enum(u8) {
@ -1110,7 +1156,7 @@ _items: []ItemStack,
pub fn init(allocator: NeverFailingAllocator, _size: usize, _type: Type, source: Source) Inventory {
const self = _init(allocator, _size, _type, .client);
Sync.executeCommand(.{.open = .{.inv = self, .source = source}});
Sync.ClientSide.executeCommand(.{.open = .{.inv = self, .source = source}});
return self;
}
@ -1131,7 +1177,7 @@ fn _init(allocator: NeverFailingAllocator, _size: usize, _type: Type, side: Side
}
pub fn deinit(self: Inventory, allocator: NeverFailingAllocator) void {
Sync.executeCommand(.{.close = .{.inv = self, .allocator = allocator}});
Sync.ClientSide.executeCommand(.{.close = .{.inv = self, .allocator = allocator}});
}
fn _deinit(self: Inventory, allocator: NeverFailingAllocator, side: Side) void {
@ -1167,15 +1213,15 @@ fn update(self: Inventory) void {
}
pub fn depositOrSwap(dest: Inventory, destSlot: u32, carried: Inventory) void {
Sync.executeCommand(.{.depositOrSwap = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = carried, .slot = 0}}});
Sync.ClientSide.executeCommand(.{.depositOrSwap = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = carried, .slot = 0}}});
}
pub fn deposit(dest: Inventory, destSlot: u32, carried: Inventory, amount: u16) void {
Sync.executeCommand(.{.deposit = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = carried, .slot = 0}, .amount = amount}});
Sync.ClientSide.executeCommand(.{.deposit = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = carried, .slot = 0}, .amount = amount}});
}
pub fn takeHalf(source: Inventory, sourceSlot: u32, carried: Inventory) void {
Sync.executeCommand(.{.takeHalf = .{.dest = .{.inv = carried, .slot = 0}, .source = .{.inv = source, .slot = sourceSlot}}});
Sync.ClientSide.executeCommand(.{.takeHalf = .{.dest = .{.inv = carried, .slot = 0}, .source = .{.inv = source, .slot = sourceSlot}}});
}
pub fn distribute(carried: Inventory, destinationInventories: []const Inventory, destinationSlots: []const u32) void {
@ -1187,23 +1233,23 @@ pub fn distribute(carried: Inventory, destinationInventories: []const Inventory,
}
pub fn depositOrDrop(dest: Inventory, source: Inventory) void {
Sync.executeCommand(.{.depositOrDrop = .{.dest = dest, .source = source}});
Sync.ClientSide.executeCommand(.{.depositOrDrop = .{.dest = dest, .source = source}});
}
pub fn dropStack(source: Inventory, sourceSlot: u32) void {
Sync.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}}});
Sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}}});
}
pub fn dropOne(source: Inventory, sourceSlot: u32) void {
Sync.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}, .desiredAmount = 1}});
Sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}, .desiredAmount = 1}});
}
pub fn fillFromCreative(dest: Inventory, destSlot: u32, item: ?Item) void {
Sync.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item}});
Sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item}});
}
pub fn fillAmountFromCreative(dest: Inventory, destSlot: u32, item: ?Item, amount: u16) void {
Sync.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item, .amount = amount}});
Sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item, .amount = amount}});
}
pub fn placeBlock(self: Inventory, slot: u32, unlimitedBlocks: bool) void {

View File

@ -1,5 +1,6 @@
pub const clear = @import("clear.zig");
pub const help = @import("help.zig");
pub const invite = @import("invite.zig");
pub const time = @import("time.zig");

View File

@ -0,0 +1,15 @@
const std = @import("std");
const main = @import("root");
const User = main.server.User;
pub const description = "Clears your inventory";
pub const usage = "/clear";
pub fn execute(args: []const u8, source: *User) void {
if(args.len != 0) {
source.sendMessage("#ff0000Too many arguments for command /clear. Expected no arguments.");
return;
}
main.items.Inventory.Sync.ServerSide.clearPlayerInventory(source);
}