Files
legacy-version/legacyver/proto/recipe.go
2025-01-01 21:42:55 +07:00

700 lines
23 KiB
Go

package proto
import (
"github.com/google/uuid"
"github.com/sandertv/gophertunnel/minecraft/protocol"
)
const (
RecipeUnlockContextNone = iota
RecipeUnlockContextAlwaysUnlocked
RecipeUnlockContextPlayerInWater
RecipeUnlockContextPlayerHasManyItems
)
// RecipeUnlockRequirement represents a requirement that must be met in order to unlock a recipe. This is used
// for both shaped and shapeless recipes.
type RecipeUnlockRequirement struct {
// Context is the context in which the recipe is unlocked. This is one of the constants above.
Context byte
// Ingredients are the ingredients required to unlock the recipe and only used if Context is set to none.
Ingredients []protocol.ItemDescriptorCount
}
func (x *RecipeUnlockRequirement) FromLatest(requirement protocol.RecipeUnlockRequirement) RecipeUnlockRequirement {
x.Context = requirement.Context
x.Ingredients = requirement.Ingredients
return *x
}
func (x *RecipeUnlockRequirement) ToLatest() protocol.RecipeUnlockRequirement {
return protocol.RecipeUnlockRequirement{
Context: x.Context,
Ingredients: x.Ingredients,
}
}
// Marshal ...
func (x *RecipeUnlockRequirement) Marshal(r protocol.IO) {
r.Uint8(&x.Context)
if x.Context == RecipeUnlockContextNone {
protocol.FuncSlice(r, &x.Ingredients, r.ItemDescriptorCount)
}
}
const (
RecipeShapeless int32 = iota
RecipeShaped
RecipeFurnace
RecipeFurnaceData
RecipeMulti
RecipeShulkerBox
RecipeShapelessChemistry
RecipeShapedChemistry
RecipeSmithingTransform
RecipeSmithingTrim
)
// Recipe represents a recipe that may be sent in a CraftingData packet to let the client know what recipes
// are available server-side.
type Recipe interface {
// Marshal encodes the recipe data to its binary representation into buf.
Marshal(w *Writer)
// Unmarshal decodes a serialised recipe from Reader r into the recipe instance.
Unmarshal(r *Reader)
}
func takePtr[T any](x T) *T {
return &x
}
func RecipeToLatest(x Recipe) protocol.Recipe {
switch x := x.(type) {
case *ShapelessRecipe:
return takePtr(x.ToLatest())
case *ShulkerBoxRecipe:
return takePtr(x.ToLatest())
case *ShapelessChemistryRecipe:
return takePtr(x.ToLatest())
case *ShapedRecipe:
return takePtr(x.ToLatest())
case *ShapedChemistryRecipe:
return takePtr(x.ToLatest())
case *FurnaceRecipe:
return takePtr(x.ToLatest())
case *FurnaceDataRecipe:
return takePtr(x.ToLatest())
case *MultiRecipe:
return takePtr(x.ToLatest())
case *SmithingTransformRecipe:
return takePtr(x.ToLatest())
case *SmithingTrimRecipe:
return takePtr(x.ToLatest())
}
panic("RecipeToLatest: unknown recipe type")
}
func RecipeFromLatest(x protocol.Recipe) Recipe {
switch x := x.(type) {
case *protocol.ShapelessRecipe:
return (&ShapelessRecipe{}).FromLatest(*x)
case *protocol.ShulkerBoxRecipe:
return (&ShulkerBoxRecipe{}).FromLatest(*x)
case *protocol.ShapelessChemistryRecipe:
return (&ShapelessChemistryRecipe{}).FromLatest(*x)
case *protocol.ShapedRecipe:
return (&ShapedRecipe{}).FromLatest(*x)
case *protocol.ShapedChemistryRecipe:
return (&ShapedChemistryRecipe{}).FromLatest(*x)
case *protocol.FurnaceRecipe:
return (&FurnaceRecipe{}).FromLatest(*x)
case *protocol.FurnaceDataRecipe:
return (&FurnaceDataRecipe{}).FromLatest(*x)
case *protocol.MultiRecipe:
return (&MultiRecipe{}).FromLatest(*x)
case *protocol.SmithingTransformRecipe:
return (&SmithingTransformRecipe{}).FromLatest(*x)
case *protocol.SmithingTrimRecipe:
return (&SmithingTrimRecipe{}).FromLatest(*x)
}
panic("RecipeFromLatest: unknown recipe type")
}
// lookupRecipe looks up the Recipe for a recipe type. False is returned if not
// found.
func lookupRecipe(recipeType int32, x *Recipe) bool {
switch recipeType {
case RecipeShapeless:
*x = &ShapelessRecipe{}
case RecipeShaped:
*x = &ShapedRecipe{}
case RecipeFurnace:
*x = &FurnaceRecipe{}
case RecipeFurnaceData:
*x = &FurnaceDataRecipe{}
case RecipeMulti:
*x = &MultiRecipe{}
case RecipeShulkerBox:
*x = &ShulkerBoxRecipe{}
case RecipeShapelessChemistry:
*x = &ShapelessChemistryRecipe{}
case RecipeShapedChemistry:
*x = &ShapedChemistryRecipe{}
case RecipeSmithingTransform:
*x = &SmithingTransformRecipe{}
case RecipeSmithingTrim:
*x = &SmithingTrimRecipe{}
default:
return false
}
return true
}
// lookupRecipeType looks up the recipe type for a Recipe. False is returned if
// none was found.
func lookupRecipeType(x Recipe, recipeType *int32) bool {
switch x.(type) {
case *ShapelessRecipe:
*recipeType = RecipeShapeless
case *ShapedRecipe:
*recipeType = RecipeShaped
case *FurnaceRecipe:
*recipeType = RecipeFurnace
case *FurnaceDataRecipe:
*recipeType = RecipeFurnaceData
case *MultiRecipe:
*recipeType = RecipeMulti
case *ShulkerBoxRecipe:
*recipeType = RecipeShulkerBox
case *ShapelessChemistryRecipe:
*recipeType = RecipeShapelessChemistry
case *ShapedChemistryRecipe:
*recipeType = RecipeShapedChemistry
case *SmithingTransformRecipe:
*recipeType = RecipeSmithingTransform
case *SmithingTrimRecipe:
*recipeType = RecipeSmithingTrim
default:
return false
}
return true
}
// ShapelessRecipe is a recipe that has no particular shape. Its functionality is shared with the
// RecipeShulkerBox and RecipeShapelessChemistry types.
type ShapelessRecipe struct {
// RecipeID is a unique ID of the recipe. This ID must be unique amongst all other types of recipes too,
// but its functionality is not exactly known.
RecipeID string
// Input is a list of items that serve as the input of the shapeless recipe. These items are the items
// required to craft the output.
Input []protocol.ItemDescriptorCount
// Output is a list of items that are created as a result of crafting the recipe.
Output []protocol.ItemStack
// UUID is a UUID identifying the recipe. Since the CraftingEvent packet no longer exists, this can always be empty.
UUID uuid.UUID
// Block is the block name that is required to craft the output of the recipe. The block is not prefixed
// with 'minecraft:', so it will look like 'crafting_table' as an example.
// The available blocks are:
// - crafting_table
// - cartography_table
// - stonecutter
// - furnace
// - blast_furnace
// - smoker
// - campfire
Block string
// Priority ...
Priority int32
// UnlockRequirement is a requirement that must be met in order to unlock the recipe.
UnlockRequirement RecipeUnlockRequirement
// RecipeNetworkID is a unique ID used to identify the recipe over network. Each recipe must have a unique
// network ID. Recommended is to just increment a variable for each unique recipe registered.
// This field must never be 0.
RecipeNetworkID uint32
}
// ShulkerBoxRecipe is a shapeless recipe made specifically for shulker box crafting, so that they don't lose
// their user data when dyeing a shulker box.
type ShulkerBoxRecipe struct {
ShapelessRecipe
}
// ShapelessChemistryRecipe is a recipe specifically made for chemistry related features, which exist only in
// the Education Edition. They function the same as shapeless recipes do.
type ShapelessChemistryRecipe struct {
ShapelessRecipe
}
// ShapedRecipe is a recipe that has a specific shape that must be used to craft the output of the recipe.
// Trying to craft the item in any other shape will not work. The ShapedRecipe is of the same structure as the
// ShapedChemistryRecipe.
type ShapedRecipe struct {
// RecipeID is a unique ID of the recipe. This ID must be unique amongst all other types of recipes too,
// but its functionality is not exactly known.
RecipeID string
// Width is the width of the recipe's shape.
Width int32
// Height is the height of the recipe's shape.
Height int32
// Input is a list of items that serve as the input of the shapeless recipe. These items are the items
// required to craft the output. The amount of input items must be exactly equal to Width * Height.
Input []protocol.ItemDescriptorCount
// Output is a list of items that are created as a result of crafting the recipe.
Output []protocol.ItemStack
// UUID is a UUID identifying the recipe. Since the CraftingEvent packet no longer exists, this can always be empty.
UUID uuid.UUID
// Block is the block name that is required to craft the output of the recipe. The block is not prefixed
// with 'minecraft:', so it will look like 'crafting_table' as an example.
Block string
// Priority ...
Priority int32
// AssumeSymmetry specifies if the recipe is symmetrical. If this is set to true, the recipe will be
// mirrored along the diagonal axis. This means that the recipe will be the same if rotated 180 degrees.
AssumeSymmetry bool
// UnlockRequirement is a requirement that must be met in order to unlock the recipe.
UnlockRequirement RecipeUnlockRequirement
// RecipeNetworkID is a unique ID used to identify the recipe over network. Each recipe must have a unique
// network ID. Recommended is to just increment a variable for each unique recipe registered.
// This field must never be 0.
RecipeNetworkID uint32
}
// ShapedChemistryRecipe is a recipe specifically made for chemistry related features, which exist only in the
// Education Edition. It functions the same as a normal ShapedRecipe.
type ShapedChemistryRecipe struct {
ShapedRecipe
}
// FurnaceRecipe is a recipe that is specifically used for all kinds of furnaces. These recipes don't just
// apply to furnaces, but also blast furnaces and smokers.
type FurnaceRecipe struct {
// InputType is the item type of the input item. The metadata value of the item is not used in the
// FurnaceRecipe. Use FurnaceDataRecipe to allow an item with only one metadata value.
InputType protocol.ItemType
// Output is the item that is created as a result of smelting/cooking an item in the furnace.
Output protocol.ItemStack
// Block is the block name that is required to create the output of the recipe. The block is not prefixed
// with 'minecraft:', so it will look like 'furnace' as an example.
Block string
}
// FurnaceDataRecipe is a recipe specifically used for furnace-type crafting stations. It is equal to
// FurnaceRecipe, except it has an input item with a specific metadata value, instead of any metadata value.
type FurnaceDataRecipe struct {
FurnaceRecipe
}
// MultiRecipe serves as an 'enable' switch for multi-shape recipes.
type MultiRecipe struct {
// UUID is a UUID identifying the recipe. Since the CraftingEvent packet no longer exists, this can always be empty.
UUID uuid.UUID
// RecipeNetworkID is a unique ID used to identify the recipe over network. Each recipe must have a unique
// network ID. Recommended is to just increment a variable for each unique recipe registered.
// This field must never be 0.
RecipeNetworkID uint32
}
// SmithingTransformRecipe is a recipe specifically used for smithing tables. It has three input items and adds them
// together, resulting in a new item.
type SmithingTransformRecipe struct {
// RecipeNetworkID is a unique ID used to identify the recipe over network. Each recipe must have a unique
// network ID. Recommended is to just increment a variable for each unique recipe registered.
// This field must never be 0.
RecipeNetworkID uint32
// RecipeID is a unique ID of the recipe. This ID must be unique amongst all other types of recipes too,
// but its functionality is not exactly known.
RecipeID string
// Template is the item that is used to shape the Base item based on the Addition being applied.
Template protocol.ItemDescriptorCount
// Base is the item that the Addition is being applied to in the smithing table.
Base protocol.ItemDescriptorCount
// Addition is the item that is being added to the Base item to result in a modified item.
Addition protocol.ItemDescriptorCount
// Result is the resulting item from the two items being added together.
Result protocol.ItemStack
// Block is the block name that is required to create the output of the recipe. The block is not prefixed with
// 'minecraft:', so it will look like 'smithing_table' as an example.
Block string
}
// SmithingTrimRecipe is a recipe specifically used for applying armour trims to an armour piece inside a smithing table.
type SmithingTrimRecipe struct {
// RecipeNetworkID is a unique ID used to identify the recipe over network. Each recipe must have a unique
// network ID. Recommended is to just increment a variable for each unique recipe registered.
// This field must never be 0.
RecipeNetworkID uint32
// RecipeID is a unique ID of the recipe. This ID must be unique amongst all other types of recipes too,
// but its functionality is not exactly known.
RecipeID string
// Template is the item that is used to shape the Base item based on the Addition being applied.
Template protocol.ItemDescriptorCount
// Base is the item that the Addition is being applied to in the smithing table.
Base protocol.ItemDescriptorCount
// Addition is the item that is being added to the Base item to result in a modified item.
Addition protocol.ItemDescriptorCount
// Block is the block name that is required to create the output of the recipe. The block is not prefixed with
// 'minecraft:', so it will look like 'smithing_table' as an example.
Block string
}
// FromLatest ...
func (recipe *ShapelessRecipe) FromLatest(v protocol.ShapelessRecipe) *ShapelessRecipe {
recipe.RecipeID = v.RecipeID
recipe.Input = v.Input
recipe.Output = v.Output
recipe.UUID = v.UUID
recipe.Block = v.Block
recipe.Priority = v.Priority
recipe.UnlockRequirement = (&RecipeUnlockRequirement{}).FromLatest(v.UnlockRequirement)
recipe.RecipeNetworkID = v.RecipeNetworkID
return recipe
}
// ToLatest ...
func (recipe *ShapelessRecipe) ToLatest() protocol.ShapelessRecipe {
return protocol.ShapelessRecipe{
RecipeID: recipe.RecipeID,
Input: recipe.Input,
Output: recipe.Output,
UUID: recipe.UUID,
Block: recipe.Block,
Priority: recipe.Priority,
UnlockRequirement: recipe.UnlockRequirement.ToLatest(),
RecipeNetworkID: recipe.RecipeNetworkID,
}
}
// Marshal ...
func (recipe *ShapelessRecipe) Marshal(w *Writer) {
marshalShapeless(w, recipe)
}
// Unmarshal ...
func (recipe *ShapelessRecipe) Unmarshal(r *Reader) {
marshalShapeless(r, recipe)
}
// FromLatest ...
func (recipe *ShulkerBoxRecipe) FromLatest(v protocol.ShulkerBoxRecipe) *ShulkerBoxRecipe {
recipe.ShapelessRecipe = *(&ShapelessRecipe{}).FromLatest(v.ShapelessRecipe)
return recipe
}
// ToLatest ...
func (recipe *ShulkerBoxRecipe) ToLatest() protocol.ShulkerBoxRecipe {
return protocol.ShulkerBoxRecipe{
ShapelessRecipe: recipe.ShapelessRecipe.ToLatest(),
}
}
// Marshal ...
func (recipe *ShulkerBoxRecipe) Marshal(w *Writer) {
marshalShapeless(w, &recipe.ShapelessRecipe)
}
// Unmarshal ...
func (recipe *ShulkerBoxRecipe) Unmarshal(r *Reader) {
marshalShapeless(r, &recipe.ShapelessRecipe)
}
// FromLatest ...
func (recipe *ShapelessChemistryRecipe) FromLatest(v protocol.ShapelessChemistryRecipe) *ShapelessChemistryRecipe {
recipe.ShapelessRecipe = *(&ShapelessRecipe{}).FromLatest(v.ShapelessRecipe)
return recipe
}
// ToLatest ...
func (recipe *ShapelessChemistryRecipe) ToLatest() protocol.ShapelessChemistryRecipe {
return protocol.ShapelessChemistryRecipe{
ShapelessRecipe: recipe.ShapelessRecipe.ToLatest(),
}
}
// Marshal ...
func (recipe *ShapelessChemistryRecipe) Marshal(w *Writer) {
marshalShapeless(w, &recipe.ShapelessRecipe)
}
// Unmarshal ...
func (recipe *ShapelessChemistryRecipe) Unmarshal(r *Reader) {
marshalShapeless(r, &recipe.ShapelessRecipe)
}
// FromLatest ...
func (recipe *ShapedRecipe) FromLatest(v protocol.ShapedRecipe) *ShapedRecipe {
recipe.RecipeID = v.RecipeID
recipe.Width = v.Width
recipe.Height = v.Height
recipe.Input = v.Input
recipe.Output = v.Output
recipe.UUID = v.UUID
recipe.Block = v.Block
recipe.AssumeSymmetry = v.AssumeSymmetry
recipe.UnlockRequirement = (&RecipeUnlockRequirement{}).FromLatest(v.UnlockRequirement)
recipe.Priority = v.Priority
recipe.RecipeNetworkID = v.RecipeNetworkID
return recipe
}
// ToLatest ...
func (recipe *ShapedRecipe) ToLatest() protocol.ShapedRecipe {
return protocol.ShapedRecipe{
RecipeID: recipe.RecipeID,
Width: recipe.Width,
Height: recipe.Height,
Input: recipe.Input,
Output: recipe.Output,
UUID: recipe.UUID,
Block: recipe.Block,
AssumeSymmetry: recipe.AssumeSymmetry,
UnlockRequirement: recipe.UnlockRequirement.ToLatest(),
Priority: recipe.Priority,
RecipeNetworkID: recipe.RecipeNetworkID,
}
}
// Marshal ...
func (recipe *ShapedRecipe) Marshal(w *Writer) {
marshalShaped(w, recipe)
}
// Unmarshal ...
func (recipe *ShapedRecipe) Unmarshal(r *Reader) {
marshalShaped(r, recipe)
}
// FromLatest ...
func (recipe *ShapedChemistryRecipe) FromLatest(v protocol.ShapedChemistryRecipe) *ShapedChemistryRecipe {
recipe.ShapedRecipe = *(&ShapedRecipe{}).FromLatest(v.ShapedRecipe)
return recipe
}
// ToLatest ...
func (recipe *ShapedChemistryRecipe) ToLatest() protocol.ShapedChemistryRecipe {
return protocol.ShapedChemistryRecipe{
ShapedRecipe: recipe.ShapedRecipe.ToLatest(),
}
}
// Marshal ...
func (recipe *ShapedChemistryRecipe) Marshal(w *Writer) {
marshalShaped(w, &recipe.ShapedRecipe)
}
// Unmarshal ...
func (recipe *ShapedChemistryRecipe) Unmarshal(r *Reader) {
marshalShaped(r, &recipe.ShapedRecipe)
}
// FromLatest ...
func (recipe *FurnaceRecipe) FromLatest(v protocol.FurnaceRecipe) *FurnaceRecipe {
recipe.InputType = v.InputType
recipe.Output = v.Output
recipe.Block = v.Block
return recipe
}
// ToLatest ...
func (recipe *FurnaceRecipe) ToLatest() protocol.FurnaceRecipe {
return protocol.FurnaceRecipe{
InputType: recipe.InputType,
Output: recipe.Output,
Block: recipe.Block,
}
}
// Marshal ...
func (recipe *FurnaceRecipe) Marshal(w *Writer) {
w.Varint32(&recipe.InputType.NetworkID)
w.Item(&recipe.Output)
w.String(&recipe.Block)
}
// Unmarshal ...
func (recipe *FurnaceRecipe) Unmarshal(r *Reader) {
r.Varint32(&recipe.InputType.NetworkID)
r.Item(&recipe.Output)
r.String(&recipe.Block)
}
// FromLatest ...
func (recipe *FurnaceDataRecipe) FromLatest(v protocol.FurnaceDataRecipe) *FurnaceDataRecipe {
recipe.FurnaceRecipe = *(&FurnaceRecipe{}).FromLatest(v.FurnaceRecipe)
return recipe
}
// ToLatest ...
func (recipe *FurnaceDataRecipe) ToLatest() protocol.FurnaceDataRecipe {
return protocol.FurnaceDataRecipe{
FurnaceRecipe: recipe.FurnaceRecipe.ToLatest(),
}
}
// Marshal ...
func (recipe *FurnaceDataRecipe) Marshal(w *Writer) {
w.Varint32(&recipe.InputType.NetworkID)
aux := int32(recipe.InputType.MetadataValue)
w.Varint32(&aux)
w.Item(&recipe.Output)
w.String(&recipe.Block)
}
// Unmarshal ...
func (recipe *FurnaceDataRecipe) Unmarshal(r *Reader) {
var dataValue int32
r.Varint32(&recipe.InputType.NetworkID)
r.Varint32(&dataValue)
recipe.InputType.MetadataValue = uint32(dataValue)
r.Item(&recipe.Output)
r.String(&recipe.Block)
}
// FromLatest ...
func (recipe *MultiRecipe) FromLatest(v protocol.MultiRecipe) *MultiRecipe {
recipe.UUID = v.UUID
recipe.RecipeNetworkID = v.RecipeNetworkID
return recipe
}
// ToLatest ...
func (recipe *MultiRecipe) ToLatest() protocol.MultiRecipe {
return protocol.MultiRecipe{
UUID: recipe.UUID,
RecipeNetworkID: recipe.RecipeNetworkID,
}
}
// Marshal ...
func (recipe *MultiRecipe) Marshal(w *Writer) {
w.UUID(&recipe.UUID)
w.Varuint32(&recipe.RecipeNetworkID)
}
// Unmarshal ...
func (recipe *MultiRecipe) Unmarshal(r *Reader) {
r.UUID(&recipe.UUID)
r.Varuint32(&recipe.RecipeNetworkID)
}
// FromLatest ...
func (recipe *SmithingTransformRecipe) FromLatest(v protocol.SmithingTransformRecipe) *SmithingTransformRecipe {
recipe.RecipeNetworkID = v.RecipeNetworkID
recipe.RecipeID = v.RecipeID
recipe.Template = v.Template
recipe.Base = v.Base
recipe.Addition = v.Addition
recipe.Result = v.Result
recipe.Block = v.Block
return recipe
}
// ToLatest ...
func (recipe *SmithingTransformRecipe) ToLatest() protocol.SmithingTransformRecipe {
return protocol.SmithingTransformRecipe{
RecipeNetworkID: recipe.RecipeNetworkID,
RecipeID: recipe.RecipeID,
Template: recipe.Template,
Base: recipe.Base,
Addition: recipe.Addition,
Result: recipe.Result,
Block: recipe.Block,
}
}
// Marshal ...
func (recipe *SmithingTransformRecipe) Marshal(w *Writer) {
w.String(&recipe.RecipeID)
w.ItemDescriptorCount(&recipe.Template)
w.ItemDescriptorCount(&recipe.Base)
w.ItemDescriptorCount(&recipe.Addition)
w.Item(&recipe.Result)
w.String(&recipe.Block)
w.Varuint32(&recipe.RecipeNetworkID)
}
// Unmarshal ...
func (recipe *SmithingTransformRecipe) Unmarshal(r *Reader) {
r.String(&recipe.RecipeID)
r.ItemDescriptorCount(&recipe.Template)
r.ItemDescriptorCount(&recipe.Base)
r.ItemDescriptorCount(&recipe.Addition)
r.Item(&recipe.Result)
r.String(&recipe.Block)
r.Varuint32(&recipe.RecipeNetworkID)
}
// FromLatest ...
func (recipe *SmithingTrimRecipe) FromLatest(v protocol.SmithingTrimRecipe) *SmithingTrimRecipe {
recipe.RecipeNetworkID = v.RecipeNetworkID
recipe.RecipeID = v.RecipeID
recipe.Template = v.Template
recipe.Base = v.Base
recipe.Addition = v.Addition
recipe.Block = v.Block
return recipe
}
// ToLatest ...
func (recipe *SmithingTrimRecipe) ToLatest() protocol.SmithingTrimRecipe {
return protocol.SmithingTrimRecipe{
RecipeNetworkID: recipe.RecipeNetworkID,
RecipeID: recipe.RecipeID,
Template: recipe.Template,
Base: recipe.Base,
Addition: recipe.Addition,
Block: recipe.Block,
}
}
// Marshal ...
func (recipe *SmithingTrimRecipe) Marshal(w *Writer) {
w.String(&recipe.RecipeID)
w.ItemDescriptorCount(&recipe.Template)
w.ItemDescriptorCount(&recipe.Base)
w.ItemDescriptorCount(&recipe.Addition)
w.String(&recipe.Block)
w.Varuint32(&recipe.RecipeNetworkID)
}
// Unmarshal ...
func (recipe *SmithingTrimRecipe) Unmarshal(r *Reader) {
r.String(&recipe.RecipeID)
r.ItemDescriptorCount(&recipe.Template)
r.ItemDescriptorCount(&recipe.Base)
r.ItemDescriptorCount(&recipe.Addition)
r.String(&recipe.Block)
r.Varuint32(&recipe.RecipeNetworkID)
}
// marshalShaped ...
func marshalShaped(r protocol.IO, recipe *ShapedRecipe) {
r.String(&recipe.RecipeID)
r.Varint32(&recipe.Width)
r.Varint32(&recipe.Height)
protocol.FuncSliceOfLen(r, uint32(recipe.Width*recipe.Height), &recipe.Input, r.ItemDescriptorCount)
protocol.FuncSlice(r, &recipe.Output, r.Item)
r.UUID(&recipe.UUID)
r.String(&recipe.Block)
r.Varint32(&recipe.Priority)
r.Bool(&recipe.AssumeSymmetry)
if IsProtoGTE(r, ID685) {
protocol.Single(r, &recipe.UnlockRequirement)
}
r.Varuint32(&recipe.RecipeNetworkID)
}
// marshalShapeless ...
func marshalShapeless(r protocol.IO, recipe *ShapelessRecipe) {
r.String(&recipe.RecipeID)
protocol.FuncSlice(r, &recipe.Input, r.ItemDescriptorCount)
protocol.FuncSlice(r, &recipe.Output, r.Item)
r.UUID(&recipe.UUID)
r.String(&recipe.Block)
r.Varint32(&recipe.Priority)
if IsProtoGTE(r, ID685) {
protocol.Single(r, &recipe.UnlockRequirement)
}
r.Varuint32(&recipe.RecipeNetworkID)
}