First support 1.21.130
This commit is contained in:
@@ -11,15 +11,16 @@ import (
|
||||
type Animate struct {
|
||||
// ActionType is the ID of the animation action to execute. It is one of the action type constants that
|
||||
// may be found above.
|
||||
ActionType int32
|
||||
ActionType uint8
|
||||
// EntityRuntimeID is the runtime ID of the player that the animation should be played upon. The runtime
|
||||
// ID is unique for each world session, and entities are generally identified in packets using this
|
||||
// runtime ID.
|
||||
EntityRuntimeID uint64
|
||||
// Data ...
|
||||
Data float32
|
||||
// RowingTime is the time for rowing actions.
|
||||
RowingTime float32
|
||||
// SwingSource is the source for swing actions. It is one of the action type constants that
|
||||
// may be found above.
|
||||
SwingSource protocol.Optional[string]
|
||||
}
|
||||
|
||||
// ID ...
|
||||
@@ -28,16 +29,30 @@ func (*Animate) ID() uint32 {
|
||||
}
|
||||
|
||||
func (pk *Animate) Marshal(io protocol.IO) {
|
||||
io.Varint32(&pk.ActionType)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
io.Uint8(&pk.ActionType)
|
||||
} else {
|
||||
v := int32(pk.ActionType)
|
||||
io.Varint32(&v)
|
||||
pk.ActionType = uint8(v)
|
||||
}
|
||||
defaultRowingTime := float32(0)
|
||||
io.Varuint64(&pk.EntityRuntimeID)
|
||||
if proto.IsProtoGTE(io, proto.ID859) {
|
||||
io.Float32(&pk.Data)
|
||||
if pk.ActionType == packet.AnimateActionRowLeft || pk.ActionType == packet.AnimateActionRowRight {
|
||||
io.Float32(&pk.RowingTime)
|
||||
}
|
||||
} else {
|
||||
if pk.ActionType&0x80 != 0 {
|
||||
io.Float32(&pk.RowingTime)
|
||||
if proto.IsProtoLT(io, proto.ID898) {
|
||||
const (
|
||||
animateActionRowRight = 128
|
||||
animateActionRowLeft = 129
|
||||
)
|
||||
if pk.ActionType == animateActionRowLeft || pk.ActionType == animateActionRowRight {
|
||||
io.Float32(&defaultRowingTime)
|
||||
}
|
||||
}
|
||||
} else if proto.IsProtoLT(io, proto.ID898) && pk.ActionType&0x80 != 0 {
|
||||
io.Float32(&defaultRowingTime)
|
||||
}
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
protocol.OptionalFunc(io, &pk.SwingSource, io.String)
|
||||
}
|
||||
}
|
||||
|
||||
59
legacyver/legacypacket/available_commands.go
Normal file
59
legacyver/legacypacket/available_commands.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package legacypacket
|
||||
|
||||
import (
|
||||
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
)
|
||||
|
||||
// AvailableCommands is sent by the server to send a list of all commands that
|
||||
// the player is able to use on the server. This packet holds all the arguments
|
||||
// of each commands as well, making it possible for the client to provide
|
||||
// auto-completion and command usages. AvailableCommands packets can be resent,
|
||||
// but the packet is often very big, so doing this very often should be avoided.
|
||||
type AvailableCommands struct {
|
||||
// EnumValues is a slice of all enum values of any enum in the
|
||||
// AvailableCommands packet. EnumValues generally should contain each
|
||||
// possible value only once. Enums are built by pointing to entries in this
|
||||
// slice.
|
||||
EnumValues []string
|
||||
// ChainedSubcommandValues is a slice of all chained subcommand names. ChainedSubcommandValues generally should
|
||||
//contain each possible value only once. ChainedSubcommands are built by pointing to entries in this slice.
|
||||
ChainedSubcommandValues []string
|
||||
// Suffixes, like EnumValues, is a slice of all suffix values of any command
|
||||
// parameter in the AvailableCommands packet.
|
||||
Suffixes []string
|
||||
// Enums is a slice of all (fixed) command enums present in any of the
|
||||
// commands.
|
||||
Enums []proto.CommandEnum
|
||||
// ChainedSubcommands is a slice of all subcommands that are followed by a chained command. An example usage of this
|
||||
// is /execute which allows you to run another command as another entity or at a different position etc.
|
||||
ChainedSubcommands []proto.ChainedSubcommand
|
||||
// Commands is a list of all commands that the client should show
|
||||
// client-side. The AvailableCommands packet replaces any commands sent
|
||||
// before. It does not only add the commands that are sent in it.
|
||||
Commands []proto.Command
|
||||
// DynamicEnums is a slice of dynamic command enums. These command enums can
|
||||
// be changed during runtime without having to resend an AvailableCommands
|
||||
// packet.
|
||||
DynamicEnums []protocol.DynamicEnum
|
||||
// Constraints is a list of constraints that should be applied to certain
|
||||
// options of enums in the commands above.
|
||||
Constraints []protocol.CommandEnumConstraint
|
||||
}
|
||||
|
||||
// ID ...
|
||||
func (*AvailableCommands) ID() uint32 {
|
||||
return packet.IDAvailableCommands
|
||||
}
|
||||
|
||||
func (pk *AvailableCommands) Marshal(io protocol.IO) {
|
||||
protocol.FuncSlice(io, &pk.EnumValues, io.String)
|
||||
protocol.FuncSlice(io, &pk.ChainedSubcommandValues, io.String)
|
||||
protocol.FuncSlice(io, &pk.Suffixes, io.String)
|
||||
protocol.FuncIOSlice(io, &pk.Enums, proto.CommandEnumContext{EnumValues: pk.EnumValues}.Marshal)
|
||||
protocol.Slice(io, &pk.ChainedSubcommands)
|
||||
protocol.Slice(io, &pk.Commands)
|
||||
protocol.Slice(io, &pk.DynamicEnums)
|
||||
protocol.Slice(io, &pk.Constraints)
|
||||
}
|
||||
81
legacyver/legacypacket/command_output.go
Normal file
81
legacyver/legacypacket/command_output.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package legacypacket
|
||||
|
||||
import (
|
||||
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
)
|
||||
|
||||
// CommandOutput is sent by the server to the client to send text as output of a command. Most servers do not
|
||||
// use this packet and instead simply send Text packets, but there is reason to send it.
|
||||
// If the origin of a CommandRequest packet is not the player itself, but, for example, a websocket server,
|
||||
// sending a Text packet will not do what is expected: The message should go to the websocket server, not to
|
||||
// the client's chat. The CommandOutput packet will make sure the messages are relayed to the correct origin
|
||||
// of the command request.
|
||||
type CommandOutput struct {
|
||||
// CommandOrigin is the data specifying the origin of the command. In other words, the source that the
|
||||
// command request was from, such as the player itself or a websocket server. The client forwards the
|
||||
// messages in this packet to the right origin, depending on what is sent here.
|
||||
CommandOrigin protocol.CommandOrigin
|
||||
// OutputType specifies the type of output that is sent. The OutputType sent by vanilla games appears to
|
||||
// be 3, which seems to work.
|
||||
OutputType string
|
||||
// SuccessCount is the amount of times that a command was executed successfully as a result of the command
|
||||
// that was requested. For servers, this is usually a rather meaningless fields, but for vanilla, this is
|
||||
// applicable for commands created with Functions.
|
||||
SuccessCount uint32
|
||||
// OutputMessages is a list of all output messages that should be sent to the player. Whether they are
|
||||
// shown or not, depends on the type of the messages.
|
||||
OutputMessages []protocol.CommandOutputMessage
|
||||
// DataSet ... TODO: Find out what this is for.
|
||||
DataSet protocol.Optional[string]
|
||||
}
|
||||
|
||||
// ID ...
|
||||
func (*CommandOutput) ID() uint32 {
|
||||
return packet.IDCommandOutput
|
||||
}
|
||||
|
||||
func (pk *CommandOutput) Marshal(io protocol.IO) {
|
||||
protocol.CommandOriginData(io, &pk.CommandOrigin)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
io.String(&pk.OutputType)
|
||||
} else {
|
||||
v := getLegacyCommandOutputType(pk.OutputType)
|
||||
io.Uint8(&v)
|
||||
pk.OutputType = getLatestCommandOutputType(v)
|
||||
}
|
||||
io.Uint32(&pk.SuccessCount)
|
||||
protocol.Slice(io, &pk.OutputMessages)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
protocol.OptionalFunc(io, &pk.DataSet, io.String)
|
||||
} else {
|
||||
v, _ := pk.DataSet.Value()
|
||||
io.String(&v)
|
||||
pk.DataSet = protocol.Option(v)
|
||||
}
|
||||
}
|
||||
|
||||
var legacyCommandOutputTypeMap = map[byte]string{
|
||||
0: packet.CommandOutputTypeNone,
|
||||
1: packet.CommandOutputTypeLastOutput,
|
||||
2: packet.CommandOutputTypeSilent,
|
||||
3: packet.CommandOutputTypeAllOutput,
|
||||
4: packet.CommandOutputTypeDataSet,
|
||||
}
|
||||
|
||||
func getLegacyCommandOutputType(outputType string) byte {
|
||||
for k, v := range legacyCommandOutputTypeMap {
|
||||
if v == outputType {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return 3 // Default to all output.
|
||||
}
|
||||
|
||||
func getLatestCommandOutputType(outputType byte) string {
|
||||
if v, ok := legacyCommandOutputTypeMap[outputType]; ok {
|
||||
return v
|
||||
}
|
||||
return packet.CommandOutputTypeAllOutput // Default to all output.
|
||||
}
|
||||
43
legacyver/legacypacket/command_request.go
Normal file
43
legacyver/legacypacket/command_request.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package legacypacket
|
||||
|
||||
import (
|
||||
"github.com/akmalfairuz/legacy-version/internal/typeconf"
|
||||
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
)
|
||||
|
||||
// CommandRequest is sent by the client to request the execution of a server-side command. Although some
|
||||
// servers support sending commands using the Text packet, this packet is guaranteed to have the correct
|
||||
// result.
|
||||
type CommandRequest struct {
|
||||
// CommandLine is the raw entered command line. The client does no parsing of the command line by itself
|
||||
// (unlike it did in the early stages), but lets the server do that.
|
||||
CommandLine string
|
||||
// CommandOrigin is the data specifying the origin of the command. In other words, the source that the
|
||||
// command was from, such as the player itself or a websocket server.
|
||||
CommandOrigin protocol.CommandOrigin
|
||||
// Internal specifies if the command request internal. Setting it to false seems to work and the usage of
|
||||
// this field is not known.
|
||||
Internal bool
|
||||
// Version is the version of the command that is being executed. This field currently has no purpose or functionality.
|
||||
Version string
|
||||
}
|
||||
|
||||
// ID ...
|
||||
func (*CommandRequest) ID() uint32 {
|
||||
return packet.IDCommandRequest
|
||||
}
|
||||
|
||||
func (pk *CommandRequest) Marshal(io protocol.IO) {
|
||||
io.String(&pk.CommandLine)
|
||||
protocol.CommandOriginData(io, &pk.CommandOrigin)
|
||||
io.Bool(&pk.Internal)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
io.String(&pk.Version)
|
||||
} else {
|
||||
v := typeconf.StringToInt[int32](pk.Version, 0)
|
||||
io.Varint32(&v)
|
||||
pk.Version = typeconf.IntToString[int32](v, "")
|
||||
}
|
||||
}
|
||||
39
legacyver/legacypacket/event.go
Normal file
39
legacyver/legacypacket/event.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package legacypacket
|
||||
|
||||
import (
|
||||
"github.com/akmalfairuz/legacy-version/internal/typeconf"
|
||||
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
)
|
||||
|
||||
// Event is sent by the server to send an event with additional data. It is typically sent to the client for
|
||||
// telemetry reasons, much like the SimpleEvent packet.
|
||||
type Event struct {
|
||||
// EntityRuntimeID is the runtime ID of the player. The runtime ID is unique for each world session, and
|
||||
// entities are generally identified in packets using this runtime ID.
|
||||
EntityRuntimeID int64
|
||||
// UsePlayerID ...
|
||||
// TODO: Figure out what UsePlayerID is for.
|
||||
UsePlayerID bool
|
||||
// Event is the event that is transmitted.
|
||||
Event protocol.Event
|
||||
}
|
||||
|
||||
// ID ...
|
||||
func (*Event) ID() uint32 {
|
||||
return packet.IDEvent
|
||||
}
|
||||
|
||||
func (pk *Event) Marshal(io protocol.IO) {
|
||||
io.Varint64(&pk.EntityRuntimeID)
|
||||
io.EventType(&pk.Event)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
io.Bool(&pk.UsePlayerID)
|
||||
} else {
|
||||
v := typeconf.BoolToByte(pk.UsePlayerID)
|
||||
io.Uint8(&v)
|
||||
pk.UsePlayerID = typeconf.ByteToBool(v)
|
||||
}
|
||||
pk.Event.Marshal(io)
|
||||
}
|
||||
40
legacyver/legacypacket/interact.go
Normal file
40
legacyver/legacypacket/interact.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package legacypacket
|
||||
|
||||
import (
|
||||
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
)
|
||||
|
||||
// Interact is sent by the client when it interacts with another entity in some way. It used to be used for
|
||||
// normal entity and block interaction, but this is no longer the case now.
|
||||
type Interact struct {
|
||||
// Action type is the ID of the action that was executed by the player. It is one of the constants that
|
||||
// may be found above.
|
||||
ActionType byte
|
||||
// TargetEntityRuntimeID is the runtime ID of the entity that the player interacted with. This is empty
|
||||
// for the InteractActionOpenInventory action type.
|
||||
TargetEntityRuntimeID uint64
|
||||
// Position associated with the ActionType above. For the InteractActionMouseOverEntity, this is the
|
||||
// position relative to the entity moused over over which the player hovered with its mouse/touch. For the
|
||||
// InteractActionLeaveVehicle, this is the position that the player spawns at after leaving the vehicle.
|
||||
Position protocol.Optional[mgl32.Vec3]
|
||||
}
|
||||
|
||||
// ID ...
|
||||
func (*Interact) ID() uint32 {
|
||||
return packet.IDInteract
|
||||
}
|
||||
|
||||
func (pk *Interact) Marshal(io protocol.IO) {
|
||||
io.Uint8(&pk.ActionType)
|
||||
io.Varuint64(&pk.TargetEntityRuntimeID)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
protocol.OptionalFunc(io, &pk.Position, io.Vec3)
|
||||
} else {
|
||||
pos, _ := pk.Position.Value()
|
||||
io.Vec3(&pos)
|
||||
pk.Position = protocol.Option(pos)
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ type MobEffect struct {
|
||||
Duration int32
|
||||
// Tick is the server tick at which the packet was sent. It is used in relation to CorrectPlayerMovePrediction.
|
||||
Tick uint64
|
||||
// Ambient specifies if the effect is ambient. If set to false, it will not get treated as an ambient effect.
|
||||
Ambient bool
|
||||
}
|
||||
|
||||
// ID ...
|
||||
@@ -50,5 +52,9 @@ func (pk *MobEffect) Marshal(io protocol.IO) {
|
||||
} else {
|
||||
io.Uint64(&pk.Tick)
|
||||
}
|
||||
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
io.Bool(&pk.Ambient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ type ResourcePackStack struct {
|
||||
// join the server. If set to true, the client gets the option to either download the resource packs and
|
||||
// join, or quit entirely. Behaviour packs never have to be downloaded.
|
||||
TexturePackRequired 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, and the order does not necessarily matter.
|
||||
BehaviourPacks []protocol.StackResourcePack
|
||||
// TexturePacks is a list of texture packs that the client needs to download before joining the server.
|
||||
// The order of these texture packs specifies the order that they are applied in on the client side. The
|
||||
// first in the list will be applied first.
|
||||
@@ -41,7 +38,10 @@ func (*ResourcePackStack) ID() uint32 {
|
||||
|
||||
func (pk *ResourcePackStack) Marshal(io protocol.IO) {
|
||||
io.Bool(&pk.TexturePackRequired)
|
||||
protocol.Slice(io, &pk.BehaviourPacks)
|
||||
if proto.IsProtoLT(io, proto.ID898) {
|
||||
var emptyResourcePack []protocol.StackResourcePack
|
||||
protocol.Slice(io, &emptyResourcePack)
|
||||
}
|
||||
protocol.Slice(io, &pk.TexturePacks)
|
||||
io.String(&pk.BaseGameVersion)
|
||||
protocol.SliceUint32Length(io, &pk.Experiments)
|
||||
|
||||
@@ -238,8 +238,6 @@ type StartGame struct {
|
||||
// its index in the expected block palette. This is useful for servers that wish to support multiple protocol versions
|
||||
// and custom blocks, but it will result in extra bytes being written for every block in a sub chunk palette.
|
||||
UseBlockNetworkIDHashes bool
|
||||
// TickDeathSystemsEnabled specifies if the new tick death systems are enabled.
|
||||
TickDeathSystemsEnabled bool
|
||||
// ServerAuthoritativeSound is currently unknown as to what it does.
|
||||
ServerAuthoritativeSound bool
|
||||
}
|
||||
@@ -338,8 +336,9 @@ func (pk *StartGame) Marshal(io protocol.IO) {
|
||||
io.UUID(&pk.WorldTemplateID)
|
||||
io.Bool(&pk.ClientSideGeneration)
|
||||
io.Bool(&pk.UseBlockNetworkIDHashes)
|
||||
if proto.IsProtoGTE(io, proto.ID827) {
|
||||
io.Bool(&pk.TickDeathSystemsEnabled)
|
||||
if proto.IsProtoGTE(io, proto.ID827) && proto.IsProtoLT(io, proto.ID898) {
|
||||
v := false
|
||||
io.Bool(&v)
|
||||
}
|
||||
io.Bool(&pk.ServerAuthoritativeSound)
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ type Text struct {
|
||||
PlatformChatID string
|
||||
// FilteredMessage is a filtered version of Message with all the profanity removed. The client will use
|
||||
// this over Message if this field is not empty and they have the "Filter Profanity" setting enabled.
|
||||
FilteredMessage string
|
||||
FilteredMessage protocol.Optional[string]
|
||||
}
|
||||
|
||||
// ID ...
|
||||
@@ -59,8 +59,21 @@ func (*Text) ID() uint32 {
|
||||
}
|
||||
|
||||
func (pk *Text) Marshal(io protocol.IO) {
|
||||
io.Uint8(&pk.TextType)
|
||||
if proto.IsProtoLT(io, proto.ID898) {
|
||||
io.Uint8(&pk.TextType)
|
||||
}
|
||||
io.Bool(&pk.NeedsTranslation)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
var categoryType uint8
|
||||
if pk.TextType == TextTypeRaw || pk.TextType == TextTypeTip || pk.TextType == TextTypeSystem || pk.TextType == TextTypeObjectWhisper || pk.TextType == TextTypeObjectAnnouncement || pk.TextType == TextTypeObject {
|
||||
categoryType = protocol.TextCategoryMessageOnly
|
||||
} else if pk.TextType == TextTypeChat || pk.TextType == TextTypeWhisper || pk.TextType == TextTypeAnnouncement {
|
||||
categoryType = protocol.TextCategoryAuthoredMessage
|
||||
} else {
|
||||
categoryType = protocol.TextCategoryMessageWithParameters
|
||||
}
|
||||
io.TextCategory(&categoryType)
|
||||
}
|
||||
switch pk.TextType {
|
||||
case TextTypeChat, TextTypeWhisper, TextTypeAnnouncement:
|
||||
io.String(&pk.SourceName)
|
||||
@@ -74,6 +87,12 @@ func (pk *Text) Marshal(io protocol.IO) {
|
||||
io.String(&pk.XUID)
|
||||
io.String(&pk.PlatformChatID)
|
||||
if proto.IsProtoGTE(io, proto.ID685) {
|
||||
io.String(&pk.FilteredMessage)
|
||||
if proto.IsProtoGTE(io, proto.ID898) {
|
||||
protocol.OptionalFunc(io, &pk.FilteredMessage, io.String)
|
||||
} else {
|
||||
v, _ := pk.FilteredMessage.Value()
|
||||
io.String(&v)
|
||||
pk.FilteredMessage = protocol.Option(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user