Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 121 additions & 70 deletions src/Inventory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -382,36 +382,149 @@ pub const Source = union(SourceType) {
other: void,
};

pub const ClientInventory = struct { // MARK: ClientInventory
const ClientType = enum {
serverShared,
creative,
};
super: Inventory,
type: ClientType,

pub fn init(allocator: NeverFailingAllocator, _size: usize, _type: Type, clientType: ClientType, source: Source, callbacks: Callbacks) ClientInventory {
const self: ClientInventory = .{
.super = Inventory._init(allocator, _size, _type, source, .client, callbacks),
.type = clientType,
};
if(clientType == .serverShared) {
sync.ClientSide.executeCommand(.{.open = .{.inv = self.super, .source = source}});
}
return self;
}

pub fn deinit(self: ClientInventory, allocator: NeverFailingAllocator) void {
if(main.game.world.?.connected) {
sync.ClientSide.executeCommand(.{.close = .{.inv = self.super, .allocator = allocator}});
} else {
main.sync.ClientSide.mutex.lock();
defer main.sync.ClientSide.mutex.unlock();
self.super._deinit(allocator, .client);
}
}

pub fn depositOrSwap(dest: ClientInventory, destSlot: u32, carried: ClientInventory) void {
if(dest.type == .creative) {
carried.fillFromCreative(0, dest.getItem(destSlot));
return;
}
main.sync.ClientSide.executeCommand(.{.depositOrSwap = .{.dest = .{.inv = dest.super, .slot = destSlot}, .source = .{.inv = carried.super, .slot = 0}}});
}

pub fn deposit(dest: ClientInventory, destSlot: u32, source: ClientInventory, sourceSlot: u32, amount: u16) void {
if(source.type == .creative) {
std.debug.assert(dest.type == .serverShared);
dest.fillFromCreative(destSlot, source.getItem(sourceSlot));
return;
}
std.debug.assert(source.type == .serverShared);
main.sync.ClientSide.executeCommand(.{.deposit = .{.dest = .{.inv = dest.super, .slot = destSlot}, .source = .{.inv = source.super, .slot = sourceSlot}, .amount = amount}});
}

pub fn takeHalf(source: ClientInventory, sourceSlot: u32, carried: ClientInventory) void {
if(carried.type == .creative) {
carried.fillFromCreative(0, source.getItem(sourceSlot));
return;
}
main.sync.ClientSide.executeCommand(.{.takeHalf = .{.dest = .{.inv = carried.super, .slot = 0}, .source = .{.inv = source.super, .slot = sourceSlot}}});
}

pub fn distribute(carried: ClientInventory, destinationInventories: []const ClientInventory, destinationSlots: []const u32) void {
const amount = carried.getAmount(0)/destinationInventories.len;
if(amount == 0) return;
for(0..destinationInventories.len) |i| {
destinationInventories[i].deposit(destinationSlots[i], carried, 0, @intCast(amount));
}
}

pub fn depositOrDrop(dest: ClientInventory, source: ClientInventory) void {
std.debug.assert(dest.type == .serverShared);
std.debug.assert(source.type != .creative);
main.sync.ClientSide.executeCommand(.{.depositOrDrop = .{.dest = dest.super, .source = source.super, .dropLocation = undefined}});
}

pub fn depositToAny(source: ClientInventory, sourceSlot: u32, destinations: []const ClientInventory, amount: u16) void {
std.debug.assert(source.type != .creative);
for(destinations) |inv| std.debug.assert(inv.super.type == .normal);
main.sync.ClientSide.executeCommand(.{.depositToAny = .init(destinations, .{.inv = source.super, .slot = sourceSlot}, amount)});
}

pub fn dropStack(source: ClientInventory, sourceSlot: u32) void {
if(source.type == .creative) return;
main.sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source.super, .slot = sourceSlot}}});
}

pub fn dropOne(source: ClientInventory, sourceSlot: u32) void {
if(source.type == .creative) return;
main.sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source.super, .slot = sourceSlot}, .desiredAmount = 1}});
}

pub fn fillFromCreative(dest: ClientInventory, destSlot: u32, item: Item) void {
main.sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest.super, .slot = destSlot}, .item = item}});
}

pub fn fillAmountFromCreative(dest: ClientInventory, destSlot: u32, item: Item, amount: u16) void {
main.sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest.super, .slot = destSlot}, .item = item, .amount = amount}});
}

pub fn placeBlock(self: ClientInventory, slot: u32) void {
std.debug.assert(self.type == .serverShared);
main.renderer.MeshSelection.placeBlock(self, slot);
}

pub fn breakBlock(self: ClientInventory, slot: u32, deltaTime: f64) void {
std.debug.assert(self.type == .serverShared);
main.renderer.MeshSelection.breakBlock(self, slot, deltaTime);
}

pub fn size(self: ClientInventory) usize {
return self.super.size();
}

pub fn getItem(self: ClientInventory, slot: usize) Item {
return self.super.getItem(slot);
}

pub fn getStack(self: ClientInventory, slot: usize) ItemStack {
return self.super.getStack(slot);
}

pub fn getAmount(self: ClientInventory, slot: usize) u16 {
return self.super.getAmount(slot);
}
};

const Inventory = @This(); // MARK: Inventory

pub const TypeEnum = enum(u8) {
normal = 0,
creative = 1,
crafting = 2,
workbench = 3,
};
pub const Type = union(TypeEnum) {
normal: void,
creative: void,
crafting: void,
workbench: ToolTypeIndex,

pub fn shouldDepositToUserOnClose(self: Type) bool {
return self == .workbench;
}
};

type: Type,
id: InventoryId,
_items: []ItemStack,
source: Source,
callbacks: Callbacks,

pub fn init(allocator: NeverFailingAllocator, _size: usize, _type: Type, source: Source, callbacks: Callbacks) Inventory {
const self = _init(allocator, _size, _type, source, .client, callbacks);
sync.ClientSide.executeCommand(.{.open = .{.inv = self, .source = source}});
return self;
}

fn _init(allocator: NeverFailingAllocator, _size: usize, _type: Type, source: Source, side: sync.Side, callbacks: Callbacks) Inventory {
if(_type == .workbench) std.debug.assert(_size == 26);
const self = Inventory{
Expand All @@ -430,16 +543,6 @@ fn _init(allocator: NeverFailingAllocator, _size: usize, _type: Type, source: So
return self;
}

pub fn deinit(self: Inventory, allocator: NeverFailingAllocator) void {
if(main.game.world.?.connected) {
sync.ClientSide.executeCommand(.{.close = .{.inv = self, .allocator = allocator}});
} else {
main.sync.ClientSide.mutex.lock();
defer main.sync.ClientSide.mutex.unlock();
self._deinit(allocator, .client);
}
}

pub fn _deinit(self: Inventory, allocator: NeverFailingAllocator, side: sync.Side) void {
switch(side) {
.client => ClientSide.freeId(self.id),
Expand Down Expand Up @@ -482,58 +585,6 @@ pub fn update(self: Inventory) void {
}
}

pub fn depositOrSwap(dest: Inventory, destSlot: u32, carried: Inventory) void {
main.sync.ClientSide.executeCommand(.{.depositOrSwap = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = carried, .slot = 0}}});
}

pub fn deposit(dest: Inventory, destSlot: u32, source: Inventory, sourceSlot: u32, amount: u16) void {
main.sync.ClientSide.executeCommand(.{.deposit = .{.dest = .{.inv = dest, .slot = destSlot}, .source = .{.inv = source, .slot = sourceSlot}, .amount = amount}});
}

pub fn takeHalf(source: Inventory, sourceSlot: u32, carried: Inventory) void {
main.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 {
const amount = carried._items[0].amount/destinationInventories.len;
if(amount == 0) return;
for(0..destinationInventories.len) |i| {
destinationInventories[i].deposit(destinationSlots[i], carried, 0, @intCast(amount));
}
}

pub fn depositOrDrop(dest: Inventory, source: Inventory) void {
main.sync.ClientSide.executeCommand(.{.depositOrDrop = .{.dest = dest, .source = source, .dropLocation = undefined}});
}

pub fn depositToAny(source: Inventory, sourceSlot: u32, destinations: []const Inventory, amount: u16) void {
main.sync.ClientSide.executeCommand(.{.depositToAny = .init(destinations, .{.inv = source, .slot = sourceSlot}, amount)});
}

pub fn dropStack(source: Inventory, sourceSlot: u32) void {
main.sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}}});
}

pub fn dropOne(source: Inventory, sourceSlot: u32) void {
main.sync.ClientSide.executeCommand(.{.drop = .{.source = .{.inv = source, .slot = sourceSlot}, .desiredAmount = 1}});
}

pub fn fillFromCreative(dest: Inventory, destSlot: u32, item: Item) void {
main.sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item}});
}

pub fn fillAmountFromCreative(dest: Inventory, destSlot: u32, item: Item, amount: u16) void {
main.sync.ClientSide.executeCommand(.{.fillFromCreative = .{.dest = .{.inv = dest, .slot = destSlot}, .item = item, .amount = amount}});
}

pub fn placeBlock(self: Inventory, slot: u32) void {
main.renderer.MeshSelection.placeBlock(self, slot);
}

pub fn breakBlock(self: Inventory, slot: u32, deltaTime: f64) void {
main.renderer.MeshSelection.breakBlock(self, slot, deltaTime);
}

pub fn size(self: Inventory) usize {
return self._items.len;
}
Expand Down
2 changes: 1 addition & 1 deletion src/block_entity.zig
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ pub const BlockEntityTypes = struct {
pub fn onInteract(pos: Vec3i, _: *Chunk) main.callbacks.Result {
main.network.protocols.blockEntityUpdate.sendClientDataUpdateToServer(main.game.world.?.conn, pos);

const inventory = main.items.Inventory.init(main.globalAllocator, inventorySize, .normal, .{.blockInventory = pos}, .{});
const inventory = main.items.Inventory.ClientInventory.init(main.globalAllocator, inventorySize, .normal, .serverShared, .{.blockInventory = pos}, .{});

main.gui.windowlist.chest.setInventory(inventory);
main.gui.openWindow("chest");
Expand Down
6 changes: 3 additions & 3 deletions src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const assets = @import("assets.zig");
const itemdrop = @import("itemdrop.zig");
const ClientItemDropManager = itemdrop.ClientItemDropManager;
const items = @import("items.zig");
const Inventory = items.Inventory;
const ClientInventory = items.Inventory.ClientInventory;
const ZonElement = @import("zon.zig").ZonElement;
const main = @import("main");
const network = @import("network.zig");
Expand Down Expand Up @@ -429,7 +429,7 @@ pub const Player = struct { // MARK: Player
pub var hyperSpeed: Atomic(bool) = .init(false);
pub var mutex: std.Thread.Mutex = .{};
pub const inventorySize = 32;
pub var inventory: Inventory = undefined;
pub var inventory: ClientInventory = undefined;
pub var selectedSlot: u32 = 0;
pub const defaultBlockDamage: f32 = 1;

Expand Down Expand Up @@ -695,7 +695,7 @@ pub const World = struct { // MARK: World
defer main.stackAllocator.free(path);
try assets.loadWorldAssets(path, self.blockPalette, self.itemPalette, self.toolPalette, self.biomePalette);
Player.id = zon.get(u32, "player_id", std.math.maxInt(u32));
Player.inventory = Inventory.init(main.globalAllocator, Player.inventorySize, .normal, .{.playerInventory = Player.id}, .{});
Player.inventory = ClientInventory.init(main.globalAllocator, Player.inventorySize, .normal, .serverShared, .{.playerInventory = Player.id}, .{});
Player.loadFrom(zon.getChild("player"));
self.playerBiome = .init(main.server.terrain.biomes.getPlaceholderBiome());
main.audio.setMusic(self.playerBiome.raw.preferredMusic);
Expand Down
2 changes: 1 addition & 1 deletion src/gui/GuiWindow.zig
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ closeIfMouseIsGrabbed: bool = false,
closeable: bool = true,
isHud: bool = false,

shiftClickableInventory: ?main.items.Inventory = null,
shiftClickableInventory: ?main.items.Inventory.ClientInventory = null,

/// Called every frame.
renderFn: *const fn() void = &defaultFunction,
Expand Down
6 changes: 3 additions & 3 deletions src/gui/components/ItemSlot.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const std = @import("std");

const main = @import("main");
const Inventory = main.items.Inventory;
const ClientInventory = main.items.Inventory.ClientInventory;
const graphics = main.graphics;
const draw = graphics.draw;
const Texture = graphics.Texture;
Expand All @@ -26,7 +26,7 @@ const Mode = enum {

pos: Vec2f,
size: Vec2f = @splat(sizeWithBorder),
inventory: Inventory,
inventory: ClientInventory,
itemSlot: u32,
lastItemAmount: u16 = 0,
text: TextBuffer,
Expand Down Expand Up @@ -69,7 +69,7 @@ pub fn __deinit() void {
craftingResultTexture.deinit();
}

pub fn init(pos: Vec2f, inventory: Inventory, itemSlot: u32, texture: TextureParamType, mode: Mode) *ItemSlot {
pub fn init(pos: Vec2f, inventory: ClientInventory, itemSlot: u32, texture: TextureParamType, mode: Mode) *ItemSlot {
const self = main.globalAllocator.create(ItemSlot);
const amount = inventory.getAmount(itemSlot);
var buf: [16]u8 = undefined;
Expand Down
16 changes: 8 additions & 8 deletions src/gui/gui.zig
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ pub fn toggleGameMenu() void {

pub const inventory = struct { // MARK: inventory
const ItemStack = main.items.ItemStack;
const Inventory = main.items.Inventory;
pub var carried: Inventory = undefined;
const ClientInventory = main.items.Inventory.ClientInventory;
pub var carried: ClientInventory = undefined;
var carriedItemSlot: *ItemSlot = undefined;
var leftClickSlots: List(*ItemSlot) = .init(main.globalAllocator);
var rightClickSlots: List(*ItemSlot) = .init(main.globalAllocator);
Expand All @@ -605,7 +605,7 @@ pub const inventory = struct { // MARK: inventory
var isCrafting: bool = false;

pub fn init() void {
carried = Inventory.init(main.globalAllocator, 1, .normal, .{.hand = main.game.Player.id}, .{});
carried = ClientInventory.init(main.globalAllocator, 1, .normal, .serverShared, .{.hand = main.game.Player.id}, .{});
carriedItemSlot = ItemSlot.init(.{0, 0}, carried, 0, .default, .normal);
carriedItemSlot.renderFrame = false;
initialized = true;
Expand Down Expand Up @@ -651,7 +651,7 @@ pub const inventory = struct { // MARK: inventory
const mainGuiButton = main.KeyBoard.key("mainGuiButton");
const secondaryGuiButton = main.KeyBoard.key("secondaryGuiButton");

if(itemSlot.inventory.type == .crafting and itemSlot.mode == .takeOnly and mainGuiButton.pressed and (recipeItem != .null or itemSlot.pressed)) {
if(itemSlot.inventory.super.type == .crafting and itemSlot.mode == .takeOnly and mainGuiButton.pressed and (recipeItem != .null or itemSlot.pressed)) {
const item = itemSlot.inventory.getItem(itemSlot.itemSlot);
if(recipeItem == .null and item != .null) recipeItem = item.clone();
if(!std.meta.eql(item, recipeItem)) return;
Expand Down Expand Up @@ -679,7 +679,7 @@ pub const inventory = struct { // MARK: inventory
if(itemSlot.mode != .normal) return;

if(mainGuiButton.pressed and mainGuiButton.modsOnPress.shift) {
if(itemSlot.inventory.id == main.game.Player.inventory.id) {
if(itemSlot.inventory.super.id == main.game.Player.inventory.super.id) {
var iterator = std.mem.reverseIterator(openWindows.items);
while(iterator.next()) |window| {
if(window.shiftClickableInventory) |inv| {
Expand Down Expand Up @@ -719,7 +719,7 @@ pub const inventory = struct { // MARK: inventory
recipeItem = .null;
isCrafting = false;
if(leftClickSlots.items.len != 0) {
const targetInventories = main.stackAllocator.alloc(Inventory, leftClickSlots.items.len);
const targetInventories = main.stackAllocator.alloc(ClientInventory, leftClickSlots.items.len);
defer main.stackAllocator.free(targetInventories);
const targetSlots = main.stackAllocator.alloc(u32, leftClickSlots.items.len);
defer main.stackAllocator.free(targetSlots);
Expand All @@ -730,7 +730,7 @@ pub const inventory = struct { // MARK: inventory
carried.distribute(targetInventories, targetSlots);
leftClickSlots.clearRetainingCapacity();
} else if(hoveredItemSlot) |hovered| {
if(hovered.inventory.type == .crafting and hovered.mode == .takeOnly) return;
if(hovered.inventory.super.type == .crafting and hovered.mode == .takeOnly) return;
hovered.inventory.depositOrSwap(hovered.itemSlot, carried);
} else if(!hoveredAWindow) {
carried.dropStack(0);
Expand All @@ -739,7 +739,7 @@ pub const inventory = struct { // MARK: inventory
if(rightClickSlots.items.len != 0) {
rightClickSlots.clearRetainingCapacity();
} else if(hoveredItemSlot) |hovered| {
if(hovered.inventory.type == .crafting and hovered.mode == .takeOnly) return;
if(hovered.inventory.super.type == .crafting and hovered.mode == .takeOnly) return;
if(hovered.inventory.type == .creative) {
carried.deposit(0, hovered.inventory, hovered.itemSlot, 1);
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/gui/windows/chest.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ pub fn deinit() void {
itemSlots.deinit();
}

pub var openInventory: main.items.Inventory = undefined;
pub var openInventory: main.items.Inventory.ClientInventory = undefined;

pub fn setInventory(selectedInventory: main.items.Inventory) void {
pub fn setInventory(selectedInventory: main.items.Inventory.ClientInventory) void {
openInventory = selectedInventory;
}

Expand Down
Loading