Giter VIP home page Giter VIP logo

go-mc's Introduction

Go-MC

Version Go Reference Go Report Card Discord

Require Go version: 1.20

There's some library in Go support you to create your Minecraft client or server.
这是一些Golang库,用于帮助你编写自己的Minecraft客户端或服务器。

  • 👍 Minecraft network protocol
  • 👍 Robot framework
  • 👍 Server framework
  • 👍 Dual role RCON protocol (Server & Client)
  • 👍 Chat Message (Support both Json and old § format)
  • 👍 NBT (Based on reflection)
  • 👌 SNBT ⇋ NBT
  • 👍 Regions & Chunks & Blocks
  • ⌛ Yggdrasil (Mojang login)
  • ⌛ Realms Server

We don't promise that API is 100% backward compatible.

Getting start

Go-MC tag the old version after new version released. For example, if 1.19.4 is the latest Minecraft version, the newest go-mc tag will be v1.19.3. To get the latest Go-MC that support 1.19.4, usually you must use go get -u github.com/Tnze/go-mc@master. Special cases are version like 1.19, the Go-MC support it is tagged v1.19.0 to avoid automatically upgrade.

Examples:
To get the latest version: go get github.com/Tnze/go-mc@master
To get old versions (e.g. 1.18.2): go get github.com/Tnze/[email protected] To get the first of each primary version: go get github.com/Tnze/[email protected]

Run Examples

  • Run go run github.com/Tnze/go-mc/examples/mcping localhost to ping and list the localhost mc server.
  • Run go run github.com/Tnze/go-mc/examples/daze to join the local server at localhost:25565 as player named Daze on the offline mode.

go-mc's People

Contributors

andrewlanin avatar baimeow avatar comblock avatar dazoe avatar deadlysurgeon avatar erikpelli avatar genanik avatar hofill avatar jacklee1792 avatar jolheiser avatar layou233 avatar mammut53 avatar masp avatar maxsupermanhd avatar nickyboy89 avatar nugget avatar patyhank avatar qwqtoday avatar rainchi avatar richgrov avatar spbinns avatar sunbread avatar tauraamui avatar tnze avatar xtrafrancyz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-mc's Issues

Panic at c.Chat()

This is the error which ide tell me:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x12a0c6e]
goroutine 42 [running]:
github.com/Tnze/go-mc/bot.(*Client).Chat(0x0, 0x134bd32, 0x4, 0x1, 0x1)
        ~/Desktop/go-mc/bot/motion.go:81 +0xce
main.watchDog()
        ~/Desktop/go-mc/cmd/Chat/Chat.go:94 +0x15e

I try to change autofish.go to make it can show me chat msg on server

This is code I changed:

func onGameStart() error {
	log.Println("Game start")
	watch = make(chan time.Time)
	go watchDog()
	return nil
}
func watchDog() {
	to := time.NewTimer(time.Second * timeout)
	for {
		select {
		case <-watch:
		case <-to.C:
			log.Println("raply")
			if err := c.Chat("test"); err != nil {
				panic(err)
			}
		}
		to.Reset(time.Second * timeout)
	}
}

Thanks!

Any sort of documentation?

I love your tool but is there a place where I can see all the functions you implemented (not only the examples you have supplied)

about AttackEntity

AttackEntity(entityID int32, hand int),这里需要一个整数型的id,但是现在的实体id都是类似iron_golem 之类的,1.14之后不能用数字id了,这里应该写什么?

Suggestion: Implement the context and Finite State Machine

I'm writing a virtual Minecraft server based on this package. Since there is no any information about connection state (i.e. FSM), I have to wrap the provided net.Conn to implement connection state.

What's more, sharing data between different connection states and goroutines seems difficult as no context has provided. For example, I want to share the protocol version, keepalive id data and so on between Play connection state and goroutine that is used to send keepalive packet repeatly so that I can measure the latency between server and client.

Implement a context may be a good choice, it could solve problems mentioned above. How about your idea?

Does it support 1.14?

Hey. Nice Tool. I'm interested to use it in 1.14. Does it support 1.14?
Thank you

Validate don't work now

Validate() don't work now.
I send the fresh token,but it retuens httpstatus 403.
Maybe Mojang changed something,
I believe Tnze will fix it.

Movement

func (g *Client) SetPosition(x, y, z float64, onGround bool) error {
 	g.Player.X, g.Player.Y, g.Player.Z = x, y, z
 	g.Player.OnGround = onGround
	g.conn.WritePacket(pk.Marshal(
		0x12,
		pk.Double(x),
		pk.Double(y),
		pk.Double(z),
		pk.Boolean(true),
	))
	
	recv, err := g.conn.ReadPacket()
	if err != nil {
		fmt.Errorf("bot: recv list packect fail: %v", err)
		return nil
	}
	var t pk.VarInt
	err = recv.Scan(&t)
	if err != nil {
		return nil
	}
	
	g.conn.WritePacket(pk.Marshal(
		0x00,
		t,
	))
	
	return nil
}

I cannot get this code to work, I'm not really used to Minecraft Protocol so I'm not sure of how to do this

Join message causes error for HandleGame()

I don't know why this happens, but certain servers have a message that gets sent when the client joins. That message causes HandleGame() to return an error.

If the server does not send a message other than the default "IGN has joined the game," the code below works well.

Log snippets:

[MCCENTRAL.ORG]
time="2020-11-29T04:27:19-07:00" level=info msg="game started" ign=7447
time="2020-11-29T04:27:19-07:00" level=error msg="error handling game" error="handle packet 0x20 error: block entities: nbt: fail to decode tag \"\": fail to decode tag \"color\": cannot parse TagInt as string" hostname=mccentral.org port=25565


[US.MINEPLEX.COM]
time="2020-11-29T04:29:13-07:00" level=info msg="joined game"
time="2020-11-29T04:29:13-07:00" level=info msg="game started" ign=7447
TELEPORT (y=0.00, velY=0.000): 0.50, 73.00, 0.50
TELEPORT (y=72.77, velY=-0.231): 0.00, 0.23, 0.00
{114898868 [60 80 114 112 23 50 66 237 187 29 227 61 117 44 214 225] 7.1875 72 8.09375 -58 -3}
{115891081 [6 115 225 13 12 250 69 78 177 102 98 141 1 216 39 248] 23.6875 73.09375 11.46875 116 14}
{114571638 [76 150 236 235 14 177 75 235 146 48 38 224 255 62 36 48] 19.28125 71 10.875 -1 24}
{91468008 [181 230 86 155 94 159 74 227 155 218 225 9 131 6 164 157] 1.6875 71 24.6875 -2 21}
{115573675 [6 111 221 243 187 64 76 210 147 68 78 176 51 139 175 74] -1.21875 71 30.21875 -94 63}
{115801888 [12 97 230 179 83 8 74 248 147 204 139 150 247 139 165 48] -10.5 71 30.5 0 0}
{115868977 [168 212 253 160 216 37 77 252 158 192 128 121 238 239 61 93] -9.6875 71 26.15625 2 14}
{115900668 [215 175 22 224 21 187 64 241 168 125 236 86 5 181 157 73] -0.96875 72 -1.9375 -85 10}
{115854796 [249 185 54 77 136 253 71 147 191 251 130 77 243 113 59 214] 4.3125 77.3125 -12.8125 -121 -29}
{115654686 [44 14 195 143 42 45 72 61 137 227 203 149 44 208 12 173] 32.21875 71 -4.34375 -84 -23}
{115876640 [22 231 247 161 46 170 77 93 172 132 180 95 14 80 98 41] 31.84375 71 1.59375 -95 -14}
{115612901 [207 11 177 23 233 33 71 160 187 130 236 34 115 251 71 113] 11.125 77 40.15625 -5 28}
{115883214 [245 26 118 121 240 1 78 175 152 28 182 102 233 224 153 223] 11.84375 71 32.59375 -89 17}
{115807671 [43 51 75 213 154 194 76 50 186 147 119 51 126 180 198 153] -25.09375 79.625 34.46875 -107 17}
{115819718 [255 74 102 143 7 37 66 161 172 219 195 171 189 245 88 176] -19.03125 72 20.9375 46 -9}
{101415607 [48 39 103 46 166 13 68 89 152 145 199 135 148 226 19 29] -25.4375 75.96875 31.90625 41 7}
{115643586 [94 92 27 216 222 64 69 174 186 99 40 164 167 9 144 97] 0.625 71 -28.1875 120 16}
time="2020-11-29T04:29:14-07:00" level=error msg="error handling game" error="handle packet 0xE error: json: cannot unmarshal string into Go struct field jsonChat.extra of type chat.jsonChat" hostname=us.mineplex.com port=25565

Relevant code: code

getting: auth fail and recv packet for Login fail errors

Hello, I'm trying to run .cmd/daze/daze.go but I'm getting this errors:
login fail: auth fail: {"error":"IllegalArgumentException","errorMessage":"Access Token can not be null or empty."}
and
bot: recv packet for Login fail: read len of packet fail: EOF

Donations

Hi! First of all, congrats for your excelent work.

I would like to somehow donate to this project keep going. Can you create a patreon or something like that?

I haven't even test this lib in my server. But I'm guessing this is exactly what i was looking for.

Online Mode Supported?

Is online mode supported out of the box, or does it have to be manually added? I was able to get offline mode working just fine, but online mode keeps throwing me authentication errors using a legitimate Minecraft account. Specifically:
bot: encryption fail: login fail: auth fail: {"error":"IllegalArgumentException","errorMessage":"Access Token can not be null or empty."} exit status 1

I've gone through and set up the account information everywhere I can find, but I'm wondering if I could be missing a file or setting somewhere. I'm still a bit new to this, so I apologize if this is a stupid question. For information, this is for connecting to a vanilla 1.14.4 server on localhost with online-mode set to true.

Edit: On the server's end, it doesn't show me connecting, but it does show me disconnecting. No errors come up there.

NBT string length less than 0 with playerdata

Hey, I am trying to read playerdata files out of the world/playerdata directory of a server but I keep getting this error because the decoder is unable to decode some string.
The NBT data is untouched and coming from the game only.
This is my code:

package reincarnation

import (
	"github.com/Tnze/go-mc/nbt"
	"github.com/zischknall/gomc-wrapper/pkg/gameserver"
	"io/ioutil"
	"log"
	"os"
)

type entityData struct {
	Pos            []float64    `nbt:"Pos"`
	Motion         []float64    `nbt:"Motion"`
	Rotation       []float64    `nbt:"Rotation"`
	FallDistance   int          `nbt:"FallDistance"`
	Fire           int          `nbt:"Fire"`
	Air            int          `nbt:"Air"`
	OnGround       byte         `nbt:"OnGround"`
	NoGravity      byte         `nbt:"NoGravity"`
	Dimension      int16        `nbt:"Dimension"`
	Invulnerable   byte         `nbt:"Invulnerable"`
	PortalCooldown int16        `nbt:"PortalCooldown"`
	UUIDMost       int64        `nbt:"UUIDMost"`
	UUIDLeast      int64        `nbt:"UUIDLeast"`
	Silent         byte         `nbt:"Silent"`
	Passengers     []entityData `nbt:"Passengers"`
	Glowing        byte         `nbt:"Glowing"`
	Tags           []string     `nbt:"Tags"`
}

type modifier struct {
	Name      string `nbt:"Name"`
	Amount    int64  `nbt:"Amount"`
	Operation int16  `nbt:"Operation"`
	UUIDMost  int64  `nbt:"UUIDMost"`
	UUIDLeast int64  `nbt:"UUIDLeast"`
}

type attribute struct {
	Name      string     `nbt:"Name"`
	Base      int64      `nbt:"Base"`
	Modifiers []modifier `nbt:"Modifiers"`
}

type effect struct {
	Id            int64   `nbt:"Id"`
	Amplifier     int16   `nbt:"Amplifier"`
	Duration      int64   `nbt:"Duration"`
	Ambient       byte    `nbt:"Ambient"`
	ShowParticles byte    `nbt:"ShowParticles"`
	ShowIcon      byte    `nbt:"ShowIcon"`
	HiddenEffect  *effect `nbt:"HiddenEffect"`
}

type item struct {
	Count int16    `nbt:"Count"`
	Slot  int16    `nbt:"Slot"`
	Id    int64    `nbt:"id"`
	Tag   []string `nbt:"tag"`
}

type playerData struct {
	Pos              []float64    `nbt:"Pos"`
	Motion           []float64    `nbt:"Motion"`
	Rotation         []float64    `nbt:"Rotation"`
	FallDistance     int          `nbt:"FallDistance"`
	Fire             int          `nbt:"Fire"`
	Air              int          `nbt:"Air"`
	OnGround         byte         `nbt:"OnGround"`
	NoGravity        byte         `nbt:"NoGravity"`
	Dimension        int16        `nbt:"Dimension"`
	Invulnerable     byte         `nbt:"Invulnerable"`
	PortalCooldown   int16        `nbt:"PortalCooldown"`
	UUIDMost         int64        `nbt:"UUIDMost"`
	UUIDLeast        int64        `nbt:"UUIDLeast"`
	Silent           byte         `nbt:"Silent"`
	Passengers       []entityData `nbt:"Passengers"`
	Glowing          byte         `nbt:"Glowing"`
	Tags             []string     `nbt:"Tags"`
	Health           int16        `nbt:"Health"`
	AbsorptionAmount int16        `nbt:"AbsorptionAmount"`
	HurtTime         int16        `nbt:"HurtTime"`
	HurtByTimestamp  int64        `nbt:"HurtByTimestamp"`
	DeathTime        int16        `nbt:"DeathTime"`
	FallFlying       byte         `nbt:"FallFlying"`
	SleepingX        float64      `nbt:"SleepingX"`
	SleepingY        float64      `nbt:"SleepingY"`
	SleepingZ        float64      `nbt:"SleepingZ"`
	Brain            struct {
		memories struct{} `nbt:"memories"`
	} `nbt:"Brain"`
	Attributes       []attribute `nbt:"Attributes"`
	ActiveEffects    []effect    `nbt:"ActiveEffects"`
	LeftHanded       byte        `nbt:"LeftHanded"`
	DataVersion      int         `nbt:"DataVersion"`
	PlayerGameType   int         `nbt:"playerGameType"`
	Score            int         `nbt:"Score"`
	SelectedItemSlot int         `nbt:"SelectedItemSlot"`
	SelectedItem     struct {
		Count int16    `nbt:"Count"`
		Id    int64    `nbt:"id"`
		Tag   []string `nbt:"tag"`
	} `nbt:"SelectedItem"`
	SpawnX              float64 `nbt:"SpawnX"`
	SpawnY              float64 `nbt:"SpawnY"`
	SpawnZ              float64 `nbt:"SpawnZ"`
	SpawnForced         byte    `nbt:"SpawnForced"`
	SleepTimer          int     `nbt:"SleepTimer"`
	FoodLevel           int16   `nbt:"foodLevel"`
	FoodExhaustionLevel int16   `nbt:"foodExhaustionLevel"`
	FoodSaturationLevel int16   `nbt:"foodSaturationLevel"`
	FoodTickTimer       int16   `nbt:"foodTickTimer"`
	XpLevel             int64   `nbt:"XpLevel"`
	XpP                 int16   `nbt:"XpP"`
	XpTotal             int64   `nbt:"XpTotal"`
	XpSeed              int64   `nbt:"XpSeed"`
	Inventory           []item  `nbt:"Inventory"`
	EnderItems          []item  `nbt:"EnderItems"`
	Abilities           struct {
		WalkSpeed    float64 `nbt:"walkSpeed"`
		FlySpeed     float64 `nbt:"flySpeed"`
		MayFly       byte    `nbt:"mayFlyx"`
		Flying       byte    `nbt:"flying"`
		Invulnerable byte    `nbt:"invulnerable"`
		MayBuild     byte    `nbt:"mayBuild"`
		InstaBuild   byte    `nbt:"instaBuild"`
	} `nbt:"abilities"`
	EnteredNetherPosition struct {
		X float64 `nbt:"x"`
		Y float64 `nbt:"y"`
		Z float64 `nbt:"z"`
	} `nbt:"enteredNetherPosition"`
	RootVehicle struct {
		AttachLeast int64      `nbt:"AttachLeast"`
		AttachMost  int64      `nbt:"AttachMost"`
		Entity      entityData `nbt:"Entity"`
	} `nbt:"RootVehicle"`
	ShoulderEntityLeft  entityData `nbt:"ShoulderEntityLeft"`
	ShoulderEntityRight entityData `nbt:"ShoulderEntityRight"`
	SeenCredits         byte       `nbt:"seenCredits"`
	RecipeBook          []byte     `nbt:"recipeBook"`
}

func Init(server gameserver.MCServer) {
	playerstore := server.BasePath + "/world/playerdata/"
	fi, err := os.Stat(playerstore)
	if err != nil {
		log.Println("[REINCARNATION] Playerstore does not exist!")
	}
	if fi.Mode().IsRegular() {
		log.Println("[REINCARNATION] Playerstore does not exist!")
		return
	}

	players, err := ioutil.ReadDir(playerstore)
	if err != nil {
		log.Println("[REINCARNATION] Is the Playerstore empty?")
		return
	}

	for _, player := range players {
		var result playerData
		b, err := ioutil.ReadFile(playerstore + player.Name())
		if err != nil {
			log.Println("[REINCARNATION] Error opening file!")
			continue
		}

		if err := nbt.Unmarshal(b, &result); err != nil {
			log.Println(err)
			continue
		}

		log.Println("[REINCARNATION] " + player.Name() + " " + string(result.PlayerGameType))
	}
}

BTW, I am still a novice to Golang and coding in general so other coding related suggestions are also welcome.

This is the Output:

2020/04/03 18:38:26 nbt: string length less than 0

And this is the Hexdump of the file:

0x0000: 0a 00 00 05 00 10 41 62 73 6f 72 70 | ......Absorp
0x000c: 74 69 6f 6e 41 6d 6f 75 6e 74 00 00 | tionAmount..
0x0018: 00 00 02 00 03 41 69 72 01 2c 09 00 | .....Air....
0x0024: 0a 41 74 74 72 69 62 75 74 65 73 0a | .Attributes.
0x0030: 00 00 00 08 06 00 04 42 61 73 65 40 | .......Base.
0x003c: 34 00 00 00 00 00 00 08 00 04 4e 61 | 4.........Na
0x0048: 6d 65 00 11 67 65 6e 65 72 69 63 2e | me..generic.
0x0054: 6d 61 78 48 65 61 6c 74 68 00 06 00 | maxHealth...
0x0060: 04 42 61 73 65 00 00 00 00 00 00 00 | .Base.......
0x006c: 00 08 00 04 4e 61 6d 65 00 1b 67 65 | ....Name..ge
0x0078: 6e 65 72 69 63 2e 6b 6e 6f 63 6b 62 | neric.knockb
0x0084: 61 63 6b 52 65 73 69 73 74 61 6e 63 | ackResistanc
0x0090: 65 00 06 00 04 42 61 73 65 3f b9 99 | e....Base...
0x009c: 99 a0 00 00 00 08 00 04 4e 61 6d 65 | ........Name
0x00a8: 00 15 67 65 6e 65 72 69 63 2e 6d 6f | ..generic.mo
0x00b4: 76 65 6d 65 6e 74 53 70 65 65 64 00 | vementSpeed.
0x00c0: 06 00 04 42 61 73 65 00 00 00 00 00 | ...Base.....
0x00cc: 00 00 00 08 00 04 4e 61 6d 65 00 0d | ......Name..
0x00d8: 67 65 6e 65 72 69 63 2e 61 72 6d 6f | generic.armo
0x00e4: 72 00 06 00 04 42 61 73 65 00 00 00 | r....Base...
0x00f0: 00 00 00 00 00 08 00 04 4e 61 6d 65 | ........Name
0x00fc: 00 16 67 65 6e 65 72 69 63 2e 61 72 | ..generic.ar
0x0108: 6d 6f 72 54 6f 75 67 68 6e 65 73 73 | morToughness
0x0114: 00 06 00 04 42 61 73 65 3f f0 00 00 | ....Base....
0x0120: 00 00 00 00 08 00 04 4e 61 6d 65 00 | .......Name.
0x012c: 14 67 65 6e 65 72 69 63 2e 61 74 74 | .generic.att
0x0138: 61 63 6b 44 61 6d 61 67 65 00 06 00 | ackDamage...
0x0144: 04 42 61 73 65 40 10 00 00 00 00 00 | .Base.......
0x0150: 00 08 00 04 4e 61 6d 65 00 13 67 65 | ....Name..ge
0x015c: 6e 65 72 69 63 2e 61 74 74 61 63 6b | neric.attack
0x0168: 53 70 65 65 64 00 06 00 04 42 61 73 | Speed....Bas
0x0174: 65 00 00 00 00 00 00 00 00 08 00 04 | e...........
0x0180: 4e 61 6d 65 00 0c 67 65 6e 65 72 69 | Name..generi
0x018c: 63 2e 6c 75 63 6b 00 0a 00 05 42 72 | c.luck....Br
0x0198: 61 69 6e 0a 00 08 6d 65 6d 6f 72 69 | ain...memori
0x01a4: 65 73 00 00 03 00 0b 44 61 74 61 56 | es.....DataV
0x01b0: 65 72 73 69 6f 6e 00 00 08 b6 02 00 | ersion......
0x01bc: 09 44 65 61 74 68 54 69 6d 65 00 00 | .DeathTime..
0x01c8: 03 00 09 44 69 6d 65 6e 73 69 6f 6e | ...Dimension
0x01d4: 00 00 00 00 09 00 0a 45 6e 64 65 72 | .......Ender
0x01e0: 49 74 65 6d 73 00 00 00 00 00 05 00 | Items.......
0x01ec: 0c 46 61 6c 6c 44 69 73 74 61 6e 63 | .FallDistanc
0x01f8: 65 00 00 00 00 01 00 0a 46 61 6c 6c | e.......Fall
0x0204: 46 6c 79 69 6e 67 00 02 00 04 46 69 | Flying....Fi
0x0210: 72 65 ff ec 05 00 06 48 65 61 6c 74 | re.....Healt
0x021c: 68 41 a0 00 00 03 00 0f 48 75 72 74 | hA......Hurt
0x0228: 42 79 54 69 6d 65 73 74 61 6d 70 00 | ByTimestamp.
0x0234: 00 00 00 02 00 08 48 75 72 74 54 69 | ......HurtTi
0x0240: 6d 65 00 00 09 00 09 49 6e 76 65 6e | me.....Inven
0x024c: 74 6f 72 79 00 00 00 00 00 01 00 0c | tory........
0x0258: 49 6e 76 75 6c 6e 65 72 61 62 6c 65 | Invulnerable
0x0264: 00 09 00 06 4d 6f 74 69 6f 6e 06 00 | ....Motion..
0x0270: 00 00 03 00 00 00 00 00 00 00 00 00 | ............
0x027c: 00 00 00 00 00 00 00 00 00 00 00 00 | ............
0x0288: 00 00 00 01 00 08 4f 6e 47 72 6f 75 | ......OnGrou
0x0294: 6e 64 00 03 00 0e 50 6f 72 74 61 6c | nd....Portal
0x02a0: 43 6f 6f 6c 64 6f 77 6e 00 00 00 00 | Cooldown....
0x02ac: 09 00 03 50 6f 73 06 00 00 00 03 c0 | ...Pos......
0x02b8: 65 e5 cb ec 0f bb cd 40 54 28 11 5e | e.......T(..
0x02c4: 40 4f 42 40 61 63 8c 0b 5a 79 7e 09 | .OB.ac..Zy..
0x02d0: 00 08 52 6f 74 61 74 69 6f 6e 05 00 | ..Rotation..
0x02dc: 00 00 02 c3 14 cc c4 41 4b ff fe 03 | .......AK...
0x02e8: 00 05 53 63 6f 72 65 00 00 00 00 03 | ..Score.....
0x02f4: 00 10 53 65 6c 65 63 74 65 64 49 74 | ..SelectedIt
0x0300: 65 6d 53 6c 6f 74 00 00 00 00 02 00 | emSlot......
0x030c: 0a 53 6c 65 65 70 54 69 6d 65 72 00 | .SleepTimer.
0x0318: 00 04 00 09 55 55 49 44 4c 65 61 73 | ....UUIDLeas
0x0324: 74 ab de 16 57 e5 43 7c 4f 04 00 08 | t...W.C.O...
0x0330: 55 55 49 44 4d 6f 73 74 f0 e5 b5 7d | UUIDMost...}
0x033c: 6a a0 4c ba 03 00 07 58 70 4c 65 76 | j.L....XpLev
0x0348: 65 6c 00 00 00 00 05 00 03 58 70 50 | el.......XpP
0x0354: 00 00 00 00 03 00 06 58 70 53 65 65 | .......XpSee
0x0360: 64 b8 3c 16 12 03 00 07 58 70 54 6f | d.......XpTo
0x036c: 74 61 6c 00 00 00 00 0a 00 09 61 62 | tal.......ab
0x0378: 69 6c 69 74 69 65 73 05 00 08 66 6c | ilities...fl
0x0384: 79 53 70 65 65 64 3d 4c cc cd 01 00 | ySpeed.L....
0x0390: 06 66 6c 79 69 6e 67 01 01 00 0a 69 | .flying....i
0x039c: 6e 73 74 61 62 75 69 6c 64 01 01 00 | nstabuild...
0x03a8: 0c 69 6e 76 75 6c 6e 65 72 61 62 6c | .invulnerabl
0x03b4: 65 01 01 00 08 6d 61 79 42 75 69 6c | e....mayBuil
0x03c0: 64 01 01 00 06 6d 61 79 66 6c 79 01 | d....mayfly.
0x03cc: 05 00 09 77 61 6c 6b 53 70 65 65 64 | ...walkSpeed
0x03d8: 3d cc cc cd 00 05 00 13 66 6f 6f 64 | ........food
0x03e4: 45 78 68 61 75 73 74 69 6f 6e 4c 65 | ExhaustionLe
0x03f0: 76 65 6c 3f a5 60 43 03 00 09 66 6f | vel...C...fo
0x03fc: 6f 64 4c 65 76 65 6c 00 00 00 14 05 | odLevel.....
0x0408: 00 13 66 6f 6f 64 53 61 74 75 72 61 | ..foodSatura
0x0414: 74 69 6f 6e 4c 65 76 65 6c 40 a0 00 | tionLevel...
0x0420: 00 03 00 0d 66 6f 6f 64 54 69 63 6b | ....foodTick
0x042c: 54 69 6d 65 72 00 00 00 00 03 00 0e | Timer.......
0x0438: 70 6c 61 79 65 72 47 61 6d 65 54 79 | playerGameTy
0x0444: 70 65 00 00 00 01 0a 00 0a 72 65 63 | pe.......rec
0x0450: 69 70 65 42 6f 6f 6b 01 00 14 69 73 | ipeBook...is
0x045c: 46 69 6c 74 65 72 69 6e 67 43 72 61 | FilteringCra
0x0468: 66 74 61 62 6c 65 00 01 00 1b 69 73 | ftable....is
0x0474: 46 75 72 6e 61 63 65 46 69 6c 74 65 | FurnaceFilte
0x0480: 72 69 6e 67 43 72 61 66 74 61 62 6c | ringCraftabl
0x048c: 65 00 01 00 10 69 73 46 75 72 6e 61 | e....isFurna
0x0498: 63 65 47 75 69 4f 70 65 6e 00 01 00 | ceGuiOpen...
0x04a4: 09 69 73 47 75 69 4f 70 65 6e 00 09 | .isGuiOpen..
0x04b0: 00 07 72 65 63 69 70 65 73 00 00 00 | ..recipes...
0x04bc: 00 00 09 00 0d 74 6f 42 65 44 69 73 | .....toBeDis
0x04c8: 70 6c 61 79 65 64 00 00 00 00 00 00 | played......
0x04d4: 01 00 0b 73 65 65 6e 43 72 65 64 69 | ...seenCredi
0x04e0: 74 73 00 00                         | ts..

building NBT Tag Compound

I try to understand how NBT works, the example is:
I try to send a Login packet to the client (https://wiki.vg/Protocol#Join_Game)

In my tests:

conn.WritePacket(pk.Marshal(packetid.Login,
		pk.Int(0),                         // EntityID
		pk.Boolean(false),                 // IsHardcode
		pk.UnsignedByte(1),                // Gamemode 0: Survival, 1: Creative, 2: Adventure, 3: Spectator.
		pk.Byte(0),                        // Previous Gamemode
		pk.VarInt(1),                      // World Count
		pk.ByteArray("main"),              // Identifiers for all worlds on the server.
		pk.ByteArray{},                    // Dimension Codec
		pk.Int(0),                         // Dimension
		pk.Identifier("main world"),       // World name
		pk.Long(0),                        // HashedSeed
		pk.UnsignedByte(config.MaxPlayer), // MaxPlayer
		pk.VarInt(15),                     // View Distance
		pk.Boolean(false),                 // Reduced Debug Info
		pk.Boolean(true),                  // Enable respawn screen
		pk.Boolean(true),                  // Is Debug
		pk.Boolean(false),                 // Is Flat
	))

how can I fill Dimension Codec or Dimension with the given wiki definition ? Is there any helper to build NBT structs ?

Handle packet error 0x1A (run daze)

I get the following error when trying to run "daze"

xxxxxxxxxxxx Login success
xxxxxxxxxxxx handle packet 0x1A error: invalid character '\n' in string literal

What am I supposed to do?

How to login with using compass?

Every time someone chat my command deleted and after i write something it didn't get sended (im using 1.14.1 maybe that's the problem, if it is the problem plss update the old client).

EOF error

Everytime i login it say

2019/08/10 00:17:10 bot: read packet fail: read len of packet fail: EOF
exit status 1

That happen sometimes

multiple protocol versions

Hi, thanks for creating and posting this library :)

This is more of a question not an issue, but are there plans for adding multiple protocol support?
Since for example many servers still use <1.11

Read Minecraft chat with bot package

I am trying to read the chat from my remote application, I tried to use the bot package. I have this piece of code I tried to run:

botClient := bot.NewClient()
err := botClient.JoinServer(server.Address, 25565)

I'm running a server on the minecraft version 1.16.4 on the port 25565, and RCON on port 25575 and got this error message:

bot: connect disconnected by server: {"translate":"multiplayer.disconnect.outdated_client","with":["1.16.4"]}

Any ideas on how to fix it?

Server example

Could you add some very basic server example ?
(I am quite new at Go and Minecraft Protocol)

Get inventory not working

Anyone having issues trying to fetch the inventory?

I'm trying to check the hotbar and I get this:

2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false
2019/08/10 16:57:16 minecraft:air, 0, 0, false

Code:

func printHotBar() {
	hotbar := c.HotBar()
	for _, slot := range hotbar {
		log.Println(fmt.Sprintf("%v, %v, %v, %v", slot, slot.Count, slot.ItemID, slot.Present))
	}
}

Tested on multiple different servers, same result.

The bar is definitely not empty, as the auto fishing works.

Install command?

I tried:
go get github.com/Tnze/go-mc

It didn't work, what should in do?

Add WriteFields func to Packet, to make packet construction more flexible

I generally use packet.Marshal() to create a packet.
But recently I encountered a issue: The packet's fields and their order may be different in different protocol version.
For example, Packet Join Game:
Structure in 1.15.2:

Packet ID State Bound To
0x26 Play Client
Field Name Field Type Notes
Entity ID Int The player's Entity ID (EID)
Gamemode Unsigned Byte 0: Survival, 1: Creative, 2: Adventure, 3: Spectator. Bit 3 (0x8) is the hardcore flag.
Dimension Int Enum -1: Nether, 0: Overworld, 1: End; also, note that this is not a VarInt but instead a regular int.
Hashed seed Long First 8 bytes of the SHA-256 hash of the world's seed.
Max Players Unsigned Byte Was once used by the client to draw the player list, but now is ignored
Level Type String Enum (16) default, flat, largeBiomes, amplified, customized, buffet, default_1_1
View Distance VarInt Render distance (2-32)
Reduced Debug Info Boolean If true, a Notchian client shows reduced information on the debug screen. For servers in development, this should almost always be false.
Enable respawn screen Boolean Set to false when the doImmediateRespawn gamerule is true

Structure in 1.12.2:

Packet ID State Bound To
0x23 Play Client
Field Name Field Type Notes
Entity ID Int The player's Entity ID (EID)
Gamemode Unsigned Byte 0: Survival, 1: Creative, 2: Adventure, 3: Spectator. Bit 3 (0x8) is the hardcore flag.
Dimension Int Enum -1: Nether, 0: Overworld, 1: End; also, note that this is not a VarInt but instead a regular int.
Difficulty Unsigned Byte 0: peaceful, 1: easy, 2: normal, 3: hard
Max Players Unsigned Byte Was once used by the client to draw the player list, but now is ignored
Level Type String Enum (16) default, flat, largeBiomes, amplified, default_1_1
Reduced Debug Info Boolean If true, a Notchian client shows reduced information on the debug screen. For servers in development, this should almost always be false.

There are some obvious diffreences between them.
If I accept multi protocol versions, I may code like this:

var pk packet.Packet
// protocover 578 represents mc 1.15.2, 340 represents mc 1.12.2
if protover == 578 {
	pk = packet.Marshal(0x26, field1, field2...)
} else if protover == 340 {
	pk = packet.Marshal(0x23, field1, field2...)
}
// sendPacket...

But I want to make it more flexible:

pk := packet.Marshal(getPacketIdByProtocol(protover))
pk.WriteFields(entityId, gameMode, dimension)
if protover == 578 {
	// Write the field that belongs to packet Join Game in protocol version 578
	pk.WriteFields(hashedSeed)
}
pk.WriteFields(maxPlayers, levelType)
......
// sendPacket......

If there is no function used to add fields to the packet, We may code like this:

pk.Data = append(pk.Data, fields...)
if protover == 578 {
	// Write the field that belongs to packet Join Game in protocol version 578
	pk.Data = append(pk.Data, hashedSeed)
}
pk.Data = append(pk.Data, fields...)
// sendPacket...

So might we add some func to make it simpler?

Get NBT data from entity.Slot

Is it possible to get the nbt data from an entity.Slot instance?
By the looks of it its just an empty struct and i've been trying to get the nbt out of it with no sucess.

This is the code i've used.

//on main function
client.Events.WindowsItem = onWinItem

//onWinItem
func onWinItem(b byte, slots []entity.Slot) error {
	for _, slot := range slots {
		log.Println(fmt.Sprintf("Items : %v, %v, %v, %v", slot, slot.Count, slot.ItemID, slot.NBT))
	}
	return nil
}

Output :

...
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {}
2019/10/05 22:36:11 Items : minecraft:player_head, 1, 770, {} ...

The items in question have nbt data as shown via the Advanced Tooltips ingame:

Refactor of the bot.Client API ?

Would you be open to me submitting PRs to refactor bot.Client ? This is what I would like to do:

  1. Move specific packet serialization/deserialization logic out of bot/ingame.go into its own types, in their own package. I could put them into net/packet if you are okay with that, otherwise I can make another package for these high-level packet types.

  2. Move entity tracking and world/block tracking logic out of bot.Client, instead having bot.Client consume an interface for such tracking. This would allow users to switch out different 'backends' for tracking entities and chunk data, and allow us to be more modular in the underlying implementation.

  3. Implement missing player state variables and tracking into bot.Client. Specifically, that would be Move() / Look() methods, as well as methods for manipulating the inventory.

EOF when writing packet

I have used the simpleServer and daze examples, and made it so that every time the client sends a packet, the server responds with a chat message:

for {
		if _, err := conn.ReadPacket(); err != nil {
			log.Printf("ReadPacket error: %v, Time: %v\n", err, time.Now().Nanosecond())
			break
		}
		// KeepAlive packet is not handled, so client might
		// exit because of "time out".
		conn.WritePacket(pk.Marshal(data.ChatClientbound,
			chat.Message{Text:"hello"},
			pk.Byte(0),
		))
	}

I have made no other changes to the original simpleServer other than the above.

However, as soon as the client sends a packet, it disconnects:
Client fatal log:

2020/10/16 17:36:33 handle packet 0xE error: EOF

Server disconnect log:

2020/10/16 17:36:39 ReadPacket error: EOF

using time.Now().Nanosecond(), I have found out that the server prints it before the client, although I do not know if this is reliable.
Here are the two ouptuts: (note that these are just numbers in the range of [0, 999999999] and resets every second, though they are the same across different programs)
server:
530846000
client
530859000

A way to access chests/crafting tables?

Hello there,

Thank you so much for the awesome library. I am trying to use this library to create a bot that can grab stuffs in the chest and then craft them to items I want. Is that possible to be done?

Create 'Extra' text outside of the 'chat' package?

I am fairly new to Go, so I may be missing a workaround way of doing this, but it does not seem possible to create chat.Message objects containing Extra contents without modifying the chat package.

For instance, consider this chat.Message object with additional formatting, containing an Extra block with its own formatting:

desc := chat.Message{
	Text: "Line 1\n",
	Color: "blue",
	Italic: true,
	Extra: []chat.jsonChat{{
		Text: "Line 2",
		Color: "green",
		Bold: true,
	}},
}

This will result in the following compiler error:

cannot refer to unexported name chat.jsonChat

If you were to replace jsonChat with Message, which is exported, you would get another compiler error:

cannot use []chat.Message literal (type []chat.Message) as type []chat.jsonChat in field value

This makes sense; even though Message is identical to jsonChat, because they are considered distinct types, this is not possible.

However, if you were to export jsonChat by captializing it, this becomes possible:

desc := chat.JsonChat{
	Text: "Line 1\n",
	Color: "blue",
	Italic: true,
	Extra: []chat.JsonChat{{
		Text: "Line 2",
		Color: "green",
		Bold: true,
	}},
}

However, this requires modifying go-mc/chat/chatMsg.go. I would rather not modify this package directly, since it complicates development somewhat. It surely makes Docker builds much more complicated than simply go get-ing your package.

My use case for this is displaying formatted server messages to Minecraft clients in the server list. I am using go-mc to create a "stub" Minecraft server, which will be shown to my players when the real Minecraft server is offline. When no players are online, I want to shut down or "hibernate" my Minecraft server. Then, if a player tries to view the server when the real Minecraft server is offline, they will see messages created in the "stub" server I am writing in Go using go-mc. A player connecting to this "stub" server launches a request to start the real Minecraft server, which will shift the IP address to the real server and allow them to play.

In fact, using go-mc, and the above example code (after modifying chatMsg.go), I was able to create this stub server:

Example

While I can create two lines by simply including a \n in the main Text block, I enjoy how easy color and text formatting is with go-mc, and I would like to create lines of text with independent formatting from one another.

Is there a workaround to do this without modifying chatMsg.go? Or can jsonChat possibly be made public in a future release of go-mc?

Thanks!


(P.S. When writing this issue, I noticed a bug in the way go-mc formats messages. In my above example code, I set "Line 1" to Italic: true. However, as you can see from the screenshot, it is not italicized. Bold and Obfuscated formatting works, but not Italic. I have set text to be italicized in server messages before, so I know it is possible to do this. Perhaps this belongs in its own issue?)

Can't use v1.15 tag

I am trying to get the v1.15 version of the bot, but go will immediately change it to v1.15.1 in the go.mod file. Changing the version to v1.15.0 does not work either.

A solution would be to add a v1.15.0 tag for minecraft v1.15.

Invalid block id's in c.Wd.Chunk

I am using this library to write a farm bot and I noticed that the block ID's I was getting were wrong. At first I thought that it was an issue with my own code but when I dumped c.Wd.Chunks I noticed impossible id's like 6190 and 3999 in places where they should've been 152 and 89.

I dumped the chunk as follows.

var chunk = c.Wd.Chunks[world.ChunkLoc{X:chunkX, Z:chunkZ}]
var cString = fmt.Sprintf("%+v\n", chunk)
log.Println(cString)

Another thing that I noticed is that in order to get specific blocks out of the Chunk, attributes that are not exported (like Chunk.sections) need to be accessed. In the file world.go a function called getBlock exists that can do this, but in the current version it is commented out.

NBT Unknown type float64 slice

I am trying to read the data out of the playerdata file of a servers world.
By now I can read the data into my struct:

package reincarnation

import (
	"compress/gzip"
	"github.com/Tnze/go-mc/nbt"
	"github.com/zischknall/gomc-wrapper/pkg/gameserver"
	"io/ioutil"
	"log"
	"os"
	"strconv"
)

type entityData struct {
	Pos            []float64    `nbt:"Pos"`
	Motion         []float64    `nbt:"Motion"`
	Rotation       []float64    `nbt:"Rotation"`
	FallDistance   float64      `nbt:"FallDistance"`
	Fire           int          `nbt:"Fire"`
	Air            int          `nbt:"Air"`
	OnGround       byte         `nbt:"OnGround"`
	NoGravity      byte         `nbt:"NoGravity"`
	Dimension      int          `nbt:"Dimension"`
	Invulnerable   byte         `nbt:"Invulnerable"`
	PortalCooldown int          `nbt:"PortalCooldown"`
	UUIDMost       int64        `nbt:"UUIDMost"`
	UUIDLeast      int64        `nbt:"UUIDLeast"`
	Silent         byte         `nbt:"Silent"`
	Passengers     []entityData `nbt:"Passengers"`
	Glowing        byte         `nbt:"Glowing"`
	Tags           []string     `nbt:"Tags"`
}

type modifier struct {
	Name      string `nbt:"Name"`
	Amount    int64  `nbt:"Amount"`
	Operation int16  `nbt:"Operation"`
	UUIDMost  int64  `nbt:"UUIDMost"`
	UUIDLeast int64  `nbt:"UUIDLeast"`
}

type attribute struct {
	Name      string     `nbt:"Name"`
	Base      float64    `nbt:"Base"`
	Modifiers []modifier `nbt:"Modifiers"`
}

type effect struct {
	Id            int64   `nbt:"Id"`
	Amplifier     int16   `nbt:"Amplifier"`
	Duration      int64   `nbt:"Duration"`
	Ambient       byte    `nbt:"Ambient"`
	ShowParticles byte    `nbt:"ShowParticles"`
	ShowIcon      byte    `nbt:"ShowIcon"`
	HiddenEffect  *effect `nbt:"HiddenEffect"`
}

type item struct {
	Count int16    `nbt:"Count"`
	Slot  int16    `nbt:"Slot"`
	Id    int64    `nbt:"id"`
	Tag   []string `nbt:"tag"`
}

type recipeBook struct {
	Recipes                     []string `nbt:"recipes"`
	ToBeDisplayed               []string `nbt:"toBeDisplayed"`
	IsFilteringCraftable        byte     `nbt:"isFilteringCraftable"`
	IsGuiOpen                   byte     `nbt:"isGuiOpen"`
	IsFurnaceFilteringCraftable byte     `nbt:"isFurnaceFilteringCraftable"`
	IsFurnaceGuiOpen            byte     `nbt:"isFurnaceGuiOpen"`
}

type playerData struct {
	Pos              []float64    `nbt:"Pos"`
	Motion           []float64    `nbt:"Motion"`
	Rotation         []float64    `nbt:"Rotation"`
	FallDistance     float64      `nbt:"FallDistance"`
	Fire             int          `nbt:"Fire"`
	Air              int          `nbt:"Air"`
	OnGround         byte         `nbt:"OnGround"`
	NoGravity        byte         `nbt:"NoGravity"`
	Dimension        int          `nbt:"Dimension"`
	Invulnerable     byte         `nbt:"Invulnerable"`
	PortalCooldown   int          `nbt:"PortalCooldown"`
	UUIDMost         int64        `nbt:"UUIDMost"`
	UUIDLeast        int64        `nbt:"UUIDLeast"`
	Silent           byte         `nbt:"Silent"`
	Passengers       []entityData `nbt:"Passengers"`
	Glowing          byte         `nbt:"Glowing"`
	Tags             []string     `nbt:"Tags"`
	Health           float64      `nbt:"Health"`
	AbsorptionAmount float64      `nbt:"AbsorptionAmount"`
	HurtTime         int16        `nbt:"HurtTime"`
	HurtByTimestamp  int64        `nbt:"HurtByTimestamp"`
	DeathTime        int16        `nbt:"DeathTime"`
	FallFlying       byte         `nbt:"FallFlying"`
	SleepingX        float64      `nbt:"SleepingX"`
	SleepingY        float64      `nbt:"SleepingY"`
	SleepingZ        float64      `nbt:"SleepingZ"`
	Brain            struct {
		memories struct{} `nbt:"memories"`
	} `nbt:"Brain"`
	Attributes       []attribute `nbt:"Attributes"`
	ActiveEffects    []effect    `nbt:"ActiveEffects"`
	LeftHanded       byte        `nbt:"LeftHanded"`
	DataVersion      int         `nbt:"DataVersion"`
	PlayerGameType   int         `nbt:"playerGameType"`
	Score            int         `nbt:"Score"`
	SelectedItemSlot int         `nbt:"SelectedItemSlot"`
	SelectedItem     struct {
		Count int16    `nbt:"Count"`
		Id    int64    `nbt:"id"`
		Tag   []string `nbt:"tag"`
	} `nbt:"SelectedItem"`
	SpawnX              float64 `nbt:"SpawnX"`
	SpawnY              float64 `nbt:"SpawnY"`
	SpawnZ              float64 `nbt:"SpawnZ"`
	SpawnForced         byte    `nbt:"SpawnForced"`
	SleepTimer          int     `nbt:"SleepTimer"`
	FoodLevel           int     `nbt:"foodLevel"`
	FoodExhaustionLevel float64 `nbt:"foodExhaustionLevel"`
	FoodSaturationLevel float64 `nbt:"foodSaturationLevel"`
	FoodTickTimer       int     `nbt:"foodTickTimer"`
	XpLevel             int64   `nbt:"XpLevel"`
	XpP                 float64 `nbt:"XpP"`
	XpTotal             int64   `nbt:"XpTotal"`
	XpSeed              int64   `nbt:"XpSeed"`
	Inventory           []item  `nbt:"Inventory"`
	EnderItems          []item  `nbt:"EnderItems"`
	Abilities           struct {
		WalkSpeed    float64 `nbt:"walkSpeed"`
		FlySpeed     float64 `nbt:"flySpeed"`
		MayFly       byte    `nbt:"mayFlyx"`
		Flying       byte    `nbt:"flying"`
		Invulnerable byte    `nbt:"invulnerable"`
		MayBuild     byte    `nbt:"mayBuild"`
		InstaBuild   byte    `nbt:"instaBuild"`
	} `nbt:"abilities"`
	EnteredNetherPosition struct {
		X float64 `nbt:"x"`
		Y float64 `nbt:"y"`
		Z float64 `nbt:"z"`
	} `nbt:"enteredNetherPosition"`
	RootVehicle struct {
		AttachLeast int64      `nbt:"AttachLeast"`
		AttachMost  int64      `nbt:"AttachMost"`
		Entity      entityData `nbt:"Entity"`
	} `nbt:"RootVehicle"`
	ShoulderEntityLeft  entityData `nbt:"ShoulderEntityLeft"`
	ShoulderEntityRight entityData `nbt:"ShoulderEntityRight"`
	SeenCredits         byte       `nbt:"seenCredits"`
	RecipeBook          recipeBook `nbt:"recipeBook"`
}

func readPlayer(filepath string) playerData {
	f, err := os.Open(filepath)
	if err != nil {
		log.Fatal("[REINCARNATION] Can't open playerdata: " + filepath)
	}
	defer f.Close()

	r, err := gzip.NewReader(f)
	if err != nil {
		log.Fatal("[REINCARNATION] Error uncompressing file: " + filepath)
	}

	var result playerData
	if err := nbt.NewDecoder(r).Decode(&result); err != nil {
		log.Fatal(err)
	}
	return result
}

func writePlayer(filepath string, data playerData) {
	f, err := os.Create(filepath)
	if err != nil {
		log.Fatal("[REINCARNATION] Can't write new file!")
	}
	defer f.Close()

	r := gzip.NewWriter(f)

	if err := nbt.NewEncoder(r).Encode(data); err != nil {
		log.Fatal(err)
	}
}

func Init(server gameserver.MCServer) {
	playerstore := server.BasePath + "/world/playerdata/"
	fi, err := os.Stat(playerstore)
	if err != nil {
		log.Println("[REINCARNATION] Playerstore does not exist!")
	}
	if fi.Mode().IsRegular() {
		log.Println("[REINCARNATION] Playerstore does not exist!")
		return
	}

	players, err := ioutil.ReadDir(playerstore)
	if err != nil {
		log.Println("[REINCARNATION] Is the Playerstore empty?")
		return
	}

	for _, player := range players {
		data := readPlayer(playerstore + player.Name())
		if data.PlayerGameType != 0 {
			data.PlayerGameType = 0
			writePlayer(playerstore+player.Name(), data)
		}
		log.Println("[REINCARNATION] " + player.Name() + " " + strconv.FormatFloat(data.Pos[0], 'f', 2, 64))
	}
}

But when writing the data back into the file it will say: 2020/04/05 11:26:37 unknown type [3]float64 slice

And I think it is about complaining about the Pos slice which is a list of TagDouble.
It will read those in completely fine and the data is the same as my ingame position just writing in the writePlayer() function does not work.

连接中断时怎么自动重新连接?

有时我想中断连接,然后让程序再连接。我式了在 onDisconnect() 里放 c.JoinServer(), 但程序还是终止了。因该怎么做呢?

2019/09/13 02:19:51 Disconnect: Internal Exception: java.lang.ArrayIndexOutOfBoundsException: Index 17 out of bounds for length 7
2019/09/13 02:19:51 Login success
(终止)

no licence?

would you consider licencing this project?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.