up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled

This commit is contained in:
2026-07-09 08:33:57 +08:00
commit 26ed99fda6
845 changed files with 75419 additions and 0 deletions
Binary file not shown.
+120
View File
@@ -0,0 +1,120 @@
package recipe
import (
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
)
// DecoratedPotRecipe is a dynamic recipe for crafting decorated pots. The output depends on which
// pottery sherds or bricks are used in the crafting grid.
type DecoratedPotRecipe struct {
block string
}
// NewDecoratedPotRecipe creates a new decorated pot recipe.
func NewDecoratedPotRecipe() DecoratedPotRecipe {
return DecoratedPotRecipe{block: "crafting_table"}
}
// potDecoration is a local interface to check if an item can be used as a pot decoration
// without importing the block package (which would create an import cycle).
type potDecoration interface {
world.Item
PotDecoration() bool
}
// Match checks if the given input items match the decorated pot recipe pattern.
// The pattern requires exactly 4 PotDecoration items (bricks or pottery sherds) in a diamond/plus shape:
// - Slot 1 (top centre)
// - Slot 3 (middle left)
// - Slot 5 (middle right)
// - Slot 7 (bottom centre)
// All other slots must be empty.
func (r DecoratedPotRecipe) Match(input []Item) (output []item.Stack, ok bool) {
// For a 3x3 crafting grid, we need exactly 9 slots
if len(input) != 9 {
return nil, false
}
// Define the slots for the diamond pattern (0-indexed)
// Layout: 0 1 2
// 3 4 5
// 6 7 8
// We need items at: 1 (top), 3 (left), 5 (right), 7 (bottom)
// Odd indices should have items, even indices should be empty
decorations := [4]world.Item{}
decorationIndex := 0
for i := range input {
it := input[i]
if i%2 == 0 {
// Even slots (0, 2, 4, 6, 8) should be empty
if !it.Empty() {
return nil, false
}
} else {
// Odd slots (1, 3, 5, 7) should have items
if it.Empty() {
return nil, false
}
// Extract the actual item from the Item interface
var actualItem item.Stack
if v, ok := it.(item.Stack); ok {
actualItem = v
} else {
// ItemTag or other types are not valid for decorated pots
return nil, false
}
// Check if the item implements PotDecoration
decoration, ok := actualItem.Item().(potDecoration)
if !ok {
return nil, false
}
decorations[decorationIndex] = decoration
decorationIndex++
}
}
// Create the decorated pot by encoding the decorations into NBT
// We'll use world.BlockByName to get the DecoratedPot block and set its decorations
// The decorations are ordered: [top, left, right, bottom] in the crafting grid
// For the pot NBT: [back, left, front, right] based on facing direction
// Get a decorated pot block instance
pot, ok := world.BlockByName("minecraft:decorated_pot", map[string]any{"direction": int32(2)})
if !ok {
return nil, false
}
// The pot will be decoded with the decorations through NBT when placed
// For now, we'll create a pot with the decorations in the correct order
// DecoratedPot.DecodeNBT expects sherds in order: [back, left, front, right]
sherds := []any{}
// Order: top -> back, left -> left, bottom -> front, right -> right
for _, idx := range []int{0, 1, 3, 2} { // top, left, bottom, right
name, _ := decorations[idx].EncodeItem()
sherds = append(sherds, name)
}
// Decode the pot with the sherds NBT data using type assertion
if nbtDecoder, ok := pot.(interface {
DecodeNBT(map[string]any) any
}); ok {
decodedPot := nbtDecoder.DecodeNBT(map[string]any{
"id": "DecoratedPot",
"sherds": sherds,
})
if potItem, ok := decodedPot.(world.Item); ok {
return []item.Stack{item.NewStack(potItem, 1)}, true
}
}
return nil, false
}
// Block returns the block used to craft this recipe.
func (r DecoratedPotRecipe) Block() string {
return r.block
}
+116
View File
@@ -0,0 +1,116 @@
package recipe
import (
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"math"
)
// Item represents an item that can be used as either the input or output of an item. These do not
// necessarily resolve to an actual item, but can be just as simple as a tag etc.
type Item interface {
// Count returns the amount of items that is present on the stack. The count is guaranteed never to be
// negative.
Count() int
// Empty checks if the stack is empty (has a count of 0).
Empty() bool
}
// inputItem is a type representing an input item, with a helper function to convert it to an Item.
type inputItem struct {
// Name is the name of the item being inputted.
Name string `nbt:"name"`
// Meta is the meta of the item. This can change the item almost completely, or act as durability.
Meta int32 `nbt:"meta"`
// Count is the amount of the item.
Count int32 `nbt:"count"`
// State is included if the output is a block. If it's not included, the meta can be discarded and the output item can be incorrect.
State struct {
Name string `nbt:"name"`
Properties map[string]interface{} `nbt:"states"`
Version int32 `nbt:"version"`
} `nbt:"block"`
// Tag is included if the input item is defined by a tag instead of a specific item.
Tag string `nbt:"tag"`
}
// Item converts an input item to a recipe item.
func (i inputItem) Item() (Item, bool) {
if i.Tag != "" {
return NewItemTag(i.Tag, int(i.Count)), true
}
it, ok := world.ItemByName(i.Name, int16(i.Meta))
if !ok {
return nil, false
}
st := item.NewStack(it, int(i.Count))
if i.Meta == math.MaxInt16 {
st = st.WithValue("variants", true)
}
return st, true
}
// inputItems is a type representing a list of input items, with a helper function to convert it to an Item.
type inputItems []inputItem
// Items converts input items to recipe items.
func (d inputItems) Items() ([]Item, bool) {
s := make([]Item, 0, len(d))
for _, i := range d {
itemInput, ok := i.Item()
if !ok {
return nil, false
}
s = append(s, itemInput)
}
return s, true
}
// outputItem is an output item.
type outputItem struct {
// Name is the name of the item being output.
Name string `nbt:"name"`
// Meta is the meta of the item. This can change the item almost completely, or act as durability.
Meta int32 `nbt:"meta"`
// Count is the amount of the item.
Count int16 `nbt:"count"`
// State is included if the output is a block. If it's not included, the meta can be discarded and the output item can be incorrect.
State struct {
Name string `nbt:"name"`
Properties map[string]interface{} `nbt:"states"`
Version int32 `nbt:"version"`
} `nbt:"block"`
// NBTData contains extra NBTData which may modify the item in other, more discreet ways.
NBTData map[string]interface{} `nbt:"data"`
}
// Stack converts an output item to an item stack.
func (o outputItem) Stack() (item.Stack, bool) {
it, ok := world.ItemByName(o.Name, int16(o.Meta))
if !ok {
return item.Stack{}, false
}
if n, ok := it.(world.NBTer); ok {
it = n.DecodeNBT(o.NBTData).(world.Item)
}
return item.NewStack(it, int(o.Count)), true
}
// outputItems is an array of output items.
type outputItems []outputItem
// Stacks converts output items to item stacks.
func (d outputItems) Stacks() ([]item.Stack, bool) {
s := make([]item.Stack, 0, len(d))
for _, o := range d {
itemOutput, ok := o.Stack()
if !ok {
return nil, false
}
s = append(s, itemOutput)
}
return s, true
}
+60
View File
@@ -0,0 +1,60 @@
package recipe
import (
_ "embed"
"encoding/json"
)
var (
//go:embed item_tags.json
itemTagData []byte
itemTags = make(map[string][]string)
)
func init() {
if err := json.Unmarshal(itemTagData, &itemTags); err != nil {
panic(err)
}
}
// ItemTag represents a recipe item that is identified by a tag, such as "minecraft:planks" or
// "minecraft:digger" and so on.
type ItemTag struct {
tag string
count int
items []string
}
// NewItemTag creates a new item tag with the tag and count passed.
func NewItemTag(tag string, count int) ItemTag {
if count < 0 {
count = 0
}
return ItemTag{tag: tag, count: count, items: itemTags[tag]}
}
// Count ...
func (i ItemTag) Count() int {
return i.count
}
// Empty ...
func (i ItemTag) Empty() bool {
return i.count == 0 || i.tag == ""
}
// Tag returns the tag of the item.
func (i ItemTag) Tag() string {
return i.tag
}
// Contains returns true if the item tag contains the item with the name passed.
func (i ItemTag) Contains(name string) bool {
for _, item := range i.items {
if item == name {
return true
}
}
return false
}
+829
View File
@@ -0,0 +1,829 @@
{
"minecraft:arrow": [
"minecraft:arrow"
],
"minecraft:banner": [
"minecraft:banner"
],
"minecraft:boat": [
"minecraft:acacia_boat",
"minecraft:acacia_chest_boat",
"minecraft:bamboo_chest_raft",
"minecraft:bamboo_raft",
"minecraft:birch_boat",
"minecraft:birch_chest_boat",
"minecraft:cherry_boat",
"minecraft:cherry_chest_boat",
"minecraft:dark_oak_boat",
"minecraft:dark_oak_chest_boat",
"minecraft:jungle_boat",
"minecraft:jungle_chest_boat",
"minecraft:mangrove_boat",
"minecraft:mangrove_chest_boat",
"minecraft:oak_boat",
"minecraft:oak_chest_boat",
"minecraft:pale_oak_boat",
"minecraft:pale_oak_chest_boat",
"minecraft:spruce_boat",
"minecraft:spruce_chest_boat"
],
"minecraft:boats": [
"minecraft:acacia_boat",
"minecraft:acacia_chest_boat",
"minecraft:bamboo_chest_raft",
"minecraft:bamboo_raft",
"minecraft:birch_boat",
"minecraft:birch_chest_boat",
"minecraft:cherry_boat",
"minecraft:cherry_chest_boat",
"minecraft:dark_oak_boat",
"minecraft:dark_oak_chest_boat",
"minecraft:jungle_boat",
"minecraft:jungle_chest_boat",
"minecraft:mangrove_boat",
"minecraft:mangrove_chest_boat",
"minecraft:oak_boat",
"minecraft:oak_chest_boat",
"minecraft:pale_oak_boat",
"minecraft:pale_oak_chest_boat",
"minecraft:spruce_boat",
"minecraft:spruce_chest_boat"
],
"minecraft:bookshelf_books": [
"minecraft:book",
"minecraft:enchanted_book",
"minecraft:writable_book",
"minecraft:written_book"
],
"minecraft:chainmail_tier": [
"minecraft:chainmail_boots",
"minecraft:chainmail_chestplate",
"minecraft:chainmail_helmet",
"minecraft:chainmail_leggings"
],
"minecraft:coals": [
"minecraft:charcoal",
"minecraft:coal"
],
"minecraft:crimson_stems": [
"minecraft:crimson_hyphae",
"minecraft:crimson_stem",
"minecraft:stripped_crimson_hyphae",
"minecraft:stripped_crimson_stem"
],
"minecraft:decorated_pot_sherds": [
"minecraft:angler_pottery_sherd",
"minecraft:archer_pottery_sherd",
"minecraft:arms_up_pottery_sherd",
"minecraft:blade_pottery_sherd",
"minecraft:brewer_pottery_sherd",
"minecraft:brick",
"minecraft:burn_pottery_sherd",
"minecraft:danger_pottery_sherd",
"minecraft:explorer_pottery_sherd",
"minecraft:flow_pottery_sherd",
"minecraft:friend_pottery_sherd",
"minecraft:guster_pottery_sherd",
"minecraft:heart_pottery_sherd",
"minecraft:heartbreak_pottery_sherd",
"minecraft:howl_pottery_sherd",
"minecraft:miner_pottery_sherd",
"minecraft:mourner_pottery_sherd",
"minecraft:plenty_pottery_sherd",
"minecraft:prize_pottery_sherd",
"minecraft:scrape_pottery_sherd",
"minecraft:sheaf_pottery_sherd",
"minecraft:shelter_pottery_sherd",
"minecraft:skull_pottery_sherd",
"minecraft:snort_pottery_sherd"
],
"minecraft:diamond_tier": [
"minecraft:diamond_axe",
"minecraft:diamond_boots",
"minecraft:diamond_chestplate",
"minecraft:diamond_helmet",
"minecraft:diamond_hoe",
"minecraft:diamond_leggings",
"minecraft:diamond_pickaxe",
"minecraft:diamond_shovel",
"minecraft:diamond_sword",
"minecraft:mace"
],
"minecraft:digger": [
"minecraft:diamond_axe",
"minecraft:diamond_hoe",
"minecraft:diamond_pickaxe",
"minecraft:diamond_shovel",
"minecraft:golden_axe",
"minecraft:golden_hoe",
"minecraft:golden_pickaxe",
"minecraft:golden_shovel",
"minecraft:iron_axe",
"minecraft:iron_hoe",
"minecraft:iron_pickaxe",
"minecraft:iron_shovel",
"minecraft:netherite_axe",
"minecraft:netherite_hoe",
"minecraft:netherite_pickaxe",
"minecraft:netherite_shovel",
"minecraft:stone_axe",
"minecraft:stone_hoe",
"minecraft:stone_pickaxe",
"minecraft:stone_shovel",
"minecraft:wooden_axe",
"minecraft:wooden_hoe",
"minecraft:wooden_pickaxe",
"minecraft:wooden_shovel"
],
"minecraft:door": [
"minecraft:acacia_door",
"minecraft:bamboo_door",
"minecraft:birch_door",
"minecraft:cherry_door",
"minecraft:copper_door",
"minecraft:crimson_door",
"minecraft:dark_oak_door",
"minecraft:exposed_copper_door",
"minecraft:iron_door",
"minecraft:jungle_door",
"minecraft:mangrove_door",
"minecraft:oxidized_copper_door",
"minecraft:pale_oak_door",
"minecraft:spruce_door",
"minecraft:warped_door",
"minecraft:waxed_copper_door",
"minecraft:waxed_exposed_copper_door",
"minecraft:waxed_oxidized_copper_door",
"minecraft:waxed_weathered_copper_door",
"minecraft:weathered_copper_door",
"minecraft:wooden_door"
],
"minecraft:golden_tier": [
"minecraft:golden_axe",
"minecraft:golden_boots",
"minecraft:golden_chestplate",
"minecraft:golden_helmet",
"minecraft:golden_hoe",
"minecraft:golden_leggings",
"minecraft:golden_pickaxe",
"minecraft:golden_shovel",
"minecraft:golden_sword"
],
"minecraft:hanging_actor": [
"minecraft:painting"
],
"minecraft:hanging_sign": [
"minecraft:acacia_hanging_sign",
"minecraft:bamboo_hanging_sign",
"minecraft:birch_hanging_sign",
"minecraft:cherry_hanging_sign",
"minecraft:crimson_hanging_sign",
"minecraft:dark_oak_hanging_sign",
"minecraft:jungle_hanging_sign",
"minecraft:mangrove_hanging_sign",
"minecraft:oak_hanging_sign",
"minecraft:pale_oak_hanging_sign",
"minecraft:spruce_hanging_sign",
"minecraft:warped_hanging_sign"
],
"minecraft:horse_armor": [
"minecraft:diamond_horse_armor",
"minecraft:golden_horse_armor",
"minecraft:iron_horse_armor",
"minecraft:leather_horse_armor"
],
"minecraft:iron_tier": [
"minecraft:iron_axe",
"minecraft:iron_boots",
"minecraft:iron_chestplate",
"minecraft:iron_helmet",
"minecraft:iron_hoe",
"minecraft:iron_leggings",
"minecraft:iron_pickaxe",
"minecraft:iron_shovel",
"minecraft:iron_sword"
],
"minecraft:is_armor": [
"minecraft:chainmail_boots",
"minecraft:chainmail_chestplate",
"minecraft:chainmail_helmet",
"minecraft:chainmail_leggings",
"minecraft:diamond_boots",
"minecraft:diamond_chestplate",
"minecraft:diamond_helmet",
"minecraft:diamond_leggings",
"minecraft:elytra",
"minecraft:golden_boots",
"minecraft:golden_chestplate",
"minecraft:golden_helmet",
"minecraft:golden_leggings",
"minecraft:iron_boots",
"minecraft:iron_chestplate",
"minecraft:iron_helmet",
"minecraft:iron_leggings",
"minecraft:leather_boots",
"minecraft:leather_chestplate",
"minecraft:leather_helmet",
"minecraft:leather_leggings",
"minecraft:netherite_boots",
"minecraft:netherite_chestplate",
"minecraft:netherite_helmet",
"minecraft:netherite_leggings",
"minecraft:turtle_helmet"
],
"minecraft:is_axe": [
"minecraft:diamond_axe",
"minecraft:golden_axe",
"minecraft:iron_axe",
"minecraft:netherite_axe",
"minecraft:stone_axe",
"minecraft:wooden_axe"
],
"minecraft:is_cooked": [
"minecraft:cooked_beef",
"minecraft:cooked_chicken",
"minecraft:cooked_cod",
"minecraft:cooked_mutton",
"minecraft:cooked_porkchop",
"minecraft:cooked_rabbit",
"minecraft:cooked_salmon",
"minecraft:rabbit_stew"
],
"minecraft:is_fish": [
"minecraft:cod",
"minecraft:cooked_cod",
"minecraft:cooked_salmon",
"minecraft:pufferfish",
"minecraft:salmon",
"minecraft:tropical_fish"
],
"minecraft:is_food": [
"minecraft:apple",
"minecraft:baked_potato",
"minecraft:beef",
"minecraft:beetroot",
"minecraft:beetroot_soup",
"minecraft:bread",
"minecraft:carrot",
"minecraft:chicken",
"minecraft:cooked_beef",
"minecraft:cooked_chicken",
"minecraft:cooked_mutton",
"minecraft:cooked_porkchop",
"minecraft:cooked_rabbit",
"minecraft:cookie",
"minecraft:dried_kelp",
"minecraft:enchanted_golden_apple",
"minecraft:golden_apple",
"minecraft:golden_carrot",
"minecraft:melon_slice",
"minecraft:mushroom_stew",
"minecraft:mutton",
"minecraft:porkchop",
"minecraft:potato",
"minecraft:pumpkin_pie",
"minecraft:rabbit",
"minecraft:rabbit_stew",
"minecraft:rotten_flesh",
"minecraft:sweet_berries"
],
"minecraft:is_hoe": [
"minecraft:diamond_hoe",
"minecraft:golden_hoe",
"minecraft:iron_hoe",
"minecraft:netherite_hoe",
"minecraft:stone_hoe",
"minecraft:wooden_hoe"
],
"minecraft:is_meat": [
"minecraft:beef",
"minecraft:chicken",
"minecraft:cooked_beef",
"minecraft:cooked_chicken",
"minecraft:cooked_mutton",
"minecraft:cooked_porkchop",
"minecraft:cooked_rabbit",
"minecraft:mutton",
"minecraft:porkchop",
"minecraft:rabbit",
"minecraft:rabbit_stew",
"minecraft:rotten_flesh"
],
"minecraft:is_minecart": [
"minecraft:chest_minecart",
"minecraft:command_block_minecart",
"minecraft:hopper_minecart",
"minecraft:minecart",
"minecraft:tnt_minecart"
],
"minecraft:is_pickaxe": [
"minecraft:diamond_pickaxe",
"minecraft:golden_pickaxe",
"minecraft:iron_pickaxe",
"minecraft:netherite_pickaxe",
"minecraft:stone_pickaxe",
"minecraft:wooden_pickaxe"
],
"minecraft:is_shears": [
"minecraft:shears"
],
"minecraft:is_shovel": [
"minecraft:diamond_shovel",
"minecraft:golden_shovel",
"minecraft:iron_shovel",
"minecraft:netherite_shovel",
"minecraft:stone_shovel",
"minecraft:wooden_shovel"
],
"minecraft:is_sword": [
"minecraft:diamond_sword",
"minecraft:golden_sword",
"minecraft:iron_sword",
"minecraft:mace",
"minecraft:netherite_sword",
"minecraft:stone_sword",
"minecraft:wooden_sword"
],
"minecraft:is_tool": [
"minecraft:diamond_axe",
"minecraft:diamond_hoe",
"minecraft:diamond_pickaxe",
"minecraft:diamond_shovel",
"minecraft:diamond_sword",
"minecraft:golden_axe",
"minecraft:golden_hoe",
"minecraft:golden_pickaxe",
"minecraft:golden_shovel",
"minecraft:golden_sword",
"minecraft:iron_axe",
"minecraft:iron_hoe",
"minecraft:iron_pickaxe",
"minecraft:iron_shovel",
"minecraft:iron_sword",
"minecraft:mace",
"minecraft:netherite_axe",
"minecraft:netherite_hoe",
"minecraft:netherite_pickaxe",
"minecraft:netherite_shovel",
"minecraft:netherite_sword",
"minecraft:stone_axe",
"minecraft:stone_hoe",
"minecraft:stone_pickaxe",
"minecraft:stone_shovel",
"minecraft:stone_sword",
"minecraft:wooden_axe",
"minecraft:wooden_hoe",
"minecraft:wooden_pickaxe",
"minecraft:wooden_shovel",
"minecraft:wooden_sword"
],
"minecraft:is_trident": [
"minecraft:trident"
],
"minecraft:leather_tier": [
"minecraft:leather_boots",
"minecraft:leather_chestplate",
"minecraft:leather_helmet",
"minecraft:leather_leggings"
],
"minecraft:lectern_books": [
"minecraft:writable_book",
"minecraft:written_book"
],
"minecraft:logs": [
"minecraft:acacia_log",
"minecraft:acacia_wood",
"minecraft:birch_log",
"minecraft:birch_wood",
"minecraft:cherry_log",
"minecraft:cherry_wood",
"minecraft:crimson_hyphae",
"minecraft:crimson_stem",
"minecraft:dark_oak_log",
"minecraft:dark_oak_wood",
"minecraft:jungle_log",
"minecraft:jungle_wood",
"minecraft:mangrove_log",
"minecraft:mangrove_wood",
"minecraft:oak_log",
"minecraft:oak_wood",
"minecraft:pale_oak_log",
"minecraft:pale_oak_wood",
"minecraft:spruce_log",
"minecraft:spruce_wood",
"minecraft:stripped_acacia_log",
"minecraft:stripped_acacia_wood",
"minecraft:stripped_birch_log",
"minecraft:stripped_birch_wood",
"minecraft:stripped_cherry_log",
"minecraft:stripped_cherry_wood",
"minecraft:stripped_crimson_hyphae",
"minecraft:stripped_crimson_stem",
"minecraft:stripped_dark_oak_log",
"minecraft:stripped_dark_oak_wood",
"minecraft:stripped_jungle_log",
"minecraft:stripped_jungle_wood",
"minecraft:stripped_mangrove_log",
"minecraft:stripped_mangrove_wood",
"minecraft:stripped_oak_log",
"minecraft:stripped_oak_wood",
"minecraft:stripped_pale_oak_log",
"minecraft:stripped_pale_oak_wood",
"minecraft:stripped_spruce_log",
"minecraft:stripped_spruce_wood",
"minecraft:stripped_warped_hyphae",
"minecraft:stripped_warped_stem",
"minecraft:warped_hyphae",
"minecraft:warped_stem"
],
"minecraft:logs_that_burn": [
"minecraft:acacia_log",
"minecraft:acacia_wood",
"minecraft:birch_log",
"minecraft:birch_wood",
"minecraft:cherry_log",
"minecraft:cherry_wood",
"minecraft:dark_oak_log",
"minecraft:dark_oak_wood",
"minecraft:jungle_log",
"minecraft:jungle_wood",
"minecraft:mangrove_log",
"minecraft:mangrove_wood",
"minecraft:oak_log",
"minecraft:oak_wood",
"minecraft:pale_oak_log",
"minecraft:pale_oak_wood",
"minecraft:spruce_log",
"minecraft:spruce_wood",
"minecraft:stripped_acacia_log",
"minecraft:stripped_acacia_wood",
"minecraft:stripped_birch_log",
"minecraft:stripped_birch_wood",
"minecraft:stripped_cherry_log",
"minecraft:stripped_cherry_wood",
"minecraft:stripped_dark_oak_log",
"minecraft:stripped_dark_oak_wood",
"minecraft:stripped_jungle_log",
"minecraft:stripped_jungle_wood",
"minecraft:stripped_mangrove_log",
"minecraft:stripped_mangrove_wood",
"minecraft:stripped_oak_log",
"minecraft:stripped_oak_wood",
"minecraft:stripped_pale_oak_log",
"minecraft:stripped_pale_oak_wood",
"minecraft:stripped_spruce_log",
"minecraft:stripped_spruce_wood"
],
"minecraft:mangrove_logs": [
"minecraft:mangrove_log",
"minecraft:mangrove_wood",
"minecraft:stripped_mangrove_log",
"minecraft:stripped_mangrove_wood"
],
"minecraft:music_disc": [
"minecraft:music_disc_11",
"minecraft:music_disc_13",
"minecraft:music_disc_5",
"minecraft:music_disc_blocks",
"minecraft:music_disc_cat",
"minecraft:music_disc_chirp",
"minecraft:music_disc_creator",
"minecraft:music_disc_creator_music_box",
"minecraft:music_disc_far",
"minecraft:music_disc_mall",
"minecraft:music_disc_mellohi",
"minecraft:music_disc_otherside",
"minecraft:music_disc_pigstep",
"minecraft:music_disc_precipice",
"minecraft:music_disc_relic",
"minecraft:music_disc_stal",
"minecraft:music_disc_strad",
"minecraft:music_disc_wait",
"minecraft:music_disc_ward"
],
"minecraft:netherite_tier": [
"minecraft:netherite_axe",
"minecraft:netherite_boots",
"minecraft:netherite_chestplate",
"minecraft:netherite_helmet",
"minecraft:netherite_hoe",
"minecraft:netherite_leggings",
"minecraft:netherite_pickaxe",
"minecraft:netherite_shovel",
"minecraft:netherite_sword"
],
"minecraft:planks": [
"minecraft:acacia_planks",
"minecraft:bamboo_planks",
"minecraft:birch_planks",
"minecraft:cherry_planks",
"minecraft:crimson_planks",
"minecraft:dark_oak_planks",
"minecraft:jungle_planks",
"minecraft:mangrove_planks",
"minecraft:oak_planks",
"minecraft:pale_oak_planks",
"minecraft:spruce_planks",
"minecraft:warped_planks"
],
"minecraft:sand": [
"minecraft:red_sand",
"minecraft:sand"
],
"minecraft:sign": [
"minecraft:acacia_hanging_sign",
"minecraft:acacia_sign",
"minecraft:bamboo_hanging_sign",
"minecraft:bamboo_sign",
"minecraft:birch_hanging_sign",
"minecraft:birch_sign",
"minecraft:cherry_hanging_sign",
"minecraft:cherry_sign",
"minecraft:crimson_hanging_sign",
"minecraft:crimson_sign",
"minecraft:dark_oak_hanging_sign",
"minecraft:dark_oak_sign",
"minecraft:jungle_hanging_sign",
"minecraft:jungle_sign",
"minecraft:mangrove_hanging_sign",
"minecraft:mangrove_sign",
"minecraft:oak_hanging_sign",
"minecraft:oak_sign",
"minecraft:pale_oak_hanging_sign",
"minecraft:pale_oak_sign",
"minecraft:spruce_hanging_sign",
"minecraft:spruce_sign",
"minecraft:warped_hanging_sign",
"minecraft:warped_sign"
],
"minecraft:soul_fire_base_blocks": [
"minecraft:soul_sand",
"minecraft:soul_soil"
],
"minecraft:spawn_egg": [
"minecraft:agent_spawn_egg",
"minecraft:allay_spawn_egg",
"minecraft:armadillo_spawn_egg",
"minecraft:axolotl_spawn_egg",
"minecraft:bat_spawn_egg",
"minecraft:bee_spawn_egg",
"minecraft:blaze_spawn_egg",
"minecraft:bogged_spawn_egg",
"minecraft:breeze_spawn_egg",
"minecraft:camel_spawn_egg",
"minecraft:cat_spawn_egg",
"minecraft:cave_spider_spawn_egg",
"minecraft:chicken_spawn_egg",
"minecraft:cod_spawn_egg",
"minecraft:cow_spawn_egg",
"minecraft:creaking_spawn_egg",
"minecraft:creeper_spawn_egg",
"minecraft:dolphin_spawn_egg",
"minecraft:donkey_spawn_egg",
"minecraft:drowned_spawn_egg",
"minecraft:elder_guardian_spawn_egg",
"minecraft:ender_dragon_spawn_egg",
"minecraft:enderman_spawn_egg",
"minecraft:endermite_spawn_egg",
"minecraft:evoker_spawn_egg",
"minecraft:fox_spawn_egg",
"minecraft:frog_spawn_egg",
"minecraft:ghast_spawn_egg",
"minecraft:glow_squid_spawn_egg",
"minecraft:goat_spawn_egg",
"minecraft:guardian_spawn_egg",
"minecraft:hoglin_spawn_egg",
"minecraft:horse_spawn_egg",
"minecraft:husk_spawn_egg",
"minecraft:iron_golem_spawn_egg",
"minecraft:llama_spawn_egg",
"minecraft:magma_cube_spawn_egg",
"minecraft:mooshroom_spawn_egg",
"minecraft:mule_spawn_egg",
"minecraft:npc_spawn_egg",
"minecraft:ocelot_spawn_egg",
"minecraft:panda_spawn_egg",
"minecraft:parrot_spawn_egg",
"minecraft:phantom_spawn_egg",
"minecraft:pig_spawn_egg",
"minecraft:piglin_brute_spawn_egg",
"minecraft:piglin_spawn_egg",
"minecraft:pillager_spawn_egg",
"minecraft:polar_bear_spawn_egg",
"minecraft:pufferfish_spawn_egg",
"minecraft:rabbit_spawn_egg",
"minecraft:ravager_spawn_egg",
"minecraft:salmon_spawn_egg",
"minecraft:sheep_spawn_egg",
"minecraft:shulker_spawn_egg",
"minecraft:silverfish_spawn_egg",
"minecraft:skeleton_horse_spawn_egg",
"minecraft:skeleton_spawn_egg",
"minecraft:slime_spawn_egg",
"minecraft:sniffer_spawn_egg",
"minecraft:snow_golem_spawn_egg",
"minecraft:spawn_egg",
"minecraft:spider_spawn_egg",
"minecraft:squid_spawn_egg",
"minecraft:stray_spawn_egg",
"minecraft:strider_spawn_egg",
"minecraft:tadpole_spawn_egg",
"minecraft:trader_llama_spawn_egg",
"minecraft:tropical_fish_spawn_egg",
"minecraft:turtle_spawn_egg",
"minecraft:vex_spawn_egg",
"minecraft:villager_spawn_egg",
"minecraft:vindicator_spawn_egg",
"minecraft:wandering_trader_spawn_egg",
"minecraft:warden_spawn_egg",
"minecraft:witch_spawn_egg",
"minecraft:wither_skeleton_spawn_egg",
"minecraft:wither_spawn_egg",
"minecraft:wolf_spawn_egg",
"minecraft:zoglin_spawn_egg",
"minecraft:zombie_horse_spawn_egg",
"minecraft:zombie_pigman_spawn_egg",
"minecraft:zombie_spawn_egg",
"minecraft:zombie_villager_spawn_egg"
],
"minecraft:stone_bricks": [
"minecraft:chiseled_stone_bricks",
"minecraft:cracked_stone_bricks",
"minecraft:mossy_stone_bricks",
"minecraft:stone_bricks"
],
"minecraft:stone_crafting_materials": [
"minecraft:blackstone",
"minecraft:cobbled_deepslate",
"minecraft:cobblestone"
],
"minecraft:stone_tier": [
"minecraft:stone_axe",
"minecraft:stone_hoe",
"minecraft:stone_pickaxe",
"minecraft:stone_shovel",
"minecraft:stone_sword"
],
"minecraft:stone_tool_materials": [
"minecraft:blackstone",
"minecraft:cobbled_deepslate",
"minecraft:cobblestone"
],
"minecraft:transform_materials": [
"minecraft:netherite_ingot"
],
"minecraft:transform_templates": [
"minecraft:netherite_upgrade_smithing_template"
],
"minecraft:transformable_items": [
"minecraft:diamond_axe",
"minecraft:diamond_boots",
"minecraft:diamond_chestplate",
"minecraft:diamond_helmet",
"minecraft:diamond_hoe",
"minecraft:diamond_leggings",
"minecraft:diamond_pickaxe",
"minecraft:diamond_shovel",
"minecraft:diamond_sword",
"minecraft:golden_boots"
],
"minecraft:trim_materials": [
"minecraft:amethyst_shard",
"minecraft:copper_ingot",
"minecraft:diamond",
"minecraft:emerald",
"minecraft:gold_ingot",
"minecraft:iron_ingot",
"minecraft:lapis_lazuli",
"minecraft:netherite_ingot",
"minecraft:quartz",
"minecraft:redstone",
"minecraft:resin_brick"
],
"minecraft:trim_templates": [
"minecraft:bolt_armor_trim_smithing_template",
"minecraft:coast_armor_trim_smithing_template",
"minecraft:dune_armor_trim_smithing_template",
"minecraft:eye_armor_trim_smithing_template",
"minecraft:flow_armor_trim_smithing_template",
"minecraft:host_armor_trim_smithing_template",
"minecraft:raiser_armor_trim_smithing_template",
"minecraft:rib_armor_trim_smithing_template",
"minecraft:sentry_armor_trim_smithing_template",
"minecraft:shaper_armor_trim_smithing_template",
"minecraft:silence_armor_trim_smithing_template",
"minecraft:snout_armor_trim_smithing_template",
"minecraft:spire_armor_trim_smithing_template",
"minecraft:tide_armor_trim_smithing_template",
"minecraft:vex_armor_trim_smithing_template",
"minecraft:ward_armor_trim_smithing_template",
"minecraft:wayfinder_armor_trim_smithing_template",
"minecraft:wild_armor_trim_smithing_template"
],
"minecraft:trimmable_armors": [
"minecraft:chainmail_boots",
"minecraft:chainmail_chestplate",
"minecraft:chainmail_helmet",
"minecraft:chainmail_leggings",
"minecraft:diamond_boots",
"minecraft:diamond_chestplate",
"minecraft:diamond_helmet",
"minecraft:diamond_leggings",
"minecraft:golden_boots",
"minecraft:golden_chestplate",
"minecraft:golden_helmet",
"minecraft:golden_leggings",
"minecraft:iron_boots",
"minecraft:iron_chestplate",
"minecraft:iron_helmet",
"minecraft:iron_leggings",
"minecraft:leather_boots",
"minecraft:leather_chestplate",
"minecraft:leather_helmet",
"minecraft:leather_leggings",
"minecraft:netherite_boots",
"minecraft:netherite_chestplate",
"minecraft:netherite_helmet",
"minecraft:netherite_leggings",
"minecraft:turtle_helmet"
],
"minecraft:vibration_damper": [
"minecraft:black_carpet",
"minecraft:black_wool",
"minecraft:blue_carpet",
"minecraft:blue_wool",
"minecraft:brown_carpet",
"minecraft:brown_wool",
"minecraft:cyan_carpet",
"minecraft:cyan_wool",
"minecraft:gray_carpet",
"minecraft:gray_wool",
"minecraft:green_carpet",
"minecraft:green_wool",
"minecraft:light_blue_carpet",
"minecraft:light_blue_wool",
"minecraft:light_gray_carpet",
"minecraft:light_gray_wool",
"minecraft:lime_carpet",
"minecraft:lime_wool",
"minecraft:magenta_carpet",
"minecraft:magenta_wool",
"minecraft:orange_carpet",
"minecraft:orange_wool",
"minecraft:pink_carpet",
"minecraft:pink_wool",
"minecraft:purple_carpet",
"minecraft:purple_wool",
"minecraft:red_carpet",
"minecraft:red_wool",
"minecraft:white_carpet",
"minecraft:white_wool",
"minecraft:yellow_carpet",
"minecraft:yellow_wool"
],
"minecraft:warped_stems": [
"minecraft:stripped_warped_hyphae",
"minecraft:stripped_warped_stem",
"minecraft:warped_hyphae",
"minecraft:warped_stem"
],
"minecraft:wooden_slabs": [
"minecraft:acacia_slab",
"minecraft:bamboo_slab",
"minecraft:birch_slab",
"minecraft:cherry_slab",
"minecraft:crimson_slab",
"minecraft:dark_oak_slab",
"minecraft:jungle_slab",
"minecraft:mangrove_slab",
"minecraft:oak_slab",
"minecraft:pale_oak_slab",
"minecraft:spruce_slab",
"minecraft:warped_slab"
],
"minecraft:wooden_tier": [
"minecraft:wooden_axe",
"minecraft:wooden_hoe",
"minecraft:wooden_pickaxe",
"minecraft:wooden_shovel",
"minecraft:wooden_sword"
],
"minecraft:wool": [
"minecraft:black_wool",
"minecraft:blue_wool",
"minecraft:brown_wool",
"minecraft:cyan_wool",
"minecraft:gray_wool",
"minecraft:green_wool",
"minecraft:light_blue_wool",
"minecraft:light_gray_wool",
"minecraft:lime_wool",
"minecraft:magenta_wool",
"minecraft:orange_wool",
"minecraft:pink_wool",
"minecraft:purple_wool",
"minecraft:red_wool",
"minecraft:white_wool",
"minecraft:yellow_wool"
]
}
Binary file not shown.
+163
View File
@@ -0,0 +1,163 @@
package recipe
import (
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
)
// Recipe is implemented by all recipe types.
type Recipe interface {
// Input returns the items required to craft the recipe.
Input() []Item
// Output returns the items that are produced when the recipe is crafted.
Output() []item.Stack
// Block returns the block that is used to craft the recipe.
Block() string
// Priority returns the priority of the recipe. Recipes with lower priority are preferred compared to recipes with
// higher priority.
Priority() uint32
}
// DynamicRecipe represents a recipe whose output depends on the specific items used in crafting.
// These recipes are not sent to the client and are validated server-side.
type DynamicRecipe interface {
// Match checks if the given input items match this dynamic recipe pattern.
// It returns true if the pattern matches, along with the computed output items.
Match(input []Item) (output []item.Stack, ok bool)
// Block returns the block that is used to craft the recipe.
Block() string
}
// Shapeless is a recipe that has no particular shape.
type Shapeless struct {
recipe
}
// NewShapeless creates a new shapeless recipe and returns it. The recipe can only be crafted on the block passed in the
// parameters. If the block given a crafting table, the recipe can also be crafted in the 2x2 crafting grid in the
// player's inventory.
func NewShapeless(input []Item, output item.Stack, block string) Shapeless {
return Shapeless{recipe: recipe{
input: input,
output: []item.Stack{output},
block: block,
}}
}
// SmithingTransform represents a recipe only craftable on a smithing table.
type SmithingTransform struct {
recipe
}
// NewSmithingTransform creates a new smithing recipe and returns it.
func NewSmithingTransform(base, addition, template Item, output item.Stack, block string) SmithingTransform {
return SmithingTransform{recipe: recipe{
input: []Item{base, addition, template},
output: []item.Stack{output},
block: block,
}}
}
// SmithingTrim represents a recipe only craftable on a smithing table using an armour trim.
type SmithingTrim struct {
recipe
}
// NewSmithingTrim creates a new smithing trim recipe and returns it. This is
// almost identical to SmithingTransform except there is no output item.
func NewSmithingTrim(base, addition, template Item, block string) SmithingTrim {
return SmithingTrim{recipe: recipe{
input: []Item{base, addition, template},
block: block,
}}
}
// PotionContainerChange is a recipe to convert a potion from one type to another, such as from a drinkable potion to a
// splash potion, or from a splash potion to a lingering potion.
type PotionContainerChange struct {
recipe
}
// NewPotionContainerChange creates a new potion container change recipe and returns it.
func NewPotionContainerChange(input, output world.Item, reagent item.Stack) PotionContainerChange {
return PotionContainerChange{recipe: recipe{
input: []Item{item.NewStack(input, 1), reagent},
output: []item.Stack{item.NewStack(output, 1)},
block: "brewing_stand",
}}
}
// Potion is a potion mixing recipe which may be used in the brewing stand.
type Potion struct {
recipe
}
// NewPotion creates a new potion recipe and returns it.
func NewPotion(input, reagent Item, output item.Stack) Potion {
return Potion{recipe: recipe{
input: []Item{input, reagent},
output: []item.Stack{output},
block: "brewing_stand",
}}
}
// Shaped is a recipe that has a specific shape that must be used to craft the output of the recipe.
type Shaped struct {
recipe
// shape contains the width and height of the shaped recipe.
shape Shape
}
// NewShaped creates a new shaped recipe and returns it. The recipe can only be crafted on the block passed in the
// parameters. If the block given a crafting table, the recipe can also be crafted in the 2x2 crafting grid in the
// player's inventory. If nil is passed, the block will be autofilled as a crafting table. The inputs must always match
// the width*height of the shape.
func NewShaped(input []Item, output item.Stack, shape Shape, block string) Shaped {
return Shaped{
shape: shape,
recipe: recipe{
input: input,
output: []item.Stack{output},
block: block,
},
}
}
// Shape returns the shape of the recipe.
func (r Shaped) Shape() Shape {
return r.shape
}
// recipe implements the Recipe interface. Structs in this package may embed it to gets its functionality
// out of the box.
type recipe struct {
// input is a list of items that serve as the input of the shaped recipe. These items are the items
// required to craft the output. The amount of input items must be exactly equal to Width * Height.
input []Item
// output contains items that are created as a result of crafting the recipe.
output []item.Stack
// block is the block that is used to craft the recipe.
block string
// priority is the priority of the recipe versus others.
priority uint32
}
// Input ...
func (r recipe) Input() []Item {
return r.input
}
// Output ...
func (r recipe) Output() []item.Stack {
return r.output
}
// Block ...
func (r recipe) Block() string {
return r.block
}
// Priority ...
func (r recipe) Priority() uint32 {
return r.priority
}
+130
View File
@@ -0,0 +1,130 @@
package recipe
import (
"github.com/df-mc/dragonfly/server/internal/sliceutil"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"slices"
"sort"
"strings"
"unsafe"
)
// recipes is a list of each recipe.
var (
recipes []Recipe
// dynamicRecipes is a list of each dynamic recipe.
dynamicRecipes []DynamicRecipe
// index maps an input hash to output stacks for each PotionContainerChange and Potion recipe.
index = make(map[string]map[string]Recipe)
// reagent maps the item name and an item.Stack.
reagent = make(map[string]item.Stack)
)
// Recipes returns each recipe in a slice.
func Recipes() []Recipe {
return slices.Clone(recipes)
}
// DynamicRecipes returns each dynamic recipe in a slice.
func DynamicRecipes() []DynamicRecipe {
return slices.Clone(dynamicRecipes)
}
// Register registers a new recipe.
func Register(recipe Recipe) {
recipes = append(recipes, recipe)
_, ok := recipe.(PotionContainerChange)
p, okTwo := recipe.(Potion)
if okTwo {
stack := p.Input()[1].(item.Stack)
name, _ := stack.Item().EncodeItem()
reagent[name] = stack
}
if ok || okTwo {
input := make([]world.Item, len(recipe.Input()))
for i, stack := range recipe.Input() {
if s, ok := stack.(item.Stack); ok {
input[i] = s.Item()
}
}
hash := hashItems(input, !ok)
block := recipe.Block()
if index[block] == nil {
index[block] = make(map[string]Recipe)
}
index[block][hash] = recipe
}
}
// Perform performs the recipe with the given block and inputs and returns the outputs. If the inputs do not map to
// any outputs, false is returned for the second return value.
func Perform(block string, input ...world.Item) (output []item.Stack, ok bool) {
blockInd, ok := index[block]
if !ok {
// Block specific index didn't exist.
return nil, false
}
r, ok := blockInd[hashItems(input, true)]
if !ok {
r, ok = blockInd[hashItems(input, false)]
if !ok {
return nil, false
}
}
_, containerChange := r.(PotionContainerChange)
for ind, it := range r.Output() {
if containerChange {
name, _ := it.Item().EncodeItem()
_, meta := input[ind].EncodeItem()
if i, ok := world.ItemByName(name, meta); ok {
it = item.NewStack(i, it.Count())
}
}
output = append(output, it)
}
return output, ok
}
// hashItems hashes the given list of item types and returns it.
func hashItems(items []world.Item, useMeta bool) string {
items = sliceutil.Filter(items, func(it world.Item) bool {
return it != nil
})
sort.Slice(items, func(i, j int) bool {
nameOne, metaOne := items[i].EncodeItem()
nameTwo, metaTwo := items[j].EncodeItem()
if nameOne == nameTwo {
return metaOne < metaTwo
}
return nameOne < nameTwo
})
var b strings.Builder
for _, it := range items {
name, meta := it.EncodeItem()
b.WriteString(name)
if useMeta {
a := *(*[2]byte)(unsafe.Pointer(&meta))
b.Write(a[:])
}
}
return b.String()
}
// ValidBrewingReagent checks if the world.Item is a brewing reagent.
func ValidBrewingReagent(i world.Item) bool {
name, _ := i.EncodeItem()
_, exists := reagent[name]
return exists
}
// RegisterDynamic registers a new dynamic recipe. Dynamic recipes are not sent to the client
// and are validated server-side.
func RegisterDynamic(recipe DynamicRecipe) {
dynamicRecipes = append(dynamicRecipes, recipe)
}
+19
View File
@@ -0,0 +1,19 @@
package recipe
// Shape make up the shape of a shaped recipe. It consists of a width and a height.
type Shape [2]int
// Width returns the width of the shape.
func (s Shape) Width() int {
return s[0]
}
// Height returns the height of the shape.
func (s Shape) Height() int {
return s[1]
}
// NewShape creates a new shape using the provided width and height.
func NewShape(width, height int) Shape {
return Shape{width, height}
}
Binary file not shown.
Binary file not shown.
+181
View File
@@ -0,0 +1,181 @@
package recipe
import (
_ "embed"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/sandertv/gophertunnel/minecraft/nbt"
)
var (
//go:embed crafting_data.nbt
vanillaCraftingData []byte
//go:embed smithing_data.nbt
vanillaSmithingData []byte
//go:embed smithing_trim_data.nbt
vanillaSmithingTrimData []byte
//go:embed potion_data.nbt
vanillaPotionData []byte
)
// shapedRecipe is a recipe that must be crafted in a specific shape.
type shapedRecipe struct {
Input inputItems `nbt:"input"`
Output outputItems `nbt:"output"`
Block string `nbt:"block"`
Width int32 `nbt:"width"`
Height int32 `nbt:"height"`
Priority int32 `nbt:"priority"`
}
// shapelessRecipe is a recipe that may be crafted without a strict shape.
type shapelessRecipe struct {
Input inputItems `nbt:"input"`
Output outputItems `nbt:"output"`
Block string `nbt:"block"`
Priority int32 `nbt:"priority"`
}
// potionRecipe is a recipe that may be crafted in a brewing stand.
type potionRecipe struct {
Input inputItem `nbt:"input"`
Reagent inputItem `nbt:"reagent"`
Output outputItem `nbt:"output"`
}
// potionContainerChangeRecipe is a recipe that may be crafted in a brewing stand.
type potionContainerChangeRecipe struct {
Input string `nbt:"input"`
Reagent inputItem `nbt:"reagent"`
Output string `nbt:"output"`
}
// registerVanilla can be called to register all vanilla recipes from the generated data files.
// noinspection GoUnusedFunction
//
//lint:ignore U1000 Function is used through compiler directives.
func registerVanilla() {
var craftingRecipes struct {
Shaped []shapedRecipe `nbt:"shaped"`
Shapeless []shapelessRecipe `nbt:"shapeless"`
}
if err := nbt.Unmarshal(vanillaCraftingData, &craftingRecipes); err != nil {
panic(err)
}
for _, s := range craftingRecipes.Shapeless {
input, ok := s.Input.Items()
output, okTwo := s.Output.Stacks()
if !ok || !okTwo {
// This can be expected to happen, as some recipes contain blocks or items that aren't currently implemented.
continue
}
Register(Shapeless{recipe{
input: input,
output: output,
block: s.Block,
priority: uint32(s.Priority),
}})
}
for _, s := range craftingRecipes.Shaped {
input, ok := s.Input.Items()
output, okTwo := s.Output.Stacks()
if !ok || !okTwo {
// This can be expected to happen - refer to the comment above.
continue
}
Register(Shaped{
shape: Shape{int(s.Width), int(s.Height)},
recipe: recipe{
input: input,
output: output,
block: s.Block,
priority: uint32(s.Priority),
},
})
}
var smithingRecipes []shapelessRecipe
if err := nbt.Unmarshal(vanillaSmithingData, &smithingRecipes); err != nil {
panic(err)
}
for _, s := range smithingRecipes {
input, ok := s.Input.Items()
output, okTwo := s.Output.Stacks()
if !ok || !okTwo {
// This can be expected to happen - refer to the comment above.
continue
}
Register(SmithingTransform{recipe{
input: input,
output: output,
block: s.Block,
priority: uint32(s.Priority),
}})
}
var smithingTrimRecipes []shapelessRecipe
if err := nbt.Unmarshal(vanillaSmithingTrimData, &smithingTrimRecipes); err != nil {
panic(err)
}
for _, s := range smithingTrimRecipes {
input, ok := s.Input.Items()
if !ok {
// This can be expected to happen - refer to the comment above.
continue
}
Register(SmithingTrim{recipe{
input: input,
block: s.Block,
priority: uint32(s.Priority),
}})
}
var potionRecipes struct {
Potions []potionRecipe `nbt:"potions"`
ContainerChanges []potionContainerChangeRecipe `nbt:"container_changes"`
}
if err := nbt.Unmarshal(vanillaPotionData, &potionRecipes); err != nil {
panic(err)
}
for _, r := range potionRecipes.Potions {
input, ok := r.Input.Item()
reagent, okTwo := r.Reagent.Item()
output, okThree := r.Output.Stack()
if !ok || !okTwo || !okThree {
// This can be expected to happen - refer to the comment above.
continue
}
Register(Potion{recipe{
input: []Item{input, reagent},
output: []item.Stack{output},
block: "brewing_stand",
}})
}
for _, c := range potionRecipes.ContainerChanges {
input, ok := world.ItemByName(c.Input, 0)
reagent, okTwo := c.Reagent.Item()
output, okThree := world.ItemByName(c.Output, 0)
if !ok || !okTwo || !okThree {
// This can be expected to happen - refer to the comment above.
continue
}
Register(PotionContainerChange{recipe{
input: []Item{item.NewStack(input, 1), reagent},
output: []item.Stack{item.NewStack(output, 1)},
block: "brewing_stand",
}})
}
// Register dynamic recipes
RegisterDynamic(NewDecoratedPotRecipe())
}