182 lines
4.7 KiB
Go
182 lines
4.7 KiB
Go
|
|
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())
|
||
|
|
}
|