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 | ✅ |
|
||||
| 748 | 1.21.40 | ✅ |
|
||||
| 729 | 1.21.30 | ✅ |
|
||||
| 712 | 1.21.20 | 🚧 |
|
||||
| 712 | 1.21.20 | ✅ |
|
||||
| 686 | 1.21.2 | 🚧 |
|
||||
| 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.
|
||||
Content []protocol.ItemInstance
|
||||
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
||||
Container protocol.FullContainerName
|
||||
Container proto.FullContainerName
|
||||
// DynamicContainerSize ...
|
||||
DynamicContainerSize uint32
|
||||
// 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) {
|
||||
io.Varuint32(&pk.WindowID)
|
||||
protocol.FuncSlice(io, &pk.Content, io.ItemInstance)
|
||||
if proto.IsProtoGTE(io, proto.ID729) {
|
||||
protocol.Single(io, &pk.Container)
|
||||
}
|
||||
if proto.IsProtoGTE(io, proto.ID748) {
|
||||
io.ItemInstance(&pk.StorageItem)
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@ type InventorySlot struct {
|
||||
// index.
|
||||
Slot uint32
|
||||
// Container is the protocol.FullContainerName that describes the container that the content is for.
|
||||
Container protocol.FullContainerName
|
||||
Container proto.FullContainerName
|
||||
// DynamicContainerSize ...
|
||||
DynamicContainerSize uint32
|
||||
// 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) {
|
||||
io.Varuint32(&pk.WindowID)
|
||||
io.Varuint32(&pk.Slot)
|
||||
if proto.IsProtoGTE(io, proto.ID729) {
|
||||
protocol.Single(io, &pk.Container)
|
||||
}
|
||||
if proto.IsProtoGTE(io, proto.ID748) {
|
||||
io.ItemInstance(&pk.StorageItem)
|
||||
} 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
|
||||
// the world was not generated from a template, this field is empty.
|
||||
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.
|
||||
// The order of these texture packs is not relevant in this packet. It is however important in the
|
||||
// ResourcePackStack packet.
|
||||
@@ -49,6 +53,12 @@ func (pk *ResourcePacksInfo) Marshal(io protocol.IO) {
|
||||
io.UUID(&pk.WorldTemplateUUID)
|
||||
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)
|
||||
if proto.IsProtoLT(io, proto.ID748) {
|
||||
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]
|
||||
}
|
||||
|
||||
func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) {
|
||||
func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) CameraPreset {
|
||||
x.Name = cp.Name
|
||||
x.Parent = cp.Parent
|
||||
x.PosX = cp.PosX
|
||||
@@ -74,6 +74,7 @@ func (x *CameraPreset) FromLatest(cp protocol.CameraPreset) {
|
||||
x.PlayerEffects = cp.PlayerEffects
|
||||
x.AlignTargetAndCameraForward = cp.AlignTargetAndCameraForward
|
||||
x.AimAssist = cp.AimAssist
|
||||
return *x
|
||||
}
|
||||
|
||||
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.RotX, r.Float32)
|
||||
protocol.OptionalFunc(r, &x.RotY, r.Float32)
|
||||
if IsProtoGTE(r, ID729) {
|
||||
protocol.OptionalFunc(r, &x.RotationSpeed, r.Float32)
|
||||
protocol.OptionalFunc(r, &x.SnapToTarget, r.Bool)
|
||||
}
|
||||
if IsProtoGTE(r, ID748) {
|
||||
protocol.OptionalFunc(r, &x.HorizontalRotationLimit, 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.ViewOffset, r.Vec2)
|
||||
if IsProtoGTE(r, ID729) {
|
||||
protocol.OptionalFunc(r, &x.EntityOffset, r.Vec3)
|
||||
}
|
||||
protocol.OptionalFunc(r, &x.Radius, r.Float32)
|
||||
protocol.OptionalFunc(r, &x.AudioListener, r.Uint8)
|
||||
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"
|
||||
|
||||
const (
|
||||
ID766 = 766
|
||||
ID748 = 748
|
||||
ID729 = 729
|
||||
ID712 = 712
|
||||
ID686 = 686
|
||||
ID685 = 685
|
||||
ID766 = 766 // v1.21.50
|
||||
ID748 = 748 // v1.21.40
|
||||
ID729 = 729 // v1.21.30
|
||||
ID712 = 712 // v1.21.20
|
||||
ID686 = 686 // v1.21.2
|
||||
ID685 = 685 // v1.21.0
|
||||
)
|
||||
|
||||
func IsProtoGTE(io protocol.IO, proto int32) bool {
|
||||
|
||||
@@ -226,6 +226,32 @@ type ItemStackResponse struct {
|
||||
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 {
|
||||
ret := protocol.ItemStackResponse{
|
||||
Status: x.Status,
|
||||
@@ -234,7 +260,7 @@ func (x *ItemStackResponse) ToLatest() protocol.ItemStackResponse {
|
||||
}
|
||||
for i, v := range x.ContainerInfo {
|
||||
ret.ContainerInfo[i] = protocol.StackResponseContainerInfo{
|
||||
Container: v.Container,
|
||||
Container: v.Container.ToLatest(),
|
||||
SlotInfo: make([]protocol.StackResponseSlotInfo, len(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
|
||||
// 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.
|
||||
Container protocol.FullContainerName
|
||||
Container FullContainerName
|
||||
// SlotInfo holds information on what item stack should be present in specific slots in the container.
|
||||
SlotInfo []StackResponseSlotInfo
|
||||
}
|
||||
@@ -635,7 +661,7 @@ func (a *CraftResultsDeprecatedStackRequestAction) Marshal(r protocol.IO) {
|
||||
// StackRequestSlotInfo holds information on a specific slot client-side.
|
||||
type StackRequestSlotInfo struct {
|
||||
// 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 byte
|
||||
// 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
|
||||
}
|
||||
|
||||
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 {
|
||||
return protocol.TexturePackInfo{
|
||||
UUID: x.UUID,
|
||||
@@ -79,3 +93,42 @@ func (x *TexturePackInfo) Marshal(r protocol.IO) {
|
||||
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{} }
|
||||
case packet.IDCameraPresets:
|
||||
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:
|
||||
return func() packet.Packet { return &legacypacket.InventoryContent{} }
|
||||
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{} }
|
||||
case packet.IDResourcePacksInfo:
|
||||
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:
|
||||
return cur
|
||||
}
|
||||
@@ -94,7 +102,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
||||
case *packet.CameraPresets:
|
||||
presets := make([]proto.CameraPreset, len(pk.Presets))
|
||||
for i, p := range pk.Presets {
|
||||
presets[i].FromLatest(p)
|
||||
presets[i] = (&proto.CameraPreset{}).FromLatest(p)
|
||||
}
|
||||
pks[pkIndex] = &legacypacket.CameraPresets{
|
||||
Presets: presets,
|
||||
@@ -133,49 +141,14 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
||||
case *packet.ItemStackResponse:
|
||||
responses := make([]proto.ItemStackResponse, len(pk.Responses))
|
||||
for i, r := range pk.Responses {
|
||||
containerInfo := make([]proto.StackResponseContainerInfo, len(r.ContainerInfo))
|
||||
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,
|
||||
}
|
||||
responses[i] = (&proto.ItemStackResponse{}).FromLatest(r)
|
||||
}
|
||||
pks[pkIndex] = &legacypacket.ItemStackResponse{Responses: responses}
|
||||
case *packet.ResourcePacksInfo:
|
||||
texturePacks := make([]proto.TexturePackInfo, len(pk.TexturePacks))
|
||||
packURLs := make([]protocol.PackURL, 0)
|
||||
for i, t := range pk.TexturePacks {
|
||||
texturePacks[i] = proto.TexturePackInfo{
|
||||
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,
|
||||
}
|
||||
texturePacks[i] = (&proto.TexturePackInfo{}).FromLatest(t)
|
||||
if t.DownloadURL != "" {
|
||||
packURLs = append(packURLs, protocol.PackURL{
|
||||
UUIDVersion: t.UUID.String() + "_" + t.Version,
|
||||
@@ -196,7 +169,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
||||
pks[pkIndex] = &legacypacket.InventorySlot{
|
||||
WindowID: pk.WindowID,
|
||||
Slot: pk.Slot,
|
||||
Container: pk.Container,
|
||||
Container: (&proto.FullContainerName{}).FromLatest(pk.Container),
|
||||
DynamicContainerSize: 0,
|
||||
StorageItem: pk.StorageItem,
|
||||
NewItem: pk.NewItem,
|
||||
@@ -205,7 +178,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
||||
pks[pkIndex] = &legacypacket.InventoryContent{
|
||||
WindowID: pk.WindowID,
|
||||
Content: pk.Content,
|
||||
Container: pk.Container,
|
||||
Container: (&proto.FullContainerName{}).FromLatest(pk.Container),
|
||||
DynamicContainerSize: 0,
|
||||
StorageItem: pk.StorageItem,
|
||||
}
|
||||
@@ -227,6 +200,39 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
||||
TargetMode: pk.TargetMode,
|
||||
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{
|
||||
WindowID: pk.WindowID,
|
||||
Slot: pk.Slot,
|
||||
Container: pk.Container,
|
||||
Container: pk.Container.ToLatest(),
|
||||
StorageItem: pk.StorageItem,
|
||||
NewItem: pk.NewItem,
|
||||
}
|
||||
@@ -312,7 +318,7 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
||||
pks[pkIndex] = &packet.InventoryContent{
|
||||
WindowID: pk.WindowID,
|
||||
Content: pk.Content,
|
||||
Container: pk.Container,
|
||||
Container: pk.Container.ToLatest(),
|
||||
StorageItem: pk.StorageItem,
|
||||
}
|
||||
case *legacypacket.MobEffect:
|
||||
@@ -333,6 +339,39 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
||||
TargetMode: pk.TargetMode,
|
||||
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
|
||||
|
||||
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