Skip to content

Commit

Permalink
Update login and joingame packets
Browse files Browse the repository at this point in the history
  • Loading branch information
robinbraemer committed Dec 28, 2023
1 parent f7389c9 commit 279fb54
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 8 deletions.
227 changes: 222 additions & 5 deletions pkg/edition/java/proto/packet/joingame.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ type JoinGame struct {
ViewDistance int // 1.14+
ReducedDebugInfo bool
ShowRespawnScreen bool
DoLimitedCrafting bool // 1.20.2+
LevelNames []string // a set of strings, 1.16+
Registry util.NBT // 1.16+
DimensionInfo *DimensionInfo // 1.16+
CurrentDimensionData util.NBT // 1.16.2+
PreviousGamemode int16 // 1.16+
SimulationDistance int // 1.18+
LastDeadPosition *DeathPosition // 1.19+
LastDeathPosition *DeathPosition // 1.19+
PortalCooldown int // 1.20+
}

Expand Down Expand Up @@ -90,7 +91,10 @@ func (d *DeathPosition) String() string {
}

func (j *JoinGame) Encode(c *proto.PacketContext, wr io.Writer) error {
if c.Protocol.GreaterEqual(version.Minecraft_1_16) {
if c.Protocol.GreaterEqual(version.Minecraft_1_20_2) {
// they made 1.20.2 more complicated
return j.encode1202Up(c, wr)
} else if c.Protocol.GreaterEqual(version.Minecraft_1_16) {
// Minecraft 1.16 and above have significantly more complicated logic for writing this packet,
// so separate it out.
return j.encode116Up(c, wr)
Expand Down Expand Up @@ -204,7 +208,7 @@ func (j *JoinGame) encode116Up(c *proto.PacketContext, wr io.Writer) error {
}

if c.Protocol.GreaterEqual(version.Minecraft_1_19) {
err = j.LastDeadPosition.encode(wr)
err = j.LastDeathPosition.encode(wr)
if err != nil {
return err
}
Expand Down Expand Up @@ -288,9 +292,116 @@ func (j *JoinGame) encodeLegacy(c *proto.PacketContext, wr io.Writer) error {
}
return nil
}
func (j *JoinGame) encode1202Up(c *proto.PacketContext, wr io.Writer) error {
err := util.WriteInt(wr, j.EntityID)
if err != nil {
return err
}
err = util.WriteBool(wr, j.Hardcore)
if err != nil {
return err
}

err = util.WriteStrings(wr, j.LevelNames)
if err != nil {
return err
}

err = util.WriteVarInt(wr, j.MaxPlayers)
if err != nil {
return err
}

err = util.WriteVarInt(wr, j.ViewDistance)
if err != nil {
return err
}
err = util.WriteVarInt(wr, j.SimulationDistance)
if err != nil {
return err
}

err = util.WriteBool(wr, j.ReducedDebugInfo)
if err != nil {
return err
}
err = util.WriteBool(wr, j.ShowRespawnScreen)
if err != nil {
return err
}
err = util.WriteBool(wr, j.DoLimitedCrafting)
if err != nil {
return err
}

err = util.WriteString(wr, j.DimensionInfo.RegistryIdentifier)
if err != nil {
return err
}
if j.DimensionInfo.LevelName == nil {
return errors.New("dimension info level name must not be nil")
}
err = util.WriteString(wr, *j.DimensionInfo.LevelName)
if err != nil {
return err
}
err = util.WriteInt64(wr, j.PartialHashedSeed)
if err != nil {
return err
}

err = util.WriteByte(wr, byte(j.Gamemode))
if err != nil {
return err
}
err = util.WriteByte(wr, byte(j.PreviousGamemode))
if err != nil {
return err
}

err = util.WriteBool(wr, j.DimensionInfo.DebugType)
if err != nil {
return err
}
err = util.WriteBool(wr, j.DimensionInfo.Flat)
if err != nil {
return err
}

// optional death location
if j.LastDeathPosition != nil {
err = util.WriteBool(wr, true)
if err != nil {
return err
}
err = util.WriteString(wr, j.LastDeathPosition.Key)
if err != nil {
return err
}
err = util.WriteInt64(wr, j.LastDeathPosition.Value)
if err != nil {
return err
}
} else {
err = util.WriteBool(wr, false)
if err != nil {
return err
}
}

err = util.WriteVarInt(wr, j.PortalCooldown)
if err != nil {
return err
}

return nil
}

func (j *JoinGame) Decode(c *proto.PacketContext, rd io.Reader) (err error) {
if c.Protocol.GreaterEqual(version.Minecraft_1_16) {
if c.Protocol.GreaterEqual(version.Minecraft_1_20_2) {
// they made 1.20.2 more complicated
return j.decode1202Up(c, rd)
} else if c.Protocol.GreaterEqual(version.Minecraft_1_16) {
// Minecraft 1.16 and above have significantly more complicated logic for reading this packet,
// so separate it out.
return j.decode116Up(c, rd)
Expand Down Expand Up @@ -481,7 +592,7 @@ func (j *JoinGame) decode116Up(c *proto.PacketContext, rd io.Reader) (err error)

// optional death location
if c.Protocol.GreaterEqual(version.Minecraft_1_19) {
j.LastDeadPosition, err = decodeDeathPosition(rd)
j.LastDeathPosition, err = decodeDeathPosition(rd)
if err != nil {
return err
}
Expand All @@ -496,4 +607,110 @@ func (j *JoinGame) decode116Up(c *proto.PacketContext, rd io.Reader) (err error)
return nil
}

func (j *JoinGame) decode1202Up(c *proto.PacketContext, rd io.Reader) error {
var err error
j.EntityID, err = util.ReadInt(rd)
if err != nil {
return err
}
j.Hardcore, err = util.ReadBool(rd)
if err != nil {
return err
}

j.LevelNames, err = util.ReadStringArray(rd)
if err != nil {
return err
}

j.MaxPlayers, err = util.ReadVarInt(rd)
if err != nil {
return err
}

j.ViewDistance, err = util.ReadVarInt(rd)
if err != nil {
return err
}
j.SimulationDistance, err = util.ReadVarInt(rd)
if err != nil {
return err
}

j.ReducedDebugInfo, err = util.ReadBool(rd)
if err != nil {
return err
}
j.ShowRespawnScreen, err = util.ReadBool(rd)
if err != nil {
return err
}
j.DoLimitedCrafting, err = util.ReadBool(rd)
if err != nil {
return err
}

dimensionIdentifier, err := util.ReadString(rd)
if err != nil {
return err
}
levelName, err := util.ReadString(rd)
if err != nil {
return err
}
j.PartialHashedSeed, err = util.ReadInt64(rd)
if err != nil {
return err
}

gamemode, err := util.ReadByte(rd)
if err != nil {
return err
}
j.Gamemode = int16(gamemode)

previousGamemode, err := util.ReadByte(rd)
if err != nil {
return err
}
j.PreviousGamemode = int16(previousGamemode)

isDebug, err := util.ReadBool(rd)
if err != nil {
return err
}
isFlat, err := util.ReadBool(rd)
if err != nil {
return err
}
j.DimensionInfo = &DimensionInfo{
RegistryIdentifier: dimensionIdentifier,
LevelName: &levelName,
Flat: isFlat,
DebugType: isDebug,
}

// optional death location
if ok, err := util.ReadBool(rd); err != nil {
return err
} else if ok {
key, err := util.ReadString(rd)
if err != nil {
return err
}
value, err := util.ReadInt64(rd)
if err != nil {
return err
}
j.LastDeathPosition = &DeathPosition{Key: key, Value: value}
}

j.PortalCooldown, err = util.ReadVarInt(rd)
if err != nil {
return err
}

return nil
}

var _ proto.Packet = (*JoinGame)(nil)
16 changes: 16 additions & 0 deletions pkg/edition/java/proto/packet/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ func (s *ServerLogin) Encode(c *proto.PacketContext, wr io.Writer) error {
}
}

if c.Protocol.GreaterEqual(version.Minecraft_1_20_2) {
err = util.WriteUUID(wr, s.HolderID)
if err != nil {
return err
}
return nil
}

if c.Protocol.GreaterEqual(version.Minecraft_1_19_1) {
okPlayerKey := s.PlayerKey != nil && s.PlayerKey.SignatureHolder() != uuid.Nil
ok := okPlayerKey || s.HolderID != uuid.Nil
Expand Down Expand Up @@ -94,6 +102,14 @@ func (s *ServerLogin) Decode(c *proto.PacketContext, rd io.Reader) (err error) {
}
}

if c.Protocol.GreaterEqual(version.Minecraft_1_20_2) {
s.HolderID, err = util.ReadUUID(rd)
if err != nil {
return err
}
return
}

if c.Protocol.GreaterEqual(version.Minecraft_1_19_1) {
ok, err := util.ReadBool(rd)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/edition/java/proto/packet/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ var packets = []proto.Packet{
LevelNames: []string{"test", "test2"},
PreviousGamemode: 2,
SimulationDistance: 3,
LastDeadPosition: mustFake(&DeathPosition{}),
LastDeathPosition: mustFake(&DeathPosition{}),
CurrentDimensionData: map[string]any{},
Registry: map[string]any{},
},
Expand Down
7 changes: 6 additions & 1 deletion pkg/edition/java/proxy/session_backend_play.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ func (b *backendPlaySessionHandler) handleServerData(p *packet.ServerData) {

var sha1HexRegex = regexp.MustCompile(`[0-9a-fA-F]{40}`)

// possibleResourcePackHash returns true if the given hash is a plausible SHA-1 hash.
func possibleResourcePackHash(hash string) bool {
return sha1HexRegex.MatchString(hash)
}

func toServerPromptedResourcePack(p *packet.ResourcePackRequest) (ResourcePackInfo, error) {
if p.URL == "" {
return ResourcePackInfo{}, fmt.Errorf("resource pack URL is empty")
Expand All @@ -248,7 +253,7 @@ func toServerPromptedResourcePack(p *packet.ResourcePackRequest) (ResourcePackIn
Prompt: p.Prompt,
Origin: DownstreamServerResourcePackOrigin,
}
if p.Hash != "" && sha1HexRegex.MatchString(p.Hash) {
if p.Hash != "" && possibleResourcePackHash(p.Hash) {
var err error
packInfo.Hash, err = hex.DecodeString(p.Hash)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/edition/java/proxy/session_client_play.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func respawnFromJoinGame(joinGame *packet.JoinGame) *packet.Respawn {
DimensionInfo: joinGame.DimensionInfo,
PreviousGamemode: joinGame.PreviousGamemode,
CurrentDimensionData: joinGame.CurrentDimensionData,
LastDeathPosition: joinGame.LastDeadPosition,
LastDeathPosition: joinGame.LastDeathPosition,
PortalCooldown: joinGame.PortalCooldown,
}
}
Expand Down

0 comments on commit 279fb54

Please sign in to comment.