Skip to content

Commit

Permalink
minecraft/protocol: Initial support for 1.21.20
Browse files Browse the repository at this point in the history
  • Loading branch information
TwistedAsylumMC committed Aug 2, 2024
1 parent 01d3093 commit 11df3cb
Show file tree
Hide file tree
Showing 26 changed files with 245 additions and 12 deletions.
1 change: 1 addition & 0 deletions minecraft/protocol/ability.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
AbilityLayerTypeSpectator
AbilityLayerTypeCommands
AbilityLayerTypeEditor
AbilityLayerTypeLoadingScreen
)

const (
Expand Down
20 changes: 20 additions & 0 deletions minecraft/protocol/camera.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,20 @@ func (x *CameraInstructionFade) Marshal(r IO) {
OptionalFunc(r, &x.Colour, r.RGB)
}

// CameraInstructionTarget represents a camera instruction that targets a specific entity.
type CameraInstructionTarget struct {
// CenterOffset is the offset from the center of the entity that the camera should target.
CenterOffset Optional[mgl32.Vec3]
// EntityUniqueID is the unique ID of the entity that the camera should target.
EntityUniqueID int64
}

// Marshal encodes/decodes a CameraInstructionTarget.
func (x *CameraInstructionTarget) Marshal(r IO) {
OptionalFunc(r, &x.CenterOffset, r.Vec3)
r.Int64(&x.EntityUniqueID)
}

// CameraPreset represents a basic preset that can be extended upon by more complex instructions.
type CameraPreset struct {
// Name is the name of the preset. Each preset must have their own unique name.
Expand All @@ -134,6 +148,10 @@ type CameraPreset struct {
RotX Optional[float32]
// RotY is the default yaw of the camera.
RotY Optional[float32]
// ViewOffset ...
ViewOffset Optional[mgl32.Vec2]
// Radius ...
Radius Optional[float32]
// AudioListener defines where the audio should be played from when using this preset. This is one of the constants
// above.
AudioListener Optional[byte]
Expand All @@ -150,6 +168,8 @@ 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.ViewOffset, r.Vec2)
OptionalFunc(r, &x.Radius, r.Float32)
OptionalFunc(r, &x.AudioListener, r.Uint8)
OptionalFunc(r, &x.PlayerEffects, r.Bool)
}
14 changes: 14 additions & 0 deletions minecraft/protocol/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const (
ContainerCreatedOutput
ContainerSmithingTableTemplate
ContainerCrafterLevelEntity
ContainerDynamic
)

const (
Expand Down Expand Up @@ -106,3 +107,16 @@ const (
ContainerTypeDecoratedPot
ContainerTypeCrafter
)

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
}

func (x *FullContainerName) Marshal(r IO) {
r.Uint8(&x.ContainerID)
r.Uint32(&x.DynamicContainerID)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/entity_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type EntityLink struct {
// RiderInitiated specifies if the link was created by the rider, for example the player starting to ride
// a horse by itself. This is generally true in vanilla environment for players.
RiderInitiated bool
// VehicleAngularVelocity is the angular velocity of the vehicle that the rider is riding.
VehicleAngularVelocity float32
}

// Marshal encodes/decodes a single entity link.
Expand All @@ -36,4 +38,5 @@ func (x *EntityLink) Marshal(r IO) {
r.Uint8(&x.Type)
r.Bool(&x.Immediate)
r.Bool(&x.RiderInitiated)
r.Float32(&x.VehicleAngularVelocity)
}
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 = 686
CurrentProtocol = 712
// CurrentVersion is the current version of Minecraft as supported by the `packet` package.
CurrentVersion = "1.21.2"
CurrentVersion = "1.21.20"
)
21 changes: 21 additions & 0 deletions minecraft/protocol/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ const (
UseItemActionBreakBlock
)

const (
TriggerTypeUnknown = iota
TriggerTypePlayerInput
TriggerTypeSimulationTick
)

const (
ClientPredictionFailure = iota
ClientPredictionSuccess
)

// UseItemTransactionData represents an inventory transaction data object sent when the client uses an item on
// a block.
type UseItemTransactionData struct {
Expand All @@ -142,6 +153,11 @@ type UseItemTransactionData struct {
// ActionType is the type of the UseItem inventory transaction. It is one of the action types found above,
// and specifies the way the player interacted with the block.
ActionType uint32
// TriggerType is the type of the trigger that caused the inventory transaction. It is one of the trigger
// types found in the constants above. If TriggerType is TriggerTypePlayerInput, the transaction is from
// the initial input of the player. If it is TriggerTypeSimulationTick, the transaction is from a simulation
// tick when the player is holding down the input.
TriggerType uint32
// BlockPosition is the position of the block that was interacted with. This is only really a correct
// block position if ActionType is not UseItemActionClickAir.
BlockPosition BlockPos
Expand All @@ -163,6 +179,9 @@ type UseItemTransactionData struct {
// BlockRuntimeID is the runtime ID of the block that was clicked. It may be used by the server to verify
// that the player's world client-side is synchronised with the server's.
BlockRuntimeID uint32
// ClientPrediction is the client's prediction on the output of the transaction. It is one of the client
// prediction found in the constants above.
ClientPrediction byte
}

const (
Expand Down Expand Up @@ -219,13 +238,15 @@ type ReleaseItemTransactionData struct {
// Marshal ...
func (data *UseItemTransactionData) Marshal(r IO) {
r.Varuint32(&data.ActionType)
r.Varuint32(&data.TriggerType)
r.UBlockPos(&data.BlockPosition)
r.Varint32(&data.BlockFace)
r.Varint32(&data.HotBarSlot)
r.ItemInstance(&data.HeldItem)
r.Vec3(&data.Position)
r.Vec3(&data.ClickedPosition)
r.Varuint32(&data.BlockRuntimeID)
r.Uint8(&data.ClientPrediction)
}

// Marshal ...
Expand Down
6 changes: 3 additions & 3 deletions minecraft/protocol/item_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ func (a *CraftResultsDeprecatedStackRequestAction) Marshal(r IO) {

// StackRequestSlotInfo holds information on a specific slot client-side.
type StackRequestSlotInfo struct {
// ContainerID is the ID of the container that the slot was in.
ContainerID byte
// Container is the FullContainerName that describes the container that the slot is in.
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
Expand All @@ -527,7 +527,7 @@ type StackRequestSlotInfo struct {

// StackReqSlotInfo reads/writes a StackRequestSlotInfo x using IO r.
func StackReqSlotInfo(r IO, x *StackRequestSlotInfo) {
r.Uint8(&x.ContainerID)
Single(r, &x.Container)
r.Uint8(&x.Slot)
r.Varint32(&x.StackNetworkID)
}
6 changes: 6 additions & 0 deletions minecraft/protocol/packet/camera_instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ type CameraInstruction struct {
Clear protocol.Optional[bool]
// Fade is a camera instruction that fades the screen to a specified colour.
Fade protocol.Optional[protocol.CameraInstructionFade]
// Target is a camera instruction that targets a specific entity.
Target protocol.Optional[protocol.CameraInstructionTarget]
// RemoveTarget can be set to true to remove the current target entity.
RemoveTarget protocol.Optional[bool]
}

// ID ...
Expand All @@ -23,4 +27,6 @@ func (pk *CameraInstruction) Marshal(io protocol.IO) {
protocol.OptionalMarshaler(io, &pk.Set)
protocol.OptionalFunc(io, &pk.Clear, io.Bool)
protocol.OptionalMarshaler(io, &pk.Fade)
protocol.OptionalMarshaler(io, &pk.Target)
protocol.OptionalFunc(io, &pk.RemoveTarget, io.Bool)
}
5 changes: 5 additions & 0 deletions minecraft/protocol/packet/change_dimension.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type ChangeDimension struct {
// PlayerActionDimensionChangeRequest if it dies in another dimension, indicating that it needs a
// DimensionChange packet with Respawn set to true.
Respawn bool
// LoadingScreenID is a unique ID for the loading screen that is displayed while the client is changing
// dimensions. The client will update the server on its state through the ServerBoundLoadingScreen packet.
// This field should be unique for every ChangeDimension packet sent.
LoadingScreenID protocol.Optional[uint32]
}

// ID ...
Expand All @@ -39,4 +43,5 @@ func (pk *ChangeDimension) Marshal(io protocol.IO) {
io.Varint32(&pk.Dimension)
io.Vec3(&pk.Position)
io.Bool(&pk.Respawn)
protocol.OptionalFunc(io, &pk.LoadingScreenID, io.Uint32)
}
8 changes: 4 additions & 4 deletions minecraft/protocol/packet/compressed_biome_definition_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
// CompressedBiomeDefinitionList is sent by the server to send a list of biomes to the client. The contents of this packet
// are very large, even after being compressed. This packet is only required when using client-side chunk generation.
type CompressedBiomeDefinitionList struct {
// Biomes is a map of biomes with their identifier as key, and the biome data as value. The biome data contains many
// different fields such as climate, surface materials and generation rules etc.
Biomes map[string]any
// SerialisedBiomeDefinitions is a network NBT serialised compound of all definitions of biomes that are
// available on the server.
SerialisedBiomeDefinitions []byte
}

// ID ...
Expand All @@ -18,5 +18,5 @@ func (*CompressedBiomeDefinitionList) ID() uint32 {
}

func (pk *CompressedBiomeDefinitionList) Marshal(io protocol.IO) {
io.CompressedBiomeDefinitions(&pk.Biomes)
io.Bytes(&pk.SerialisedBiomeDefinitions)
}
22 changes: 22 additions & 0 deletions minecraft/protocol/packet/current_structure_feature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package packet

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

// CurrentStructureFeature is sent by the server to let the client know the name of the structure feature
// that the player is currently occupying.
type CurrentStructureFeature struct {
// CurrentFeature is the identifier of the structure feature that the player is currently occupying.
// If the player is not occupying any structure feature, this field is empty.
CurrentFeature string
}

// ID ...
func (*CurrentStructureFeature) ID() uint32 {
return IDCurrentStructureFeature
}

func (pk *CurrentStructureFeature) Marshal(io protocol.IO) {
io.String(&pk.CurrentFeature)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/disconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type Disconnect struct {
// Message is an optional message to show when disconnected. This message is only written if the
// HideDisconnectionScreen field is set to true.
Message string
// FilteredMessage is always set to empty and the usage is currently unknown.
FilteredMessage string
}

// ID ...
Expand All @@ -28,5 +30,6 @@ func (pk *Disconnect) Marshal(io protocol.IO) {
io.Bool(&pk.HideDisconnectionScreen)
if !pk.HideDisconnectionScreen {
io.String(&pk.Message)
io.String(&pk.FilteredMessage)
}
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/editor_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
// EditorNetwork is a packet sent from the server to the client and vise-versa to communicate editor-mode related
// information. It carries a single compound tag containing the relevant information.
type EditorNetwork struct {
// RouteToManager ...
RouteToManager bool
// Payload is a network little endian compound tag holding data relevant to the editor.
Payload map[string]any
}
Expand All @@ -18,5 +20,6 @@ func (*EditorNetwork) ID() uint32 {
}

func (pk *EditorNetwork) Marshal(io protocol.IO) {
io.Bool(&pk.RouteToManager)
io.NBT(&pk.Payload, nbt.NetworkLittleEndian)
}
5 changes: 5 additions & 0 deletions minecraft/protocol/packet/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,9 @@ const (
IDSetHud
IDAwardAchievement
IDClientBoundCloseForm
_
IDServerBoundLoadingScreen
IDJigsawStructureData
IDCurrentStructureFeature
IDServerBoundDiagnostics
)
4 changes: 4 additions & 0 deletions minecraft/protocol/packet/inventory_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ 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
}

// ID ...
Expand All @@ -24,4 +27,5 @@ 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)
}
4 changes: 4 additions & 0 deletions minecraft/protocol/packet/inventory_slot.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ 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
// 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 @@ -27,5 +30,6 @@ func (*InventorySlot) ID() uint32 {
func (pk *InventorySlot) Marshal(io protocol.IO) {
io.Varuint32(&pk.WindowID)
io.Varuint32(&pk.Slot)
io.Varuint32(&pk.DynamicWindowID)
io.ItemInstance(&pk.NewItem)
}
21 changes: 21 additions & 0 deletions minecraft/protocol/packet/jigsaw_structure_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package packet

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

// JigsawStructureData is sent by the server to let the client know all the rules for jigsaw structures.
type JigsawStructureData struct {
// StructureData is a network NBT serialised compound of all the jigsaw structure rules defined
// on the server.
StructureData []byte
}

// ID ...
func (*JigsawStructureData) ID() uint32 {
return IDJigsawStructureData
}

func (pk *JigsawStructureData) Marshal(io protocol.IO) {
io.Bytes(&pk.StructureData)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/mob_armour_equipment.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type MobArmourEquipment struct {
Leggings protocol.ItemInstance
// Boots is the item worn as boots by the entity. Items not wearable as boots will not be rendered.
Boots protocol.ItemInstance
// Body is the item worn on the body of the entity. Items not wearable on the body will not be rendered.
Body protocol.ItemInstance
}

// ID ...
Expand All @@ -34,4 +36,5 @@ func (pk *MobArmourEquipment) Marshal(io protocol.IO) {
io.ItemInstance(&pk.Chestplate)
io.ItemInstance(&pk.Leggings)
io.ItemInstance(&pk.Boots)
io.ItemInstance(&pk.Body)
}
8 changes: 7 additions & 1 deletion minecraft/protocol/packet/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ func init() {
IDSetHud: func() Packet { return &SetHud{} },
IDAwardAchievement: func() Packet { return &AwardAchievement{} },
IDClientBoundCloseForm: func() Packet { return &ClientBoundCloseForm{} },
IDServerBoundLoadingScreen: func() Packet { return &ServerBoundLoadingScreen{} },
IDJigsawStructureData: func() Packet { return &JigsawStructureData{} },
IDCurrentStructureFeature: func() Packet { return &CurrentStructureFeature{} },
IDServerBoundDiagnostics: func() Packet { return &ServerBoundDiagnostics{} },
}
for id, pk := range serverOriginating {
RegisterPacketFromServer(id, pk)
Expand Down Expand Up @@ -286,7 +290,7 @@ func init() {
IDMapInfoRequest: func() Packet { return &MapInfoRequest{} },
IDRequestChunkRadius: func() Packet { return &RequestChunkRadius{} },
IDBossEvent: func() Packet { return &BossEvent{} },
IDShowCredits: func() Packet { return &ShowCredits{} },
IDShowCredits: func() Packet { return &ShowCredits{} },
IDCommandRequest: func() Packet { return &CommandRequest{} },
IDCommandBlockUpdate: func() Packet { return &CommandBlockUpdate{} },
IDResourcePackChunkRequest: func() Packet { return &ResourcePackChunkRequest{} },
Expand Down Expand Up @@ -336,6 +340,8 @@ func init() {
IDBlockActorData: func() Packet { return &BlockActorData{} },
IDPlayerToggleCrafterSlotRequest: func() Packet { return &PlayerToggleCrafterSlotRequest{} },
IDSetPlayerInventoryOptions: func() Packet { return &SetPlayerInventoryOptions{} },
IDServerBoundLoadingScreen: func() Packet { return &ServerBoundLoadingScreen{} },
IDServerBoundDiagnostics: func() Packet { return &ServerBoundDiagnostics{} },
}
for id, pk := range clientOriginating {
RegisterPacketFromClient(id, pk)
Expand Down
Loading

0 comments on commit 11df3cb

Please sign in to comment.