diff --git a/bot/ingame.go b/bot/ingame.go index a8742a4..afa2cbc 100644 --- a/bot/ingame.go +++ b/bot/ingame.go @@ -2,6 +2,7 @@ package bot import ( "bytes" + "errors" "fmt" "io/ioutil" @@ -36,12 +37,12 @@ func (c *Client) HandleGame() error { //Read packets p, err := c.conn.ReadPacket() if err != nil { - return fmt.Errorf("bot: read packet fail: %v", err) + return fmt.Errorf("bot: read packet fail: %w", err) } //handle packets disconnect, err := c.handlePacket(p) if err != nil { - return fmt.Errorf("handle packet 0x%X error: %v", p.ID, err) + return fmt.Errorf("handle packet 0x%X error: %w", p.ID, err) } if disconnect { return nil @@ -201,7 +202,7 @@ func handleSetSlotPacket(c *Client, p pk.Packet) error { slotI pk.Short slot entity.Slot ) - if err := p.Scan(&windowID, &slotI, &slot); err != nil && err != nbt.ErrEND { + if err := p.Scan(&windowID, &slotI, &slot); err != nil && !errors.Is(err, nbt.ErrEND) { return err } @@ -451,7 +452,7 @@ func handleChunkDataPacket(c *Client, p pk.Packet) error { } chunk, err := world.DecodeChunkColumn(int32(PrimaryBitMask), Data) if err != nil { - return fmt.Errorf("decode chunk column fail: %v", err) + return fmt.Errorf("decode chunk column fail: %w", err) } c.Wd.LoadChunk(int(X), int(Z), chunk) @@ -588,7 +589,7 @@ func handleWindowItemsPacket(c *Client, p pk.Packet) (err error) { } for i := 0; i < int(count); i++ { var slot entity.Slot - if err := slot.Decode(r); err != nil && err != nbt.ErrEND { + if err := slot.Decode(r); err != nil && !errors.Is(err, nbt.ErrEND) { return err } slots = append(slots, slot) diff --git a/bot/world/chunk.go b/bot/world/chunk.go index 572d94f..2d2a97a 100644 --- a/bot/world/chunk.go +++ b/bot/world/chunk.go @@ -82,8 +82,8 @@ func fillSection(s *Section, bpb uint, DataArray []int64, palette []uint) { data := uint(DataArray[offset/64]) data >>= offset % 64 if offset%64 > 64-bpb { - l := bpb + offset%64 - 64 - data &= uint(DataArray[offset/64+1] << l) + l := 64 - offset % 64 + data |= uint(DataArray[offset/64+1] << l) } data &= mask diff --git a/cmd/mcadump/mcadump.go b/cmd/mcadump/mcadump.go index eccfdfc..ee96be1 100644 --- a/cmd/mcadump/mcadump.go +++ b/cmd/mcadump/mcadump.go @@ -23,7 +23,7 @@ func main() { args := flag.Args() var o string - o = "."// output dir + o = "." // output dir if len(args) < 2 { usage() } @@ -44,7 +44,7 @@ func main() { } func usage() { - _, _ = fmt.Fprintf(os.Stderr, "usage: %s [-x] [-r] r...mc{a,c}\n", flag.Arg(0)) + _, _ = fmt.Fprintf(os.Stderr, "usage: %s [-x] [-r] r...mc{a,c}\n", os.Args[0]) os.Exit(1) } diff --git a/cmd/mcping/README.md b/cmd/mcping/README.md index 76c8b30..c087b52 100644 --- a/cmd/mcping/README.md +++ b/cmd/mcping/README.md @@ -1,5 +1,10 @@ # mcping -适用于Minecraft: Java Edition的ping工具 + +Ping tool for Minecraft: Java Edition. +Just for example. Not recommended for daily use. Use [github.com/go-mc/mcping](github.com/go-mc/mcping) instead, which including SRV parse. + +适用于Minecraft: Java Edition的ping工具。 +只起示例作用,日常使用建议使用完整版[github.com/go-mc/mcping](github.com/go-mc/mcping),包含SRV解析等功能。 Install with go tools: ```go get -u github.com/Tnze/go-mc/cmd/mcping``` diff --git a/go.mod b/go.mod index 5bf52ac..d2206fc 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/Tnze/go-mc -go 1.12 +go 1.13 require github.com/google/uuid v1.1.1 diff --git a/nbt/interface_test.go b/nbt/interface_test.go deleted file mode 100644 index 41ad9a7..0000000 --- a/nbt/interface_test.go +++ /dev/null @@ -1 +0,0 @@ -package nbt diff --git a/nbt/marshal.go b/nbt/marshal.go index d19d336..a3da95e 100644 --- a/nbt/marshal.go +++ b/nbt/marshal.go @@ -106,6 +106,81 @@ func (e *Encoder) marshal(val reflect.Value, tagName string) error { } } + case reflect.Int16: + if err := e.writeTag(TagList, tagName); err != nil { + return err + } + if _, err := e.w.Write([]byte{TagShort}); err != nil { + return err + } + n := val.Len() + if err := e.writeInt32(int32(n)); err != nil { + return err + } + for i := 0; i < n; i++ { + if err := e.writeInt16(int16(val.Index(i).Int())); err != nil { + return err + } + } + + case reflect.Float32: + if err := e.writeTag(TagList, tagName); err != nil { + return err + } + if _, err := e.w.Write([]byte{TagFloat}); err != nil { + return err + } + n := val.Len() + if err := e.writeInt32(int32(n)); err != nil { + return err + } + for i := 0; i < n; i++ { + if err := e.writeInt32(int32(math.Float32bits(float32(val.Index(i).Float())))); err != nil { + return err + } + } + + case reflect.Float64: + if err := e.writeTag(TagList, tagName); err != nil { + return err + } + if _, err := e.w.Write([]byte{TagFloat}); err != nil { + return err + } + n := val.Len() + if err := e.writeInt32(int32(n)); err != nil { + return err + } + for i := 0; i < n; i++ { + if err := e.writeInt64(int64(math.Float64bits(val.Index(i).Float()))); err != nil { + return err + } + } + + case reflect.String: + if err := e.writeTag(TagList, tagName); err != nil { + return err + } + if _, err := e.w.Write([]byte{TagString}); err != nil { + return err + } + n := val.Len() + // Write length of strings + if err := e.writeInt32(int32(n)); err != nil { + return err + } + for i := 0; i < n; i++ { + // Write length of this string + s := val.Index(i).String() + if err := e.writeInt16(int16(len(s))); err != nil { + return err + } + // Write string + if _, err := e.w.Write([]byte(s)); err != nil { + return err + } + } + default: return errors.New("unknown type " + val.Type().String() + " slice") } diff --git a/nbt/marshal_test.go b/nbt/marshal_test.go new file mode 100644 index 0000000..b1db812 --- /dev/null +++ b/nbt/marshal_test.go @@ -0,0 +1,57 @@ +package nbt + +import ( + "bytes" + "math" + "testing" +) + +func TestMarshal_IntArray(t *testing.T) { + // Test marshal pure Int array + v := []int32{0, -10, 3} + out := []byte{TagIntArray, 0x00, 0x00, 0, 0, 0, 3, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x03, + } + var buf bytes.Buffer + if err := Marshal(&buf, v); err != nil { + t.Error(err) + } else if !bytes.Equal(buf.Bytes(), out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } + + // Test marshal in a struct + v2 := struct { + Ary []int32 `nbt:"ary"` + }{[]int32{0, -10, 3}} + out = []byte{TagCompound, 0x00, 0x00, + TagIntArray, 0x00, 0x03, 'a', 'r', 'y', 0, 0, 0, 3, + 0x00, 0x00, 0x00, 0x00, // 0 + 0xff, 0xff, 0xff, 0xf6, // -10 + 0x00, 0x00, 0x00, 0x03, // 3 + TagEnd, + } + buf.Reset() + if err := Marshal(&buf, v2); err != nil { + t.Error(err) + } else if !bytes.Equal(buf.Bytes(), out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } +} + +func TestMarshal_FloatArray(t *testing.T) { + // Test marshal pure Int array + v := []float32{0.3, -100, float32(math.NaN())} + out := []byte{TagList, 0x00, 0x00, TagFloat, 0, 0, 0, 3, + 0x3e, 0x99, 0x99, 0x9a, // 0.3 + 0xc2, 0xc8, 0x00, 0x00, // -100 + 0x7f, 0xc0, 0x00, 0x00, // NaN + } + var buf bytes.Buffer + if err := Marshal(&buf, v); err != nil { + t.Error(err) + } else if !bytes.Equal(buf.Bytes(), out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } +} diff --git a/nbt/read.go b/nbt/read.go index 251d83c..53ed54a 100644 --- a/nbt/read.go +++ b/nbt/read.go @@ -23,7 +23,7 @@ func (d *Decoder) Decode(v interface{}) error { //start read NBT tagType, tagName, err := d.readTag() if err != nil { - return fmt.Errorf("nbt: %v", err) + return fmt.Errorf("nbt: %w", err) } if c := d.checkCompressed(tagType); c != "" { @@ -32,7 +32,7 @@ func (d *Decoder) Decode(v interface{}) error { err = d.unmarshal(val.Elem(), tagType, tagName) if err != nil { - return fmt.Errorf("nbt: %v", err) + return fmt.Errorf("nbt: fail to decode tag %q: %w", tagName, err) } return nil } @@ -304,7 +304,7 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err if field != -1 { err = d.unmarshal(val.Field(field), tt, tn) if err != nil { - return err + return fmt.Errorf("fail to decode tag %q: %w", tn, err) } } else { if err := d.rawRead(tt); err != nil { @@ -329,7 +329,7 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err } v := reflect.New(val.Type().Elem()) if err = d.unmarshal(v.Elem(), tt, tn); err != nil { - return err + return fmt.Errorf("fail to decode tag %q: %w", tn, err) } val.SetMapIndex(reflect.ValueOf(tn), v.Elem()) } @@ -345,7 +345,7 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err } var value interface{} if err = d.unmarshal(reflect.ValueOf(&value).Elem(), tt, tn); err != nil { - return err + return fmt.Errorf("fail to decode tag %q: %w", tn, err) } buf[tn] = value }