Repository: GoLangMc/minecraft-server
Branch: master
Commit: ca992e94ba13
Files: 99
Total size: 152.1 KB
Directory structure:
gitextract_p9xoijfz/
├── .github/
│ └── dependabot.yml
├── .gitignore
├── LICENSE
├── README.md
├── apis/
│ ├── base/
│ │ ├── funcs.go
│ │ ├── named.go
│ │ ├── state.go
│ │ └── unique.go
│ ├── buff/
│ │ └── buffers.go
│ ├── cmds/
│ │ ├── command.go
│ │ └── commandmanager.go
│ ├── data/
│ │ ├── chat/
│ │ │ └── coloring.go
│ │ ├── location.go
│ │ ├── material.go
│ │ ├── msgs/
│ │ │ └── messages.go
│ │ ├── position.go
│ │ ├── rotation.go
│ │ ├── tags/
│ │ │ └── nbt.go
│ │ └── versions.go
│ ├── ents/
│ │ ├── entity.go
│ │ ├── living.go
│ │ ├── player.go
│ │ └── sender.go
│ ├── game/
│ │ ├── difficulty.go
│ │ ├── dimension.go
│ │ ├── event/
│ │ │ ├── block.go
│ │ │ ├── cancel.go
│ │ │ └── player.go
│ │ ├── gamemode.go
│ │ ├── level/
│ │ │ ├── block.go
│ │ │ ├── chunk.go
│ │ │ ├── level.go
│ │ │ ├── slice.go
│ │ │ └── value.go
│ │ ├── leveltype.go
│ │ └── profile.go
│ ├── logs/
│ │ └── logging.go
│ ├── math/
│ │ └── vector.go
│ ├── rand/
│ │ └── random.go
│ ├── server.go
│ ├── task/
│ │ ├── tasking.go
│ │ └── tasking_test.go
│ ├── urls/
│ │ └── urls.go
│ ├── util/
│ │ ├── formats.go
│ │ └── watcher.go
│ └── uuid/
│ └── uuids.go
├── go.mod
├── go.sum
├── impl/
│ ├── base/
│ │ ├── combine.go
│ │ ├── compact.go
│ │ ├── connect.go
│ │ ├── network.go
│ │ └── packets.go
│ ├── conf/
│ │ └── config.go
│ ├── conn/
│ │ ├── buffers.go
│ │ ├── connect.go
│ │ ├── crypto/
│ │ │ └── cfb8.go
│ │ └── network.go
│ ├── cons/
│ │ └── console.go
│ ├── data/
│ │ ├── client/
│ │ │ ├── abilities.go
│ │ │ ├── chat.go
│ │ │ ├── hand.go
│ │ │ ├── playerinfo.go
│ │ │ ├── position.go
│ │ │ ├── skin.go
│ │ │ ├── slot.go
│ │ │ └── status.go
│ │ ├── plugin/
│ │ │ └── message.go
│ │ ├── status/
│ │ │ └── response.go
│ │ ├── system/
│ │ │ └── command.go
│ │ └── values/
│ │ └── constants.go
│ ├── game/
│ │ ├── auth/
│ │ │ ├── authenticate.go
│ │ │ └── cryptography.go
│ │ ├── ents/
│ │ │ ├── entity.go
│ │ │ ├── living.go
│ │ │ └── player.go
│ │ ├── event/
│ │ │ └── events.go
│ │ ├── level/
│ │ │ ├── block.go
│ │ │ ├── chunk.go
│ │ │ ├── level.go
│ │ │ ├── slice.go
│ │ │ └── value.go
│ │ └── mode/
│ │ ├── mode_state0.go
│ │ ├── mode_state1.go
│ │ ├── mode_state2.go
│ │ └── mode_state3.go
│ ├── mask/
│ │ ├── masking.go
│ │ └── masking_test.go
│ ├── prot/
│ │ ├── client/
│ │ │ ├── to_client_state0.go
│ │ │ ├── to_client_state1.go
│ │ │ ├── to_client_state2.go
│ │ │ └── to_client_state3.go
│ │ ├── packets.go
│ │ └── server/
│ │ ├── to_server_state0.go
│ │ ├── to_server_state1.go
│ │ ├── to_server_state2.go
│ │ └── to_server_state3.go
│ └── server.go
└── main.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/" # Location of package manifests
schedule:
interval: "daily"
assignees:
- "Sxtanna"
================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# IntelliJ project files
.idea
*.iml
out
gen
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 GoLangMc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center">
<a href="https://github.com/GoLangMc/minecraft-server">
<img src="https://avatars3.githubusercontent.com/u/61735329" alt="logo" width="100" height="100">
</a>
<h3 align="center">minecraft-server</h3>
<p align="center">
Minecraft Server implementation written in Go
<br />
<br />
<a href="https://github.com/GoLangMc/minecraft-server/issues">Report Bug</a>
·
<a href="https://github.com/GoLangMc/minecraft-server/issues">Request Feature</a>
·
<a href="https://github.com/GoLangMc/minecraft-server/pulls">Send a Pull Request</a>
</p>
</p>
================================================
FILE: apis/base/funcs.go
================================================
package base
import (
"crypto/sha256"
"encoding/binary"
"fmt"
"strings"
)
func ConvertToString(data ...interface{}) string {
strs := make([]string, len(data))
for i, str := range data {
strs[i] = fmt.Sprintf("%v", str)
}
return strings.Join(strs, "")
}
func Attempt(function func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("caught: %v", r)
}
}()
function()
return
}
func JavaStringHashCode(value string) int32 {
var h int32
if len(value) > 0 {
for _, r := range value {
h = 31*h + r
}
}
return h
}
func JavaSHA256HashLong(value int64) []byte {
bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, uint64(value))
hash := sha256.Sum256(bytes)
return hash[:]
}
================================================
FILE: apis/base/named.go
================================================
package base
type Named interface {
Name() string
}
================================================
FILE: apis/base/state.go
================================================
package base
type Loads interface {
Load()
}
type Kills interface {
Kill()
}
type State interface {
Loads
Kills
}
================================================
FILE: apis/base/unique.go
================================================
package base
import "github.com/golangmc/minecraft-server/apis/uuid"
type Unique interface {
UUID() uuid.UUID
}
================================================
FILE: apis/buff/buffers.go
================================================
package buff
import (
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/data/tags"
"github.com/golangmc/minecraft-server/apis/uuid"
)
type Buffer interface {
Len() int32
SAS() []int8
UAS() []byte
InI() int32
InO() int32
SkpAll()
SkpLen(delta int32)
// pull
PullBit() bool
PullByt() byte
PullI16() int16
PullU16() uint16
PullI32() int32
PullI64() int64
PullU64() uint64
PullF32() float32
PullF64() float64
PullVrI() int32
PullVrL() int64
PullTxt() string
PullUAS() []byte
PullSAS() []int8
PullUID() uuid.UUID
PullPos() data.PositionI
PullNbt() *tags.NbtCompound
// push
PushBit(data bool)
PushByt(data byte)
PushI16(data int16)
PushI32(data int32)
PushI64(data int64)
PushF32(data float32)
PushF64(data float64)
PushVrI(data int32)
PushVrL(data int64)
PushTxt(data string)
PushUAS(data []byte, prefixWithLen bool)
PushSAS(data []int8, prefixWithLen bool)
PushUID(data uuid.UUID)
PushPos(data data.PositionI)
PushNbt(data *tags.NbtCompound)
}
type BufferPush interface {
Push(writer Buffer)
}
type BufferPull interface {
Pull(reader Buffer)
}
type BufferCodec interface {
BufferPush
BufferPull
}
================================================
FILE: apis/cmds/command.go
================================================
package cmds
import (
"github.com/golangmc/minecraft-server/apis/base"
"github.com/golangmc/minecraft-server/apis/ents"
)
type Command interface {
base.Named
base.State
Evaluate(sender ents.Sender, params []string)
Complete(sender ents.Sender, params []string, output *[]string)
}
================================================
FILE: apis/cmds/commandmanager.go
================================================
package cmds
import (
"strings"
"github.com/golangmc/minecraft-server/apis/ents"
)
type CommandManager struct {
commands map[string]*Command
}
func NewCommandManager() *CommandManager {
return &CommandManager{
commands: make(map[string]*Command),
}
}
func (c *CommandManager) Load() {
}
func (c *CommandManager) Kill() {
c.commands = nil
}
func (c *CommandManager) RegisterCommand(command Command) {
c.commands[command.Name()] = &command
command.Load()
}
func (c *CommandManager) Register(name string, evaluate func(sender ents.Sender, params []string)) {
command := simpleCommand{
name: name,
evaluate: evaluate,
}
c.RegisterCommand(&command)
}
func (c *CommandManager) Search(named string) *Command {
for name, command := range c.commands {
if strings.EqualFold(name, named) {
return command
}
}
return nil
}
type simpleCommand struct {
name string
evaluate func(sender ents.Sender, params []string)
}
func (s *simpleCommand) Name() string {
return s.name
}
func (s *simpleCommand) Load() {
}
func (s *simpleCommand) Kill() {
}
func (s *simpleCommand) Evaluate(sender ents.Sender, params []string) {
s.evaluate(sender, params)
}
func (s *simpleCommand) Complete(sender ents.Sender, params []string, output *[]string) {
}
================================================
FILE: apis/data/chat/coloring.go
================================================
package chat
import (
"fmt"
"strings"
"github.com/fatih/color"
)
type ChatColor int
type ColorCode struct {
Chat string
Motd string
Json string
Dec string
Hex string
}
const (
DarkRed ChatColor = iota
Red
Gold
Yellow
DarkGreen
Green
DarkAqua
Aqua
DarkBlue
Blue
DarkPurple
Purple
White
Black
DarkGray
Gray
Obfuscated
Bold
Strikethrough
Underline
Italic
Reset
)
const ColorCChar = '§'
const ColorAChar = '&'
var codeToCode = map[ChatColor]*ColorCode{
DarkRed: {
Chat: `§4`,
Motd: `\u00A74`,
Json: `dark_red`,
Dec: `11141120`,
Hex: `AA0000`,
},
Red: {
Chat: `§c`,
Motd: `\u00A7c`,
Json: `red`,
Dec: `16733525`,
Hex: `FF5555`,
},
Gold: {
Chat: `§6`,
Motd: `\u00A76`,
Json: `gold`,
Dec: `16755200`,
Hex: `FFAA00`,
},
Yellow: {
Chat: `§e`,
Motd: `\u00A7e`,
Json: `yellow`,
Dec: `16777045`,
Hex: `FFFF55`,
},
DarkGreen: {
Chat: `§2`,
Motd: `\u00A72`,
Json: `dark_green`,
Dec: `43520`,
Hex: `00AA00`,
},
Green: {
Chat: `§a`,
Motd: `\u00A7a`,
Dec: `5635925`,
Hex: `55FF55`,
},
DarkAqua: {
Chat: `§3`,
Motd: `\u00A73`,
Json: `dark_aqua`,
Dec: `43690`,
Hex: `00AAAA`,
},
Aqua: {
Chat: `§b`,
Motd: `\u00A7b`,
Json: `aqua`,
Dec: `5636095`,
Hex: `55FFFF`,
},
DarkBlue: {
Chat: `§1`,
Motd: `\u00A71`,
Json: `dark_blue`,
Dec: `170`,
Hex: `0000AA`,
},
Blue: {
Chat: `§9`,
Motd: `\u00A79`,
Json: `blue`,
Dec: `5592575`,
Hex: `5555FF`,
},
DarkPurple: {
Chat: `§5`,
Motd: `\u00A75`,
Json: `dark_purple`,
Dec: `11141290`,
Hex: `AA00AA`,
},
Purple: {
Chat: `§d`,
Motd: `\u00A7d`,
Json: `light_purple`,
Dec: `16733695`,
Hex: `FF55FF`,
},
White: {
Chat: `§f`,
Motd: `\u00A7f`,
Json: `white`,
Dec: `16777215`,
Hex: `FFFFFF`,
},
Black: {
Chat: `§0`,
Motd: `\u00A70`,
Json: `black`,
Dec: `0`,
Hex: `000000`,
},
DarkGray: {
Chat: `§8`,
Motd: `\u00A78`,
Json: `dark_gray`,
Dec: `5592405`,
Hex: `555555`,
},
Gray: {
Chat: `§7`,
Motd: `\u00A77`,
Json: `gray`,
Dec: `11184810`,
Hex: `AAAAAA`,
},
Obfuscated: {
Chat: `§k`,
Motd: `\u00A7k`,
Json: `obfuscated`,
},
Bold: {
Chat: `§l`,
Motd: `\u00A7l`,
Json: `bold`,
},
Strikethrough: {
Chat: `§m`,
Motd: `\u00A7m`,
Json: `strikethrough`,
},
Underline: {
Chat: `§n`,
Motd: `\u00A7n`,
Json: `underline`,
},
Italic: {
Chat: `§o`,
Motd: `\u00A7o`,
Json: `italic`,
},
Reset: {
Chat: `§r`,
Motd: `\u00A7r`,
Json: `reset`,
},
}
var codeToForm = map[ChatColor]color.Attribute{
DarkRed: color.FgHiRed,
Red: color.FgRed,
Gold: color.FgYellow,
Yellow: color.FgHiYellow,
DarkGreen: color.FgGreen,
Green: color.FgHiGreen,
DarkAqua: color.FgCyan,
Aqua: color.FgHiCyan,
DarkBlue: color.FgBlue,
Blue: color.FgHiBlue,
DarkPurple: color.FgMagenta,
Purple: color.FgHiMagenta,
White: color.FgHiWhite,
Black: color.FgBlack,
DarkGray: color.FgHiBlack,
Gray: color.FgWhite,
Reset: color.Reset,
Obfuscated: color.BlinkRapid,
Bold: color.Bold,
Strikethrough: color.CrossedOut,
Underline: color.Underline,
Italic: color.Italic,
}
var charToCode = map[rune]ChatColor{
'4': DarkRed,
'c': Red,
'6': Gold,
'e': Yellow,
'2': DarkGreen,
'a': Green,
'3': DarkAqua,
'b': Aqua,
'1': DarkBlue,
'9': Blue,
'5': DarkPurple,
'd': Purple,
'f': White,
'0': Black,
'8': DarkGray,
'7': Gray,
'k': Obfuscated,
'l': Bold,
'm': Strikethrough,
'n': Underline,
'o': Italic,
'r': Reset,
}
var jsonToCode = map[string]ChatColor{
`dark_red`: DarkRed,
`red`: Red,
`gold`: Gold,
`yellow`: Yellow,
`dark_green`: DarkGreen,
`green`: Green,
`dark_aqua`: DarkAqua,
`aqua`: Aqua,
`dark_blue`: DarkBlue,
`blue`: Blue,
`dark_purple`: DarkPurple,
`light_purple`: Purple,
`white`: White,
`black`: Black,
`dark_gray`: DarkGray,
`gray`: Gray,
`obfuscated`: Obfuscated,
`bold`: Bold,
`strikethrough`: Strikethrough,
`underline`: Underline,
`italic`: Italic,
`reset`: Reset,
}
func (code ChatColor) String() string {
return codeToCode[code].Chat
}
func (code *ChatColor) MarshalJSON() ([]byte, error) {
return []byte(`"` + codeToCode[*code].Json + `"`), nil
}
func (code *ChatColor) UnmarshalJSON(bytes []byte) error {
*code = jsonToCode[string(bytes)]
return nil
}
func (code *ChatColor) On(text string) string {
if len(text) == 0 {
return ""
}
return fmt.Sprintf("%p%s%v", code, text, Reset)
}
func Translate(text string) string {
build := strings.Builder{}
chars := []rune(text)
for i := 0; i < len(chars); i++ {
r := chars[i]
if r != ColorAChar || i+1 >= len(chars) {
build.WriteRune(r)
} else {
c := codeToCode[charToCode[chars[i+1]]]
if c == nil {
build.WriteRune(r)
} else {
build.WriteString(c.Chat)
i++
}
}
}
return build.String()
}
func TranslateConsole(text string) string {
text = Translate(text)
build := strings.Builder{}
temps := strings.Builder{}
chars := []rune(text)
forms := make([]color.Attribute, 0)
for i := 0; i < len(chars); i++ {
r := chars[i]
if r != ColorCChar || i+1 >= len(chars) {
temps.WriteRune(r)
continue
}
f, con := codeToForm[charToCode[chars[i+1]]]
if !con {
temps.WriteRune(r)
continue
}
if temps.Len() > 0 {
build.WriteString(color.New(forms...).Sprint(temps.String()))
temps.Reset()
}
i++
if f <= color.CrossedOut {
forms = append(forms, f)
} else {
forms = make([]color.Attribute, 0)
forms = append(forms, f)
}
}
if temps.Len() > 0 {
build.WriteString(color.New(forms...).Sprint(temps.String()))
}
return build.String()
}
================================================
FILE: apis/data/location.go
================================================
package data
type Location struct {
PositionF
RotationF
}
================================================
FILE: apis/data/material.go
================================================
package data
type Material int32
const (
AIR Material = iota
STONE
GRANITE
POLISHED_GRANITE
ANDESITE
POLISHED_ANDESITE
DIORITE
POLISHED_DIORITE
)
================================================
FILE: apis/data/msgs/messages.go
================================================
package msgs
import (
"encoding/json"
"strings"
"github.com/golangmc/minecraft-server/apis/data/chat"
)
type MessagePosition byte
const (
NormalChat MessagePosition = iota
SystemChat
HotBarText
)
type Message struct {
Text string `json:"text"`
Color *chat.ChatColor `json:"color,string,omitempty"`
Bold *bool `json:"bold,boolean,omitempty"`
Italic *bool `json:"italic,boolean,omitempty"`
Underlined *bool `json:"underlined,boolean,omitempty"`
Strikethrough *bool `json:"strikethrough,boolean,omitempty"`
Obfuscated *bool `json:"obfuscated,boolean,omitempty"`
Extra []*Message `json:"extra,omitempty"`
head *Message
}
func New(text string) *Message {
return &Message{
Text: text,
}
}
func (c *Message) SetColor(code chat.ChatColor) *Message {
c.Color = &code
return c
}
func (c *Message) SetBold(value bool) *Message {
c.Bold = &value
return c
}
func (c *Message) SetItalic(value bool) *Message {
c.Italic = &value
return c
}
func (c *Message) SetUnderlined(value bool) *Message {
c.Underlined = &value
return c
}
func (c *Message) SetStrikethrough(value bool) *Message {
c.Strikethrough = &value
return c
}
func (c *Message) SetObfuscated(value bool) *Message {
c.Obfuscated = &value
return c
}
// creates and returns a new Chat object, and adds it to the caller's extra slice
func (c *Message) Add(text string) *Message {
chat := New(text)
chat.head = c
c.Extra = append(c.Extra, chat)
return chat
}
func (c *Message) Reset() *Message {
next := c.Add("").SetColor(chat.Reset)
if c.Bold != nil && *c.Bold == true {
next.SetBold(false)
}
if c.Italic != nil && *c.Italic == true {
next.SetItalic(false)
}
if c.Underlined != nil && *c.Underlined == true {
next.SetUnderlined(false)
}
if c.Strikethrough != nil && *c.Strikethrough == true {
next.SetStrikethrough(false)
}
if c.Obfuscated != nil && *c.Obfuscated == true {
next.SetObfuscated(false)
}
return next
}
func (c *Message) AsJson() string {
chat := c
for chat.head != nil {
chat = chat.head
}
if text, err := json.Marshal(chat); err != nil {
panic(err)
} else {
return string(text)
}
}
func (c *Message) AsText() string {
builder := strings.Builder{}
curr := c
for curr.head != nil {
curr = curr.head
}
builder.WriteString(curr.asText())
return builder.String()
}
func (c *Message) asText() string {
builder := strings.Builder{}
if c.Color != nil {
builder.WriteString(c.Color.String())
}
if c.Bold != nil && *c.Bold == true {
builder.WriteString(chat.Bold.String())
}
if c.Italic != nil && *c.Italic == true {
builder.WriteString(chat.Italic.String())
}
if c.Underlined != nil && *c.Underlined == true {
builder.WriteString(chat.Underline.String())
}
if c.Strikethrough != nil && *c.Strikethrough == true {
builder.WriteString(chat.Strikethrough.String())
}
if c.Obfuscated != nil && *c.Obfuscated == true {
builder.WriteString(chat.Obfuscated.String())
}
builder.WriteString(c.Text)
for _, extra := range c.Extra {
builder.WriteString(extra.asText())
}
return builder.String()
}
func (c *Message) String() string {
return c.AsJson()
}
================================================
FILE: apis/data/position.go
================================================
package data
type PositionI struct {
X int64
Y int64
Z int64
}
type PositionF struct {
X float64
Y float64
Z float64
}
================================================
FILE: apis/data/rotation.go
================================================
package data
type RotationF struct {
AxisX float32 // 'yaw'
AxisY float32 // 'pitch'
}
================================================
FILE: apis/data/tags/nbt.go
================================================
package tags
type Typ byte
const (
TAG_End Typ = iota
TAG_Byte
TAG_Short
TAG_Int
TAG_Long
TAG_Float
TAG_Double
TAG_Byte_Array
TAG_String
TAG_List
TAG_Compound
TAG_Int_Array
TAG_Long_Array
)
type Nbt interface {
Type() Typ
Name() string
}
// end
type NbtEnd struct{}
func (n *NbtEnd) Type() Typ {
return TAG_End
}
func (n *NbtEnd) Name() string {
return "TAG_End"
}
// byte
type NbtByt struct {
Value int8
}
func (n *NbtByt) Type() Typ {
return TAG_Byte
}
func (n *NbtByt) Name() string {
return "TAG_Byte"
}
// short
type NbtI16 struct {
Value int16
}
func (n *NbtI16) Type() Typ {
return TAG_Short
}
func (n *NbtI16) Name() string {
return "TAG_Short"
}
/*func (n *NbtI16) Push(writer buff.Buffer) {
writer.PushI16(n.Value)
}
func (n *NbtI16) Pull(reader buff.Buffer) {
n.Value = reader.PullI16()
}*/
// int
type NbtI32 struct {
Value int32
}
func (n *NbtI32) Type() Typ {
return TAG_Int
}
func (n *NbtI32) Name() string {
return "TAG_Int"
}
/*func (n *NbtI32) Push(writer buff.Buffer) {
writer.PushI32(n.Value)
}
func (n *NbtI32) Pull(reader buff.Buffer) {
n.Value = reader.PullI32()
}*/
// long
type NbtI64 struct {
Value int64
}
func (n *NbtI64) Type() Typ {
return TAG_Long
}
func (n *NbtI64) Name() string {
return "TAG_Long"
}
/*func (n *NbtI64) Push(writer buff.Buffer) {
writer.PushI64(n.Value)
}
func (n *NbtI64) Pull(reader buff.Buffer) {
n.Value = reader.PullI64()
}*/
// float
type NbtF32 struct {
Value float32
}
func (n *NbtF32) Type() Typ {
return TAG_Float
}
func (n *NbtF32) Name() string {
return "TAG_Float"
}
/*func (n *NbtF32) Push(writer buff.Buffer) {
writer.PushF32(n.Value)
}
func (n *NbtF32) Pull(reader buff.Buffer) {
n.Value = reader.PullF32()
}*/
// double
type NbtF64 struct {
Value float64
}
func (n *NbtF64) Type() Typ {
return TAG_Double
}
func (n *NbtF64) Name() string {
return "TAG_Double"
}
/*func (n *NbtF64) Push(writer buff.Buffer) {
writer.PushF64(n.Value)
}
func (n *NbtF64) Pull(reader buff.Buffer) {
n.Value = reader.PullF64()
}*/
// byte array
type NbtArrByt struct {
Value []int8
}
func (n *NbtArrByt) Type() Typ {
return TAG_Byte_Array
}
func (n *NbtArrByt) Name() string {
return "TAG_Byte_Array"
}
/*func (n *NbtArrByt) Push(writer buff.Buffer) {
writer.PushSAS(n.Value, true)
}
func (n *NbtArrByt) Pull(reader buff.Buffer) {
n.Value = reader.PullSAS()
}*/
// string
type NbtTxt struct {
Value string
}
func (n *NbtTxt) Type() Typ {
return TAG_String
}
func (n *NbtTxt) Name() string {
return "TAG_String"
}
/*func (n *NbtTxt) Push(writer buff.Buffer) {
writer.PushTxt(n.Value)
}
func (n *NbtTxt) Pull(reader buff.Buffer) {
n.Value = reader.PullTxt()
}*/
// typed list
type NbtArrAny struct {
NType Typ
Value []Nbt
}
func (n *NbtArrAny) Type() Typ {
return TAG_List
}
func (n *NbtArrAny) Name() string {
return "TAG_List"
}
/*func (n *NbtArrAny) Push(writer buff.Buffer) {
if len(n.Value) == 0 {
writer.PushByt(0)
} else {
writer.PushByt(byte(n.NType))
}
writer.PushI32(int32(len(n.Value)))
for _, nbt := range n.Value {
nbt.Push(writer)
}
}
func (n *NbtArrAny) Pull(reader buff.Buffer) {
nType := Typ(reader.PullByt()) // this can probably fail...
size := reader.PullI32()
value := make([]Nbt, size, size)
for i := int32(0); i < size; i++ {
inst := typeToInst[nType]()
inst.Pull(reader)
value[i] = inst
}
}*/
// compound (map)
type NbtCompound struct {
Named string
Value map[string]Nbt
}
func (n *NbtCompound) Type() Typ {
return TAG_Compound
}
func (n *NbtCompound) Name() string {
return "TAG_Compound"
}
func (n *NbtCompound) Set(name string, data Nbt) {
n.Value[name] = data
}
func (n *NbtCompound) Get(name string) (nbt Nbt, con bool) {
nbt, con = n.Value[name]
return
}
// int list
type NbtArrI32 struct {
Value []int32
}
func (n *NbtArrI32) Type() Typ {
return TAG_Int_Array
}
func (n *NbtArrI32) Name() string {
return "TAG_Int_Array"
}
/*func (n *NbtArrI32) Push(writer buff.Buffer) {
writer.PushI32(int32(len(n.Value)))
for _, value := range n.Value {
writer.PushI32(value)
}
}
func (n *NbtArrI32) Pull(reader buff.Buffer) {
value := make([]int32, reader.PullI32())
for i := 0; i < len(value); i++ {
value[i] = reader.PullI32()
}
}*/
// long list
type NbtArrI64 struct {
Value []int64
}
func (n *NbtArrI64) Type() Typ {
return TAG_Long_Array
}
func (n *NbtArrI64) Name() string {
return "TAG_Long_Array"
}
================================================
FILE: apis/data/versions.go
================================================
package data
type MinecraftVersion int
const (
MC1_12_2 MinecraftVersion = iota
MC1_13_2
MC1_14_4
MC1_15_2
)
var CurrentProtocol = MC1_15_2
var protocolVersion = map[MinecraftVersion]int{
MC1_12_2: 340,
MC1_13_2: 404,
MC1_14_4: 498,
MC1_15_2: 578,
}
func (m MinecraftVersion) Protocol() int {
return protocolVersion[m]
}
func (m MinecraftVersion) String() string {
switch m {
case MC1_12_2:
return "1.12.2"
case MC1_13_2:
return "1.13.2"
case MC1_14_4:
return "1.14.4"
case MC1_15_2:
return "1.15.2"
default:
return "Unknown"
}
}
================================================
FILE: apis/ents/entity.go
================================================
package ents
import "github.com/golangmc/minecraft-server/apis/base"
type Entity interface {
Sender
base.Unique
EntityUUID() int64
}
================================================
FILE: apis/ents/living.go
================================================
package ents
type EntityLiving interface {
Entity
GetHealth() float64
SetHealth(health float64)
}
================================================
FILE: apis/ents/player.go
================================================
package ents
import "github.com/golangmc/minecraft-server/apis/game"
type Player interface {
EntityLiving
GetGameMode() game.GameMode
SetGameMode(mode game.GameMode)
GetIsOnline() bool
SetIsOnline(state bool)
GetProfile() *game.Profile
}
================================================
FILE: apis/ents/sender.go
================================================
package ents
import (
"github.com/golangmc/minecraft-server/apis/base"
)
type Sender interface {
base.Named
SendMessage(message ...interface{})
}
================================================
FILE: apis/game/difficulty.go
================================================
package game
import "fmt"
type Difficulty byte
const (
PEACEFUL Difficulty = iota
EASY
NORMAL
HARD
)
func (d Difficulty) String() string {
switch d {
case PEACEFUL:
return "Peaceful"
case EASY:
return "Easy"
case NORMAL:
return "Normal"
case HARD:
return "Hard"
default:
panic(fmt.Errorf("no difficulty for id %d", byte(d)))
}
}
func ValueOfDifficulty(d Difficulty) byte {
return byte(d)
}
func DifficultyValueOf(id byte) Difficulty {
switch id {
case 0:
return PEACEFUL
case 1:
return EASY
case 2:
return NORMAL
case 3:
return HARD
default:
panic(fmt.Errorf("no difficulty for id %d", id))
}
}
================================================
FILE: apis/game/dimension.go
================================================
package game
type Dimension int
const (
NETHER = -1
OVERWORLD = 0
THE_END = 1
)
================================================
FILE: apis/game/event/block.go
================================================
package event
import (
"github.com/golangmc/minecraft-server/apis/game/level"
)
type BlockEvent struct {
level.Block
}
type BlockBreakEvent struct {
BlockEvent
PlayerEvent
Cancellable
}
================================================
FILE: apis/game/event/cancel.go
================================================
package event
type Cancellable struct {
cancelled bool
}
func (c *Cancellable) GetCancelled() bool {
return c.cancelled
}
func (c *Cancellable) SetCancelled(cancelled bool) {
c.cancelled = cancelled
}
================================================
FILE: apis/game/event/player.go
================================================
package event
import "github.com/golangmc/minecraft-server/apis/ents"
type PlayerEvent struct {
ents.Player
}
type PlayerJoinEvent struct {
PlayerEvent
}
type PlayerQuitEvent struct {
PlayerEvent
}
================================================
FILE: apis/game/gamemode.go
================================================
package game
type GameMode int
const (
SURVIVAL GameMode = iota
CREATIVE
ADVENTURE
SPECTATOR
)
func (g GameMode) Encoded(hardcore bool) byte {
bit := 0
if hardcore {
bit = 0x8
}
return byte(g) | byte(bit)
}
================================================
FILE: apis/game/level/block.go
================================================
package level
type Block interface {
X() int
Y() int
Z() int
Chunk() Chunk
Level() Level
GetBlockType() int
SetBlockType(value int)
}
================================================
FILE: apis/game/level/chunk.go
================================================
package level
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data/tags"
)
type Chunk interface {
buff.BufferPush
ChunkX() int
ChunkZ() int
Slices() []Slice
Level() Level
// supports values y:[0:15]
GetSlice(y int) Slice
// supports values x:[0:15] y:[0:255] z: [0:15]
GetBlock(x, y, z int) Block
HeightMapNbtCompound() *tags.NbtCompound
}
================================================
FILE: apis/game/level/level.go
================================================
package level
import "github.com/golangmc/minecraft-server/apis/base"
type Level interface {
base.Named
base.Unique
Chunks() []Chunk
GetChunk(x, z int) Chunk
GetChunkIfLoaded(x, z int) Chunk
GetBlock(x, y, z int) Block
}
================================================
FILE: apis/game/level/slice.go
================================================
package level
import (
"github.com/golangmc/minecraft-server/apis/buff"
)
type Slice interface {
buff.BufferPush
Index() int
Chunk() Chunk
Level() Level
// supports values x:[0:15] y:[0:15] z: [0:15]
GetBlock(x, y, z int) Block
}
================================================
FILE: apis/game/level/value.go
================================================
package level
const (
ChunkW = 16
ChunkH = 256
ChunkL = 16
SliceC = 16
SliceH = ChunkH / SliceC
SliceS = ChunkW * ChunkL * SliceH
BitsPerBlock = 14
MaxPaletteID = (1 << BitsPerBlock) - 1
)
================================================
FILE: apis/game/leveltype.go
================================================
package game
type LevelType int
const (
DEFAULT LevelType = iota
FLAT
LARGEBIOMES
AMPLIFIED
CUSTOMIZED
BUFFET
DEFAULT11
)
var typeToName = map[LevelType]string{
DEFAULT: "default",
FLAT: "flat",
LARGEBIOMES: "largeBiomes",
AMPLIFIED: "amplified",
CUSTOMIZED: "customized",
BUFFET: "buffet",
DEFAULT11: "default_1_1",
}
func (l LevelType) String() string {
return typeToName[l]
}
================================================
FILE: apis/game/profile.go
================================================
package game
import "github.com/golangmc/minecraft-server/apis/uuid"
type Profile struct {
UUID uuid.UUID
Name string
Properties []*ProfileProperty
}
type ProfileProperty struct {
Name string
Value string
Signature *string
}
================================================
FILE: apis/logs/logging.go
================================================
package logs
import (
"fmt"
"io"
"os"
"time"
"github.com/fatih/color"
"github.com/golangmc/minecraft-server/apis/base"
"github.com/golangmc/minecraft-server/apis/data/chat"
)
type LogLevel int
const (
Info LogLevel = iota
Warn
Fail
Data
)
var BasicLevel = []LogLevel{Info, Warn, Fail}
var EveryLevel = []LogLevel{Info, Warn, Fail, Data}
type Logging struct {
name string
writer io.Writer
show []LogLevel
}
func (log *Logging) Name() string {
return log.name
}
func (log *Logging) Show() []LogLevel {
return log.show
}
func (log *Logging) formatPrint(level, message string) {
_, _ = fmt.Fprint(log.writer, fmt.Sprintf("[%s] [%s] [%s] %s\n", color.HiGreenString(currentTimeAsText()), level, color.WhiteString(log.Name()), chat.TranslateConsole(message)))
}
func (log *Logging) info(message string) {
log.formatPrint(color.CyanString("INFO"), message)
}
func (log *Logging) warn(message string) {
log.formatPrint(color.YellowString("WARN"), message)
}
func (log *Logging) fail(message string) {
log.formatPrint(color.RedString("FAIL"), message)
}
func (log *Logging) data(message string) {
log.formatPrint(color.MagentaString("DATA"), message)
}
func (log *Logging) Info(message ...interface{}) {
if !checkIfLevelShows(log, Info) {
return
}
log.info(base.ConvertToString(message...))
}
func (log *Logging) Warn(message ...interface{}) {
if !checkIfLevelShows(log, Warn) {
return
}
log.warn(base.ConvertToString(message...))
}
func (log *Logging) Fail(message ...interface{}) {
if !checkIfLevelShows(log, Fail) {
return
}
log.fail(base.ConvertToString(message...))
}
func (log *Logging) Data(message ...interface{}) {
if !checkIfLevelShows(log, Data) {
return
}
log.data(base.ConvertToString(message...))
}
func (log *Logging) InfoF(format string, a ...interface{}) {
if !checkIfLevelShows(log, Info) {
return
}
log.info(fmt.Sprintf(format, a...))
}
func (log *Logging) WarnF(format string, a ...interface{}) {
if !checkIfLevelShows(log, Warn) {
return
}
log.warn(fmt.Sprintf(format, a...))
}
func (log *Logging) FailF(format string, a ...interface{}) {
if !checkIfLevelShows(log, Fail) {
return
}
log.fail(fmt.Sprintf(format, a...))
}
func (log *Logging) DataF(format string, a ...interface{}) {
if !checkIfLevelShows(log, Data) {
return
}
log.data(fmt.Sprintf(format, a...))
}
func NewLogging(name string, show ...LogLevel) *Logging {
return NewLoggingWith(name, os.Stdout, show...)
}
func NewLoggingWith(name string, writer io.Writer, show ...LogLevel) *Logging {
return &Logging{name: name, writer: writer, show: show}
}
func currentTimeAsText() string {
h, m, s := time.Now().Clock()
return fmt.Sprintf("%02d:%02d:%02d", h, m, s)
}
func checkIfLevelShows(log *Logging, lvl LogLevel) bool {
for _, a := range log.Show() {
if a == lvl {
return true
}
}
return false
}
================================================
FILE: apis/math/vector.go
================================================
package math
type Vector2F struct {
X float64
Z float64
}
type Vector3F struct {
Vector2F
Y float64
}
================================================
FILE: apis/rand/random.go
================================================
package rand
import "crypto/rand"
func RandomByteArray(len int) []byte {
array := make([]byte, 4)
_, _ = rand.Read(array)
return array
}
================================================
FILE: apis/server.go
================================================
package apis
import (
"sync"
"github.com/golangmc/minecraft-server/apis/cmds"
"github.com/golangmc/minecraft-server/apis/ents"
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/apis/task"
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/apis/uuid"
apis_base "github.com/golangmc/minecraft-server/apis/base"
impl_base "github.com/golangmc/minecraft-server/impl/base"
)
type Server interface {
apis_base.State
Logging() *logs.Logging
Command() *cmds.CommandManager
Tasking() *task.Tasking
Watcher() util.Watcher
Players() []ents.Player
ConnByUUID(uuid uuid.UUID) impl_base.Connection
PlayerByUUID(uuid uuid.UUID) ents.Player
PlayerByConn(conn impl_base.Connection) ents.Player
ServerVersion() string
Broadcast(message string)
}
var instance *Server
var syncOnce sync.Once
func MinecraftServer() Server {
if instance == nil {
panic("server is unavailable")
}
return *instance
}
func SetMinecraftServer(server Server) {
syncOnce.Do(func() {
instance = &server
})
}
================================================
FILE: apis/task/tasking.go
================================================
package task
import (
"fmt"
"sync/atomic"
"time"
"github.com/golangmc/minecraft-server/apis/base"
)
type Task struct {
uuid int64
exec *func(task *Task)
cancel bool
period int64
paused int64
tasker *Tasking
}
type Tasking struct {
// milliseconds per tick
mpt int64
// uuid -> task
tasks map[int64]*Task
// task -> last ran
ticks map[*Task]int64
// time -> tasks
queue map[int64][]*Task
next uint64
done bool
kill chan bool
}
func NewTasking(mpt int64) *Tasking {
return &Tasking{
mpt: mpt,
tasks: make(map[int64]*Task),
ticks: make(map[*Task]int64),
queue: make(map[int64][]*Task),
}
}
func (t *Tasking) Load() {
t.done = false
t.kill = make(chan bool, 1)
go t.tick()
}
func (t *Tasking) Kill() {
if t.done {
return
}
t.done = true
t.kill <- true
for k := range t.ticks {
delete(t.ticks, k)
}
for k := range t.queue {
delete(t.queue, k)
}
for k, v := range t.tasks {
delete(t.tasks, k)
v.Cancel()
}
close(t.kill)
}
func (t *Tasking) tick() {
tick := time.NewTicker(time.Millisecond)
defer tick.Stop()
for {
select {
case <-t.kill:
return
case curr := <-tick.C:
t.tickQueue(curr)
t.tickTasks(curr)
}
}
}
func (t *Tasking) tickTasks(curr time.Time) {
unix := curr.UnixNano() / 1e6
for task, last := range t.ticks {
if unix-last < task.period {
continue // not ready to be executed
}
if err := task.attemptExec(); err != nil {
task.cancel = true
fmt.Printf("%v", err)
}
if task.cancel || task.period <= 0 {
delete(t.ticks, task)
} else {
t.ticks[task] = unix
}
}
}
func (t *Tasking) tickQueue(curr time.Time) {
// this is for handling the delayed tasks
// delay gets counted down, and then the tasks are added to the queue used for tickTasks
unix := curr.UnixNano() / 1e6
for when, tasks := range t.queue {
if unix < when {
continue // not ready to be executed
}
delete(t.queue, when)
for _, task := range tasks {
t.ticks[task] = 0
}
}
}
func (t *Tasking) nextTaskU() int64 {
return int64(atomic.AddUint64(&t.next, 1))
}
func (t *Tasking) repeats(period int64, function func(task *Task)) {
task := t.newTask(period, 0, &function)
t.ticks[task] = 0
t.tasks[task.uuid] = task
}
func (t *Tasking) delayed(paused int64, function func(task *Task)) {
task := t.newTask(0, paused, &function)
unix := time.Now().UnixNano() / 1e6
when := unix + paused
queue, exists := t.queue[when]
if !exists {
queue = make([]*Task, 0)
}
queue = append(queue, task)
t.queue[when] = queue
t.tasks[task.uuid] = task
}
// repeats the function every period, in ticks
func (t *Tasking) Every(period int64, function func(task *Task)) {
t.repeats(period*t.mpt, function)
}
// executes the function after paused, in ticks
func (t *Tasking) After(paused int64, function func(task *Task)) {
t.delayed(paused*t.mpt, function)
}
func (t *Tasking) EveryTime(period int64, duration time.Duration, function func(task *Task)) {
t.repeats(period*duration.Milliseconds(), function)
}
func (t *Tasking) AfterTime(paused int64, duration time.Duration, function func(task *Task)) {
t.delayed(paused*duration.Milliseconds(), function)
}
func (t *Tasking) newTask(period int64, paused int64, function *func(task *Task)) *Task {
return &Task{
tasker: t,
uuid: t.nextTaskU(),
exec: function,
period: period,
paused: paused,
}
}
func (t *Task) attemptExec() (error error) {
return base.Attempt(func() { (*t.exec)(t) })
}
func (t *Task) Cancel() {
t.cancel = true
}
func (t *Task) Tasker() *Tasking {
return t.tasker
}
================================================
FILE: apis/task/tasking_test.go
================================================
package task
import (
"fmt"
"testing"
)
func TestTasker_Load(t *testing.T) {
tasker := NewTasking(1_000 / 20)
tasker.Load()
tasker.Every(20, printCurrentTask)
done := <-tasker.kill
fmt.Printf("Tasker done: %t\n", done)
}
var count = 0
func printCurrentTask(_ *Task) {
fmt.Printf("Running print task %d\n", count)
if count++; count >= 2 {
panic("hi")
}
}
================================================
FILE: apis/urls/urls.go
================================================
package urls
import (
"io/ioutil"
"net/http"
)
func GetByte(url string) (res []byte, err error) {
// get
out, err := http.Get(url)
if err != nil {
return
}
// read body
bdy, err := ioutil.ReadAll(out.Body)
if err != nil {
return
}
// assign response
res = bdy
return
}
func GetText(url string) (res string, err error) {
arr, err := GetByte(url)
if err != nil {
return
}
res = string(arr)
return
}
================================================
FILE: apis/util/formats.go
================================================
package util
import (
"time"
"github.com/hako/durafmt"
)
func FormatTime(durationInSeconds int64) string {
return durafmt.Parse(time.Second * time.Duration(durationInSeconds)).String()
}
================================================
FILE: apis/util/watcher.go
================================================
package util
import (
"fmt"
"reflect"
"sync"
)
type Watcher interface {
Has(topic string) bool
Pub(topic string, args ...interface{})
PubAs(topicValue ...interface{})
PubTo(topicType reflect.Type, args ...interface{})
Sub(topic string, function interface{}) Handler
SubAs(function interface{}) Handler
SubTo(topicType reflect.Type, function interface{}) Handler
}
type Handler interface {
UnSub()
}
func NewWatcher() Watcher {
return &watcher{
locker: sync.Mutex{},
topics: make(map[string][]*handler),
}
}
type watcher struct {
locker sync.Mutex
topics map[string][]*handler
}
func (w *watcher) Has(topic string) bool {
handlers, contains := w.topics[topic]
return contains && len(handlers) > 0
}
func (w *watcher) Pub(topic string, args ...interface{}) {
if handlers, contains := w.topics[topic]; contains && len(handlers) > 0 {
callArgs := make([]reflect.Value, 0)
for _, arg := range args {
callArgs = append(callArgs, reflect.ValueOf(arg))
}
for _, handler := range handlers {
if handler.function.Type().NumIn() != len(callArgs) {
continue
}
handler.function.Call(callArgs)
}
}
}
func (w *watcher) PubAs(topicValue ...interface{}) {
w.PubTo(reflect.TypeOf(topicValue[0]), topicValue...)
}
func (w *watcher) PubTo(topicType reflect.Type, args ...interface{}) {
w.Pub(topicType.String(), args...)
}
func (w *watcher) Sub(topic string, function interface{}) Handler {
w.locker.Lock()
defer w.locker.Unlock()
// check if function is actual a function
if reflect.TypeOf(function).Kind() != reflect.Func {
panic(fmt.Errorf("cannot sub with %v, must be reflect.Func", reflect.TypeOf(function).Kind()))
}
handler := &handler{
topic: topic,
watch: w,
function: reflect.ValueOf(function),
}
// append watch handler to topic list
w.topics[topic] = append(w.topics[topic], handler)
return handler
}
func (w *watcher) SubAs(function interface{}) Handler {
funcType := reflect.TypeOf(function)
// check if function is actual a function
if funcType.Kind() != reflect.Func {
panic(fmt.Errorf("cannot sub with %v, must be reflect.Func", funcType.Kind()))
}
if funcType.NumIn() == 0 {
panic(fmt.Errorf("cannot sub with %v, must have at least 1 input parameter", funcType))
}
return w.SubTo(funcType.In(0), function)
}
func (w *watcher) SubTo(topicType reflect.Type, function interface{}) Handler {
return w.Sub(topicType.String(), function)
}
type handler struct {
topic string
watch *watcher
function reflect.Value
}
func (h *handler) UnSub() {
handlers := h.watch.topics[h.topic]
if handlers == nil {
return
}
for i, elem := range handlers {
if elem == h {
h.watch.topics[h.topic] = append(h.watch.topics[h.topic][:i], h.watch.topics[h.topic][i+1:]...)
}
}
}
================================================
FILE: apis/uuid/uuids.go
================================================
package uuid
import (
"encoding/binary"
"github.com/satori/go.uuid"
)
type UUID = uuid.UUID
func NewUUID() UUID {
gen := uuid.NewV4()
/*if err != nil {
panic(err)
}*/
return gen
}
func TextToUUID(text string) (data UUID, err error) {
return uuid.FromString(text)
}
func BitsToUUID(msb, lsb int64) (data UUID, err error) {
mBytes := make([]byte, 8)
lBytes := make([]byte, 8)
binary.BigEndian.PutUint64(mBytes, uint64(msb))
binary.BigEndian.PutUint64(lBytes, uint64(lsb))
return uuid.FromBytes(append(mBytes, lBytes...))
}
func UUIDToText(uuid UUID) (text string, err error) {
data, err := uuid.MarshalText()
if err == nil {
text = string(data)
}
return
}
func SigBits(uuid UUID) (msb, lsb int64) {
bytes := uuid.Bytes()
msb = 0
lsb = 0
for i := 0; i < 8; i++ {
msb = (msb << 0x08) | int64(bytes[i]&0xFF)
}
for i := 8; i < 16; i++ {
lsb = (lsb << 0x08) | int64(bytes[i]&0xFF)
}
return
}
================================================
FILE: go.mod
================================================
module github.com/golangmc/minecraft-server
go 1.13
require (
github.com/fatih/color v1.9.0
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/satori/go.uuid v1.2.0
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
)
================================================
FILE: go.sum
================================================
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/golangmc/minecraft-server v0.0.0-20200307201348-f5daeb2b6d07 h1:BCos3PMMuZxapSHWy/FfT1PBai2qInTqk1z5JjsiCE4=
github.com/golangmc/minecraft-server v0.0.0-20200307201348-f5daeb2b6d07/go.mod h1:KXyWige3rVvzcZEnSzJJYCeyTdyaBATU03/dVMpS72M=
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4 h1:60gBOooTSmNtrqNaRvrDbi8VAne0REaek2agjnITKSw=
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
================================================
FILE: impl/base/combine.go
================================================
package base
import "github.com/golangmc/minecraft-server/apis/ents"
type PlayerAndConnection struct {
Connection
ents.Player
}
================================================
FILE: impl/base/compact.go
================================================
package base
type Compacter struct {
Values []int64
bpb int
max int
}
func NewCompacter(bits, size int) *Compacter {
sliceSize := iDontKnowWhatThisDoes(size*bits, 64) / 64
return &Compacter{
bpb: bits,
max: (1 << bits) - 1,
Values: make([]int64, sliceSize, sliceSize),
}
}
func (c *Compacter) Set(index int, value int) int {
bIndex := index * c.bpb
sIndex := bIndex >> 0x06
eIndex := (((index + 1) * c.bpb) - 1) >> 0x06
uIndex := bIndex ^ (sIndex << 0x06)
previousValue := int64(uint64(c.Values[sIndex])>>uIndex) & int64(c.max)
c.Values[sIndex] = c.Values[sIndex]&int64(^(c.max<<uIndex)) | int64((value&c.max)<<uIndex)
if sIndex != eIndex {
zIndex := 64 - uIndex
pIndex := c.bpb - 1
previousValue |= (c.Values[eIndex] << zIndex) & int64(c.max)
c.Values[eIndex] = int64(((uint64(c.Values[eIndex]) >> pIndex) << pIndex) | uint64((value&c.max)>>zIndex))
}
return int(previousValue)
}
func (c *Compacter) Get(index int) int {
bIndex := index * c.bpb
sIndex := bIndex >> 0x06
eIndex := (((index + 1) * c.bpb) - 1) >> 0x06
uIndex := bIndex ^ (sIndex << 0x06)
if sIndex == eIndex {
return int((uint64(c.Values[sIndex]) >> uIndex) & uint64(c.max))
}
zIndex := 64 - uIndex
return int(uint64(c.Values[sIndex]>>uIndex) | uint64(c.Values[eIndex]<<zIndex)&uint64(c.max))
}
func iDontKnowWhatThisDoes(var0, var1 int) int {
if var1 == 0 {
return 0
} else if var0 == 0 {
return var1
} else {
if var0 < 0 {
var1 *= -1
}
var2 := var0 % var1
if var2 == 0 {
return var0
} else {
return var0 + var1 - var2
}
}
}
================================================
FILE: impl/base/connect.go
================================================
package base
import "net"
type Connection interface {
Address() net.Addr
GetState() PacketState
SetState(state PacketState)
Encrypt(data []byte) (output []byte)
Decrypt(data []byte) (output []byte)
CertifyName() string
CertifyData() []byte
CertifyValues(name string)
CertifyUpdate(secret []byte)
Deflate(data []byte) (output []byte)
Inflate(data []byte) (output []byte)
Pull(data []byte) (len int, err error)
Push(data []byte) (len int, err error)
Stop() (err error)
SendPacket(packet PacketO)
}
================================================
FILE: impl/base/network.go
================================================
package base
import (
"github.com/golangmc/minecraft-server/apis/base"
)
type Network interface {
base.State
}
================================================
FILE: impl/base/packets.go
================================================
package base
import (
"fmt"
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/util"
)
type PacketState int
const (
SHAKE PacketState = iota
STATUS
LOGIN
PLAY
)
func ValueOfPacketState(s PacketState) int {
return int(s)
}
func PacketStateValueOf(s int) PacketState {
switch s {
case 0:
return SHAKE
case 1:
return STATUS
case 2:
return LOGIN
case 3:
return PLAY
default:
panic(fmt.Errorf("no state for value: %d", s))
}
}
func (state PacketState) String() string {
switch state {
case SHAKE:
return "Shake"
case STATUS:
return "Status"
case LOGIN:
return "Login"
case PLAY:
return "Play"
default:
panic(fmt.Errorf("no state for value: %d", state))
}
}
func (state PacketState) Next() PacketState {
switch state {
case SHAKE:
return STATUS
case STATUS:
return LOGIN
case LOGIN:
return PLAY
case PLAY:
return SHAKE
default:
panic(fmt.Errorf("no state for value: %d", state))
}
}
type Packet interface {
// the uuid of this packet
UUID() int32
}
type PacketI interface {
Packet
// decode the server_data from the reader into this packet
Pull(reader buff.Buffer, conn Connection)
}
type PacketO interface {
Packet
// encode the server_data from the packet into this writer
Push(writer buff.Buffer, conn Connection)
}
type Packets interface {
util.Watcher
/*GetPacketM(uuid int32, state PacketState) (pid int32, cont bool)*/
GetPacketI(uuid int32, state PacketState) PacketI
/*GetPacketO(uuid int32, state PacketState) PacketO*/
}
================================================
FILE: impl/conf/config.go
================================================
package conf
var DefaultServerConfig = ServerConfig{
Network: Network{
Host: "0.0.0.0",
Port: 25565,
},
}
type ServerConfig struct {
Network Network
}
type Network struct {
Host string `toml:"host"`
Port int `toml:"port"`
}
================================================
FILE: impl/conn/buffers.go
================================================
package conn
import (
"encoding/binary"
"fmt"
"math"
"strconv"
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/data/tags"
"github.com/golangmc/minecraft-server/apis/uuid"
)
/*
Language used:
- Len = Length
- Arr = Array
- Bit = Boolean
- Byt = Byte
- Int = int
- VrI = VarInt
- Srt = Short
- Txt = String
*/
type buffer struct {
iIndex int32
oIndex int32
bArray []byte
}
func (b *buffer) String() string {
return fmt.Sprintf("Buffer[%d](i: %d, o: %d)%v", b.Len(), b.iIndex, b.oIndex, b.bArray)
}
// new
func NewBuffer() buff.Buffer {
return NewBufferWith(make([]byte, 0))
}
func NewBufferWith(bArray []byte) buff.Buffer {
return &buffer{bArray: bArray}
}
// server_data
func (b *buffer) Len() int32 {
return int32(len(b.bArray))
}
func (b *buffer) SAS() []int8 {
return asSArray(b.bArray)
}
func (b *buffer) UAS() []byte {
return b.bArray
}
func (b *buffer) InI() int32 {
return b.iIndex
}
func (b *buffer) InO() int32 {
return b.oIndex
}
func (b *buffer) SkpAll() {
b.SkpLen(b.Len() - 1)
}
func (b *buffer) SkpLen(delta int32) {
b.iIndex += delta
}
// pull
func (b *buffer) PullBit() bool {
return b.pullNext() != 0
}
func (b *buffer) PullByt() byte {
return b.pullNext()
}
func (b *buffer) PullI16() int16 {
return int16(binary.BigEndian.Uint16(b.pullSize(4)))
}
func (b *buffer) PullU16() uint16 {
return uint16(b.pullNext())<<8 | uint16(b.pullNext())
}
func (b *buffer) PullI32() int32 {
return int32(binary.BigEndian.Uint32(b.pullSize(4)))
}
func (b *buffer) PullI64() int64 {
return int64(b.PullU64())
}
func (b *buffer) PullU64() uint64 {
return binary.BigEndian.Uint64(b.pullSize(8))
}
func (b *buffer) PullF32() float32 {
return math.Float32frombits(binary.BigEndian.Uint32(b.pullSize(4)))
}
func (b *buffer) PullF64() float64 {
return math.Float64frombits(binary.BigEndian.Uint64(b.pullSize(8)))
}
func (b *buffer) PullVrI() int32 {
return int32(b.pullVariable(5))
}
func (b *buffer) PullVrL() int64 {
return b.pullVariable(10)
}
func (b *buffer) PullTxt() string {
return string(b.PullUAS())
}
func (b *buffer) PullUAS() []byte {
sze := b.PullVrI()
arr := b.bArray[b.iIndex : b.iIndex+sze]
b.iIndex += sze
return arr
}
func (b *buffer) PullSAS() []int8 {
return asSArray(b.PullUAS())
}
func (b *buffer) PullUID() uuid.UUID {
data, _ := uuid.BitsToUUID(b.PullI64(), b.PullI64())
return data
}
func (b *buffer) PullPos() data.PositionI {
val := b.PullU64()
x := int64(val) >> 38
y := int64(val) & 0xFFF
z := int64(val) << 26 >> 38
return data.PositionI{
X: x,
Y: y,
Z: z,
}
}
func (b *buffer) PullNbt() *tags.NbtCompound {
typ := tags.Typ(b.PullByt())
fmt.Println("==type")
fmt.Println(typ)
if typ != tags.TAG_Compound {
panic("root tag must be compound") // probably shouldn't panic?
}
name := b.PullTxt()
if len(name) != 0 {
panic("root compound should have an empty name")
}
fmt.Println("==name")
fmt.Println(name)
tag := &tags.NbtCompound{}
b.pullNbt(tag)
return tag
}
// push
func (b *buffer) PushBit(data bool) {
if data {
b.pushNext(byte(0x01))
} else {
b.pushNext(byte(0x00))
}
}
func (b *buffer) PushByt(data byte) {
b.pushNext(data)
}
func (b *buffer) PushI16(data int16) {
b.pushNext(
byte(data)>>8,
byte(data))
}
func (b *buffer) PushI32(data int32) {
b.pushNext(
byte(data>>24),
byte(data>>16),
byte(data>>8),
byte(data))
}
func (b *buffer) PushI64(data int64) {
b.pushNext(
byte(data>>56),
byte(data>>48),
byte(data>>40),
byte(data>>32),
byte(data>>24),
byte(data>>16),
byte(data>>8),
byte(data))
}
func (b *buffer) PushF32(data float32) {
b.PushI32(int32(math.Float32bits(data)))
}
func (b *buffer) PushF64(data float64) {
b.PushI64(int64(math.Float64bits(data)))
}
func (b *buffer) PushVrI(data int32) {
for {
temp := data & 0x7F
data >>= 7
if data != 0 {
temp |= 0x80
}
b.pushNext(byte(temp))
if data == 0 {
break
}
}
}
func (b *buffer) PushVrL(data int64) {
for {
temp := data & 0x7F
data >>= 7
if data != 0 {
temp |= 0x80
}
b.pushNext(byte(temp))
if data == 0 {
break
}
}
}
func (b *buffer) PushTxt(data string) {
b.PushUAS([]byte(data), true)
}
func (b *buffer) PushUAS(data []byte, prefixWithLen bool) {
if prefixWithLen {
b.PushVrI(int32(len(data)))
}
b.pushNext(data...)
}
func (b *buffer) PushSAS(data []int8, prefixWithLen bool) {
b.PushUAS(asUArray(data), prefixWithLen)
}
func (b *buffer) PushUID(data uuid.UUID) {
msb, lsb := uuid.SigBits(data)
b.PushI64(msb)
b.PushI64(lsb)
}
func (b *buffer) PushPos(data data.PositionI) {
b.PushI64(((data.X & 0x3FFFFFF) << 38) | ((data.Z & 0x3FFFFFF) << 12) | (data.Y & 0xFFF))
}
func (b *buffer) PushNbt(data *tags.NbtCompound) {
if data == nil {
b.PushByt(0)
} else {
b.PushByt(byte(data.Type()))
b.pushNext(0, 0)
b.pushNbt(data)
}
}
// internal
func (b *buffer) pullNext() byte {
if b.iIndex >= b.Len() {
return 0
// panic("reached end of buffer")
}
next := b.bArray[b.iIndex]
b.iIndex++
if b.oIndex > 0 {
b.oIndex--
}
return next
}
func (b *buffer) pullSize(next int) []byte {
bytes := make([]byte, next)
for i := 0; i < next; i++ {
bytes[i] = b.pullNext()
}
return bytes
}
func (b *buffer) pushNext(bArray ...byte) {
b.oIndex += int32(len(bArray))
b.bArray = append(b.bArray, bArray...)
}
func (b *buffer) pullVariable(max int) int64 {
var num int
var res int64
for {
tmp := int64(b.pullNext())
res |= (tmp & 0x7F) << uint(num*7)
if num++; num > max {
panic("VarInt > " + strconv.Itoa(max))
}
if tmp&0x80 != 0x80 {
break
}
}
return res
}
func asSArray(bytes []byte) []int8 {
array := make([]int8, 0)
for _, b := range bytes {
array = append(array, int8(b))
}
return array
}
func asUArray(bytes []int8) []byte {
array := make([]byte, 0)
for _, b := range bytes {
array = append(array, byte(b))
}
return array
}
var typeToInst = map[tags.Typ]func() tags.Nbt{
tags.TAG_End: func() tags.Nbt {
return &tags.NbtEnd{}
},
tags.TAG_Byte: func() tags.Nbt {
return &tags.NbtByt{}
},
tags.TAG_Short: func() tags.Nbt {
return &tags.NbtI16{}
},
tags.TAG_Int: func() tags.Nbt {
return &tags.NbtI32{}
},
tags.TAG_Long: func() tags.Nbt {
return &tags.NbtI64{}
},
tags.TAG_Float: func() tags.Nbt {
return &tags.NbtF32{}
},
tags.TAG_Double: func() tags.Nbt {
return &tags.NbtF64{}
},
tags.TAG_Byte_Array: func() tags.Nbt {
return &tags.NbtArrByt{}
},
tags.TAG_String: func() tags.Nbt {
return &tags.NbtTxt{}
},
tags.TAG_List: func() tags.Nbt {
return &tags.NbtArrAny{}
},
tags.TAG_Compound: func() tags.Nbt {
return &tags.NbtCompound{}
},
tags.TAG_Int_Array: func() tags.Nbt {
return &tags.NbtArrI32{}
},
tags.TAG_Long_Array: func() tags.Nbt {
return &tags.NbtArrI64{}
},
}
func (b *buffer) pullNbt(data tags.Nbt) {
switch data.Type() {
case tags.TAG_End:
// nothing
break
case tags.TAG_Byte:
data.(*tags.NbtByt).Value = int8(b.PullByt())
break
case tags.TAG_Short:
panic("unimplemented")
break
case tags.TAG_Int:
panic("unimplemented")
break
case tags.TAG_Long:
panic("unimplemented")
break
case tags.TAG_Float:
panic("unimplemented")
break
case tags.TAG_Double:
panic("unimplemented")
break
case tags.TAG_Byte_Array:
panic("unimplemented")
break
case tags.TAG_String:
panic("unimplemented")
break
case tags.TAG_List:
panic("unimplemented")
break
case tags.TAG_Compound:
value := make(map[string]tags.Nbt)
fmt.Println("reading compound")
for {
typ := tags.Typ(b.PullByt())
if typ == tags.TAG_End {
fmt.Println("encountered break")
break
}
fmt.Println("===type")
fmt.Println(typ)
name := b.pullNbtTxt()
fmt.Println("===name")
fmt.Println(name)
inst := typeToInst[typ]()
b.pullNbt(inst)
value[name] = inst
}
data.(*tags.NbtCompound).Value = value
break
case tags.TAG_Int_Array:
panic("unimplemented")
break
case tags.TAG_Long_Array:
value := make([]int64, b.PullI32())
for i := 0; i < len(value); i++ {
value[i] = b.PullI64()
}
data.(*tags.NbtArrI64).Value = value
break
}
}
func (b *buffer) pushNbt(data tags.Nbt) {
switch data.Type() {
case tags.TAG_End:
// nothing
break
case tags.TAG_Byte:
b.PushByt(byte(data.(*tags.NbtByt).Value))
break
case tags.TAG_Short:
panic("unimplemented")
break
case tags.TAG_Int:
panic("unimplemented")
break
case tags.TAG_Long:
panic("unimplemented")
break
case tags.TAG_Float:
panic("unimplemented")
break
case tags.TAG_Double:
panic("unimplemented")
break
case tags.TAG_Byte_Array:
panic("unimplemented")
break
case tags.TAG_String:
panic("unimplemented")
break
case tags.TAG_List:
panic("unimplemented")
break
case tags.TAG_Compound:
for name, tag := range data.(*tags.NbtCompound).Value {
b.PushByt(byte(tag.Type()))
if tag.Type() == tags.TAG_End {
continue
}
b.pushNbtTxt(name)
b.pushNbt(tag)
}
b.PushByt(0)
break
case tags.TAG_Int_Array:
panic("unimplemented")
break
case tags.TAG_Long_Array:
value := data.(*tags.NbtArrI64).Value
b.PushI32(int32(len(value)))
for _, value := range value {
b.PushI64(value)
}
break
}
}
func (b *buffer) pullNbtTxt() string {
size := b.PullI16()
data := b.pullSize(int(size))
return string(data)
}
func (b *buffer) pushNbtTxt(data string) {
b.PushI16(int16(len(data)))
b.PushUAS([]byte(data), false)
}
================================================
FILE: impl/conn/connect.go
================================================
package conn
import (
"bytes"
"compress/zlib"
"crypto/cipher"
"fmt"
"io"
"net"
"github.com/golangmc/minecraft-server/apis/rand"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/conn/crypto"
)
type connection struct {
new bool
tcp *net.TCPConn
state base.PacketState
certify Certify
compact Compact
}
func NewConnection(conn *net.TCPConn) base.Connection {
return &connection{
new: true,
tcp: conn,
certify: Certify{},
compact: Compact{},
}
}
func (c *connection) Address() net.Addr {
return c.tcp.RemoteAddr()
}
func (c *connection) GetState() base.PacketState {
return c.state
}
func (c *connection) SetState(state base.PacketState) {
c.state = state
}
type Certify struct {
name string
used bool
data []byte
encrypt cipher.Stream
decrypt cipher.Stream
}
func (c *connection) Encrypt(data []byte) (output []byte) {
if !c.certify.used {
return data
}
output = make([]byte, len(data))
c.certify.encrypt.XORKeyStream(output, data)
return
}
func (c *connection) Decrypt(data []byte) (output []byte) {
if !c.certify.used {
return data
}
output = make([]byte, len(data))
c.certify.decrypt.XORKeyStream(output, data)
return
}
func (c *connection) CertifyName() string {
return c.certify.name
}
func (c *connection) CertifyData() []byte {
return c.certify.data
}
func (c *connection) CertifyUpdate(secret []byte) {
encrypt, decrypt, err := crypto.NewEncryptAndDecrypt(secret)
c.certify.encrypt = encrypt
c.certify.decrypt = decrypt
if err != nil {
panic(fmt.Errorf("failed to enable encryption for user: %s\n%v", c.CertifyName(), err))
}
c.certify.used = true
c.certify.data = secret
}
func (c *connection) CertifyValues(name string) {
c.certify.name = name
c.certify.data = rand.RandomByteArray(4)
}
type Compact struct {
used bool
size int32
}
func (c *connection) Deflate(data []byte) (output []byte) {
if !c.compact.used {
return data
}
var out bytes.Buffer
writer, _ := zlib.NewWriterLevel(&out, zlib.BestCompression)
_, _ = writer.Write(data)
_ = writer.Close()
output = out.Bytes()
return
}
func (c *connection) Inflate(data []byte) (output []byte) {
if !c.compact.used {
return data
}
reader, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
panic(err)
}
var out bytes.Buffer
_, _ = io.Copy(&out, reader)
output = out.Bytes()
return
}
func (c *connection) Pull(data []byte) (len int, err error) {
len, err = c.tcp.Read(data)
return
}
func (c *connection) Push(data []byte) (len int, err error) {
len, err = c.tcp.Write(data)
return
}
func (c *connection) Stop() (err error) {
err = c.tcp.Close()
return
}
func (c *connection) SendPacket(packet base.PacketO) {
bufO := NewBuffer()
temp := NewBuffer()
// write buffer
bufO.PushVrI(packet.UUID())
packet.Push(bufO, c)
temp.PushVrI(bufO.Len())
temp.PushUAS(bufO.UAS(), false)
_, _ = c.tcp.Write(c.Encrypt(temp.UAS()))
}
================================================
FILE: impl/conn/crypto/cfb8.go
================================================
package crypto
import (
"crypto/aes"
"crypto/cipher"
)
type cfb8 struct {
b cipher.Block
sr []byte
srEnc []byte
srPos int
decrypt bool
}
func newEncrypt(block cipher.Block, iv []byte) cipher.Stream {
if len(iv) != block.BlockSize() {
panic("cfb8.newEncrypt: IV length must equal block size")
}
return newCFB8(block, iv, false)
}
func newDecrypt(block cipher.Block, iv []byte) cipher.Stream {
if len(iv) != block.BlockSize() {
panic("cfb8.newDecrypt: IV length must equal block size")
}
return newCFB8(block, iv, true)
}
func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
blockSize := block.BlockSize()
if len(iv) != blockSize {
return nil
}
x := &cfb8{
b: block,
sr: make([]byte, blockSize*4),
srEnc: make([]byte, blockSize),
srPos: 0,
decrypt: decrypt,
}
copy(x.sr, iv)
return x
}
func (x *cfb8) XORKeyStream(dst, src []byte) {
blockSize := x.b.BlockSize()
for i := 0; i < len(src); i++ {
x.b.Encrypt(x.srEnc, x.sr[x.srPos:x.srPos+blockSize])
var c byte
if x.decrypt {
c = src[i]
dst[i] = c ^ x.srEnc[0]
} else {
c = src[i] ^ x.srEnc[0]
dst[i] = c
}
x.sr[x.srPos+blockSize] = c
x.srPos++
if x.srPos+blockSize == len(x.sr) {
copy(x.sr, x.sr[x.srPos:])
x.srPos = 0
}
}
}
func NewEncryptAndDecrypt(secret []byte) (encrypt cipher.Stream, decrypt cipher.Stream, err error) {
block, err := aes.NewCipher(secret)
if err != nil {
return nil, nil, err
}
encrypt = newEncrypt(block, secret)
decrypt = newDecrypt(block, secret)
return
}
================================================
FILE: impl/conn/network.go
================================================
package conn
import (
"fmt"
"net"
"reflect"
"strconv"
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/system"
)
type network struct {
host string
port int
logger *logs.Logging
packets base.Packets
join chan base.PlayerAndConnection
quit chan base.PlayerAndConnection
report chan system.Message
}
func NewNetwork(host string, port int, packet base.Packets, report chan system.Message, join chan base.PlayerAndConnection, quit chan base.PlayerAndConnection) base.Network {
return &network{
host: host,
port: port,
join: join,
quit: quit,
report: report,
logger: logs.NewLogging("network", logs.EveryLevel...),
packets: packet,
}
}
func (n *network) Load() {
if err := n.startListening(); err != nil {
n.report <- system.Make(system.FAIL, err)
return
}
}
func (n *network) Kill() {
}
func (n *network) startListening() error {
ser, err := net.ResolveTCPAddr("tcp", n.host+":"+strconv.Itoa(n.port))
if err != nil {
return fmt.Errorf("address resolution failed [%v]", err)
}
tcp, err := net.ListenTCP("tcp", ser)
if err != nil {
return fmt.Errorf("failed to bind [%v]", err)
}
n.logger.InfoF("listening on %s:%d", n.host, n.port)
go func() {
for {
con, err := tcp.AcceptTCP()
if err != nil {
n.report <- system.Make(system.FAIL, err)
break
}
_ = con.SetNoDelay(true)
_ = con.SetKeepAlive(true)
go handleConnect(n, NewConnection(con))
}
}()
return nil
}
func handleConnect(network *network, conn base.Connection) {
network.logger.DataF("New Connection from &6%v", conn.Address())
var inf []byte
for {
inf = make([]byte, 1024)
sze, err := conn.Pull(inf)
if err != nil && err.Error() == "EOF" {
network.quit <- base.PlayerAndConnection{
Player: nil,
Connection: conn,
}
break
}
if err != nil || sze == 0 {
_ = conn.Stop()
network.quit <- base.PlayerAndConnection{
Player: nil,
Connection: conn,
}
break
}
buf := NewBufferWith(conn.Decrypt(inf[:sze]))
// decompression
// decryption
if buf.UAS()[0] == 0xFE { // LEGACY PING
continue
}
packetLen := buf.PullVrI()
bufI := NewBufferWith(buf.UAS()[buf.InI() : buf.InI()+packetLen])
bufO := NewBuffer()
handleReceive(network, conn, bufI, bufO)
if bufO.Len() > 1 {
temp := NewBuffer()
temp.PushVrI(bufO.Len())
comp := NewBuffer()
comp.PushUAS(conn.Deflate(bufO.UAS()), false)
temp.PushUAS(comp.UAS(), false)
_, err := conn.Push(conn.Encrypt(temp.UAS()))
if err != nil {
network.logger.Fail("Failed to push client bound packet: %v", err)
}
}
}
}
func handleReceive(network *network, conn base.Connection, bufI buff.Buffer, bufO buff.Buffer) {
uuid := bufI.PullVrI()
packetI := network.packets.GetPacketI(uuid, conn.GetState())
if packetI == nil {
network.logger.DataF("unable to decode %v packet with uuid: %d", conn.GetState(), uuid)
return
}
network.logger.DataF("GET packet: %d | %v | %v", packetI.UUID(), reflect.TypeOf(packetI), conn.GetState())
// populate incoming packet
packetI.Pull(bufI, conn)
network.packets.PubAs(packetI)
network.packets.PubAs(packetI, conn)
}
================================================
FILE: impl/cons/console.go
================================================
package cons
import (
"bufio"
"io"
"os"
"github.com/golangmc/minecraft-server/apis/base"
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/impl/data/system"
)
type Console struct {
i io.Reader
o io.Writer
logger *logs.Logging
IChannel chan string
OChannel chan string
report chan system.Message
}
func NewConsole(report chan system.Message) *Console {
console := &Console{
IChannel: make(chan string),
OChannel: make(chan string),
report: report,
}
console.i = io.MultiReader(os.Stdin)
console.o = io.MultiWriter(os.Stdout, console.newLogFile("latest.log"))
console.logger = logs.NewLoggingWith("console", console.o, logs.EveryLevel...)
return console
}
func (c *Console) Load() {
// handle i channel
go func() {
scanner := bufio.NewScanner(c.i)
for scanner.Scan() {
err := base.Attempt(func() {
c.IChannel <- scanner.Text()
})
if err != nil {
c.report <- system.Make(system.FAIL, err)
}
}
}()
// handle o channel
go func() {
for line := range c.OChannel {
c.logger.Info(line)
}
}()
}
func (c *Console) Kill() {
defer func() {
_ = recover() // ignore panic with closing closed channel
}()
// save the log file as YYYY-MM-DD-{index}.log{.gz optionally compressed}
close(c.IChannel)
close(c.OChannel)
}
func (c *Console) Name() string {
return "ConsoleSender"
}
func (c *Console) SendMessage(message ...interface{}) {
defer func() {
if err := recover(); err != nil {
c.report <- system.Make(system.FAIL, err)
}
}()
c.OChannel <- base.ConvertToString(message...)
}
type logFileWriter struct {
file *os.File
}
func (c *Console) newLogFile(name string) io.Writer {
file, err := os.Create(name)
if err != nil {
c.report <- system.Make(system.FAIL, err)
return nil
}
return &logFileWriter{file: file}
}
func (l *logFileWriter) Write(p []byte) (n int, err error) {
// this is going to be messy, but this should convert to string, strip colors, and then write to file. Don't @ me.
return l.file.Write(p)
}
================================================
FILE: impl/data/client/abilities.go
================================================
package client
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/mask"
)
type PlayerAbilities struct {
mask.Masking
Invulnerable bool
Flying bool
AllowFlight bool
InstantBuild bool // creative??
}
func (p *PlayerAbilities) Push(writer buff.Buffer) {
flags := byte(0)
p.Set(&flags, 0x01, p.Invulnerable)
p.Set(&flags, 0x02, p.Flying)
p.Set(&flags, 0x04, p.AllowFlight)
p.Set(&flags, 0x08, p.InstantBuild)
writer.PushByt(flags)
}
func (p *PlayerAbilities) Pull(reader buff.Buffer) {
flags := reader.PullByt()
p.Invulnerable = p.Has(flags, 0x01)
p.Flying = p.Has(flags, 0x02)
p.AllowFlight = p.Has(flags, 0x04)
p.InstantBuild = p.Has(flags, 0x08)
}
================================================
FILE: impl/data/client/chat.go
================================================
package client
type ChatMode int
const (
Full ChatMode = iota
Cmds
None
)
================================================
FILE: impl/data/client/hand.go
================================================
package client
type MainHand int
const (
Hand_L MainHand = iota
Hand_R
)
================================================
FILE: impl/data/client/playerinfo.go
================================================
package client
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/ents"
)
type PlayerInfoAction int32
const (
AddPlayer PlayerInfoAction = iota
UpdateGameMode
UpdateLatency
UpdateDisplayName
RemovePlayer
)
type PlayerInfo interface {
buff.BufferPush
}
type PlayerInfoAddPlayer struct {
Player ents.Player
}
func (p *PlayerInfoAddPlayer) Push(writer buff.Buffer) {
prof := p.Player.GetProfile()
writer.PushUID(prof.UUID)
writer.PushTxt(prof.Name)
writer.PushVrI(int32(len(prof.Properties)))
for _, prop := range prof.Properties {
writer.PushTxt(prop.Name)
writer.PushTxt(prop.Value)
if prop.Signature == nil {
writer.PushBit(false)
} else {
writer.PushBit(true)
writer.PushTxt(*prop.Signature)
}
}
writer.PushVrI(int32(p.Player.GetGameMode()))
writer.PushVrI(0) // update this to the player's actual ping
writer.PushBit(false) // update this to be whether the player has a custom display name or not, write that name as json if they do
}
type PlayerInfoUpdateLatency struct {
}
================================================
FILE: impl/data/client/position.go
================================================
package client
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/mask"
)
type Relativity struct {
mask.Masking
X bool
Y bool
Z bool
AxisX bool
AxisY bool
}
func (r *Relativity) Push(writer buff.Buffer) {
flags := byte(0)
r.Set(&flags, 0x01, r.X)
r.Set(&flags, 0x02, r.Y)
r.Set(&flags, 0x04, r.Z)
// the fact that these are flipped deeply bothers me.
r.Set(&flags, 0x08, r.AxisY)
r.Set(&flags, 0x10, r.AxisX)
writer.PushByt(flags)
}
================================================
FILE: impl/data/client/skin.go
================================================
package client
import (
"fmt"
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/mask"
)
type SkinParts struct {
mask.Masking
Cape bool
Head bool
Body bool
ArmL bool
ArmR bool
LegL bool
LegR bool
}
func (d *SkinParts) String() string {
return fmt.Sprintf("Cape:%t Head:%t Body:%t ArmL:%t ArmR:%t LegL:%t LegR:%t", d.Cape, d.Head, d.Body, d.ArmL, d.ArmR, d.LegL, d.LegR)
}
func (d *SkinParts) Push(writer buff.Buffer) {
flags := byte(0)
d.Set(&flags, 0x01, d.Cape)
d.Set(&flags, 0x02, d.Body)
d.Set(&flags, 0x04, d.ArmL)
d.Set(&flags, 0x08, d.ArmR)
d.Set(&flags, 0x10, d.LegL)
d.Set(&flags, 0x20, d.LegR)
d.Set(&flags, 0x40, d.Head)
writer.PushByt(flags)
}
func (d *SkinParts) Pull(reader buff.Buffer) {
flags := reader.PullByt()
d.Cape = d.Has(flags, 0x01)
d.Body = d.Has(flags, 0x02)
d.ArmL = d.Has(flags, 0x04)
d.ArmR = d.Has(flags, 0x08)
d.LegL = d.Has(flags, 0x10)
d.LegR = d.Has(flags, 0x20)
d.Head = d.Has(flags, 0x40)
}
================================================
FILE: impl/data/client/slot.go
================================================
package client
type HotBarSlot byte
const (
SLOT_0 HotBarSlot = iota
SLOT_1
SLOT_2
SLOT_3
SLOT_4
SLOT_5
SLOT_6
SLOT_7
SLOT_8
)
================================================
FILE: impl/data/client/status.go
================================================
package client
type StatusAction int
const (
Respawn StatusAction = iota
Request
)
================================================
FILE: impl/data/plugin/message.go
================================================
package plugin
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data"
)
type Message interface {
Chan() string
buff.BufferPush
buff.BufferPull
}
var registry = createMessageRegistry()
type MessageRegistry struct {
channels map[string]func() Message
}
func createMessageRegistry() MessageRegistry {
registry := MessageRegistry{make(map[string]func() Message)}
registry.channels["minecraft:brand"] = func() Message {
return &Brand{}
}
registry.channels["minecraft:debug/paths"] = func() Message {
return &DebugPaths{}
}
registry.channels["minecraft:debug/neighbors_update"] = func() Message {
return &DebugNeighbors{}
}
return registry
}
func GetMessageForChannel(channel string) Message {
creator := registry.channels[channel]
if creator == nil {
return nil
}
return creator()
}
const (
CHANNEL_BRAND = "minecraft:brand"
CHANNEL_DEBUG_PATHS = "minecraft:debug/paths"
CHANNEL_DEBUG_NEIGHBORS = "minecraft:debug/neighbors_update"
)
// look, they're like cute little packets :D
type Brand struct {
Name string
}
func (b *Brand) Chan() string {
return CHANNEL_BRAND
}
func (b *Brand) Push(writer buff.Buffer) {
writer.PushTxt(b.Name)
}
func (b *Brand) Pull(reader buff.Buffer) {
b.Name = reader.PullTxt()
}
type DebugPaths struct { // unused? honestly why did I do this
UnknownValue1 int32
UnknownValue2 float32
PathEntity PathEntity
}
type PathEntity struct {
Index int
Target PathPoint
PSetLen int
PSet []PathPoint
OSetLen int
OSet []PathPoint
CSetLen int
CSet []PathPoint
}
func (p *PathEntity) Push(writer buff.Buffer) {
writer.PushI32(int32(p.Index))
p.Target.Push(writer)
writer.PushI32(int32(p.PSetLen))
for _, point := range p.PSet {
point.Push(writer)
}
writer.PushI32(int32(p.OSetLen))
for _, point := range p.OSet {
point.Push(writer)
}
writer.PushI32(int32(p.CSetLen))
for _, point := range p.CSet {
point.Push(writer)
}
}
func (p *PathEntity) Pull(reader buff.Buffer) {
p.Index = int(reader.PullI32())
target := PathPoint{}
target.Pull(reader)
p.Target = target
p.PSet = make([]PathPoint, 0)
p.PSetLen = int(reader.PullI32())
for i := 0; i < p.PSetLen; i++ {
point := PathPoint{}
point.Pull(reader)
p.PSet = append(p.PSet, point)
}
p.OSet = make([]PathPoint, 0)
p.OSetLen = int(reader.PullI32())
for i := 0; i < p.OSetLen; i++ {
point := PathPoint{}
point.Pull(reader)
p.OSet = append(p.OSet, point)
}
p.CSet = make([]PathPoint, 0)
p.CSetLen = int(reader.PullI32())
for i := 0; i < p.CSetLen; i++ {
point := PathPoint{}
point.Pull(reader)
p.CSet = append(p.CSet, point)
}
}
type PathPoint struct {
X int32
Y int32
Z int32
DistanceOrigin float32
Cost float32
CostMalus float32
Visited bool
NodeType NodeType
DistanceTarget float32
}
func (p *PathPoint) Push(writer buff.Buffer) {
writer.PushI32(p.X)
writer.PushI32(p.Y)
writer.PushI32(p.Z)
writer.PushF32(p.DistanceOrigin)
writer.PushF32(p.Cost)
writer.PushF32(p.CostMalus)
writer.PushBit(p.Visited)
writer.PushI32(int32(p.NodeType))
writer.PushF32(p.DistanceTarget)
}
func (p *PathPoint) Pull(reader buff.Buffer) {
p.X = reader.PullI32()
p.Y = reader.PullI32()
p.Z = reader.PullI32()
p.DistanceOrigin = reader.PullF32()
p.Cost = reader.PullF32()
p.CostMalus = reader.PullF32()
p.Visited = reader.PullBit()
p.NodeType = NodeType(reader.PullI32())
p.DistanceTarget = reader.PullF32()
}
type NodeType int
const (
BLOCKED NodeType = iota
OPEN
WALKABLE
TRAPDOOR
FENCE
LAVA
WATER
RAIL
DANGER_FIRE
DAMAGE_FIRE
DANGER_CACTUS
DAMAGE_CACTUS
DANGER_OTHER
DAMAGE_OTHER
DOOR_OPEN
DOOR_WOOD_CLOSED
DOOR_IRON_CLOSED
)
func (d *DebugPaths) Chan() string {
return CHANNEL_DEBUG_PATHS
}
func (d *DebugPaths) Push(writer buff.Buffer) {
writer.PushI32(d.UnknownValue1)
writer.PushF32(d.UnknownValue2)
d.PathEntity.Push(writer)
}
func (d *DebugPaths) Pull(reader buff.Buffer) {
d.UnknownValue1 = reader.PullI32()
d.UnknownValue2 = reader.PullF32()
entity := PathEntity{}
entity.Pull(reader)
d.PathEntity = entity
}
type DebugNeighbors struct {
Time int64
Location data.PositionI
}
func (d *DebugNeighbors) Chan() string {
return CHANNEL_DEBUG_NEIGHBORS
}
func (d *DebugNeighbors) Push(writer buff.Buffer) {
writer.PushVrL(d.Time)
writer.PushPos(d.Location)
}
func (d *DebugNeighbors) Pull(reader buff.Buffer) {
d.Time = reader.PullVrL()
d.Location = reader.PullPos()
}
================================================
FILE: impl/data/status/response.go
================================================
package status
import (
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/data/chat"
)
const (
SxtannaName = "Sxtanna"
SxtannaUUID = "41d1fed5-aa44-432c-ab1b-2810001f3270"
ServerMotd = " &bA GoLang Server"
ServerIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAACXBIWXMAAAMTAAADEwE9ZoPHAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAEqNaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzA2NyA3OS4xNTc3NDcsIDIwMTUvMDMvMzAtMjM6NDA6NDIgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTktMDctMjJUMjM6NTA6MTUtMDQ6MDA8L3htcDpDcmVhdGVEYXRlPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDE5LTA4LTEzVDE3OjQ2OjIzLTA0OjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOS0wOC0xM1QxNzo0NjoyMy0wNDowMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6NzNlNTdkYTYtMDFiOC1mNDQ1LTlmMTEtYjIxODc1NmJjZWZlPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NWJiYWE4Y2ItYmUxMy0xMWU5LTljNWUtY2IzZWQ2NWEzZDZlPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6ZDI0NTZmNTUtOTlmYi05OTRlLThhNDItODA5N2RjYjhhYmQ4PC94bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpIaXN0b3J5PgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y3JlYXRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmQyNDU2ZjU1LTk5ZmItOTk0ZS04YTQyLTgwOTdkY2I4YWJkODwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOS0wNy0yMlQyMzo1MDoxNS0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDo5NzZlZmVlMC1kOTZmLWQ1NDYtOTIxMC0wNjA5NGFiN2RlNTE8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTktMDctMjJUMjM6NTA6NDYtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MmU5Yjg4ZjItNzJhZS0zMjQ5LTg5OGUtN2IxNDI0ZjY2ZTI4PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE5LTA3LTI2VDE4OjEyOjUxLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jb252ZXJ0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnBhcmFtZXRlcnM+ZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL2pwZWc8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5kZXJpdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmNvbnZlcnRlZCBmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvanBlZzwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6M2Q5ZTkzMmYtZTRmNC05MDRlLWE2MTQtY2YwMjBkYzYzZGNmPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE5LTA3LTI2VDE4OjEyOjUxLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmQ2YzUzY2FhLWRhMzktNzI0Zi1iNGZmLTY4ZWRkOWRiYWZkNjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOS0wOC0xM1QxNzo0MzozMC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y29udmVydGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmZyb20gaW1hZ2UvanBlZyB0byBpbWFnZS9wbmc8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5kZXJpdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmNvbnZlcnRlZCBmcm9tIGltYWdlL2pwZWcgdG8gaW1hZ2UvcG5nPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDo0MmIzNjk2NS04ZjI5LWQ0NDEtYjJmOS05NTNiZTJhNWJhZTY8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTktMDgtMTNUMTc6NDM6MzAtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6NzNlNTdkYTYtMDFiOC1mNDQ1LTlmMTEtYjIxODc1NmJjZWZlPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE5LTA4LTEzVDE3OjQ2OjIzLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwveG1wTU06SGlzdG9yeT4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOmluc3RhbmNlSUQ+eG1wLmlpZDpkNmM1M2NhYS1kYTM5LTcyNGYtYjRmZi02OGVkZDlkYmFmZDY8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo3ZDBjYmQ1Mi1hZmYyLTExZTktOGY4ZS05YzQ4OTgwOWNiOTU8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgICAgIDxzdFJlZjpvcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpkMjQ1NmY1NS05OWZiLTk5NGUtOGE0Mi04MDk3ZGNiOGFiZDg8L3N0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPC94bXBNTTpEZXJpdmVkRnJvbT4KICAgICAgICAgPHBob3Rvc2hvcDpMZWdhY3lJUFRDRGlnZXN0PjI3QUUyMTVBODcyNUI0NDlFQ0Q4QzNGNEQxQkI2QkFDPC9waG90b3Nob3A6TGVnYWN5SVBUQ0RpZ2VzdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHRpZmY6SW1hZ2VXaWR0aD4xMDAwPC90aWZmOkltYWdlV2lkdGg+CiAgICAgICAgIDx0aWZmOkltYWdlTGVuZ3RoPjEwMDA8L3RpZmY6SW1hZ2VMZW5ndGg+CiAgICAgICAgIDx0aWZmOkJpdHNQZXJTYW1wbGU+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpPjg8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT44PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+ODwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwvdGlmZjpCaXRzUGVyU2FtcGxlPgogICAgICAgICA8dGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPjI8L3RpZmY6UGhvdG9tZXRyaWNJbnRlcnByZXRhdGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6U2FtcGxlc1BlclBpeGVsPjM8L3RpZmY6U2FtcGxlc1BlclBpeGVsPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4yMDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjIwMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6RXhpZlZlcnNpb24+MDIyMTwvZXhpZjpFeGlmVmVyc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj42NDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj42NDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+NSu5mgAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAHiklEQVR42uxZS49cVxGuqnPOffS7ZzwziWN7DIkBkYcEYsOG30AkNlkRARILxGOBWPAX2ASxCBtASLADxBokxGPDgqdFFMdREnsmnmHePdPd93EeVSx6xunusdvd80Cy1LXse7t0vlP1VX1VF59fvQlPsxE85TYHMAcwBzAHMAcwBzAHMAcwB/AUm57+VUTFbH2xBcDjyIWBtElWABUIT/RCIMEXW8IOUI0+YwAyyTNA+glOzgZAuFAqbXzsq8o0hMuROKrUFVu9rd+LMI4fa8yLQ8DWjddM8iyHbBRaEuxed+t3whZRXzAARCzz/aj5maVb30IkDvnwU2XqvtzPD/5hs3vKtCY4cWUXo2cXP/51kywHdzR6C4kIl913soO/63jp4gFYV5InwhD8kbAbfsjiQQKqZHLoEcB5C4QIwr4jIxFA5gJ1jXRFJFwKB0jXbL7R2fqL0tWRCAiQqYdi02X3AIRDBsKoEqToGA+SsJVQACkQLvv3D7f/nFRXvTscdoIqhdCz2Zoy9RmYOeVMTETOc6+3QxTpqDUcAQFRyiRmcFQDIgDAIUdUgHTySkBKkNAHzrIuACiVyFC4BESpOKIcIZBuiPgLjgAzo/QardXlW99Wps6hGCYmAqDSRAmACICJVzoPfr3/wc90fAUAQ7nbvvl669qXXLmFgALAPhMJo6VMlK6y7+zc/aEvd0lXL4EDxWGSvthY/nzw2XAEEEAAQATwxGlyNW28jIOSipiXdqn6ibh2E1AhIh5f+Tg9ADXpFw+rvy37H1wKAB/E2j5RTHE8GoFTTqO2iBd2iMgi1joRjpI2+6OJWZoEDuyzJxTiM5NYR+2iv7b+1hs6bnPIEU1wR77cRRpxwiJxsmA7f/UuR9xm5uBg486bxeGdEdYe9xav40VlGsyedEqhY7M1FbUunsSIyAxZ0XXZ7iDkwmCSetp8SdgNZ4SIGI1JukBmASQAgvNcZNvsjpDMuFeKss5tV/SQQClIk8Qky4CX0IlFhAhrlbqkg+zEvHtv6YXXr730/TJbH8tmEWF4yAhAJAABkKHfji2qXN+684Ptu29EleuIKHIiTC4jhUQEj08DCGAdANWY8+C6p092mqaPdOldT5kWkkEEETiD6ZneHlSbATUDg803OZQAIMKAAMIgAoiTrwEQAQkEAFGCdfkGyOByzmJ4tuUuIvb63SAqqV47vjqUYA+E/UnzeqwkRFQqWgBABknjBP1uCPn06u1cERi2Slovbdd1bwMSggRv29dfrbReDq4z4V/KtPLD/+yv/YaURlS2VCZuEaUz6Z8LADDgdCVtQFoHwOD7ztMzt75Wbb/iyt2JtXih6N7x3X9KyElXmBkAznz6c0VAREQEAAjBOV84BAARDxNPI+yYRQBYGJjh3HZ2AIAkwXLoASrhwuX9nXu/qi1+1pf7k1IoarveWz7fRIoDewAmVUUVz1Q6L4DEDzUc6SYSBZa8yLw9RMAJVUhEtFJpHJOpAahBcwjuEESeQP3LiIDLN1s3Xlt64Ruu2MLj3hxEwiN7wlD5AgACVHgs+1Z23/vxwdovTHL1/woAEfLCtszVKF1m3wfEKcu4jEZEx4tRdXXQXyYjv0gAiCgizoOETEdNE7cFztJFEVCZJvts+vHlfACQgL0rNgEYgVBg892fZodvcyjGb5adjto6viLsB2OaL3e93R8TcwKQxHXX/ZcEdvmGSEDUs65VZiGxeFJRZfELZBrAlgWLfM8XO6c0JpCu9ff/lnXWlAEAYA9p80Z14XPse6O5JEZhXFkh3RRxRIm3+/2dPwnI9CPB1AMNgC0PosYry5/8LpCRkCPi4zI/Sq/t3//lg9vfM/EyIOa9D5/79HdWnv9Kma2dqkv8UMORSoXtev/9vPNvHV+5aABE1hYYNIAL5QFMzlqMgAxSDCDCXDoRIVfu+HJv0tjtj0g3lWnORImpOSCCKnH5f/Ojd5WujS3VQARQIUWD1EDVLXvvCVsAEmAOIe+9H9yRd4MUQmELEsY6BqoK5xs2W1dTD8SzrVWs5153W+uKjtosbqyeMFukCCkS5iRONPQDWyIjAv2sGxhNsjiY8YGdsEUyI7VLRKnYUB/Fkm5Mr45mWKsoyRvNa+3VL2tTGxvqlanb7MPtuz9iLkglXCLrGqpEhBGxktad6wW7BqBQSsFo5dY34+r14LqjTiriu/v3fs6ugyq9hN1ocZC0P7W0+iqHYnS1CKRTDrbY+0PRfVtHi8IsJ5PhQLcmSR2khohlsYfx6uKNLypdYZ+NBBE1UNrb+WNv5765DAAuBHI5klaYcqCx7XQILgQrAnxKY36kWwGc9wI5EildGdOtqGIRFHY4iy6agcQ6ahX99Qd33tSmObwbFQClq+B3g90jXX/CJwZdy8vdzXd+EleeC6NtgVRKfOSy+xP22+cgMaJnyLIjV+yNaRYR0AoraarjpckfOE52M/0y38ZTo7IiqKSJiZeQoulJPEMnHkggedT5TjoaTtMQZbAEOIeTc6xVEB/Z5GXqlYgAPM7JDF7OvlY52+7mEpx8lNvwlNscwBzAHMAcwBzAHMAcwBzAOex/AwBoET5bwRr9gwAAAABJRU5ErkJggg=="
)
type Response struct {
Version Version `json:"version,string"`
Players Players `json:"players,string"`
Description Message `json:"description"`
Favicon string `json:"favicon"`
}
type Version struct {
Name string `json:"name"`
Protocol int `json:"protocol"`
}
type Players struct {
Max int `json:"max"`
Online int `json:"online"`
Sample []SamplePlayer `json:"sample"`
}
type SamplePlayer struct {
Name string `json:"name"`
ID string `json:"id"`
}
type Message struct {
Text string `json:"text"`
}
func DefaultResponse() Response {
return Response{
Version: Version{
Name: "GoLang Server",
Protocol: data.CurrentProtocol.Protocol(),
},
Players: Players{
Max: 10,
Online: 1,
Sample: []SamplePlayer{
{
Name: SxtannaName,
ID: SxtannaUUID,
},
},
},
Description: Message{
Text: chat.Translate(ServerMotd),
},
Favicon: ServerIcon,
}
}
================================================
FILE: impl/data/system/command.go
================================================
package system
type Command int
type Message struct {
Command
Message interface{}
}
const (
// stops the server entirely
STOP Command = iota
FAIL
)
func Make(command Command, message interface{}) Message {
return struct {
Command
Message interface{}
}{Command: command, Message: message}
}
================================================
FILE: impl/data/values/constants.go
================================================
package values
import (
"encoding/binary"
"github.com/golangmc/minecraft-server/apis/base"
)
const (
// ticks per second
TPS = 20
// milliseconds per tick
MPT = 1_000 / TPS
)
var DefaultWorldHashedSeed = int64(binary.LittleEndian.Uint64(base.JavaSHA256HashLong(int64(base.JavaStringHashCode("North Carolina")))))
================================================
FILE: impl/game/auth/authenticate.go
================================================
package auth
import (
"crypto/sha1"
"encoding/json"
"fmt"
"strings"
"github.com/golangmc/minecraft-server/apis/urls"
)
const url = "https://sessionserver.mojang.com/session/minecraft/hasJoined"
type Auth struct {
UUID string `json:"id"`
Name string `json:"name"`
Prop []Prop `json:"properties"`
}
type Prop struct {
Name string `json:"name"`
Data string `json:"value"`
Sign *string `json:"signature"`
}
func RunAuthGet(secret []byte, name string, callback func(auth *Auth, err error)) {
go execute(generateAuthURL(name, generateAuthSHA(secret)), callback)
}
func execute(url string, callback func(auth *Auth, err error)) {
get, err := urls.GetByte(url)
if err != nil {
callback(nil, err)
return
}
var auth Auth
err = json.Unmarshal(get, &auth)
if err != nil {
callback(nil, err)
} else {
callback(&auth, nil)
}
}
func generateAuthURL(name, hash string) string {
return fmt.Sprintf("%s?username=%s&serverId=%s", url, name, hash)
}
func generateAuthSHA(secret []byte) string {
sha := sha1.New()
// update with encoded secret, and encoded public
_, public := NewCrypt()
sha.Write(secret)
sha.Write(public)
hash := sha.Sum(nil)
// Check for negative hashes
negative := (hash[0] & 0x80) == 0x80
if negative {
carry := true
for i := len(hash) - 1; i >= 0; i-- {
hash[i] = ^hash[i]
if carry {
carry = hash[i] == 0xff
hash[i]++
}
}
}
// Trim away zeroes
res := strings.TrimLeft(fmt.Sprintf("%x", hash), "0")
if negative {
res = "-" + res
}
return res
}
================================================
FILE: impl/game/auth/cryptography.go
================================================
package auth
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
)
var secretKey *rsa.PrivateKey
var publicKey *rsa.PublicKey
var secretArr []byte
var publicArr []byte
func NewCrypt() (secret []byte, public []byte) {
// initialize keys
if secretKey == nil || publicKey == nil {
secretKey, publicKey = generate()
x509Secret := x509.MarshalPKCS1PrivateKey(secretKey)
x509Public, _ := x509.MarshalPKIXPublicKey(publicKey)
secretArr = x509Secret
publicArr = x509Public
}
return secretArr, publicArr
}
func Encrypt(data []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, publicKey, data)
}
func Decrypt(data []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, secretKey, data)
}
func generate() (secretKey *rsa.PrivateKey, publicKey *rsa.PublicKey) {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
secretKey = key
publicKey = &key.PublicKey
secretKey.Precompute()
if err := secretKey.Validate(); err != nil {
panic(err)
}
return
}
================================================
FILE: impl/game/ents/entity.go
================================================
package ents
import "github.com/golangmc/minecraft-server/apis/uuid"
var entityCounter = int64(0)
type entity struct {
name string
uuid uuid.UUID
entityID int64
}
func newEntity() entity {
id := entityCounter
entityCounter++
return entity{entityID: id}
}
func (e *entity) Name() string {
return e.name
}
func (e *entity) UUID() uuid.UUID {
return e.uuid
}
func (e *entity) SetName(name string) {
e.name = name
}
func (e *entity) SetUUID(uuid uuid.UUID) {
e.uuid = uuid
}
func (e *entity) SendMessage(message ...interface{}) {
// nothing
}
func (e *entity) EntityUUID() int64 {
return e.entityID
}
================================================
FILE: impl/game/ents/living.go
================================================
package ents
type entityLiving struct {
entity
health float64
}
func newEntityLiving() entityLiving {
return entityLiving{entity: newEntity()}
}
func (e *entityLiving) GetHealth() float64 {
return e.health
}
func (e *entityLiving) SetHealth(health float64) {
e.health = health
}
================================================
FILE: impl/game/ents/player.go
================================================
package ents
import (
"github.com/golangmc/minecraft-server/apis/data/msgs"
"github.com/golangmc/minecraft-server/apis/ents"
"github.com/golangmc/minecraft-server/apis/game"
"github.com/golangmc/minecraft-server/impl/prot/client"
apis_base "github.com/golangmc/minecraft-server/apis/base"
impl_base "github.com/golangmc/minecraft-server/impl/base"
)
type player struct {
entityLiving
prof *game.Profile
online bool
conn impl_base.Connection
mode game.GameMode
}
func NewPlayer(prof *game.Profile, conn impl_base.Connection) ents.Player {
player := &player{
prof: prof,
entityLiving: newEntityLiving(),
}
player.SetName(prof.Name)
player.SetUUID(prof.UUID)
player.SetConn(conn)
return player
}
func (p *player) SendMessage(message ...interface{}) {
packet := client.PacketOChatMessage{
Message: *msgs.New(apis_base.ConvertToString(message...)),
MessagePosition: msgs.NormalChat,
}
p.conn.SendPacket(&packet)
}
func (p *player) GetGameMode() game.GameMode {
return p.mode
}
func (p *player) SetGameMode(mode game.GameMode) {
p.mode = mode
}
func (p *player) GetIsOnline() bool {
return p.online
}
func (p *player) SetIsOnline(state bool) {
p.online = state
}
func (p *player) GetProfile() *game.Profile {
return p.prof
}
func (p *player) SetConn(conn impl_base.Connection) {
p.conn = conn
}
================================================
FILE: impl/game/event/events.go
================================================
package event
import (
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/plugin"
)
type PlayerConnJoinEvent struct {
Conn base.PlayerAndConnection
}
type PlayerConnQuitEvent struct {
Conn base.PlayerAndConnection
}
type PlayerPluginMessagePullEvent struct {
Conn base.PlayerAndConnection
Channel string
Message plugin.Message
}
================================================
FILE: impl/game/level/block.go
================================================
package level
import (
apis_level "github.com/golangmc/minecraft-server/apis/game/level"
)
type block struct {
// these should always be level coordinates
x int
y int
z int
slice *slice
}
func (b *block) X() int {
return b.x
}
func (b *block) Y() int {
return b.y
}
func (b *block) Z() int {
return b.z
}
func (b *block) Chunk() apis_level.Chunk {
return b.slice.chunk
}
func (b *block) Level() apis_level.Level {
return b.slice.chunk.level
}
func (b *block) GetBlockType() (value int) {
value = b.slice.sliceBlockGet(sliceIndex(blockLevelToSlice(b.x, b.y, b.z)))
return
}
func (b *block) SetBlockType(value int) {
value = b.slice.sliceBlockSet(sliceIndex(blockLevelToSlice(b.x, b.y, b.z)), value)
return
}
================================================
FILE: impl/game/level/chunk.go
================================================
package level
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data/tags"
apis_level "github.com/golangmc/minecraft-server/apis/game/level"
"github.com/golangmc/minecraft-server/impl/base"
)
type chunk struct {
x int
z int
level *level
slices []*slice
heightMap map[heightMapType]*heightMap
}
func newChunk(level *level, x, z int) *chunk {
chunk := &chunk{
x: x,
z: z,
level: level,
slices: make([]*slice, apis_level.SliceC, apis_level.SliceC),
heightMap: make(map[heightMapType]*heightMap),
}
for _, mapType := range heightMapTypes {
chunk.heightMap[mapType] = &heightMap{
chunk: chunk,
heightMapType: mapType,
heightMapData: base.NewCompacter(9, 256),
}
}
return chunk
}
func (c *chunk) ChunkX() int {
return c.x
}
func (c *chunk) ChunkZ() int {
return c.z
}
func (c *chunk) Level() apis_level.Level {
return c.level
}
func (c *chunk) Slices() []apis_level.Slice {
slices := make([]apis_level.Slice, apis_level.SliceC, apis_level.SliceC)
for index, slice := range c.slices {
slices[index] = slice
}
return slices
}
func (c *chunk) GetSlice(y int) apis_level.Slice {
if y < 0 || y > 15 {
panic("index out of range [0:15]")
}
slc := c.slices[y]
if slc != nil {
return slc
}
gen := newSlice(c, y)
c.slices[y] = gen
return gen
}
func (c *chunk) GetBlock(x, y, z int) apis_level.Block {
if x < 0 || x > 15 {
panic("invalid x value for chunk get block")
}
if y < 0 || y > 255 {
panic("invalid y value for chunk get block")
}
if z < 0 || z > 15 {
panic("invalid z value for chunk get block")
}
return &block{
x: (c.x << 0x04) | x,
y: y,
z: (c.z << 0x04) | z,
slice: c.GetSlice(y >> 0x04).(*slice),
}
}
func (c *chunk) Push(writer buff.Buffer) {
mask := int32(0)
for i := 0; i < apis_level.SliceC; i++ {
if len(c.slices) < i {
break
}
mask |= 1 << i
slice := c.slices[i]
slice.Push(writer)
}
writer.PushVrI(mask)
}
func (c *chunk) HeightMapNbtCompound() *tags.NbtCompound {
compound := tags.NbtCompound{Value: make(map[string]tags.Nbt)}
motionBlocking := c.heightMap[MotionBlocking]
compound.Set(string(motionBlocking.heightMapType), &tags.NbtArrI64{Value: motionBlocking.heightMapData.Values})
return &compound
}
type heightMapType string
const (
WorldSurfaceWg heightMapType = "WORLD_SURFACE_WG"
WorldSurface heightMapType = "WORLD_SURFACE"
OceanFloorWg heightMapType = "OCEAN_FLOOR_WG"
OceanFloor heightMapType = "OCEAN_FLOOR"
MotionBlocking heightMapType = "MOTION_BLOCKING"
MotionBlockingNoLeaves heightMapType = "MOTION_BLOCKING_NO_LEAVES"
)
var heightMapTypes = []heightMapType{
WorldSurfaceWg,
WorldSurface,
OceanFloorWg,
OceanFloor,
MotionBlocking,
MotionBlockingNoLeaves,
}
type heightMap struct {
chunk *chunk
check func(b *block) bool
heightMapType heightMapType
heightMapData *base.Compacter
}
================================================
FILE: impl/game/level/level.go
================================================
package level
import (
apis_level "github.com/golangmc/minecraft-server/apis/game/level"
"github.com/golangmc/minecraft-server/apis/uuid"
)
type level struct {
name string
uuid uuid.UUID
chunks map[int64]*chunk
}
func NewLevel(name string) apis_level.Level {
level := &level{
name: name,
uuid: uuid.NewUUID(),
chunks: make(map[int64]*chunk),
}
return level
}
func (l *level) Name() string {
return l.name
}
func (l *level) UUID() uuid.UUID {
return l.uuid
}
func (l *level) Chunks() []apis_level.Chunk {
chunks := make([]apis_level.Chunk, len(l.chunks), len(l.chunks))
index := 0
for _, chunk := range l.chunks {
chunks[index] = chunk
index++
}
return chunks
}
func (l *level) GetChunk(x, z int) apis_level.Chunk {
return l.getChunk(x, z, true)
}
func (l *level) GetChunkIfLoaded(x, z int) apis_level.Chunk {
return l.getChunk(x, z, false)
}
func (l *level) GetBlock(x, y, z int) apis_level.Block {
return &block{
x: x,
y: y,
z: z,
slice: l.GetChunk(blockXZToChunkXZ(x, z)).GetSlice(blockYToSliceY(y)).(*slice),
}
}
func (l *level) getChunk(x, z int, generate bool) apis_level.Chunk {
idx := chunkIndex(x, z)
cnk, con := l.chunks[idx]
if con {
return cnk
}
if generate {
gen := newChunk(l, x, z)
l.chunks[idx] = gen
return gen
}
return nil
}
// generates chunks with the normal super-flat style
func GenSuperFlat(level apis_level.Level, size int) {
id := 210
for x := -size; x < size; x++ {
for z := -size; z < size; z++ {
chunk := level.GetChunk(x, z)
for sliceY := 0; sliceY < apis_level.SliceC; sliceY++ {
chunk.GetSlice(sliceY)
}
chunk.GetSlice(0).(*slice).fill(id)
chunk.GetSlice(1).(*slice).fill(id)
chunk.GetSlice(2).(*slice).fill(id)
id++
}
}
for _, c := range level.Chunks() {
_ = c.(*chunk).heightMap[MotionBlocking]
for x := 0; x < apis_level.ChunkW; x++ {
for z := 0; z < apis_level.ChunkL; z++ {
// height.heightMapData.Set(x + z * 16, 16 * 3)
}
}
}
}
================================================
FILE: impl/game/level/slice.go
================================================
package level
import (
"github.com/golangmc/minecraft-server/apis/buff"
apis_level "github.com/golangmc/minecraft-server/apis/game/level"
"github.com/golangmc/minecraft-server/impl/base"
)
type slice struct {
index int
chunk *chunk
values *base.Compacter
}
func newSlice(chunk *chunk, index int) *slice {
slice := &slice{
index: index,
chunk: chunk,
values: base.NewCompacter(apis_level.BitsPerBlock, apis_level.SliceS),
}
return slice
}
func (s *slice) Index() int {
return s.index
}
func (s *slice) Chunk() apis_level.Chunk {
return s.chunk
}
func (s *slice) Level() apis_level.Level {
return s.chunk.level
}
func (s *slice) GetBlock(x, y, z int) apis_level.Block {
if x < 0 || x > 15 {
panic("invalid x value for slice get block")
}
if y < 0 || y > 15 {
panic("invalid y value for slice get block")
}
if z < 0 || z > 15 {
panic("invalid z value for slice get block")
}
return &block{
x: (s.chunk.x << 0x04) | x,
y: (apis_level.SliceH * s.index) + y,
z: (s.chunk.z << 0x04) | z,
slice: s,
}
}
func (s *slice) Push(writer buff.Buffer) {
writer.PushI16(apis_level.SliceS) // full slice
writer.PushByt(apis_level.BitsPerBlock)
// the server is using the direct palette
writer.PushVrI(int32(len(s.values.Values)))
for _, value := range s.values.Values {
writer.PushI64(value)
}
}
func (s *slice) sliceBlockGet(index int) int {
return s.values.Get(index)
}
func (s *slice) sliceBlockSet(index int, value int) int {
return s.values.Set(index, value)
}
func (s *slice) fill(value int) {
for y := 0; y < apis_level.SliceH; y++ {
s.layer(y, value)
}
}
func (s *slice) layer(index int, value int) {
for x := 0; x < apis_level.ChunkW; x++ {
for z := 0; z < apis_level.ChunkL; z++ {
s.sliceBlockSet(sliceIndex(x, index, z), value)
}
}
}
================================================
FILE: impl/game/level/value.go
================================================
package level
func chunkIndex(x, z int) int64 {
return (int64(z) << 0x20) | (int64(x) & 0xFFFFFFFF)
}
func sliceIndex(x, y, z int) int {
return y<<0x08 | z<<0x04 | x
}
func blockYToSliceY(blockY int) (sliceY int) {
sliceY = blockY >> 0x04
return
}
func blockXZToChunkXZ(blockX, blockZ int) (chunkX, chunkZ int) {
chunkX = blockX >> 0x04
chunkZ = blockZ >> 0x04
return
}
func blockLevelToSlice(levelBlockX, levelBlockY, levelBlockZ int) (sliceBlockX, sliceBlockY, sliceBlockZ int) {
sliceBlockX = levelBlockX & 0xF
sliceBlockY = levelBlockY & 0xF
sliceBlockZ = levelBlockZ & 0xF
return
}
================================================
FILE: impl/game/mode/mode_state0.go
================================================
package mode
import (
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/prot/server"
)
/**
* handshake
*/
func HandleState0(watcher util.Watcher) {
watcher.SubAs(func(packet *server.PacketIHandshake, conn base.Connection) {
conn.SetState(packet.State)
})
}
================================================
FILE: impl/game/mode/mode_state1.go
================================================
package mode
import (
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/status"
"github.com/golangmc/minecraft-server/impl/prot/client"
"github.com/golangmc/minecraft-server/impl/prot/server"
)
/**
* status
*/
func HandleState1(watcher util.Watcher) {
watcher.SubAs(func(packet *server.PacketIRequest, conn base.Connection) {
response := client.PacketOResponse{Status: status.DefaultResponse()}
conn.SendPacket(&response)
})
watcher.SubAs(func(packet *server.PacketIPing, conn base.Connection) {
response := client.PacketOPong{Ping: packet.Ping}
conn.SendPacket(&response)
})
}
================================================
FILE: impl/game/mode/mode_state2.go
================================================
package mode
import (
"bytes"
"fmt"
"github.com/golangmc/minecraft-server/apis/data/chat"
"github.com/golangmc/minecraft-server/apis/data/msgs"
"github.com/golangmc/minecraft-server/apis/game"
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/apis/uuid"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/game/auth"
"github.com/golangmc/minecraft-server/impl/game/ents"
"github.com/golangmc/minecraft-server/impl/prot/client"
"github.com/golangmc/minecraft-server/impl/prot/server"
)
/**
* login
*/
func HandleState2(watcher util.Watcher, join chan base.PlayerAndConnection) {
watcher.SubAs(func(packet *server.PacketILoginStart, conn base.Connection) {
conn.CertifyValues(packet.PlayerName)
_, public := auth.NewCrypt()
response := client.PacketOEncryptionRequest{
Server: "",
Public: public,
Verify: conn.CertifyData(),
}
conn.SendPacket(&response)
})
watcher.SubAs(func(packet *server.PacketIEncryptionResponse, conn base.Connection) {
defer func() {
if err := recover(); err != nil {
conn.SendPacket(&client.PacketODisconnect{
Reason: *msgs.New(fmt.Sprintf("Authentication failed: %v", err)).SetColor(chat.Red),
})
}
}()
ver, err := auth.Decrypt(packet.Verify)
if err != nil {
panic(fmt.Errorf("failed to decrypt token: %s\n%v\n", conn.CertifyName(), err))
}
if !bytes.Equal(ver, conn.CertifyData()) {
panic(fmt.Errorf("encryption failed, tokens are different: %s\n%v | %v", conn.CertifyName(), ver, conn.CertifyData()))
}
sec, err := auth.Decrypt(packet.Secret)
if err != nil {
panic(fmt.Errorf("failed to decrypt secret: %s\n%v\n", conn.CertifyName(), err))
}
conn.CertifyUpdate(sec) // enable encryption on the connection
auth.RunAuthGet(sec, conn.CertifyName(), func(auth *auth.Auth, err error) {
defer func() {
if err := recover(); err != nil {
conn.SendPacket(&client.PacketODisconnect{
Reason: *msgs.New(fmt.Sprintf("Authentication failed: %v", err)).SetColor(chat.Red),
})
}
}()
if err != nil {
panic(fmt.Errorf("failed to authenticate: %s\n%v\n", conn.CertifyName(), err))
}
uuid, err := uuid.TextToUUID(auth.UUID)
if err != nil {
panic(fmt.Errorf("failed to decode uuid for %s: %s\n%v\n", conn.CertifyName(), auth.UUID, err))
}
prof := game.Profile{
UUID: uuid,
Name: auth.Name,
}
for _, prop := range auth.Prop {
prof.Properties = append(prof.Properties, &game.ProfileProperty{
Name: prop.Name,
Value: prop.Data,
Signature: prop.Sign,
})
}
player := ents.NewPlayer(&prof, conn)
conn.SendPacket(&client.PacketOLoginSuccess{
PlayerName: player.Name(),
PlayerUUID: player.UUID().String(),
})
conn.SetState(base.PLAY)
join <- base.PlayerAndConnection{
Player: player,
Connection: conn,
}
})
})
}
================================================
FILE: impl/game/mode/mode_state3.go
================================================
package mode
import (
"fmt"
"time"
"github.com/golangmc/minecraft-server/apis"
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/data/chat"
"github.com/golangmc/minecraft-server/apis/data/msgs"
"github.com/golangmc/minecraft-server/apis/game"
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/apis/task"
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/client"
"github.com/golangmc/minecraft-server/impl/data/plugin"
"github.com/golangmc/minecraft-server/impl/data/values"
impl_level "github.com/golangmc/minecraft-server/impl/game/level"
impl_event "github.com/golangmc/minecraft-server/impl/game/event"
client_packet "github.com/golangmc/minecraft-server/impl/prot/client"
server_packet "github.com/golangmc/minecraft-server/impl/prot/server"
)
func HandleState3(watcher util.Watcher, logger *logs.Logging, tasking *task.Tasking, join chan base.PlayerAndConnection, quit chan base.PlayerAndConnection) {
tasking.EveryTime(10, time.Second, func(task *task.Task) {
api := apis.MinecraftServer()
// I hate this, add a functional method for player iterating
for _, player := range api.Players() {
// also probably add one that returns both the player and their connection
conn := api.ConnByUUID(player.UUID())
// keep player connection alive via keep alive
conn.SendPacket(&client_packet.PacketOKeepAlive{KeepAliveID: time.Now().UnixNano() / 1e6})
}
})
watcher.SubAs(func(packet *server_packet.PacketIKeepAlive, conn base.Connection) {
logger.DataF("player %s is being kept alive", conn.Address())
})
watcher.SubAs(func(packet *server_packet.PacketIPluginMessage, conn base.Connection) {
api := apis.MinecraftServer()
player := api.PlayerByConn(conn)
if player == nil {
return // log no player found?
}
api.Watcher().PubAs(impl_event.PlayerPluginMessagePullEvent{
Conn: base.PlayerAndConnection{
Connection: conn,
Player: player,
},
Channel: packet.Message.Chan(),
Message: packet.Message,
})
})
watcher.SubAs(func(packet *server_packet.PacketIChatMessage, conn base.Connection) {
api := apis.MinecraftServer()
who := api.PlayerByConn(conn)
out := msgs.
New(who.Name()).SetColor(chat.White).
Add(":").SetColor(chat.Gray).
Add(" ").
Add(chat.Translate(packet.Message)).SetColor(chat.White).
AsText() // why not just use translate?
api.Broadcast(out)
})
go func() {
for conn := range join {
apis.MinecraftServer().Watcher().PubAs(impl_event.PlayerConnJoinEvent{Conn: conn})
conn.SendPacket(&client_packet.PacketOJoinGame{
EntityID: int32(conn.EntityUUID()),
Hardcore: false,
GameMode: game.CREATIVE,
Dimension: game.OVERWORLD,
HashedSeed: values.DefaultWorldHashedSeed,
MaxPlayers: 10,
LevelType: game.DEFAULT,
ViewDistance: 12,
ReduceDebug: false,
RespawnScreen: false,
})
conn.SendPacket(&client_packet.PacketOPluginMessage{
Message: &plugin.Brand{
Name: chat.Translate(fmt.Sprintf("&b%s&r &a%s&r", "GoLangMc", apis.MinecraftServer().ServerVersion())),
},
})
conn.SendPacket(&client_packet.PacketOServerDifficulty{
Difficulty: game.PEACEFUL,
Locked: true,
})
conn.SendPacket(&client_packet.PacketOPlayerAbilities{
Abilities: client.PlayerAbilities{
Invulnerable: true,
Flying: true,
AllowFlight: true,
InstantBuild: false,
},
FlyingSpeed: 0.05, // default value
FieldOfView: 0.1, // default value
})
conn.SendPacket(&client_packet.PacketOHeldItemChange{
Slot: client.SLOT_0,
})
conn.SendPacket(&client_packet.PacketODeclareRecipes{})
conn.SendPacket(&client_packet.PacketOPlayerLocation{
ID: 0,
Location: data.Location{
PositionF: data.PositionF{
X: 0,
Y: 10,
Z: 0,
},
RotationF: data.RotationF{
AxisX: 0,
AxisY: 0,
},
},
Relative: client.Relativity{},
})
conn.SendPacket(&client_packet.PacketOPlayerInfo{
Action: client.AddPlayer,
Values: []client.PlayerInfo{
&client.PlayerInfoAddPlayer{Player: conn.Player},
},
})
conn.SendPacket(&client_packet.PacketOEntityMetadata{Entity: conn.Player})
level := impl_level.NewLevel("test")
impl_level.GenSuperFlat(level, 6)
for _, chunk := range level.Chunks() {
conn.SendPacket(&client_packet.PacketOChunkData{Chunk: chunk})
}
logger.DataF("chunks sent to player: %s", conn.Player.Name())
conn.SendPacket(&client_packet.PacketOPlayerLocation{
ID: 1,
Location: data.Location{
PositionF: data.PositionF{
X: 0,
Y: 10,
Z: 0,
},
RotationF: data.RotationF{
AxisX: 0,
AxisY: 0,
},
},
Relative: client.Relativity{},
})
}
}()
go func() {
for conn := range quit {
apis.MinecraftServer().Watcher().PubAs(impl_event.PlayerConnQuitEvent{Conn: conn})
}
}()
}
================================================
FILE: impl/mask/masking.go
================================================
package mask
type Masking struct{}
func (m *Masking) Has(mask, field byte) bool {
return mask&field != 0
}
func (m *Masking) Set(mask *byte, field byte, when bool) {
if when {
*mask |= field
}
}
================================================
FILE: impl/mask/masking_test.go
================================================
package mask
import (
"fmt"
"testing"
)
type Data struct {
Masking
Head bool
Body bool
}
func TestMasking(t *testing.T) {
mask := byte(0)
data := Data{
Head: true,
}
data.Set(&mask, 0x01, data.Head)
data.Set(&mask, 0x02, data.Body)
fmt.Println(data.Has(mask, 0x01))
fmt.Println(data.Has(mask, 0x02))
}
================================================
FILE: impl/prot/client/to_client_state0.go
================================================
package client
// done
================================================
FILE: impl/prot/client/to_client_state1.go
================================================
package client
import (
"encoding/json"
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/status"
)
// done
type PacketOResponse struct {
Status status.Response
}
func (p *PacketOResponse) UUID() int32 {
return 0x00
}
func (p *PacketOResponse) Push(writer buff.Buffer, conn base.Connection) {
if text, err := json.Marshal(p.Status); err != nil {
panic(err)
} else {
writer.PushTxt(string(text))
}
}
type PacketOPong struct {
Ping int64
}
func (p *PacketOPong) UUID() int32 {
return 0x01
}
func (p *PacketOPong) Push(writer buff.Buffer, conn base.Connection) {
writer.PushI64(p.Ping)
}
================================================
FILE: impl/prot/client/to_client_state2.go
================================================
package client
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data/msgs"
"github.com/golangmc/minecraft-server/impl/base"
)
// done
type PacketODisconnect struct {
Reason msgs.Message
}
func (p *PacketODisconnect) UUID() int32 {
return 0x00
}
func (p *PacketODisconnect) Push(writer buff.Buffer, conn base.Connection) {
message := p.Reason
writer.PushTxt(message.AsJson())
}
type PacketOEncryptionRequest struct {
Server string // unused?
Public []byte
Verify []byte
}
func (p *PacketOEncryptionRequest) UUID() int32 {
return 0x01
}
func (p *PacketOEncryptionRequest) Push(writer buff.Buffer, conn base.Connection) {
writer.PushTxt(p.Server)
writer.PushUAS(p.Public, true)
writer.PushUAS(p.Verify, true)
}
type PacketOLoginSuccess struct {
PlayerUUID string
PlayerName string
}
func (p *PacketOLoginSuccess) UUID() int32 {
return 0x02
}
func (p *PacketOLoginSuccess) Push(writer buff.Buffer, conn base.Connection) {
writer.PushTxt(p.PlayerUUID)
writer.PushTxt(p.PlayerName)
}
type PacketOSetCompression struct {
Threshold int32
}
func (p *PacketOSetCompression) UUID() int32 {
return 0x03
}
func (p *PacketOSetCompression) Push(writer buff.Buffer, conn base.Connection) {
writer.PushVrI(p.Threshold)
}
type PacketOLoginPluginRequest struct {
MessageID int32
Channel string
OptData []byte
}
func (p *PacketOLoginPluginRequest) UUID() int32 {
return 0x04
}
func (p *PacketOLoginPluginRequest) Push(writer buff.Buffer, conn base.Connection) {
writer.PushVrI(p.MessageID)
writer.PushTxt(p.Channel)
writer.PushUAS(p.OptData, false)
}
================================================
FILE: impl/prot/client/to_client_state3.go
================================================
package client
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/data/msgs"
"github.com/golangmc/minecraft-server/apis/ents"
"github.com/golangmc/minecraft-server/apis/game"
"github.com/golangmc/minecraft-server/apis/game/level"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/client"
"github.com/golangmc/minecraft-server/impl/data/plugin"
apis_conn "github.com/golangmc/minecraft-server/impl/conn"
)
type PacketOChatMessage struct {
Message msgs.Message
MessagePosition msgs.MessagePosition
}
func (p *PacketOChatMessage) UUID() int32 {
return 0x0F
}
func (p *PacketOChatMessage) Push(writer buff.Buffer, conn base.Connection) {
message := p.Message
if p.MessagePosition == msgs.HotBarText {
message = *msgs.New(message.AsText())
}
writer.PushTxt(message.AsJson())
writer.PushByt(byte(p.MessagePosition))
}
type PacketOJoinGame struct {
EntityID int32
Hardcore bool
GameMode game.GameMode
Dimension game.Dimension
HashedSeed int64
MaxPlayers int
LevelType game.LevelType
ViewDistance int32
ReduceDebug bool
RespawnScreen bool
}
func (p *PacketOJoinGame) UUID() int32 {
return 0x26
}
func (p *PacketOJoinGame) Push(writer buff.Buffer, conn base.Connection) {
writer.PushI32(p.EntityID)
writer.PushByt(p.GameMode.Encoded(p.Hardcore /* pull this value from somewhere */))
writer.PushI32(int32(p.Dimension))
writer.PushI64(p.HashedSeed)
writer.PushByt(uint8(p.MaxPlayers))
writer.PushTxt(p.LevelType.String())
writer.PushVrI(p.ViewDistance)
writer.PushBit(p.ReduceDebug)
writer.PushBit(p.RespawnScreen)
}
type PacketOPluginMessage struct {
Message plugin.Message
}
func (p *PacketOPluginMessage) UUID() int32 {
return 0x19
}
func (p *PacketOPluginMessage) Push(writer buff.Buffer, conn base.Connection) {
writer.PushTxt(p.Message.Chan())
p.Message.Push(writer)
}
type PacketOPlayerLocation struct {
Location data.Location
Relative client.Relativity
ID int32
}
func (p *PacketOPlayerLocation) UUID() int32 {
return 0x36
}
func (p *PacketOPlayerLocation) Push(writer buff.Buffer, conn base.Connection) {
writer.PushF64(p.Location.X)
writer.PushF64(p.Location.Y)
writer.PushF64(p.Location.Z)
writer.PushF32(p.Location.AxisX)
writer.PushF32(p.Location.AxisY)
p.Relative.Push(writer)
writer.PushVrI(p.ID)
}
type PacketOKeepAlive struct {
KeepAliveID int64
}
func (p *PacketOKeepAlive) UUID() int32 {
return 0x21
}
func (p *PacketOKeepAlive) Push(writer buff.Buffer, conn base.Connection) {
writer.PushI64(p.KeepAliveID)
}
type PacketOServerDifficulty struct {
Difficulty game.Difficulty
Locked bool // should probably always be true
}
func (p *PacketOServerDifficulty) UUID() int32 {
return 0x0E
}
func (p *PacketOServerDifficulty) Push(writer buff.Buffer, conn base.Connection) {
writer.PushByt(byte(p.Difficulty))
writer.PushBit(p.Locked)
}
type PacketOPlayerAbilities struct {
Abilities client.PlayerAbilities
FlyingSpeed float32
FieldOfView float32
}
func (p *PacketOPlayerAbilities) UUID() int32 {
return 0x32
}
func (p *PacketOPlayerAbilities) Push(writer buff.Buffer, conn base.Connection) {
p.Abilities.Push(writer)
writer.PushF32(p.FlyingSpeed)
writer.PushF32(p.FieldOfView)
}
type PacketOHeldItemChange struct {
Slot client.HotBarSlot
}
func (p *PacketOHeldItemChange) UUID() int32 {
return 0x40
}
func (p *PacketOHeldItemChange) Push(writer buff.Buffer, conn base.Connection) {
writer.PushByt(byte(p.Slot))
}
type PacketODeclareRecipes struct {
// Recipes []*Recipe // this doesn't exist yet ;(
RecipeCount int32
}
func (p *PacketODeclareRecipes) UUID() int32 {
return 0x5B
}
func (p *PacketODeclareRecipes) Push(writer buff.Buffer, conn base.Connection) {
writer.PushVrI(p.RecipeCount)
// when recipes are implemented, instead of holding a recipe count, simply write the size of the slice, Recipe will implement BufferPush
}
type PacketOChunkData struct {
Chunk level.Chunk
}
func (p *PacketOChunkData) UUID() int32 {
return 0x22
}
func (p *PacketOChunkData) Push(writer buff.Buffer, conn base.Connection) {
writer.PushI32(int32(p.Chunk.ChunkX()))
writer.PushI32(int32(p.Chunk.ChunkZ()))
// full chunk (for now >:D)
writer.PushBit(true)
chunkData := apis_conn.NewBuffer()
p.Chunk.Push(chunkData) // write chunk data and primary bit mask
// pull primary bit mask and push to writer
writer.PushVrI(chunkData.PullVrI())
// write height-maps
writer.PushNbt(p.Chunk.HeightMapNbtCompound())
biomes := make([]int32, 1024, 1024)
for i := range biomes {
biomes[i] = 0 // void biome
}
for _, biome := range biomes {
writer.PushI32(biome)
}
// data, prefixed with len
writer.PushUAS(chunkData.UAS(), true)
// write block entities
writer.PushVrI(0)
}
type PacketOPlayerInfo struct {
Action client.PlayerInfoAction
Values []client.PlayerInfo
}
func (p *PacketOPlayerInfo) UUID() int32 {
return 0x34
}
func (p *PacketOPlayerInfo) Push(writer buff.Buffer, conn base.Connection) {
writer.PushVrI(int32(p.Action))
writer.PushVrI(int32(len(p.Values)))
for _, value := range p.Values {
value.Push(writer)
}
}
type PacketOEntityMetadata struct {
Entity ents.Entity
}
func (p *PacketOEntityMetadata) UUID() int32 {
return 0x44
}
func (p *PacketOEntityMetadata) Push(writer buff.Buffer, conn base.Connection) {
writer.PushVrI(int32(p.Entity.EntityUUID())) // questionable...
// only supporting player metadata for now
_, ok := p.Entity.(ents.Player)
if ok {
writer.PushByt(16) // index | displayed skin parts
writer.PushVrI(0) // type | byte
skin := client.SkinParts{
Cape: true,
Head: true,
Body: true,
ArmL: true,
ArmR: true,
LegL: true,
LegR: true,
}
skin.Push(writer)
}
writer.PushByt(0xFF)
}
================================================
FILE: impl/prot/packets.go
================================================
package prot
import (
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/apis/task"
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/game/mode"
"github.com/golangmc/minecraft-server/impl/prot/server"
)
type packets struct {
util.Watcher
logger *logs.Logging
packetI map[base.PacketState]map[int32]func() base.PacketI // UUID to I server_data
join chan base.PlayerAndConnection
quit chan base.PlayerAndConnection
}
func NewPackets(tasking *task.Tasking, join chan base.PlayerAndConnection, quit chan base.PlayerAndConnection) base.Packets {
packets := &packets{
Watcher: util.NewWatcher(),
logger: logs.NewLogging("protocol", logs.EveryLevel...),
packetI: createPacketI(),
}
mode.HandleState0(packets)
mode.HandleState1(packets)
mode.HandleState2(packets, join)
mode.HandleState3(packets, packets.logger, tasking, join, quit)
return packets
}
func (p *packets) GetPacketI(uuid int32, state base.PacketState) base.PacketI {
creator := p.packetI[state][uuid]
if creator == nil {
return nil
}
return creator()
}
func createPacketI() map[base.PacketState]map[int32]func() base.PacketI {
return map[base.PacketState]map[int32]func() base.PacketI{
base.SHAKE: {
0x00: func() base.PacketI {
return &server.PacketIHandshake{}
},
},
base.STATUS: {
0x00: func() base.PacketI {
return &server.PacketIRequest{}
},
0x01: func() base.PacketI {
return &server.PacketIPing{}
},
},
base.LOGIN: {
0x00: func() base.PacketI {
return &server.PacketILoginStart{}
},
0x01: func() base.PacketI {
return &server.PacketIEncryptionResponse{}
},
0x02: func() base.PacketI {
return &server.PacketILoginPluginResponse{}
},
},
base.PLAY: {
0x00: func() base.PacketI {
return &server.PacketITeleportConfirm{}
},
0x01: func() base.PacketI {
return &server.PacketIQueryBlockNBT{}
},
0x02: func() base.PacketI {
return &server.PacketISetDifficulty{}
},
0x03: func() base.PacketI {
return &server.PacketIChatMessage{}
},
0x04: func() base.PacketI {
return &server.PacketIClientStatus{}
},
0x05: func() base.PacketI {
return &server.PacketIClientSettings{}
},
0x0B: func() base.PacketI {
return &server.PacketIPluginMessage{}
},
0x0F: func() base.PacketI {
return &server.PacketIKeepAlive{}
},
0x11: func() base.PacketI {
return &server.PacketIPlayerPosition{}
},
0x12: func() base.PacketI {
return &server.PacketIPlayerLocation{}
},
0x13: func() base.PacketI {
return &server.PacketIPlayerRotation{}
},
0x19: func() base.PacketI {
return &server.PacketIPlayerAbilities{}
},
},
}
}
================================================
FILE: impl/prot/server/to_server_state0.go
================================================
package server
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/base"
)
// done
type PacketIHandshake struct {
version int32
host string
port uint16
State base.PacketState
}
func (p *PacketIHandshake) UUID() int32 {
return 0x00
}
func (p *PacketIHandshake) Pull(reader buff.Buffer, conn base.Connection) {
p.version = reader.PullVrI()
p.host = reader.PullTxt()
p.port = reader.PullU16()
state := reader.PullVrI()
p.State = base.PacketStateValueOf(int(state))
}
================================================
FILE: impl/prot/server/to_server_state1.go
================================================
package server
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/base"
)
// done
type PacketIRequest struct {
}
func (p *PacketIRequest) UUID() int32 {
return 0x00
}
func (p *PacketIRequest) Pull(reader buff.Buffer, conn base.Connection) {
// no fields
}
type PacketIPing struct {
Ping int64
}
func (p *PacketIPing) UUID() int32 {
return 0x01
}
func (p *PacketIPing) Pull(reader buff.Buffer, conn base.Connection) {
p.Ping = reader.PullI64()
}
================================================
FILE: impl/prot/server/to_server_state2.go
================================================
package server
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/impl/base"
)
// done
type PacketILoginStart struct {
PlayerName string
}
func (p *PacketILoginStart) UUID() int32 {
return 0x00
}
func (p *PacketILoginStart) Pull(reader buff.Buffer, conn base.Connection) {
p.PlayerName = reader.PullTxt()
}
type PacketIEncryptionResponse struct {
Secret []byte
Verify []byte
}
func (p *PacketIEncryptionResponse) UUID() int32 {
return 0x01
}
func (p *PacketIEncryptionResponse) Pull(reader buff.Buffer, conn base.Connection) {
p.Secret = reader.PullUAS()
p.Verify = reader.PullUAS()
}
type PacketILoginPluginResponse struct {
Message int32
Success bool
OptData []byte
}
func (p *PacketILoginPluginResponse) UUID() int32 {
return 0x02
}
func (p *PacketILoginPluginResponse) Pull(reader buff.Buffer, conn base.Connection) {
p.Message = reader.PullVrI()
p.Success = reader.PullBit()
p.OptData = reader.UAS()[reader.InI():reader.Len()]
}
================================================
FILE: impl/prot/server/to_server_state3.go
================================================
package server
import (
"github.com/golangmc/minecraft-server/apis/buff"
"github.com/golangmc/minecraft-server/apis/data"
"github.com/golangmc/minecraft-server/apis/game"
"github.com/golangmc/minecraft-server/impl/base"
"github.com/golangmc/minecraft-server/impl/data/client"
"github.com/golangmc/minecraft-server/impl/data/plugin"
)
type PacketIKeepAlive struct {
KeepAliveID int64
}
func (p *PacketIKeepAlive) UUID() int32 {
return 0x0F
}
func (p *PacketIKeepAlive) Pull(reader buff.Buffer, conn base.Connection) {
p.KeepAliveID = reader.PullI64()
}
type PacketIChatMessage struct {
Message string
}
func (p *PacketIChatMessage) UUID() int32 {
return 0x03
}
func (p *PacketIChatMessage) Pull(reader buff.Buffer, conn base.Connection) {
p.Message = reader.PullTxt()
}
type PacketITeleportConfirm struct {
TeleportID int32
}
func (p *PacketITeleportConfirm) UUID() int32 {
return 0x00
}
func (p *PacketITeleportConfirm) Pull(reader buff.Buffer, conn base.Connection) {
p.TeleportID = reader.PullVrI()
}
type PacketIQueryBlockNBT struct {
TransactionID int32
Position data.PositionI
}
func (p *PacketIQueryBlockNBT) UUID() int32 {
return 0x01
}
func (p *PacketIQueryBlockNBT) Pull(reader buff.Buffer, conn base.Connection) {
p.TransactionID = reader.PullVrI()
p.Position = reader.PullPos()
}
type PacketISetDifficulty struct {
Difficult game.Difficulty
}
func (p *PacketISetDifficulty) UUID() int32 {
return 0x02
}
func (p *PacketISetDifficulty) Pull(reader buff.Buffer, conn base.Connection) {
p.Difficult = game.DifficultyValueOf(reader.PullByt())
}
type PacketIPluginMessage struct {
Message plugin.Message
}
func (p *PacketIPluginMessage) UUID() int32 {
return 0x0B
}
func (p *PacketIPluginMessage) Pull(reader buff.Buffer, conn base.Connection) {
channel := reader.PullTxt()
message := plugin.GetMessageForChannel(channel)
if message == nil {
return // log unregistered channel?
}
message.Pull(reader)
p.Message = message
}
type PacketIClientStatus struct {
Action client.StatusAction
}
func (p *PacketIClientStatus) UUID() int32 {
return 0x04
}
func (p *PacketIClientStatus) Pull(reader buff.Buffer, conn base.Connection) {
p.Action = client.StatusAction(reader.PullVrI())
}
type PacketIClientSettings struct {
Locale string
ViewDistance byte
ChatMode client.ChatMode
ChatColors bool // if false, strip messages of colors before sending
SkinParts client.SkinParts
MainHand client.MainHand
}
func (p *PacketIClientSettings) UUID() int32 {
return 0x05
}
func (p *PacketIClientSettings) Pull(reader buff.Buffer, conn base.Connection) {
p.Locale = reader.PullTxt()
p.ViewDistance = reader.PullByt()
p.ChatMode = client.ChatMode(reader.PullVrI())
p.ChatColors = reader.PullBit()
parts := client.SkinParts{}
parts.Pull(reader)
p.SkinParts = parts
p.MainHand = client.MainHand(reader.PullVrI())
}
type PacketIPlayerAbilities struct {
Abilities client.PlayerAbilities
FlightSpeed float32
GroundSpeed float32
}
func (p *PacketIPlayerAbilities) UUID() int32 {
return 0x19
}
func (p *PacketIPlayerAbilities) Pull(reader buff.Buffer, conn base.Connection) {
abilities := client.PlayerAbilities{}
abilities.Pull(reader)
p.Abilities = abilities
p.FlightSpeed = reader.PullF32()
p.GroundSpeed = reader.PullF32()
}
type PacketIPlayerPosition struct {
Position data.PositionF
OnGround bool
}
func (p *PacketIPlayerPosition) UUID() int32 {
return 0x11
}
func (p *PacketIPlayerPosition) Pull(reader buff.Buffer, conn base.Connection) {
p.Position = data.PositionF{
X: reader.PullF64(),
Y: reader.PullF64(),
Z: reader.PullF64(),
}
p.OnGround = reader.PullBit()
}
type PacketIPlayerLocation struct {
Location data.Location
OnGround bool
}
func (p *PacketIPlayerLocation) UUID() int32 {
return 0x12
}
func (p *PacketIPlayerLocation) Pull(reader buff.Buffer, conn base.Connection) {
p.Location = data.Location{
PositionF: data.PositionF{
X: reader.PullF64(),
Y: reader.PullF64(),
Z: reader.PullF64(),
},
RotationF: data.RotationF{
AxisX: reader.PullF32(),
AxisY: reader.PullF32(),
},
}
p.OnGround = reader.PullBit()
}
type PacketIPlayerRotation struct {
Rotation data.RotationF
OnGround bool
}
func (p *PacketIPlayerRotation) UUID() int32 {
return 0x13
}
func (p *PacketIPlayerRotation) Pull(reader buff.Buffer, conn base.Connection) {
p.Rotation = data.RotationF{
AxisX: reader.PullF32(),
AxisY: reader.PullF32(),
}
p.OnGround = reader.PullBit()
}
================================================
FILE: impl/server.go
================================================
package impl
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/golangmc/minecraft-server/apis"
"github.com/golangmc/minecraft-server/apis/cmds"
"github.com/golangmc/minecraft-server/apis/data/chat"
"github.com/golangmc/minecraft-server/apis/ents"
"github.com/golangmc/minecraft-server/apis/logs"
"github.com/golangmc/minecraft-server/apis/task"
"github.com/golangmc/minecraft-server/apis/util"
"github.com/golangmc/minecraft-server/apis/uuid"
"github.com/golangmc/minecraft-server/impl/conf"
"github.com/golangmc/minecraft-server/impl/data/plugin"
"github.com/golangmc/minecraft-server/impl/conn"
"github.com/golangmc/minecraft-server/impl/cons"
"github.com/golangmc/minecraft-server/impl/data/system"
"github.com/golangmc/minecraft-server/impl/data/values"
"github.com/golangmc/minecraft-server/impl/prot"
apis_base "github.com/golangmc/minecraft-server/apis/base"
impl_base "github.com/golangmc/minecraft-server/impl/base"
apis_event "github.com/golangmc/minecraft-server/apis/game/event"
impl_event "github.com/golangmc/minecraft-server/impl/game/event"
)
type server struct {
message chan system.Message
console *cons.Console
logging *logs.Logging
tasking *task.Tasking
watcher util.Watcher
command *cmds.CommandManager
network impl_base.Network
packets impl_base.Packets
players *playerAssociation
}
// ==== new ====
func NewServer(conf conf.ServerConfig) apis.Server {
message := make(chan system.Message)
console := cons.NewConsole(message)
logging := logs.NewLogging("server", logs.EveryLevel...)
tasking := task.NewTasking(values.MPT)
watcher := util.NewWatcher()
join := make(chan impl_base.PlayerAndConnection)
quit := make(chan impl_base.PlayerAndConnection)
packets := prot.NewPackets(tasking, join, quit)
network := conn.NewNetwork(conf.Network.Host, conf.Network.Port, packets, message, join, quit)
command := cmds.NewCommandManager()
return &server{
message: message,
console: console,
logging: logging,
tasking: tasking,
watcher: watcher,
command: command,
packets: packets,
network: network,
players: &playerAssociation{
uuidToData: make(map[uuid.UUID]ents.Player),
connToUUID: make(map[impl_base.Connection]uuid.UUID),
uuidToConn: make(map[uuid.UUID]impl_base.Connection),
},
}
}
// ==== State ====
func (s *server) Load() {
apis.SetMinecraftServer(s)
go s.loadServer()
go s.readInputs()
s.wait()
}
func (s *server) Kill() {
s.console.Kill()
s.command.Kill()
s.tasking.Kill()
s.network.Kill()
// push the stop message to the server exit channel
s.message <- system.Make(system.STOP, "normal stop")
close(s.message)
s.logging.Info(chat.DarkRed, "server stopped")
}
// ==== Server ====
func (s *server) Logging() *logs.Logging {
return s.logging
}
func (s *server) Command() *cmds.CommandManager {
return s.command
}
func (s *server) Tasking() *task.Tasking {
return s.tasking
}
func (s *server) Watcher() util.Watcher {
return s.watcher
}
func (s *server) Players() []ents.Player {
players := make([]ents.Player, 0)
for _, player := range s.players.uuidToData {
players = append(players, player)
}
return players
}
func (s *server) ConnByUUID(uuid uuid.UUID) impl_base.Connection {
return s.players.uuidToConn[uuid]
}
func (s *server) PlayerByUUID(uuid uuid.UUID) ents.Player {
return s.players.uuidToData[uuid]
}
func (s *server) PlayerByConn(conn impl_base.Connection) ents.Player {
uuid, con := s.players.connToUUID[conn]
if !con {
return nil
}
return s.PlayerByUUID(uuid)
}
func (s *server) ServerVersion() string {
return "0.0.1-SNAPSHOT"
}
func (s *server) Broadcast(message string) {
s.console.SendMessage(message)
for _, player := range s.Players() {
player.SendMessage(message)
}
}
// ==== server commands ====
func (s *server) broadcastCommand(sender ents.Sender, params []string) {
message := strings.Join(params, " ")
for _, player := range s.Players() {
player.SendMessage(message)
}
}
func (s *server) stopServerCommand(sender ents.Sender, params []string) {
if _, ok := sender.(*cons.Console); !ok {
s.logging.FailF("non console sender %s tried to stop the server", sender.Name())
return
}
var after int64 = 0
if len(params) > 0 {
param, err := strconv.Atoi(params[0])
if err != nil {
panic(err)
}
if param <= 0 {
panic(fmt.Errorf("value must be a positive whole number. [1..]"))
}
after = int64(param)
}
if after == 0 {
s.Kill()
} else {
// inform future shutdown
s.logging.Warn(chat.Gold, "stopping server in ", chat.Green, util.FormatTime(after))
// schedule shutdown {after} seconds later
s.tasking.AfterTime(after, time.Second, func(task *task.Task) {
s.Kill()
})
}
}
func (s *server) versionCommand(sender ents.Sender, params []string) {
sender.SendMessage(s.ServerVersion())
}
// ==== internal ====
func (s *server) loadServer() {
s.console.Load()
s.command.Load()
s.tasking.Load()
s.network.Load()
s.command.Register("vers", s.versionCommand)
s.command.Register("send", s.broadcastCommand)
s.command.Register("stop", s.stopServerCommand)
s.watcher.SubAs(func(event apis_event.PlayerJoinEvent) {
s.logging.InfoF("player %s logged in with uuid:%v", event.Player.Name(), event.Player.UUID())
s.Broadcast(chat.Translate(fmt.Sprintf("%s%s has joined!", chat.Yellow, event.Player.Name())))
})
s.watcher.SubAs(func(event apis_event.PlayerQuitEvent) {
s.logging.InfoF("%s disconnected!", event.Player.Name())
s.Broadcast(chat.Translate(fmt.Sprintf("%s%s has left!", chat.Yellow, event.Player.Name())))
})
s.watcher.SubAs(func(event impl_event.PlayerConnJoinEvent) {
s.players.addData(event.Conn)
s.watcher.PubAs(apis_event.PlayerJoinEvent{PlayerEvent: apis_event.PlayerEvent{Player: event.Conn.Player}})
})
s.watcher.SubAs(func(event impl_event.PlayerConnQuitEvent) {
player := s.players.playerByConn(event.Conn.Connection)
if player != nil {
s.watcher.PubAs(apis_event.PlayerQuitEvent{PlayerEvent: apis_event.PlayerEvent{Player: player}})
}
s.players.delData(event.Conn)
})
s.watcher.SubAs(func(event impl_event.PlayerPluginMessagePullEvent) {
s.logging.DataF("received message on channel '%s' from player %s:%s", event.Channel, event.Conn.Name(), event.Conn.UUID())
switch event.Channel {
case plugin.CHANNEL_BRAND:
s.logging.DataF("their client's brand is '%s'", event.Message.(*plugin.Brand).Name)
}
})
}
func (s *server) readInputs() {
for {
// read input from console
text := strings.Trim(<-s.console.IChannel, " ")
if len(text) == 0 {
continue
}
args := strings.Split(text, " ")
if len(args) == 0 {
continue
}
if command := s.command.Search(args[0]); command != nil {
err := apis_base.Attempt(func() {
(*command).Evaluate(s.console, args[1:])
})
if err != nil {
s.logging.Fail(
chat.Red, "failed to evaluate ",
chat.DarkGray, "`",
chat.White, (*command).Name(),
chat.DarkGray, "`",
chat.Red, ": ", err.Error()[8:])
}
continue
}
s.console.SendMessage(text)
}
}
func (s *server) wait() {
// select over server commands channel
select {
case command := <-s.message:
switch command.Command {
// stop selecting when stop is received
case system.STOP:
return
case system.FAIL:
s.logging.Fail("internal server error: ", command.Message)
s.logging.Fail("stopping server")
return
}
}
s.wait()
}
// ==== players ====
type playerAssociation struct {
uuidToData map[uuid.UUID]ents.Player
connToUUID map[impl_base.Connection]uuid.UUID
uuidToConn map[uuid.UUID]impl_base.Connection
}
func (p *playerAssociation) addData(data impl_base.PlayerAndConnection) {
p.uuidToData[data.Player.UUID()] = data.Player
p.connToUUID[data.Connection] = data.Player.UUID()
p.uuidToConn[data.Player.UUID()] = data.Connection
}
func (p *playerAssociation) delData(data impl_base.PlayerAndConnection) {
player := p.playerByConn(data.Connection)
uuid := p.connToUUID[data.Connection]
delete(p.connToUUID, data.Connection)
delete(p.uuidToConn, uuid)
if player != nil {
delete(p.uuidToData, player.UUID())
}
}
func (p *playerAssociation) playerByUUID(uuid uuid.UUID) ents.Player {
return p.uuidToData[uuid]
}
func (p *playerAssociation) playerByConn(conn impl_base.Connection) ents.Player {
uuid, con := p.connToUUID[conn]
if !con {
return nil
}
data, con := p.uuidToData[uuid]
if !con {
return nil
}
return data
}
================================================
FILE: main.go
================================================
package main
import (
"flag"
"github.com/fatih/color"
"github.com/golangmc/minecraft-server/impl"
"github.com/golangmc/minecraft-server/impl/conf"
)
func main() {
color.NoColor = false
server := impl.NewServer(mergeWithFlags(conf.DefaultServerConfig))
server.Load()
}
func mergeWithFlags(c conf.ServerConfig) conf.ServerConfig {
host := flag.String("host",
conf.DefaultServerConfig.Network.Host,
"the address this server will bind to")
port := flag.Int("port",
conf.DefaultServerConfig.Network.Port,
"the port this server will bind to")
flag.Parse()
if *host != conf.DefaultServerConfig.Network.Host {
c.Network.Host = *host
}
if *port != conf.DefaultServerConfig.Network.Port {
c.Network.Port = *port
}
return c
}
gitextract_p9xoijfz/ ├── .github/ │ └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── apis/ │ ├── base/ │ │ ├── funcs.go │ │ ├── named.go │ │ ├── state.go │ │ └── unique.go │ ├── buff/ │ │ └── buffers.go │ ├── cmds/ │ │ ├── command.go │ │ └── commandmanager.go │ ├── data/ │ │ ├── chat/ │ │ │ └── coloring.go │ │ ├── location.go │ │ ├── material.go │ │ ├── msgs/ │ │ │ └── messages.go │ │ ├── position.go │ │ ├── rotation.go │ │ ├── tags/ │ │ │ └── nbt.go │ │ └── versions.go │ ├── ents/ │ │ ├── entity.go │ │ ├── living.go │ │ ├── player.go │ │ └── sender.go │ ├── game/ │ │ ├── difficulty.go │ │ ├── dimension.go │ │ ├── event/ │ │ │ ├── block.go │ │ │ ├── cancel.go │ │ │ └── player.go │ │ ├── gamemode.go │ │ ├── level/ │ │ │ ├── block.go │ │ │ ├── chunk.go │ │ │ ├── level.go │ │ │ ├── slice.go │ │ │ └── value.go │ │ ├── leveltype.go │ │ └── profile.go │ ├── logs/ │ │ └── logging.go │ ├── math/ │ │ └── vector.go │ ├── rand/ │ │ └── random.go │ ├── server.go │ ├── task/ │ │ ├── tasking.go │ │ └── tasking_test.go │ ├── urls/ │ │ └── urls.go │ ├── util/ │ │ ├── formats.go │ │ └── watcher.go │ └── uuid/ │ └── uuids.go ├── go.mod ├── go.sum ├── impl/ │ ├── base/ │ │ ├── combine.go │ │ ├── compact.go │ │ ├── connect.go │ │ ├── network.go │ │ └── packets.go │ ├── conf/ │ │ └── config.go │ ├── conn/ │ │ ├── buffers.go │ │ ├── connect.go │ │ ├── crypto/ │ │ │ └── cfb8.go │ │ └── network.go │ ├── cons/ │ │ └── console.go │ ├── data/ │ │ ├── client/ │ │ │ ├── abilities.go │ │ │ ├── chat.go │ │ │ ├── hand.go │ │ │ ├── playerinfo.go │ │ │ ├── position.go │ │ │ ├── skin.go │ │ │ ├── slot.go │ │ │ └── status.go │ │ ├── plugin/ │ │ │ └── message.go │ │ ├── status/ │ │ │ └── response.go │ │ ├── system/ │ │ │ └── command.go │ │ └── values/ │ │ └── constants.go │ ├── game/ │ │ ├── auth/ │ │ │ ├── authenticate.go │ │ │ └── cryptography.go │ │ ├── ents/ │ │ │ ├── entity.go │ │ │ ├── living.go │ │ │ └── player.go │ │ ├── event/ │ │ │ └── events.go │ │ ├── level/ │ │ │ ├── block.go │ │ │ ├── chunk.go │ │ │ ├── level.go │ │ │ ├── slice.go │ │ │ └── value.go │ │ └── mode/ │ │ ├── mode_state0.go │ │ ├── mode_state1.go │ │ ├── mode_state2.go │ │ └── mode_state3.go │ ├── mask/ │ │ ├── masking.go │ │ └── masking_test.go │ ├── prot/ │ │ ├── client/ │ │ │ ├── to_client_state0.go │ │ │ ├── to_client_state1.go │ │ │ ├── to_client_state2.go │ │ │ └── to_client_state3.go │ │ ├── packets.go │ │ └── server/ │ │ ├── to_server_state0.go │ │ ├── to_server_state1.go │ │ ├── to_server_state2.go │ │ └── to_server_state3.go │ └── server.go └── main.go
SYMBOL INDEX (733 symbols across 92 files)
FILE: apis/base/funcs.go
function ConvertToString (line 10) | func ConvertToString(data ...interface{}) string {
function Attempt (line 20) | func Attempt(function func()) (err error) {
function JavaStringHashCode (line 32) | func JavaStringHashCode(value string) int32 {
function JavaSHA256HashLong (line 44) | func JavaSHA256HashLong(value int64) []byte {
FILE: apis/base/named.go
type Named (line 3) | type Named interface
FILE: apis/base/state.go
type Loads (line 3) | type Loads interface
type Kills (line 7) | type Kills interface
type State (line 11) | type State interface
FILE: apis/base/unique.go
type Unique (line 5) | type Unique interface
FILE: apis/buff/buffers.go
type Buffer (line 9) | type Buffer interface
type BufferPush (line 91) | type BufferPush interface
type BufferPull (line 95) | type BufferPull interface
type BufferCodec (line 99) | type BufferCodec interface
FILE: apis/cmds/command.go
type Command (line 8) | type Command interface
FILE: apis/cmds/commandmanager.go
type CommandManager (line 9) | type CommandManager struct
method Load (line 19) | func (c *CommandManager) Load() {
method Kill (line 23) | func (c *CommandManager) Kill() {
method RegisterCommand (line 27) | func (c *CommandManager) RegisterCommand(command Command) {
method Register (line 33) | func (c *CommandManager) Register(name string, evaluate func(sender en...
method Search (line 42) | func (c *CommandManager) Search(named string) *Command {
function NewCommandManager (line 13) | func NewCommandManager() *CommandManager {
type simpleCommand (line 52) | type simpleCommand struct
method Name (line 58) | func (s *simpleCommand) Name() string {
method Load (line 62) | func (s *simpleCommand) Load() {
method Kill (line 66) | func (s *simpleCommand) Kill() {
method Evaluate (line 70) | func (s *simpleCommand) Evaluate(sender ents.Sender, params []string) {
method Complete (line 74) | func (s *simpleCommand) Complete(sender ents.Sender, params []string, ...
FILE: apis/data/chat/coloring.go
type ChatColor (line 10) | type ChatColor
method String (line 291) | func (code ChatColor) String() string {
method MarshalJSON (line 295) | func (code *ChatColor) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 299) | func (code *ChatColor) UnmarshalJSON(bytes []byte) error {
method On (line 304) | func (code *ChatColor) On(text string) string {
type ColorCode (line 12) | type ColorCode struct
constant DarkRed (line 22) | DarkRed ChatColor = iota
constant Red (line 23) | Red
constant Gold (line 25) | Gold
constant Yellow (line 26) | Yellow
constant DarkGreen (line 28) | DarkGreen
constant Green (line 29) | Green
constant DarkAqua (line 31) | DarkAqua
constant Aqua (line 32) | Aqua
constant DarkBlue (line 34) | DarkBlue
constant Blue (line 35) | Blue
constant DarkPurple (line 37) | DarkPurple
constant Purple (line 38) | Purple
constant White (line 40) | White
constant Black (line 41) | Black
constant DarkGray (line 43) | DarkGray
constant Gray (line 44) | Gray
constant Obfuscated (line 46) | Obfuscated
constant Bold (line 47) | Bold
constant Strikethrough (line 48) | Strikethrough
constant Underline (line 49) | Underline
constant Italic (line 50) | Italic
constant Reset (line 51) | Reset
constant ColorCChar (line 54) | ColorCChar = '§'
constant ColorAChar (line 55) | ColorAChar = '&'
function Translate (line 312) | func Translate(text string) string {
function TranslateConsole (line 338) | func TranslateConsole(text string) string {
FILE: apis/data/location.go
type Location (line 3) | type Location struct
FILE: apis/data/material.go
type Material (line 3) | type Material
constant AIR (line 6) | AIR Material = iota
constant STONE (line 8) | STONE
constant GRANITE (line 10) | GRANITE
constant POLISHED_GRANITE (line 11) | POLISHED_GRANITE
constant ANDESITE (line 13) | ANDESITE
constant POLISHED_ANDESITE (line 14) | POLISHED_ANDESITE
constant DIORITE (line 16) | DIORITE
constant POLISHED_DIORITE (line 17) | POLISHED_DIORITE
FILE: apis/data/msgs/messages.go
type MessagePosition (line 10) | type MessagePosition
constant NormalChat (line 13) | NormalChat MessagePosition = iota
constant SystemChat (line 14) | SystemChat
constant HotBarText (line 15) | HotBarText
type Message (line 18) | type Message struct
method SetColor (line 39) | func (c *Message) SetColor(code chat.ChatColor) *Message {
method SetBold (line 44) | func (c *Message) SetBold(value bool) *Message {
method SetItalic (line 49) | func (c *Message) SetItalic(value bool) *Message {
method SetUnderlined (line 54) | func (c *Message) SetUnderlined(value bool) *Message {
method SetStrikethrough (line 59) | func (c *Message) SetStrikethrough(value bool) *Message {
method SetObfuscated (line 64) | func (c *Message) SetObfuscated(value bool) *Message {
method Add (line 70) | func (c *Message) Add(text string) *Message {
method Reset (line 79) | func (c *Message) Reset() *Message {
method AsJson (line 106) | func (c *Message) AsJson() string {
method AsText (line 121) | func (c *Message) AsText() string {
method asText (line 135) | func (c *Message) asText() string {
method String (line 171) | func (c *Message) String() string {
function New (line 33) | func New(text string) *Message {
FILE: apis/data/position.go
type PositionI (line 3) | type PositionI struct
type PositionF (line 9) | type PositionF struct
FILE: apis/data/rotation.go
type RotationF (line 3) | type RotationF struct
FILE: apis/data/tags/nbt.go
type Typ (line 3) | type Typ
constant TAG_End (line 6) | TAG_End Typ = iota
constant TAG_Byte (line 7) | TAG_Byte
constant TAG_Short (line 8) | TAG_Short
constant TAG_Int (line 9) | TAG_Int
constant TAG_Long (line 10) | TAG_Long
constant TAG_Float (line 11) | TAG_Float
constant TAG_Double (line 12) | TAG_Double
constant TAG_Byte_Array (line 13) | TAG_Byte_Array
constant TAG_String (line 14) | TAG_String
constant TAG_List (line 15) | TAG_List
constant TAG_Compound (line 16) | TAG_Compound
constant TAG_Int_Array (line 17) | TAG_Int_Array
constant TAG_Long_Array (line 18) | TAG_Long_Array
type Nbt (line 21) | type Nbt interface
type NbtEnd (line 28) | type NbtEnd struct
method Type (line 30) | func (n *NbtEnd) Type() Typ {
method Name (line 34) | func (n *NbtEnd) Name() string {
type NbtByt (line 39) | type NbtByt struct
method Type (line 43) | func (n *NbtByt) Type() Typ {
method Name (line 47) | func (n *NbtByt) Name() string {
type NbtI16 (line 52) | type NbtI16 struct
method Type (line 56) | func (n *NbtI16) Type() Typ {
method Name (line 60) | func (n *NbtI16) Name() string {
type NbtI32 (line 73) | type NbtI32 struct
method Type (line 77) | func (n *NbtI32) Type() Typ {
method Name (line 81) | func (n *NbtI32) Name() string {
type NbtI64 (line 94) | type NbtI64 struct
method Type (line 98) | func (n *NbtI64) Type() Typ {
method Name (line 102) | func (n *NbtI64) Name() string {
type NbtF32 (line 115) | type NbtF32 struct
method Type (line 119) | func (n *NbtF32) Type() Typ {
method Name (line 123) | func (n *NbtF32) Name() string {
type NbtF64 (line 136) | type NbtF64 struct
method Type (line 140) | func (n *NbtF64) Type() Typ {
method Name (line 144) | func (n *NbtF64) Name() string {
type NbtArrByt (line 157) | type NbtArrByt struct
method Type (line 161) | func (n *NbtArrByt) Type() Typ {
method Name (line 165) | func (n *NbtArrByt) Name() string {
type NbtTxt (line 178) | type NbtTxt struct
method Type (line 182) | func (n *NbtTxt) Type() Typ {
method Name (line 186) | func (n *NbtTxt) Name() string {
type NbtArrAny (line 199) | type NbtArrAny struct
method Type (line 204) | func (n *NbtArrAny) Type() Typ {
method Name (line 208) | func (n *NbtArrAny) Name() string {
type NbtCompound (line 241) | type NbtCompound struct
method Type (line 246) | func (n *NbtCompound) Type() Typ {
method Name (line 250) | func (n *NbtCompound) Name() string {
method Set (line 254) | func (n *NbtCompound) Set(name string, data Nbt) {
method Get (line 258) | func (n *NbtCompound) Get(name string) (nbt Nbt, con bool) {
type NbtArrI32 (line 264) | type NbtArrI32 struct
method Type (line 268) | func (n *NbtArrI32) Type() Typ {
method Name (line 272) | func (n *NbtArrI32) Name() string {
type NbtArrI64 (line 293) | type NbtArrI64 struct
method Type (line 297) | func (n *NbtArrI64) Type() Typ {
method Name (line 301) | func (n *NbtArrI64) Name() string {
FILE: apis/data/versions.go
type MinecraftVersion (line 3) | type MinecraftVersion
method Protocol (line 21) | func (m MinecraftVersion) Protocol() int {
method String (line 25) | func (m MinecraftVersion) String() string {
constant MC1_12_2 (line 6) | MC1_12_2 MinecraftVersion = iota
constant MC1_13_2 (line 7) | MC1_13_2
constant MC1_14_4 (line 8) | MC1_14_4
constant MC1_15_2 (line 9) | MC1_15_2
FILE: apis/ents/entity.go
type Entity (line 5) | type Entity interface
FILE: apis/ents/living.go
type EntityLiving (line 3) | type EntityLiving interface
FILE: apis/ents/player.go
type Player (line 5) | type Player interface
FILE: apis/ents/sender.go
type Sender (line 7) | type Sender interface
FILE: apis/game/difficulty.go
type Difficulty (line 5) | type Difficulty
method String (line 14) | func (d Difficulty) String() string {
constant PEACEFUL (line 8) | PEACEFUL Difficulty = iota
constant EASY (line 9) | EASY
constant NORMAL (line 10) | NORMAL
constant HARD (line 11) | HARD
function ValueOfDifficulty (line 29) | func ValueOfDifficulty(d Difficulty) byte {
function DifficultyValueOf (line 33) | func DifficultyValueOf(id byte) Difficulty {
FILE: apis/game/dimension.go
type Dimension (line 3) | type Dimension
constant NETHER (line 6) | NETHER = -1
constant OVERWORLD (line 7) | OVERWORLD = 0
constant THE_END (line 8) | THE_END = 1
FILE: apis/game/event/block.go
type BlockEvent (line 7) | type BlockEvent struct
type BlockBreakEvent (line 11) | type BlockBreakEvent struct
FILE: apis/game/event/cancel.go
type Cancellable (line 3) | type Cancellable struct
method GetCancelled (line 7) | func (c *Cancellable) GetCancelled() bool {
method SetCancelled (line 11) | func (c *Cancellable) SetCancelled(cancelled bool) {
FILE: apis/game/event/player.go
type PlayerEvent (line 5) | type PlayerEvent struct
type PlayerJoinEvent (line 9) | type PlayerJoinEvent struct
type PlayerQuitEvent (line 13) | type PlayerQuitEvent struct
FILE: apis/game/gamemode.go
type GameMode (line 3) | type GameMode
method Encoded (line 12) | func (g GameMode) Encoded(hardcore bool) byte {
constant SURVIVAL (line 6) | SURVIVAL GameMode = iota
constant CREATIVE (line 7) | CREATIVE
constant ADVENTURE (line 8) | ADVENTURE
constant SPECTATOR (line 9) | SPECTATOR
FILE: apis/game/level/block.go
type Block (line 3) | type Block interface
FILE: apis/game/level/chunk.go
type Chunk (line 8) | type Chunk interface
FILE: apis/game/level/level.go
type Level (line 5) | type Level interface
FILE: apis/game/level/slice.go
type Slice (line 7) | type Slice interface
FILE: apis/game/level/value.go
constant ChunkW (line 4) | ChunkW = 16
constant ChunkH (line 5) | ChunkH = 256
constant ChunkL (line 6) | ChunkL = 16
constant SliceC (line 8) | SliceC = 16
constant SliceH (line 9) | SliceH = ChunkH / SliceC
constant SliceS (line 11) | SliceS = ChunkW * ChunkL * SliceH
constant BitsPerBlock (line 13) | BitsPerBlock = 14
constant MaxPaletteID (line 14) | MaxPaletteID = (1 << BitsPerBlock) - 1
FILE: apis/game/leveltype.go
type LevelType (line 3) | type LevelType
method String (line 25) | func (l LevelType) String() string {
constant DEFAULT (line 6) | DEFAULT LevelType = iota
constant FLAT (line 7) | FLAT
constant LARGEBIOMES (line 8) | LARGEBIOMES
constant AMPLIFIED (line 9) | AMPLIFIED
constant CUSTOMIZED (line 10) | CUSTOMIZED
constant BUFFET (line 11) | BUFFET
constant DEFAULT11 (line 12) | DEFAULT11
FILE: apis/game/profile.go
type Profile (line 5) | type Profile struct
type ProfileProperty (line 12) | type ProfileProperty struct
FILE: apis/logs/logging.go
type LogLevel (line 15) | type LogLevel
constant Info (line 18) | Info LogLevel = iota
constant Warn (line 19) | Warn
constant Fail (line 20) | Fail
constant Data (line 21) | Data
type Logging (line 27) | type Logging struct
method Name (line 33) | func (log *Logging) Name() string {
method Show (line 37) | func (log *Logging) Show() []LogLevel {
method formatPrint (line 41) | func (log *Logging) formatPrint(level, message string) {
method info (line 45) | func (log *Logging) info(message string) {
method warn (line 49) | func (log *Logging) warn(message string) {
method fail (line 53) | func (log *Logging) fail(message string) {
method data (line 57) | func (log *Logging) data(message string) {
method Info (line 61) | func (log *Logging) Info(message ...interface{}) {
method Warn (line 69) | func (log *Logging) Warn(message ...interface{}) {
method Fail (line 77) | func (log *Logging) Fail(message ...interface{}) {
method Data (line 85) | func (log *Logging) Data(message ...interface{}) {
method InfoF (line 93) | func (log *Logging) InfoF(format string, a ...interface{}) {
method WarnF (line 101) | func (log *Logging) WarnF(format string, a ...interface{}) {
method FailF (line 109) | func (log *Logging) FailF(format string, a ...interface{}) {
method DataF (line 117) | func (log *Logging) DataF(format string, a ...interface{}) {
function NewLogging (line 125) | func NewLogging(name string, show ...LogLevel) *Logging {
function NewLoggingWith (line 129) | func NewLoggingWith(name string, writer io.Writer, show ...LogLevel) *Lo...
function currentTimeAsText (line 133) | func currentTimeAsText() string {
function checkIfLevelShows (line 138) | func checkIfLevelShows(log *Logging, lvl LogLevel) bool {
FILE: apis/math/vector.go
type Vector2F (line 3) | type Vector2F struct
type Vector3F (line 8) | type Vector3F struct
FILE: apis/rand/random.go
function RandomByteArray (line 5) | func RandomByteArray(len int) []byte {
FILE: apis/server.go
type Server (line 17) | type Server interface
function MinecraftServer (line 44) | func MinecraftServer() Server {
function SetMinecraftServer (line 52) | func SetMinecraftServer(server Server) {
FILE: apis/task/tasking.go
type Task (line 11) | type Task struct
method attemptExec (line 191) | func (t *Task) attemptExec() (error error) {
method Cancel (line 195) | func (t *Task) Cancel() {
method Tasker (line 199) | func (t *Task) Tasker() *Tasking {
type Tasking (line 21) | type Tasking struct
method Load (line 48) | func (t *Tasking) Load() {
method Kill (line 55) | func (t *Tasking) Kill() {
method tick (line 79) | func (t *Tasking) tick() {
method tickTasks (line 94) | func (t *Tasking) tickTasks(curr time.Time) {
method tickQueue (line 115) | func (t *Tasking) tickQueue(curr time.Time) {
method nextTaskU (line 134) | func (t *Tasking) nextTaskU() int64 {
method repeats (line 138) | func (t *Tasking) repeats(period int64, function func(task *Task)) {
method delayed (line 145) | func (t *Tasking) delayed(paused int64, function func(task *Task)) {
method Every (line 164) | func (t *Tasking) Every(period int64, function func(task *Task)) {
method After (line 169) | func (t *Tasking) After(paused int64, function func(task *Task)) {
method EveryTime (line 173) | func (t *Tasking) EveryTime(period int64, duration time.Duration, func...
method AfterTime (line 177) | func (t *Tasking) AfterTime(paused int64, duration time.Duration, func...
method newTask (line 181) | func (t *Tasking) newTask(period int64, paused int64, function *func(t...
function NewTasking (line 38) | func NewTasking(mpt int64) *Tasking {
FILE: apis/task/tasking_test.go
function TestTasker_Load (line 8) | func TestTasker_Load(t *testing.T) {
function printCurrentTask (line 21) | func printCurrentTask(_ *Task) {
FILE: apis/urls/urls.go
function GetByte (line 8) | func GetByte(url string) (res []byte, err error) {
function GetText (line 27) | func GetText(url string) (res string, err error) {
FILE: apis/util/formats.go
function FormatTime (line 9) | func FormatTime(durationInSeconds int64) string {
FILE: apis/util/watcher.go
type Watcher (line 9) | type Watcher interface
type Handler (line 25) | type Handler interface
function NewWatcher (line 29) | func NewWatcher() Watcher {
type watcher (line 36) | type watcher struct
method Has (line 41) | func (w *watcher) Has(topic string) bool {
method Pub (line 47) | func (w *watcher) Pub(topic string, args ...interface{}) {
method PubAs (line 65) | func (w *watcher) PubAs(topicValue ...interface{}) {
method PubTo (line 69) | func (w *watcher) PubTo(topicType reflect.Type, args ...interface{}) {
method Sub (line 73) | func (w *watcher) Sub(topic string, function interface{}) Handler {
method SubAs (line 94) | func (w *watcher) SubAs(function interface{}) Handler {
method SubTo (line 109) | func (w *watcher) SubTo(topicType reflect.Type, function interface{}) ...
type handler (line 113) | type handler struct
method UnSub (line 120) | func (h *handler) UnSub() {
FILE: apis/uuid/uuids.go
function NewUUID (line 11) | func NewUUID() UUID {
function TextToUUID (line 20) | func TextToUUID(text string) (data UUID, err error) {
function BitsToUUID (line 24) | func BitsToUUID(msb, lsb int64) (data UUID, err error) {
function UUIDToText (line 34) | func UUIDToText(uuid UUID) (text string, err error) {
function SigBits (line 44) | func SigBits(uuid UUID) (msb, lsb int64) {
FILE: impl/base/combine.go
type PlayerAndConnection (line 5) | type PlayerAndConnection struct
FILE: impl/base/compact.go
type Compacter (line 3) | type Compacter struct
method Set (line 20) | func (c *Compacter) Set(index int, value int) int {
method Get (line 44) | func (c *Compacter) Get(index int) int {
function NewCompacter (line 10) | func NewCompacter(bits, size int) *Compacter {
function iDontKnowWhatThisDoes (line 61) | func iDontKnowWhatThisDoes(var0, var1 int) int {
FILE: impl/base/connect.go
type Connection (line 5) | type Connection interface
FILE: impl/base/network.go
type Network (line 7) | type Network interface
FILE: impl/base/packets.go
type PacketState (line 10) | type PacketState
method String (line 38) | func (state PacketState) String() string {
method Next (line 53) | func (state PacketState) Next() PacketState {
constant SHAKE (line 13) | SHAKE PacketState = iota
constant STATUS (line 14) | STATUS
constant LOGIN (line 15) | LOGIN
constant PLAY (line 16) | PLAY
function ValueOfPacketState (line 19) | func ValueOfPacketState(s PacketState) int {
function PacketStateValueOf (line 23) | func PacketStateValueOf(s int) PacketState {
type Packet (line 68) | type Packet interface
type PacketI (line 73) | type PacketI interface
type PacketO (line 80) | type PacketO interface
type Packets (line 87) | type Packets interface
FILE: impl/conf/config.go
type ServerConfig (line 10) | type ServerConfig struct
type Network (line 14) | type Network struct
FILE: impl/conn/buffers.go
type buffer (line 28) | type buffer struct
method String (line 35) | func (b *buffer) String() string {
method Len (line 49) | func (b *buffer) Len() int32 {
method SAS (line 53) | func (b *buffer) SAS() []int8 {
method UAS (line 57) | func (b *buffer) UAS() []byte {
method InI (line 61) | func (b *buffer) InI() int32 {
method InO (line 65) | func (b *buffer) InO() int32 {
method SkpAll (line 69) | func (b *buffer) SkpAll() {
method SkpLen (line 73) | func (b *buffer) SkpLen(delta int32) {
method PullBit (line 78) | func (b *buffer) PullBit() bool {
method PullByt (line 82) | func (b *buffer) PullByt() byte {
method PullI16 (line 86) | func (b *buffer) PullI16() int16 {
method PullU16 (line 90) | func (b *buffer) PullU16() uint16 {
method PullI32 (line 94) | func (b *buffer) PullI32() int32 {
method PullI64 (line 98) | func (b *buffer) PullI64() int64 {
method PullU64 (line 102) | func (b *buffer) PullU64() uint64 {
method PullF32 (line 106) | func (b *buffer) PullF32() float32 {
method PullF64 (line 110) | func (b *buffer) PullF64() float64 {
method PullVrI (line 114) | func (b *buffer) PullVrI() int32 {
method PullVrL (line 118) | func (b *buffer) PullVrL() int64 {
method PullTxt (line 122) | func (b *buffer) PullTxt() string {
method PullUAS (line 126) | func (b *buffer) PullUAS() []byte {
method PullSAS (line 135) | func (b *buffer) PullSAS() []int8 {
method PullUID (line 139) | func (b *buffer) PullUID() uuid.UUID {
method PullPos (line 145) | func (b *buffer) PullPos() data.PositionI {
method PullNbt (line 159) | func (b *buffer) PullNbt() *tags.NbtCompound {
method PushBit (line 184) | func (b *buffer) PushBit(data bool) {
method PushByt (line 192) | func (b *buffer) PushByt(data byte) {
method PushI16 (line 196) | func (b *buffer) PushI16(data int16) {
method PushI32 (line 202) | func (b *buffer) PushI32(data int32) {
method PushI64 (line 210) | func (b *buffer) PushI64(data int64) {
method PushF32 (line 222) | func (b *buffer) PushF32(data float32) {
method PushF64 (line 226) | func (b *buffer) PushF64(data float64) {
method PushVrI (line 230) | func (b *buffer) PushVrI(data int32) {
method PushVrL (line 247) | func (b *buffer) PushVrL(data int64) {
method PushTxt (line 264) | func (b *buffer) PushTxt(data string) {
method PushUAS (line 268) | func (b *buffer) PushUAS(data []byte, prefixWithLen bool) {
method PushSAS (line 276) | func (b *buffer) PushSAS(data []int8, prefixWithLen bool) {
method PushUID (line 280) | func (b *buffer) PushUID(data uuid.UUID) {
method PushPos (line 287) | func (b *buffer) PushPos(data data.PositionI) {
method PushNbt (line 291) | func (b *buffer) PushNbt(data *tags.NbtCompound) {
method pullNext (line 304) | func (b *buffer) pullNext() byte {
method pullSize (line 321) | func (b *buffer) pullSize(next int) []byte {
method pushNext (line 331) | func (b *buffer) pushNext(bArray ...byte) {
method pullVariable (line 336) | func (b *buffer) pullVariable(max int) int64 {
method pullNbt (line 418) | func (b *buffer) pullNbt(data tags.Nbt) {
method pushNbt (line 493) | func (b *buffer) pushNbt(data tags.Nbt) {
method pullNbtTxt (line 555) | func (b *buffer) pullNbtTxt() string {
method pushNbtTxt (line 562) | func (b *buffer) pushNbtTxt(data string) {
function NewBuffer (line 40) | func NewBuffer() buff.Buffer {
function NewBufferWith (line 44) | func NewBufferWith(bArray []byte) buff.Buffer {
function asSArray (line 356) | func asSArray(bytes []byte) []int8 {
function asUArray (line 366) | func asUArray(bytes []int8) []byte {
FILE: impl/conn/connect.go
type connection (line 16) | type connection struct
method Address (line 36) | func (c *connection) Address() net.Addr {
method GetState (line 40) | func (c *connection) GetState() base.PacketState {
method SetState (line 44) | func (c *connection) SetState(state base.PacketState) {
method Encrypt (line 58) | func (c *connection) Encrypt(data []byte) (output []byte) {
method Decrypt (line 69) | func (c *connection) Decrypt(data []byte) (output []byte) {
method CertifyName (line 80) | func (c *connection) CertifyName() string {
method CertifyData (line 84) | func (c *connection) CertifyData() []byte {
method CertifyUpdate (line 88) | func (c *connection) CertifyUpdate(secret []byte) {
method CertifyValues (line 102) | func (c *connection) CertifyValues(name string) {
method Deflate (line 112) | func (c *connection) Deflate(data []byte) (output []byte) {
method Inflate (line 128) | func (c *connection) Inflate(data []byte) (output []byte) {
method Pull (line 146) | func (c *connection) Pull(data []byte) (len int, err error) {
method Push (line 151) | func (c *connection) Push(data []byte) (len int, err error) {
method Stop (line 156) | func (c *connection) Stop() (err error) {
method SendPacket (line 161) | func (c *connection) SendPacket(packet base.PacketO) {
function NewConnection (line 26) | func NewConnection(conn *net.TCPConn) base.Connection {
type Certify (line 48) | type Certify struct
type Compact (line 107) | type Compact struct
FILE: impl/conn/crypto/cfb8.go
type cfb8 (line 8) | type cfb8 struct
method XORKeyStream (line 51) | func (x *cfb8) XORKeyStream(dst, src []byte) {
function newEncrypt (line 16) | func newEncrypt(block cipher.Block, iv []byte) cipher.Stream {
function newDecrypt (line 24) | func newDecrypt(block cipher.Block, iv []byte) cipher.Stream {
function newCFB8 (line 32) | func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
function NewEncryptAndDecrypt (line 76) | func NewEncryptAndDecrypt(secret []byte) (encrypt cipher.Stream, decrypt...
FILE: impl/conn/network.go
type network (line 15) | type network struct
method Load (line 43) | func (n *network) Load() {
method Kill (line 50) | func (n *network) Kill() {
method startListening (line 54) | func (n *network) startListening() error {
function NewNetwork (line 28) | func NewNetwork(host string, port int, packet base.Packets, report chan ...
function handleConnect (line 86) | func handleConnect(network *network, conn base.Connection) {
function handleReceive (line 148) | func handleReceive(network *network, conn base.Connection, bufI buff.Buf...
FILE: impl/cons/console.go
type Console (line 13) | type Console struct
method Load (line 41) | func (c *Console) Load() {
method Kill (line 65) | func (c *Console) Kill() {
method Name (line 76) | func (c *Console) Name() string {
method SendMessage (line 80) | func (c *Console) SendMessage(message ...interface{}) {
method newLogFile (line 94) | func (c *Console) newLogFile(name string) io.Writer {
function NewConsole (line 25) | func NewConsole(report chan system.Message) *Console {
type logFileWriter (line 90) | type logFileWriter struct
method Write (line 104) | func (l *logFileWriter) Write(p []byte) (n int, err error) {
FILE: impl/data/client/abilities.go
type PlayerAbilities (line 8) | type PlayerAbilities struct
method Push (line 17) | func (p *PlayerAbilities) Push(writer buff.Buffer) {
method Pull (line 28) | func (p *PlayerAbilities) Pull(reader buff.Buffer) {
FILE: impl/data/client/chat.go
type ChatMode (line 3) | type ChatMode
constant Full (line 6) | Full ChatMode = iota
constant Cmds (line 7) | Cmds
constant None (line 8) | None
FILE: impl/data/client/hand.go
type MainHand (line 3) | type MainHand
constant Hand_L (line 6) | Hand_L MainHand = iota
constant Hand_R (line 7) | Hand_R
FILE: impl/data/client/playerinfo.go
type PlayerInfoAction (line 8) | type PlayerInfoAction
constant AddPlayer (line 11) | AddPlayer PlayerInfoAction = iota
constant UpdateGameMode (line 12) | UpdateGameMode
constant UpdateLatency (line 13) | UpdateLatency
constant UpdateDisplayName (line 14) | UpdateDisplayName
constant RemovePlayer (line 15) | RemovePlayer
type PlayerInfo (line 18) | type PlayerInfo interface
type PlayerInfoAddPlayer (line 22) | type PlayerInfoAddPlayer struct
method Push (line 26) | func (p *PlayerInfoAddPlayer) Push(writer buff.Buffer) {
type PlayerInfoUpdateLatency (line 52) | type PlayerInfoUpdateLatency struct
FILE: impl/data/client/position.go
type Relativity (line 8) | type Relativity struct
method Push (line 19) | func (r *Relativity) Push(writer buff.Buffer) {
FILE: impl/data/client/skin.go
type SkinParts (line 10) | type SkinParts struct
method String (line 22) | func (d *SkinParts) String() string {
method Push (line 26) | func (d *SkinParts) Push(writer buff.Buffer) {
method Pull (line 40) | func (d *SkinParts) Pull(reader buff.Buffer) {
FILE: impl/data/client/slot.go
type HotBarSlot (line 3) | type HotBarSlot
constant SLOT_0 (line 6) | SLOT_0 HotBarSlot = iota
constant SLOT_1 (line 7) | SLOT_1
constant SLOT_2 (line 8) | SLOT_2
constant SLOT_3 (line 9) | SLOT_3
constant SLOT_4 (line 10) | SLOT_4
constant SLOT_5 (line 11) | SLOT_5
constant SLOT_6 (line 12) | SLOT_6
constant SLOT_7 (line 13) | SLOT_7
constant SLOT_8 (line 14) | SLOT_8
FILE: impl/data/client/status.go
type StatusAction (line 3) | type StatusAction
constant Respawn (line 6) | Respawn StatusAction = iota
constant Request (line 7) | Request
FILE: impl/data/plugin/message.go
type Message (line 8) | type Message interface
type MessageRegistry (line 17) | type MessageRegistry struct
function createMessageRegistry (line 21) | func createMessageRegistry() MessageRegistry {
function GetMessageForChannel (line 39) | func GetMessageForChannel(channel string) Message {
constant CHANNEL_BRAND (line 49) | CHANNEL_BRAND = "minecraft:brand"
constant CHANNEL_DEBUG_PATHS (line 50) | CHANNEL_DEBUG_PATHS = "minecraft:debug/paths"
constant CHANNEL_DEBUG_NEIGHBORS (line 51) | CHANNEL_DEBUG_NEIGHBORS = "minecraft:debug/neighbors_update"
type Brand (line 56) | type Brand struct
method Chan (line 60) | func (b *Brand) Chan() string {
method Push (line 64) | func (b *Brand) Push(writer buff.Buffer) {
method Pull (line 68) | func (b *Brand) Pull(reader buff.Buffer) {
type DebugPaths (line 72) | type DebugPaths struct
method Chan (line 208) | func (d *DebugPaths) Chan() string {
method Push (line 212) | func (d *DebugPaths) Push(writer buff.Buffer) {
method Pull (line 218) | func (d *DebugPaths) Pull(reader buff.Buffer) {
type PathEntity (line 78) | type PathEntity struct
method Push (line 89) | func (p *PathEntity) Push(writer buff.Buffer) {
method Pull (line 110) | func (p *PathEntity) Pull(reader buff.Buffer) {
type PathPoint (line 149) | type PathPoint struct
method Push (line 162) | func (p *PathPoint) Push(writer buff.Buffer) {
method Pull (line 174) | func (p *PathPoint) Pull(reader buff.Buffer) {
type NodeType (line 186) | type NodeType
constant BLOCKED (line 189) | BLOCKED NodeType = iota
constant OPEN (line 190) | OPEN
constant WALKABLE (line 191) | WALKABLE
constant TRAPDOOR (line 192) | TRAPDOOR
constant FENCE (line 193) | FENCE
constant LAVA (line 194) | LAVA
constant WATER (line 195) | WATER
constant RAIL (line 196) | RAIL
constant DANGER_FIRE (line 197) | DANGER_FIRE
constant DAMAGE_FIRE (line 198) | DAMAGE_FIRE
constant DANGER_CACTUS (line 199) | DANGER_CACTUS
constant DAMAGE_CACTUS (line 200) | DAMAGE_CACTUS
constant DANGER_OTHER (line 201) | DANGER_OTHER
constant DAMAGE_OTHER (line 202) | DAMAGE_OTHER
constant DOOR_OPEN (line 203) | DOOR_OPEN
constant DOOR_WOOD_CLOSED (line 204) | DOOR_WOOD_CLOSED
constant DOOR_IRON_CLOSED (line 205) | DOOR_IRON_CLOSED
type DebugNeighbors (line 228) | type DebugNeighbors struct
method Chan (line 233) | func (d *DebugNeighbors) Chan() string {
method Push (line 237) | func (d *DebugNeighbors) Push(writer buff.Buffer) {
method Pull (line 242) | func (d *DebugNeighbors) Pull(reader buff.Buffer) {
FILE: impl/data/status/response.go
constant SxtannaName (line 9) | SxtannaName = "Sxtanna"
constant SxtannaUUID (line 10) | SxtannaUUID = "41d1fed5-aa44-432c-ab1b-2810001f3270"
constant ServerMotd (line 12) | ServerMotd = " &bA GoLang Server"
constant ServerIcon (line 13) | ServerIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIA...
type Response (line 16) | type Response struct
type Version (line 23) | type Version struct
type Players (line 28) | type Players struct
type SamplePlayer (line 34) | type SamplePlayer struct
type Message (line 39) | type Message struct
function DefaultResponse (line 43) | func DefaultResponse() Response {
FILE: impl/data/system/command.go
type Command (line 3) | type Command
type Message (line 5) | type Message struct
constant STOP (line 12) | STOP Command = iota
constant FAIL (line 13) | FAIL
function Make (line 16) | func Make(command Command, message interface{}) Message {
FILE: impl/data/values/constants.go
constant TPS (line 11) | TPS = 20
constant MPT (line 13) | MPT = 1_000 / TPS
FILE: impl/game/auth/authenticate.go
constant url (line 12) | url = "https://sessionserver.mojang.com/session/minecraft/hasJoined"
type Auth (line 14) | type Auth struct
type Prop (line 20) | type Prop struct
function RunAuthGet (line 26) | func RunAuthGet(secret []byte, name string, callback func(auth *Auth, er...
function execute (line 30) | func execute(url string, callback func(auth *Auth, err error)) {
function generateAuthURL (line 48) | func generateAuthURL(name, hash string) string {
function generateAuthSHA (line 52) | func generateAuthSHA(secret []byte) string {
FILE: impl/game/auth/cryptography.go
function NewCrypt (line 15) | func NewCrypt() (secret []byte, public []byte) {
function Encrypt (line 31) | func Encrypt(data []byte) ([]byte, error) {
function Decrypt (line 35) | func Decrypt(data []byte) ([]byte, error) {
function generate (line 39) | func generate() (secretKey *rsa.PrivateKey, publicKey *rsa.PublicKey) {
FILE: impl/game/ents/entity.go
type entity (line 7) | type entity struct
method Name (line 21) | func (e *entity) Name() string {
method UUID (line 25) | func (e *entity) UUID() uuid.UUID {
method SetName (line 29) | func (e *entity) SetName(name string) {
method SetUUID (line 33) | func (e *entity) SetUUID(uuid uuid.UUID) {
method SendMessage (line 37) | func (e *entity) SendMessage(message ...interface{}) {
method EntityUUID (line 41) | func (e *entity) EntityUUID() int64 {
function newEntity (line 14) | func newEntity() entity {
FILE: impl/game/ents/living.go
type entityLiving (line 3) | type entityLiving struct
method GetHealth (line 13) | func (e *entityLiving) GetHealth() float64 {
method SetHealth (line 17) | func (e *entityLiving) SetHealth(health float64) {
function newEntityLiving (line 9) | func newEntityLiving() entityLiving {
FILE: impl/game/ents/player.go
type player (line 14) | type player struct
method SendMessage (line 40) | func (p *player) SendMessage(message ...interface{}) {
method GetGameMode (line 49) | func (p *player) GetGameMode() game.GameMode {
method SetGameMode (line 53) | func (p *player) SetGameMode(mode game.GameMode) {
method GetIsOnline (line 57) | func (p *player) GetIsOnline() bool {
method SetIsOnline (line 61) | func (p *player) SetIsOnline(state bool) {
method GetProfile (line 65) | func (p *player) GetProfile() *game.Profile {
method SetConn (line 69) | func (p *player) SetConn(conn impl_base.Connection) {
function NewPlayer (line 26) | func NewPlayer(prof *game.Profile, conn impl_base.Connection) ents.Player {
FILE: impl/game/event/events.go
type PlayerConnJoinEvent (line 8) | type PlayerConnJoinEvent struct
type PlayerConnQuitEvent (line 12) | type PlayerConnQuitEvent struct
type PlayerPluginMessagePullEvent (line 16) | type PlayerPluginMessagePullEvent struct
FILE: impl/game/level/block.go
type block (line 7) | type block struct
method X (line 16) | func (b *block) X() int {
method Y (line 20) | func (b *block) Y() int {
method Z (line 24) | func (b *block) Z() int {
method Chunk (line 28) | func (b *block) Chunk() apis_level.Chunk {
method Level (line 32) | func (b *block) Level() apis_level.Level {
method GetBlockType (line 36) | func (b *block) GetBlockType() (value int) {
method SetBlockType (line 41) | func (b *block) SetBlockType(value int) {
FILE: impl/game/level/chunk.go
type chunk (line 10) | type chunk struct
method ChunkX (line 44) | func (c *chunk) ChunkX() int {
method ChunkZ (line 48) | func (c *chunk) ChunkZ() int {
method Level (line 52) | func (c *chunk) Level() apis_level.Level {
method Slices (line 56) | func (c *chunk) Slices() []apis_level.Slice {
method GetSlice (line 66) | func (c *chunk) GetSlice(y int) apis_level.Slice {
method GetBlock (line 82) | func (c *chunk) GetBlock(x, y, z int) apis_level.Block {
method Push (line 102) | func (c *chunk) Push(writer buff.Buffer) {
method HeightMapNbtCompound (line 119) | func (c *chunk) HeightMapNbtCompound() *tags.NbtCompound {
function newChunk (line 21) | func newChunk(level *level, x, z int) *chunk {
type heightMapType (line 128) | type heightMapType
constant WorldSurfaceWg (line 131) | WorldSurfaceWg heightMapType = "WORLD_SURFACE_WG"
constant WorldSurface (line 132) | WorldSurface heightMapType = "WORLD_SURFACE"
constant OceanFloorWg (line 133) | OceanFloorWg heightMapType = "OCEAN_FLOOR_WG"
constant OceanFloor (line 134) | OceanFloor heightMapType = "OCEAN_FLOOR"
constant MotionBlocking (line 135) | MotionBlocking heightMapType = "MOTION_BLOCKING"
constant MotionBlockingNoLeaves (line 136) | MotionBlockingNoLeaves heightMapType = "MOTION_BLOCKING_NO_LEAVES"
type heightMap (line 148) | type heightMap struct
FILE: impl/game/level/level.go
type level (line 8) | type level struct
method Name (line 26) | func (l *level) Name() string {
method UUID (line 30) | func (l *level) UUID() uuid.UUID {
method Chunks (line 34) | func (l *level) Chunks() []apis_level.Chunk {
method GetChunk (line 46) | func (l *level) GetChunk(x, z int) apis_level.Chunk {
method GetChunkIfLoaded (line 50) | func (l *level) GetChunkIfLoaded(x, z int) apis_level.Chunk {
method GetBlock (line 54) | func (l *level) GetBlock(x, y, z int) apis_level.Block {
method getChunk (line 64) | func (l *level) getChunk(x, z int, generate bool) apis_level.Chunk {
function NewLevel (line 15) | func NewLevel(name string) apis_level.Level {
function GenSuperFlat (line 83) | func GenSuperFlat(level apis_level.Level, size int) {
FILE: impl/game/level/slice.go
type slice (line 9) | type slice struct
method Index (line 29) | func (s *slice) Index() int {
method Chunk (line 33) | func (s *slice) Chunk() apis_level.Chunk {
method Level (line 37) | func (s *slice) Level() apis_level.Level {
method GetBlock (line 41) | func (s *slice) GetBlock(x, y, z int) apis_level.Block {
method Push (line 61) | func (s *slice) Push(writer buff.Buffer) {
method sliceBlockGet (line 75) | func (s *slice) sliceBlockGet(index int) int {
method sliceBlockSet (line 79) | func (s *slice) sliceBlockSet(index int, value int) int {
method fill (line 83) | func (s *slice) fill(value int) {
method layer (line 89) | func (s *slice) layer(index int, value int) {
function newSlice (line 17) | func newSlice(chunk *chunk, index int) *slice {
FILE: impl/game/level/value.go
function chunkIndex (line 3) | func chunkIndex(x, z int) int64 {
function sliceIndex (line 7) | func sliceIndex(x, y, z int) int {
function blockYToSliceY (line 11) | func blockYToSliceY(blockY int) (sliceY int) {
function blockXZToChunkXZ (line 16) | func blockXZToChunkXZ(blockX, blockZ int) (chunkX, chunkZ int) {
function blockLevelToSlice (line 22) | func blockLevelToSlice(levelBlockX, levelBlockY, levelBlockZ int) (slice...
FILE: impl/game/mode/mode_state0.go
function HandleState0 (line 13) | func HandleState0(watcher util.Watcher) {
FILE: impl/game/mode/mode_state1.go
function HandleState1 (line 15) | func HandleState1(watcher util.Watcher) {
FILE: impl/game/mode/mode_state2.go
function HandleState2 (line 23) | func HandleState2(watcher util.Watcher, join chan base.PlayerAndConnecti...
FILE: impl/game/mode/mode_state3.go
function HandleState3 (line 27) | func HandleState3(watcher util.Watcher, logger *logs.Logging, tasking *t...
FILE: impl/mask/masking.go
type Masking (line 3) | type Masking struct
method Has (line 5) | func (m *Masking) Has(mask, field byte) bool {
method Set (line 9) | func (m *Masking) Set(mask *byte, field byte, when bool) {
FILE: impl/mask/masking_test.go
type Data (line 8) | type Data struct
function TestMasking (line 15) | func TestMasking(t *testing.T) {
FILE: impl/prot/client/to_client_state1.go
type PacketOResponse (line 13) | type PacketOResponse struct
method UUID (line 17) | func (p *PacketOResponse) UUID() int32 {
method Push (line 21) | func (p *PacketOResponse) Push(writer buff.Buffer, conn base.Connectio...
type PacketOPong (line 29) | type PacketOPong struct
method UUID (line 33) | func (p *PacketOPong) UUID() int32 {
method Push (line 37) | func (p *PacketOPong) Push(writer buff.Buffer, conn base.Connection) {
FILE: impl/prot/client/to_client_state2.go
type PacketODisconnect (line 11) | type PacketODisconnect struct
method UUID (line 15) | func (p *PacketODisconnect) UUID() int32 {
method Push (line 19) | func (p *PacketODisconnect) Push(writer buff.Buffer, conn base.Connect...
type PacketOEncryptionRequest (line 25) | type PacketOEncryptionRequest struct
method UUID (line 31) | func (p *PacketOEncryptionRequest) UUID() int32 {
method Push (line 35) | func (p *PacketOEncryptionRequest) Push(writer buff.Buffer, conn base....
type PacketOLoginSuccess (line 41) | type PacketOLoginSuccess struct
method UUID (line 46) | func (p *PacketOLoginSuccess) UUID() int32 {
method Push (line 50) | func (p *PacketOLoginSuccess) Push(writer buff.Buffer, conn base.Conne...
type PacketOSetCompression (line 55) | type PacketOSetCompression struct
method UUID (line 59) | func (p *PacketOSetCompression) UUID() int32 {
method Push (line 63) | func (p *PacketOSetCompression) Push(writer buff.Buffer, conn base.Con...
type PacketOLoginPluginRequest (line 67) | type PacketOLoginPluginRequest struct
method UUID (line 73) | func (p *PacketOLoginPluginRequest) UUID() int32 {
method Push (line 77) | func (p *PacketOLoginPluginRequest) Push(writer buff.Buffer, conn base...
FILE: impl/prot/client/to_client_state3.go
type PacketOChatMessage (line 17) | type PacketOChatMessage struct
method UUID (line 22) | func (p *PacketOChatMessage) UUID() int32 {
method Push (line 26) | func (p *PacketOChatMessage) Push(writer buff.Buffer, conn base.Connec...
type PacketOJoinGame (line 37) | type PacketOJoinGame struct
method UUID (line 50) | func (p *PacketOJoinGame) UUID() int32 {
method Push (line 54) | func (p *PacketOJoinGame) Push(writer buff.Buffer, conn base.Connectio...
type PacketOPluginMessage (line 66) | type PacketOPluginMessage struct
method UUID (line 70) | func (p *PacketOPluginMessage) UUID() int32 {
method Push (line 74) | func (p *PacketOPluginMessage) Push(writer buff.Buffer, conn base.Conn...
type PacketOPlayerLocation (line 79) | type PacketOPlayerLocation struct
method UUID (line 86) | func (p *PacketOPlayerLocation) UUID() int32 {
method Push (line 90) | func (p *PacketOPlayerLocation) Push(writer buff.Buffer, conn base.Con...
type PacketOKeepAlive (line 103) | type PacketOKeepAlive struct
method UUID (line 107) | func (p *PacketOKeepAlive) UUID() int32 {
method Push (line 111) | func (p *PacketOKeepAlive) Push(writer buff.Buffer, conn base.Connecti...
type PacketOServerDifficulty (line 115) | type PacketOServerDifficulty struct
method UUID (line 120) | func (p *PacketOServerDifficulty) UUID() int32 {
method Push (line 124) | func (p *PacketOServerDifficulty) Push(writer buff.Buffer, conn base.C...
type PacketOPlayerAbilities (line 129) | type PacketOPlayerAbilities struct
method UUID (line 135) | func (p *PacketOPlayerAbilities) UUID() int32 {
method Push (line 139) | func (p *PacketOPlayerAbilities) Push(writer buff.Buffer, conn base.Co...
type PacketOHeldItemChange (line 146) | type PacketOHeldItemChange struct
method UUID (line 150) | func (p *PacketOHeldItemChange) UUID() int32 {
method Push (line 154) | func (p *PacketOHeldItemChange) Push(writer buff.Buffer, conn base.Con...
type PacketODeclareRecipes (line 158) | type PacketODeclareRecipes struct
method UUID (line 163) | func (p *PacketODeclareRecipes) UUID() int32 {
method Push (line 167) | func (p *PacketODeclareRecipes) Push(writer buff.Buffer, conn base.Con...
type PacketOChunkData (line 172) | type PacketOChunkData struct
method UUID (line 176) | func (p *PacketOChunkData) UUID() int32 {
method Push (line 180) | func (p *PacketOChunkData) Push(writer buff.Buffer, conn base.Connecti...
type PacketOPlayerInfo (line 212) | type PacketOPlayerInfo struct
method UUID (line 217) | func (p *PacketOPlayerInfo) UUID() int32 {
method Push (line 221) | func (p *PacketOPlayerInfo) Push(writer buff.Buffer, conn base.Connect...
type PacketOEntityMetadata (line 230) | type PacketOEntityMetadata struct
method UUID (line 234) | func (p *PacketOEntityMetadata) UUID() int32 {
method Push (line 238) | func (p *PacketOEntityMetadata) Push(writer buff.Buffer, conn base.Con...
FILE: impl/prot/packets.go
type packets (line 12) | type packets struct
method GetPacketI (line 38) | func (p *packets) GetPacketI(uuid int32, state base.PacketState) base....
function NewPackets (line 22) | func NewPackets(tasking *task.Tasking, join chan base.PlayerAndConnectio...
function createPacketI (line 47) | func createPacketI() map[base.PacketState]map[int32]func() base.PacketI {
FILE: impl/prot/server/to_server_state0.go
type PacketIHandshake (line 10) | type PacketIHandshake struct
method UUID (line 19) | func (p *PacketIHandshake) UUID() int32 {
method Pull (line 23) | func (p *PacketIHandshake) Pull(reader buff.Buffer, conn base.Connecti...
FILE: impl/prot/server/to_server_state1.go
type PacketIRequest (line 10) | type PacketIRequest struct
method UUID (line 13) | func (p *PacketIRequest) UUID() int32 {
method Pull (line 17) | func (p *PacketIRequest) Pull(reader buff.Buffer, conn base.Connection) {
type PacketIPing (line 21) | type PacketIPing struct
method UUID (line 25) | func (p *PacketIPing) UUID() int32 {
method Pull (line 29) | func (p *PacketIPing) Pull(reader buff.Buffer, conn base.Connection) {
FILE: impl/prot/server/to_server_state2.go
type PacketILoginStart (line 10) | type PacketILoginStart struct
method UUID (line 14) | func (p *PacketILoginStart) UUID() int32 {
method Pull (line 18) | func (p *PacketILoginStart) Pull(reader buff.Buffer, conn base.Connect...
type PacketIEncryptionResponse (line 22) | type PacketIEncryptionResponse struct
method UUID (line 27) | func (p *PacketIEncryptionResponse) UUID() int32 {
method Pull (line 31) | func (p *PacketIEncryptionResponse) Pull(reader buff.Buffer, conn base...
type PacketILoginPluginResponse (line 36) | type PacketILoginPluginResponse struct
method UUID (line 42) | func (p *PacketILoginPluginResponse) UUID() int32 {
method Pull (line 46) | func (p *PacketILoginPluginResponse) Pull(reader buff.Buffer, conn bas...
FILE: impl/prot/server/to_server_state3.go
type PacketIKeepAlive (line 12) | type PacketIKeepAlive struct
method UUID (line 16) | func (p *PacketIKeepAlive) UUID() int32 {
method Pull (line 20) | func (p *PacketIKeepAlive) Pull(reader buff.Buffer, conn base.Connecti...
type PacketIChatMessage (line 24) | type PacketIChatMessage struct
method UUID (line 28) | func (p *PacketIChatMessage) UUID() int32 {
method Pull (line 32) | func (p *PacketIChatMessage) Pull(reader buff.Buffer, conn base.Connec...
type PacketITeleportConfirm (line 36) | type PacketITeleportConfirm struct
method UUID (line 40) | func (p *PacketITeleportConfirm) UUID() int32 {
method Pull (line 44) | func (p *PacketITeleportConfirm) Pull(reader buff.Buffer, conn base.Co...
type PacketIQueryBlockNBT (line 48) | type PacketIQueryBlockNBT struct
method UUID (line 53) | func (p *PacketIQueryBlockNBT) UUID() int32 {
method Pull (line 57) | func (p *PacketIQueryBlockNBT) Pull(reader buff.Buffer, conn base.Conn...
type PacketISetDifficulty (line 62) | type PacketISetDifficulty struct
method UUID (line 66) | func (p *PacketISetDifficulty) UUID() int32 {
method Pull (line 70) | func (p *PacketISetDifficulty) Pull(reader buff.Buffer, conn base.Conn...
type PacketIPluginMessage (line 74) | type PacketIPluginMessage struct
method UUID (line 78) | func (p *PacketIPluginMessage) UUID() int32 {
method Pull (line 82) | func (p *PacketIPluginMessage) Pull(reader buff.Buffer, conn base.Conn...
type PacketIClientStatus (line 95) | type PacketIClientStatus struct
method UUID (line 99) | func (p *PacketIClientStatus) UUID() int32 {
method Pull (line 103) | func (p *PacketIClientStatus) Pull(reader buff.Buffer, conn base.Conne...
type PacketIClientSettings (line 107) | type PacketIClientSettings struct
method UUID (line 116) | func (p *PacketIClientSettings) UUID() int32 {
method Pull (line 120) | func (p *PacketIClientSettings) Pull(reader buff.Buffer, conn base.Con...
type PacketIPlayerAbilities (line 133) | type PacketIPlayerAbilities struct
method UUID (line 139) | func (p *PacketIPlayerAbilities) UUID() int32 {
method Pull (line 143) | func (p *PacketIPlayerAbilities) Pull(reader buff.Buffer, conn base.Co...
type PacketIPlayerPosition (line 153) | type PacketIPlayerPosition struct
method UUID (line 158) | func (p *PacketIPlayerPosition) UUID() int32 {
method Pull (line 162) | func (p *PacketIPlayerPosition) Pull(reader buff.Buffer, conn base.Con...
type PacketIPlayerLocation (line 172) | type PacketIPlayerLocation struct
method UUID (line 177) | func (p *PacketIPlayerLocation) UUID() int32 {
method Pull (line 181) | func (p *PacketIPlayerLocation) Pull(reader buff.Buffer, conn base.Con...
type PacketIPlayerRotation (line 197) | type PacketIPlayerRotation struct
method UUID (line 202) | func (p *PacketIPlayerRotation) UUID() int32 {
method Pull (line 206) | func (p *PacketIPlayerRotation) Pull(reader buff.Buffer, conn base.Con...
FILE: impl/server.go
type server (line 33) | type server struct
method Load (line 92) | func (s *server) Load() {
method Kill (line 101) | func (s *server) Kill() {
method Logging (line 116) | func (s *server) Logging() *logs.Logging {
method Command (line 120) | func (s *server) Command() *cmds.CommandManager {
method Tasking (line 124) | func (s *server) Tasking() *task.Tasking {
method Watcher (line 128) | func (s *server) Watcher() util.Watcher {
method Players (line 132) | func (s *server) Players() []ents.Player {
method ConnByUUID (line 142) | func (s *server) ConnByUUID(uuid uuid.UUID) impl_base.Connection {
method PlayerByUUID (line 146) | func (s *server) PlayerByUUID(uuid uuid.UUID) ents.Player {
method PlayerByConn (line 150) | func (s *server) PlayerByConn(conn impl_base.Connection) ents.Player {
method ServerVersion (line 159) | func (s *server) ServerVersion() string {
method Broadcast (line 163) | func (s *server) Broadcast(message string) {
method broadcastCommand (line 172) | func (s *server) broadcastCommand(sender ents.Sender, params []string) {
method stopServerCommand (line 180) | func (s *server) stopServerCommand(sender ents.Sender, params []string) {
method versionCommand (line 219) | func (s *server) versionCommand(sender ents.Sender, params []string) {
method loadServer (line 224) | func (s *server) loadServer() {
method readInputs (line 270) | func (s *server) readInputs() {
method wait (line 305) | func (s *server) wait() {
function NewServer (line 51) | func NewServer(conf conf.ServerConfig) apis.Server {
type playerAssociation (line 324) | type playerAssociation struct
method addData (line 331) | func (p *playerAssociation) addData(data impl_base.PlayerAndConnection) {
method delData (line 338) | func (p *playerAssociation) delData(data impl_base.PlayerAndConnection) {
method playerByUUID (line 351) | func (p *playerAssociation) playerByUUID(uuid uuid.UUID) ents.Player {
method playerByConn (line 355) | func (p *playerAssociation) playerByConn(conn impl_base.Connection) en...
FILE: main.go
function main (line 12) | func main() {
function mergeWithFlags (line 19) | func mergeWithFlags(c conf.ServerConfig) conf.ServerConfig {
Condensed preview — 99 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (173K chars).
[
{
"path": ".github/dependabot.yml",
"chars": 173,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"gomod\"\n directory: \"/\" # Location of package manifests\n schedule:\n "
},
{
"path": ".gitignore",
"chars": 315,
"preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2020 GoLangMc\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
},
{
"path": "README.md",
"chars": 608,
"preview": "\n<p align=\"center\">\n\n <a href=\"https://github.com/GoLangMc/minecraft-server\">\n <img src=\"https://avatars3.githubuser"
},
{
"path": "apis/base/funcs.go",
"chars": 752,
"preview": "package base\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc ConvertToString(data ...interface{}"
},
{
"path": "apis/base/named.go",
"chars": 54,
"preview": "package base\n\ntype Named interface {\n\tName() string\n}\n"
},
{
"path": "apis/base/state.go",
"chars": 121,
"preview": "package base\n\ntype Loads interface {\n\tLoad()\n}\n\ntype Kills interface {\n\tKill()\n}\n\ntype State interface {\n\tLoads\n\tKills\n}"
},
{
"path": "apis/base/unique.go",
"chars": 115,
"preview": "package base\n\nimport \"github.com/golangmc/minecraft-server/apis/uuid\"\n\ntype Unique interface {\n\tUUID() uuid.UUID\n}\n"
},
{
"path": "apis/buff/buffers.go",
"chars": 1227,
"preview": "package buff\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/data\"\n\t\"github.com/golangmc/minecraft-server/apis/dat"
},
{
"path": "apis/cmds/command.go",
"chars": 291,
"preview": "package cmds\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n\t\"github.com/golangmc/minecraft-server/apis/ent"
},
{
"path": "apis/cmds/commandmanager.go",
"chars": 1281,
"preview": "package cmds\n\nimport (\n\t\"strings\"\n\n\t\"github.com/golangmc/minecraft-server/apis/ents\"\n)\n\ntype CommandManager struct {\n\tco"
},
{
"path": "apis/data/chat/coloring.go",
"chars": 5803,
"preview": "package chat\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/fatih/color\"\n)\n\ntype ChatColor int\n\ntype ColorCode struct {\n\tChat"
},
{
"path": "apis/data/location.go",
"chars": 61,
"preview": "package data\n\ntype Location struct {\n\tPositionF\n\tRotationF\n}\n"
},
{
"path": "apis/data/material.go",
"chars": 160,
"preview": "package data\n\ntype Material int32\n\nconst (\n\tAIR Material = iota\n\n\tSTONE\n\n\tGRANITE\n\tPOLISHED_GRANITE\n\n\tANDESITE\n\tPOLISHED"
},
{
"path": "apis/data/msgs/messages.go",
"chars": 3179,
"preview": "package msgs\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/golangmc/minecraft-server/apis/data/chat\"\n)\n\ntype Messa"
},
{
"path": "apis/data/position.go",
"chars": 127,
"preview": "package data\n\ntype PositionI struct {\n\tX int64\n\tY int64\n\tZ int64\n}\n\ntype PositionF struct {\n\tX float64\n\tY float64\n\tZ flo"
},
{
"path": "apis/data/rotation.go",
"chars": 90,
"preview": "package data\n\ntype RotationF struct {\n\tAxisX float32 // 'yaw'\n\tAxisY float32 // 'pitch'\n}\n"
},
{
"path": "apis/data/tags/nbt.go",
"chars": 4443,
"preview": "package tags\n\ntype Typ byte\n\nconst (\n\tTAG_End Typ = iota\n\tTAG_Byte\n\tTAG_Short\n\tTAG_Int\n\tTAG_Long\n\tTAG_Float\n\tTAG_Double\n"
},
{
"path": "apis/data/versions.go",
"chars": 562,
"preview": "package data\n\ntype MinecraftVersion int\n\nconst (\n\tMC1_12_2 MinecraftVersion = iota\n\tMC1_13_2\n\tMC1_14_4\n\tMC1_15_2\n)\n\nvar "
},
{
"path": "apis/ents/entity.go",
"chars": 139,
"preview": "package ents\n\nimport \"github.com/golangmc/minecraft-server/apis/base\"\n\ntype Entity interface {\n\tSender\n\tbase.Unique\n\n\tEn"
},
{
"path": "apis/ents/living.go",
"chars": 103,
"preview": "package ents\n\ntype EntityLiving interface {\n\tEntity\n\n\tGetHealth() float64\n\tSetHealth(health float64)\n}\n"
},
{
"path": "apis/ents/player.go",
"chars": 249,
"preview": "package ents\n\nimport \"github.com/golangmc/minecraft-server/apis/game\"\n\ntype Player interface {\n\tEntityLiving\n\n\tGetGameMo"
},
{
"path": "apis/ents/sender.go",
"chars": 152,
"preview": "package ents\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n)\n\ntype Sender interface {\n\tbase.Named\n\n\tSendMe"
},
{
"path": "apis/game/difficulty.go",
"chars": 640,
"preview": "package game\n\nimport \"fmt\"\n\ntype Difficulty byte\n\nconst (\n\tPEACEFUL Difficulty = iota\n\tEASY\n\tNORMAL\n\tHARD\n)\n\nfunc (d Dif"
},
{
"path": "apis/game/dimension.go",
"chars": 90,
"preview": "package game\n\ntype Dimension int\n\nconst (\n\tNETHER = -1\n\tOVERWORLD = 0\n\tTHE_END = 1\n)\n"
},
{
"path": "apis/game/event/block.go",
"chars": 194,
"preview": "package event\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/game/level\"\n)\n\ntype BlockEvent struct {\n\tlevel.Block"
},
{
"path": "apis/game/event/cancel.go",
"chars": 207,
"preview": "package event\n\ntype Cancellable struct {\n\tcancelled bool\n}\n\nfunc (c *Cancellable) GetCancelled() bool {\n\treturn c.cancel"
},
{
"path": "apis/game/event/player.go",
"chars": 205,
"preview": "package event\n\nimport \"github.com/golangmc/minecraft-server/apis/ents\"\n\ntype PlayerEvent struct {\n\tents.Player\n}\n\ntype P"
},
{
"path": "apis/game/gamemode.go",
"chars": 222,
"preview": "package game\n\ntype GameMode int\n\nconst (\n\tSURVIVAL GameMode = iota\n\tCREATIVE\n\tADVENTURE\n\tSPECTATOR\n)\n\nfunc (g GameMode) "
},
{
"path": "apis/game/level/block.go",
"chars": 144,
"preview": "package level\n\ntype Block interface {\n\tX() int\n\tY() int\n\tZ() int\n\n\tChunk() Chunk\n\tLevel() Level\n\n\tGetBlockType() int\n\tSe"
},
{
"path": "apis/game/level/chunk.go",
"chars": 413,
"preview": "package level\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/da"
},
{
"path": "apis/game/level/level.go",
"chars": 233,
"preview": "package level\n\nimport \"github.com/golangmc/minecraft-server/apis/base\"\n\ntype Level interface {\n\tbase.Named\n\tbase.Unique\n"
},
{
"path": "apis/game/level/slice.go",
"chars": 242,
"preview": "package level\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n)\n\ntype Slice interface {\n\tbuff.BufferPush\n\n\tI"
},
{
"path": "apis/game/level/value.go",
"chars": 201,
"preview": "package level\n\nconst (\n\tChunkW = 16\n\tChunkH = 256\n\tChunkL = 16\n\n\tSliceC = 16\n\tSliceH = ChunkH / SliceC\n\n\tSliceS = ChunkW"
},
{
"path": "apis/game/leveltype.go",
"chars": 419,
"preview": "package game\n\ntype LevelType int\n\nconst (\n\tDEFAULT LevelType = iota\n\tFLAT\n\tLARGEBIOMES\n\tAMPLIFIED\n\tCUSTOMIZED\n\tBUFFET\n\tD"
},
{
"path": "apis/game/profile.go",
"chars": 244,
"preview": "package game\n\nimport \"github.com/golangmc/minecraft-server/apis/uuid\"\n\ntype Profile struct {\n\tUUID uuid.UUID\n\tName strin"
},
{
"path": "apis/logs/logging.go",
"chars": 2880,
"preview": "package logs\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/fatih/color\"\n\n\t\"github.com/golangmc/minecraft-server/api"
},
{
"path": "apis/math/vector.go",
"chars": 108,
"preview": "package math\n\ntype Vector2F struct {\n\tX float64\n\tZ float64\n}\n\ntype Vector3F struct {\n\tVector2F\n\tY float64\n}\n"
},
{
"path": "apis/rand/random.go",
"chars": 143,
"preview": "package rand\n\nimport \"crypto/rand\"\n\nfunc RandomByteArray(len int) []byte {\n\tarray := make([]byte, 4)\n\t_, _ = rand.Read(a"
},
{
"path": "apis/server.go",
"chars": 1083,
"preview": "package apis\n\nimport (\n\t\"sync\"\n\n\t\"github.com/golangmc/minecraft-server/apis/cmds\"\n\t\"github.com/golangmc/minecraft-server"
},
{
"path": "apis/task/tasking.go",
"chars": 3579,
"preview": "package task\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n)\n\ntype Task str"
},
{
"path": "apis/task/tasking_test.go",
"chars": 374,
"preview": "package task\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestTasker_Load(t *testing.T) {\n\n\ttasker := NewTasking(1_000 / 20)\n\ttas"
},
{
"path": "apis/urls/urls.go",
"chars": 429,
"preview": "package urls\n\nimport (\n\t\"io/ioutil\"\n\t\"net/http\"\n)\n\nfunc GetByte(url string) (res []byte, err error) {\n\t// get\n\tout, err "
},
{
"path": "apis/util/formats.go",
"chars": 193,
"preview": "package util\n\nimport (\n\t\"time\"\n\n\t\"github.com/hako/durafmt\"\n)\n\nfunc FormatTime(durationInSeconds int64) string {\n\treturn "
},
{
"path": "apis/util/watcher.go",
"chars": 2785,
"preview": "package util\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"sync\"\n)\n\ntype Watcher interface {\n\tHas(topic string) bool\n\n\tPub(topic string,"
},
{
"path": "apis/uuid/uuids.go",
"chars": 934,
"preview": "package uuid\n\nimport (\n\t\"encoding/binary\"\n\n\t\"github.com/satori/go.uuid\"\n)\n\ntype UUID = uuid.UUID\n\nfunc NewUUID() UUID {\n"
},
{
"path": "go.mod",
"chars": 447,
"preview": "module github.com/golangmc/minecraft-server\n\ngo 1.13\n\nrequire (\n\tgithub.com/fatih/color v1.9.0\n\tgithub.com/hako/durafmt "
},
{
"path": "go.sum",
"chars": 2995,
"preview": "github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=\ngithub.com/fatih/color v1.9.0/go.mod h1:eQ"
},
{
"path": "impl/base/combine.go",
"chars": 132,
"preview": "package base\n\nimport \"github.com/golangmc/minecraft-server/apis/ents\"\n\ntype PlayerAndConnection struct {\n\tConnection\n\ten"
},
{
"path": "impl/base/compact.go",
"chars": 1587,
"preview": "package base\n\ntype Compacter struct {\n\tValues []int64\n\n\tbpb int\n\tmax int\n}\n\nfunc NewCompacter(bits, size int) *Compacter"
},
{
"path": "impl/base/connect.go",
"chars": 522,
"preview": "package base\n\nimport \"net\"\n\ntype Connection interface {\n\tAddress() net.Addr\n\n\tGetState() PacketState\n\tSetState(state Pac"
},
{
"path": "impl/base/network.go",
"chars": 115,
"preview": "package base\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n)\n\ntype Network interface {\n\tbase.State\n}\n"
},
{
"path": "impl/base/packets.go",
"chars": 1555,
"preview": "package base\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/"
},
{
"path": "impl/conf/config.go",
"chars": 239,
"preview": "package conf\n\nvar DefaultServerConfig = ServerConfig{\n\tNetwork: Network{\n\t\tHost: \"0.0.0.0\",\n\t\tPort: 25565,\n\t},\n}\n\ntype S"
},
{
"path": "impl/conn/buffers.go",
"chars": 9558,
"preview": "package conn\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t"
},
{
"path": "impl/conn/connect.go",
"chars": 2964,
"preview": "package conn\n\nimport (\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"crypto/cipher\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\n\t\"github.com/golangmc/minecraft-s"
},
{
"path": "impl/conn/crypto/cfb8.go",
"chars": 1582,
"preview": "package crypto\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n)\n\ntype cfb8 struct {\n\tb cipher.Block\n\tsr []byte\n\tsrE"
},
{
"path": "impl/conn/network.go",
"chars": 3309,
"preview": "package conn\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"reflect\"\n\t\"strconv\"\n\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.c"
},
{
"path": "impl/cons/console.go",
"chars": 2053,
"preview": "package cons\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n\t\"github.com/golangmc/min"
},
{
"path": "impl/data/client/abilities.go",
"chars": 730,
"preview": "package client\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/impl/m"
},
{
"path": "impl/data/client/chat.go",
"chars": 79,
"preview": "package client\n\ntype ChatMode int\n\nconst (\n\tFull ChatMode = iota\n\tCmds\n\tNone\n)\n"
},
{
"path": "impl/data/client/hand.go",
"chars": 77,
"preview": "package client\n\ntype MainHand int\n\nconst (\n\tHand_L MainHand = iota\n\tHand_R\n)\n"
},
{
"path": "impl/data/client/playerinfo.go",
"chars": 1077,
"preview": "package client\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/e"
},
{
"path": "impl/data/client/position.go",
"chars": 507,
"preview": "package client\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/impl/m"
},
{
"path": "impl/data/client/skin.go",
"chars": 1007,
"preview": "package client\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-serve"
},
{
"path": "impl/data/client/slot.go",
"chars": 138,
"preview": "package client\n\ntype HotBarSlot byte\n\nconst (\n\tSLOT_0 HotBarSlot = iota\n\tSLOT_1\n\tSLOT_2\n\tSLOT_3\n\tSLOT_4\n\tSLOT_5\n\tSLOT_6\n"
},
{
"path": "impl/data/client/status.go",
"chars": 87,
"preview": "package client\n\ntype StatusAction int\n\nconst (\n\tRespawn StatusAction = iota\n\tRequest\n)\n"
},
{
"path": "impl/data/plugin/message.go",
"chars": 4526,
"preview": "package plugin\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/d"
},
{
"path": "impl/data/status/response.go",
"chars": 33010,
"preview": "package status\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/data\"\n\t\"github.com/golangmc/minecraft-server/apis/d"
},
{
"path": "impl/data/system/command.go",
"chars": 305,
"preview": "package system\n\ntype Command int\n\ntype Message struct {\n\tCommand\n\tMessage interface{}\n}\n\nconst (\n\t// stops the server en"
},
{
"path": "impl/data/values/constants.go",
"chars": 323,
"preview": "package values\n\nimport (\n\t\"encoding/binary\"\n\n\t\"github.com/golangmc/minecraft-server/apis/base\"\n)\n\nconst (\n\t// ticks per "
},
{
"path": "impl/game/auth/authenticate.go",
"chars": 1536,
"preview": "package auth\n\nimport (\n\t\"crypto/sha1\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/golangmc/minecraft-server/apis/ur"
},
{
"path": "impl/game/auth/cryptography.go",
"chars": 1028,
"preview": "package auth\n\nimport (\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n)\n\nvar secretKey *rsa.PrivateKey\nvar publicKey *rsa.P"
},
{
"path": "impl/game/ents/entity.go",
"chars": 621,
"preview": "package ents\n\nimport \"github.com/golangmc/minecraft-server/apis/uuid\"\n\nvar entityCounter = int64(0)\n\ntype entity struct "
},
{
"path": "impl/game/ents/living.go",
"chars": 289,
"preview": "package ents\n\ntype entityLiving struct {\n\tentity\n\n\thealth float64\n}\n\nfunc newEntityLiving() entityLiving {\n\treturn entit"
},
{
"path": "impl/game/ents/player.go",
"chars": 1359,
"preview": "package ents\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/data/msgs\"\n\t\"github.com/golangmc/minecraft-server/api"
},
{
"path": "impl/game/event/events.go",
"chars": 387,
"preview": "package event\n\nimport (\n\t\"github.com/golangmc/minecraft-server/impl/base\"\n\t\"github.com/golangmc/minecraft-server/impl/da"
},
{
"path": "impl/game/level/block.go",
"chars": 732,
"preview": "package level\n\nimport (\n\tapis_level \"github.com/golangmc/minecraft-server/apis/game/level\"\n)\n\ntype block struct {\n\t// th"
},
{
"path": "impl/game/level/chunk.go",
"chars": 2958,
"preview": "package level\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/da"
},
{
"path": "impl/game/level/level.go",
"chars": 1993,
"preview": "package level\n\nimport (\n\tapis_level \"github.com/golangmc/minecraft-server/apis/game/level\"\n\t\"github.com/golangmc/minecra"
},
{
"path": "impl/game/level/slice.go",
"chars": 1813,
"preview": "package level\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\tapis_level \"github.com/golangmc/minecraft-ser"
},
{
"path": "impl/game/level/value.go",
"chars": 604,
"preview": "package level\n\nfunc chunkIndex(x, z int) int64 {\n\treturn (int64(z) << 0x20) | (int64(x) & 0xFFFFFFFF)\n}\n\nfunc sliceIndex"
},
{
"path": "impl/game/mode/mode_state0.go",
"chars": 362,
"preview": "package mode\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/util\"\n\t\"github.com/golangmc/minecraft-server/impl/bas"
},
{
"path": "impl/game/mode/mode_state1.go",
"chars": 699,
"preview": "package mode\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/util\"\n\t\"github.com/golangmc/minecraft-server/impl/bas"
},
{
"path": "impl/game/mode/mode_state2.go",
"chars": 2943,
"preview": "package mode\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\n\t\"github.com/golangmc/minecraft-server/apis/data/chat\"\n\t\"github.com/golangmc/min"
},
{
"path": "impl/game/mode/mode_state3.go",
"chars": 5086,
"preview": "package mode\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/golangmc/minecraft-server/apis\"\n\t\"github.com/golangmc/minecraft-serv"
},
{
"path": "impl/mask/masking.go",
"chars": 203,
"preview": "package mask\n\ntype Masking struct{}\n\nfunc (m *Masking) Has(mask, field byte) bool {\n\treturn mask&field != 0\n}\n\nfunc (m *"
},
{
"path": "impl/mask/masking_test.go",
"chars": 322,
"preview": "package mask\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\ntype Data struct {\n\tMasking\n\n\tHead bool\n\tBody bool\n}\n\nfunc TestMasking(t *te"
},
{
"path": "impl/prot/client/to_client_state0.go",
"chars": 24,
"preview": "package client\n\n// done\n"
},
{
"path": "impl/prot/client/to_client_state1.go",
"chars": 706,
"preview": "package client\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minec"
},
{
"path": "impl/prot/client/to_client_state2.go",
"chars": 1634,
"preview": "package client\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/d"
},
{
"path": "impl/prot/client/to_client_state3.go",
"chars": 5886,
"preview": "package client\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/d"
},
{
"path": "impl/prot/packets.go",
"chars": 2814,
"preview": "package prot\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/logs\"\n\t\"github.com/golangmc/minecraft-server/apis/tas"
},
{
"path": "impl/prot/server/to_server_state0.go",
"chars": 535,
"preview": "package server\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/impl/b"
},
{
"path": "impl/prot/server/to_server_state1.go",
"chars": 510,
"preview": "package server\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/impl/b"
},
{
"path": "impl/prot/server/to_server_state2.go",
"chars": 1007,
"preview": "package server\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/impl/b"
},
{
"path": "impl/prot/server/to_server_state3.go",
"chars": 4515,
"preview": "package server\n\nimport (\n\t\"github.com/golangmc/minecraft-server/apis/buff\"\n\t\"github.com/golangmc/minecraft-server/apis/d"
},
{
"path": "impl/server.go",
"chars": 8456,
"preview": "package impl\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/golangmc/minecraft-server/apis\"\n\t\"github.com/g"
},
{
"path": "main.go",
"chars": 753,
"preview": "package main\n\nimport (\n\t\"flag\"\n\n\t\"github.com/fatih/color\"\n\n\t\"github.com/golangmc/minecraft-server/impl\"\n\t\"github.com/gol"
}
]
About this extraction
This page contains the full source code of the GoLangMc/minecraft-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 99 files (152.1 KB), approximately 53.7k tokens, and a symbol index with 733 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.