1.21.60 support

This commit is contained in:
AkmalFairuz
2025-02-13 10:42:17 +07:00
parent 1eea0360a5
commit f424b90afd
28 changed files with 10000 additions and 96 deletions

View File

@@ -53,7 +53,7 @@ type AddPlayer struct {
// attributes of the entity.
EntityProperties protocol.EntityProperties
// AbilityData represents various data about the abilities of a player, such as ability layers or permissions.
AbilityData protocol.AbilityData
AbilityData proto.AbilityData
// EntityLinks is a list of entity links that are currently active on the player. These links alter the
// way the player shows up when first spawned in terms of it shown as riding an entity. Setting these
// links is important for new viewers to see the player is riding another entity.

View File

@@ -0,0 +1,115 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
const (
BossEventShow = iota
BossEventRegisterPlayer
BossEventHide
BossEventUnregisterPlayer
BossEventHealthPercentage
BossEventTitle
BossEventAppearanceProperties
BossEventTexture
BossEventRequest
)
const (
BossEventColourGrey = iota
BossEventColourBlue
BossEventColourRed
BossEventColourGreen
BossEventColourYellow
BossEventColourPurple
BossEventColourWhite
)
// BossEvent is sent by the server to make a specific 'boss event' occur in the
// world. It includes features such as showing a boss bar to the player and
// turning the sky dark.
type BossEvent struct {
// BossEntityUniqueID is the unique ID of the boss entity that the boss
// event sent involves. By default, the health percentage and title of the
// boss bar depend on the health and name tag of this entity. If
// BossEntityUniqueID is the same as the client's entity unique ID, its
// HealthPercentage and BossBarTitle can be freely altered.
BossEntityUniqueID int64
// EventType is the type of the event. The fields written depend on the
// event type set, and some event types are sent by the client, whereas
// others are sent by the server. The event type is one of the constants
// above.
EventType uint32
// PlayerUniqueID is the unique ID of the player that is registered to or
// unregistered from the boss fight. It is set if EventType is either
// BossEventRegisterPlayer or BossEventUnregisterPlayer.
PlayerUniqueID int64
// BossBarTitle is the title shown above the boss bar. It may be set to set
// a different title if the BossEntityUniqueID matches the client's entity
// unique ID.
BossBarTitle string
// FilteredBossBarTitle is a filtered version of BossBarTitle with all the
// profanity removed. The client will use this over BossBarTitle if this
// field is not empty and they have the "Filter Profanity" setting enabled.
FilteredBossBarTitle string
// HealthPercentage is the percentage of health that is shown in the boss
// bar (0.0-1.0). The HealthPercentage may be set to a specific value if the
// BossEntityUniqueID matches the client's entity unique ID.
HealthPercentage float32
// ScreenDarkening currently seems not to do anything.
ScreenDarkening uint16
// Colour is the colour of the boss bar that is shown when a player is
// subscribed. It is only set if the EventType is BossEventShow,
// BossEventAppearanceProperties or BossEventTexture. This is functional as
// of 1.18 and can be any of the BossEventColour constants listed above.
Colour uint32
// Overlay is the overlay of the boss bar that is shown on top of the boss
// bar when a player is subscribed. It currently does not function. It is
// only set if the EventType is BossEventShow, BossEventAppearanceProperties
// or BossEventTexture.
Overlay uint32
}
// ID ...
func (*BossEvent) ID() uint32 {
return packet.IDBossEvent
}
func (pk *BossEvent) Marshal(io protocol.IO) {
io.Varint64(&pk.BossEntityUniqueID)
io.Varuint32(&pk.EventType)
switch pk.EventType {
case BossEventShow:
io.String(&pk.BossBarTitle)
if proto.IsProtoGTE(io, proto.ID776) {
io.String(&pk.FilteredBossBarTitle)
}
io.Float32(&pk.HealthPercentage)
io.Uint16(&pk.ScreenDarkening)
io.Varuint32(&pk.Colour)
io.Varuint32(&pk.Overlay)
case BossEventRegisterPlayer, BossEventUnregisterPlayer, BossEventRequest:
io.Varint64(&pk.PlayerUniqueID)
case BossEventHide:
// No extra payload for this boss event type.
case BossEventHealthPercentage:
io.Float32(&pk.HealthPercentage)
case BossEventTitle:
io.String(&pk.BossBarTitle)
if proto.IsProtoGTE(io, proto.ID776) {
io.String(&pk.FilteredBossBarTitle)
}
case BossEventAppearanceProperties:
io.Uint16(&pk.ScreenDarkening)
io.Varuint32(&pk.Colour)
io.Varuint32(&pk.Overlay)
case BossEventTexture:
io.Varuint32(&pk.Colour)
io.Varuint32(&pk.Overlay)
default:
io.UnknownEnumOption(pk.EventType, "boss event type")
}
}

View File

@@ -0,0 +1,36 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
const (
CameraAunAssistPresetOperationSet = iota
CameraAunAssistPresetOperationAddToExisting
)
// CameraAimAssistPresets is sent by the server to the client to provide a list of categories and presets
// that can be used when sending a CameraAimAssist packet or a CameraInstruction including aim assist.
type CameraAimAssistPresets struct {
// CategoryGroups is a list of groups of categories which can be referenced by one of the Presets.
CategoryGroups []protocol.CameraAimAssistCategoryGroup
// Presets is a list of presets which define a base for how aim assist should behave
Presets []protocol.CameraAimAssistPreset
// Operation is the operation to perform with the presets. It is one of the constants above.
Operation byte
}
// ID ...
func (*CameraAimAssistPresets) ID() uint32 {
return packet.IDCameraAimAssistPresets
}
func (pk *CameraAimAssistPresets) Marshal(io protocol.IO) {
protocol.Slice(io, &pk.CategoryGroups)
protocol.Slice(io, &pk.Presets)
if proto.IsProtoGTE(io, proto.ID776) {
io.Uint8(&pk.Operation)
}
}

View 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"
)
// ClientCheatAbility functions the same as UpdateAbilities. It is unclear why these two were separated.
//
// Deprecated: ClientCheatAbility is deprecated as of 1.20.10.
type ClientCheatAbility struct {
// AbilityData represents various data about the abilities of a player, such as ability layers or permissions.
AbilityData proto.AbilityData
}
// ID ...
func (*ClientCheatAbility) ID() uint32 {
return packet.IDClientCheatAbility
}
func (pk *ClientCheatAbility) Marshal(io protocol.IO) {
protocol.Single(io, &pk.AbilityData)
}

View File

@@ -0,0 +1,88 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
const (
CommandBlockImpulse = iota
CommandBlockRepeating
CommandBlockChain
)
// CommandBlockUpdate is sent by the client to update a command block at a specific position. The command
// block may be either a physical block or an entity.
type CommandBlockUpdate struct {
// Block specifies if the command block updated was an actual physical block. If false, the command block
// is in a minecart and has an entity runtime ID instead.
Block bool
// Position is the position of the command block updated. It is only set if Block is set to true. Nothing
// happens if no command block is set at this position.
Position protocol.BlockPos
// Mode is the mode of the command block. It is either CommandBlockImpulse, CommandBlockChain or
// CommandBlockRepeat. It is only set if Block is set to true.
Mode uint32
// NeedsRedstone specifies if the command block needs to be powered by redstone to be activated. If false,
// the command block is always active. The field is only set if Block is set to true.
NeedsRedstone bool
// Conditional specifies the behaviour of the command block if the command block before it (the opposite
// side of the direction the arrow if facing) fails to execute. If set to false, it will activate at all
// times, whereas if set to true, it will activate only if the previous command block executed
// successfully. The field is only set if Block is set to true.
Conditional bool
// MinecartEntityRuntimeID is the runtime ID of the minecart entity carrying the command block that is
// updated. It is set only if Block is set to false.
MinecartEntityRuntimeID uint64
// Command is the command currently entered in the command block. This is the command that is executed
// when the command block is activated.
Command string
// LastOutput is the output of the last command executed by the command block. It may be left empty to
// show simply no output at all, in combination with setting ShouldTrackOutput to false.
LastOutput string
// Name is the name of the command block updated. If not empty, it will show this name hovering above the
// command block when hovering over the block with the cursor.
Name string
// FilteredName is a filtered version of Name with all the profanity removed. The client will use this
// over Name if this field is not empty and they have the "Filter Profanity" setting enabled.
FilteredName string
// ShouldTrackOutput specifies if the command block tracks output. If set to false, the output box won't
// be shown within the command block.
ShouldTrackOutput bool
// TickDelay is the delay in ticks between executions of a command block, if it is a repeating command
// block.
TickDelay int32
// ExecuteOnFirstTick specifies if the command block should execute on the first tick, AKA as soon as the
// command block is enabled.
ExecuteOnFirstTick bool
}
// ID ...
func (*CommandBlockUpdate) ID() uint32 {
return packet.IDCommandBlockUpdate
}
func (pk *CommandBlockUpdate) Marshal(io protocol.IO) {
io.Bool(&pk.Block)
if pk.Block {
io.UBlockPos(&pk.Position)
io.Varuint32(&pk.Mode)
io.Bool(&pk.NeedsRedstone)
io.Bool(&pk.Conditional)
} else {
io.Varuint64(&pk.MinecartEntityRuntimeID)
}
io.String(&pk.Command)
io.String(&pk.LastOutput)
io.String(&pk.Name)
if proto.IsProtoGTE(io, proto.ID776) {
io.String(&pk.FilteredName)
}
io.Bool(&pk.ShouldTrackOutput)
io.Int32(&pk.TickDelay)
io.Bool(&pk.ExecuteOnFirstTick)
}

View File

@@ -0,0 +1,53 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
// CreativeContent is a packet sent by the server to set the creative inventory's content for a player.
// Introduced in 1.16, this packet replaces the previous method - sending an InventoryContent packet with
// creative inventory window ID.
// As of v1.21.60, this packet is no longer required to be sent as part of the login sequence however the
// client will crash if they try to open their creative inventory before receiving this packet. Every item
// must be part of a group, any items that are not part of a group will need to reference an "anonymous group"
// which has an empty name OR no icon. The order of Groups and Items is how the client will render items
// in the creative inventory compared to the previous, hard coded order.
//
// Below is an example of defining 2 ungrouped items, 2 grouped items and then another 2 ungrouped items, all
// in the nature category.
//
// CreativeContent{
// Groups: []protocol.CreativeGroup{
// {Category: 1}, // No name or icon, this is the "anonymous group"
// {Category: 1, Name: "itemGroup.name.planks", Icon: protocol.ItemStack{...}}, // A "planks" group
// {Category: 1}, // Another "anonymous group"
// },
// Items: []protocol.CreativeItem{
// {CreativeItemNetworkID: 0, Item: protocol.ItemStack{...}, GroupIndex: 0}, // Ungrouped before "planks"
// {CreativeItemNetworkID: 1, Item: protocol.ItemStack{...}, GroupIndex: 0}, // Ungrouped before "planks"
// {CreativeItemNetworkID: 2, Item: protocol.ItemStack{...}, GroupIndex: 1}, // Grouped under the "planks" group
// {CreativeItemNetworkID: 3, Item: protocol.ItemStack{...}, GroupIndex: 1}, // Grouped under the "planks" group
// {CreativeItemNetworkID: 4, Item: protocol.ItemStack{...}, GroupIndex: 2}, // Ungrouped after "planks"
// {CreativeItemNetworkID: 5, Item: protocol.ItemStack{...}, GroupIndex: 2}, // Ungrouped after "planks"
// }
// }
type CreativeContent struct {
// Groups is a list of the groups that should be added to the creative inventory.
Groups []protocol.CreativeGroup
// Items is a list of the items that should be added to the creative inventory.
Items []proto.CreativeItem
}
// ID ...
func (*CreativeContent) ID() uint32 {
return packet.IDCreativeContent
}
func (pk *CreativeContent) Marshal(io protocol.IO) {
if proto.IsProtoGTE(io, proto.ID776) {
protocol.Slice(io, &pk.Groups)
}
protocol.Slice(io, &pk.Items)
}

View File

@@ -0,0 +1,25 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
// ItemRegistry is sent by the server to send the client a list of available items and attach client-side
// components to a custom item. This packet was formerly known as the ItemComponent packet before 1.21.60,
// which did not include item definitions but only the components.
type ItemRegistry struct {
// Items is a list of all items with their legacy IDs which are available in the game. Failing to send any
// of the items that are in the game will crash mobile clients. Any custom components are also attached to
// the items in this list.
Items []proto.ItemEntry
}
// ID ...
func (*ItemRegistry) ID() uint32 {
return packet.IDItemRegistry
}
func (pk *ItemRegistry) Marshal(io protocol.IO) {
protocol.Slice(io, &pk.Items)
}

View File

@@ -200,7 +200,7 @@ type StartGame struct {
Blocks []protocol.BlockEntry
// Items is a list of all items with their legacy IDs which are available in the game. Failing to send any
// of the items that are in the game will crash mobile clients.
Items []protocol.ItemEntry
Items []proto.LegacyItemRegistryEntry
// MultiPlayerCorrelationID is a unique ID specifying the multi-player session of the player. A random
// UUID should be filled out for this field.
MultiPlayerCorrelationID string
@@ -316,7 +316,11 @@ func (pk *StartGame) Marshal(io protocol.IO) {
io.Int64(&pk.Time)
io.Varint32(&pk.EnchantmentSeed)
protocol.Slice(io, &pk.Blocks)
protocol.Slice(io, &pk.Items)
if proto.IsProtoLT(io, proto.ID776) {
protocol.Slice(io, &pk.Items)
} else {
proto.EmptySlice(io, &pk.Items)
}
io.String(&pk.MultiPlayerCorrelationID)
io.Bool(&pk.ServerAuthoritativeInventory)
io.String(&pk.GameVersion)

View File

@@ -0,0 +1,82 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
const (
StructureBlockData = iota
StructureBlockSave
StructureBlockLoad
StructureBlockCorner
StructureBlockInvalid
StructureBlockExport
)
const (
StructureRedstoneSaveModeMemory = iota
StructureRedstoneSaveModeDisk
)
// StructureBlockUpdate is sent by the client when it updates a structure block using the in-game UI. The
// data it contains depends on the type of structure block that it is. In Minecraft Bedrock Edition v1.11,
// there is only the Export structure block type, but in v1.13 the ones present in Java Edition will,
// according to the wiki, be added too.
type StructureBlockUpdate struct {
// Position is the position of the structure block that is updated.
Position protocol.BlockPos
// StructureName is the name of the structure that was set in the structure block's UI. This is the name
// used to export the structure to a file.
StructureName string
// FilteredStructureName is a filtered version of StructureName with all the profanity removed. The client
// will use this over StructureName if this field is not empty and they have the "Filter Profanity"
// setting enabled.
FilteredStructureName string
// DataField is the name of a function to run, usually used during natural generation. A description can
// be found here: https://minecraft.wiki/w/Structure_Block#Data.
DataField string
// IncludePlayers specifies if the 'Include Players' toggle has been enabled, meaning players are also
// exported by the structure block.
IncludePlayers bool
// ShowBoundingBox specifies if the structure block should have its bounds outlined. A thin line will
// encapsulate the bounds of the structure if set to true.
ShowBoundingBox bool
// StructureBlockType is the type of the structure block updated. A list of structure block types that
// will be used can be found in the constants above.
StructureBlockType int32
// Settings is a struct of settings that should be used for exporting the structure. These settings are
// identical to the last sent in the StructureBlockUpdate packet by the client.
Settings protocol.StructureSettings
// RedstoneSaveMode is the mode that should be used to save the structure when used with redstone. In
// Java Edition, this is always stored in memory, but in Bedrock Edition it can be stored either to disk
// or memory. See the constants above for the options.
RedstoneSaveMode int32
// ShouldTrigger specifies if the structure block should be triggered immediately after this packet
// reaches the server.
ShouldTrigger bool
// Waterlogged specifies if non-air blocks replace water or combine with water.
Waterlogged bool
}
// ID ...
func (*StructureBlockUpdate) ID() uint32 {
return packet.IDStructureBlockUpdate
}
func (pk *StructureBlockUpdate) Marshal(io protocol.IO) {
io.UBlockPos(&pk.Position)
io.String(&pk.StructureName)
if proto.IsProtoGTE(io, proto.ID776) {
io.String(&pk.FilteredStructureName)
}
io.String(&pk.DataField)
io.Bool(&pk.IncludePlayers)
io.Bool(&pk.ShowBoundingBox)
io.Varint32(&pk.StructureBlockType)
protocol.Single(io, &pk.Settings)
io.Varint32(&pk.RedstoneSaveMode)
io.Bool(&pk.ShouldTrigger)
io.Bool(&pk.Waterlogged)
}

View File

@@ -0,0 +1,23 @@
package legacypacket
import (
"github.com/akmalfairuz/legacy-version/legacyver/proto"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
// UpdateAbilities is a packet sent from the server to the client to update the abilities of the player. It, along with
// the UpdateAdventureSettings packet, are replacements of the AdventureSettings packet since v1.19.10.
type UpdateAbilities struct {
// AbilityData represents various data about the abilities of a player, such as ability layers or permissions.
AbilityData proto.AbilityData
}
// ID ...
func (*UpdateAbilities) ID() uint32 {
return packet.IDUpdateAbilities
}
func (pk *UpdateAbilities) Marshal(io protocol.IO) {
protocol.Single(io, &pk.AbilityData)
}