mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Add ToolTypeIndex
struct (#1478)
## Description This pull request adds `ToolTypeIndex` struct that behaves similarly to `ModelIndex` and `BaseItemIndex` structs. ## Links Related to: #1290 Related to: #1060 --------- Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
This commit is contained in:
parent
cd4cd8e9b9
commit
9f0289551d
@ -15,6 +15,7 @@ const Vec3i = vec.Vec3i;
|
||||
const ZonElement = main.ZonElement;
|
||||
const Neighbor = main.chunk.Neighbor;
|
||||
const BaseItemIndex = main.items.BaseItemIndex;
|
||||
const ToolTypeIndex = main.items.ToolTypeIndex;
|
||||
|
||||
const Gamemode = main.game.Gamemode;
|
||||
|
||||
@ -1137,7 +1138,7 @@ pub const Command = struct { // MARK: Command
|
||||
switch(self.inv.type) {
|
||||
.normal, .creative, .crafting => {},
|
||||
.workbench => {
|
||||
writer.writeSlice(self.inv.type.workbench.id);
|
||||
writer.writeSlice(self.inv.type.workbench.id());
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1180,7 +1181,7 @@ pub const Command = struct { // MARK: Command
|
||||
};
|
||||
const typ: Type = switch(typeEnum) {
|
||||
inline .normal, .creative, .crafting => |tag| tag,
|
||||
.workbench => .{.workbench = main.items.getToolTypeByID(reader.remaining) orelse return error.Invalid},
|
||||
.workbench => .{.workbench = ToolTypeIndex.fromId(reader.remaining) orelse return error.Invalid},
|
||||
};
|
||||
Sync.ServerSide.createInventory(user.?, id, len, typ, source);
|
||||
return .{
|
||||
@ -1231,7 +1232,7 @@ pub const Command = struct { // MARK: Command
|
||||
cmd.tryCraftingTo(allocator, self.source, self.dest, side, user);
|
||||
return;
|
||||
}
|
||||
if(self.dest.inv.type == .workbench and self.dest.slot != 25 and self.dest.inv.type.workbench.slotInfos[self.dest.slot].disabled) return;
|
||||
if(self.dest.inv.type == .workbench and self.dest.slot != 25 and self.dest.inv.type.workbench.slotInfos()[self.dest.slot].disabled) return;
|
||||
if(self.dest.inv.type == .workbench and self.dest.slot == 25) {
|
||||
if(self.source.ref().item == null and self.dest.ref().item != null) {
|
||||
cmd.executeBaseOperation(allocator, .{.move = .{
|
||||
@ -1288,7 +1289,7 @@ pub const Command = struct { // MARK: Command
|
||||
std.debug.assert(self.source.inv.type == .normal);
|
||||
if(self.dest.inv.type == .creative) return;
|
||||
if(self.dest.inv.type == .crafting) return;
|
||||
if(self.dest.inv.type == .workbench and (self.dest.slot == 25 or self.dest.inv.type.workbench.slotInfos[self.dest.slot].disabled)) return;
|
||||
if(self.dest.inv.type == .workbench and (self.dest.slot == 25 or self.dest.inv.type.workbench.slotInfos()[self.dest.slot].disabled)) return;
|
||||
if(self.dest.inv.type == .workbench and !canPutIntoWorkbench(self.source)) return;
|
||||
const itemSource = self.source.ref().item orelse return;
|
||||
if(self.dest.ref().item) |itemDest| {
|
||||
@ -1342,7 +1343,7 @@ pub const Command = struct { // MARK: Command
|
||||
cmd.tryCraftingTo(allocator, self.dest, self.source, side, user);
|
||||
return;
|
||||
}
|
||||
if(self.source.inv.type == .workbench and self.source.slot != 25 and self.source.inv.type.workbench.slotInfos[self.source.slot].disabled) return;
|
||||
if(self.source.inv.type == .workbench and self.source.slot != 25 and self.source.inv.type.workbench.slotInfos()[self.source.slot].disabled) return;
|
||||
if(self.source.inv.type == .workbench and self.source.slot == 25) {
|
||||
if(self.dest.ref().item == null and self.source.ref().item != null) {
|
||||
cmd.executeBaseOperation(allocator, .{.move = .{
|
||||
@ -1413,7 +1414,7 @@ pub const Command = struct { // MARK: Command
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(self.source.inv.type == .workbench and self.source.slot != 25 and self.source.inv.type.workbench.slotInfos[self.source.slot].disabled) return;
|
||||
if(self.source.inv.type == .workbench and self.source.slot != 25 and self.source.inv.type.workbench.slotInfos()[self.source.slot].disabled) return;
|
||||
if(self.source.inv.type == .workbench and self.source.slot == 25) {
|
||||
cmd.removeToolCraftingIngredients(allocator, self.source.inv, side);
|
||||
}
|
||||
@ -1449,7 +1450,7 @@ pub const Command = struct { // MARK: Command
|
||||
amount: u16 = 0,
|
||||
|
||||
fn run(self: FillFromCreative, allocator: NeverFailingAllocator, cmd: *Command, side: Side, user: ?*main.server.User, mode: Gamemode) error{serverFailure}!void {
|
||||
if(self.dest.inv.type == .workbench and (self.dest.slot == 25 or self.dest.inv.type.workbench.slotInfos[self.dest.slot].disabled)) return;
|
||||
if(self.dest.inv.type == .workbench and (self.dest.slot == 25 or self.dest.inv.type.workbench.slotInfos()[self.dest.slot].disabled)) return;
|
||||
if(side == .server and user != null and mode != .creative) return;
|
||||
if(side == .client and mode != .creative) return;
|
||||
|
||||
@ -1847,7 +1848,7 @@ const Type = union(TypeEnum) {
|
||||
normal: void,
|
||||
creative: void,
|
||||
crafting: void,
|
||||
workbench: *const main.items.ToolType,
|
||||
workbench: ToolTypeIndex,
|
||||
|
||||
pub fn shouldDepositToUserOnClose(self: Type) bool {
|
||||
return self == .workbench;
|
||||
@ -1905,7 +1906,7 @@ fn update(self: Inventory) void {
|
||||
self._items[self._items.len - 1].deinit();
|
||||
self._items[self._items.len - 1].clear();
|
||||
var availableItems: [25]?BaseItemIndex = undefined;
|
||||
const slotInfos = self.type.workbench.slotInfos;
|
||||
const slotInfos = self.type.workbench.slotInfos();
|
||||
|
||||
for(0..25) |i| {
|
||||
if(self._items[i].item != null and self._items[i].item.? == .baseItem) {
|
||||
|
@ -6,6 +6,8 @@ const BaseItem = items.BaseItem;
|
||||
const Inventory = items.Inventory;
|
||||
const Item = items.Item;
|
||||
const Tool = items.Tool;
|
||||
const ToolType = items.ToolType;
|
||||
const ToolTypeIndex = items.ToolTypeIndex;
|
||||
const Player = main.game.Player;
|
||||
const Texture = main.graphics.Texture;
|
||||
const Vec2f = main.vec.Vec2f;
|
||||
@ -37,7 +39,7 @@ var inv: Inventory = undefined;
|
||||
|
||||
var itemSlots: [25]*ItemSlot = undefined;
|
||||
|
||||
var toolTypes: main.ListUnmanaged(*const main.items.ToolType) = .{};
|
||||
var toolTypes: main.ListUnmanaged(ToolTypeIndex) = undefined;
|
||||
var currentToolType: usize = 0;
|
||||
|
||||
var toolButton: *Button = undefined;
|
||||
@ -47,7 +49,7 @@ var needsUpdate: bool = false;
|
||||
fn toggleTool(_: usize) void {
|
||||
currentToolType += 1;
|
||||
currentToolType %= toolTypes.items.len;
|
||||
toolButton.child.label.updateText(toolTypes.items[currentToolType].id);
|
||||
toolButton.child.label.updateText(toolTypes.items[currentToolType].id());
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
@ -61,7 +63,7 @@ fn openInventory() void {
|
||||
const row = HorizontalList.init();
|
||||
for(0..5) |x| {
|
||||
const index = x + y*5;
|
||||
const slotInfo = toolTypes.items[currentToolType].slotInfos[index];
|
||||
const slotInfo = toolTypes.items[currentToolType].slotInfos()[index];
|
||||
const slot = ItemSlot.init(.{0, 0}, inv, @intCast(index), if(slotInfo.disabled) .invisible else if(slotInfo.optional) .immutable else .default, if(slotInfo.disabled) .immutable else .normal);
|
||||
itemSlots[index] = slot;
|
||||
row.add(slot);
|
||||
@ -72,7 +74,7 @@ fn openInventory() void {
|
||||
list.add(grid);
|
||||
}
|
||||
const verticalThing = VerticalList.init(.{0, 0}, 300, padding);
|
||||
toolButton = Button.initText(.{8, 0}, 116, toolTypes.items[currentToolType].id, .{.callback = &toggleTool});
|
||||
toolButton = Button.initText(.{8, 0}, 116, toolTypes.items[currentToolType].id(), .{.callback = &toggleTool});
|
||||
verticalThing.add(toolButton);
|
||||
const buttonHeight = verticalThing.size[1];
|
||||
const craftingResultList = HorizontalList.init();
|
||||
@ -119,15 +121,17 @@ pub fn render() void {
|
||||
|
||||
pub fn onOpen() void {
|
||||
currentToolType = 0;
|
||||
var iterator = main.items.toolTypeIterator();
|
||||
|
||||
toolTypes = .{};
|
||||
var iterator = ToolTypeIndex.iterator();
|
||||
while(iterator.next()) |toolType| {
|
||||
toolTypes.append(main.globalAllocator, toolType);
|
||||
}
|
||||
|
||||
openInventory();
|
||||
}
|
||||
|
||||
pub fn onClose() void {
|
||||
toolTypes.deinit(main.globalAllocator);
|
||||
closeInventory();
|
||||
toolTypes.clearAndFree(main.globalAllocator);
|
||||
}
|
||||
|
105
src/items.zig
105
src/items.zig
@ -16,6 +16,7 @@ const Vec2i = vec.Vec2i;
|
||||
const Vec3i = vec.Vec3i;
|
||||
const Vec3f = vec.Vec3f;
|
||||
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
|
||||
const ListUnmanaged = main.ListUnmanaged;
|
||||
|
||||
const modifierList = @import("tool/modifiers/_list.zig");
|
||||
const modifierRestrictionList = @import("tool/modifiers/restrictions/_list.zig");
|
||||
@ -340,8 +341,8 @@ const TextureGenerator = struct { // MARK: TextureGenerator
|
||||
const img = tool.image;
|
||||
for(0..16) |x| {
|
||||
for(0..16) |y| {
|
||||
const source = tool.type.pixelSources[x][y];
|
||||
const sourceOverlay = tool.type.pixelSourcesOverlay[x][y];
|
||||
const source = tool.type.pixelSources()[x][y];
|
||||
const sourceOverlay = tool.type.pixelSourcesOverlay()[x][y];
|
||||
if(sourceOverlay < 25 and tool.craftingGrid[sourceOverlay] != null) {
|
||||
tool.materialGrid[x][y] = tool.craftingGrid[sourceOverlay];
|
||||
} else if(source < 25) {
|
||||
@ -389,7 +390,7 @@ const ToolPhysics = struct { // MARK: ToolPhysics
|
||||
}
|
||||
var tempModifiers: main.List(Modifier) = .init(main.stackAllocator);
|
||||
defer tempModifiers.deinit();
|
||||
for(tool.type.properties) |property| {
|
||||
for(tool.type.properties()) |property| {
|
||||
var sum: f32 = 0;
|
||||
var weight: f32 = 0;
|
||||
for(0..25) |i| {
|
||||
@ -504,6 +505,45 @@ const PropertyMatrix = struct { // MARK: PropertyMatrix
|
||||
};
|
||||
};
|
||||
|
||||
pub const ToolTypeIndex = packed struct {
|
||||
index: u16,
|
||||
|
||||
const ToolTypeIterator = struct {
|
||||
i: u16 = 0,
|
||||
|
||||
pub fn next(self: *ToolTypeIterator) ?ToolTypeIndex {
|
||||
if(self.i >= toolTypeList.items.len) return null;
|
||||
defer self.i += 1;
|
||||
return ToolTypeIndex{.index = self.i};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn iterator() ToolTypeIterator {
|
||||
return .{};
|
||||
}
|
||||
pub fn fromId(_id: []const u8) ?ToolTypeIndex {
|
||||
return toolTypeIdToIndex.get(_id);
|
||||
}
|
||||
pub fn id(self: ToolTypeIndex) []const u8 {
|
||||
return toolTypeList.items[self.index].id;
|
||||
}
|
||||
pub fn blockTags(self: ToolTypeIndex) []const Tag {
|
||||
return toolTypeList.items[self.index].blockTags;
|
||||
}
|
||||
pub fn properties(self: ToolTypeIndex) []const PropertyMatrix {
|
||||
return toolTypeList.items[self.index].properties;
|
||||
}
|
||||
pub fn slotInfos(self: ToolTypeIndex) *const [25]SlotInfo {
|
||||
return &toolTypeList.items[self.index].slotInfos;
|
||||
}
|
||||
pub fn pixelSources(self: ToolTypeIndex) *const [16][16]u8 {
|
||||
return &toolTypeList.items[self.index].pixelSources;
|
||||
}
|
||||
pub fn pixelSourcesOverlay(self: ToolTypeIndex) *const [16][16]u8 {
|
||||
return &toolTypeList.items[self.index].pixelSourcesOverlay;
|
||||
}
|
||||
};
|
||||
|
||||
pub const ToolType = struct { // MARK: ToolType
|
||||
id: []const u8,
|
||||
blockTags: []main.Tag,
|
||||
@ -534,7 +574,7 @@ pub const Tool = struct { // MARK: Tool
|
||||
image: graphics.Image,
|
||||
texture: ?graphics.Texture,
|
||||
seed: u32,
|
||||
type: *const ToolType,
|
||||
type: ToolTypeIndex,
|
||||
|
||||
damage: f32,
|
||||
|
||||
@ -600,7 +640,7 @@ pub const Tool = struct { // MARK: Tool
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn initFromCraftingGrid(craftingGrid: [25]?BaseItemIndex, seed: u32, typ: *const ToolType) *Tool {
|
||||
pub fn initFromCraftingGrid(craftingGrid: [25]?BaseItemIndex, seed: u32, typ: ToolTypeIndex) *Tool {
|
||||
const self = init();
|
||||
self.seed = seed;
|
||||
self.craftingGrid = craftingGrid;
|
||||
@ -613,9 +653,9 @@ pub const Tool = struct { // MARK: Tool
|
||||
}
|
||||
|
||||
pub fn initFromZon(zon: ZonElement) *Tool {
|
||||
const self = initFromCraftingGrid(extractItemsFromZon(zon.getChild("grid")), zon.get(u32, "seed", 0), getToolTypeByID(zon.get([]const u8, "type", "cubyz:pickaxe")) orelse blk: {
|
||||
const self = initFromCraftingGrid(extractItemsFromZon(zon.getChild("grid")), zon.get(u32, "seed", 0), ToolTypeIndex.fromId(zon.get([]const u8, "type", "cubyz:pickaxe")) orelse blk: {
|
||||
std.log.err("Couldn't find tool with type {s}. Replacing it with cubyz:pickaxe", .{zon.get([]const u8, "type", "cubyz:pickaxe")});
|
||||
break :blk getToolTypeByID("cubyz:pickaxe") orelse @panic("cubyz:pickaxe tool not found. Did you load the game with the correct assets?");
|
||||
break :blk ToolTypeIndex.fromId("cubyz:pickaxe") orelse @panic("cubyz:pickaxe tool not found. Did you load the game with the correct assets?");
|
||||
});
|
||||
self.durability = zon.get(u32, "durability", std.math.lossyCast(u32, self.maxDurability));
|
||||
return self;
|
||||
@ -643,7 +683,7 @@ pub const Tool = struct { // MARK: Tool
|
||||
zonObject.put("grid", zonArray);
|
||||
zonObject.put("durability", self.durability);
|
||||
zonObject.put("seed", self.seed);
|
||||
zonObject.put("type", self.type.id);
|
||||
zonObject.put("type", self.type.id());
|
||||
return zonObject;
|
||||
}
|
||||
|
||||
@ -685,7 +725,7 @@ pub const Tool = struct { // MARK: Tool
|
||||
\\Damage: {d:.2}
|
||||
\\Durability: {}/{}
|
||||
, .{
|
||||
self.type.id,
|
||||
self.type.id(),
|
||||
self.swingTime,
|
||||
self.damage,
|
||||
self.durability,
|
||||
@ -708,7 +748,7 @@ pub const Tool = struct { // MARK: Tool
|
||||
damage = modifier.changeBlockDamage(damage, block);
|
||||
}
|
||||
for(block.blockTags()) |blockTag| {
|
||||
for(self.type.blockTags) |toolTag| {
|
||||
for(self.type.blockTags()) |toolTag| {
|
||||
if(toolTag == blockTag) return damage;
|
||||
}
|
||||
}
|
||||
@ -874,7 +914,10 @@ pub const Recipe = struct { // MARK: Recipe
|
||||
};
|
||||
|
||||
var arena: main.heap.NeverFailingArenaAllocator = undefined;
|
||||
var toolTypes: std.StringHashMap(ToolType) = undefined;
|
||||
|
||||
var toolTypeList: ListUnmanaged(ToolType) = undefined;
|
||||
var toolTypeIdToIndex: std.StringHashMapUnmanaged(ToolTypeIndex) = undefined;
|
||||
|
||||
var reverseIndices: std.StringHashMap(BaseItemIndex) = undefined;
|
||||
var modifiers: std.StringHashMap(*const Modifier.VTable) = undefined;
|
||||
var modifierRestrictions: std.StringHashMap(*const ModifierRestriction.VTable) = undefined;
|
||||
@ -888,11 +931,7 @@ pub fn hasRegistered(id: []const u8) bool {
|
||||
}
|
||||
|
||||
pub fn hasRegisteredTool(id: []const u8) bool {
|
||||
return toolTypes.contains(id);
|
||||
}
|
||||
|
||||
pub fn toolTypeIterator() std.StringHashMap(ToolType).ValueIterator {
|
||||
return toolTypes.valueIterator();
|
||||
return toolTypeIdToIndex.contains(id);
|
||||
}
|
||||
|
||||
pub fn iterator() std.StringHashMap(BaseItemIndex).ValueIterator {
|
||||
@ -905,7 +944,10 @@ pub fn recipes() []Recipe {
|
||||
|
||||
pub fn globalInit() void {
|
||||
arena = .init(main.globalAllocator);
|
||||
toolTypes = .init(arena.allocator().allocator);
|
||||
|
||||
toolTypeList = .{};
|
||||
toolTypeIdToIndex = .{};
|
||||
|
||||
reverseIndices = .init(arena.allocator().allocator);
|
||||
recipeList = .init(arena.allocator());
|
||||
itemListSize = 0;
|
||||
@ -982,7 +1024,7 @@ fn loadPixelSources(assetFolder: []const u8, id: []const u8, layerPostfix: []con
|
||||
}
|
||||
|
||||
pub fn registerTool(assetFolder: []const u8, id: []const u8, zon: ZonElement) void {
|
||||
if(toolTypes.contains(id)) {
|
||||
if(toolTypeIdToIndex.contains(id)) {
|
||||
std.log.err("Registered tool type with id {s} twice!", .{id});
|
||||
}
|
||||
var slotInfos: [25]SlotInfo = @splat(.{});
|
||||
@ -1000,9 +1042,9 @@ pub fn registerTool(assetFolder: []const u8, id: []const u8, zon: ZonElement) vo
|
||||
}
|
||||
slotInfos[i].optional = zonDisabled.as(usize, 0) != 0;
|
||||
}
|
||||
var parameterMatrics: main.List(PropertyMatrix) = .init(arena.allocator());
|
||||
var parameterMatrices: main.List(PropertyMatrix) = .init(arena.allocator());
|
||||
for(zon.getChild("parameters").toSlice()) |paramZon| {
|
||||
const val = parameterMatrics.addOne();
|
||||
const val = parameterMatrices.addOne();
|
||||
val.source = MaterialProperty.fromString(paramZon.get([]const u8, "source", "not specified"));
|
||||
val.destination = ToolProperty.fromString(paramZon.get([]const u8, "destination", "not specified"));
|
||||
val.resultScale = paramZon.get(f32, "factor", 1.0);
|
||||
@ -1016,15 +1058,17 @@ pub fn registerTool(assetFolder: []const u8, id: []const u8, zon: ZonElement) vo
|
||||
loadPixelSources(assetFolder, id, "", &pixelSources);
|
||||
var pixelSourcesOverlay: [16][16]u8 = undefined;
|
||||
loadPixelSources(assetFolder, id, "_overlay", &pixelSourcesOverlay);
|
||||
|
||||
const idDupe = arena.allocator().dupe(u8, id);
|
||||
toolTypes.put(idDupe, .{
|
||||
toolTypeList.append(arena.allocator(), .{
|
||||
.id = idDupe,
|
||||
.blockTags = Tag.loadTagsFromZon(arena.allocator(), zon.getChild("blockTags")),
|
||||
.slotInfos = slotInfos,
|
||||
.properties = parameterMatrics.toOwnedSlice(),
|
||||
.properties = parameterMatrices.toOwnedSlice(),
|
||||
.pixelSources = pixelSources,
|
||||
.pixelSourcesOverlay = pixelSourcesOverlay,
|
||||
}) catch unreachable;
|
||||
});
|
||||
toolTypeIdToIndex.put(arena.allocator().allocator, idDupe, .{.index = @intCast(toolTypeList.items.len - 1)}) catch unreachable;
|
||||
|
||||
std.log.debug("Registered tool: '{s}'", .{id});
|
||||
}
|
||||
@ -1071,7 +1115,8 @@ pub fn registerRecipes(zon: ZonElement) void {
|
||||
}
|
||||
|
||||
pub fn reset() void {
|
||||
toolTypes.clearAndFree();
|
||||
toolTypeList.clearAndFree(arena.allocator());
|
||||
toolTypeIdToIndex.clearAndFree(arena.allocator().allocator);
|
||||
reverseIndices.clearAndFree();
|
||||
for(recipeList.items) |recipe| {
|
||||
if(recipe.cachedInventory) |inv| {
|
||||
@ -1084,7 +1129,8 @@ pub fn reset() void {
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
toolTypes.clearAndFree();
|
||||
toolTypeList.deinit(arena.allocator());
|
||||
toolTypeIdToIndex.deinit(arena.allocator().allocator);
|
||||
reverseIndices.clearAndFree();
|
||||
for(recipeList.items) |recipe| {
|
||||
if(recipe.cachedInventory) |inv| {
|
||||
@ -1097,12 +1143,3 @@ pub fn deinit() void {
|
||||
arena.deinit();
|
||||
Inventory.Sync.ClientSide.deinit();
|
||||
}
|
||||
|
||||
pub fn getToolTypeByID(id: []const u8) ?*const ToolType {
|
||||
if(toolTypes.getPtr(id)) |result| {
|
||||
return result;
|
||||
} else {
|
||||
std.log.err("Couldn't find item {s}.", .{id});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user