Add 1.21.20
This commit is contained in:
@@ -8,7 +8,7 @@ A gophertunnel protocol interface implementation to support older Minecraft Bedr
|
|||||||
| 766 | 1.21.50 | ✅ |
|
| 766 | 1.21.50 | ✅ |
|
||||||
| 748 | 1.21.40 | ✅ |
|
| 748 | 1.21.40 | ✅ |
|
||||||
| 729 | 1.21.30 | ✅ |
|
| 729 | 1.21.30 | ✅ |
|
||||||
| 712 | 1.21.20 | 🚧 |
|
| 712 | 1.21.20 | ✅ |
|
||||||
| 686 | 1.21.2 | 🚧 |
|
| 686 | 1.21.2 | 🚧 |
|
||||||
| 685 | 1.21.0 | 🚧 |
|
| 685 | 1.21.0 | 🚧 |
|
||||||
|
|
||||||
|
|||||||
BIN
legacyver/data/block_states_712.nbt
Normal file
BIN
legacyver/data/block_states_712.nbt
Normal file
Binary file not shown.
BIN
legacyver/data/item_runtime_ids_712.nbt
Normal file
BIN
legacyver/data/item_runtime_ids_712.nbt
Normal file
Binary file not shown.
6802
legacyver/data/required_item_list_712.json
Normal file
6802
legacyver/data/required_item_list_712.json
Normal file
File diff suppressed because it is too large
Load Diff
24
legacyver/legacypacket/container_registry_cleanup.go
Normal file
24
legacyver/legacypacket/container_registry_cleanup.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContainerRegistryCleanup is sent by the server to trigger a client-side cleanup of the dynamic container
|
||||||
|
// registry.
|
||||||
|
type ContainerRegistryCleanup struct {
|
||||||
|
// RemovedContainers is a list of protocol.FullContainerName's that should be removed from the client-side
|
||||||
|
// container registry.
|
||||||
|
RemovedContainers []proto.FullContainerName
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*ContainerRegistryCleanup) ID() uint32 {
|
||||||
|
return packet.IDContainerRegistryCleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *ContainerRegistryCleanup) Marshal(io protocol.IO) {
|
||||||
|
protocol.Slice(io, &pk.RemovedContainers)
|
||||||
|
}
|
||||||
49
legacyver/legacypacket/emote_packet.go
Normal file
49
legacyver/legacypacket/emote_packet.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EmoteFlagServerSide = 1 << iota
|
||||||
|
EmoteFlagMuteChat
|
||||||
|
)
|
||||||
|
|
||||||
|
// Emote is sent by both the server and the client. When the client sends an emote, it sends this packet to
|
||||||
|
// the server, after which the server will broadcast the packet to other players online.
|
||||||
|
type Emote struct {
|
||||||
|
// EntityRuntimeID is the entity that sent the emote. When a player sends this packet, it has this field
|
||||||
|
// set as its own entity runtime ID.
|
||||||
|
EntityRuntimeID uint64
|
||||||
|
// EmoteLength is the number of ticks that the emote lasts for.
|
||||||
|
EmoteLength uint32
|
||||||
|
// EmoteID is the ID of the emote to send.
|
||||||
|
EmoteID string
|
||||||
|
// XUID is the Xbox User ID of the player that sent the emote. It is only set when the emote is used by a player that
|
||||||
|
// is authenticated with Xbox Live.
|
||||||
|
XUID string
|
||||||
|
// PlatformID is an identifier only set for particular platforms when using an emote (presumably only for Nintendo
|
||||||
|
// Switch). It is otherwise an empty string, and is used to decide which players are able to emote with each other.
|
||||||
|
PlatformID string
|
||||||
|
// Flags is a combination of flags that change the way the Emote packet operates. When the server sends
|
||||||
|
// this packet to other players, EmoteFlagServerSide must be present.
|
||||||
|
Flags byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*Emote) ID() uint32 {
|
||||||
|
return packet.IDEmote
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *Emote) Marshal(io protocol.IO) {
|
||||||
|
io.Varuint64(&pk.EntityRuntimeID)
|
||||||
|
io.String(&pk.EmoteID)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID729) {
|
||||||
|
io.Varuint32(&pk.EmoteLength)
|
||||||
|
}
|
||||||
|
io.String(&pk.XUID)
|
||||||
|
io.String(&pk.PlatformID)
|
||||||
|
io.Uint8(&pk.Flags)
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ type InventoryContent struct {
|
|||||||
// the inventory window updated.
|
// the inventory window updated.
|
||||||
Content []protocol.ItemInstance
|
Content []protocol.ItemInstance
|
||||||
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
||||||
Container protocol.FullContainerName
|
Container proto.FullContainerName
|
||||||
// DynamicContainerSize ...
|
// DynamicContainerSize ...
|
||||||
DynamicContainerSize uint32
|
DynamicContainerSize uint32
|
||||||
// StorageItem is the item that is acting as the storage container for the inventory. If the inventory is
|
// StorageItem is the item that is acting as the storage container for the inventory. If the inventory is
|
||||||
@@ -34,7 +34,9 @@ func (*InventoryContent) ID() uint32 {
|
|||||||
func (pk *InventoryContent) Marshal(io protocol.IO) {
|
func (pk *InventoryContent) Marshal(io protocol.IO) {
|
||||||
io.Varuint32(&pk.WindowID)
|
io.Varuint32(&pk.WindowID)
|
||||||
protocol.FuncSlice(io, &pk.Content, io.ItemInstance)
|
protocol.FuncSlice(io, &pk.Content, io.ItemInstance)
|
||||||
protocol.Single(io, &pk.Container)
|
if proto.IsProtoGTE(io, proto.ID729) {
|
||||||
|
protocol.Single(io, &pk.Container)
|
||||||
|
}
|
||||||
if proto.IsProtoGTE(io, proto.ID748) {
|
if proto.IsProtoGTE(io, proto.ID748) {
|
||||||
io.ItemInstance(&pk.StorageItem)
|
io.ItemInstance(&pk.StorageItem)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type InventorySlot struct {
|
|||||||
// index.
|
// index.
|
||||||
Slot uint32
|
Slot uint32
|
||||||
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
||||||
Container protocol.FullContainerName
|
Container proto.FullContainerName
|
||||||
// DynamicContainerSize ...
|
// DynamicContainerSize ...
|
||||||
DynamicContainerSize uint32
|
DynamicContainerSize uint32
|
||||||
// StorageItem is the item that is acting as the storage container for the inventory. If the inventory is
|
// StorageItem is the item that is acting as the storage container for the inventory. If the inventory is
|
||||||
@@ -37,7 +37,9 @@ func (*InventorySlot) ID() uint32 {
|
|||||||
func (pk *InventorySlot) Marshal(io protocol.IO) {
|
func (pk *InventorySlot) Marshal(io protocol.IO) {
|
||||||
io.Varuint32(&pk.WindowID)
|
io.Varuint32(&pk.WindowID)
|
||||||
io.Varuint32(&pk.Slot)
|
io.Varuint32(&pk.Slot)
|
||||||
protocol.Single(io, &pk.Container)
|
if proto.IsProtoGTE(io, proto.ID729) {
|
||||||
|
protocol.Single(io, &pk.Container)
|
||||||
|
}
|
||||||
if proto.IsProtoGTE(io, proto.ID748) {
|
if proto.IsProtoGTE(io, proto.ID748) {
|
||||||
io.ItemInstance(&pk.StorageItem)
|
io.ItemInstance(&pk.StorageItem)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ type ResourcePacksInfo struct {
|
|||||||
// WorldTemplateVersion is the version of the world template that has been used to generate the world. If
|
// WorldTemplateVersion is the version of the world template that has been used to generate the world. If
|
||||||
// the world was not generated from a template, this field is empty.
|
// the world was not generated from a template, this field is empty.
|
||||||
WorldTemplateVersion string
|
WorldTemplateVersion string
|
||||||
|
// ForcingServerPacks ...
|
||||||
|
ForcingServerPacks bool
|
||||||
|
// BehaviourPacks ...
|
||||||
|
BehaviourPacks []proto.BehaviourPackInfo
|
||||||
// TexturePacks is a list of texture packs that the client needs to download before joining the server.
|
// TexturePacks is a list of texture packs that the client needs to download before joining the server.
|
||||||
// The order of these texture packs is not relevant in this packet. It is however important in the
|
// The order of these texture packs is not relevant in this packet. It is however important in the
|
||||||
// ResourcePackStack packet.
|
// ResourcePackStack packet.
|
||||||
@@ -49,6 +53,12 @@ func (pk *ResourcePacksInfo) Marshal(io protocol.IO) {
|
|||||||
io.UUID(&pk.WorldTemplateUUID)
|
io.UUID(&pk.WorldTemplateUUID)
|
||||||
io.String(&pk.WorldTemplateVersion)
|
io.String(&pk.WorldTemplateVersion)
|
||||||
}
|
}
|
||||||
|
if proto.IsProtoLT(io, proto.ID729) {
|
||||||
|
io.Bool(&pk.ForcingServerPacks)
|
||||||
|
protocol.SliceUint16Length(io, &pk.BehaviourPacks)
|
||||||
|
} else {
|
||||||
|
proto.EmptySlice(io, &pk.BehaviourPacks)
|
||||||
|
}
|
||||||
protocol.SliceUint16Length(io, &pk.TexturePacks)
|
protocol.SliceUint16Length(io, &pk.TexturePacks)
|
||||||
if proto.IsProtoLT(io, proto.ID748) {
|
if proto.IsProtoLT(io, proto.ID748) {
|
||||||
protocol.Slice(io, &pk.PackURLs)
|
protocol.Slice(io, &pk.PackURLs)
|
||||||
|
|||||||
31
legacyver/legacypacket/transfer.go
Normal file
31
legacyver/legacypacket/transfer.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transfer is sent by the server to transfer a player from the current server to another. Doing so will
|
||||||
|
// fully disconnect the client, bring it back to the main menu and make it connect to the next server.
|
||||||
|
type Transfer struct {
|
||||||
|
// Address is the address of the new server, which might be either a hostname or an actual IP address.
|
||||||
|
Address string
|
||||||
|
// Port is the UDP port of the new server.
|
||||||
|
Port uint16
|
||||||
|
// ReloadWorld currently has an unknown usage.
|
||||||
|
ReloadWorld bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*Transfer) ID() uint32 {
|
||||||
|
return packet.IDTransfer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *Transfer) Marshal(io protocol.IO) {
|
||||||
|
io.String(&pk.Address)
|
||||||
|
io.Uint16(&pk.Port)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID729) {
|
||||||
|
io.Bool(&pk.ReloadWorld)
|
||||||
|
}
|
||||||
|
}
|
||||||
32
legacyver/legacypacket/update_attributes.go
Normal file
32
legacyver/legacypacket/update_attributes.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateAttributes is sent by the server to update an amount of attributes of any entity in the world. These
|
||||||
|
// attributes include ones such as the health or the movement speed of the entity.
|
||||||
|
type UpdateAttributes struct {
|
||||||
|
// EntityRuntimeID is the runtime ID of the entity. The runtime ID is unique for each world session, and
|
||||||
|
// entities are generally identified in packets using this runtime ID.
|
||||||
|
EntityRuntimeID uint64
|
||||||
|
// Attributes is a slice of new attributes that the entity gets. It includes attributes such as its
|
||||||
|
// health, movement speed, etc. Note that only changed attributes have to be sent in this packet. It is
|
||||||
|
// not required to send attributes that did not have their values changed.
|
||||||
|
Attributes []proto.Attribute
|
||||||
|
// Tick is the server tick at which the packet was sent. It is used in relation to CorrectPlayerMovePrediction.
|
||||||
|
Tick uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*UpdateAttributes) ID() uint32 {
|
||||||
|
return packet.IDUpdateAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *UpdateAttributes) Marshal(io protocol.IO) {
|
||||||
|
io.Varuint64(&pk.EntityRuntimeID)
|
||||||
|
protocol.Slice(io, &pk.Attributes)
|
||||||
|
io.Varuint64(&pk.Tick)
|
||||||
|
}
|
||||||
58
legacyver/proto/attribute.go
Normal file
58
legacyver/proto/attribute.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package proto
|
||||||
|
|
||||||
|
import "github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
|
||||||
|
// Attribute is an entity attribute, that holds specific data such as the health of the entity. Each attribute
|
||||||
|
// holds a default value, maximum and minimum value, name and its current value.
|
||||||
|
type Attribute struct {
|
||||||
|
protocol.AttributeValue
|
||||||
|
// DefaultMin is the default minimum value of the attribute. It's not clear why this field must be sent to
|
||||||
|
// the client, but it is required regardless.
|
||||||
|
DefaultMin float32
|
||||||
|
// DefaultMax is the default maximum value of the attribute. It's not clear why this field must be sent to
|
||||||
|
// the client, but it is required regardless.
|
||||||
|
DefaultMax float32
|
||||||
|
// Default is the default value of the attribute. It's not clear why this field must be sent to the
|
||||||
|
// client, but it is required regardless.
|
||||||
|
Default float32
|
||||||
|
// Modifiers is a slice of AttributeModifiers that are applied to the attribute.
|
||||||
|
Modifiers []protocol.AttributeModifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Attribute) FromLatest(v protocol.Attribute) Attribute {
|
||||||
|
x.AttributeValue = v.AttributeValue
|
||||||
|
x.DefaultMin = v.DefaultMin
|
||||||
|
x.DefaultMax = v.DefaultMax
|
||||||
|
x.Default = v.Default
|
||||||
|
x.Modifiers = v.Modifiers
|
||||||
|
return *x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Attribute) ToLatest() protocol.Attribute {
|
||||||
|
return protocol.Attribute{
|
||||||
|
AttributeValue: protocol.AttributeValue{
|
||||||
|
Name: x.Name,
|
||||||
|
Value: x.Value,
|
||||||
|
Max: x.Max,
|
||||||
|
Min: x.Min,
|
||||||
|
},
|
||||||
|
DefaultMin: x.DefaultMin,
|
||||||
|
DefaultMax: x.DefaultMax,
|
||||||
|
Default: x.Default,
|
||||||
|
Modifiers: x.Modifiers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal encodes/decodes an Attribute.
|
||||||
|
func (x *Attribute) Marshal(r protocol.IO) {
|
||||||
|
r.Float32(&x.Min)
|
||||||
|
r.Float32(&x.Max)
|
||||||
|
r.Float32(&x.Value)
|
||||||
|
if IsProtoGTE(r, ID729) {
|
||||||
|
r.Float32(&x.DefaultMin)
|
||||||
|
r.Float32(&x.DefaultMax)
|
||||||
|
}
|
||||||
|
r.Float32(&x.Default)
|
||||||
|
r.String(&x.Name)
|
||||||
|
protocol.Slice(r, &x.Modifiers)
|
||||||
|
}
|
||||||
@@ -53,7 +53,7 @@ type CameraPreset struct {
|
|||||||
AimAssist protocol.Optional[protocol.CameraPresetAimAssist]
|
AimAssist protocol.Optional[protocol.CameraPresetAimAssist]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) {
|
func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) CameraPreset {
|
||||||
x.Name = cp.Name
|
x.Name = cp.Name
|
||||||
x.Parent = cp.Parent
|
x.Parent = cp.Parent
|
||||||
x.PosX = cp.PosX
|
x.PosX = cp.PosX
|
||||||
@@ -74,6 +74,7 @@ func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) {
|
|||||||
x.PlayerEffects = cp.PlayerEffects
|
x.PlayerEffects = cp.PlayerEffects
|
||||||
x.AlignTargetAndCameraForward = cp.AlignTargetAndCameraForward
|
x.AlignTargetAndCameraForward = cp.AlignTargetAndCameraForward
|
||||||
x.AimAssist = cp.AimAssist
|
x.AimAssist = cp.AimAssist
|
||||||
|
return *x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CameraPreset) ToLatest() protocol.CameraPreset {
|
func (x *CameraPreset) ToLatest() protocol.CameraPreset {
|
||||||
@@ -110,8 +111,10 @@ func (x *CameraPreset) Marshal(r protocol.IO) {
|
|||||||
protocol.OptionalFunc(r, &x.PosZ, r.Float32)
|
protocol.OptionalFunc(r, &x.PosZ, r.Float32)
|
||||||
protocol.OptionalFunc(r, &x.RotX, r.Float32)
|
protocol.OptionalFunc(r, &x.RotX, r.Float32)
|
||||||
protocol.OptionalFunc(r, &x.RotY, r.Float32)
|
protocol.OptionalFunc(r, &x.RotY, r.Float32)
|
||||||
protocol.OptionalFunc(r, &x.RotationSpeed, r.Float32)
|
if IsProtoGTE(r, ID729) {
|
||||||
protocol.OptionalFunc(r, &x.SnapToTarget, r.Bool)
|
protocol.OptionalFunc(r, &x.RotationSpeed, r.Float32)
|
||||||
|
protocol.OptionalFunc(r, &x.SnapToTarget, r.Bool)
|
||||||
|
}
|
||||||
if IsProtoGTE(r, ID748) {
|
if IsProtoGTE(r, ID748) {
|
||||||
protocol.OptionalFunc(r, &x.HorizontalRotationLimit, r.Vec2)
|
protocol.OptionalFunc(r, &x.HorizontalRotationLimit, r.Vec2)
|
||||||
protocol.OptionalFunc(r, &x.VerticalRotationLimit, r.Vec2)
|
protocol.OptionalFunc(r, &x.VerticalRotationLimit, r.Vec2)
|
||||||
@@ -121,7 +124,9 @@ func (x *CameraPreset) Marshal(r protocol.IO) {
|
|||||||
protocol.OptionalFunc(r, &x.TrackingRadius, r.Float32)
|
protocol.OptionalFunc(r, &x.TrackingRadius, r.Float32)
|
||||||
}
|
}
|
||||||
protocol.OptionalFunc(r, &x.ViewOffset, r.Vec2)
|
protocol.OptionalFunc(r, &x.ViewOffset, r.Vec2)
|
||||||
protocol.OptionalFunc(r, &x.EntityOffset, r.Vec3)
|
if IsProtoGTE(r, ID729) {
|
||||||
|
protocol.OptionalFunc(r, &x.EntityOffset, r.Vec3)
|
||||||
|
}
|
||||||
protocol.OptionalFunc(r, &x.Radius, r.Float32)
|
protocol.OptionalFunc(r, &x.Radius, r.Float32)
|
||||||
protocol.OptionalFunc(r, &x.AudioListener, r.Uint8)
|
protocol.OptionalFunc(r, &x.AudioListener, r.Uint8)
|
||||||
protocol.OptionalFunc(r, &x.PlayerEffects, r.Bool)
|
protocol.OptionalFunc(r, &x.PlayerEffects, r.Bool)
|
||||||
|
|||||||
38
legacyver/proto/container.go
Normal file
38
legacyver/proto/container.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package proto
|
||||||
|
|
||||||
|
import "github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
|
||||||
|
// FullContainerName contains information required to identify a container in a StackRequestSlotInfo.
|
||||||
|
type FullContainerName struct {
|
||||||
|
// ContainerID is the ID of the container that the slot was in.
|
||||||
|
ContainerID byte
|
||||||
|
// DynamicContainerID is the ID of the container if it is dynamic. If the container is not dynamic, this
|
||||||
|
// field should be left empty. A non-optional value of 0 is assumed to be non-empty.
|
||||||
|
DynamicContainerID protocol.Optional[uint32]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FullContainerName) FromLatest(v protocol.FullContainerName) FullContainerName {
|
||||||
|
x.ContainerID = v.ContainerID
|
||||||
|
x.DynamicContainerID = v.DynamicContainerID
|
||||||
|
return *x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FullContainerName) ToLatest() protocol.FullContainerName {
|
||||||
|
return protocol.FullContainerName{
|
||||||
|
ContainerID: x.ContainerID,
|
||||||
|
DynamicContainerID: x.DynamicContainerID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FullContainerName) Marshal(r protocol.IO) {
|
||||||
|
r.Uint8(&x.ContainerID)
|
||||||
|
if IsProtoGTE(r, ID729) {
|
||||||
|
protocol.OptionalFunc(r, &x.DynamicContainerID, r.Uint32)
|
||||||
|
} else {
|
||||||
|
dynamicContainerID, _ := x.DynamicContainerID.Value()
|
||||||
|
r.Uint32(&dynamicContainerID)
|
||||||
|
if dynamicContainerID != 0 {
|
||||||
|
x.DynamicContainerID = protocol.Option(dynamicContainerID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,12 @@ package proto
|
|||||||
import "github.com/sandertv/gophertunnel/minecraft/protocol"
|
import "github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ID766 = 766
|
ID766 = 766 // v1.21.50
|
||||||
ID748 = 748
|
ID748 = 748 // v1.21.40
|
||||||
ID729 = 729
|
ID729 = 729 // v1.21.30
|
||||||
ID712 = 712
|
ID712 = 712 // v1.21.20
|
||||||
ID686 = 686
|
ID686 = 686 // v1.21.2
|
||||||
ID685 = 685
|
ID685 = 685 // v1.21.0
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsProtoGTE(io protocol.IO, proto int32) bool {
|
func IsProtoGTE(io protocol.IO, proto int32) bool {
|
||||||
|
|||||||
@@ -226,6 +226,32 @@ type ItemStackResponse struct {
|
|||||||
ContainerInfo []StackResponseContainerInfo
|
ContainerInfo []StackResponseContainerInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ItemStackResponse) FromLatest(y protocol.ItemStackResponse) ItemStackResponse {
|
||||||
|
ret := ItemStackResponse{
|
||||||
|
Status: y.Status,
|
||||||
|
RequestID: y.RequestID,
|
||||||
|
ContainerInfo: make([]StackResponseContainerInfo, len(y.ContainerInfo)),
|
||||||
|
}
|
||||||
|
for i, v := range y.ContainerInfo {
|
||||||
|
ret.ContainerInfo[i] = StackResponseContainerInfo{
|
||||||
|
Container: (&FullContainerName{}).FromLatest(v.Container),
|
||||||
|
SlotInfo: make([]StackResponseSlotInfo, len(v.SlotInfo)),
|
||||||
|
}
|
||||||
|
for j, w := range v.SlotInfo {
|
||||||
|
ret.ContainerInfo[i].SlotInfo[j] = StackResponseSlotInfo{
|
||||||
|
Slot: w.Slot,
|
||||||
|
HotbarSlot: w.HotbarSlot,
|
||||||
|
Count: w.Count,
|
||||||
|
StackNetworkID: w.StackNetworkID,
|
||||||
|
CustomName: w.CustomName,
|
||||||
|
FilteredCustomName: w.FilteredCustomName,
|
||||||
|
DurabilityCorrection: w.DurabilityCorrection,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func (x *ItemStackResponse) ToLatest() protocol.ItemStackResponse {
|
func (x *ItemStackResponse) ToLatest() protocol.ItemStackResponse {
|
||||||
ret := protocol.ItemStackResponse{
|
ret := protocol.ItemStackResponse{
|
||||||
Status: x.Status,
|
Status: x.Status,
|
||||||
@@ -234,7 +260,7 @@ func (x *ItemStackResponse) ToLatest() protocol.ItemStackResponse {
|
|||||||
}
|
}
|
||||||
for i, v := range x.ContainerInfo {
|
for i, v := range x.ContainerInfo {
|
||||||
ret.ContainerInfo[i] = protocol.StackResponseContainerInfo{
|
ret.ContainerInfo[i] = protocol.StackResponseContainerInfo{
|
||||||
Container: v.Container,
|
Container: v.Container.ToLatest(),
|
||||||
SlotInfo: make([]protocol.StackResponseSlotInfo, len(v.SlotInfo)),
|
SlotInfo: make([]protocol.StackResponseSlotInfo, len(v.SlotInfo)),
|
||||||
}
|
}
|
||||||
for j, w := range v.SlotInfo {
|
for j, w := range v.SlotInfo {
|
||||||
@@ -266,7 +292,7 @@ type StackResponseContainerInfo struct {
|
|||||||
// Container is the FullContainerName that describes the container that the slots that follow are in. For
|
// Container is the FullContainerName that describes the container that the slots that follow are in. For
|
||||||
// the main inventory, the ContainerID seems to be 0x1b. Fur the cursor, this value seems to be 0x3a. For
|
// the main inventory, the ContainerID seems to be 0x1b. Fur the cursor, this value seems to be 0x3a. For
|
||||||
// the crafting grid, this value seems to be 0x0d.
|
// the crafting grid, this value seems to be 0x0d.
|
||||||
Container protocol.FullContainerName
|
Container FullContainerName
|
||||||
// SlotInfo holds information on what item stack should be present in specific slots in the container.
|
// SlotInfo holds information on what item stack should be present in specific slots in the container.
|
||||||
SlotInfo []StackResponseSlotInfo
|
SlotInfo []StackResponseSlotInfo
|
||||||
}
|
}
|
||||||
@@ -635,7 +661,7 @@ func (a *CraftResultsDeprecatedStackRequestAction) Marshal(r protocol.IO) {
|
|||||||
// StackRequestSlotInfo holds information on a specific slot client-side.
|
// StackRequestSlotInfo holds information on a specific slot client-side.
|
||||||
type StackRequestSlotInfo struct {
|
type StackRequestSlotInfo struct {
|
||||||
// Container is the FullContainerName that describes the container that the slot is in.
|
// Container is the FullContainerName that describes the container that the slot is in.
|
||||||
Container protocol.FullContainerName
|
Container FullContainerName
|
||||||
// Slot is the index of the slot within the container with the ContainerID above.
|
// Slot is the index of the slot within the container with the ContainerID above.
|
||||||
Slot byte
|
Slot byte
|
||||||
// StackNetworkID is the unique stack ID that the client assumes to be present in this slot. The server
|
// StackNetworkID is the unique stack ID that the client assumes to be present in this slot. The server
|
||||||
|
|||||||
@@ -38,6 +38,20 @@ type TexturePackInfo struct {
|
|||||||
DownloadURL string
|
DownloadURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *TexturePackInfo) FromLatest(y protocol.TexturePackInfo) TexturePackInfo {
|
||||||
|
x.UUID = y.UUID
|
||||||
|
x.Version = y.Version
|
||||||
|
x.Size = y.Size
|
||||||
|
x.ContentKey = y.ContentKey
|
||||||
|
x.SubPackName = y.SubPackName
|
||||||
|
x.ContentIdentity = y.ContentIdentity
|
||||||
|
x.HasScripts = y.HasScripts
|
||||||
|
x.AddonPack = y.AddonPack
|
||||||
|
x.RTXEnabled = y.RTXEnabled
|
||||||
|
x.DownloadURL = y.DownloadURL
|
||||||
|
return *x
|
||||||
|
}
|
||||||
|
|
||||||
func (x *TexturePackInfo) ToLatest() protocol.TexturePackInfo {
|
func (x *TexturePackInfo) ToLatest() protocol.TexturePackInfo {
|
||||||
return protocol.TexturePackInfo{
|
return protocol.TexturePackInfo{
|
||||||
UUID: x.UUID,
|
UUID: x.UUID,
|
||||||
@@ -79,3 +93,42 @@ func (x *TexturePackInfo) Marshal(r protocol.IO) {
|
|||||||
r.String(&x.DownloadURL)
|
r.String(&x.DownloadURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BehaviourPackInfo represents a behaviour pack's info sent over network. It holds information about the
|
||||||
|
// behaviour pack such as its name, description and version.
|
||||||
|
type BehaviourPackInfo struct {
|
||||||
|
// UUID is the UUID of the behaviour pack. Each behaviour pack downloaded must have a different UUID in
|
||||||
|
// order for the client to be able to handle them properly.
|
||||||
|
UUID string
|
||||||
|
// Version is the version of the behaviour pack. The client will cache behaviour packs sent by the server as
|
||||||
|
// long as they carry the same version. Sending a behaviour pack with a different version than previously
|
||||||
|
// will force the client to re-download it.
|
||||||
|
Version string
|
||||||
|
// Size is the total size in bytes that the behaviour pack occupies. This is the size of the compressed
|
||||||
|
// archive (zip) of the behaviour pack.
|
||||||
|
Size uint64
|
||||||
|
// ContentKey is the key used to decrypt the behaviour pack if it is encrypted. This is generally the case
|
||||||
|
// for marketplace behaviour packs.
|
||||||
|
ContentKey string
|
||||||
|
// SubPackName ...
|
||||||
|
SubPackName string
|
||||||
|
// ContentIdentity ...
|
||||||
|
ContentIdentity string
|
||||||
|
// HasScripts specifies if the behaviour packs has any scripts in it. A client will only download the
|
||||||
|
// behaviour pack if it supports scripts, which, up to 1.11, only includes Windows 10.
|
||||||
|
HasScripts bool
|
||||||
|
// AddonPack specifies if the texture pack is from an addon.
|
||||||
|
AddonPack bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal encodes/decodes a BehaviourPackInfo.
|
||||||
|
func (x *BehaviourPackInfo) Marshal(r protocol.IO) {
|
||||||
|
r.String(&x.UUID)
|
||||||
|
r.String(&x.Version)
|
||||||
|
r.Uint64(&x.Size)
|
||||||
|
r.String(&x.ContentKey)
|
||||||
|
r.String(&x.SubPackName)
|
||||||
|
r.String(&x.ContentIdentity)
|
||||||
|
r.Bool(&x.HasScripts)
|
||||||
|
r.Bool(&x.AddonPack)
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packe
|
|||||||
return func() packet.Packet { return &legacypacket.CameraAimAssist{} }
|
return func() packet.Packet { return &legacypacket.CameraAimAssist{} }
|
||||||
case packet.IDCameraPresets:
|
case packet.IDCameraPresets:
|
||||||
return func() packet.Packet { return &legacypacket.CameraPresets{} }
|
return func() packet.Packet { return &legacypacket.CameraPresets{} }
|
||||||
|
case packet.IDContainerRegistryCleanup:
|
||||||
|
return func() packet.Packet { return &legacypacket.ContainerRegistryCleanup{} }
|
||||||
|
case packet.IDEmote:
|
||||||
|
return func() packet.Packet { return &legacypacket.Emote{} }
|
||||||
case packet.IDInventoryContent:
|
case packet.IDInventoryContent:
|
||||||
return func() packet.Packet { return &legacypacket.InventoryContent{} }
|
return func() packet.Packet { return &legacypacket.InventoryContent{} }
|
||||||
case packet.IDInventorySlot:
|
case packet.IDInventorySlot:
|
||||||
@@ -40,6 +44,10 @@ func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packe
|
|||||||
return func() packet.Packet { return &legacypacket.PlayerAuthInput{} }
|
return func() packet.Packet { return &legacypacket.PlayerAuthInput{} }
|
||||||
case packet.IDResourcePacksInfo:
|
case packet.IDResourcePacksInfo:
|
||||||
return func() packet.Packet { return &legacypacket.ResourcePacksInfo{} }
|
return func() packet.Packet { return &legacypacket.ResourcePacksInfo{} }
|
||||||
|
case packet.IDTransfer:
|
||||||
|
return func() packet.Packet { return &legacypacket.Transfer{} }
|
||||||
|
case packet.IDUpdateAttributes:
|
||||||
|
return func() packet.Packet { return &legacypacket.UpdateAttributes{} }
|
||||||
default:
|
default:
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
@@ -94,7 +102,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
case *packet.CameraPresets:
|
case *packet.CameraPresets:
|
||||||
presets := make([]proto.CameraPreset, len(pk.Presets))
|
presets := make([]proto.CameraPreset, len(pk.Presets))
|
||||||
for i, p := range pk.Presets {
|
for i, p := range pk.Presets {
|
||||||
presets[i].FromLatest(p)
|
presets[i] = (&proto.CameraPreset{}).FromLatest(p)
|
||||||
}
|
}
|
||||||
pks[pkIndex] = &legacypacket.CameraPresets{
|
pks[pkIndex] = &legacypacket.CameraPresets{
|
||||||
Presets: presets,
|
Presets: presets,
|
||||||
@@ -133,49 +141,14 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
case *packet.ItemStackResponse:
|
case *packet.ItemStackResponse:
|
||||||
responses := make([]proto.ItemStackResponse, len(pk.Responses))
|
responses := make([]proto.ItemStackResponse, len(pk.Responses))
|
||||||
for i, r := range pk.Responses {
|
for i, r := range pk.Responses {
|
||||||
containerInfo := make([]proto.StackResponseContainerInfo, len(r.ContainerInfo))
|
responses[i] = (&proto.ItemStackResponse{}).FromLatest(r)
|
||||||
for j, c := range r.ContainerInfo {
|
|
||||||
slotInfo := make([]proto.StackResponseSlotInfo, len(c.SlotInfo))
|
|
||||||
for k, s := range c.SlotInfo {
|
|
||||||
slotInfo[k] = proto.StackResponseSlotInfo{
|
|
||||||
Slot: s.Slot,
|
|
||||||
HotbarSlot: s.HotbarSlot,
|
|
||||||
Count: s.Count,
|
|
||||||
StackNetworkID: s.StackNetworkID,
|
|
||||||
CustomName: s.CustomName,
|
|
||||||
FilteredCustomName: s.FilteredCustomName,
|
|
||||||
DurabilityCorrection: s.DurabilityCorrection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
containerInfo[j] = proto.StackResponseContainerInfo{
|
|
||||||
Container: c.Container,
|
|
||||||
SlotInfo: slotInfo,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
responses[i] = proto.ItemStackResponse{
|
|
||||||
Status: r.Status,
|
|
||||||
RequestID: r.RequestID,
|
|
||||||
ContainerInfo: containerInfo,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pks[pkIndex] = &legacypacket.ItemStackResponse{Responses: responses}
|
pks[pkIndex] = &legacypacket.ItemStackResponse{Responses: responses}
|
||||||
case *packet.ResourcePacksInfo:
|
case *packet.ResourcePacksInfo:
|
||||||
texturePacks := make([]proto.TexturePackInfo, len(pk.TexturePacks))
|
texturePacks := make([]proto.TexturePackInfo, len(pk.TexturePacks))
|
||||||
packURLs := make([]protocol.PackURL, 0)
|
packURLs := make([]protocol.PackURL, 0)
|
||||||
for i, t := range pk.TexturePacks {
|
for i, t := range pk.TexturePacks {
|
||||||
texturePacks[i] = proto.TexturePackInfo{
|
texturePacks[i] = (&proto.TexturePackInfo{}).FromLatest(t)
|
||||||
UUID: t.UUID,
|
|
||||||
Version: t.Version,
|
|
||||||
Size: t.Size,
|
|
||||||
ContentKey: t.ContentKey,
|
|
||||||
SubPackName: t.SubPackName,
|
|
||||||
ContentIdentity: t.ContentIdentity,
|
|
||||||
HasScripts: t.HasScripts,
|
|
||||||
AddonPack: t.AddonPack,
|
|
||||||
RTXEnabled: t.RTXEnabled,
|
|
||||||
DownloadURL: t.DownloadURL,
|
|
||||||
}
|
|
||||||
if t.DownloadURL != "" {
|
if t.DownloadURL != "" {
|
||||||
packURLs = append(packURLs, protocol.PackURL{
|
packURLs = append(packURLs, protocol.PackURL{
|
||||||
UUIDVersion: t.UUID.String() + "_" + t.Version,
|
UUIDVersion: t.UUID.String() + "_" + t.Version,
|
||||||
@@ -196,7 +169,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
pks[pkIndex] = &legacypacket.InventorySlot{
|
pks[pkIndex] = &legacypacket.InventorySlot{
|
||||||
WindowID: pk.WindowID,
|
WindowID: pk.WindowID,
|
||||||
Slot: pk.Slot,
|
Slot: pk.Slot,
|
||||||
Container: pk.Container,
|
Container: (&proto.FullContainerName{}).FromLatest(pk.Container),
|
||||||
DynamicContainerSize: 0,
|
DynamicContainerSize: 0,
|
||||||
StorageItem: pk.StorageItem,
|
StorageItem: pk.StorageItem,
|
||||||
NewItem: pk.NewItem,
|
NewItem: pk.NewItem,
|
||||||
@@ -205,7 +178,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
pks[pkIndex] = &legacypacket.InventoryContent{
|
pks[pkIndex] = &legacypacket.InventoryContent{
|
||||||
WindowID: pk.WindowID,
|
WindowID: pk.WindowID,
|
||||||
Content: pk.Content,
|
Content: pk.Content,
|
||||||
Container: pk.Container,
|
Container: (&proto.FullContainerName{}).FromLatest(pk.Container),
|
||||||
DynamicContainerSize: 0,
|
DynamicContainerSize: 0,
|
||||||
StorageItem: pk.StorageItem,
|
StorageItem: pk.StorageItem,
|
||||||
}
|
}
|
||||||
@@ -227,6 +200,39 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
TargetMode: pk.TargetMode,
|
TargetMode: pk.TargetMode,
|
||||||
Action: pk.Action,
|
Action: pk.Action,
|
||||||
}
|
}
|
||||||
|
case *packet.UpdateAttributes:
|
||||||
|
attributes := make([]proto.Attribute, len(pk.Attributes))
|
||||||
|
for i, a := range pk.Attributes {
|
||||||
|
attributes[i] = (&proto.Attribute{}).FromLatest(a)
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &legacypacket.UpdateAttributes{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
Attributes: attributes,
|
||||||
|
Tick: pk.Tick,
|
||||||
|
}
|
||||||
|
case *packet.ContainerRegistryCleanup:
|
||||||
|
removedContainers := make([]proto.FullContainerName, len(pk.RemovedContainers))
|
||||||
|
for i, c := range pk.RemovedContainers {
|
||||||
|
removedContainers[i] = (&proto.FullContainerName{}).FromLatest(c)
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &legacypacket.ContainerRegistryCleanup{
|
||||||
|
RemovedContainers: removedContainers,
|
||||||
|
}
|
||||||
|
case *packet.Emote:
|
||||||
|
pks[pkIndex] = &legacypacket.Emote{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
EmoteLength: pk.EmoteLength,
|
||||||
|
EmoteID: pk.EmoteID,
|
||||||
|
XUID: pk.XUID,
|
||||||
|
PlatformID: pk.PlatformID,
|
||||||
|
Flags: pk.Flags,
|
||||||
|
}
|
||||||
|
case *packet.Transfer:
|
||||||
|
pks[pkIndex] = &legacypacket.Transfer{
|
||||||
|
Address: pk.Address,
|
||||||
|
Port: pk.Port,
|
||||||
|
ReloadWorld: pk.ReloadWorld,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +310,7 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
|||||||
pks[pkIndex] = &packet.InventorySlot{
|
pks[pkIndex] = &packet.InventorySlot{
|
||||||
WindowID: pk.WindowID,
|
WindowID: pk.WindowID,
|
||||||
Slot: pk.Slot,
|
Slot: pk.Slot,
|
||||||
Container: pk.Container,
|
Container: pk.Container.ToLatest(),
|
||||||
StorageItem: pk.StorageItem,
|
StorageItem: pk.StorageItem,
|
||||||
NewItem: pk.NewItem,
|
NewItem: pk.NewItem,
|
||||||
}
|
}
|
||||||
@@ -312,7 +318,7 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
|||||||
pks[pkIndex] = &packet.InventoryContent{
|
pks[pkIndex] = &packet.InventoryContent{
|
||||||
WindowID: pk.WindowID,
|
WindowID: pk.WindowID,
|
||||||
Content: pk.Content,
|
Content: pk.Content,
|
||||||
Container: pk.Container,
|
Container: pk.Container.ToLatest(),
|
||||||
StorageItem: pk.StorageItem,
|
StorageItem: pk.StorageItem,
|
||||||
}
|
}
|
||||||
case *legacypacket.MobEffect:
|
case *legacypacket.MobEffect:
|
||||||
@@ -333,6 +339,39 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
|||||||
TargetMode: pk.TargetMode,
|
TargetMode: pk.TargetMode,
|
||||||
Action: pk.Action,
|
Action: pk.Action,
|
||||||
}
|
}
|
||||||
|
case *legacypacket.UpdateAttributes:
|
||||||
|
attributes := make([]protocol.Attribute, len(pk.Attributes))
|
||||||
|
for i, a := range pk.Attributes {
|
||||||
|
attributes[i] = a.ToLatest()
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &packet.UpdateAttributes{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
Attributes: attributes,
|
||||||
|
Tick: pk.Tick,
|
||||||
|
}
|
||||||
|
case *legacypacket.ContainerRegistryCleanup:
|
||||||
|
removedContainers := make([]protocol.FullContainerName, len(pk.RemovedContainers))
|
||||||
|
for i, c := range pk.RemovedContainers {
|
||||||
|
removedContainers[i] = c.ToLatest()
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &packet.ContainerRegistryCleanup{
|
||||||
|
RemovedContainers: removedContainers,
|
||||||
|
}
|
||||||
|
case *legacypacket.Emote:
|
||||||
|
pks[pkIndex] = &packet.Emote{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
EmoteLength: pk.EmoteLength,
|
||||||
|
EmoteID: pk.EmoteID,
|
||||||
|
XUID: pk.XUID,
|
||||||
|
PlatformID: pk.PlatformID,
|
||||||
|
Flags: pk.Flags,
|
||||||
|
}
|
||||||
|
case *legacypacket.Transfer:
|
||||||
|
pks[pkIndex] = &packet.Transfer{
|
||||||
|
Address: pk.Address,
|
||||||
|
Port: pk.Port,
|
||||||
|
ReloadWorld: pk.ReloadWorld,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pks
|
return pks
|
||||||
|
|||||||
36
legacyver/v712.go
Normal file
36
legacyver/v712.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package legacyver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/akmalfairuz/legacy-version/internal/chunk"
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/akmalfairuz/legacy-version/mapping"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ItemVersion712 ...
|
||||||
|
ItemVersion712 = 201
|
||||||
|
// BlockVersion712 ...
|
||||||
|
BlockVersion712 int32 = (1 << 24) | (21 << 16) | (20 << 8)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed data/item_runtime_ids_712.nbt
|
||||||
|
itemRuntimeIDData712 []byte
|
||||||
|
//go:embed data/required_item_list_712.json
|
||||||
|
requiredItemList712 []byte
|
||||||
|
//go:embed data/block_states_712.nbt
|
||||||
|
blockStateData712 []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func New712(direct bool) *Protocol {
|
||||||
|
itemMapping := mapping.NewItemMapping(itemRuntimeIDData712, requiredItemList712, ItemVersion712, false)
|
||||||
|
blockMapping := mapping.NewBlockMapping(blockStateData712)
|
||||||
|
|
||||||
|
return &Protocol{
|
||||||
|
ver: "1.21.20",
|
||||||
|
id: proto.ID712,
|
||||||
|
blockTranslator: NewBlockTranslator(blockMapping, latestBlockMapping, chunk.NewNetworkPersistentEncoding(blockMapping, BlockVersion712), chunk.NewBlockPaletteEncoding(blockMapping, BlockVersion712), false),
|
||||||
|
itemTranslator: NewItemTranslator(itemMapping, itemMappingLatest, blockMapping, blockMappingLatest),
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user