diff --git a/src/items.zig b/src/items.zig index a3019ba350..c6b7e3802a 100644 --- a/src/items.zig +++ b/src/items.zig @@ -1321,16 +1321,21 @@ pub const Recipe = struct { // MARK: Recipe sourceAmounts: []u16, resultItem: BaseItemIndex, resultAmount: u16, + craftingTags: []const Tag, fn getValidRecipe(self: Recipe) error{Invalid}!*Recipe { outer: for (main.items.getRecipes()) |*recipe| { if (recipe.resultItem != self.resultItem) continue; if (recipe.resultAmount != self.resultAmount) continue; if (recipe.sourceItems.len != self.sourceItems.len) continue; + if (recipe.craftingTags.len != self.craftingTags.len) continue; for (recipe.sourceItems, recipe.sourceAmounts, self.sourceItems, self.sourceAmounts) |recipeItem, recipeAmount, selfItem, selfAmount| { if (recipeItem != selfItem) continue :outer; if (recipeAmount != selfAmount) continue :outer; } + for (recipe.craftingTags, self.craftingTags) |recipeCraftingTag, selfCraftingTag| { + if (recipeCraftingTag != selfCraftingTag) continue :outer; + } return recipe; } return error.Invalid; @@ -1344,6 +1349,10 @@ pub const Recipe = struct { // MARK: Recipe writer.writeEnum(BaseItemIndex, item); writer.writeVarInt(u16, amount); } + writer.writeVarInt(usize, self.craftingTags.len); + for (self.craftingTags) |tag| { + writer.writeSliceWithSize(tag.getName()); + } } pub fn fromBytes(reader: *BinaryReader) !*Recipe { @@ -1361,7 +1370,15 @@ pub const Recipe = struct { // MARK: Recipe sourceAmounts.append(main.stackAllocator, try reader.readVarInt(u16)); } - return getValidRecipe(.{.sourceItems = sourceItems.items, .sourceAmounts = sourceAmounts.items, .resultItem = resultItem, .resultAmount = resultAmount}); + const tagCount = try reader.readVarInt(usize); + var craftingTagTypes: main.List(Tag) = .initCapacity(main.stackAllocator, @min(256, tagCount)); + defer craftingTagTypes.deinit(main.stackAllocator); + + while (craftingTagTypes.items.len < tagCount) { + craftingTagTypes.append(main.stackAllocator, Tag.get(try reader.readSliceWithSize()) orelse return error.invalidTag); + } + + return getValidRecipe(.{.sourceItems = sourceItems.items, .sourceAmounts = sourceAmounts.items, .resultItem = resultItem, .resultAmount = resultAmount, .craftingTags = craftingTagTypes.items}); } }; diff --git a/src/items/recipes.zig b/src/items/recipes.zig index ab79b3bb0e..2c6bca8569 100644 --- a/src/items/recipes.zig +++ b/src/items/recipes.zig @@ -190,7 +190,7 @@ fn generateItemCombos(allocator: NeverFailingAllocator, recipe: []const ZonEleme return newInputCombos; } -pub fn addRecipe(itemCombo: []const ItemWithAmount, list: *main.ListManaged(Recipe)) void { +pub fn addRecipe(itemCombo: []const ItemWithAmount, list: *main.ListManaged(Recipe), craftingTags: []const Tag) void { const inputs = itemCombo[0 .. itemCombo.len - 1]; const output = itemCombo[itemCombo.len - 1]; const recipe = Recipe{ @@ -198,6 +198,7 @@ pub fn addRecipe(itemCombo: []const ItemWithAmount, list: *main.ListManaged(Reci .sourceAmounts = main.worldArena.alloc(u16, inputs.len), .resultItem = output.item, .resultAmount = output.amount, + .craftingTags = main.worldArena.dupe(Tag, craftingTags), }; for (inputs, 0..) |input, i| { recipe.sourceItems[i] = input.item; @@ -218,11 +219,15 @@ pub fn parseRecipe(zon: ZonElement, list: *main.ListManaged(Recipe)) !void { return error.InvalidReversibleRecipe; } + const defaultCraftingTags: []const Tag = &.{.handCraftable}; + const foundCraftingTags = Tag.loadTagsFromZon(arena, zon.getChild("craftingTags")); + const craftingTags = if (foundCraftingTags.len != 0) foundCraftingTags else defaultCraftingTags; + const itemCombos = try generateItemCombos(arena, recipeItems); for (itemCombos) |itemCombo| { - addRecipe(itemCombo, list); + addRecipe(itemCombo, list, craftingTags); if (reversible) { - addRecipe(&.{itemCombo[1], itemCombo[0]}, list); + addRecipe(&.{itemCombo[1], itemCombo[0]}, list, craftingTags); } } } diff --git a/src/tag.zig b/src/tag.zig index e6a380c4b2..491021fc85 100644 --- a/src/tag.zig +++ b/src/tag.zig @@ -12,6 +12,7 @@ pub const Tag = enum(u32) { fluidPlaceable = 3, chiselable = 4, playerModel = 5, + handCraftable = 6, _, pub fn initTags() void {