Add 1.21.2 & 1.21.0 support
This commit is contained in:
12
README.md
12
README.md
@@ -9,8 +9,16 @@ A gophertunnel protocol interface implementation to support older Minecraft Bedr
|
|||||||
| 748 | 1.21.40 | ✅ |
|
| 748 | 1.21.40 | ✅ |
|
||||||
| 729 | 1.21.30 | ✅ |
|
| 729 | 1.21.30 | ✅ |
|
||||||
| 712 | 1.21.20 | ✅ |
|
| 712 | 1.21.20 | ✅ |
|
||||||
| 686 | 1.21.2 | 🚧 |
|
| 686 | 1.21.2 | ✅ |
|
||||||
| 685 | 1.21.0 | 🚧 |
|
| 685 | 1.21.0 | ✅ |
|
||||||
|
| 671 | 1.20.80 | 🚧 |
|
||||||
|
| 662 | 1.20.70 | 🚧 |
|
||||||
|
| 649 | 1.20.60 | 🚧 |
|
||||||
|
| 630 | 1.20.50 | 🚧 |
|
||||||
|
| 622 | 1.20.40 | 🚧 |
|
||||||
|
| 618 | 1.20.30 | 🚧 |
|
||||||
|
| 594 | 1.20.10 | 🚧 |
|
||||||
|
| 589 | 1.20.0 | 🚧 |
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
- [Flonja/multiversion](https://github.com/Flonja/multiversion)
|
- [Flonja/multiversion](https://github.com/Flonja/multiversion)
|
||||||
|
|||||||
BIN
legacyver/data/block_states_686.nbt
Normal file
BIN
legacyver/data/block_states_686.nbt
Normal file
Binary file not shown.
BIN
legacyver/data/item_runtime_ids_686.nbt
Normal file
BIN
legacyver/data/item_runtime_ids_686.nbt
Normal file
Binary file not shown.
6398
legacyver/data/required_item_list_686.json
Normal file
6398
legacyver/data/required_item_list_686.json
Normal file
File diff suppressed because it is too large
Load Diff
76
legacyver/legacypacket/add_actor.go
Normal file
76
legacyver/legacypacket/add_actor.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddActor is sent by the server to the client to spawn an entity to the player. It is used for every entity
|
||||||
|
// except other players, for which the AddPlayer packet is used.
|
||||||
|
type AddActor struct {
|
||||||
|
// EntityUniqueID is the unique ID of the entity. The unique ID is a value that remains consistent across
|
||||||
|
// different sessions of the same world, but most servers simply fill the runtime ID of the entity out for
|
||||||
|
// this field.
|
||||||
|
EntityUniqueID int64
|
||||||
|
// EntityRuntimeID is the runtime ID of the entity. The runtime ID is unique for each world session, and
|
||||||
|
// entities are generally identified in packets using this runtime ID.
|
||||||
|
EntityRuntimeID uint64
|
||||||
|
// EntityType is the string entity type of the entity, for example 'minecraft:skeleton'. A list of these
|
||||||
|
// entities may be found online.
|
||||||
|
EntityType string
|
||||||
|
// Position is the position to spawn the entity on. If the entity is on a distance that the player cannot
|
||||||
|
// see it, the entity will still show up if the player moves closer.
|
||||||
|
Position mgl32.Vec3
|
||||||
|
// Velocity is the initial velocity the entity spawns with. This velocity will initiate client side
|
||||||
|
// movement of the entity.
|
||||||
|
Velocity mgl32.Vec3
|
||||||
|
// Pitch is the vertical rotation of the entity. Facing straight forward yields a pitch of 0. Pitch is
|
||||||
|
// measured in degrees.
|
||||||
|
Pitch float32
|
||||||
|
// Yaw is the horizontal rotation of the entity. Yaw is also measured in degrees.
|
||||||
|
Yaw float32
|
||||||
|
// HeadYaw is the same as Yaw, except that it applies specifically to the head of the entity. A different value for
|
||||||
|
// HeadYaw than Yaw means that the entity will have its head turned.
|
||||||
|
HeadYaw float32
|
||||||
|
// BodyYaw is the same as Yaw, except that it applies specifically to the body of the entity. A different value for
|
||||||
|
// BodyYaw than HeadYaw means that the entity will have its body turned, although it is unclear what the difference
|
||||||
|
// between BodyYaw and Yaw is.
|
||||||
|
BodyYaw float32
|
||||||
|
// Attributes is a slice of attributes that the entity has. It includes attributes such as its health,
|
||||||
|
// movement speed, etc.
|
||||||
|
Attributes []protocol.AttributeValue
|
||||||
|
// EntityMetadata is a map of entity metadata, which includes flags and data properties that alter in
|
||||||
|
// particular the way the entity looks. Flags include ones such as 'on fire' and 'sprinting'.
|
||||||
|
// The metadata values are indexed by their property key.
|
||||||
|
EntityMetadata map[uint32]any
|
||||||
|
// EntityProperties is a list of properties that the entity inhibits. These properties define and alter specific
|
||||||
|
// attributes of the entity.
|
||||||
|
EntityProperties protocol.EntityProperties
|
||||||
|
// EntityLinks is a list of entity links that are currently active on the entity. These links alter the
|
||||||
|
// way the entity 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 entity is riding another entity.
|
||||||
|
EntityLinks []proto.EntityLink
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*AddActor) ID() uint32 {
|
||||||
|
return packet.IDAddActor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *AddActor) Marshal(io protocol.IO) {
|
||||||
|
io.Varint64(&pk.EntityUniqueID)
|
||||||
|
io.Varuint64(&pk.EntityRuntimeID)
|
||||||
|
io.String(&pk.EntityType)
|
||||||
|
io.Vec3(&pk.Position)
|
||||||
|
io.Vec3(&pk.Velocity)
|
||||||
|
io.Float32(&pk.Pitch)
|
||||||
|
io.Float32(&pk.Yaw)
|
||||||
|
io.Float32(&pk.HeadYaw)
|
||||||
|
io.Float32(&pk.BodyYaw)
|
||||||
|
protocol.Slice(io, &pk.Attributes)
|
||||||
|
io.EntityMetadata(&pk.EntityMetadata)
|
||||||
|
protocol.Single(io, &pk.EntityProperties)
|
||||||
|
protocol.Slice(io, &pk.EntityLinks)
|
||||||
|
}
|
||||||
92
legacyver/legacypacket/add_player.go
Normal file
92
legacyver/legacypacket/add_player.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddPlayer is sent by the server to the client to make a player entity show up client-side. It is one of the
|
||||||
|
// few entities that cannot be sent using the AddActor packet.
|
||||||
|
type AddPlayer struct {
|
||||||
|
// UUID is the UUID of the player. It is the same UUID that the client sent in the Login packet at the
|
||||||
|
// start of the session. A player with this UUID must exist in the player list (built up using the
|
||||||
|
// PlayerList packet), for it to show up in-game.
|
||||||
|
UUID uuid.UUID
|
||||||
|
// Username is the name of the player. This username is the username that will be set as the initial
|
||||||
|
// name tag of the player.
|
||||||
|
Username string
|
||||||
|
// 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 uint64
|
||||||
|
// PlatformChatID is an identifier only set for particular platforms when chatting (presumably only for
|
||||||
|
// Nintendo Switch). It is otherwise an empty string, and is used to decide which players are able to
|
||||||
|
// chat with each other.
|
||||||
|
PlatformChatID string
|
||||||
|
// Position is the position to spawn the player on. If the player is on a distance that the viewer cannot
|
||||||
|
// see it, the player will still show up if the viewer moves closer.
|
||||||
|
Position mgl32.Vec3
|
||||||
|
// Velocity is the initial velocity the player spawns with. This velocity will initiate client side
|
||||||
|
// movement of the player.
|
||||||
|
Velocity mgl32.Vec3
|
||||||
|
// Pitch is the vertical rotation of the player. Facing straight forward yields a pitch of 0. Pitch is
|
||||||
|
// measured in degrees.
|
||||||
|
Pitch float32
|
||||||
|
// Yaw is the horizontal rotation of the player. Yaw is also measured in degrees.
|
||||||
|
Yaw float32
|
||||||
|
// HeadYaw is the same as Yaw, except that it applies specifically to the head of the player. A different
|
||||||
|
// value for HeadYaw than Yaw means that the player will have its head turned.
|
||||||
|
HeadYaw float32
|
||||||
|
// HeldItem is the item that the player is holding. The item is shown to the viewer as soon as the player
|
||||||
|
// itself shows up. Needless to say that this field is rather pointless, as additional packets still must
|
||||||
|
// be sent for armour to show up.
|
||||||
|
HeldItem protocol.ItemInstance
|
||||||
|
// GameType is the game type of the player. If set to GameTypeSpectator, the player will not be shown to viewers.
|
||||||
|
GameType int32
|
||||||
|
// EntityMetadata is a map of entity metadata, which includes flags and data properties that alter in
|
||||||
|
// particular the way the player looks. Flags include ones such as 'on fire' and 'sprinting'.
|
||||||
|
// The metadata values are indexed by their property key.
|
||||||
|
EntityMetadata map[uint32]any
|
||||||
|
// EntityProperties is a list of properties that the entity inhibits. These properties define and alter specific
|
||||||
|
// 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
|
||||||
|
// 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.
|
||||||
|
EntityLinks []proto.EntityLink
|
||||||
|
// DeviceID is the device ID set in one of the files found in the storage of the device of the player. It
|
||||||
|
// may be changed freely, so it should not be relied on for anything.
|
||||||
|
DeviceID string
|
||||||
|
// BuildPlatform is the build platform/device OS of the player that is about to be added, as it sent in
|
||||||
|
// the Login packet when joining.
|
||||||
|
BuildPlatform int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*AddPlayer) ID() uint32 {
|
||||||
|
return packet.IDAddPlayer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *AddPlayer) Marshal(io protocol.IO) {
|
||||||
|
io.UUID(&pk.UUID)
|
||||||
|
io.String(&pk.Username)
|
||||||
|
io.Varuint64(&pk.EntityRuntimeID)
|
||||||
|
io.String(&pk.PlatformChatID)
|
||||||
|
io.Vec3(&pk.Position)
|
||||||
|
io.Vec3(&pk.Velocity)
|
||||||
|
io.Float32(&pk.Pitch)
|
||||||
|
io.Float32(&pk.Yaw)
|
||||||
|
io.Float32(&pk.HeadYaw)
|
||||||
|
io.ItemInstance(&pk.HeldItem)
|
||||||
|
io.Varint32(&pk.GameType)
|
||||||
|
io.EntityMetadata(&pk.EntityMetadata)
|
||||||
|
protocol.Single(io, &pk.EntityProperties)
|
||||||
|
protocol.Single(io, &pk.AbilityData)
|
||||||
|
protocol.Slice(io, &pk.EntityLinks)
|
||||||
|
io.String(&pk.DeviceID)
|
||||||
|
io.Int32(&pk.BuildPlatform)
|
||||||
|
}
|
||||||
36
legacyver/legacypacket/camera_instruction.go
Normal file
36
legacyver/legacypacket/camera_instruction.go
Normal 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CameraInstruction gives a custom camera specific instructions to operate.
|
||||||
|
type CameraInstruction struct {
|
||||||
|
// Set is a camera instruction that sets the camera to a specified preset.
|
||||||
|
Set protocol.Optional[protocol.CameraInstructionSet]
|
||||||
|
// Clear can be set to true to clear all the current camera instructions.
|
||||||
|
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 aim assist target.
|
||||||
|
RemoveTarget protocol.Optional[bool]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*CameraInstruction) ID() uint32 {
|
||||||
|
return packet.IDCameraInstruction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *CameraInstruction) Marshal(io protocol.IO) {
|
||||||
|
protocol.OptionalMarshaler(io, &pk.Set)
|
||||||
|
protocol.OptionalFunc(io, &pk.Clear, io.Bool)
|
||||||
|
protocol.OptionalMarshaler(io, &pk.Fade)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
protocol.OptionalMarshaler(io, &pk.Target)
|
||||||
|
protocol.OptionalFunc(io, &pk.RemoveTarget, io.Bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
46
legacyver/legacypacket/change_dimension.go
Normal file
46
legacyver/legacypacket/change_dimension.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChangeDimension is sent by the server to the client to send a dimension change screen client-side. Once the
|
||||||
|
// screen is cleared client-side, the client will send a PlayerAction packet with
|
||||||
|
// PlayerActionDimensionChangeDone.
|
||||||
|
type ChangeDimension struct {
|
||||||
|
// Dimension is the dimension that the client should be changed to. The fog colour will change depending
|
||||||
|
// on the type of dimension, which is one of the constants above.
|
||||||
|
// Note that Dimension MUST be a different dimension than the one that the player is currently in. Sending
|
||||||
|
// a ChangeDimension packet with a Dimension that the player is currently in will result in a never-ending
|
||||||
|
// dimension change screen.
|
||||||
|
Dimension int32
|
||||||
|
// Position is the position in the new dimension that the player is spawned in.
|
||||||
|
Position mgl32.Vec3
|
||||||
|
// Respawn specifies if the dimension change was respawn based, meaning that the player died in one
|
||||||
|
// dimension and got respawned into another. The client will send a PlayerAction packet with
|
||||||
|
// 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 ...
|
||||||
|
func (*ChangeDimension) ID() uint32 {
|
||||||
|
return packet.IDChangeDimension
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *ChangeDimension) Marshal(io protocol.IO) {
|
||||||
|
io.Varint32(&pk.Dimension)
|
||||||
|
io.Vec3(&pk.Position)
|
||||||
|
io.Bool(&pk.Respawn)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
protocol.OptionalFunc(io, &pk.LoadingScreenID, io.Uint32)
|
||||||
|
}
|
||||||
|
}
|
||||||
50
legacyver/legacypacket/correct_player_move_prediction.go
Normal file
50
legacyver/legacypacket/correct_player_move_prediction.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CorrectPlayerMovePrediction is sent by the server if and only if StartGame.ServerAuthoritativeMovementMode
|
||||||
|
// is set to AuthoritativeMovementModeServerWithRewind. The packet is used to correct movement at a specific
|
||||||
|
// point in time.
|
||||||
|
type CorrectPlayerMovePrediction struct {
|
||||||
|
// PredictionType is the type of prediction that was corrected. It is one of the constants above.
|
||||||
|
PredictionType byte
|
||||||
|
// Position is the position that the player is supposed to be at the tick written in the field below.
|
||||||
|
// The client will change its current position based on movement after that tick starting from the
|
||||||
|
// Position.
|
||||||
|
Position mgl32.Vec3
|
||||||
|
// Delta is the change in position compared to what the client sent as its position at that specific tick.
|
||||||
|
Delta mgl32.Vec3
|
||||||
|
// 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.
|
||||||
|
Tick uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*CorrectPlayerMovePrediction) ID() uint32 {
|
||||||
|
return packet.IDCorrectPlayerMovePrediction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *CorrectPlayerMovePrediction) Marshal(io protocol.IO) {
|
||||||
|
io.Uint8(&pk.PredictionType)
|
||||||
|
io.Vec3(&pk.Position)
|
||||||
|
io.Vec3(&pk.Delta)
|
||||||
|
if pk.PredictionType == packet.PredictionTypeVehicle {
|
||||||
|
io.Vec2(&pk.Rotation)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
protocol.OptionalFunc(io, &pk.VehicleAngularVelocity, io.Float32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
io.Bool(&pk.OnGround)
|
||||||
|
io.Varuint64(&pk.Tick)
|
||||||
|
}
|
||||||
40
legacyver/legacypacket/disconnect.go
Normal file
40
legacyver/legacypacket/disconnect.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Disconnect may be sent by the server to disconnect the client using an optional message to send as the
|
||||||
|
// disconnect screen.
|
||||||
|
type Disconnect struct {
|
||||||
|
// Reason is the reason for the disconnection. It seems as if this field has no use other than for
|
||||||
|
// telemetry reasons as it does not affect the message that gets displayed on the disconnect screen.
|
||||||
|
Reason int32
|
||||||
|
// HideDisconnectionScreen specifies if the disconnection screen should be hidden when the client is
|
||||||
|
// disconnected, meaning it will be sent directly to the main menu.
|
||||||
|
HideDisconnectionScreen bool
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*Disconnect) ID() uint32 {
|
||||||
|
return packet.IDDisconnect
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *Disconnect) Marshal(io protocol.IO) {
|
||||||
|
io.Varint32(&pk.Reason)
|
||||||
|
io.Bool(&pk.HideDisconnectionScreen)
|
||||||
|
if !pk.HideDisconnectionScreen {
|
||||||
|
io.String(&pk.Message)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
io.String(&pk.FilteredMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
legacyver/legacypacket/editor_network.go
Normal file
29
legacyver/legacypacket/editor_network.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/nbt"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*EditorNetwork) ID() uint32 {
|
||||||
|
return packet.IDEditorNetwork
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *EditorNetwork) Marshal(io protocol.IO) {
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
io.Bool(&pk.RouteToManager)
|
||||||
|
}
|
||||||
|
io.NBT(&pk.Payload, nbt.NetworkLittleEndian)
|
||||||
|
}
|
||||||
@@ -40,6 +40,8 @@ func (pk *InventoryContent) Marshal(io protocol.IO) {
|
|||||||
if proto.IsProtoGTE(io, proto.ID748) {
|
if proto.IsProtoGTE(io, proto.ID748) {
|
||||||
io.ItemInstance(&pk.StorageItem)
|
io.ItemInstance(&pk.StorageItem)
|
||||||
} else {
|
} else {
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
io.Varuint32(&pk.DynamicContainerSize)
|
io.Varuint32(&pk.DynamicContainerSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ func (pk *InventorySlot) Marshal(io protocol.IO) {
|
|||||||
if proto.IsProtoGTE(io, proto.ID748) {
|
if proto.IsProtoGTE(io, proto.ID748) {
|
||||||
io.ItemInstance(&pk.StorageItem)
|
io.ItemInstance(&pk.StorageItem)
|
||||||
} else {
|
} else {
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
io.Varuint32(&pk.DynamicContainerSize)
|
io.Varuint32(&pk.DynamicContainerSize)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
io.ItemInstance(&pk.NewItem)
|
io.ItemInstance(&pk.NewItem)
|
||||||
}
|
}
|
||||||
|
|||||||
50
legacyver/legacypacket/inventory_transaction.go
Normal file
50
legacyver/legacypacket/inventory_transaction.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InventoryTransaction is a packet sent by the client. It essentially exists out of multiple sub-packets,
|
||||||
|
// each of which have something to do with the inventory in one way or another. Some of these sub-packets
|
||||||
|
// directly relate to the inventory, others relate to interaction with the world, that could potentially
|
||||||
|
// result in a change in the inventory.
|
||||||
|
type InventoryTransaction struct {
|
||||||
|
// LegacyRequestID is an ID that is only non-zero at times when sent by the client. The server should
|
||||||
|
// always send 0 for this. When this field is not 0, the LegacySetItemSlots slice below will have values
|
||||||
|
// in it.
|
||||||
|
// LegacyRequestID ties in with the ItemStackResponse packet. If this field is non-0, the server should
|
||||||
|
// respond with an ItemStackResponse packet. Some inventory actions such as dropping an item out of the
|
||||||
|
// hotbar are still one using this packet, and the ItemStackResponse packet needs to tie in with it.
|
||||||
|
LegacyRequestID int32
|
||||||
|
// LegacySetItemSlots are only present if the LegacyRequestID is non-zero. These item slots inform the
|
||||||
|
// server of the slots that were changed during the inventory transaction, and the server should send
|
||||||
|
// back an ItemStackResponse packet with these slots present in it. (Or false with no slots, if rejected.)
|
||||||
|
LegacySetItemSlots []protocol.LegacySetItemSlot
|
||||||
|
// Actions is a list of actions that took place, that form the inventory transaction together. Each of
|
||||||
|
// these actions hold one slot in which one item was changed to another. In general, the combination of
|
||||||
|
// all of these actions results in a balanced inventory transaction. This should be checked to ensure that
|
||||||
|
// no items are cheated into the inventory.
|
||||||
|
Actions []protocol.InventoryAction
|
||||||
|
// TransactionData is a data object that holds data specific to the type of transaction that the
|
||||||
|
// TransactionPacket held. Its concrete type must be one of NormalTransactionData, MismatchTransactionData
|
||||||
|
// UseItemTransactionData, UseItemOnEntityTransactionData or ReleaseItemTransactionData. If nil is set,
|
||||||
|
// the transaction will be assumed to of type InventoryTransactionTypeNormal.
|
||||||
|
TransactionData proto.InventoryTransactionData
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*InventoryTransaction) ID() uint32 {
|
||||||
|
return packet.IDInventoryTransaction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *InventoryTransaction) Marshal(io protocol.IO) {
|
||||||
|
io.Varint32(&pk.LegacyRequestID)
|
||||||
|
if pk.LegacyRequestID != 0 {
|
||||||
|
protocol.Slice(io, &pk.LegacySetItemSlots)
|
||||||
|
}
|
||||||
|
proto.TransactionDataType(io, &pk.TransactionData)
|
||||||
|
protocol.Slice(io, &pk.Actions)
|
||||||
|
pk.TransactionData.Marshal(io)
|
||||||
|
}
|
||||||
44
legacyver/legacypacket/mob_armour_equipment.go
Normal file
44
legacyver/legacypacket/mob_armour_equipment.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MobArmourEquipment is sent by the server to the client to update the armour an entity is wearing. It is
|
||||||
|
// sent for both players and other entities, such as zombies.
|
||||||
|
type MobArmourEquipment struct {
|
||||||
|
// EntityRuntimeID is the runtime ID of the entity. The runtime ID is unique for each world session, and
|
||||||
|
// entities are generally identified in packets using this runtime ID.
|
||||||
|
EntityRuntimeID uint64
|
||||||
|
// Helmet is the equipped helmet of the entity. Items that are not wearable on the head will not be
|
||||||
|
// rendered by the client. Unlike in Java Edition, blocks cannot be worn.
|
||||||
|
Helmet protocol.ItemInstance
|
||||||
|
// Chestplate is the chestplate of the entity. Items that are not wearable as chestplate will not be
|
||||||
|
// rendered.
|
||||||
|
Chestplate protocol.ItemInstance
|
||||||
|
// Leggings is the item worn as leggings by the entity. Items not wearable as leggings will not be
|
||||||
|
// rendered client-side.
|
||||||
|
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 ...
|
||||||
|
func (*MobArmourEquipment) ID() uint32 {
|
||||||
|
return packet.IDMobArmourEquipment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *MobArmourEquipment) Marshal(io protocol.IO) {
|
||||||
|
io.Varuint64(&pk.EntityRuntimeID)
|
||||||
|
io.ItemInstance(&pk.Helmet)
|
||||||
|
io.ItemInstance(&pk.Chestplate)
|
||||||
|
io.ItemInstance(&pk.Leggings)
|
||||||
|
io.ItemInstance(&pk.Boots)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
io.ItemInstance(&pk.Body)
|
||||||
|
}
|
||||||
|
}
|
||||||
63
legacyver/legacypacket/player_armour_damage.go
Normal file
63
legacyver/legacypacket/player_armour_damage.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PlayerArmourDamage is sent by the server to damage the armour of a player. It is a very efficient packet,
|
||||||
|
// but generally it's much easier to just send a slot update for the damaged armour.
|
||||||
|
type PlayerArmourDamage struct {
|
||||||
|
// Bitset holds a bitset of 4 bits that indicate which pieces of armour need to have damage dealt to them.
|
||||||
|
// The first bit, when toggled, is for a helmet, the second for the chestplate, the third for the leggings
|
||||||
|
// and the fourth for boots.
|
||||||
|
Bitset uint8
|
||||||
|
// HelmetDamage is the amount of damage that should be dealt to the helmet.
|
||||||
|
HelmetDamage int32
|
||||||
|
// ChestplateDamage is the amount of damage that should be dealt to the chestplate.
|
||||||
|
ChestplateDamage int32
|
||||||
|
// LeggingsDamage is the amount of damage that should be dealt to the leggings.
|
||||||
|
LeggingsDamage int32
|
||||||
|
// BootsDamage is the amount of damage that should be dealt to the boots.
|
||||||
|
BootsDamage int32
|
||||||
|
// BodyDamage is the amount of damage that should be dealt to the body.
|
||||||
|
BodyDamage int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (pk *PlayerArmourDamage) ID() uint32 {
|
||||||
|
return packet.IDPlayerArmourDamage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *PlayerArmourDamage) Marshal(io protocol.IO) {
|
||||||
|
io.Uint8(&pk.Bitset)
|
||||||
|
if pk.Bitset&packet.PlayerArmourDamageFlagHelmet != 0 {
|
||||||
|
io.Varint32(&pk.HelmetDamage)
|
||||||
|
} else {
|
||||||
|
pk.HelmetDamage = 0
|
||||||
|
}
|
||||||
|
if pk.Bitset&packet.PlayerArmourDamageFlagChestplate != 0 {
|
||||||
|
io.Varint32(&pk.ChestplateDamage)
|
||||||
|
} else {
|
||||||
|
pk.ChestplateDamage = 0
|
||||||
|
}
|
||||||
|
if pk.Bitset&packet.PlayerArmourDamageFlagLeggings != 0 {
|
||||||
|
io.Varint32(&pk.LeggingsDamage)
|
||||||
|
} else {
|
||||||
|
pk.LeggingsDamage = 0
|
||||||
|
}
|
||||||
|
if pk.Bitset&packet.PlayerArmourDamageFlagBoots != 0 {
|
||||||
|
io.Varint32(&pk.BootsDamage)
|
||||||
|
} else {
|
||||||
|
pk.BootsDamage = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
if pk.Bitset&packet.PlayerArmourDamageFlagBody != 0 {
|
||||||
|
io.Varint32(&pk.BodyDamage)
|
||||||
|
} else {
|
||||||
|
pk.BodyDamage = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ func (pk *PlayerAuthInput) Marshal(io protocol.IO) {
|
|||||||
io.Vec3(&pk.Delta)
|
io.Vec3(&pk.Delta)
|
||||||
|
|
||||||
if pk.InputData.Load(packet.InputFlagPerformItemInteraction) {
|
if pk.InputData.Load(packet.InputFlagPerformItemInteraction) {
|
||||||
io.PlayerInventoryAction(&pk.ItemInteractionData)
|
proto.PlayerInventoryAction(io, &pk.ItemInteractionData)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pk.InputData.Load(packet.InputFlagPerformItemStackRequest) {
|
if pk.InputData.Load(packet.InputFlagPerformItemStackRequest) {
|
||||||
|
|||||||
25
legacyver/legacypacket/set_actor_link.go
Normal file
25
legacyver/legacypacket/set_actor_link.go
Normal 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetActorLink is sent by the server to initiate an entity link client-side, meaning one entity will start
|
||||||
|
// riding another.
|
||||||
|
type SetActorLink struct {
|
||||||
|
// EntityLink is the link to be set client-side. It links two entities together, so that one entity rides
|
||||||
|
// another. Note that players that see those entities later will not see the link, unless it is also sent
|
||||||
|
// in the AddActor and AddPlayer packets.
|
||||||
|
EntityLink proto.EntityLink
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*SetActorLink) ID() uint32 {
|
||||||
|
return packet.IDSetActorLink
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *SetActorLink) Marshal(io protocol.IO) {
|
||||||
|
protocol.Single(io, &pk.EntityLink)
|
||||||
|
}
|
||||||
53
legacyver/legacypacket/set_title.go
Normal file
53
legacyver/legacypacket/set_title.go
Normal 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetTitle is sent by the server to make a title, subtitle or action bar shown to a player. It has several
|
||||||
|
// fields that allow setting the duration of the titles.
|
||||||
|
type SetTitle struct {
|
||||||
|
// ActionType is the type of the action that should be executed upon the title of a player. It is one of
|
||||||
|
// the constants above and specifies the response of the client to the packet.
|
||||||
|
ActionType int32
|
||||||
|
// Text is the text of the title, which has a different meaning depending on the ActionType that the
|
||||||
|
// packet has. The text is the text of a title, subtitle or action bar, depending on the type set.
|
||||||
|
Text string
|
||||||
|
// FadeInDuration is the duration that the title takes to fade in on the screen of the player. It is
|
||||||
|
// measured in 20ths of a second (AKA in ticks).
|
||||||
|
FadeInDuration int32
|
||||||
|
// RemainDuration is the duration that the title remains on the screen of the player. It is measured in
|
||||||
|
// 20ths of a second (AKA in ticks).
|
||||||
|
RemainDuration int32
|
||||||
|
// FadeOutDuration is the duration that the title takes to fade out of the screen of the player. It is
|
||||||
|
// measured in 20ths of a second (AKA in ticks).
|
||||||
|
FadeOutDuration int32
|
||||||
|
// XUID is the XBOX Live user ID of the player, which will remain consistent as long as the player is
|
||||||
|
// logged in with the XBOX Live account. It is empty if the user is not logged into its XBL account.
|
||||||
|
XUID string
|
||||||
|
// PlatformOnlineID is either a uint64 or an empty string.
|
||||||
|
PlatformOnlineID 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*SetTitle) ID() uint32 {
|
||||||
|
return packet.IDSetTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *SetTitle) Marshal(io protocol.IO) {
|
||||||
|
io.Varint32(&pk.ActionType)
|
||||||
|
io.String(&pk.Text)
|
||||||
|
io.Varint32(&pk.FadeInDuration)
|
||||||
|
io.Varint32(&pk.RemainDuration)
|
||||||
|
io.Varint32(&pk.FadeOutDuration)
|
||||||
|
io.String(&pk.XUID)
|
||||||
|
io.String(&pk.PlatformOnlineID)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
io.String(&pk.FilteredMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
33
legacyver/legacypacket/stop_sound.go
Normal file
33
legacyver/legacypacket/stop_sound.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package legacypacket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StopSound is sent by the server to stop a sound playing to the player, such as a playing music disk track
|
||||||
|
// or other long-lasting sounds.
|
||||||
|
type StopSound struct {
|
||||||
|
// SoundName is the name of the sound that should be stopped from playing. If no sound with this name is
|
||||||
|
// currently active, the packet is ignored.
|
||||||
|
SoundName string
|
||||||
|
// StopAll specifies if all sounds currently playing to the player should be stopped. If set to true, the
|
||||||
|
// SoundName field may be left empty.
|
||||||
|
StopAll bool
|
||||||
|
// StopMusicLegacy is currently unknown.
|
||||||
|
StopMusicLegacy bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID ...
|
||||||
|
func (*StopSound) ID() uint32 {
|
||||||
|
return packet.IDStopSound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *StopSound) Marshal(io protocol.IO) {
|
||||||
|
io.String(&pk.SoundName)
|
||||||
|
io.Bool(&pk.StopAll)
|
||||||
|
if proto.IsProtoGTE(io, proto.ID712) {
|
||||||
|
io.Bool(&pk.StopMusicLegacy)
|
||||||
|
}
|
||||||
|
}
|
||||||
56
legacyver/proto/entity_link.go
Normal file
56
legacyver/proto/entity_link.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package proto
|
||||||
|
|
||||||
|
import "github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
|
||||||
|
// EntityLink is a link between two entities, typically being one entity riding another.
|
||||||
|
type EntityLink struct {
|
||||||
|
// RiddenEntityUniqueID is the entity unique ID of the entity that is being ridden. For a player sitting
|
||||||
|
// in a boat, this is the unique ID of the boat.
|
||||||
|
RiddenEntityUniqueID int64
|
||||||
|
// RiderEntityUniqueID is the entity unique ID of the entity that is riding. For a player sitting in a
|
||||||
|
// boat, this is the unique ID of the player.
|
||||||
|
RiderEntityUniqueID int64
|
||||||
|
// Type is one of the types above. It specifies the way the entity is linked to another entity.
|
||||||
|
Type byte
|
||||||
|
// Immediate is set to immediately dismount an entity from another. This should be set when the mount of
|
||||||
|
// an entity is killed.
|
||||||
|
Immediate bool
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EntityLink) FromLatest(link protocol.EntityLink) EntityLink {
|
||||||
|
x.RiddenEntityUniqueID = link.RiddenEntityUniqueID
|
||||||
|
x.RiderEntityUniqueID = link.RiderEntityUniqueID
|
||||||
|
x.Type = link.Type
|
||||||
|
x.Immediate = link.Immediate
|
||||||
|
x.RiderInitiated = link.RiderInitiated
|
||||||
|
x.VehicleAngularVelocity = link.VehicleAngularVelocity
|
||||||
|
return *x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EntityLink) ToLatest() protocol.EntityLink {
|
||||||
|
return protocol.EntityLink{
|
||||||
|
RiddenEntityUniqueID: x.RiddenEntityUniqueID,
|
||||||
|
RiderEntityUniqueID: x.RiderEntityUniqueID,
|
||||||
|
Type: x.Type,
|
||||||
|
Immediate: x.Immediate,
|
||||||
|
RiderInitiated: x.RiderInitiated,
|
||||||
|
VehicleAngularVelocity: x.VehicleAngularVelocity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal encodes/decodes a single entity link.
|
||||||
|
func (x *EntityLink) Marshal(r protocol.IO) {
|
||||||
|
r.Varint64(&x.RiddenEntityUniqueID)
|
||||||
|
r.Varint64(&x.RiderEntityUniqueID)
|
||||||
|
r.Uint8(&x.Type)
|
||||||
|
r.Bool(&x.Immediate)
|
||||||
|
r.Bool(&x.RiderInitiated)
|
||||||
|
if IsProtoGTE(r, ID712) {
|
||||||
|
r.Float32(&x.VehicleAngularVelocity)
|
||||||
|
}
|
||||||
|
}
|
||||||
158
legacyver/proto/inventory.go
Normal file
158
legacyver/proto/inventory.go
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InventoryTransactionData represents an object that holds data specific to an inventory transaction type.
|
||||||
|
// The data it holds depends on the type.
|
||||||
|
type InventoryTransactionData interface {
|
||||||
|
// Marshal encodes/decodes a serialised inventory transaction data object.
|
||||||
|
Marshal(r protocol.IO)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupTransactionData looks up inventory transaction data for the ID passed.
|
||||||
|
func lookupTransactionData(id uint32, x *InventoryTransactionData) bool {
|
||||||
|
switch id {
|
||||||
|
case protocol.InventoryTransactionTypeNormal:
|
||||||
|
*x = &protocol.NormalTransactionData{}
|
||||||
|
case protocol.InventoryTransactionTypeMismatch:
|
||||||
|
*x = &protocol.MismatchTransactionData{}
|
||||||
|
case protocol.InventoryTransactionTypeUseItem:
|
||||||
|
*x = &UseItemTransactionData{}
|
||||||
|
case protocol.InventoryTransactionTypeUseItemOnEntity:
|
||||||
|
*x = &protocol.UseItemOnEntityTransactionData{}
|
||||||
|
case protocol.InventoryTransactionTypeReleaseItem:
|
||||||
|
*x = &protocol.ReleaseItemTransactionData{}
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupTransactionDataType looks up an ID for a specific transaction data.
|
||||||
|
func lookupTransactionDataType(x InventoryTransactionData, id *uint32) bool {
|
||||||
|
switch x.(type) {
|
||||||
|
case *protocol.NormalTransactionData:
|
||||||
|
*id = protocol.InventoryTransactionTypeNormal
|
||||||
|
case *protocol.MismatchTransactionData:
|
||||||
|
*id = protocol.InventoryTransactionTypeMismatch
|
||||||
|
case *UseItemTransactionData:
|
||||||
|
*id = protocol.InventoryTransactionTypeUseItem
|
||||||
|
case *protocol.UseItemOnEntityTransactionData:
|
||||||
|
*id = protocol.InventoryTransactionTypeUseItemOnEntity
|
||||||
|
case *protocol.ReleaseItemTransactionData:
|
||||||
|
*id = protocol.InventoryTransactionTypeReleaseItem
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseItemTransactionData represents an inventory transaction data object sent when the client uses an item on
|
||||||
|
// a block.
|
||||||
|
type UseItemTransactionData struct {
|
||||||
|
// LegacyRequestID is an ID that is only non-zero at times when sent by the client. The server should
|
||||||
|
// always send 0 for this. When this field is not 0, the LegacySetItemSlots slice below will have values
|
||||||
|
// in it.
|
||||||
|
// LegacyRequestID ties in with the ItemStackResponse packet. If this field is non-0, the server should
|
||||||
|
// respond with an ItemStackResponse packet. Some inventory actions such as dropping an item out of the
|
||||||
|
// hotbar are still one using this packet, and the ItemStackResponse packet needs to tie in with it.
|
||||||
|
LegacyRequestID int32
|
||||||
|
// LegacySetItemSlots are only present if the LegacyRequestID is non-zero. These item slots inform the
|
||||||
|
// server of the slots that were changed during the inventory transaction, and the server should send
|
||||||
|
// back an ItemStackResponse packet with these slots present in it. (Or false with no slots, if rejected.)
|
||||||
|
LegacySetItemSlots []protocol.LegacySetItemSlot
|
||||||
|
// Actions is a list of actions that took place, that form the inventory transaction together. Each of
|
||||||
|
// these actions hold one slot in which one item was changed to another. In general, the combination of
|
||||||
|
// all of these actions results in a balanced inventory transaction. This should be checked to ensure that
|
||||||
|
// no items are cheated into the inventory.
|
||||||
|
Actions []protocol.InventoryAction
|
||||||
|
// 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 protocol.BlockPos
|
||||||
|
// BlockFace is the face of the block that was interacted with. When clicking the block, it is the face
|
||||||
|
// clicked. When breaking the block, it is the face that was last being hit until the block broke.
|
||||||
|
BlockFace int32
|
||||||
|
// HotBarSlot is the hot bar slot that the player was holding while clicking the block. It should be used
|
||||||
|
// to ensure that the hot bar slot and held item are correctly synchronised with the server.
|
||||||
|
HotBarSlot int32
|
||||||
|
// HeldItem is the item that was held to interact with the block. The server should check if this item
|
||||||
|
// is actually present in the HotBarSlot.
|
||||||
|
HeldItem protocol.ItemInstance
|
||||||
|
// Position is the position of the player at the time of interaction. For clicking a block, this is the
|
||||||
|
// position at that time, whereas for breaking the block it is the position at the time of breaking.
|
||||||
|
Position mgl32.Vec3
|
||||||
|
// ClickedPosition is the position that was clicked relative to the block's base coordinate. It can be
|
||||||
|
// used to find out exactly where a player clicked the block.
|
||||||
|
ClickedPosition mgl32.Vec3
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UseItemTransactionData) FromLatest(l *protocol.UseItemTransactionData) *UseItemTransactionData {
|
||||||
|
return &UseItemTransactionData{
|
||||||
|
LegacyRequestID: l.LegacyRequestID,
|
||||||
|
LegacySetItemSlots: l.LegacySetItemSlots,
|
||||||
|
Actions: l.Actions,
|
||||||
|
ActionType: l.ActionType,
|
||||||
|
TriggerType: l.TriggerType,
|
||||||
|
BlockPosition: l.BlockPosition,
|
||||||
|
BlockFace: l.BlockFace,
|
||||||
|
HotBarSlot: l.HotBarSlot,
|
||||||
|
HeldItem: l.HeldItem,
|
||||||
|
Position: l.Position,
|
||||||
|
ClickedPosition: l.ClickedPosition,
|
||||||
|
BlockRuntimeID: l.BlockRuntimeID,
|
||||||
|
ClientPrediction: l.ClientPrediction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UseItemTransactionData) ToLatest() *protocol.UseItemTransactionData {
|
||||||
|
return &protocol.UseItemTransactionData{
|
||||||
|
LegacyRequestID: x.LegacyRequestID,
|
||||||
|
LegacySetItemSlots: x.LegacySetItemSlots,
|
||||||
|
Actions: x.Actions,
|
||||||
|
ActionType: x.ActionType,
|
||||||
|
TriggerType: x.TriggerType,
|
||||||
|
BlockPosition: x.BlockPosition,
|
||||||
|
BlockFace: x.BlockFace,
|
||||||
|
HotBarSlot: x.HotBarSlot,
|
||||||
|
HeldItem: x.HeldItem,
|
||||||
|
Position: x.Position,
|
||||||
|
ClickedPosition: x.ClickedPosition,
|
||||||
|
BlockRuntimeID: x.BlockRuntimeID,
|
||||||
|
ClientPrediction: x.ClientPrediction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal ...
|
||||||
|
func (x *UseItemTransactionData) Marshal(r protocol.IO) {
|
||||||
|
r.Varuint32(&x.ActionType)
|
||||||
|
if IsProtoGTE(r, ID712) {
|
||||||
|
r.Varuint32(&x.TriggerType)
|
||||||
|
}
|
||||||
|
r.UBlockPos(&x.BlockPosition)
|
||||||
|
r.Varint32(&x.BlockFace)
|
||||||
|
r.Varint32(&x.HotBarSlot)
|
||||||
|
r.ItemInstance(&x.HeldItem)
|
||||||
|
r.Vec3(&x.Position)
|
||||||
|
r.Vec3(&x.ClickedPosition)
|
||||||
|
r.Varuint32(&x.BlockRuntimeID)
|
||||||
|
if IsProtoGTE(r, ID712) {
|
||||||
|
r.Varuint32(&x.ClientPrediction)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package proto
|
package proto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,3 +58,41 @@ func EmptySlice[T any](io protocol.IO, slice *[]T) {
|
|||||||
*slice = make([]T, 0)
|
*slice = make([]T, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TransactionDataType(io protocol.IO, x *InventoryTransactionData) {
|
||||||
|
if IsReader(io) {
|
||||||
|
var transactionType uint32
|
||||||
|
io.Varuint32(&transactionType)
|
||||||
|
if !lookupTransactionData(transactionType, x) {
|
||||||
|
io.UnknownEnumOption(transactionType, "inventory transaction data type")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var id uint32
|
||||||
|
if !lookupTransactionDataType(*x, &id) {
|
||||||
|
io.UnknownEnumOption(fmt.Sprintf("%T", x), "inventory transaction data type")
|
||||||
|
}
|
||||||
|
io.Varuint32(&id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PlayerInventoryAction(io protocol.IO, x *protocol.UseItemTransactionData) {
|
||||||
|
io.Varint32(&x.LegacyRequestID)
|
||||||
|
if x.LegacyRequestID < -1 && (x.LegacyRequestID&1) == 0 {
|
||||||
|
protocol.Slice(io, &x.LegacySetItemSlots)
|
||||||
|
}
|
||||||
|
protocol.Slice(io, &x.Actions)
|
||||||
|
io.Varuint32(&x.ActionType)
|
||||||
|
if IsProtoGTE(io, ID712) {
|
||||||
|
io.Varuint32(&x.TriggerType)
|
||||||
|
}
|
||||||
|
io.BlockPos(&x.BlockPosition)
|
||||||
|
io.Varint32(&x.BlockFace)
|
||||||
|
io.Varint32(&x.HotBarSlot)
|
||||||
|
io.ItemInstance(&x.HeldItem)
|
||||||
|
io.Vec3(&x.Position)
|
||||||
|
io.Vec3(&x.ClickedPosition)
|
||||||
|
io.Varuint32(&x.BlockRuntimeID)
|
||||||
|
if IsProtoGTE(io, ID712) {
|
||||||
|
io.Varuint32(&x.ClientPrediction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -538,8 +538,10 @@ type CraftRecipeStackRequestAction struct {
|
|||||||
// Marshal ...
|
// Marshal ...
|
||||||
func (a *CraftRecipeStackRequestAction) Marshal(r protocol.IO) {
|
func (a *CraftRecipeStackRequestAction) Marshal(r protocol.IO) {
|
||||||
r.Varuint32(&a.RecipeNetworkID)
|
r.Varuint32(&a.RecipeNetworkID)
|
||||||
|
if IsProtoGTE(r, ID712) {
|
||||||
r.Uint8(&a.NumberOfCrafts)
|
r.Uint8(&a.NumberOfCrafts)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AutoCraftRecipeStackRequestAction is sent by the client similarly to the CraftRecipeStackRequestAction. The
|
// AutoCraftRecipeStackRequestAction is sent by the client similarly to the CraftRecipeStackRequestAction. The
|
||||||
// only difference is that the recipe is automatically created and crafted by shift clicking the recipe book.
|
// only difference is that the recipe is automatically created and crafted by shift clicking the recipe book.
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ func (x *TexturePackInfo) Marshal(r protocol.IO) {
|
|||||||
r.String(&x.SubPackName)
|
r.String(&x.SubPackName)
|
||||||
r.String(&x.ContentIdentity)
|
r.String(&x.ContentIdentity)
|
||||||
r.Bool(&x.HasScripts)
|
r.Bool(&x.HasScripts)
|
||||||
|
if IsProtoGTE(r, ID712) {
|
||||||
r.Bool(&x.AddonPack)
|
r.Bool(&x.AddonPack)
|
||||||
|
}
|
||||||
r.Bool(&x.RTXEnabled)
|
r.Bool(&x.RTXEnabled)
|
||||||
if IsProtoGTE(r, ID748) {
|
if IsProtoGTE(r, ID748) {
|
||||||
r.String(&x.DownloadURL)
|
r.String(&x.DownloadURL)
|
||||||
|
|||||||
@@ -233,6 +233,137 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
|
|||||||
Port: pk.Port,
|
Port: pk.Port,
|
||||||
ReloadWorld: pk.ReloadWorld,
|
ReloadWorld: pk.ReloadWorld,
|
||||||
}
|
}
|
||||||
|
case *packet.AddActor:
|
||||||
|
links := make([]proto.EntityLink, len(pk.EntityLinks))
|
||||||
|
for i, l := range pk.EntityLinks {
|
||||||
|
links[i] = (&proto.EntityLink{}).FromLatest(l)
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &legacypacket.AddActor{
|
||||||
|
EntityUniqueID: pk.EntityUniqueID,
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
EntityType: pk.EntityType,
|
||||||
|
Position: pk.Position,
|
||||||
|
Velocity: pk.Velocity,
|
||||||
|
Pitch: pk.Pitch,
|
||||||
|
Yaw: pk.Yaw,
|
||||||
|
HeadYaw: pk.HeadYaw,
|
||||||
|
BodyYaw: pk.BodyYaw,
|
||||||
|
Attributes: pk.Attributes,
|
||||||
|
EntityMetadata: pk.EntityMetadata,
|
||||||
|
EntityProperties: pk.EntityProperties,
|
||||||
|
EntityLinks: links,
|
||||||
|
}
|
||||||
|
case *packet.AddPlayer:
|
||||||
|
links := make([]proto.EntityLink, len(pk.EntityLinks))
|
||||||
|
for i, l := range pk.EntityLinks {
|
||||||
|
links[i] = (&proto.EntityLink{}).FromLatest(l)
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &legacypacket.AddPlayer{
|
||||||
|
UUID: pk.UUID,
|
||||||
|
Username: pk.Username,
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
PlatformChatID: pk.PlatformChatID,
|
||||||
|
Position: pk.Position,
|
||||||
|
Velocity: pk.Velocity,
|
||||||
|
Pitch: pk.Pitch,
|
||||||
|
Yaw: pk.Yaw,
|
||||||
|
HeadYaw: pk.HeadYaw,
|
||||||
|
HeldItem: pk.HeldItem,
|
||||||
|
GameType: pk.GameType,
|
||||||
|
EntityMetadata: pk.EntityMetadata,
|
||||||
|
EntityProperties: pk.EntityProperties,
|
||||||
|
AbilityData: pk.AbilityData,
|
||||||
|
EntityLinks: links,
|
||||||
|
DeviceID: pk.DeviceID,
|
||||||
|
BuildPlatform: pk.BuildPlatform,
|
||||||
|
}
|
||||||
|
case *packet.SetActorLink:
|
||||||
|
pks[pkIndex] = &legacypacket.SetActorLink{
|
||||||
|
EntityLink: (&proto.EntityLink{}).FromLatest(pk.EntityLink),
|
||||||
|
}
|
||||||
|
case *packet.CameraInstruction:
|
||||||
|
pks[pkIndex] = &legacypacket.CameraInstruction{
|
||||||
|
Set: pk.Set,
|
||||||
|
Clear: pk.Clear,
|
||||||
|
Fade: pk.Fade,
|
||||||
|
Target: pk.Target,
|
||||||
|
RemoveTarget: pk.RemoveTarget,
|
||||||
|
}
|
||||||
|
case *packet.ChangeDimension:
|
||||||
|
pks[pkIndex] = &legacypacket.ChangeDimension{
|
||||||
|
Dimension: pk.Dimension,
|
||||||
|
Position: pk.Position,
|
||||||
|
Respawn: pk.Respawn,
|
||||||
|
LoadingScreenID: pk.LoadingScreenID,
|
||||||
|
}
|
||||||
|
case *packet.CorrectPlayerMovePrediction:
|
||||||
|
pks[pkIndex] = &legacypacket.CorrectPlayerMovePrediction{
|
||||||
|
PredictionType: pk.PredictionType,
|
||||||
|
Position: pk.Position,
|
||||||
|
Delta: pk.Delta,
|
||||||
|
Rotation: pk.Rotation,
|
||||||
|
VehicleAngularVelocity: pk.VehicleAngularVelocity,
|
||||||
|
OnGround: pk.OnGround,
|
||||||
|
Tick: pk.Tick,
|
||||||
|
}
|
||||||
|
case *packet.Disconnect:
|
||||||
|
pks[pkIndex] = &legacypacket.Disconnect{
|
||||||
|
Reason: pk.Reason,
|
||||||
|
HideDisconnectionScreen: pk.HideDisconnectionScreen,
|
||||||
|
Message: pk.Message,
|
||||||
|
FilteredMessage: pk.FilteredMessage,
|
||||||
|
}
|
||||||
|
case *packet.EditorNetwork:
|
||||||
|
pks[pkIndex] = &legacypacket.EditorNetwork{
|
||||||
|
RouteToManager: pk.RouteToManager,
|
||||||
|
Payload: pk.Payload,
|
||||||
|
}
|
||||||
|
case *packet.MobArmourEquipment:
|
||||||
|
pks[pkIndex] = &legacypacket.MobArmourEquipment{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
Helmet: pk.Helmet,
|
||||||
|
Chestplate: pk.Chestplate,
|
||||||
|
Leggings: pk.Leggings,
|
||||||
|
Boots: pk.Boots,
|
||||||
|
Body: pk.Body,
|
||||||
|
}
|
||||||
|
case *packet.PlayerArmourDamage:
|
||||||
|
pks[pkIndex] = &legacypacket.PlayerArmourDamage{
|
||||||
|
Bitset: pk.Bitset,
|
||||||
|
HelmetDamage: pk.HelmetDamage,
|
||||||
|
ChestplateDamage: pk.ChestplateDamage,
|
||||||
|
LeggingsDamage: pk.LeggingsDamage,
|
||||||
|
BootsDamage: pk.BootsDamage,
|
||||||
|
BodyDamage: pk.BodyDamage,
|
||||||
|
}
|
||||||
|
case *packet.SetTitle:
|
||||||
|
pks[pkIndex] = &legacypacket.SetTitle{
|
||||||
|
ActionType: pk.ActionType,
|
||||||
|
Text: pk.Text,
|
||||||
|
FadeInDuration: pk.FadeInDuration,
|
||||||
|
RemainDuration: pk.RemainDuration,
|
||||||
|
FadeOutDuration: pk.FadeOutDuration,
|
||||||
|
XUID: pk.XUID,
|
||||||
|
PlatformOnlineID: pk.PlatformOnlineID,
|
||||||
|
FilteredMessage: pk.FilteredMessage,
|
||||||
|
}
|
||||||
|
case *packet.StopSound:
|
||||||
|
pks[pkIndex] = &legacypacket.StopSound{
|
||||||
|
SoundName: pk.SoundName,
|
||||||
|
StopAll: pk.StopAll,
|
||||||
|
StopMusicLegacy: pk.StopMusicLegacy,
|
||||||
|
}
|
||||||
|
case *packet.InventoryTransaction:
|
||||||
|
trData := pk.TransactionData
|
||||||
|
if x, ok := trData.(*protocol.UseItemTransactionData); ok {
|
||||||
|
trData = (&proto.UseItemTransactionData{}).FromLatest(x)
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &legacypacket.InventoryTransaction{
|
||||||
|
LegacyRequestID: pk.LegacyRequestID,
|
||||||
|
LegacySetItemSlots: pk.LegacySetItemSlots,
|
||||||
|
Actions: pk.Actions,
|
||||||
|
TransactionData: trData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +503,137 @@ func (p *Protocol) upgradePackets(pks []packet.Packet, conn *minecraft.Conn) []p
|
|||||||
Port: pk.Port,
|
Port: pk.Port,
|
||||||
ReloadWorld: pk.ReloadWorld,
|
ReloadWorld: pk.ReloadWorld,
|
||||||
}
|
}
|
||||||
|
case *legacypacket.AddActor:
|
||||||
|
links := make([]protocol.EntityLink, len(pk.EntityLinks))
|
||||||
|
for i, l := range pk.EntityLinks {
|
||||||
|
links[i] = l.ToLatest()
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &packet.AddActor{
|
||||||
|
EntityUniqueID: pk.EntityUniqueID,
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
EntityType: pk.EntityType,
|
||||||
|
Position: pk.Position,
|
||||||
|
Velocity: pk.Velocity,
|
||||||
|
Pitch: pk.Pitch,
|
||||||
|
Yaw: pk.Yaw,
|
||||||
|
HeadYaw: pk.HeadYaw,
|
||||||
|
BodyYaw: pk.BodyYaw,
|
||||||
|
Attributes: pk.Attributes,
|
||||||
|
EntityMetadata: pk.EntityMetadata,
|
||||||
|
EntityProperties: pk.EntityProperties,
|
||||||
|
EntityLinks: links,
|
||||||
|
}
|
||||||
|
case *legacypacket.AddPlayer:
|
||||||
|
links := make([]protocol.EntityLink, len(pk.EntityLinks))
|
||||||
|
for i, l := range pk.EntityLinks {
|
||||||
|
links[i] = l.ToLatest()
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &packet.AddPlayer{
|
||||||
|
UUID: pk.UUID,
|
||||||
|
Username: pk.Username,
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
PlatformChatID: pk.PlatformChatID,
|
||||||
|
Position: pk.Position,
|
||||||
|
Velocity: pk.Velocity,
|
||||||
|
Pitch: pk.Pitch,
|
||||||
|
Yaw: pk.Yaw,
|
||||||
|
HeadYaw: pk.HeadYaw,
|
||||||
|
HeldItem: pk.HeldItem,
|
||||||
|
GameType: pk.GameType,
|
||||||
|
EntityMetadata: pk.EntityMetadata,
|
||||||
|
EntityProperties: pk.EntityProperties,
|
||||||
|
AbilityData: pk.AbilityData,
|
||||||
|
EntityLinks: links,
|
||||||
|
DeviceID: pk.DeviceID,
|
||||||
|
BuildPlatform: pk.BuildPlatform,
|
||||||
|
}
|
||||||
|
case *legacypacket.SetActorLink:
|
||||||
|
pks[pkIndex] = &packet.SetActorLink{
|
||||||
|
EntityLink: pk.EntityLink.ToLatest(),
|
||||||
|
}
|
||||||
|
case *legacypacket.CameraInstruction:
|
||||||
|
pks[pkIndex] = &packet.CameraInstruction{
|
||||||
|
Set: pk.Set,
|
||||||
|
Clear: pk.Clear,
|
||||||
|
Fade: pk.Fade,
|
||||||
|
Target: pk.Target,
|
||||||
|
RemoveTarget: pk.RemoveTarget,
|
||||||
|
}
|
||||||
|
case *legacypacket.ChangeDimension:
|
||||||
|
pks[pkIndex] = &packet.ChangeDimension{
|
||||||
|
Dimension: pk.Dimension,
|
||||||
|
Position: pk.Position,
|
||||||
|
Respawn: pk.Respawn,
|
||||||
|
LoadingScreenID: pk.LoadingScreenID,
|
||||||
|
}
|
||||||
|
case *legacypacket.CorrectPlayerMovePrediction:
|
||||||
|
pks[pkIndex] = &packet.CorrectPlayerMovePrediction{
|
||||||
|
PredictionType: pk.PredictionType,
|
||||||
|
Position: pk.Position,
|
||||||
|
Delta: pk.Delta,
|
||||||
|
Rotation: pk.Rotation,
|
||||||
|
VehicleAngularVelocity: pk.VehicleAngularVelocity,
|
||||||
|
OnGround: pk.OnGround,
|
||||||
|
Tick: pk.Tick,
|
||||||
|
}
|
||||||
|
case *legacypacket.Disconnect:
|
||||||
|
pks[pkIndex] = &packet.Disconnect{
|
||||||
|
Reason: pk.Reason,
|
||||||
|
HideDisconnectionScreen: pk.HideDisconnectionScreen,
|
||||||
|
Message: pk.Message,
|
||||||
|
FilteredMessage: pk.FilteredMessage,
|
||||||
|
}
|
||||||
|
case *legacypacket.EditorNetwork:
|
||||||
|
pks[pkIndex] = &packet.EditorNetwork{
|
||||||
|
RouteToManager: pk.RouteToManager,
|
||||||
|
Payload: pk.Payload,
|
||||||
|
}
|
||||||
|
case *legacypacket.MobArmourEquipment:
|
||||||
|
pks[pkIndex] = &packet.MobArmourEquipment{
|
||||||
|
EntityRuntimeID: pk.EntityRuntimeID,
|
||||||
|
Helmet: pk.Helmet,
|
||||||
|
Chestplate: pk.Chestplate,
|
||||||
|
Leggings: pk.Leggings,
|
||||||
|
Boots: pk.Boots,
|
||||||
|
Body: pk.Body,
|
||||||
|
}
|
||||||
|
case *legacypacket.PlayerArmourDamage:
|
||||||
|
pks[pkIndex] = &packet.PlayerArmourDamage{
|
||||||
|
Bitset: pk.Bitset,
|
||||||
|
HelmetDamage: pk.HelmetDamage,
|
||||||
|
ChestplateDamage: pk.ChestplateDamage,
|
||||||
|
LeggingsDamage: pk.LeggingsDamage,
|
||||||
|
BootsDamage: pk.BootsDamage,
|
||||||
|
BodyDamage: pk.BodyDamage,
|
||||||
|
}
|
||||||
|
case *legacypacket.SetTitle:
|
||||||
|
pks[pkIndex] = &packet.SetTitle{
|
||||||
|
ActionType: pk.ActionType,
|
||||||
|
Text: pk.Text,
|
||||||
|
FadeInDuration: pk.FadeInDuration,
|
||||||
|
RemainDuration: pk.RemainDuration,
|
||||||
|
FadeOutDuration: pk.FadeOutDuration,
|
||||||
|
XUID: pk.XUID,
|
||||||
|
PlatformOnlineID: pk.PlatformOnlineID,
|
||||||
|
FilteredMessage: pk.FilteredMessage,
|
||||||
|
}
|
||||||
|
case *legacypacket.StopSound:
|
||||||
|
pks[pkIndex] = &packet.StopSound{
|
||||||
|
SoundName: pk.SoundName,
|
||||||
|
StopAll: pk.StopAll,
|
||||||
|
StopMusicLegacy: pk.StopMusicLegacy,
|
||||||
|
}
|
||||||
|
case *legacypacket.InventoryTransaction:
|
||||||
|
trData := pk.TransactionData
|
||||||
|
if x, ok := trData.(*proto.UseItemTransactionData); ok {
|
||||||
|
trData = x.ToLatest()
|
||||||
|
}
|
||||||
|
pks[pkIndex] = &packet.InventoryTransaction{
|
||||||
|
LegacyRequestID: pk.LegacyRequestID,
|
||||||
|
LegacySetItemSlots: pk.LegacySetItemSlots,
|
||||||
|
Actions: pk.Actions,
|
||||||
|
TransactionData: trData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pks
|
return pks
|
||||||
|
|||||||
28
legacyver/v685.go
Normal file
28
legacyver/v685.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package legacyver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/akmalfairuz/legacy-version/internal/chunk"
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/akmalfairuz/legacy-version/mapping"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ItemVersion685 ...
|
||||||
|
ItemVersion685 = 191
|
||||||
|
// BlockVersion685 ...
|
||||||
|
BlockVersion685 int32 = (1 << 24) | (21 << 16) | (0 << 8)
|
||||||
|
)
|
||||||
|
|
||||||
|
// New685 uses same data as 686
|
||||||
|
func New685(direct bool) *Protocol {
|
||||||
|
itemMapping := mapping.NewItemMapping(itemRuntimeIDData686, requiredItemList686, ItemVersion685, false)
|
||||||
|
blockMapping := mapping.NewBlockMapping(blockStateData686)
|
||||||
|
|
||||||
|
return &Protocol{
|
||||||
|
ver: "1.21.0",
|
||||||
|
id: proto.ID685,
|
||||||
|
blockTranslator: NewBlockTranslator(blockMapping, latestBlockMapping, chunk.NewNetworkPersistentEncoding(blockMapping, BlockVersion685), chunk.NewBlockPaletteEncoding(blockMapping, BlockVersion685), false),
|
||||||
|
itemTranslator: NewItemTranslator(itemMapping, itemMappingLatest, blockMapping, blockMappingLatest),
|
||||||
|
}
|
||||||
|
}
|
||||||
36
legacyver/v686.go
Normal file
36
legacyver/v686.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package legacyver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/akmalfairuz/legacy-version/internal/chunk"
|
||||||
|
"github.com/akmalfairuz/legacy-version/legacyver/proto"
|
||||||
|
"github.com/akmalfairuz/legacy-version/mapping"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ItemVersion686 ...
|
||||||
|
ItemVersion686 = 191
|
||||||
|
// BlockVersion686 ...
|
||||||
|
BlockVersion686 int32 = (1 << 24) | (21 << 16) | (2 << 8)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed data/item_runtime_ids_686.nbt
|
||||||
|
itemRuntimeIDData686 []byte
|
||||||
|
//go:embed data/required_item_list_686.json
|
||||||
|
requiredItemList686 []byte
|
||||||
|
//go:embed data/block_states_686.nbt
|
||||||
|
blockStateData686 []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func New686(direct bool) *Protocol {
|
||||||
|
itemMapping := mapping.NewItemMapping(itemRuntimeIDData686, requiredItemList686, ItemVersion686, false)
|
||||||
|
blockMapping := mapping.NewBlockMapping(blockStateData686)
|
||||||
|
|
||||||
|
return &Protocol{
|
||||||
|
ver: "1.21.2",
|
||||||
|
id: proto.ID686,
|
||||||
|
blockTranslator: NewBlockTranslator(blockMapping, latestBlockMapping, chunk.NewNetworkPersistentEncoding(blockMapping, BlockVersion686), chunk.NewBlockPaletteEncoding(blockMapping, BlockVersion686), false),
|
||||||
|
itemTranslator: NewItemTranslator(itemMapping, itemMappingLatest, blockMapping, blockMappingLatest),
|
||||||
|
}
|
||||||
|
}
|
||||||
4
main.go
4
main.go
@@ -29,6 +29,10 @@ func main() {
|
|||||||
StatusProvider: p,
|
StatusProvider: p,
|
||||||
AcceptedProtocols: []minecraft.Protocol{
|
AcceptedProtocols: []minecraft.Protocol{
|
||||||
legacyver.New748(false),
|
legacyver.New748(false),
|
||||||
|
legacyver.New729(false),
|
||||||
|
legacyver.New712(false),
|
||||||
|
legacyver.New686(false),
|
||||||
|
legacyver.New685(false),
|
||||||
},
|
},
|
||||||
}.Listen("raknet", config.Connection.LocalAddress)
|
}.Listen("raknet", config.Connection.LocalAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user