Skip to content

Commit

Permalink
protocol: Initial 1.20.30 support
Browse files Browse the repository at this point in the history
  • Loading branch information
TwistedAsylumMC committed Sep 19, 2023
1 parent b290697 commit 51e9ccc
Show file tree
Hide file tree
Showing 18 changed files with 255 additions and 18 deletions.
4 changes: 2 additions & 2 deletions minecraft/conn.go
Expand Up @@ -1021,7 +1021,7 @@ func (conn *Conn) startGame() {
WorldSeed: data.WorldSeed,
Dimension: data.Dimension,
WorldSpawn: data.WorldSpawn,
EditorWorld: data.EditorWorld,
EditorWorldType: data.EditorWorldType,
CreatedInEditor: data.CreatedInEditor,
ExportedFromEditor: data.ExportedFromEditor,
PersonaDisabled: data.PersonaDisabled,
Expand Down Expand Up @@ -1220,7 +1220,7 @@ func (conn *Conn) handleStartGame(pk *packet.StartGame) error {
Yaw: pk.Yaw,
Dimension: pk.Dimension,
WorldSpawn: pk.WorldSpawn,
EditorWorld: pk.EditorWorld,
EditorWorldType: pk.EditorWorldType,
CreatedInEditor: pk.CreatedInEditor,
ExportedFromEditor: pk.ExportedFromEditor,
PersonaDisabled: pk.PersonaDisabled,
Expand Down
4 changes: 2 additions & 2 deletions minecraft/game_data.go
Expand Up @@ -53,9 +53,9 @@ type GameData struct {
// WorldSpawn is the block on which the world spawn of the world. This coordinate has no effect on the
// place that the client spawns, but it does have an effect on the direction that a compass points.
WorldSpawn protocol.BlockPos
// EditorWorld is a value to dictate if the world is in editor mode, a special mode recently introduced adding
// EditorWorldType is a value to dictate the type of editor mode, a special mode recently introduced adding
// "powerful tools for editing worlds, intended for experienced creators."
EditorWorld bool
EditorWorldType int32
// CreatedInEditor is a value to dictate if the world was created as a project in the editor mode. The functionality
// of this field is currently unknown.
CreatedInEditor bool
Expand Down
159 changes: 159 additions & 0 deletions minecraft/protocol/camera.go
@@ -0,0 +1,159 @@
package protocol

import (
"github.com/go-gl/mathgl/mgl32"
"image/color"
)

const (
AudioListenerCamera = iota
AudioListenerPlayer
)

const (
EasingTypeLinear = iota
EasingTypeSpring
EasingTypeInQuad
EasingTypeOutQuad
EasingTypeInOutQuad
EasingTypeInCubic
EasingTypeOutCubic
EasingTypeInOutCubic
EasingTypeInQuart
EasingTypeOutQuart
EasingTypeInOutQuart
EasingTypeInQuint
EasingTypeOutQuint
EasingTypeInOutQuint
EasingTypeInSine
EasingTypeOutSine
EasingTypeInOutSine
EasingTypeInExpo
EasingTypeOutExpo
EasingTypeInOutExpo
EasingTypeInCirc
EasingTypeOutCirc
EasingTypeInOutCirc
EasingTypeInBounce
EasingTypeOutBounce
EasingTypeInOutBounce
EasingTypeInBack
EasingTypeOutBack
EasingTypeInOutBack
EasingTypeInElastic
EasingTypeOutElastic
EasingTypeInOutElastic
)

// CameraEase represents an easing function that can be used by a CameraInstructionSet.
type CameraEase struct {
// Type is the type of easing function used. This is one of the constants above.
Type uint8
// Duration is the time in seconds that the easing function should take.
Duration float32
}

// Marshal encodes/decodes a CameraEase.
func (x *CameraEase) Marshal(r IO) {
r.Uint8(&x.Type)
r.Float32(&x.Duration)
}

type CameraInstruction struct {
// Set is a camera instruction that sets the camera to a specified preset.
Set Optional[CameraInstructionSet]
// Clear can be set to true to clear all the current camera instructions.
Clear Optional[bool]
// Fade is a camera instruction that fades the screen to a specified colour.
Fade Optional[CameraInstructionFade]
}

// Marshal encodes/decodes a CameraInstruction.
func (x *CameraInstruction) Marshal(r IO) {
OptionalMarshaler(r, &x.Set)
OptionalFunc(r, &x.Clear, r.Bool)
OptionalMarshaler(r, &x.Fade)
}

// CameraInstructionSet represents a camera instruction that sets the camera to a specified preset and can be extended
// with easing functions and translations to the camera's position and rotation.
type CameraInstructionSet struct {
// Preset is the index of the preset in the CameraPresets packet sent to the player.
Preset uint32
// Ease represents the easing function that is used by the instruction.
Ease Optional[CameraEase]
// Position represents the position of the camera.
Position Optional[mgl32.Vec3]
// Rotation represents the rotation of the camera.
Rotation Optional[mgl32.Vec2]
// Facing is a vector that the camera will always face towards during the duration of the instruction.
Facing Optional[mgl32.Vec3]
// Default determines whether the camera is a default camera or not.
Default Optional[bool]
}

// Marshal encodes/decodes a CameraInstructionSet.
func (x *CameraInstructionSet) Marshal(r IO) {
r.Uint32(&x.Preset)
OptionalMarshaler(r, &x.Ease)
OptionalFunc(r, &x.Position, r.Vec3)
OptionalFunc(r, &x.Rotation, r.Vec2)
OptionalFunc(r, &x.Facing, r.Vec3)
OptionalFunc(r, &x.Default, r.Bool)
}

// CameraInstructionFade represents a camera instruction that fades the screen to a specified colour.
type CameraInstructionFade struct {
// FadeInDuration is the time in seconds for the screen to fully fade in.
FadeInDuration float32
// WaitDuration is time in seconds to wait before fading out.
WaitDuration float32
// FadeOutDuration is the time in seconds for the screen to fully fade out.
FadeOutDuration float32
// Colour is the colour of the screen to fade to. This only uses the red, green and blue components.
Colour color.RGBA
}

// Marshal encodes/decodes a CameraInstructionFade.
func (x *CameraInstructionFade) Marshal(r IO) {
r.Float32(&x.FadeInDuration)
r.Float32(&x.WaitDuration)
r.Float32(&x.FadeOutDuration)
r.RGB(&x.Colour)
}

// CameraPreset represents a basic preset that can be extended upon by more complex instructions.
type CameraPreset struct {
// Name is the name of the preset. Each preset must have their own unique name.
Name string
// Parent is the name of the preset that this preset extends upon. This can be left empty.
Parent string
// PosX ...
PosX Optional[float32]
// PosY ...
PosY Optional[float32]
// PosZ ...
PosZ Optional[float32]
// RotX ...
RotX Optional[float32]
// RotY ...
RotY Optional[float32]
// AudioListener defines where the audio should be played from when using this preset. This is one of the constants
// above.
AudioListener Optional[byte]
// PlayerEffects ...
PlayerEffects Optional[bool]
}

// Marshal encodes/decodes a CameraPreset.
func (x *CameraPreset) Marshal(r IO) {
r.String(&x.Name)
r.String(&x.Parent)
OptionalFunc(r, &x.PosX, r.Float32)
OptionalFunc(r, &x.PosY, r.Float32)
OptionalFunc(r, &x.PosZ, r.Float32)
OptionalFunc(r, &x.RotX, r.Float32)
OptionalFunc(r, &x.RotY, r.Float32)
OptionalFunc(r, &x.AudioListener, r.Uint8)
OptionalFunc(r, &x.PlayerEffects, r.Bool)
}
4 changes: 2 additions & 2 deletions minecraft/protocol/info.go
Expand Up @@ -2,7 +2,7 @@ package protocol

const (
// CurrentProtocol is the current protocol version for the version below.
CurrentProtocol = 594
CurrentProtocol = 618
// CurrentVersion is the current version of Minecraft as supported by the `packet` package.
CurrentVersion = "1.20.10"
CurrentVersion = "1.20.30"
)
1 change: 1 addition & 0 deletions minecraft/protocol/io.go
Expand Up @@ -41,6 +41,7 @@ type IO interface {
NBT(m *map[string]any, encoding nbt.Encoding)
NBTList(m *[]any, encoding nbt.Encoding)
UUID(x *uuid.UUID)
RGB(x *color.RGBA)
RGBA(x *color.RGBA)
VarRGBA(x *color.RGBA)
EntityMetadata(x *map[uint32]any)
Expand Down
7 changes: 3 additions & 4 deletions minecraft/protocol/packet/camera_instruction.go
@@ -1,14 +1,13 @@
package packet

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

// CameraInstruction gives a custom camera specific instructions to operate.
type CameraInstruction struct {
// Data is a compound tag of the instructions to sent. The structure of this tag is currently unknown.
Data map[string]any
// Instructions is a list of the instructions that should be executed by the camera.
Instructions []protocol.CameraInstruction
}

// ID ...
Expand All @@ -17,5 +16,5 @@ func (*CameraInstruction) ID() uint32 {
}

func (pk *CameraInstruction) Marshal(io protocol.IO) {
io.NBT(&pk.Data, nbt.NetworkLittleEndian)
protocol.Slice(io, &pk.Instructions)
}
8 changes: 4 additions & 4 deletions minecraft/protocol/packet/camera_presets.go
@@ -1,14 +1,14 @@
package packet

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

// CameraPresets gives the client a list of custom camera presets.
type CameraPresets struct {
// Data is a compound tag of the presets being set. The structure of this tag is currently unknown.
Data map[string]any
// Presets is a list of camera presets that can be used by other cameras. The order of this list is important because
// the index of presets is used as a pointer in the CameraInstruction packet.
Presets []protocol.CameraPreset
}

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

func (pk *CameraPresets) Marshal(io protocol.IO) {
io.NBT(&pk.Data, nbt.NetworkLittleEndian)
protocol.Slice(io, &pk.Presets)
}
1 change: 1 addition & 0 deletions minecraft/protocol/packet/id.go
Expand Up @@ -205,4 +205,5 @@ const (
IDTrimData
IDOpenSign
IDAgentAnimation
IDRefreshEntitlements
)
7 changes: 7 additions & 0 deletions minecraft/protocol/packet/level_sound_event.go
Expand Up @@ -477,6 +477,13 @@ const (
SoundEventSnifferEggHatched
SoundEventWaxedSignInteractFail
SoundEventRecordRelic
SoundEventBump
SoundEventPumpkinCarve
SoundEventConvertHuskToZombie
SoundEventPigDeath
SoundEventHoglinZombified
SoundEventAmbientUnderwaterEnter
SoundEventAmbientUnderwaterExit
)

// LevelSoundEvent is sent by the server to make any kind of built-in sound heard to a player. It is sent to,
Expand Down
2 changes: 2 additions & 0 deletions minecraft/protocol/packet/player_auth_input.go
Expand Up @@ -48,6 +48,8 @@ const (
InputFlagMissedSwing
InputFlagStartCrawling
InputFlagStopCrawling
InputFlagStartFlying
InputFlagStopFlying
)

const (
Expand Down
1 change: 1 addition & 0 deletions minecraft/protocol/packet/pool.go
Expand Up @@ -250,6 +250,7 @@ func init() {
IDTrimData: func() Packet { return &TrimData{} },
IDOpenSign: func() Packet { return &OpenSign{} },
IDAgentAnimation: func() Packet { return &AgentAnimation{} },
IDRefreshEntitlements: func() Packet { return &RefreshEntitlements{} },
}
for id, pk := range serverOriginating {
RegisterPacketFromServer(id, pk)
Expand Down
15 changes: 15 additions & 0 deletions minecraft/protocol/packet/refresh_entitlements.go
@@ -0,0 +1,15 @@
package packet

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

// RefreshEntitlements is sent by the client to the server to refresh the entitlements of the player.
type RefreshEntitlements struct{}

// ID ...
func (*RefreshEntitlements) ID() uint32 {
return IDRefreshEntitlements
}

func (*RefreshEntitlements) Marshal(protocol.IO) {}
4 changes: 4 additions & 0 deletions minecraft/protocol/packet/resource_packs_info.go
Expand Up @@ -23,6 +23,9 @@ type ResourcePacksInfo struct {
TexturePacks []protocol.TexturePackInfo
// ForcingServerPacks is currently an unclear field.
ForcingServerPacks bool
// PackURLs is a list of URLs that the client can use to download a resource pack instead of downloading
// it the usual way.
PackURLs []protocol.PackURL
}

// ID ...
Expand All @@ -36,4 +39,5 @@ func (pk *ResourcePacksInfo) Marshal(io protocol.IO) {
io.Bool(&pk.ForcingServerPacks)
protocol.SliceUint16Length(io, &pk.BehaviourPacks)
protocol.SliceUint16Length(io, &pk.TexturePacks)
protocol.Slice(io, &pk.PackURLs)
}
14 changes: 10 additions & 4 deletions minecraft/protocol/packet/start_game.go
Expand Up @@ -18,6 +18,12 @@ const (
ChatRestrictionLevelDisabled = 2
)

const (
EditorWorldTypeNotEditor = iota
EditorWorldTypeProject
EditorWorldTypeTestLevel
)

// StartGame is sent by the server to send information about the world the player will be spawned in. It
// contains information about the position the player spawns in, and information about the world in general
// such as its game rules.
Expand Down Expand Up @@ -72,9 +78,9 @@ type StartGame struct {
// value is set to true while the player's or the world's game mode is creative, and it's recommended to
// simply always set this to false as a server.
AchievementsDisabled bool
// EditorWorld is a value to dictate if the world is in editor mode, a special mode recently introduced adding
// "powerful tools for editing worlds, intended for experienced creators."
EditorWorld bool
// EditorWorldType is a value to dictate the type of editor mode, a special mode recently introduced adding
// "powerful tools for editing worlds, intended for experienced creators." It is one of the constants above.
EditorWorldType int32
// CreatedInEditor is a value to dictate if the world was created as a project in the editor mode. The functionality
// of this field is currently unknown.
CreatedInEditor bool
Expand Down Expand Up @@ -262,7 +268,7 @@ func (pk *StartGame) Marshal(io protocol.IO) {
io.Varint32(&pk.Difficulty)
io.UBlockPos(&pk.WorldSpawn)
io.Bool(&pk.AchievementsDisabled)
io.Bool(&pk.EditorWorld)
io.Varint32(&pk.EditorWorldType)
io.Bool(&pk.CreatedInEditor)
io.Bool(&pk.ExportedFromEditor)
io.Varint32(&pk.DayCycleLockTime)
Expand Down
2 changes: 2 additions & 0 deletions minecraft/protocol/player.go
Expand Up @@ -39,6 +39,8 @@ const (
PlayerActionMissedSwing
PlayerActionStartCrawling
PlayerActionStopCrawling
PlayerActionStartFlying
PlayerActionStopFlying
)

const (
Expand Down
13 changes: 13 additions & 0 deletions minecraft/protocol/reader.go
Expand Up @@ -162,6 +162,19 @@ func (r *Reader) ByteFloat(x *float32) {
*x = float32(v) * (360.0 / 256.0)
}

// RGB reads a color.RGBA x from three float32s.
func (r *Reader) RGB(x *color.RGBA) {
var red, green, blue float32
r.Float32(&red)
r.Float32(&green)
r.Float32(&blue)
*x = color.RGBA{
R: uint8(red * 255),
G: uint8(green * 255),
B: uint8(blue * 255),
}
}

// RGBA reads a color.RGBA x from a uint32.
func (r *Reader) RGBA(x *color.RGBA) {
var v uint32
Expand Down

0 comments on commit 51e9ccc

Please sign in to comment.