782 lines
30 KiB
Go
782 lines
30 KiB
Go
package legacyver
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/akmalfairuz/legacy-version/internal/item"
|
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
|
"github.com/akmalfairuz/legacy-version/mapping"
|
|
"github.com/df-mc/dragonfly/server/world"
|
|
"github.com/samber/lo"
|
|
"github.com/sandertv/gophertunnel/minecraft"
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
)
|
|
|
|
type ItemTranslator interface {
|
|
// DowngradeItemType downgrades the input item type to a legacy item type.
|
|
DowngradeItemType(input protocol.ItemType) protocol.ItemType
|
|
// DowngradeItemStack downgrades the input item stack to a legacy item stack.
|
|
DowngradeItemStack(input protocol.ItemStack) protocol.ItemStack
|
|
// DowngradeItemInstance downgrades the input item instance to a legacy item instance.
|
|
DowngradeItemInstance(input protocol.ItemInstance) protocol.ItemInstance
|
|
// DowngradeItemDescriptor downgrades the input item descriptor to a legacy item descriptor.
|
|
DowngradeItemDescriptor(input protocol.ItemDescriptor) protocol.ItemDescriptor
|
|
// DowngradeItemDescriptorCount downgrades the input item descriptor (with count) to a legacy item descriptor (with count).
|
|
DowngradeItemDescriptorCount(input protocol.ItemDescriptorCount) protocol.ItemDescriptorCount
|
|
DowngradeItemPackets(pks []packet.Packet, conn *minecraft.Conn) []packet.Packet
|
|
// UpgradeItemType upgrades the input item type to the latest item type.
|
|
UpgradeItemType(input protocol.ItemType) protocol.ItemType
|
|
// UpgradeItemStack upgrades the input item stack to the latest item stack.
|
|
UpgradeItemStack(input protocol.ItemStack) protocol.ItemStack
|
|
// UpgradeItemInstance upgrades the input item instance to the latest item instance.
|
|
UpgradeItemInstance(input protocol.ItemInstance) protocol.ItemInstance
|
|
// UpgradeItemDescriptor upgrades the input item descriptor to the latest item descriptor.
|
|
UpgradeItemDescriptor(input protocol.ItemDescriptor) protocol.ItemDescriptor
|
|
// UpgradeItemDescriptorCount upgrades the input item descriptor (with count) to the latest item descriptor (with count).
|
|
UpgradeItemDescriptorCount(input protocol.ItemDescriptorCount) protocol.ItemDescriptorCount
|
|
UpgradeItemPackets(pks []packet.Packet, conn *minecraft.Conn) []packet.Packet
|
|
// Register registers a custom item entry.
|
|
Register(item world.CustomItem, replacement string)
|
|
// CustomItems lists all custom items used as substitutes, with the runtime id as the key
|
|
CustomItems() map[int32]world.CustomItem
|
|
// DowngradeLegacyItemRegistry ...
|
|
DowngradeLegacyItemRegistry(entries []proto.LegacyItemRegistryEntry) []proto.LegacyItemRegistryEntry
|
|
// UpgradeLegacyItemRegistry ...
|
|
UpgradeLegacyItemRegistry(entries []proto.LegacyItemRegistryEntry) []proto.LegacyItemRegistryEntry
|
|
}
|
|
|
|
type DefaultItemTranslator struct {
|
|
mapping mapping.Item
|
|
latest mapping.Item
|
|
blockMapping mapping.Block
|
|
blockMappingLatest mapping.Block
|
|
ridToCustomItem map[int32]world.CustomItem
|
|
originalToCustom map[int32]int32
|
|
customToOriginal map[int32]int32
|
|
}
|
|
|
|
func NewItemTranslator(mapping mapping.Item, latestMapping mapping.Item, blockMapping mapping.Block, blockMappingLatest mapping.Block) *DefaultItemTranslator {
|
|
return &DefaultItemTranslator{mapping: mapping, latest: latestMapping, blockMapping: blockMapping, blockMappingLatest: blockMappingLatest,
|
|
ridToCustomItem: make(map[int32]world.CustomItem), originalToCustom: make(map[int32]int32), customToOriginal: make(map[int32]int32)}
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemType(input protocol.ItemType) protocol.ItemType {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
if input.NetworkID == t.latest.Air() || input.NetworkID == 0 {
|
|
return protocol.ItemType{
|
|
NetworkID: t.mapping.Air(),
|
|
}
|
|
}
|
|
networkID := input.NetworkID
|
|
metadata := input.MetadataValue
|
|
|
|
var ok bool
|
|
if networkID, ok = t.originalToCustom[input.NetworkID]; !ok {
|
|
name, _ := t.latest.ItemRuntimeIDToName(input.NetworkID)
|
|
i := item.Downgrade(item.Item{
|
|
Name: name,
|
|
Metadata: input.MetadataValue,
|
|
Version: t.latest.ItemVersion(),
|
|
}, t.mapping.ItemVersion())
|
|
metadata = i.Metadata
|
|
|
|
if i.Name == "minecraft:netherstar" {
|
|
i.Name = "minecraft:nether_star"
|
|
}
|
|
|
|
networkID, ok = t.mapping.ItemNameToRuntimeID(i.Name)
|
|
if !ok {
|
|
networkID, _ = t.mapping.ItemNameToRuntimeID("minecraft:info_update")
|
|
}
|
|
}
|
|
|
|
return protocol.ItemType{
|
|
NetworkID: networkID,
|
|
MetadataValue: metadata,
|
|
}
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemStack(input protocol.ItemStack) protocol.ItemStack {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.ItemType = t.DowngradeItemType(input.ItemType)
|
|
|
|
blockRuntimeId := uint32(0)
|
|
if input.NetworkID != t.mapping.Air() {
|
|
name, _ := t.mapping.ItemRuntimeIDToName(input.NetworkID)
|
|
if latestBlockState, ok := item.BlockStateFromItemName(name, input.MetadataValue); ok {
|
|
var found bool
|
|
if blockRuntimeId, found = t.blockMapping.StateToRuntimeID(latestBlockState); !found {
|
|
blockRuntimeId = t.blockMapping.Air()
|
|
}
|
|
}
|
|
}
|
|
return protocol.ItemStack{
|
|
ItemType: input.ItemType,
|
|
BlockRuntimeID: int32(blockRuntimeId),
|
|
Count: input.Count,
|
|
NBTData: input.NBTData,
|
|
CanBePlacedOn: input.CanBePlacedOn,
|
|
CanBreak: input.CanBreak,
|
|
HasNetworkID: input.HasNetworkID,
|
|
}
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemInstance(input protocol.ItemInstance) protocol.ItemInstance {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.Stack = t.DowngradeItemStack(input.Stack)
|
|
return input
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemDescriptor(input protocol.ItemDescriptor) protocol.ItemDescriptor {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
switch descriptor := input.(type) {
|
|
case *protocol.InvalidItemDescriptor:
|
|
return input
|
|
case *protocol.DefaultItemDescriptor:
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: int32(descriptor.NetworkID), MetadataValue: uint32(descriptor.MetadataValue)})
|
|
descriptor.NetworkID, descriptor.MetadataValue = int16(itemType.NetworkID), int16(itemType.MetadataValue)
|
|
return descriptor
|
|
case *protocol.MoLangItemDescriptor:
|
|
return input
|
|
case *protocol.ItemTagItemDescriptor:
|
|
return input
|
|
case *protocol.DeferredItemDescriptor:
|
|
rid, ok := t.latest.ItemNameToRuntimeID(descriptor.Name)
|
|
descriptor.Name = "minecraft:air"
|
|
if !ok {
|
|
descriptor.MetadataValue = 0
|
|
return descriptor
|
|
}
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: rid, MetadataValue: uint32(descriptor.MetadataValue)})
|
|
descriptor.MetadataValue = int16(itemType.MetadataValue)
|
|
if name, ok := t.mapping.ItemRuntimeIDToName(itemType.NetworkID); ok {
|
|
descriptor.Name = name
|
|
}
|
|
return descriptor
|
|
case *protocol.ComplexAliasItemDescriptor:
|
|
rid, ok := t.latest.ItemNameToRuntimeID(descriptor.Name)
|
|
descriptor.Name = "minecraft:air"
|
|
if !ok {
|
|
return descriptor
|
|
}
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: rid})
|
|
if name, ok := t.mapping.ItemRuntimeIDToName(itemType.NetworkID); ok {
|
|
descriptor.Name = name
|
|
}
|
|
return descriptor
|
|
}
|
|
panic("unknown item descriptor")
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemDescriptorCount(input protocol.ItemDescriptorCount) protocol.ItemDescriptorCount {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.Descriptor = t.DowngradeItemDescriptor(input.Descriptor)
|
|
return input
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemType(input protocol.ItemType) protocol.ItemType {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
if input.NetworkID == t.mapping.Air() || input.NetworkID == 0 {
|
|
return protocol.ItemType{
|
|
NetworkID: t.latest.Air(),
|
|
}
|
|
}
|
|
networkID := input.NetworkID
|
|
metadata := input.MetadataValue
|
|
|
|
var ok bool
|
|
if networkID, ok = t.customToOriginal[input.NetworkID]; !ok {
|
|
name, _ := t.mapping.ItemRuntimeIDToName(input.NetworkID)
|
|
i := item.Upgrade(item.Item{
|
|
Name: name,
|
|
Metadata: input.MetadataValue,
|
|
Version: t.mapping.ItemVersion(),
|
|
}, t.latest.ItemVersion())
|
|
networkID, ok = t.latest.ItemNameToRuntimeID(i.Name)
|
|
if !ok {
|
|
networkID, _ = t.latest.ItemNameToRuntimeID("minecraft:info_update")
|
|
}
|
|
}
|
|
|
|
return protocol.ItemType{
|
|
NetworkID: networkID,
|
|
MetadataValue: metadata,
|
|
}
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemStack(input protocol.ItemStack) protocol.ItemStack {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.ItemType = t.UpgradeItemType(input.ItemType)
|
|
|
|
blockRuntimeId := uint32(0)
|
|
if input.NetworkID != t.latest.Air() {
|
|
name, _ := t.latest.ItemRuntimeIDToName(input.NetworkID)
|
|
if latestBlockState, ok := item.BlockStateFromItemName(name, input.MetadataValue); ok {
|
|
blockRuntimeId, _ = t.blockMappingLatest.StateToRuntimeID(latestBlockState)
|
|
}
|
|
}
|
|
return protocol.ItemStack{
|
|
ItemType: input.ItemType,
|
|
BlockRuntimeID: int32(blockRuntimeId),
|
|
Count: input.Count,
|
|
NBTData: input.NBTData,
|
|
CanBePlacedOn: input.CanBePlacedOn,
|
|
CanBreak: input.CanBreak,
|
|
HasNetworkID: input.HasNetworkID,
|
|
}
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemInstance(input protocol.ItemInstance) protocol.ItemInstance {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.Stack = t.UpgradeItemStack(input.Stack)
|
|
return input
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemDescriptor(input protocol.ItemDescriptor) protocol.ItemDescriptor {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
switch descriptor := input.(type) {
|
|
case *protocol.InvalidItemDescriptor:
|
|
return input
|
|
case *protocol.DefaultItemDescriptor:
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: int32(descriptor.NetworkID), MetadataValue: uint32(descriptor.MetadataValue)})
|
|
descriptor.NetworkID, descriptor.MetadataValue = int16(itemType.NetworkID), int16(itemType.MetadataValue)
|
|
return descriptor
|
|
case *protocol.MoLangItemDescriptor:
|
|
return input
|
|
case *protocol.ItemTagItemDescriptor:
|
|
return input
|
|
case *protocol.DeferredItemDescriptor:
|
|
rid, ok := t.mapping.ItemNameToRuntimeID(descriptor.Name)
|
|
descriptor.Name = "minecraft:air"
|
|
if !ok {
|
|
descriptor.MetadataValue = 0
|
|
return descriptor
|
|
}
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: rid, MetadataValue: uint32(descriptor.MetadataValue)})
|
|
descriptor.MetadataValue = int16(itemType.MetadataValue)
|
|
if name, ok := t.latest.ItemRuntimeIDToName(itemType.NetworkID); ok {
|
|
descriptor.Name = name
|
|
}
|
|
return descriptor
|
|
case *protocol.ComplexAliasItemDescriptor:
|
|
rid, ok := t.mapping.ItemNameToRuntimeID(descriptor.Name)
|
|
descriptor.Name = "minecraft:air"
|
|
if !ok {
|
|
return descriptor
|
|
}
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: rid})
|
|
if name, ok := t.latest.ItemRuntimeIDToName(itemType.NetworkID); ok {
|
|
descriptor.Name = name
|
|
}
|
|
return descriptor
|
|
}
|
|
panic("unknown item descriptor")
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemDescriptorCount(input protocol.ItemDescriptorCount) protocol.ItemDescriptorCount {
|
|
if t.latest == t.mapping {
|
|
return input
|
|
}
|
|
input.Descriptor = t.UpgradeItemDescriptor(input.Descriptor)
|
|
return input
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeItemPackets(pks []packet.Packet, _ *minecraft.Conn) (result []packet.Packet) {
|
|
for _, pk := range pks {
|
|
switch pk := pk.(type) {
|
|
case *packet.MobEquipment:
|
|
pk.NewItem = t.DowngradeItemInstance(pk.NewItem)
|
|
case *packet.MobArmourEquipment:
|
|
pk.Helmet = t.DowngradeItemInstance(pk.Helmet)
|
|
pk.Chestplate = t.DowngradeItemInstance(pk.Chestplate)
|
|
pk.Leggings = t.DowngradeItemInstance(pk.Leggings)
|
|
pk.Boots = t.DowngradeItemInstance(pk.Boots)
|
|
pk.Body = t.DowngradeItemInstance(pk.Body)
|
|
case *packet.ActorEvent:
|
|
if pk.EventType == packet.ActorEventFeed {
|
|
value := pk.EventData
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: value >> 16, MetadataValue: uint32(value & 0xf)})
|
|
pk.EventData = (itemType.NetworkID << 16) | int32(itemType.MetadataValue)
|
|
}
|
|
case *packet.AddItemActor:
|
|
pk.Item = t.DowngradeItemInstance(pk.Item)
|
|
case *packet.AddPlayer:
|
|
pk.HeldItem = t.DowngradeItemInstance(pk.HeldItem)
|
|
case *packet.InventorySlot:
|
|
pk.NewItem = t.DowngradeItemInstance(pk.NewItem)
|
|
pk.StorageItem = t.DowngradeItemInstance(pk.StorageItem)
|
|
case *packet.InventoryContent:
|
|
pk.Content = lo.Map(pk.Content, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
return t.DowngradeItemInstance(item)
|
|
})
|
|
pk.StorageItem = t.DowngradeItemInstance(pk.StorageItem)
|
|
case *packet.ItemStackRequest:
|
|
for i, request := range pk.Requests {
|
|
for i2, action := range request.Actions {
|
|
if act, ok := action.(*protocol.CraftResultsDeprecatedStackRequestAction); ok {
|
|
act.ResultItems = lo.Map(act.ResultItems, func(item protocol.ItemStack, _ int) protocol.ItemStack {
|
|
return t.DowngradeItemStack(item)
|
|
})
|
|
pk.Requests[i].Actions[i2] = act
|
|
}
|
|
}
|
|
}
|
|
case *packet.CraftingData:
|
|
for i, recipe := range pk.Recipes {
|
|
switch recipe := recipe.(type) {
|
|
case *protocol.ShapelessRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.DowngradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.DowngradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapedRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.DowngradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.DowngradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.FurnaceRecipe:
|
|
recipe.InputType = t.DowngradeItemType(recipe.InputType)
|
|
recipe.Output = t.DowngradeItemStack(recipe.Output)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.FurnaceDataRecipe:
|
|
recipe.InputType = t.DowngradeItemType(recipe.InputType)
|
|
recipe.Output = t.DowngradeItemStack(recipe.Output)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShulkerBoxRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.DowngradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.DowngradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapelessChemistryRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.DowngradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.DowngradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapedChemistryRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.DowngradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.DowngradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.SmithingTransformRecipe:
|
|
recipe.Template = t.DowngradeItemDescriptorCount(recipe.Template)
|
|
recipe.Base = t.DowngradeItemDescriptorCount(recipe.Base)
|
|
recipe.Addition = t.DowngradeItemDescriptorCount(recipe.Addition)
|
|
recipe.Result = t.DowngradeItemStack(recipe.Result)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.SmithingTrimRecipe:
|
|
recipe.Template = t.DowngradeItemDescriptorCount(recipe.Template)
|
|
recipe.Base = t.DowngradeItemDescriptorCount(recipe.Base)
|
|
recipe.Addition = t.DowngradeItemDescriptorCount(recipe.Addition)
|
|
}
|
|
}
|
|
for i, recipe := range pk.PotionRecipes {
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.InputPotionID, MetadataValue: uint32(recipe.InputPotionMetadata)})
|
|
recipe.InputPotionID, recipe.InputPotionMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
itemType = t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.ReagentItemID, MetadataValue: uint32(recipe.ReagentItemMetadata)})
|
|
recipe.ReagentItemID, recipe.ReagentItemMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
itemType = t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.OutputPotionID, MetadataValue: uint32(recipe.OutputPotionMetadata)})
|
|
recipe.OutputPotionID, recipe.OutputPotionMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
pk.PotionRecipes[i] = recipe
|
|
}
|
|
for i, recipe := range pk.PotionContainerChangeRecipes {
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.InputItemID})
|
|
recipe.InputItemID = itemType.NetworkID
|
|
itemType = t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.ReagentItemID})
|
|
recipe.ReagentItemID = itemType.NetworkID
|
|
itemType = t.DowngradeItemType(protocol.ItemType{NetworkID: recipe.OutputItemID})
|
|
recipe.OutputItemID = itemType.NetworkID
|
|
pk.PotionContainerChangeRecipes[i] = recipe
|
|
}
|
|
for i, recipe := range pk.MaterialReducers {
|
|
recipe.InputItem = t.DowngradeItemType(recipe.InputItem)
|
|
for i2, output := range recipe.Outputs {
|
|
itemType := t.DowngradeItemType(protocol.ItemType{NetworkID: output.NetworkID})
|
|
output.NetworkID = itemType.NetworkID
|
|
recipe.Outputs[i2] = output
|
|
}
|
|
pk.MaterialReducers[i] = recipe
|
|
}
|
|
//case *packet.CraftingEvent:
|
|
// pk.Input = lo.Map(pk.Input, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
// return t.DowngradeItemInstance(item)
|
|
// })
|
|
// pk.Output = lo.Map(pk.Output, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
// return t.DowngradeItemInstance(item)
|
|
// })
|
|
case *packet.PlayerAuthInput:
|
|
for i, action := range pk.ItemStackRequest.Actions {
|
|
if act, ok := action.(*protocol.CraftResultsDeprecatedStackRequestAction); ok {
|
|
act.ResultItems = lo.Map(act.ResultItems, func(item protocol.ItemStack, _ int) protocol.ItemStack {
|
|
return t.DowngradeItemStack(item)
|
|
})
|
|
pk.ItemStackRequest.Actions[i] = act
|
|
}
|
|
}
|
|
for i, action := range pk.ItemInteractionData.Actions {
|
|
action.OldItem = t.DowngradeItemInstance(action.OldItem)
|
|
action.NewItem = t.DowngradeItemInstance(action.NewItem)
|
|
pk.ItemInteractionData.Actions[i] = action
|
|
}
|
|
pk.ItemInteractionData.HeldItem = t.DowngradeItemInstance(pk.ItemInteractionData.HeldItem)
|
|
case *packet.CreativeContent:
|
|
for i, creativeItem := range pk.Items {
|
|
creativeItem.Item = t.DowngradeItemStack(creativeItem.Item)
|
|
|
|
pk.Items[i] = creativeItem
|
|
}
|
|
case *packet.InventoryTransaction:
|
|
for i, action := range pk.Actions {
|
|
action.OldItem = t.DowngradeItemInstance(action.OldItem)
|
|
action.NewItem = t.DowngradeItemInstance(action.NewItem)
|
|
pk.Actions[i] = action
|
|
}
|
|
switch transactionData := pk.TransactionData.(type) {
|
|
case *protocol.UseItemTransactionData:
|
|
transactionData.HeldItem = t.DowngradeItemInstance(transactionData.HeldItem)
|
|
for i, action := range transactionData.Actions {
|
|
action.OldItem = t.DowngradeItemInstance(action.OldItem)
|
|
action.NewItem = t.DowngradeItemInstance(action.NewItem)
|
|
transactionData.Actions[i] = action
|
|
}
|
|
case *protocol.UseItemOnEntityTransactionData:
|
|
transactionData.HeldItem = t.DowngradeItemInstance(transactionData.HeldItem)
|
|
case *protocol.ReleaseItemTransactionData:
|
|
transactionData.HeldItem = t.DowngradeItemInstance(transactionData.HeldItem)
|
|
}
|
|
case *packet.LevelEvent:
|
|
if pk.EventType == packet.LevelEventParticleLegacyEvent|14 { // egg crack
|
|
itemType := t.DowngradeItemType(protocol.ItemType{
|
|
NetworkID: pk.EventData >> 16,
|
|
MetadataValue: uint32(pk.EventData & 0xf),
|
|
})
|
|
pk.EventData = (itemType.NetworkID << 16) | int32(itemType.MetadataValue)
|
|
}
|
|
//case *packet.ItemRegistry:
|
|
// for _, i := range t.CustomItems() {
|
|
// name, _ := i.EncodeItem()
|
|
// pk.Items = append(pk.Items, protocol.ItemEntry{
|
|
// Name: name,
|
|
// Data: packbuilder.Components(i),
|
|
// })
|
|
// }
|
|
}
|
|
result = append(result, pk)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) DowngradeLegacyItemRegistry(entries []proto.LegacyItemRegistryEntry) []proto.LegacyItemRegistryEntry {
|
|
for i, entry := range entries {
|
|
if !entry.ComponentBased {
|
|
itemType := t.DowngradeItemType(protocol.ItemType{
|
|
NetworkID: int32(entry.RuntimeID),
|
|
MetadataValue: 0,
|
|
})
|
|
if itemType.NetworkID == t.mapping.Air() {
|
|
removeIndex(entries, i)
|
|
continue
|
|
}
|
|
entry.RuntimeID = int16(itemType.NetworkID)
|
|
|
|
var ok bool
|
|
if entry.Name, ok = t.mapping.ItemRuntimeIDToName(itemType.NetworkID); !ok {
|
|
panic(itemType)
|
|
}
|
|
} else {
|
|
t.latest.RegisterEntryRID(entry.Name, int32(entry.RuntimeID), 2)
|
|
entry.RuntimeID = int16(t.mapping.RegisterEntry(entry.Name))
|
|
}
|
|
entries[i] = entry
|
|
}
|
|
for rid, i := range t.CustomItems() {
|
|
name, _ := i.EncodeItem()
|
|
entries = append(entries, proto.LegacyItemRegistryEntry{
|
|
Name: name,
|
|
RuntimeID: int16(rid),
|
|
ComponentBased: true,
|
|
})
|
|
}
|
|
return entries
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeLegacyItemRegistry(entries []proto.LegacyItemRegistryEntry) []proto.LegacyItemRegistryEntry {
|
|
for i, entry := range entries {
|
|
if !entry.ComponentBased {
|
|
itemType := t.UpgradeItemType(protocol.ItemType{
|
|
NetworkID: int32(entry.RuntimeID),
|
|
MetadataValue: 0,
|
|
})
|
|
entry.RuntimeID = int16(itemType.NetworkID)
|
|
|
|
var ok bool
|
|
if entry.Name, ok = t.latest.ItemRuntimeIDToName(itemType.NetworkID); !ok {
|
|
panic(itemType)
|
|
}
|
|
} else {
|
|
t.latest.RegisterEntryRID(entry.Name, int32(entry.RuntimeID), 2)
|
|
entry.RuntimeID = int16(t.mapping.RegisterEntry(entry.Name))
|
|
}
|
|
entries[i] = entry
|
|
}
|
|
for rid, i := range t.CustomItems() {
|
|
name, _ := i.EncodeItem()
|
|
entries = append(entries, proto.LegacyItemRegistryEntry{
|
|
Name: name,
|
|
RuntimeID: int16(rid),
|
|
ComponentBased: true,
|
|
})
|
|
}
|
|
return entries
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) UpgradeItemPackets(pks []packet.Packet, _ *minecraft.Conn) (result []packet.Packet) {
|
|
for _, pk := range pks {
|
|
switch pk := pk.(type) {
|
|
case *packet.MobEquipment:
|
|
pk.NewItem = t.UpgradeItemInstance(pk.NewItem)
|
|
case *packet.MobArmourEquipment:
|
|
pk.Helmet = t.UpgradeItemInstance(pk.Helmet)
|
|
pk.Chestplate = t.UpgradeItemInstance(pk.Chestplate)
|
|
pk.Leggings = t.UpgradeItemInstance(pk.Leggings)
|
|
pk.Boots = t.UpgradeItemInstance(pk.Boots)
|
|
pk.Body = t.UpgradeItemInstance(pk.Body)
|
|
case *packet.AddItemActor:
|
|
pk.Item = t.UpgradeItemInstance(pk.Item)
|
|
case *packet.AddPlayer:
|
|
pk.HeldItem = t.UpgradeItemInstance(pk.HeldItem)
|
|
case *packet.InventorySlot:
|
|
pk.NewItem = t.UpgradeItemInstance(pk.NewItem)
|
|
pk.StorageItem = t.UpgradeItemInstance(pk.StorageItem)
|
|
case *packet.InventoryContent:
|
|
pk.Content = lo.Map(pk.Content, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
return t.UpgradeItemInstance(item)
|
|
})
|
|
pk.StorageItem = t.UpgradeItemInstance(pk.StorageItem)
|
|
case *packet.ItemStackRequest:
|
|
for i, request := range pk.Requests {
|
|
for i2, action := range request.Actions {
|
|
if act, ok := action.(*protocol.CraftResultsDeprecatedStackRequestAction); ok {
|
|
act.ResultItems = lo.Map(act.ResultItems, func(item protocol.ItemStack, _ int) protocol.ItemStack {
|
|
return t.UpgradeItemStack(item)
|
|
})
|
|
pk.Requests[i].Actions[i2] = act
|
|
}
|
|
}
|
|
}
|
|
case *packet.CraftingData:
|
|
for i, recipe := range pk.Recipes {
|
|
switch recipe := recipe.(type) {
|
|
case *protocol.ShapelessRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.UpgradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.UpgradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapedRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.UpgradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.UpgradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.FurnaceRecipe:
|
|
recipe.InputType = t.UpgradeItemType(recipe.InputType)
|
|
recipe.Output = t.UpgradeItemStack(recipe.Output)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.FurnaceDataRecipe:
|
|
recipe.InputType = t.UpgradeItemType(recipe.InputType)
|
|
recipe.Output = t.UpgradeItemStack(recipe.Output)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShulkerBoxRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.UpgradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.UpgradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapelessChemistryRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.UpgradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.UpgradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.ShapedChemistryRecipe:
|
|
for i2, input := range recipe.Input {
|
|
recipe.Input[i2] = t.UpgradeItemDescriptorCount(input)
|
|
}
|
|
for i2, stack := range recipe.Output {
|
|
recipe.Output[i2] = t.UpgradeItemStack(stack)
|
|
}
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.SmithingTransformRecipe:
|
|
recipe.Template = t.UpgradeItemDescriptorCount(recipe.Template)
|
|
recipe.Base = t.UpgradeItemDescriptorCount(recipe.Base)
|
|
recipe.Addition = t.UpgradeItemDescriptorCount(recipe.Addition)
|
|
recipe.Result = t.UpgradeItemStack(recipe.Result)
|
|
pk.Recipes[i] = recipe
|
|
case *protocol.SmithingTrimRecipe:
|
|
recipe.Template = t.UpgradeItemDescriptorCount(recipe.Template)
|
|
recipe.Base = t.UpgradeItemDescriptorCount(recipe.Base)
|
|
recipe.Addition = t.UpgradeItemDescriptorCount(recipe.Addition)
|
|
}
|
|
}
|
|
for i, recipe := range pk.PotionRecipes {
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.InputPotionID, MetadataValue: uint32(recipe.InputPotionMetadata)})
|
|
recipe.InputPotionID, recipe.InputPotionMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
itemType = t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.ReagentItemID, MetadataValue: uint32(recipe.ReagentItemMetadata)})
|
|
recipe.ReagentItemID, recipe.ReagentItemMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
itemType = t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.OutputPotionID, MetadataValue: uint32(recipe.OutputPotionMetadata)})
|
|
recipe.OutputPotionID, recipe.OutputPotionMetadata = itemType.NetworkID, int32(itemType.MetadataValue)
|
|
pk.PotionRecipes[i] = recipe
|
|
}
|
|
for i, recipe := range pk.PotionContainerChangeRecipes {
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.InputItemID})
|
|
recipe.InputItemID = itemType.NetworkID
|
|
itemType = t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.ReagentItemID})
|
|
recipe.ReagentItemID = itemType.NetworkID
|
|
itemType = t.UpgradeItemType(protocol.ItemType{NetworkID: recipe.OutputItemID})
|
|
recipe.OutputItemID = itemType.NetworkID
|
|
pk.PotionContainerChangeRecipes[i] = recipe
|
|
}
|
|
for i, recipe := range pk.MaterialReducers {
|
|
recipe.InputItem = t.UpgradeItemType(recipe.InputItem)
|
|
for i2, output := range recipe.Outputs {
|
|
itemType := t.UpgradeItemType(protocol.ItemType{NetworkID: output.NetworkID})
|
|
output.NetworkID = itemType.NetworkID
|
|
recipe.Outputs[i2] = output
|
|
}
|
|
pk.MaterialReducers[i] = recipe
|
|
}
|
|
//case *packet.CraftingEvent:
|
|
// pk.Input = lo.Map(pk.Input, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
// return t.UpgradeItemInstance(item)
|
|
// })
|
|
// pk.Output = lo.Map(pk.Output, func(item protocol.ItemInstance, _ int) protocol.ItemInstance {
|
|
// return t.UpgradeItemInstance(item)
|
|
// })
|
|
case *packet.PlayerAuthInput:
|
|
for i, action := range pk.ItemStackRequest.Actions {
|
|
if act, ok := action.(*protocol.CraftResultsDeprecatedStackRequestAction); ok {
|
|
act.ResultItems = lo.Map(act.ResultItems, func(item protocol.ItemStack, _ int) protocol.ItemStack {
|
|
return t.UpgradeItemStack(item)
|
|
})
|
|
pk.ItemStackRequest.Actions[i] = act
|
|
}
|
|
}
|
|
for i, action := range pk.ItemInteractionData.Actions {
|
|
action.OldItem = t.UpgradeItemInstance(action.OldItem)
|
|
action.NewItem = t.UpgradeItemInstance(action.NewItem)
|
|
pk.ItemInteractionData.Actions[i] = action
|
|
}
|
|
pk.ItemInteractionData.HeldItem = t.UpgradeItemInstance(pk.ItemInteractionData.HeldItem)
|
|
case *packet.CreativeContent:
|
|
for i, creativeItem := range pk.Items {
|
|
creativeItem.Item = t.UpgradeItemStack(creativeItem.Item)
|
|
pk.Items[i] = creativeItem
|
|
}
|
|
case *packet.InventoryTransaction:
|
|
for i, action := range pk.Actions {
|
|
action.OldItem = t.UpgradeItemInstance(action.OldItem)
|
|
action.NewItem = t.UpgradeItemInstance(action.NewItem)
|
|
pk.Actions[i] = action
|
|
}
|
|
switch transactionData := pk.TransactionData.(type) {
|
|
case *protocol.UseItemTransactionData:
|
|
transactionData.HeldItem = t.UpgradeItemInstance(transactionData.HeldItem)
|
|
for i, action := range transactionData.Actions {
|
|
action.OldItem = t.UpgradeItemInstance(action.OldItem)
|
|
action.NewItem = t.UpgradeItemInstance(action.NewItem)
|
|
transactionData.Actions[i] = action
|
|
}
|
|
case *protocol.UseItemOnEntityTransactionData:
|
|
transactionData.HeldItem = t.UpgradeItemInstance(transactionData.HeldItem)
|
|
case *protocol.ReleaseItemTransactionData:
|
|
transactionData.HeldItem = t.UpgradeItemInstance(transactionData.HeldItem)
|
|
}
|
|
case *packet.LevelEvent:
|
|
if pk.EventType == packet.LevelEventParticleLegacyEvent|14 { // egg crack
|
|
itemType := t.UpgradeItemType(protocol.ItemType{
|
|
NetworkID: pk.EventData >> 16,
|
|
MetadataValue: uint32(pk.EventData & 0xf),
|
|
})
|
|
pk.EventData = (itemType.NetworkID << 16) | int32(itemType.MetadataValue)
|
|
}
|
|
//case *packet.ItemRegistry:
|
|
// for _, i := range t.CustomItems() {
|
|
// name, _ := i.EncodeItem()
|
|
// pk.Items = append(pk.Items, protocol.ItemEntry{
|
|
// Name: name,
|
|
// Data: packbuilder.Components(i),
|
|
// })
|
|
// }
|
|
}
|
|
result = append(result, pk)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) Register(item world.CustomItem, replacement string) {
|
|
name, _ := item.EncodeItem()
|
|
originalRid, ok := t.latest.ItemNameToRuntimeID(replacement)
|
|
if !ok {
|
|
panic(fmt.Errorf("%v not found in latest items", replacement))
|
|
}
|
|
if _, ok := t.originalToCustom[originalRid]; ok {
|
|
panic(fmt.Errorf("%v is already mapped", replacement))
|
|
}
|
|
|
|
nextRID := t.mapping.RegisterEntry(name)
|
|
t.ridToCustomItem[nextRID] = item
|
|
t.originalToCustom[originalRid] = nextRID
|
|
t.customToOriginal[nextRID] = originalRid
|
|
}
|
|
|
|
func (t *DefaultItemTranslator) CustomItems() map[int32]world.CustomItem {
|
|
return t.ridToCustomItem
|
|
}
|
|
|
|
func removeIndex[T any](s []T, index int) []T {
|
|
ret := make([]T, 0)
|
|
ret = append(ret, s[:index]...)
|
|
return append(ret, s[index+1:]...)
|
|
}
|