update to 1.18.2 & fix bug in snbt encoding

This commit is contained in:
Tnze
2022-03-10 12:29:03 +08:00
parent 0bbd279dd1
commit 46b021e1ef
18 changed files with 70 additions and 2147 deletions

View File

@ -1,6 +1,6 @@
# Go-MC # Go-MC
![Version](https://img.shields.io/badge/Minecraft-1.18-blue.svg) ![Version](https://img.shields.io/badge/Minecraft-1.18.2-blue.svg)
[![Go Reference](https://pkg.go.dev/badge/github.com/Tnze/go-mc.svg)](https://pkg.go.dev/github.com/Tnze/go-mc) [![Go Reference](https://pkg.go.dev/badge/github.com/Tnze/go-mc.svg)](https://pkg.go.dev/github.com/Tnze/go-mc)
[![Go Report Card](https://goreportcard.com/badge/github.com/Tnze/go-mc)](https://goreportcard.com/report/github.com/Tnze/go-mc) [![Go Report Card](https://goreportcard.com/badge/github.com/Tnze/go-mc)](https://goreportcard.com/report/github.com/Tnze/go-mc)
[![Build Status](https://travis-ci.org/Tnze/go-mc.svg?branch=master)](https://travis-ci.org/Tnze/go-mc) [![Build Status](https://travis-ci.org/Tnze/go-mc.svg?branch=master)](https://travis-ci.org/Tnze/go-mc)

View File

@ -10,11 +10,8 @@ import (
// WorldInfo content player info in server. // WorldInfo content player info in server.
type WorldInfo struct { type WorldInfo struct {
DimensionCodec struct { DimensionCodec nbt.StringifiedMessage
DimensionType interface{} `nbt:"minecraft:dimension_type"` Dimension nbt.StringifiedMessage
WorldgenBiome interface{} `nbt:"minecraft:worldgen/biome"`
}
Dimension interface{}
WorldNames []string // Identifiers for all worlds on the server. WorldNames []string // Identifiers for all worlds on the server.
WorldName string // Name of the world being spawned into. WorldName string // Name of the world being spawned into.
HashedSeed int64 // First 8 bytes of the SHA-256 hash of the world's seed. Used client side for biome noise HashedSeed int64 // First 8 bytes of the SHA-256 hash of the world's seed. Used client side for biome noise
@ -49,8 +46,8 @@ func (p *Player) handleLoginPacket(packet pk.Packet) error {
(*pk.Byte)(&p.PrevGamemode), (*pk.Byte)(&p.PrevGamemode),
&WorldCount, &WorldCount,
pk.Ary{Len: &WorldCount, Ary: &WorldNames}, pk.Ary{Len: &WorldCount, Ary: &WorldNames},
pk.NBT(new(nbt.RawMessage)), pk.NBT(&p.WorldInfo.DimensionCodec),
pk.NBT(new(nbt.RawMessage)), pk.NBT(&p.WorldInfo.Dimension),
(*pk.Identifier)(&p.WorldName), (*pk.Identifier)(&p.WorldName),
(*pk.Long)(&p.HashedSeed), (*pk.Long)(&p.HashedSeed),
(*pk.VarInt)(&p.MaxPlayers), (*pk.VarInt)(&p.MaxPlayers),

View File

@ -6,6 +6,7 @@ package bot
import ( import (
"context" "context"
"errors"
"net" "net"
"strconv" "strconv"
@ -16,7 +17,7 @@ import (
) )
// ProtocolVersion is the protocol version number of minecraft net protocol // ProtocolVersion is the protocol version number of minecraft net protocol
const ProtocolVersion = 757 const ProtocolVersion = 758
const DefaultPort = mcnet.DefaultPort const DefaultPort = mcnet.DefaultPort
// JoinServer connect a Minecraft server for playing the game. // JoinServer connect a Minecraft server for playing the game.
@ -27,20 +28,31 @@ func (c *Client) JoinServer(addr string) (err error) {
// JoinServerWithDialer is similar to JoinServer but using a Dialer. // JoinServerWithDialer is similar to JoinServer but using a Dialer.
func (c *Client) JoinServerWithDialer(d *net.Dialer, addr string) (err error) { func (c *Client) JoinServerWithDialer(d *net.Dialer, addr string) (err error) {
return c.join(context.Background(), &mcnet.Dialer{Dialer: d}, addr) var dialer *mcnet.Dialer
if d != nil {
dialer = &mcnet.Dialer{Dialer: *d}
}
return c.join(context.Background(), dialer, addr)
} }
func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error { func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error {
const Handshake = 0x00 const Handshake = 0x00
// Split Host and Port // Split Host and Port
host, portStr, err := net.SplitHostPort(addr) host, portStr, err := net.SplitHostPort(addr)
var port uint64
if err != nil { if err != nil {
return LoginErr{"split address", err} var addrErr *net.AddrError
} const missingPort = "missing port in address"
port, err := strconv.ParseUint(portStr, 0, 16) if errors.As(err, &addrErr) && addrErr.Err == missingPort {
if err != nil { port = 25565
return LoginErr{"parse port", err} } else {
return LoginErr{"split address", err}
}
} else {
port, err = strconv.ParseUint(portStr, 0, 16)
if err != nil {
return LoginErr{"parse port", err}
}
} }
// Dial connection // Dial connection

View File

@ -39,7 +39,7 @@ func main() {
func readBlockStates(states *[]State) { func readBlockStates(states *[]State) {
// open block_states data file // open block_states data file
f, err := os.Open("testdata/blocks.nbt") f, err := os.Open("blocks.nbt")
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }

View File

@ -94,7 +94,7 @@ func (m *StringifiedMessage) encode(d *Decoder, sb *strings.Builder, tagType byt
return err return err
case TagInt: case TagInt:
i, err := d.readInt32() i, err := d.readInt32()
sb.WriteString(strconv.FormatInt(int64(i), 10) + "I") sb.WriteString(strconv.FormatInt(int64(i), 10))
return err return err
case TagFloat: case TagFloat:
i, err := d.readInt32() i, err := d.readInt32()

3
nbt/snbt_encode_test.go Normal file
View File

@ -0,0 +1,3 @@
package nbt
//TODO: Test SNBT encode

View File

@ -63,11 +63,11 @@ func DialMCTimeout(addr string, timeout time.Duration) (*Conn, error) {
} }
type Dialer struct { type Dialer struct {
*net.Dialer net.Dialer
} }
func (d *Dialer) resolver() *net.Resolver { func (d *Dialer) resolver() *net.Resolver {
if d.Resolver != nil { if d != nil && d.Resolver != nil {
return d.Resolver return d.Resolver
} }
return net.DefaultResolver return net.DefaultResolver

View File

@ -1,17 +1,17 @@
{ {
piglin_safe: 0b, piglin_safe:0B,
natural: 1b, natural:1B,
ambient_light: 0.0f, ambient_light:0.0000000000F,
infiniburn: "minecraft:infiniburn_overworld", infiniburn:"#minecraft:infiniburn_overworld",
respawn_anchor_works: 0b, respawn_anchor_works:0B,
has_skylight: 1b, has_skylight:1B,
bed_works: 1b, bed_works:1B,
effects: "minecraft:overworld", effects:"minecraft:overworld",
has_raids: 1b, has_raids:1B,
min_y: 0, logical_height:384,
height: 256, coordinate_scale:1.0000000000D,
logical_height: 256, min_y:-64,
coordinate_scale: 1.0d, has_ceiling:0B,
ultrawarm: 0b, ultrawarm:0B,
has_ceiling: 0b height:384
} }

File diff suppressed because one or more lines are too long

View File

@ -35,7 +35,7 @@ func NewGlobalChat() *GlobalChat {
func (g *GlobalChat) Init(game *Game) { func (g *GlobalChat) Init(game *Game) {
game.AddHandler(&PacketHandler{ game.AddHandler(&PacketHandler{
ID: packetid.ServerboundChat, ID: packetid.ServerboundChat,
F: func(player *Player, packet Packet757) error { F: func(player *Player, packet Packet758) error {
var msg pk.String var msg pk.String
if err := pk.Packet(packet).Scan(&msg); err != nil { if err := pk.Packet(packet).Scan(&msg); err != nil {
return err return err
@ -59,14 +59,14 @@ func (g *GlobalChat) Run(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
case item := <-g.msg: case item := <-g.msg:
g.broadcast(Packet757(pk.Marshal( g.broadcast(Packet758(pk.Marshal(
packetid.ClientboundChat, packetid.ClientboundChat,
item.toMessage(), item.toMessage(),
pk.Byte(chatPosChat), pk.Byte(chatPosChat),
pk.UUID(item.p.UUID), pk.UUID(item.p.UUID),
))) )))
case p := <-g.join: case p := <-g.join:
g.broadcast(Packet757(pk.Marshal( g.broadcast(Packet758(pk.Marshal(
packetid.ClientboundChat, packetid.ClientboundChat,
chat.TranslateMsg("multiplayer.player.joined", chat.Text(p.Name)).SetColor(chat.Yellow), chat.TranslateMsg("multiplayer.player.joined", chat.Text(p.Name)).SetColor(chat.Yellow),
pk.Byte(chatPosSystem), pk.Byte(chatPosSystem),
@ -74,7 +74,7 @@ func (g *GlobalChat) Run(ctx context.Context) {
))) )))
g.players[p.UUID] = p g.players[p.UUID] = p
case p := <-g.quit: case p := <-g.quit:
g.broadcast(Packet757(pk.Marshal( g.broadcast(Packet758(pk.Marshal(
packetid.ClientboundChat, packetid.ClientboundChat,
chat.TranslateMsg("multiplayer.player.left", chat.Text(p.Name)).SetColor(chat.Yellow), chat.TranslateMsg("multiplayer.player.left", chat.Text(p.Name)).SetColor(chat.Yellow),
pk.Byte(chatPosSystem), pk.Byte(chatPosSystem),
@ -85,7 +85,7 @@ func (g *GlobalChat) Run(ctx context.Context) {
} }
} }
func (g *GlobalChat) broadcast(packet Packet757) { func (g *GlobalChat) broadcast(packet Packet758) {
for _, p := range g.players { for _, p := range g.players {
p.WritePacket(packet) p.WritePacket(packet)
} }

View File

@ -13,7 +13,7 @@ import (
func (g *Graph) Init(game *server.Game) { func (g *Graph) Init(game *server.Game) {
game.AddHandler(&server.PacketHandler{ game.AddHandler(&server.PacketHandler{
ID: packetid.ServerboundChat, ID: packetid.ServerboundChat,
F: func(player *server.Player, packet server.Packet757) error { F: func(player *server.Player, packet server.Packet758) error {
var msg pk.String var msg pk.String
if err := pk.Packet(packet).Scan(&msg); err != nil { if err := pk.Packet(packet).Scan(&msg); err != nil {
return err return err
@ -35,7 +35,7 @@ func (g *Graph) Run(ctx context.Context) {}
// AddPlayer implement server.Component for Graph // AddPlayer implement server.Component for Graph
func (g *Graph) AddPlayer(p *server.Player) { func (g *Graph) AddPlayer(p *server.Player) {
p.WritePacket(server.Packet757(pk.Marshal( p.WritePacket(server.Packet758(pk.Marshal(
packetid.ClientboundCommands, g, packetid.ClientboundCommands, g,
))) )))
} }

View File

@ -50,10 +50,10 @@ func (s *SimpleDim) PlayerJoin(p *Player) {
) )
column.Unlock() column.Unlock()
p.WritePacket(Packet757(packet)) p.WritePacket(Packet758(packet))
} }
p.WritePacket(Packet757(pk.Marshal( p.WritePacket(Packet758(pk.Marshal(
packetid.ClientboundPlayerPosition, packetid.ClientboundPlayerPosition,
pk.Double(0), pk.Double(143), pk.Double(0), pk.Double(0), pk.Double(143), pk.Double(0),
pk.Float(0), pk.Float(0), pk.Float(0), pk.Float(0),

View File

@ -42,7 +42,7 @@ type PacketHandler struct {
F packetHandlerFunc F packetHandlerFunc
} }
type packetHandlerFunc func(player *Player, packet Packet757) error type packetHandlerFunc func(player *Player, packet Packet758) error
//go:embed DimensionCodec.snbt //go:embed DimensionCodec.snbt
var dimensionCodecSNBT string var dimensionCodecSNBT string
@ -95,7 +95,9 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
pk.Boolean(false), // Is hardcore pk.Boolean(false), // Is hardcore
pk.Byte(p.Gamemode), // Gamemode pk.Byte(p.Gamemode), // Gamemode
pk.Byte(-1), // Prev Gamemode pk.Byte(-1), // Prev Gamemode
pk.Array([]pk.Identifier{pk.Identifier(dimInfo.Name)}), pk.Array([]pk.Identifier{
pk.Identifier(dimInfo.Name),
}),
pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)), pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)),
pk.NBT(nbt.StringifiedMessage(dimensionSNBT)), pk.NBT(nbt.StringifiedMessage(dimensionSNBT)),
pk.Identifier(dimInfo.Name), // World Name pk.Identifier(dimInfo.Name), // World Name
@ -145,7 +147,7 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
return return
} }
for _, ph := range g.handlers[packet.ID] { for _, ph := range g.handlers[packet.ID] {
if err := ph.F(p, Packet757(packet)); err != nil { if err := ph.F(p, Packet758(packet)); err != nil {
return return
} }
if err := p.GetErr(); err != nil { if err := p.GetErr(); err != nil {

View File

@ -60,7 +60,7 @@ func (k *KeepAlive) AddPlayerDelayUpdateHandler(f func(p *Player, delay time.Dur
func (k *KeepAlive) Init(g *Game) { func (k *KeepAlive) Init(g *Game) {
g.AddHandler(&PacketHandler{ g.AddHandler(&PacketHandler{
ID: packetid.ServerboundKeepAlive, ID: packetid.ServerboundKeepAlive,
F: func(player *Player, packet Packet757) error { F: func(player *Player, packet Packet758) error {
var KeepAliveID pk.Long var KeepAliveID pk.Long
if err := pk.Packet(packet).Scan(&KeepAliveID); err != nil { if err := pk.Packet(packet).Scan(&KeepAliveID); err != nil {
return err return err
@ -121,7 +121,7 @@ func (k *KeepAlive) pingPlayer(now time.Time) {
if elem := k.pingList.Front(); elem != nil { if elem := k.pingList.Front(); elem != nil {
p := k.pingList.Remove(elem).(keepAliveItem).player p := k.pingList.Remove(elem).(keepAliveItem).player
// Send Clientbound KeepAlive packet. // Send Clientbound KeepAlive packet.
p.WritePacket(Packet757(pk.Marshal( p.WritePacket(Packet758(pk.Marshal(
packetid.ClientboundKeepAlive, packetid.ClientboundKeepAlive,
pk.Long(k.keepAliveID), pk.Long(k.keepAliveID),
))) )))

View File

@ -22,12 +22,13 @@ type Player struct {
errChan chan error errChan chan error
} }
// Packet757 is a packet in protocol 757. // Packet758 is a packet in protocol 757.
// We are using type system to force programmers to update packets. // We are using type system to force programmers to update packets.
type Packet758 pk.Packet
type Packet757 pk.Packet type Packet757 pk.Packet
// WritePacket to player client. The type of parameter will update per version. // WritePacket to player client. The type of parameter will update per version.
func (p *Player) WritePacket(packet Packet757) { func (p *Player) WritePacket(packet Packet758) {
p.packetQueue.Push(pk.Packet(packet)) p.packetQueue.Push(pk.Packet(packet))
} }

View File

@ -42,7 +42,7 @@ func (p *PlayerList) AddPlayer(player *Player) {
defer p.playersLock.Unlock() defer p.playersLock.Unlock()
if len(p.players) >= p.maxPlayer { if len(p.players) >= p.maxPlayer {
player.WritePacket(Packet757(pk.Marshal( player.WritePacket(Packet758(pk.Marshal(
packetid.ClientboundDisconnect, packetid.ClientboundDisconnect,
chat.TranslateMsg("multiplayer.disconnect.server_full"), chat.TranslateMsg("multiplayer.disconnect.server_full"),
))) )))

View File

@ -30,8 +30,8 @@ import (
"github.com/Tnze/go-mc/net" "github.com/Tnze/go-mc/net"
) )
const ProtocolName = "1.18.1" const ProtocolName = "1.18.2"
const ProtocolVersion = 757 const ProtocolVersion = 758
type Server struct { type Server struct {
ListPingHandler ListPingHandler