mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-09 12:16:24 -04:00
parent
3c6147dc6a
commit
178489b044
@ -1,111 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const main = @import("root");
|
||||
const ItemStack = main.items.ItemStack;
|
||||
const graphics = main.graphics;
|
||||
const draw = graphics.draw;
|
||||
const Texture = graphics.Texture;
|
||||
const TextBuffer = graphics.TextBuffer;
|
||||
const vec = main.vec;
|
||||
const Vec2f = vec.Vec2f;
|
||||
|
||||
const gui = @import("../gui.zig");
|
||||
const GuiComponent = gui.GuiComponent;
|
||||
|
||||
const CraftingResultSlot = @This();
|
||||
|
||||
var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{24 + 2*border, 24 + 2*border},
|
||||
itemStack: ItemStack,
|
||||
text: TextBuffer,
|
||||
textSize: Vec2f = .{0, 0},
|
||||
onTake: gui.Callback,
|
||||
hovered: bool = false,
|
||||
pressed: bool = false,
|
||||
|
||||
pub fn __init() !void {
|
||||
texture = try Texture.initFromFile("assets/cubyz/ui/inventory/crafting_result_slot.png");
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
texture.deinit();
|
||||
}
|
||||
|
||||
pub fn init(pos: Vec2f, itemStack: ItemStack, onTake: gui.Callback) Allocator.Error!*CraftingResultSlot {
|
||||
const self = try main.globalAllocator.create(CraftingResultSlot);
|
||||
var buf: [16]u8 = undefined;
|
||||
self.* = CraftingResultSlot {
|
||||
.itemStack = itemStack,
|
||||
.pos = pos,
|
||||
.text = try TextBuffer.init(main.globalAllocator, std.fmt.bufPrint(&buf, "{}", .{self.itemStack.amount}) catch "∞", .{}, false, .right),
|
||||
.onTake = onTake,
|
||||
};
|
||||
self.textSize = try self.text.calculateLineBreaks(8, self.size[0] - 2*border);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const CraftingResultSlot) void {
|
||||
self.text.deinit();
|
||||
main.globalAllocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn toComponent(self: *CraftingResultSlot) GuiComponent {
|
||||
return GuiComponent{
|
||||
.craftingResultSlot = self
|
||||
};
|
||||
}
|
||||
|
||||
pub fn updateHovered(self: *CraftingResultSlot, _: Vec2f) void {
|
||||
self.hovered = true;
|
||||
gui.hoveredCraftingSlot = self;
|
||||
}
|
||||
|
||||
pub fn mainButtonPressed(self: *CraftingResultSlot, _: Vec2f) void {
|
||||
self.pressed = true;
|
||||
}
|
||||
|
||||
pub fn mainButtonReleased(self: *CraftingResultSlot, mousePosition: Vec2f) void {
|
||||
if(self.pressed) {
|
||||
self.pressed = false;
|
||||
if(GuiComponent.contains(self.pos, self.size, mousePosition)) {
|
||||
if(self.itemStack.item == null) return;
|
||||
if(gui.inventory.carriedItemStack.item == null or std.meta.eql(self.itemStack.item, gui.inventory.carriedItemStack.item)) {
|
||||
if(std.math.add(u16, gui.inventory.carriedItemStack.amount, self.itemStack.amount) catch null) |nextAmount| if(nextAmount <= self.itemStack.item.?.stackSize()) {
|
||||
const itemStack = self.itemStack;
|
||||
self.onTake.run();
|
||||
gui.inventory.carriedItemStack.item = itemStack.item;
|
||||
gui.inventory.carriedItemStack.amount += itemStack.amount;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: *CraftingResultSlot, _: Vec2f) !void {
|
||||
draw.setColor(0xffffffff);
|
||||
texture.bindTo(0);
|
||||
draw.boundImage(self.pos, self.size);
|
||||
if(self.itemStack.item) |item| {
|
||||
const itemTexture = try item.getTexture();
|
||||
itemTexture.bindTo(0);
|
||||
draw.setColor(0xff000000);
|
||||
draw.boundImage(self.pos + @as(Vec2f, @splat(border)) + Vec2f{1.0, 1.0}, self.size - @as(Vec2f, @splat(2*border)));
|
||||
draw.setColor(0xffffffff);
|
||||
draw.boundImage(self.pos + @as(Vec2f, @splat(border)), self.size - @as(Vec2f, @splat(2*border)));
|
||||
if(self.itemStack.amount != 1) {
|
||||
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);
|
||||
}
|
||||
}
|
||||
if(self.pressed) {
|
||||
draw.setColor(0x80808080);
|
||||
draw.rect(self.pos, self.size);
|
||||
} else if(self.hovered) {
|
||||
self.hovered = false;
|
||||
draw.setColor(0x300000ff);
|
||||
draw.rect(self.pos, self.size);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const main = @import("root");
|
||||
const BaseItem = main.items.BaseItem;
|
||||
const graphics = main.graphics;
|
||||
const draw = graphics.draw;
|
||||
const Texture = graphics.Texture;
|
||||
const TextBuffer = graphics.TextBuffer;
|
||||
const vec = main.vec;
|
||||
const Vec2f = vec.Vec2f;
|
||||
|
||||
const gui = @import("../gui.zig");
|
||||
const GuiComponent = gui.GuiComponent;
|
||||
|
||||
const ImmutableItemSlot = @This();
|
||||
|
||||
var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{24 + 2*border, 24 + 2*border},
|
||||
item: *BaseItem,
|
||||
amount: u32,
|
||||
text: TextBuffer,
|
||||
textSize: Vec2f = .{0, 0},
|
||||
|
||||
pub fn __init() !void {
|
||||
texture = try Texture.initFromFile("assets/cubyz/ui/inventory/immutable_slot.png");
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
texture.deinit();
|
||||
}
|
||||
|
||||
pub fn init(pos: Vec2f, item: *BaseItem, amount: u32) Allocator.Error!*ImmutableItemSlot {
|
||||
const self = try main.globalAllocator.create(ImmutableItemSlot);
|
||||
var buf: [16]u8 = undefined;
|
||||
self.* = ImmutableItemSlot {
|
||||
.item = item,
|
||||
.amount = amount,
|
||||
.pos = pos,
|
||||
.text = try TextBuffer.init(main.globalAllocator, std.fmt.bufPrint(&buf, "{}", .{amount}) catch "∞", .{}, false, .right),
|
||||
};
|
||||
self.textSize = try self.text.calculateLineBreaks(8, self.size[0] - 2*border);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const ImmutableItemSlot) void {
|
||||
self.text.deinit();
|
||||
main.globalAllocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn toComponent(self: *ImmutableItemSlot) GuiComponent {
|
||||
return GuiComponent{
|
||||
.immutableItemSlot = self
|
||||
};
|
||||
}
|
||||
|
||||
pub fn render(self: *ImmutableItemSlot, _: Vec2f) !void {
|
||||
draw.setColor(0xffffffff);
|
||||
texture.bindTo(0);
|
||||
draw.boundImage(self.pos, self.size);
|
||||
const itemTexture = try self.item.getTexture();
|
||||
itemTexture.bindTo(0);
|
||||
draw.setColor(0xff000000);
|
||||
draw.boundImage(self.pos + @as(Vec2f, @splat(border)) + Vec2f{1.0, 1.0}, self.size - @as(Vec2f, @splat(2*border)));
|
||||
draw.setColor(0xffffffff);
|
||||
draw.boundImage(self.pos + @as(Vec2f, @splat(border)), self.size - @as(Vec2f, @splat(2*border)));
|
||||
if(self.amount != 1) {
|
||||
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);
|
||||
}
|
||||
}
|
@ -16,13 +16,22 @@ const GuiComponent = gui.GuiComponent;
|
||||
|
||||
const ItemSlot = @This();
|
||||
|
||||
var texture: Texture = undefined;
|
||||
const border: f32 = 2;
|
||||
|
||||
pub const VTable = struct {
|
||||
tryAddingItems: *const fn(usize, *ItemStack, u16) void,
|
||||
tryTakingItems: *const fn(usize, *ItemStack, u16) void,
|
||||
trySwappingItems: *const fn(usize, *ItemStack) void,
|
||||
tryAddingItems: *const fn(usize, *ItemStack, u16) void = &defaultAddingItems,
|
||||
tryTakingItems: *const fn(usize, *ItemStack, u16) void = &defaultTakingItems,
|
||||
trySwappingItems: *const fn(usize, *ItemStack) void = &defaultSwappingItems,
|
||||
|
||||
fn defaultAddingItems(_: usize, _: *ItemStack, _: u16) void {}
|
||||
fn defaultTakingItems(_: usize, _: *ItemStack, _: u16) void {}
|
||||
fn defaultSwappingItems(_: usize, _: *ItemStack) void {}
|
||||
};
|
||||
|
||||
const Mode = enum {
|
||||
normal,
|
||||
takeOnly,
|
||||
immutable,
|
||||
};
|
||||
|
||||
pos: Vec2f,
|
||||
@ -35,16 +44,40 @@ pressed: bool = false,
|
||||
renderFrame: bool = true,
|
||||
userData: usize,
|
||||
vtable: *const VTable,
|
||||
texture: Texture,
|
||||
mode: Mode,
|
||||
|
||||
var defaultTexture: Texture = undefined;
|
||||
var immutableTexture: Texture = undefined;
|
||||
var craftingResultTexture: Texture = undefined;
|
||||
const TextureParamType = union(enum) {
|
||||
default: void,
|
||||
immutable: void,
|
||||
craftingResult: void,
|
||||
custom: Texture,
|
||||
fn value(self: TextureParamType) Texture {
|
||||
return switch(self) {
|
||||
.default => defaultTexture,
|
||||
.immutable => immutableTexture,
|
||||
.craftingResult => craftingResultTexture,
|
||||
.custom => |t| t,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn __init() !void {
|
||||
texture = try Texture.initFromFile("assets/cubyz/ui/inventory/slot.png");
|
||||
defaultTexture = try Texture.initFromFile("assets/cubyz/ui/inventory/slot.png");
|
||||
immutableTexture = try Texture.initFromFile("assets/cubyz/ui/inventory/immutable_slot.png");
|
||||
craftingResultTexture = try Texture.initFromFile("assets/cubyz/ui/inventory/crafting_result_slot.png");
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
texture.deinit();
|
||||
defaultTexture.deinit();
|
||||
immutableTexture.deinit();
|
||||
craftingResultTexture.deinit();
|
||||
}
|
||||
|
||||
pub fn init(pos: Vec2f, itemStack: ItemStack, vtable: *const VTable, userData: usize) Allocator.Error!*ItemSlot {
|
||||
pub fn init(pos: Vec2f, itemStack: ItemStack, vtable: *const VTable, userData: usize, texture: TextureParamType, mode: Mode) Allocator.Error!*ItemSlot {
|
||||
const self = try main.globalAllocator.create(ItemSlot);
|
||||
var buf: [16]u8 = undefined;
|
||||
self.* = ItemSlot {
|
||||
@ -53,6 +86,8 @@ pub fn init(pos: Vec2f, itemStack: ItemStack, vtable: *const VTable, userData: u
|
||||
.userData = userData,
|
||||
.pos = pos,
|
||||
.text = try TextBuffer.init(main.globalAllocator, std.fmt.bufPrint(&buf, "{}", .{self.itemStack.amount}) catch "∞", .{}, false, .right),
|
||||
.texture = texture.value(),
|
||||
.mode = mode,
|
||||
};
|
||||
self.textSize = try self.text.calculateLineBreaks(8, self.size[0] - 2*border);
|
||||
return self;
|
||||
@ -63,14 +98,14 @@ pub fn deinit(self: *const ItemSlot) void {
|
||||
main.globalAllocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn tryAddingItems(self: *ItemSlot, source: *ItemStack, amount: u16) void {
|
||||
pub fn tryAddingItems(self: *ItemSlot, source: *ItemStack, desiredAmount: u16) void {
|
||||
std.debug.assert(source.item != null);
|
||||
std.debug.assert(amount <= source.amount);
|
||||
self.vtable.tryAddingItems(self.userData, source, amount);
|
||||
std.debug.assert(desiredAmount <= source.amount);
|
||||
self.vtable.tryAddingItems(self.userData, source, desiredAmount);
|
||||
}
|
||||
|
||||
pub fn tryTakingItems(self: *ItemSlot, destination: *ItemStack, amount: u16) void {
|
||||
self.vtable.tryTakingItems(self.userData, destination, amount);
|
||||
pub fn tryTakingItems(self: *ItemSlot, destination: *ItemStack, desiredAmount: u16) void {
|
||||
self.vtable.tryTakingItems(self.userData, destination, desiredAmount);
|
||||
}
|
||||
|
||||
pub fn trySwappingItems(self: *ItemSlot, destination: *ItemStack) void {
|
||||
@ -122,7 +157,7 @@ pub fn mainButtonReleased(self: *ItemSlot, _: Vec2f) void {
|
||||
pub fn render(self: *ItemSlot, _: Vec2f) !void {
|
||||
draw.setColor(0xffffffff);
|
||||
if(self.renderFrame) {
|
||||
texture.bindTo(0);
|
||||
self.texture.bindTo(0);
|
||||
draw.boundImage(self.pos, self.size);
|
||||
}
|
||||
if(self.itemStack.item) |item| {
|
||||
@ -140,8 +175,10 @@ pub fn render(self: *ItemSlot, _: Vec2f) !void {
|
||||
draw.setColor(0x80808080);
|
||||
draw.rect(self.pos, self.size);
|
||||
} else if(self.hovered) {
|
||||
self.hovered = false;
|
||||
draw.setColor(0x300000ff);
|
||||
draw.rect(self.pos, self.size);
|
||||
if(self.mode != .immutable) {
|
||||
self.hovered = false;
|
||||
draw.setColor(0x300000ff);
|
||||
draw.rect(self.pos, self.size);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ const Vec2f = vec.Vec2f;
|
||||
|
||||
const Button = @import("components/Button.zig");
|
||||
const CheckBox = @import("components/CheckBox.zig");
|
||||
const CraftingResultSlot = @import("components/CraftingResultSlot.zig");
|
||||
const ImmutableItemSlot = @import("components/ImmutableItemSlot.zig");
|
||||
const ItemSlot = @import("components/ItemSlot.zig");
|
||||
const ScrollBar = @import("components/ScrollBar.zig");
|
||||
const ContinuousSlider = @import("components/ContinuousSlider.zig");
|
||||
@ -33,7 +31,6 @@ var hoveredAWindow: bool = false;
|
||||
pub var scale: f32 = undefined;
|
||||
|
||||
pub var hoveredItemSlot: ?*ItemSlot = null;
|
||||
pub var hoveredCraftingSlot: ?*CraftingResultSlot = null;
|
||||
|
||||
const GuiCommandQueue = struct {
|
||||
const Action = enum {
|
||||
@ -147,8 +144,6 @@ pub fn init() !void {
|
||||
try GuiWindow.__init();
|
||||
try Button.__init();
|
||||
try CheckBox.__init();
|
||||
try CraftingResultSlot.__init();
|
||||
try ImmutableItemSlot.__init();
|
||||
try ItemSlot.__init();
|
||||
try ScrollBar.__init();
|
||||
try ContinuousSlider.__init();
|
||||
@ -171,8 +166,6 @@ pub fn deinit() void {
|
||||
GuiWindow.__deinit();
|
||||
Button.__deinit();
|
||||
CheckBox.__deinit();
|
||||
CraftingResultSlot.__deinit();
|
||||
ImmutableItemSlot.__deinit();
|
||||
ItemSlot.__deinit();
|
||||
ScrollBar.__deinit();
|
||||
ContinuousSlider.__deinit();
|
||||
@ -444,12 +437,6 @@ pub fn mainButtonPressed() void {
|
||||
inventory.update() catch |err| {
|
||||
std.log.err("Encountered error while updating inventory: {s}", .{@errorName(err)});
|
||||
};
|
||||
if(inventory.carriedItemStack.amount != 0) {
|
||||
if(hoveredCraftingSlot) |hovered| {
|
||||
hovered.mainButtonPressed(undefined);
|
||||
}
|
||||
return;
|
||||
}
|
||||
selectedWindow = null;
|
||||
selectedTextInput = null;
|
||||
var selectedI: usize = 0;
|
||||
@ -527,7 +514,6 @@ pub fn updateAndRenderGui() !void {
|
||||
try selected.updateSelected(mousePos);
|
||||
}
|
||||
hoveredItemSlot = null;
|
||||
hoveredCraftingSlot = null;
|
||||
var i: usize = openWindows.items.len;
|
||||
while(i != 0) {
|
||||
i -= 1;
|
||||
@ -568,7 +554,7 @@ pub const inventory = struct {
|
||||
pub fn init() !void {
|
||||
deliveredItemSlots = std.ArrayList(*ItemSlot).init(main.globalAllocator);
|
||||
deliveredItemStacksAmountAdded = std.ArrayList(u16).init(main.globalAllocator);
|
||||
carriedItemSlot = try ItemSlot.init(.{0, 0}, carriedItemStack, undefined, undefined);
|
||||
carriedItemSlot = try ItemSlot.init(.{0, 0}, carriedItemStack, undefined, undefined, .default, .normal);
|
||||
carriedItemSlot.renderFrame = false;
|
||||
}
|
||||
|
||||
@ -584,6 +570,7 @@ pub const inventory = struct {
|
||||
initialAmount = carriedItemStack.amount;
|
||||
}
|
||||
if(hoveredItemSlot) |itemSlot| {
|
||||
if(itemSlot.mode != .normal) return;
|
||||
if(initialAmount == 0) return;
|
||||
if(!std.meta.eql(itemSlot.itemStack.item, carriedItemStack.item) and itemSlot.itemStack.item != null) return;
|
||||
|
||||
@ -619,7 +606,6 @@ pub const inventory = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
try carriedItemSlot.updateItemStack(carriedItemStack);
|
||||
}
|
||||
|
||||
fn applyChanges(leftClick: bool) void {
|
||||
@ -633,11 +619,15 @@ pub const inventory = struct {
|
||||
} else if(hoveredItemSlot) |hovered| {
|
||||
if(carriedItemStack.amount != 0) {
|
||||
if(leftClick) {
|
||||
hovered.trySwappingItems(&carriedItemStack);
|
||||
if(std.meta.eql(carriedItemStack.item, hovered.itemStack.item)) {
|
||||
hovered.tryTakingItems(&carriedItemStack, hovered.itemStack.amount);
|
||||
} else {
|
||||
hovered.trySwappingItems(&carriedItemStack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(leftClick) {
|
||||
hovered.tryTakingItems(&carriedItemStack, std.math.maxInt(u16));
|
||||
hovered.tryTakingItems(&carriedItemStack, hovered.itemStack.amount);
|
||||
} else {
|
||||
hovered.tryTakingItems(&carriedItemStack, hovered.itemStack.amount/2);
|
||||
}
|
||||
@ -652,12 +642,13 @@ pub const inventory = struct {
|
||||
main.network.Protocols.genericUpdate.itemStackDrop(main.game.world.?.conn, .{.item = carriedItemStack.item, .amount = 1}, @floatCast(main.game.Player.getPosBlocking()), main.game.camera.direction, 20) catch |err| {
|
||||
std.log.err("Error while dropping itemStack: {s}", .{@errorName(err)});
|
||||
};
|
||||
_ = carriedItemStack.add(@as(i32, -1));
|
||||
_ = carriedItemStack.add(carriedItemStack.item.?, @as(i32, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(mousePos: Vec2f) !void {
|
||||
try carriedItemSlot.updateItemStack(carriedItemStack);
|
||||
carriedItemSlot.pos = mousePos - Vec2f{12, 12};
|
||||
try carriedItemSlot.render(.{0, 0});
|
||||
// Draw tooltip:
|
||||
|
@ -8,10 +8,8 @@ pub const GuiComponent = union(enum) {
|
||||
|
||||
pub const Button = @import("components/Button.zig");
|
||||
pub const CheckBox = @import("components/CheckBox.zig");
|
||||
pub const CraftingResultSlot = @import("components/CraftingResultSlot.zig");
|
||||
pub const HorizontalList = @import("components/HorizontalList.zig");
|
||||
pub const Icon = @import("components/Icon.zig");
|
||||
pub const ImmutableItemSlot = @import("components/ImmutableItemSlot.zig");
|
||||
pub const ItemSlot = @import("components/ItemSlot.zig");
|
||||
pub const Label = @import("components/Label.zig");
|
||||
pub const MutexComponent = @import("components/MutexComponent.zig");
|
||||
@ -24,10 +22,8 @@ pub const GuiComponent = union(enum) {
|
||||
|
||||
button: *Button,
|
||||
checkBox: *CheckBox,
|
||||
craftingResultSlot: *CraftingResultSlot,
|
||||
horizontalList: *HorizontalList,
|
||||
icon: *Icon,
|
||||
immutableItemSlot: *ImmutableItemSlot,
|
||||
itemSlot: *ItemSlot,
|
||||
label: *Label,
|
||||
mutexComponent: *MutexComponent,
|
||||
|
@ -26,26 +26,12 @@ pub var window = GuiWindow {
|
||||
const padding: f32 = 8;
|
||||
var items: std.ArrayList(Item) = undefined;
|
||||
|
||||
pub fn tryAddingItems(_: usize, _: *ItemStack, _: u16) void {
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, amount: u16) void {
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, _: u16) void {
|
||||
if(destination.item != null and !std.meta.eql(destination.item.?, items.items[index])) return;
|
||||
destination.item = items.items[index];
|
||||
_ = destination.add(amount);
|
||||
destination.amount = destination.item.?.stackSize();
|
||||
}
|
||||
|
||||
pub fn trySwappingItems(_: usize, _: *ItemStack) void {
|
||||
return;
|
||||
}
|
||||
|
||||
const vtable = ItemSlot.VTable {
|
||||
.tryAddingItems = &tryAddingItems,
|
||||
.tryTakingItems = &tryTakingItems,
|
||||
.trySwappingItems = &trySwappingItems,
|
||||
};
|
||||
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
items = std.ArrayList(Item).init(main.globalAllocator);
|
||||
var itemIterator = main.items.iterator();
|
||||
@ -60,7 +46,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
for(0..8) |_| {
|
||||
if(i >= items.items.len) break;
|
||||
const item = items.items[i];
|
||||
try row.add(try ItemSlot.init(.{0, 0}, .{.item = item, .amount = item.stackSize()}, &vtable, i));
|
||||
try row.add(try ItemSlot.init(.{0, 0}, .{.item = item, .amount = item.stackSize()}, &.{.tryTakingItems = &tryTakingItems}, i, .default, .takeOnly));
|
||||
i += 1;
|
||||
}
|
||||
try list.add(row);
|
||||
|
@ -29,13 +29,12 @@ pub var window = GuiWindow {
|
||||
|
||||
var itemSlots: [8]*ItemSlot = undefined;
|
||||
|
||||
pub fn tryAddingItems(index: usize, source: *ItemStack, amount: u16) void {
|
||||
pub fn tryAddingItems(index: usize, source: *ItemStack, desiredAmount: u16) void {
|
||||
Player.mutex.lock();
|
||||
defer Player.mutex.unlock();
|
||||
const destination = &Player.inventory__SEND_CHANGES_TO_SERVER.items[index];
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, desiredAmount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
main.network.Protocols.genericUpdate.sendInventory_full(main.game.world.?.conn, Player.inventory__SEND_CHANGES_TO_SERVER) catch |err| { // TODO(post-java): Add better options to the protocol.
|
||||
@ -43,16 +42,15 @@ pub fn tryAddingItems(index: usize, source: *ItemStack, amount: u16) void {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, _amount: u16) void {
|
||||
var amount = _amount;
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, desiredAmount: u16) void {
|
||||
var amount = desiredAmount;
|
||||
Player.mutex.lock();
|
||||
defer Player.mutex.unlock();
|
||||
const source = &Player.inventory__SEND_CHANGES_TO_SERVER.items[index];
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
if(source.item == null) return;
|
||||
amount = @min(amount, source.amount);
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, amount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
main.network.Protocols.genericUpdate.sendInventory_full(main.game.world.?.conn, Player.inventory__SEND_CHANGES_TO_SERVER) catch |err| { // TODO(post-java): Add better options to the protocol.
|
||||
@ -81,7 +79,7 @@ const vtable = ItemSlot.VTable {
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
const list = try HorizontalList.init();
|
||||
for(0..8) |i| {
|
||||
itemSlots[i] = try ItemSlot.init(.{0, 0}, Player.inventory__SEND_CHANGES_TO_SERVER.items[i], &vtable, i);
|
||||
itemSlots[i] = try ItemSlot.init(.{0, 0}, Player.inventory__SEND_CHANGES_TO_SERVER.items[i], &vtable, i, .default, .normal);
|
||||
try list.add(itemSlots[i]);
|
||||
}
|
||||
list.finish(.{0, 0}, .center);
|
||||
|
@ -40,13 +40,12 @@ pub fn deinit() void {
|
||||
|
||||
var itemSlots: [24]*ItemSlot = undefined;
|
||||
|
||||
pub fn tryAddingItems(index: usize, source: *ItemStack, amount: u16) void {
|
||||
pub fn tryAddingItems(index: usize, source: *ItemStack, desiredAmount: u16) void {
|
||||
Player.mutex.lock();
|
||||
defer Player.mutex.unlock();
|
||||
const destination = &Player.inventory__SEND_CHANGES_TO_SERVER.items[index];
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, desiredAmount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
main.network.Protocols.genericUpdate.sendInventory_full(main.game.world.?.conn, Player.inventory__SEND_CHANGES_TO_SERVER) catch |err| { // TODO(post-java): Add better options to the protocol.
|
||||
@ -54,16 +53,15 @@ pub fn tryAddingItems(index: usize, source: *ItemStack, amount: u16) void {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, _amount: u16) void {
|
||||
var amount = _amount;
|
||||
pub fn tryTakingItems(index: usize, destination: *ItemStack, desiredAmount: u16) void {
|
||||
var amount = desiredAmount;
|
||||
Player.mutex.lock();
|
||||
defer Player.mutex.unlock();
|
||||
const source = &Player.inventory__SEND_CHANGES_TO_SERVER.items[index];
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
if(source.item == null) return;
|
||||
amount = @min(amount, source.amount);
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, amount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
main.network.Protocols.genericUpdate.sendInventory_full(main.game.world.?.conn, Player.inventory__SEND_CHANGES_TO_SERVER) catch |err| { // TODO(post-java): Add better options to the protocol.
|
||||
@ -103,7 +101,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
const row = try HorizontalList.init();
|
||||
for(0..8) |x| {
|
||||
const index: usize = y*8 + x;
|
||||
const slot = try ItemSlot.init(.{0, 0}, Player.inventory__SEND_CHANGES_TO_SERVER.items[index], &vtable, index);
|
||||
const slot = try ItemSlot.init(.{0, 0}, Player.inventory__SEND_CHANGES_TO_SERVER.items[index], &vtable, index, .default, .normal);
|
||||
itemSlots[index - 8] = slot;
|
||||
try row.add(slot);
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ const Button = GuiComponent.Button;
|
||||
const HorizontalList = GuiComponent.HorizontalList;
|
||||
const VerticalList = GuiComponent.VerticalList;
|
||||
const Icon = GuiComponent.Icon;
|
||||
const CraftingResultSlot = GuiComponent.CraftingResultSlot;
|
||||
const ImmutableItemSlot = GuiComponent.ImmutableItemSlot;
|
||||
const ItemSlot = GuiComponent.ItemSlot;
|
||||
|
||||
const inventory = @import("inventory.zig");
|
||||
|
||||
@ -62,10 +61,12 @@ fn addItemStackToAvailable(itemStack: ItemStack) Allocator.Error!void {
|
||||
}
|
||||
}
|
||||
|
||||
fn onTake(recipeIndex: usize) void {
|
||||
fn tryTakingItems(recipeIndex: usize, destination: *ItemStack, _: u16) void {
|
||||
const recipe = items.recipes()[recipeIndex];
|
||||
const resultItem = recipe.resultItem;
|
||||
if(!destination.canAddAll(resultItem.item.?, resultItem.amount)) return;
|
||||
for(recipe.sourceItems, recipe.sourceAmounts) |item, _amount| {
|
||||
var amount: u32 = _amount;
|
||||
var amount = _amount;
|
||||
for(main.game.Player.inventory__SEND_CHANGES_TO_SERVER.items) |*itemStack| {
|
||||
if(itemStack.item) |invItem| {
|
||||
if(invItem == .baseItem and invItem.baseItem == item) {
|
||||
@ -84,6 +85,7 @@ fn onTake(recipeIndex: usize) void {
|
||||
std.log.warn("Congratulations, you just managed to cheat {}*{s}, thanks to my lazy coding. Have fun with that :D", .{amount, item.id});
|
||||
}
|
||||
}
|
||||
std.debug.assert(destination.add(resultItem.item.?, resultItem.amount) == resultItem.amount);
|
||||
}
|
||||
|
||||
fn findAvailableRecipes(list: *VerticalList) Allocator.Error!bool {
|
||||
@ -127,14 +129,14 @@ fn findAvailableRecipes(list: *VerticalList) Allocator.Error!bool {
|
||||
if(col < remainder) itemsThisColumn += 1;
|
||||
const columnList = try VerticalList.init(.{0, 0}, std.math.inf(f32), 0);
|
||||
for(0..itemsThisColumn) |_| {
|
||||
try columnList.add(try ImmutableItemSlot.init(.{0, 0}, recipe.sourceItems[i], recipe.sourceAmounts[i]));
|
||||
try columnList.add(try ItemSlot.init(.{0, 0}, .{.item = .{.baseItem = recipe.sourceItems[i]}, .amount = recipe.sourceAmounts[i]}, &.{}, 0, .immutable, .immutable));
|
||||
i += 1;
|
||||
}
|
||||
columnList.finish(.center);
|
||||
try rowList.add(columnList);
|
||||
}
|
||||
try rowList.add(try Icon.init(.{8, 0}, .{32, 32}, arrowTexture, false));
|
||||
const itemSlot = try CraftingResultSlot.init(.{8, 0}, recipe.resultItem, .{.callback = &onTake, .arg = recipeIndex});
|
||||
const itemSlot = try ItemSlot.init(.{8, 0}, recipe.resultItem, &.{.tryTakingItems = &tryTakingItems}, recipeIndex, .craftingResult, .takeOnly);
|
||||
try rowList.add(itemSlot);
|
||||
rowList.finish(.{0, 0}, .center);
|
||||
try list.add(rowList);
|
||||
|
@ -19,8 +19,6 @@ const HorizontalList = GuiComponent.HorizontalList;
|
||||
const VerticalList = GuiComponent.VerticalList;
|
||||
const Icon = GuiComponent.Icon;
|
||||
const ItemSlot = GuiComponent.ItemSlot;
|
||||
const CraftingResultSlot = GuiComponent.CraftingResultSlot;
|
||||
const ImmutableItemSlot = GuiComponent.ImmutableItemSlot;
|
||||
|
||||
const inventory = @import("inventory.zig");
|
||||
const inventory_crafting = @import("inventory_crafting.zig");
|
||||
@ -40,7 +38,7 @@ var availableItems: [25]?*const BaseItem = undefined;
|
||||
|
||||
var craftingGrid: [25]ItemStack = undefined;
|
||||
|
||||
var craftingResult: *CraftingResultSlot = undefined;
|
||||
var craftingResult: *ItemSlot = undefined;
|
||||
|
||||
var seed: u32 = undefined;
|
||||
|
||||
@ -52,8 +50,7 @@ pub fn tryAddingItems(index: usize, source: *ItemStack, amount: u16) void {
|
||||
if(source.item.?.baseItem.material == null) return;
|
||||
const destination = &craftingGrid[index];
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, amount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
}
|
||||
@ -64,8 +61,7 @@ pub fn tryTakingItems(index: usize, destination: *ItemStack, _amount: u16) void
|
||||
if(destination.item != null and !std.meta.eql(source.item, destination.item)) return;
|
||||
if(source.item == null) return;
|
||||
amount = @min(amount, source.amount);
|
||||
destination.item = source.item;
|
||||
const actual = destination.add(amount);
|
||||
const actual = destination.add(source.item.?, amount);
|
||||
source.amount -= actual;
|
||||
if(source.amount == 0) source.item = null;
|
||||
}
|
||||
@ -83,10 +79,12 @@ const vtable = ItemSlot.VTable {
|
||||
.trySwappingItems = &trySwappingItems,
|
||||
};
|
||||
|
||||
fn onTake(_: usize) void {
|
||||
fn onTake(_: usize, destination: *ItemStack, _: u16) void {
|
||||
if(destination.item != null) return;
|
||||
destination.* = craftingResult.itemStack;
|
||||
for(&craftingGrid) |*itemStack| {
|
||||
if(itemStack.item != null and itemStack.item.? == .baseItem and itemStack.item.?.baseItem.material != null) {
|
||||
_ = itemStack.add(@as(i32, -1));
|
||||
_ = itemStack.add(itemStack.item.?, @as(i32, -1));
|
||||
}
|
||||
}
|
||||
craftingResult.itemStack = .{};
|
||||
@ -137,7 +135,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
const row = try HorizontalList.init();
|
||||
for(0..5) |x| {
|
||||
const index = x + y*5;
|
||||
const slot = try ItemSlot.init(.{0, 0}, craftingGrid[index], &vtable, index);
|
||||
const slot = try ItemSlot.init(.{0, 0}, craftingGrid[index], &vtable, index, .default, .normal);
|
||||
itemSlots[index] = slot;
|
||||
try row.add(slot);
|
||||
}
|
||||
@ -147,7 +145,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
try list.add(grid);
|
||||
}
|
||||
try list.add(try Icon.init(.{8, 0}, .{32, 32}, inventory_crafting.arrowTexture, false));
|
||||
craftingResult = try CraftingResultSlot.init(.{8, 0}, .{}, .{.callback = &onTake});
|
||||
craftingResult = try ItemSlot.init(.{8, 0}, .{}, &.{.tryTakingItems = &onTake}, 0, .craftingResult, .takeOnly);
|
||||
try list.add(craftingResult);
|
||||
list.finish(.{padding, padding + 16}, .center);
|
||||
window.rootComponent = list.toComponent();
|
||||
|
@ -1154,8 +1154,8 @@ pub const ItemStack = struct {
|
||||
}
|
||||
|
||||
/// Returns the number of items actually added/removed.
|
||||
pub fn add(self: *ItemStack, number: anytype) @TypeOf(number) {
|
||||
std.debug.assert(self.item != null);
|
||||
pub fn add(self: *ItemStack, item: Item, number: anytype) @TypeOf(number) {
|
||||
if(self.item == null) self.item = item;
|
||||
var newAmount = self.amount + number;
|
||||
var returnValue = number;
|
||||
if(newAmount < 0) {
|
||||
@ -1173,9 +1173,9 @@ pub const ItemStack = struct {
|
||||
}
|
||||
|
||||
/// whether the given number of items can be added to this stack.
|
||||
pub fn canAddAll(self: *const ItemStack, number: u16) bool {
|
||||
std.debug.assert(self.item);
|
||||
return @as(u32, self.amount) + number <= self.item.?.stackSize();
|
||||
pub fn canAddAll(self: *const ItemStack, item: Item, number: u16) bool {
|
||||
if(self.item != null and !std.meta.eql(self.item.?, item)) return false;
|
||||
return @as(u32, self.amount) + number <= item.stackSize();
|
||||
}
|
||||
|
||||
pub fn clear(self: *ItemStack) void {
|
||||
@ -1225,14 +1225,13 @@ pub const Inventory = struct {
|
||||
var amount = _amount;
|
||||
for(self.items) |*stack| {
|
||||
if(!stack.empty() and std.meta.eql(stack.item, item) and !stack.filled()) {
|
||||
amount -= stack.add(amount);
|
||||
amount -= stack.add(item, amount);
|
||||
if(amount == 0) return 0;
|
||||
}
|
||||
}
|
||||
for(self.items) |*stack| {
|
||||
if(stack.empty()) {
|
||||
stack.item = item;
|
||||
amount -= stack.add(amount);
|
||||
amount -= stack.add(item, amount);
|
||||
if(amount == 0) return 0;
|
||||
}
|
||||
}
|
||||
@ -1288,7 +1287,7 @@ pub const Inventory = struct {
|
||||
|
||||
const Recipe = struct {
|
||||
sourceItems: []*BaseItem,
|
||||
sourceAmounts: []u32,
|
||||
sourceAmounts: []u16,
|
||||
resultItem: ItemStack,
|
||||
};
|
||||
|
||||
@ -1337,7 +1336,7 @@ pub fn registerRecipes(file: []const u8) !void {
|
||||
}
|
||||
var items = std.ArrayList(*BaseItem).init(main.globalAllocator);
|
||||
defer items.deinit();
|
||||
var itemAmounts = std.ArrayList(u32).init(main.globalAllocator);
|
||||
var itemAmounts = std.ArrayList(u16).init(main.globalAllocator);
|
||||
defer itemAmounts.deinit();
|
||||
var string = std.ArrayList(u8).init(main.globalAllocator);
|
||||
defer string.deinit();
|
||||
@ -1369,7 +1368,7 @@ pub fn registerRecipes(file: []const u8) !void {
|
||||
const item = shortcuts.get(id) orelse getByID(id) orelse continue;
|
||||
const recipe = Recipe {
|
||||
.sourceItems = try arena.allocator().dupe(*BaseItem, items.items),
|
||||
.sourceAmounts = try arena.allocator().dupe(u32, itemAmounts.items),
|
||||
.sourceAmounts = try arena.allocator().dupe(u16, itemAmounts.items),
|
||||
.resultItem = ItemStack{.item = Item{.baseItem = item}, .amount = amount},
|
||||
};
|
||||
try recipeList.append(recipe);
|
||||
|
@ -782,7 +782,7 @@ pub const MeshSelection = struct {
|
||||
if(rotationMode.generateData(main.game.world.?, selectedPos, relPos, lastDir, neighborDir, &block, false)) {
|
||||
// TODO: world.updateBlock(bi.x, bi.y, bi.z, block.data); (→ Sending it over the network)
|
||||
try mesh_storage.updateBlock(selectedPos[0], selectedPos[1], selectedPos[2], block);
|
||||
_ = inventoryStack.add(@as(i32, -1));
|
||||
_ = inventoryStack.add(item, @as(i32, -1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -795,7 +795,7 @@ pub const MeshSelection = struct {
|
||||
if(rotationMode.generateData(main.game.world.?, neighborPos, relPos, lastDir, neighborDir, &block, false)) {
|
||||
// TODO: world.updateBlock(bi.x, bi.y, bi.z, block.data); (→ Sending it over the network)
|
||||
try mesh_storage.updateBlock(neighborPos[0], neighborPos[1], neighborPos[2], block);
|
||||
_ = inventoryStack.add(@as(i32, -1));
|
||||
_ = inventoryStack.add(item, @as(i32, -1));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -815,7 +815,7 @@ pub const MeshSelection = struct {
|
||||
if(rotationMode.generateData(main.game.world.?, neighborPos, relPos, lastDir, neighborDir, &block, true)) {
|
||||
// TODO: world.updateBlock(bi.x, bi.y, bi.z, block.data); (→ Sending it over the network)
|
||||
try mesh_storage.updateBlock(neighborPos[0], neighborPos[1], neighborPos[2], block);
|
||||
_ = inventoryStack.add(@as(i32, -1));
|
||||
_ = inventoryStack.add(item, @as(i32, -1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user