Palette support 1
This commit is contained in:
@ -22,6 +22,71 @@
|
|||||||
ultrawarm: 0b,
|
ultrawarm: 0b,
|
||||||
has_ceiling: 0b
|
has_ceiling: 0b
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "minecraft:overworld_caves",
|
||||||
|
id: 1,
|
||||||
|
element: {
|
||||||
|
piglin_safe: 0b,
|
||||||
|
natural: 1b,
|
||||||
|
ambient_light: 0.0f,
|
||||||
|
infiniburn: "minecraft:infiniburn_overworld",
|
||||||
|
respawn_anchor_works: 0b,
|
||||||
|
has_skylight: 1b,
|
||||||
|
bed_works: 1b,
|
||||||
|
effects: "minecraft:overworld",
|
||||||
|
has_raids: 1b,
|
||||||
|
min_y: 0,
|
||||||
|
height: 256,
|
||||||
|
logical_height: 256,
|
||||||
|
coordinate_scale: 1.0d,
|
||||||
|
ultrawarm: 0b,
|
||||||
|
has_ceiling: 1b
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "minecraft:the_nether",
|
||||||
|
id: 2,
|
||||||
|
element: {
|
||||||
|
piglin_safe: 1b,
|
||||||
|
natural: 0b,
|
||||||
|
ambient_light: 0.1f,
|
||||||
|
infiniburn: "minecraft:infiniburn_nether",
|
||||||
|
respawn_anchor_works: 1b,
|
||||||
|
has_skylight: 0b,
|
||||||
|
bed_works: 0b,
|
||||||
|
effects: "minecraft:the_nether",
|
||||||
|
fixed_time: 18000L,
|
||||||
|
has_raids: 0b,
|
||||||
|
min_y: 0,
|
||||||
|
height: 256,
|
||||||
|
logical_height: 128,
|
||||||
|
coordinate_scale: 8.0d,
|
||||||
|
ultrawarm: 1b,
|
||||||
|
has_ceiling: 1b
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "minecraft:the_end",
|
||||||
|
id: 3,
|
||||||
|
element: {
|
||||||
|
piglin_safe: 0b,
|
||||||
|
natural: 0b,
|
||||||
|
ambient_light: 0.0f,
|
||||||
|
infiniburn: "minecraft:infiniburn_end",
|
||||||
|
respawn_anchor_works: 0b,
|
||||||
|
has_skylight: 0b,
|
||||||
|
bed_works: 0b,
|
||||||
|
effects: "minecraft:the_end",
|
||||||
|
fixed_time: 6000L,
|
||||||
|
has_raids: 1b,
|
||||||
|
min_y: 0,
|
||||||
|
height: 256,
|
||||||
|
logical_height: 256,
|
||||||
|
coordinate_scale: 1.0d,
|
||||||
|
ultrawarm: 0b,
|
||||||
|
has_ceiling: 0b
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -3,11 +3,10 @@ package packet
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/google/uuid"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/nbt"
|
"github.com/Tnze/go-mc/nbt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,6 +78,20 @@ func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array return an Ary but handled the previous Length field
|
||||||
|
//
|
||||||
|
// Warning: unstable API, may change in later version
|
||||||
|
func Array(array interface{}) Field {
|
||||||
|
length := VarInt(reflect.ValueOf(array).Len())
|
||||||
|
return Tuple{
|
||||||
|
&length,
|
||||||
|
Ary{
|
||||||
|
Len: &length,
|
||||||
|
Ary: array,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Opt struct {
|
type Opt struct {
|
||||||
Has interface{} // Pointer of bool, or `func() bool`
|
Has interface{} // Pointer of bool, or `func() bool`
|
||||||
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
|
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
|
||||||
|
@ -2,6 +2,8 @@ package save
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -128,3 +130,41 @@ func (b *BitStorage) Longs() []uint64 {
|
|||||||
}
|
}
|
||||||
return b.data
|
return b.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BitStorage) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
var Len pk.VarInt
|
||||||
|
n, err := Len.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if cap(b.data) >= int(Len) {
|
||||||
|
b.data = b.data[:Len]
|
||||||
|
} else {
|
||||||
|
b.data = make([]uint64, Len)
|
||||||
|
}
|
||||||
|
var v pk.Long
|
||||||
|
for i := range b.data {
|
||||||
|
nn, err := v.ReadFrom(r)
|
||||||
|
n += nn
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
b.data[i] = uint64(v)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BitStorage) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
n, err := pk.VarInt(len(b.data)).WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
for _, v := range b.data {
|
||||||
|
nn, err := pk.Long(v).WriteTo(w)
|
||||||
|
n += nn
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
@ -3,25 +3,76 @@ package save
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/nbt"
|
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockState interface {
|
type BlockState interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaletteContainer struct {
|
||||||
|
maps blockMaps
|
||||||
|
palette
|
||||||
|
BitStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PaletteContainer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
var bits pk.UnsignedByte
|
||||||
|
n, err = bits.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch bits {
|
||||||
|
case 0:
|
||||||
|
// TODO: SingleValuePalette
|
||||||
|
case 1, 2, 3, 4:
|
||||||
|
p.palette = &linearPalette{
|
||||||
|
onResize: nil,
|
||||||
|
maps: p.maps,
|
||||||
|
bits: 4,
|
||||||
|
}
|
||||||
|
case 5, 6, 7, 8:
|
||||||
|
// TODO: HashMapPalette
|
||||||
|
default:
|
||||||
|
// TODO: GlobalPalette
|
||||||
|
}
|
||||||
|
|
||||||
|
nn, err := p.palette.ReadFrom(r)
|
||||||
|
n += nn
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nn, err = p.BitStorage.ReadFrom(r)
|
||||||
|
n += nn
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PaletteContainer) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
return pk.Tuple{
|
||||||
|
pk.UnsignedByte(p.bits),
|
||||||
|
p.palette,
|
||||||
|
p.BitStorage,
|
||||||
|
}.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
||||||
type palette interface {
|
type palette interface {
|
||||||
id(v BlockState) int
|
|
||||||
value(i int) BlockState
|
|
||||||
pk.FieldEncoder
|
pk.FieldEncoder
|
||||||
pk.FieldDecoder
|
pk.FieldDecoder
|
||||||
read(r nbt.DecoderReader) (int, error)
|
id(v BlockState) int
|
||||||
|
value(i int) BlockState
|
||||||
|
}
|
||||||
|
|
||||||
|
type blockMaps interface {
|
||||||
|
getID(state BlockState) (id int)
|
||||||
|
getValue(id int) (state BlockState)
|
||||||
}
|
}
|
||||||
|
|
||||||
type linearPalette struct {
|
type linearPalette struct {
|
||||||
onResize func(n int, v BlockState) int
|
onResize func(n int, v BlockState) int
|
||||||
sToID map[BlockState]int
|
maps blockMaps
|
||||||
idTos map[int]BlockState
|
|
||||||
values []BlockState
|
values []BlockState
|
||||||
bits int
|
bits int
|
||||||
}
|
}
|
||||||
@ -57,7 +108,7 @@ func (l *linearPalette) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
} else {
|
} else {
|
||||||
n += nn
|
n += nn
|
||||||
}
|
}
|
||||||
l.values[i] = l.idTos[int(value)]
|
l.values[i] = l.maps.getValue(int(value))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -67,7 +118,7 @@ func (l *linearPalette) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, v := range l.values {
|
for _, v := range l.values {
|
||||||
if nn, err := pk.VarInt(l.sToID[v]).WriteTo(w); err != nil {
|
if nn, err := pk.VarInt(l.maps.getID(v)).WriteTo(w); err != nil {
|
||||||
return n + nn, err
|
return n + nn, err
|
||||||
} else {
|
} else {
|
||||||
n += nn
|
n += nn
|
||||||
@ -76,6 +127,8 @@ func (l *linearPalette) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *linearPalette) read(r nbt.DecoderReader) (int, error) {
|
type hashMapPalette struct {
|
||||||
panic("not implemented yet")
|
maps blockMaps
|
||||||
|
values map[int]BlockState
|
||||||
|
bits int
|
||||||
}
|
}
|
||||||
|
17
server/Dimension.snbt
Normal file
17
server/Dimension.snbt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
piglin_safe: 0b,
|
||||||
|
natural: 1b,
|
||||||
|
ambient_light: 0.0f,
|
||||||
|
infiniburn: "minecraft:infiniburn_overworld",
|
||||||
|
respawn_anchor_works: 0b,
|
||||||
|
has_skylight: 1b,
|
||||||
|
bed_works: 1b,
|
||||||
|
effects: "minecraft:overworld",
|
||||||
|
has_raids: 1b,
|
||||||
|
min_y: 0,
|
||||||
|
height: 256,
|
||||||
|
logical_height: 256,
|
||||||
|
coordinate_scale: 1.0d,
|
||||||
|
ultrawarm: 0b,
|
||||||
|
has_ceiling: 0b
|
||||||
|
}
|
2093
server/DimensionCodec.snbt
Normal file
2093
server/DimensionCodec.snbt
Normal file
File diff suppressed because it is too large
Load Diff
104
server/dimension.go
Normal file
104
server/dimension.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"github.com/Tnze/go-mc/save"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dimension interface {
|
||||||
|
Info() DimInfo
|
||||||
|
PlayerJoin(p *Player)
|
||||||
|
PlayerQuit(p *Player)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DimInfo struct {
|
||||||
|
Name string
|
||||||
|
HashedSeed uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type SimpleDim struct {
|
||||||
|
Columns map[struct{ X, Z int }]*struct {
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type chunkData struct {
|
||||||
|
HeightMaps save.BitStorage
|
||||||
|
BlockState save.BitStorage
|
||||||
|
Biomes save.BitStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *chunkData) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
return pk.Tuple{
|
||||||
|
// Heightmaps
|
||||||
|
pk.NBT(struct {
|
||||||
|
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
|
||||||
|
}{c.HeightMaps.Longs()}),
|
||||||
|
pk.ByteArray(c.Data()), // TODO: Chunk Data
|
||||||
|
pk.VarInt(0), // TODO: Block Entity
|
||||||
|
}.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *chunkData) Data() []byte {
|
||||||
|
var buff bytes.Buffer
|
||||||
|
_, _ = pk.Short(0).WriteTo(&buff)
|
||||||
|
return buff.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
type lightData struct {
|
||||||
|
SkyLightMask pk.BitSet
|
||||||
|
BlockLightMask pk.BitSet
|
||||||
|
SkyLight []pk.ByteArray
|
||||||
|
BlockLight []pk.ByteArray
|
||||||
|
}
|
||||||
|
|
||||||
|
func bitSetRev(set pk.BitSet) pk.BitSet {
|
||||||
|
rev := make(pk.BitSet, len(set))
|
||||||
|
for i := range rev {
|
||||||
|
rev[i] = ^set[i]
|
||||||
|
}
|
||||||
|
return rev
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lightData) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
return pk.Tuple{
|
||||||
|
pk.Boolean(true), // Trust Edges
|
||||||
|
l.SkyLightMask,
|
||||||
|
l.BlockLightMask,
|
||||||
|
bitSetRev(l.SkyLightMask),
|
||||||
|
bitSetRev(l.BlockLightMask),
|
||||||
|
pk.Array(l.SkyLight),
|
||||||
|
pk.Array(l.BlockLight),
|
||||||
|
}.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SimpleDim) PlayerJoin(p *Player) {
|
||||||
|
for pos, column := range s.Columns {
|
||||||
|
column.Lock()
|
||||||
|
packet := pk.Marshal(
|
||||||
|
packetid.ClientboundLevelChunkWithLight,
|
||||||
|
pk.Int(pos.X), pk.Int(pos.Z),
|
||||||
|
&chunkData{},
|
||||||
|
&lightData{
|
||||||
|
SkyLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||||
|
BlockLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||||
|
SkyLight: []pk.ByteArray{},
|
||||||
|
BlockLight: []pk.ByteArray{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
column.Unlock()
|
||||||
|
|
||||||
|
err := p.WritePacket(Packet757(packet))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SimpleDim) PlayerQuit(p *Player) {
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,15 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Tnze/go-mc/net"
|
_ "embed"
|
||||||
|
"github.com/Tnze/go-mc/nbt"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
|
"github.com/Tnze/go-mc/net"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GamePlay interface {
|
type GamePlay interface {
|
||||||
@ -12,3 +19,50 @@ type GamePlay interface {
|
|||||||
// You don't need to close the connection, but to keep not returning while the player is playing.
|
// You don't need to close the connection, but to keep not returning while the player is playing.
|
||||||
AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn)
|
AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Game struct {
|
||||||
|
eid int32
|
||||||
|
Dim Dimension
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed DimensionCodec.snbt
|
||||||
|
var dimensionCodecSNBT string
|
||||||
|
|
||||||
|
//go:embed Dimension.snbt
|
||||||
|
var dimensionSNBT string
|
||||||
|
|
||||||
|
func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) {
|
||||||
|
p := &Player{
|
||||||
|
Conn: conn,
|
||||||
|
EntityID: g.newEID(),
|
||||||
|
Gamemode: 1,
|
||||||
|
}
|
||||||
|
dimInfo := g.Dim.Info()
|
||||||
|
err := p.WritePacket(Packet757(pk.Marshal(
|
||||||
|
packetid.ClientboundLogin,
|
||||||
|
pk.Int(p.EntityID), // Entity ID
|
||||||
|
pk.Boolean(false), // Is hardcore
|
||||||
|
pk.Byte(p.Gamemode), // Gamemode
|
||||||
|
pk.Byte(-1), // Prev Gamemode
|
||||||
|
pk.Array([]pk.Identifier{pk.Identifier(dimInfo.Name)}),
|
||||||
|
pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)),
|
||||||
|
pk.NBT(nbt.StringifiedMessage(dimensionSNBT)),
|
||||||
|
pk.Identifier(dimInfo.Name), // World Name
|
||||||
|
pk.Long(dimInfo.HashedSeed), // Hashed seed
|
||||||
|
pk.VarInt(0), // Max Players (Ignored by client)
|
||||||
|
pk.VarInt(15), // View Distance
|
||||||
|
pk.VarInt(15), // Simulation Distance
|
||||||
|
pk.Boolean(false), // Reduced Debug Info
|
||||||
|
pk.Boolean(true), // Enable respawn screen
|
||||||
|
pk.Boolean(false), // Is Debug
|
||||||
|
pk.Boolean(true), // Is Flat
|
||||||
|
)))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.Dim.PlayerJoin(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) newEID() int32 {
|
||||||
|
return atomic.AddInt32(&g.eid, 1)
|
||||||
|
}
|
||||||
|
@ -20,10 +20,10 @@ type LoginHandler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoginChecker is the interface to check if a player is allowed to log in the server.
|
// LoginChecker is the interface to check if a player is allowed to log in the server.
|
||||||
// The checking could be anything, server player number, blacklist or whitelist.
|
// The checking could be anything, server player number, protocol version, blacklist or whitelist.
|
||||||
// If a player is not allowed to, the reason should be returned and will be sent to client by "LoginDisconnect" packet.
|
// If a player is not allowed to, the reason should be returned and will be sent to client by "LoginDisconnect" packet.
|
||||||
type LoginChecker interface {
|
type LoginChecker interface {
|
||||||
CheckPlayer(name string, id uuid.UUID) (ok bool, reason chat.Message)
|
CheckPlayer(name string, id uuid.UUID, protocol int32) (ok bool, reason chat.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MojangLoginHandler is a standard LoginHandler that implement both online and offline login progress.
|
// MojangLoginHandler is a standard LoginHandler that implement both online and offline login progress.
|
||||||
@ -92,7 +92,7 @@ func (d *MojangLoginHandler) AcceptLogin(conn *net.Conn, protocol int32) (name s
|
|||||||
|
|
||||||
// check if player can join (whitelist, blacklist, server full or something else)
|
// check if player can join (whitelist, blacklist, server full or something else)
|
||||||
if d.LoginChecker != nil {
|
if d.LoginChecker != nil {
|
||||||
if ok, result := d.CheckPlayer(name, id); !ok {
|
if ok, result := d.CheckPlayer(name, id, protocol); !ok {
|
||||||
// player is not allowed to join the server
|
// player is not allowed to join the server
|
||||||
err = conn.WritePacket(pk.Marshal(
|
err = conn.WritePacket(pk.Marshal(
|
||||||
packetid.LoginDisconnect,
|
packetid.LoginDisconnect,
|
||||||
|
21
server/player.go
Normal file
21
server/player.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Tnze/go-mc/net"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Player struct {
|
||||||
|
*net.Conn
|
||||||
|
EntityID int32
|
||||||
|
Gamemode byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packet757 is a packet in protocol 757.
|
||||||
|
// We are using type system to force programmers to update packets.
|
||||||
|
type Packet757 pk.Packet
|
||||||
|
|
||||||
|
// WritePacket to player client. The type of parameter will update per version.
|
||||||
|
func (p *Player) WritePacket(packet Packet757) error {
|
||||||
|
return p.Conn.WritePacket(pk.Packet(packet))
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
// You can build the server you want by combining the various functional modules provided here.
|
// You can build the server you want by combining the various functional modules provided here.
|
||||||
// An example can be found in examples/frameworkServer.
|
// An example can be found in examples/frameworkServer.
|
||||||
//
|
//
|
||||||
|
// This package is under rapid development, and any API may be subject to break changes
|
||||||
|
//
|
||||||
// A server is roughly divided into two parts: Gate and GamePlay
|
// A server is roughly divided into two parts: Gate and GamePlay
|
||||||
//
|
//
|
||||||
// +---------------------------------------------------------------------+
|
// +---------------------------------------------------------------------+
|
||||||
@ -24,7 +26,9 @@
|
|||||||
// The implement of Gameplay will provide later.
|
// The implement of Gameplay will provide later.
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import "github.com/Tnze/go-mc/net"
|
import (
|
||||||
|
"github.com/Tnze/go-mc/net"
|
||||||
|
)
|
||||||
|
|
||||||
const ProtocolName = "1.18.1"
|
const ProtocolName = "1.18.1"
|
||||||
const ProtocolVersion = 757
|
const ProtocolVersion = 757
|
||||||
|
Reference in New Issue
Block a user