Files

182 lines
4.7 KiB
Go
Raw Permalink Normal View History

2026-07-09 08:33:57 +08:00
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())
}