Skip to content

Commit

Permalink
minecraft/protocol: Support 1.21.30
Browse files Browse the repository at this point in the history
  • Loading branch information
TwistedAsylumMC committed Sep 18, 2024
1 parent 664db0b commit 500a41a
Show file tree
Hide file tree
Showing 17 changed files with 119 additions and 99 deletions.
38 changes: 1 addition & 37 deletions minecraft/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,19 +774,6 @@ func (conn *Conn) handleClientToServerHandshake() error {
URL: pack.DownloadURL(),
})
}

// If it has behaviours, add it to the behaviour pack list. If not, we add it to the texture packs
// list.
if pack.HasBehaviours() {
behaviourPack := protocol.BehaviourPackInfo{UUID: pack.UUID(), Version: pack.Version(), Size: uint64(pack.Len())}
if pack.HasScripts() {
// One of the resource packs has scripts, so we set HasScripts in the packet to true.
pk.HasScripts = true
behaviourPack.HasScripts = true
}
pk.BehaviourPacks = append(pk.BehaviourPacks, behaviourPack)
continue
}
texturePack := protocol.TexturePackInfo{UUID: pack.UUID(), Version: pack.Version(), Size: uint64(pack.Len())}
if pack.Encrypted() {
texturePack.ContentKey = pack.ContentKey()
Expand Down Expand Up @@ -860,7 +847,7 @@ func (conn *Conn) handleClientCacheStatus(pk *packet.ClientCacheStatus) error {
func (conn *Conn) handleResourcePacksInfo(pk *packet.ResourcePacksInfo) error {
// First create a new resource pack queue with the information in the packet so we can download them
// properly later.
totalPacks := len(pk.TexturePacks) + len(pk.BehaviourPacks)
totalPacks := len(pk.TexturePacks)
conn.packQueue = &resourcePackQueue{
packAmount: totalPacks,
downloadingPacks: make(map[string]downloadingPack),
Expand Down Expand Up @@ -891,29 +878,6 @@ func (conn *Conn) handleResourcePacksInfo(pk *packet.ResourcePacksInfo) error {
contentKey: pack.ContentKey,
}
}
for index, pack := range pk.BehaviourPacks {
if _, ok := conn.packQueue.downloadingPacks[pack.UUID]; ok {
conn.log.Printf("handle ResourcePacksInfo: duplicate behaviour pack (UUID=%v)\n", pack.UUID)
conn.packQueue.packAmount--
continue
}
if conn.downloadResourcePack != nil && !conn.downloadResourcePack(uuid.MustParse(pack.UUID), pack.Version, index, totalPacks) {
conn.ignoredResourcePacks = append(conn.ignoredResourcePacks, exemptedResourcePack{
uuid: pack.UUID,
version: pack.Version,
})
conn.packQueue.packAmount--
continue
}
// This UUID_Version is a hack Mojang put in place.
packsToDownload = append(packsToDownload, pack.UUID+"_"+pack.Version)
conn.packQueue.downloadingPacks[pack.UUID] = downloadingPack{
size: pack.Size,
buf: bytes.NewBuffer(make([]byte, 0, pack.Size)),
newFrag: make(chan []byte),
contentKey: pack.ContentKey,
}
}

if len(packsToDownload) != 0 {
conn.expect(packet.IDResourcePackDataInfo, packet.IDResourcePackChunkData)
Expand Down
8 changes: 8 additions & 0 deletions minecraft/protocol/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func (x *AttributeValue) Marshal(r IO) {
// holds a default value, maximum and minimum value, name and its current value.
type Attribute struct {
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
Expand All @@ -51,6 +57,8 @@ func (x *Attribute) Marshal(r IO) {
r.Float32(&x.Min)
r.Float32(&x.Max)
r.Float32(&x.Value)
r.Float32(&x.DefaultMin)
r.Float32(&x.DefaultMax)
r.Float32(&x.Default)
r.String(&x.Name)
Slice(r, &x.Modifiers)
Expand Down
9 changes: 9 additions & 0 deletions minecraft/protocol/camera.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,15 @@ type CameraPreset struct {
RotX Optional[float32]
// RotY is the default yaw of the camera.
RotY Optional[float32]
// RotationSpeed is the speed at which the camera should rotate.
RotationSpeed Optional[float32]
// SnapToTarget determines whether the camera should snap to the target entity or not.
SnapToTarget Optional[bool]
// ViewOffset is only used in a follow_orbit camera and controls an offset based on a pivot point to the
// player, causing it to be shifted in a certain direction.
ViewOffset Optional[mgl32.Vec2]
// EntityOffset controls the offset from the entity that the camera should be rendered at.
EntityOffset Optional[mgl32.Vec3]
// Radius is only used in a follow_orbit camera and controls how far away from the player the camera should
// be rendered.
Radius Optional[float32]
Expand All @@ -174,7 +180,10 @@ func (x *CameraPreset) Marshal(r IO) {
OptionalFunc(r, &x.PosZ, r.Float32)
OptionalFunc(r, &x.RotX, r.Float32)
OptionalFunc(r, &x.RotY, r.Float32)
OptionalFunc(r, &x.RotationSpeed, r.Float32)
OptionalFunc(r, &x.SnapToTarget, r.Bool)
OptionalFunc(r, &x.ViewOffset, r.Vec2)
OptionalFunc(r, &x.EntityOffset, r.Vec3)
OptionalFunc(r, &x.Radius, r.Float32)
OptionalFunc(r, &x.AudioListener, r.Uint8)
OptionalFunc(r, &x.PlayerEffects, r.Bool)
Expand Down
8 changes: 4 additions & 4 deletions minecraft/protocol/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ const (
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 is
// set to 0.
DynamicContainerID uint32
// 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 Optional[uint32]
}

func (x *FullContainerName) Marshal(r IO) {
r.Uint8(&x.ContainerID)
r.Uint32(&x.DynamicContainerID)
OptionalFunc(r, &x.DynamicContainerID, r.Uint32)
}
4 changes: 2 additions & 2 deletions minecraft/protocol/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package protocol

const (
// CurrentProtocol is the current protocol version for the version below.
CurrentProtocol = 712
CurrentProtocol = 729
// CurrentVersion is the current version of Minecraft as supported by the `packet` package.
CurrentVersion = "1.21.20"
CurrentVersion = "1.21.30"
)
43 changes: 43 additions & 0 deletions minecraft/protocol/packet/camera_aim_assist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package packet

import (
"github.com/go-gl/mathgl/mgl32"
"github.com/sandertv/gophertunnel/minecraft/protocol"
)

const (
CameraAimAssistActionSet = iota
CameraAimAssistActionClear
)

const (
CameraAimAssistTargetModeAngle = iota
CameraAimAssistTargetModeDistance
)

// CameraAimAssist is sent by the server to the client to set up aim assist for the client's camera.
type CameraAimAssist struct {
// ViewAngle is the angle that the camera should aim at, if TargetMode is set to
// CameraAimAssistTargetModeAngle.
ViewAngle mgl32.Vec2
// Distance is the distance that the camera should keep from the target, if TargetMode is set to
// CameraAimAssistTargetModeDistance.
Distance float32
// TargetMode is the mode that the camera should use to aim at the target. This is one of the constants
// above.
TargetMode byte
// Action is the action that should be performed with the aim assist. This is one of the constants above.
Action byte
}

// ID ...
func (*CameraAimAssist) ID() uint32 {
return IDCameraAimAssist
}

func (pk *CameraAimAssist) Marshal(io protocol.IO) {
io.Vec2(&pk.ViewAngle)
io.Float32(&pk.Distance)
io.Uint8(&pk.TargetMode)
io.Uint8(&pk.Action)
}
22 changes: 22 additions & 0 deletions minecraft/protocol/packet/container_registry_cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package packet

import (
"github.com/sandertv/gophertunnel/minecraft/protocol"
)

// 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 []protocol.FullContainerName
}

// ID ...
func (*ContainerRegistryCleanup) ID() uint32 {
return IDContainerRegistryCleanup
}

func (pk *ContainerRegistryCleanup) Marshal(io protocol.IO) {
protocol.Slice(io, &pk.RemovedContainers)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/emote.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ 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
Expand All @@ -36,6 +38,7 @@ func (*Emote) ID() uint32 {
func (pk *Emote) Marshal(io protocol.IO) {
io.Varuint64(&pk.EntityRuntimeID)
io.String(&pk.EmoteID)
io.Varuint32(&pk.EmoteLength)
io.String(&pk.XUID)
io.String(&pk.PlatformID)
io.Uint8(&pk.Flags)
Expand Down
2 changes: 2 additions & 0 deletions minecraft/protocol/packet/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,6 @@ const (
IDJigsawStructureData
IDCurrentStructureFeature
IDServerBoundDiagnostics
IDCameraAimAssist
IDContainerRegistryCleanup
)
10 changes: 6 additions & 4 deletions minecraft/protocol/packet/inventory_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ type InventoryContent struct {
// Content is the new content of the inventory. The length of this slice must be equal to the full size of
// the inventory window updated.
Content []protocol.ItemInstance
// DynamicWindowID is the ID of the window if it is dynamic. If the window is not dynamic, this field is
// set to 0.
DynamicWindowID uint32
// Container is the protocol.FullContainerName that describes the container that the content is for.
Container protocol.FullContainerName
// DynamicContainerSize is the size of the container, if the container is dynamic.
DynamicContainerSize uint32
}

// ID ...
Expand All @@ -27,5 +28,6 @@ func (*InventoryContent) ID() uint32 {
func (pk *InventoryContent) Marshal(io protocol.IO) {
io.Varuint32(&pk.WindowID)
protocol.FuncSlice(io, &pk.Content, io.ItemInstance)
io.Varuint32(&pk.DynamicWindowID)
protocol.Single(io, &pk.Container)
io.Varuint32(&pk.DynamicContainerSize)
}
10 changes: 6 additions & 4 deletions minecraft/protocol/packet/inventory_slot.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ type InventorySlot struct {
// Slot is the index of the slot that the packet modifies. The new item will be set to the slot at this
// index.
Slot uint32
// DynamicWindowID is the ID of the window if it is dynamic. If the window is not dynamic, this field is
// set to 0.
DynamicWindowID uint32
// Container is the protocol.FullContainerName that describes the container that the content is for.
Container protocol.FullContainerName
// DynamicContainerSize is the size of the container, if the container is dynamic.
DynamicContainerSize uint32
// NewItem is the item to be put in the slot at Slot. It will overwrite any item that may currently
// be present in that slot.
NewItem protocol.ItemInstance
Expand All @@ -30,6 +31,7 @@ func (*InventorySlot) ID() uint32 {
func (pk *InventorySlot) Marshal(io protocol.IO) {
io.Varuint32(&pk.WindowID)
io.Varuint32(&pk.Slot)
io.Varuint32(&pk.DynamicWindowID)
protocol.Single(io, &pk.Container)
io.Varuint32(&pk.DynamicContainerSize)
io.ItemInstance(&pk.NewItem)
}
2 changes: 2 additions & 0 deletions minecraft/protocol/packet/level_sound_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ const (
SoundEventRecordCreatorMusicBox
SoundEventRecordPrecipice
SoundEventVaultRejectRewardedPlayer
SoundEventImitateDrowned
SoundEventBundleInsertFailed
)

// LevelSoundEvent is sent by the server to make any kind of built-in sound heard to a player. It is sent to,
Expand Down
8 changes: 6 additions & 2 deletions minecraft/protocol/packet/player_auth_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const (
InputFlagPaddlingLeft
InputFlagPaddlingRight
InputFlagBlockBreakingDelayEnabled
InputFlagHorizontalCollision
InputFlagVerticalCollision
InputFlagDownLeft
InputFlagDownRight
)

const (
Expand Down Expand Up @@ -161,11 +165,11 @@ func (pk *PlayerAuthInput) Marshal(io protocol.IO) {
if pk.InputData&InputFlagPerformItemStackRequest != 0 {
protocol.Single(io, &pk.ItemStackRequest)
}

if pk.InputData&InputFlagPerformBlockActions != 0 {
protocol.SliceVarint32Length(io, &pk.BlockActions)
}

if pk.InputData&InputFlagClientPredictedVehicle != 0 {
io.Vec2(&pk.VehicleRotation)
io.Varint64(&pk.ClientPredictedVehicle)
Expand Down
2 changes: 2 additions & 0 deletions minecraft/protocol/packet/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ func init() {
IDJigsawStructureData: func() Packet { return &JigsawStructureData{} },
IDCurrentStructureFeature: func() Packet { return &CurrentStructureFeature{} },
IDServerBoundDiagnostics: func() Packet { return &ServerBoundDiagnostics{} },
IDCameraAimAssist: func() Packet { return &CameraAimAssist{} },
IDContainerRegistryCleanup: func() Packet { return &ContainerRegistryCleanup{} },
}
for id, pk := range serverOriginating {
RegisterPacketFromServer(id, pk)
Expand Down
7 changes: 0 additions & 7 deletions minecraft/protocol/packet/resource_packs_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,10 @@ type ResourcePacksInfo struct {
// HasScripts specifies if any of the resource packs contain scripts in them. If set to true, only clients
// that support scripts will be able to download them.
HasScripts bool
// BehaviourPack is a list of behaviour packs that the client needs to download before joining the server.
// All of these behaviour packs will be applied together.
BehaviourPacks []protocol.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.
TexturePacks []protocol.TexturePackInfo
// ForcingServerPacks is currently an unclear field.
ForcingServerPacks bool
// PackURLs is a list of URLs that the client can use to download a resource pack instead of downloading
// it the usual way.
PackURLs []protocol.PackURL
Expand All @@ -40,8 +35,6 @@ func (pk *ResourcePacksInfo) Marshal(io protocol.IO) {
io.Bool(&pk.TexturePackRequired)
io.Bool(&pk.HasAddons)
io.Bool(&pk.HasScripts)
io.Bool(&pk.ForcingServerPacks)
protocol.SliceUint16Length(io, &pk.BehaviourPacks)
protocol.SliceUint16Length(io, &pk.TexturePacks)
protocol.Slice(io, &pk.PackURLs)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type Transfer struct {
Address string
// Port is the UDP port of the new server.
Port uint16
// ReloadWorld currently has an unknown usage.
ReloadWorld bool
}

// ID ...
Expand All @@ -21,4 +23,5 @@ func (*Transfer) ID() uint32 {
func (pk *Transfer) Marshal(io protocol.IO) {
io.String(&pk.Address)
io.Uint16(&pk.Port)
io.Bool(&pk.ReloadWorld)
}
39 changes: 0 additions & 39 deletions minecraft/protocol/resource_pack.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,5 @@
package protocol

// 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 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)
}

// TexturePackInfo represents a texture pack's info sent over network. It holds information about the
// texture pack such as its name, description and version.
type TexturePackInfo struct {
Expand Down

0 comments on commit 500a41a

Please sign in to comment.