Skip to content
This repository
Browse code

Inital hack to support anvil format *.mca files

  • Loading branch information...
commit 80488e01982b8946b7c3f6a91a52638e4ad05c4d 1 parent fc6b447
Jonathan Wright authored
2  cmd/mcobj/mcobj.go
@@ -370,7 +370,7 @@ type Blocks struct {
370 370 type BlockColumn []nbt.Block
371 371
372 372 func (b *Blocks) Get(x, y, z int) nbt.Block {
373   - return b.data[y+(z*b.height+(x*b.height*16))]
  373 + return b.data[y+b.height*(z+16*x)]
374 374 }
375 375
376 376 func (b *Blocks) Column(x, z int) BlockColumn {
2  cmd/mcobj/obj.go
@@ -387,7 +387,7 @@ func (vs *Vertexes) Print(w io.Writer, xPos, zPos int) (count int) {
387 387
388 388 var (
389 389 xa = x + xPos*16
390   - ya = y - vs.height/2
  390 + ya = y - 64
391 391 za = z + zPos*16
392 392 )
393 393
2  cmd/mcobj/prt.go
@@ -84,7 +84,7 @@ func (o *PrtGenerator) chunkProcessor() {
84 84 o.particleCount++
85 85 var (
86 86 xa = x + e.xPos*16
87   - ya = y - height/2
  87 + ya = y - 64
88 88 za = -(z + e.zPos*16)
89 89 )
90 90 binary.Write(o.zw, binary.LittleEndian, float32(xa))
12 mcworld/betaworld.go
@@ -31,18 +31,16 @@ func (w *BetaWorld) OpenChunk(x, z int) (io.ReadCloser, error) {
31 31 mcrName := fmt.Sprintf("r.%v.%v.mcr", x>>5, z>>5)
32 32 mcrPath := filepath.Join(w.worldDir, "region", mcrName)
33 33
34   - var name, path string
  34 + var path string
35 35 if _, err := os.Stat(mcaPath); err == nil {
36   - name = mcaName
37 36 path = mcaPath
38 37 } else {
39   - name = mcrName
40 38 path = mcrPath
41 39 }
42 40
43   - var file, mcrOpenErr = os.Open(path)
44   - if mcrOpenErr != nil {
45   - return nil, mcrOpenErr
  41 + file, openErr := os.Open(path)
  42 + if openErr != nil {
  43 + return nil, openErr
46 44 }
47 45 defer func() {
48 46 if file != nil {
@@ -57,7 +55,7 @@ func (w *BetaWorld) OpenChunk(x, z int) (io.ReadCloser, error) {
57 55 }
58 56
59 57 if loc == 0 {
60   - return nil, errors.New(fmt.Sprintf("Chunk missing: %v,%v in %v. %v", x, z, name, (x&31)+(z&31)*32))
  58 + return nil, errors.New(fmt.Sprintf("Chunk missing: %v,%v in %v. %v", x, z, mcaName, (x&31)+(z&31)*32))
61 59 }
62 60
63 61 var (
91 nbt/chunk.go
@@ -28,32 +28,79 @@ func ReadChunkDat(reader io.Reader) (*Chunk, error) {
28 28
29 29 func ReadChunkNbt(reader io.Reader) (*Chunk, error) {
30 30 chunkData := new(chunkData)
  31 + chunkData.sections = make([]*sectionData, 0)
31 32 if err := chunkData.parse(NewReader(reader), false); err != nil {
32 33 return nil, err
33 34 }
34 35
35 36 chunk := &Chunk{chunkData.xPos, chunkData.zPos, nil}
36 37
37   - if chunkData.blocks != nil && chunkData.data != nil {
38   - chunk.Blocks = make([]Block, len(chunkData.blocks))
39   - for i, blockId := range chunkData.blocks {
40   - var metadata byte
41   - if i&1 == 1 {
42   - metadata = chunkData.data[i/2] >> 4
43   - } else {
44   - metadata = chunkData.data[i/2] & 0xf
  38 + if len(chunkData.sections) != 0 {
  39 + chunk.Blocks = make([]Block, 256*16*16) // Hard coded height for now. TODO: Make variable height chunks.
  40 + for _, section := range chunkData.sections {
  41 + for i, blockId := range section.blocks {
  42 + var metadata byte
  43 + if i&1 == 1 {
  44 + metadata = section.data[i/2] >> 4
  45 + } else {
  46 + metadata = section.data[i/2] & 0xf
  47 + }
  48 + // Note that the old format is XZY and the new format is YZX
  49 + x, z, y := indexToCoords(i, 16, 16)
  50 + chunk.Blocks[coordsToIndex(x, z, y+16*section.y, 16, 256)] = Block(blockId) + (Block(metadata) << 8)
  51 + }
  52 + }
  53 + } else {
  54 + if chunkData.blocks != nil && chunkData.data != nil {
  55 + chunk.Blocks = make([]Block, len(chunkData.blocks))
  56 + for i, blockId := range chunkData.blocks {
  57 + var metadata byte
  58 + if i&1 == 1 {
  59 + metadata = chunkData.data[i/2] >> 4
  60 + } else {
  61 + metadata = chunkData.data[i/2] & 0xf
  62 + }
  63 + chunk.Blocks[i] = Block(blockId) + (Block(metadata) << 8)
45 64 }
46   - chunk.Blocks[i] = Block(blockId) + (Block(metadata) << 8)
47 65 }
48 66 }
49 67
50 68 return chunk, nil
51 69 }
52 70
  71 +func indexToCoords(i, aMax, bMax int) (a, b, c int) {
  72 + a = i % aMax
  73 + b = (i / aMax) % bMax
  74 + c = i / (aMax*bMax)
  75 + return
  76 +}
  77 +
  78 +func coordsToIndex(a, b, c, bMax, cMax int) int {
  79 + return c + cMax*(b + bMax*a)
  80 +}
  81 +
  82 +func yzxToXzy(yzx, xMax, zMax, yMax int) int {
  83 + x := yzx % xMax
  84 + z := (yzx / xMax) % zMax
  85 + y := (yzx / (xMax*zMax)) % yMax
  86 +
  87 + // yzx := x + xMax*(z + zMax*y)
  88 + xzy := y + yMax*(z + zMax*x)
  89 + return xzy
  90 +}
  91 +
53 92 type chunkData struct {
54 93 xPos, zPos int
55 94 blocks []byte
56 95 data []byte
  96 + section *sectionData
  97 + sections []*sectionData
  98 +}
  99 +
  100 +type sectionData struct {
  101 + y int
  102 + blocks []byte
  103 + data []byte
57 104 }
58 105
59 106 func (chunk *chunkData) parse(r *Reader, listStruct bool) error {
@@ -85,15 +132,31 @@ func (chunk *chunkData) parse(r *Reader, listStruct bool) error {
85 132 return err
86 133 }
87 134 if name == "Blocks" {
88   - chunk.blocks = bytes
  135 + if chunk.section != nil {
  136 + chunk.section.blocks = bytes
  137 + } else {
  138 + chunk.blocks = bytes
  139 + }
89 140 } else if name == "Data" {
90   - chunk.data = bytes
  141 + if chunk.section != nil {
  142 + chunk.section.data = bytes
  143 + } else {
  144 + chunk.data = bytes
  145 + }
  146 + }
  147 + case TagIntArray:
  148 + _, err := r.ReadInts()
  149 + if err != nil {
  150 + return err
91 151 }
92 152 case TagInt8:
93   - _, err := r.ReadInt8()
  153 + number, err := r.ReadInt8()
94 154 if err != nil {
95 155 return err
96 156 }
  157 + if name == "Y" {
  158 + chunk.section.y = int(number)
  159 + }
97 160 case TagInt16:
98 161 _, err := r.ReadInt16()
99 162 if err != nil {
@@ -160,6 +223,10 @@ func (chunk *chunkData) parse(r *Reader, listStruct bool) error {
160 223 }
161 224 case TagStruct:
162 225 for i := 0; i < length; i++ {
  226 + if name == "Sections" {
  227 + chunk.section = new(sectionData)
  228 + chunk.sections = append(chunk.sections, chunk.section)
  229 + }
163 230 err := chunk.parse(r, true)
164 231 if err != nil {
165 232 return err
17 nbt/nbt.go
@@ -22,6 +22,7 @@ const (
22 22 TagString TypeId = 8 // { TAG_Short length; An array of bytes defining a string in UTF-8 format. The length of this array is <length> bytes }
23 23 TagList TypeId = 9 // { TAG_Byte tagId; TAG_Int length; A sequential list of Tags (not Named Tags), of type <typeId>. The length of this array is <length> Tags. } Notes: All tags share the same type.
24 24 TagStruct TypeId = 10 // { A sequential list of Named Tags. This array keeps going until a TAG_End is found.; TAG_End end } Notes: If there's a nested TAG_Compound within this tag, that one will also have a TAG_End, so simply reading until the next TAG_End will not work. The names of the named tags have to be unique within each TAG_Compound The order of the tags is not guaranteed.
  25 + TagIntArray TypeId = 11 // { TAG_Int length; An array of ints. The length of this array is <length> ints }
25 26 )
26 27
27 28 type Reader struct {
@@ -93,6 +94,22 @@ func (r *Reader) ReadBytes() ([]byte, error) {
93 94 return bytes, err
94 95 }
95 96
  97 +func (r *Reader) ReadInts() ([]int, error) {
  98 + length, err := r.ReadInt32()
  99 + if err != nil {
  100 + return nil, err
  101 + }
  102 +
  103 + ints := make([]int, length)
  104 + for i := 0; i < length; i++ {
  105 + ints[i], err = r.ReadInt32()
  106 + if err != nil {
  107 + return nil, err
  108 + }
  109 + }
  110 + return ints, nil
  111 +}
  112 +
96 113 func (r *Reader) ReadInt8() (int, error) {
97 114 return r.readIntN(1)
98 115 }

0 comments on commit 80488e0

Please sign in to comment.
Something went wrong with that request. Please try again.