Skip to content

Commit

Permalink
minecraft/protocol: Support 1.21.20 (#262)
Browse files Browse the repository at this point in the history
Co-authored-by: Doge <[email protected]>
  • Loading branch information
TwistedAsylumMC and cooldogedev authored Aug 14, 2024
1 parent d96a940 commit d900285
Show file tree
Hide file tree
Showing 30 changed files with 296 additions and 18 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
26 changes: 24 additions & 2 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,8 +148,14 @@ type CameraPreset struct {
RotX Optional[float32]
// RotY is the default yaw of the camera.
RotY Optional[float32]
// AudioListener defines where the audio should be played from when using this preset. This is one of the constants
// above.
// 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]
// 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]
// AudioListener defines where the audio should be played from when using this preset. This is one of the
// constants above.
AudioListener Optional[byte]
// PlayerEffects is currently unknown.
PlayerEffects Optional[bool]
Expand All @@ -150,6 +170,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)
}
15 changes: 15 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,17 @@ const (
ContainerTypeDecoratedPot
ContainerTypeCrafter
)

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

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.Varuint32(&data.ClientPrediction)
}

// Marshal ...
Expand Down
25 changes: 22 additions & 3 deletions minecraft/protocol/item_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,11 +468,15 @@ type CraftRecipeStackRequestAction struct {
// one of the recipes sent in the CraftingData packet, where each of the recipes have a RecipeNetworkID as
// of 1.16.
RecipeNetworkID uint32
// NumberOfCrafts is how many times the recipe was crafted. This field appears to be boilerplate and
// has no effect.
NumberOfCrafts byte
}

// Marshal ...
func (a *CraftRecipeStackRequestAction) Marshal(r IO) {
r.Varuint32(&a.RecipeNetworkID)
r.Uint8(&a.NumberOfCrafts)
}

// AutoCraftRecipeStackRequestAction is sent by the client similarly to the CraftRecipeStackRequestAction. The
Expand All @@ -482,6 +486,8 @@ type AutoCraftRecipeStackRequestAction struct {
// one of the recipes sent in the CraftingData packet, where each of the recipes have a RecipeNetworkID as
// of 1.16.
RecipeNetworkID uint32
// NumberOfCrafts is how many times the recipe was crafted. This field is just a duplicate of TimesCrafted.
NumberOfCrafts byte
// TimesCrafted is how many times the recipe was crafted.
TimesCrafted byte
// Ingredients is a slice of ItemDescriptorCount that contains the ingredients that were used to craft the recipe.
Expand All @@ -492,6 +498,7 @@ type AutoCraftRecipeStackRequestAction struct {
// Marshal ...
func (a *AutoCraftRecipeStackRequestAction) Marshal(r IO) {
r.Varuint32(&a.RecipeNetworkID)
r.Uint8(&a.NumberOfCrafts)
r.Uint8(&a.TimesCrafted)
FuncSlice(r, &a.Ingredients, r.ItemDescriptorCount)
}
Expand All @@ -502,11 +509,15 @@ type CraftCreativeStackRequestAction struct {
// CreativeItemNetworkID is the network ID of the creative item that is being created. This is one of the
// creative item network IDs sent in the CreativeContent packet.
CreativeItemNetworkID uint32
// NumberOfCrafts is how many times the recipe was crafted. This field appears to be boilerplate and
// has no effect.
NumberOfCrafts byte
}

// Marshal ...
func (a *CraftCreativeStackRequestAction) Marshal(r IO) {
r.Varuint32(&a.CreativeItemNetworkID)
r.Uint8(&a.NumberOfCrafts)
}

// CraftRecipeOptionalStackRequestAction is sent when using an anvil. When this action is sent, the
Expand All @@ -517,13 +528,17 @@ type CraftRecipeOptionalStackRequestAction struct {
// one of the multi-recipes sent in the CraftingData packet, where each of the recipes have a RecipeNetworkID as
// of 1.16.
RecipeNetworkID uint32
// NumberOfCrafts is how many times the recipe was crafted. This field appears to be boilerplate and
// has no effect.
NumberOfCrafts byte
// FilterStringIndex is the index of a filter string sent in a ItemStackRequest.
FilterStringIndex int32
}

// Marshal ...
func (c *CraftRecipeOptionalStackRequestAction) Marshal(r IO) {
r.Varuint32(&c.RecipeNetworkID)
r.Uint8(&c.NumberOfCrafts)
r.Int32(&c.FilterStringIndex)
}

Expand All @@ -534,13 +549,17 @@ type CraftGrindstoneRecipeStackRequestAction struct {
// one of the recipes sent in the CraftingData packet, where each of the recipes have a RecipeNetworkID as
// of 1.16.
RecipeNetworkID uint32
// NumberOfCrafts is how many times the recipe was crafted. This field appears to be boilerplate and
// has no effect.
NumberOfCrafts byte
// Cost is the cost of the recipe that was crafted.
Cost int32
}

// Marshal ...
func (c *CraftGrindstoneRecipeStackRequestAction) Marshal(r IO) {
r.Varuint32(&c.RecipeNetworkID)
r.Uint8(&c.NumberOfCrafts)
r.Varint32(&c.Cost)
}

Expand Down Expand Up @@ -580,8 +599,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 @@ -592,7 +611,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)
}
6 changes: 6 additions & 0 deletions minecraft/protocol/packet/change_dimension.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ 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 the player is currently in. The client will
// update the server on its state through the ServerBoundLoadingScreen packet, and it can be used to not
// send specific packets to the client if it is changing dimensions. This field should be unique for every
//ChangeDimension packet sent.
LoadingScreenID protocol.Optional[uint32]
}

// ID ...
Expand All @@ -39,4 +44,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)
}
3 changes: 3 additions & 0 deletions minecraft/protocol/packet/correct_player_move_prediction.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type CorrectPlayerMovePrediction struct {
// Rotation is the rotation of the player at the tick written in the field below. It is only included if
// PredictionType is PredictionTypeVehicle.
Rotation mgl32.Vec2
// VehicleAngularVelocity is the angular velocity of the vehicle that the rider is riding.
VehicleAngularVelocity protocol.Optional[float32]
// OnGround specifies if the player was on the ground at the time of the tick below.
OnGround bool
// Tick is the tick of the movement which was corrected by this packet.
Expand All @@ -42,6 +44,7 @@ func (pk *CorrectPlayerMovePrediction) Marshal(io protocol.IO) {
io.Vec3(&pk.Delta)
if pk.PredictionType == PredictionTypeVehicle {
io.Vec2(&pk.Rotation)
protocol.OptionalFunc(io, &pk.VehicleAngularVelocity, io.Float32)
}
io.Bool(&pk.OnGround)
io.Varuint64(&pk.Tick)
Expand Down
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)
}
Loading

0 comments on commit d900285

Please sign in to comment.