mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Change SyncOperation to use a tagged union (#958)
* change syncoperation to a tagged union * remove comments * fixes
This commit is contained in:
parent
b39cfc199c
commit
07d9451580
@ -262,20 +262,23 @@ pub const Sync = struct { // MARK: Sync
|
|||||||
for(command.syncOperations.items) |op| {
|
for(command.syncOperations.items) |op| {
|
||||||
const syncData = op.serialize(main.stackAllocator);
|
const syncData = op.serialize(main.stackAllocator);
|
||||||
defer main.stackAllocator.free(syncData);
|
defer main.stackAllocator.free(syncData);
|
||||||
for(inventories.items[op.inv.inv.id].users.items) |otherUser| {
|
|
||||||
if(otherUser == source) continue;
|
const users = op.getUsers(main.stackAllocator);
|
||||||
main.network.Protocols.inventory.sendSyncOperation(otherUser.conn, syncData);
|
defer main.stackAllocator.free(users);
|
||||||
|
|
||||||
|
for (users) |user| {
|
||||||
|
if (user == source) continue;
|
||||||
|
main.network.Protocols.inventory.sendSyncOperation(user.conn, syncData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(source != null and 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| {
|
for(command.payload.open.inv._items, 0..) |stack, slot| {
|
||||||
if(stack.item != null) {
|
if(stack.item != null) {
|
||||||
const syncOp = Command.SyncOperation {
|
const syncOp = Command.SyncOperation {.create = .{
|
||||||
.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);
|
||||||
main.network.Protocols.inventory.sendSyncOperation(source.?.conn, syncData);
|
main.network.Protocols.inventory.sendSyncOperation(source.?.conn, syncData);
|
||||||
@ -507,69 +510,154 @@ pub const Command = struct { // MARK: Command
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const SyncOperation = struct { // MARK: SyncOperation
|
const SyncOperationType = enum(u8) {
|
||||||
|
create = 0,
|
||||||
|
delete = 1,
|
||||||
|
useDurability = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SyncOperation = union(SyncOperationType) { // MARK: SyncOperation
|
||||||
// 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.
|
// 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,
|
create: struct {
|
||||||
amount: i32,
|
inv: InventoryAndSlot,
|
||||||
item: ?Item,
|
amount: u16,
|
||||||
durability: i32,
|
item: ?Item
|
||||||
|
},
|
||||||
|
delete: struct {
|
||||||
|
inv: InventoryAndSlot,
|
||||||
|
amount: u16
|
||||||
|
},
|
||||||
|
useDurability: struct {
|
||||||
|
inv: InventoryAndSlot,
|
||||||
|
durability: u32
|
||||||
|
},
|
||||||
|
|
||||||
pub fn executeFromData(data: []const u8) !void {
|
pub fn executeFromData(data: []const u8) !void {
|
||||||
std.debug.assert(data.len >= 16);
|
std.debug.assert(data.len >= 1);
|
||||||
var self = SyncOperation {
|
|
||||||
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
switch (try deserialize(data)) {
|
||||||
.amount = std.mem.readInt(i32, data[8..12], .big),
|
.create => |create| {
|
||||||
.durability = std.mem.readInt(i32, data[12..16], .big),
|
if (create.item) |item| {
|
||||||
.item = null,
|
create.inv.ref().item = item;
|
||||||
};
|
} else if (create.inv.ref().item == null) {
|
||||||
if(data.len > 16) {
|
return error.Invalid;
|
||||||
const zon = ZonElement.parseFromString(main.stackAllocator, data[16..]);
|
}
|
||||||
defer zon.deinit(main.stackAllocator);
|
|
||||||
self.item = try Item.init(zon);
|
if (create.inv.ref().amount +| create.amount > create.inv.ref().item.?.stackSize()) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
create.inv.ref().amount += create.amount;
|
||||||
|
|
||||||
|
create.inv.inv.update();
|
||||||
|
},
|
||||||
|
.delete => |delete| {
|
||||||
|
if (delete.inv.ref().amount < delete.amount) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
delete.inv.ref().amount -= delete.amount;
|
||||||
|
if (delete.inv.ref().amount == 0) {
|
||||||
|
delete.inv.ref().item = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete.inv.inv.update();
|
||||||
|
},
|
||||||
|
.useDurability => |durability| {
|
||||||
|
durability.inv.ref().item.?.tool.durability -|= durability.durability;
|
||||||
|
if (durability.inv.ref().item.?.tool.durability == 0) {
|
||||||
|
durability.inv.ref().item = null;
|
||||||
|
durability.inv.ref().amount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
durability.inv.inv.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(self.amount > 0) { // Create
|
}
|
||||||
if(self.item) |item| {
|
|
||||||
self.inv.ref().item = item;
|
pub fn getUsers(self: SyncOperation, allocator: NeverFailingAllocator) []*main.server.User {
|
||||||
} else if(self.inv.ref().item == null) {
|
switch (self) {
|
||||||
return error.Invalid;
|
inline .create, .delete, .useDurability => |data| {
|
||||||
}
|
return allocator.dupe(*main.server.User, Sync.ServerSide.inventories.items[data.inv.inv.id].users.items);
|
||||||
if(self.inv.ref().amount +| self.amount > self.inv.ref().item.?.stackSize()) {
|
|
||||||
return error.Invalid;
|
|
||||||
}
|
|
||||||
self.inv.ref().amount += @intCast(self.amount);
|
|
||||||
} else if(self.amount < 0) { // Delete
|
|
||||||
if(self.inv.ref().amount < -self.amount) {
|
|
||||||
return error.Invalid;
|
|
||||||
}
|
|
||||||
self.inv.ref().amount -= @intCast(-self.amount);
|
|
||||||
if(self.inv.ref().amount == 0) {
|
|
||||||
self.inv.ref().item = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(fullData: []const u8) !SyncOperation {
|
||||||
|
if (fullData.len == 0) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
if(self.durability < 0) { // useDurability
|
const typ: SyncOperationType = @enumFromInt(fullData[0]);
|
||||||
self.inv.ref().item.?.tool.durability -|= @intCast(-self.durability);
|
|
||||||
if(self.inv.ref().item.?.tool.durability == 0) {
|
const data = fullData[1..];
|
||||||
self.inv.ref().item = null;
|
|
||||||
self.inv.ref().amount = 0;
|
switch (typ) {
|
||||||
|
.create => {
|
||||||
|
if (data.len < 10) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
var out: SyncOperation = .{.create = .{
|
||||||
|
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
||||||
|
.amount = std.mem.readInt(u16, data[8..10], .big),
|
||||||
|
.item = null
|
||||||
|
}};
|
||||||
|
|
||||||
|
if (data.len > 10) {
|
||||||
|
const zon = ZonElement.parseFromString(main.stackAllocator, data[10..]);
|
||||||
|
defer zon.deinit(main.stackAllocator);
|
||||||
|
out.create.item = try Item.init(zon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
.delete => {
|
||||||
|
if (data.len != 10) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
const out: SyncOperation = .{.delete = .{
|
||||||
|
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
||||||
|
.amount = std.mem.readInt(u16, data[8..10], .big)
|
||||||
|
}};
|
||||||
|
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
.useDurability => {
|
||||||
|
if (data.len != 12) {
|
||||||
|
return error.Invalid;
|
||||||
|
}
|
||||||
|
const out: SyncOperation = .{.useDurability = .{
|
||||||
|
.inv = try InventoryAndSlot.read(data[0..8], .client, null),
|
||||||
|
.durability = std.mem.readInt(u32, data[8..12], .big)
|
||||||
|
}};
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 16);
|
var data = main.List(u8).initCapacity(allocator, 13);
|
||||||
self.inv.write(data.addMany(8)[0..8]);
|
data.append(@intFromEnum(self));
|
||||||
std.mem.writeInt(i32, data.addMany(4)[0..4], self.amount, .big);
|
switch (self) {
|
||||||
std.mem.writeInt(i32, data.addMany(4)[0..4], self.durability, .big);
|
.create => |create| {
|
||||||
if(self.item) |item| {
|
create.inv.write(data.addMany(8)[0..8]);
|
||||||
const zon = ZonElement.initObject(main.stackAllocator);
|
std.mem.writeInt(u16, data.addMany(2)[0..2], create.amount, .big);
|
||||||
defer zon.deinit(main.stackAllocator);
|
if(create.item) |item| {
|
||||||
item.insertIntoZon(main.stackAllocator, zon);
|
const zon = ZonElement.initObject(main.stackAllocator);
|
||||||
const string = zon.toStringEfficient(main.stackAllocator, &.{});
|
defer zon.deinit(main.stackAllocator);
|
||||||
defer main.stackAllocator.free(string);
|
item.insertIntoZon(main.stackAllocator, zon);
|
||||||
data.appendSlice(string);
|
const string = zon.toStringEfficient(main.stackAllocator, &.{});
|
||||||
|
defer main.stackAllocator.free(string);
|
||||||
|
data.appendSlice(string);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.delete => |delete| {
|
||||||
|
delete.inv.write(data.addMany(8)[0..8]);
|
||||||
|
std.mem.writeInt(u16, data.addMany(2)[0..2], delete.amount, .big);
|
||||||
|
},
|
||||||
|
.useDurability => |durability| {
|
||||||
|
durability.inv.write(data.addMany(8)[0..8]);
|
||||||
|
std.mem.writeInt(u32, data.addMany(4)[0..4], durability.durability, .big);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return data.toOwnedSlice();
|
return data.toOwnedSlice();
|
||||||
}
|
}
|
||||||
@ -691,12 +779,11 @@ pub const Command = struct { // MARK: Command
|
|||||||
if(amount == 0) return;
|
if(amount == 0) return;
|
||||||
if(item == null) return;
|
if(item == null) return;
|
||||||
if(side == .server) {
|
if(side == .server) {
|
||||||
self.syncOperations.append(allocator, .{
|
self.syncOperations.append(allocator, .{.create = .{
|
||||||
.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.?));
|
||||||
inv.ref().item = item.?;
|
inv.ref().item = item.?;
|
||||||
@ -707,12 +794,10 @@ pub const Command = struct { // MARK: Command
|
|||||||
fn executeRemoveOperation(self: *Command, allocator: NeverFailingAllocator, side: Side, inv: InventoryAndSlot, amount: u16) void {
|
fn executeRemoveOperation(self: *Command, allocator: NeverFailingAllocator, side: Side, inv: InventoryAndSlot, amount: u16) void {
|
||||||
if(amount == 0) return;
|
if(amount == 0) return;
|
||||||
if(side == .server) {
|
if(side == .server) {
|
||||||
self.syncOperations.append(allocator, .{
|
self.syncOperations.append(allocator, .{.delete = .{
|
||||||
.inv = inv,
|
.inv = inv,
|
||||||
.amount = -@as(i32, amount),
|
.amount = amount
|
||||||
.item = null,
|
}});
|
||||||
.durability = 0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
inv.ref().amount -= amount;
|
inv.ref().amount -= amount;
|
||||||
if(inv.ref().amount == 0) {
|
if(inv.ref().amount == 0) {
|
||||||
@ -723,12 +808,10 @@ pub const Command = struct { // MARK: Command
|
|||||||
fn executeDurabilityUseOperation(self: *Command, allocator: NeverFailingAllocator, side: Side, inv: InventoryAndSlot, durability: u31) void {
|
fn executeDurabilityUseOperation(self: *Command, allocator: NeverFailingAllocator, side: Side, inv: InventoryAndSlot, durability: u31) void {
|
||||||
if(durability == 0) return;
|
if(durability == 0) return;
|
||||||
if(side == .server) {
|
if(side == .server) {
|
||||||
self.syncOperations.append(allocator, .{
|
self.syncOperations.append(allocator, .{.useDurability = .{
|
||||||
.inv = inv,
|
.inv = inv,
|
||||||
.amount = 0,
|
.durability = durability
|
||||||
.item = null,
|
}});
|
||||||
.durability = -@as(i32, durability),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
inv.ref().item.?.tool.durability -|= durability;
|
inv.ref().item.?.tool.durability -|= durability;
|
||||||
if(inv.ref().item.?.tool.durability == 0) {
|
if(inv.ref().item.?.tool.durability == 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user