mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Track durability changes in inventory operations when breaking blocks.
fixes #847
This commit is contained in:
parent
72796f9905
commit
a85237ba2e
@ -274,6 +274,7 @@ pub const Sync = struct { // MARK: Sync
|
|||||||
.inv = .{.inv = command.payload.open.inv, .slot = @intCast(slot)},
|
.inv = .{.inv = command.payload.open.inv, .slot = @intCast(slot)},
|
||||||
.amount = stack.amount,
|
.amount = stack.amount,
|
||||||
.item = stack.item,
|
.item = stack.item,
|
||||||
|
.durability = 0,
|
||||||
};
|
};
|
||||||
const syncData = syncOp.serialize(main.stackAllocator);
|
const syncData = syncOp.serialize(main.stackAllocator);
|
||||||
defer main.stackAllocator.free(syncData);
|
defer main.stackAllocator.free(syncData);
|
||||||
@ -453,6 +454,7 @@ pub const Command = struct { // MARK: Command
|
|||||||
swap = 1,
|
swap = 1,
|
||||||
delete = 2,
|
delete = 2,
|
||||||
create = 3,
|
create = 3,
|
||||||
|
useDurability = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
const InventoryAndSlot = struct {
|
const InventoryAndSlot = struct {
|
||||||
@ -497,23 +499,31 @@ pub const Command = struct { // MARK: Command
|
|||||||
item: ?Item,
|
item: ?Item,
|
||||||
amount: u16,
|
amount: u16,
|
||||||
},
|
},
|
||||||
|
useDurability: struct {
|
||||||
|
source: InventoryAndSlot,
|
||||||
|
item: main.items.Item = undefined,
|
||||||
|
durability: u31,
|
||||||
|
previousDurability: u32 = undefined,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const SyncOperation = struct { // MARK: SyncOperation
|
const SyncOperation = struct { // MARK: SyncOperation
|
||||||
// Since the client doesn't know about all inventories, we can only use create(+amount)/delete(-amount) operations to apply the server side updates.
|
// Since the client doesn't know about all inventories, we can only use create(+amount)/delete(-amount) and use durability operations to apply the server side updates.
|
||||||
inv: InventoryAndSlot,
|
inv: InventoryAndSlot,
|
||||||
amount: i32,
|
amount: i32,
|
||||||
item: ?Item,
|
item: ?Item,
|
||||||
|
durability: i32,
|
||||||
|
|
||||||
pub fn executeFromData(data: []const u8) !void {
|
pub fn executeFromData(data: []const u8) !void {
|
||||||
std.debug.assert(data.len >= 12);
|
std.debug.assert(data.len >= 16);
|
||||||
var self = SyncOperation {
|
var self = SyncOperation {
|
||||||
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
||||||
.amount = std.mem.readInt(i32, data[8..12], .big),
|
.amount = std.mem.readInt(i32, data[8..12], .big),
|
||||||
|
.durability = std.mem.readInt(i32, data[12..16], .big),
|
||||||
.item = null,
|
.item = null,
|
||||||
};
|
};
|
||||||
if(data.len > 12) {
|
if(data.len > 16) {
|
||||||
const zon = ZonElement.parseFromString(main.stackAllocator, data[12..]);
|
const zon = ZonElement.parseFromString(main.stackAllocator, data[16..]);
|
||||||
defer zon.deinit(main.stackAllocator);
|
defer zon.deinit(main.stackAllocator);
|
||||||
self.item = try Item.init(zon);
|
self.item = try Item.init(zon);
|
||||||
}
|
}
|
||||||
@ -527,7 +537,7 @@ pub const Command = struct { // MARK: Command
|
|||||||
return error.Invalid;
|
return error.Invalid;
|
||||||
}
|
}
|
||||||
self.inv.ref().amount += @intCast(self.amount);
|
self.inv.ref().amount += @intCast(self.amount);
|
||||||
} else { // Delete
|
} else if(self.amount < 0) { // Delete
|
||||||
if(self.inv.ref().amount < -self.amount) {
|
if(self.inv.ref().amount < -self.amount) {
|
||||||
return error.Invalid;
|
return error.Invalid;
|
||||||
}
|
}
|
||||||
@ -537,13 +547,22 @@ pub const Command = struct { // MARK: Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(self.durability < 0) { // useDurability
|
||||||
|
self.inv.ref().item.?.tool.durability -|= @intCast(-self.durability);
|
||||||
|
if(self.inv.ref().item.?.tool.durability == 0) {
|
||||||
|
self.inv.ref().item = null;
|
||||||
|
self.inv.ref().amount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.inv.inv.update();
|
self.inv.inv.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize(self: SyncOperation, allocator: NeverFailingAllocator) []const u8 {
|
pub fn serialize(self: SyncOperation, allocator: NeverFailingAllocator) []const u8 {
|
||||||
var data = main.List(u8).initCapacity(allocator, 12);
|
var data = main.List(u8).initCapacity(allocator, 16);
|
||||||
self.inv.write(data.addMany(8)[0..8]);
|
self.inv.write(data.addMany(8)[0..8]);
|
||||||
std.mem.writeInt(i32, data.addMany(4)[0..4], self.amount, .big);
|
std.mem.writeInt(i32, data.addMany(4)[0..4], self.amount, .big);
|
||||||
|
std.mem.writeInt(i32, data.addMany(4)[0..4], self.durability, .big);
|
||||||
if(self.item) |item| {
|
if(self.item) |item| {
|
||||||
const zon = ZonElement.initObject(main.stackAllocator);
|
const zon = ZonElement.initObject(main.stackAllocator);
|
||||||
defer zon.deinit(main.stackAllocator);
|
defer zon.deinit(main.stackAllocator);
|
||||||
@ -617,6 +636,12 @@ pub const Command = struct { // MARK: Command
|
|||||||
}
|
}
|
||||||
info.dest.inv.update();
|
info.dest.inv.update();
|
||||||
},
|
},
|
||||||
|
.useDurability => |info| {
|
||||||
|
std.debug.assert(info.source.ref().item == null or std.meta.eql(info.source.ref().item, info.item));
|
||||||
|
info.source.ref().item = info.item;
|
||||||
|
info.item.tool.durability = info.previousDurability;
|
||||||
|
info.source.inv.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -628,6 +653,11 @@ pub const Command = struct { // MARK: Command
|
|||||||
.delete => |info| {
|
.delete => |info| {
|
||||||
info.item.?.deinit();
|
info.item.?.deinit();
|
||||||
},
|
},
|
||||||
|
.useDurability => |info| {
|
||||||
|
if(info.previousDurability <= info.durability) {
|
||||||
|
info.item.deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.baseOperations.deinit(allocator);
|
self.baseOperations.deinit(allocator);
|
||||||
@ -665,6 +695,7 @@ pub const Command = struct { // MARK: Command
|
|||||||
.inv = inv,
|
.inv = inv,
|
||||||
.amount = amount,
|
.amount = amount,
|
||||||
.item = if(inv.ref().amount == 0) item else null,
|
.item = if(inv.ref().amount == 0) item else null,
|
||||||
|
.durability = 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
std.debug.assert(inv.ref().item == null or std.meta.eql(inv.ref().item.?, item.?));
|
std.debug.assert(inv.ref().item == null or std.meta.eql(inv.ref().item.?, item.?));
|
||||||
@ -680,6 +711,7 @@ pub const Command = struct { // MARK: Command
|
|||||||
.inv = inv,
|
.inv = inv,
|
||||||
.amount = -@as(i32, amount),
|
.amount = -@as(i32, amount),
|
||||||
.item = null,
|
.item = null,
|
||||||
|
.durability = 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
inv.ref().amount -= amount;
|
inv.ref().amount -= amount;
|
||||||
@ -688,6 +720,23 @@ pub const Command = struct { // MARK: Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn executeDurabilityUseOperation(self: *Command, allocator: NeverFailingAllocator, side: Side, inv: InventoryAndSlot, durability: u31) void {
|
||||||
|
if(durability == 0) return;
|
||||||
|
if(side == .server) {
|
||||||
|
self.syncOperations.append(allocator, .{
|
||||||
|
.inv = inv,
|
||||||
|
.amount = 0,
|
||||||
|
.item = null,
|
||||||
|
.durability = -@as(i32, durability),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
inv.ref().item.?.tool.durability -|= durability;
|
||||||
|
if(inv.ref().item.?.tool.durability == 0) {
|
||||||
|
inv.ref().item = null;
|
||||||
|
inv.ref().amount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn executeBaseOperation(self: *Command, allocator: NeverFailingAllocator, _op: BaseOperation, side: Side) void { // MARK: executeBaseOperation()
|
fn executeBaseOperation(self: *Command, allocator: NeverFailingAllocator, _op: BaseOperation, side: Side) void { // MARK: executeBaseOperation()
|
||||||
var op = _op;
|
var op = _op;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
@ -716,6 +765,12 @@ pub const Command = struct { // MARK: Command
|
|||||||
self.executeAddOperation(allocator, side, info.dest, info.amount, info.item);
|
self.executeAddOperation(allocator, side, info.dest, info.amount, info.item);
|
||||||
info.dest.inv.update();
|
info.dest.inv.update();
|
||||||
},
|
},
|
||||||
|
.useDurability => |*info| {
|
||||||
|
info.item = info.source.ref().item.?;
|
||||||
|
info.previousDurability = info.item.tool.durability;
|
||||||
|
self.executeDurabilityUseOperation(allocator, side, info.source, info.durability);
|
||||||
|
info.source.inv.update();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.baseOperations.append(allocator, op);
|
self.baseOperations.append(allocator, op);
|
||||||
}
|
}
|
||||||
@ -1295,8 +1350,10 @@ pub const Command = struct { // MARK: Command
|
|||||||
.no => unreachable,
|
.no => unreachable,
|
||||||
.yes => {},
|
.yes => {},
|
||||||
.yes_costsDurability => |durability| {
|
.yes_costsDurability => |durability| {
|
||||||
// TODO: Add operations to track tool durability.
|
cmd.executeBaseOperation(allocator, .{.useDurability = .{
|
||||||
_ = durability;
|
.source = self.source,
|
||||||
|
.durability = durability,
|
||||||
|
}}, side);
|
||||||
},
|
},
|
||||||
.yes_costsItems => |amount| {
|
.yes_costsItems => |amount| {
|
||||||
cmd.executeBaseOperation(allocator, .{.delete = .{
|
cmd.executeBaseOperation(allocator, .{.delete = .{
|
||||||
|
@ -865,7 +865,7 @@ const ToolPhysics = struct { // MARK: ToolPhysics
|
|||||||
pub const Tool = struct { // MARK: Tool
|
pub const Tool = struct { // MARK: Tool
|
||||||
craftingGrid: [25]?*const BaseItem,
|
craftingGrid: [25]?*const BaseItem,
|
||||||
materialGrid: [16][16]?*const BaseItem,
|
materialGrid: [16][16]?*const BaseItem,
|
||||||
tooltip: ?[]const u8,
|
tooltip: main.List(u8),
|
||||||
image: graphics.Image,
|
image: graphics.Image,
|
||||||
texture: ?graphics.Texture,
|
texture: ?graphics.Texture,
|
||||||
seed: u32,
|
seed: u32,
|
||||||
@ -901,7 +901,7 @@ pub const Tool = struct { // MARK: Tool
|
|||||||
const self = main.globalAllocator.create(Tool);
|
const self = main.globalAllocator.create(Tool);
|
||||||
self.image = graphics.Image.init(main.globalAllocator, 16, 16);
|
self.image = graphics.Image.init(main.globalAllocator, 16, 16);
|
||||||
self.texture = null;
|
self.texture = null;
|
||||||
self.tooltip = null;
|
self.tooltip = .init(main.globalAllocator);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,7 +910,7 @@ pub const Tool = struct { // MARK: Tool
|
|||||||
texture.deinit();
|
texture.deinit();
|
||||||
}
|
}
|
||||||
self.image.deinit(main.globalAllocator);
|
self.image.deinit(main.globalAllocator);
|
||||||
if(self.tooltip) |tooltip| main.globalAllocator.free(tooltip);
|
self.tooltip.deinit();
|
||||||
main.globalAllocator.destroy(self);
|
main.globalAllocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,7 +919,7 @@ pub const Tool = struct { // MARK: Tool
|
|||||||
result.* = .{
|
result.* = .{
|
||||||
.craftingGrid = self.craftingGrid,
|
.craftingGrid = self.craftingGrid,
|
||||||
.materialGrid = self.materialGrid,
|
.materialGrid = self.materialGrid,
|
||||||
.tooltip = null,
|
.tooltip = .init(main.globalAllocator),
|
||||||
.image = graphics.Image.init(main.globalAllocator, self.image.width, self.image.height),
|
.image = graphics.Image.init(main.globalAllocator, self.image.width, self.image.height),
|
||||||
.texture = null,
|
.texture = null,
|
||||||
.seed = self.seed,
|
.seed = self.seed,
|
||||||
@ -1001,9 +1001,8 @@ pub const Tool = struct { // MARK: Tool
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn getTooltip(self: *Tool) []const u8 {
|
fn getTooltip(self: *Tool) []const u8 {
|
||||||
if(self.tooltip) |tooltip| return tooltip;
|
self.tooltip.clearRetainingCapacity();
|
||||||
self.tooltip = std.fmt.allocPrint(
|
self.tooltip.writer().print(
|
||||||
main.globalAllocator.allocator,
|
|
||||||
\\Time to swing: {d:.2} s
|
\\Time to swing: {d:.2} s
|
||||||
\\Pickaxe power: {} %
|
\\Pickaxe power: {} %
|
||||||
\\Axe power: {} %
|
\\Axe power: {} %
|
||||||
@ -1018,7 +1017,7 @@ pub const Tool = struct { // MARK: Tool
|
|||||||
self.durability, self.maxDurability,
|
self.durability, self.maxDurability,
|
||||||
}
|
}
|
||||||
) catch unreachable;
|
) catch unreachable;
|
||||||
return self.tooltip.?;
|
return self.tooltip.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPowerByBlockClass(self: *Tool, blockClass: blocks.BlockClass) f32 {
|
pub fn getPowerByBlockClass(self: *Tool, blockClass: blocks.BlockClass) f32 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user