artificer/api/schemas/slot_array.zig

109 lines
3.1 KiB
Zig

const std = @import("std");
const json_utils = @import("../json_utils.zig");
const Server = @import("../server.zig");
const ItemId = Server.ItemId;
const assert = std.debug.assert;
const json = std.json;
const Slot = @import("./slot.zig");
pub fn BoundedSlotsArray(comptime slot_count: u32) type {
const Slots = std.BoundedArray(Slot, slot_count);
return struct {
slots: Slots,
pub fn init() @This() {
return @This(){
.slots = Slots.init(0) catch unreachable
};
}
pub fn parse(api: *Server, slots_array: json.Array) !@This() {
var slots = Slots.init(0) catch unreachable;
for (slots_array.items) |slot_value| {
const slot_obj = json_utils.asObject(slot_value) orelse return error.InvalidType;
if (try Slot.parse(api, slot_obj)) |slot| {
try slots.append(slot);
}
}
return @This(){ .slots = slots };
}
fn findSlotIndex(self: *const @This(), id: ItemId) ?usize {
for (0.., self.slots.slice()) |i, *slot| {
if (slot.id == id) {
return i;
}
}
return null;
}
fn findSlot(self: *@This(), id: ItemId) ?*Slot {
if (self.findSlotIndex(id)) |index| {
return &self.slots.buffer[index];
}
return null;
}
pub fn remove(self: *@This(), id: ItemId, quantity: u64) void {
const slot_index = self.findSlotIndex(id) orelse unreachable;
const slot = self.slots.get(slot_index);
assert(slot.quantity >= quantity);
slot.quantity -= quantity;
if (slot.quantity == 0) {
self.slots.swapRemove(slot_index);
}
}
pub fn add(self: *@This(), id: ItemId, quantity: u64) !void {
if (quantity == 0) return;
if (self.findSlot(id)) |slot| {
slot.quantity += quantity;
} else {
try self.slots.append(Slot{ .id = id, .quantity = quantity });
}
}
pub fn addSlice(self: *@This(), items: []const Server.ItemIdQuantity) void {
for (items) |item| {
self.add(item.id, item.quantity);
}
}
pub fn removeSlice(self: *@This(), items: []const Server.ItemIdQuantity) void {
for (items) |item| {
self.remove(item.id, item.quantity);
}
}
pub fn getQuantity(self: *const @This(), id: ItemId) u64 {
if (self.findSlotIndex(id)) |index| {
return self.slots.get(index).quantity;
}
return 0;
}
pub fn totalQuantity(self: *const @This()) u64 {
var count: u64 = 0;
for (self.slots.constSlice()) |slot| {
count += slot.quantity;
}
return count;
}
pub fn slice(self: *@This()) []Slot {
return self.slots.slice();
}
};
}