1 package nbt // import "vimagination.zapto.org/minecraft/nbt" 2 3 import ( 4 "io" 5 6 "vimagination.zapto.org/byteio" 7 ) 8 9 // Encoder is a type used to encode NBT streams 10 type Encoder struct { 11 w byteio.EndianWriter 12 } 13 14 // NewEncoder returns an Encoder using Big Endian 15 func NewEncoder(w io.Writer) Encoder { 16 return NewEncoderEndian(&byteio.BigEndianWriter{Writer: w}) 17 } 18 19 // NewEncoderEndian allows you to specify your own Endian Writer 20 func NewEncoderEndian(e byteio.EndianWriter) Encoder { 21 return Encoder{w: e} 22 } 23 24 // Encode will encode a single tag to the writer using the default settings 25 func Encode(w io.Writer, t Tag) error { 26 return NewEncoder(w).Encode(t) 27 } 28 29 // Encode will encode a whole tag to the encoding stream 30 func (e Encoder) Encode(t Tag) error { 31 tagType := t.TagID() 32 _, err := e.w.WriteUint8(uint8(tagType)) 33 if err != nil { 34 return WriteError{"named TagId", err} 35 } 36 if tagType == TagEnd { 37 return nil 38 } 39 s := String(t.name) 40 err = e.encodeString(s) 41 if err != nil { 42 return err 43 } 44 return e.encodeData(t.data) 45 } 46 47 func (e Encoder) encodeData(d Data) error { 48 var err error 49 switch d := d.(type) { 50 case Byte: 51 err = e.encodeByte(d) 52 case Short: 53 err = e.encodeShort(d) 54 case Int: 55 err = e.encodeInt(d) 56 case Long: 57 err = e.encodeLong(d) 58 case Float: 59 err = e.encodeFloat(d) 60 case Double: 61 err = e.encodeDouble(d) 62 case ByteArray: 63 err = e.encodeByteArray(d) 64 case String: 65 err = e.encodeString(d) 66 case *ListData: 67 err = e.encodeList(d) 68 case Compound: 69 err = e.encodeCompound(d) 70 case IntArray: 71 err = e.encodeIntArray(d) 72 case Bool: 73 err = e.encodeBool(d) 74 case Uint8: 75 err = e.encodeUint8(d) 76 case Uint16: 77 err = e.encodeUint16(d) 78 case Uint32: 79 err = e.encodeUint32(d) 80 case Uint64: 81 err = e.encodeUint64(d) 82 case Complex64: 83 err = e.encodeComplex64(d) 84 case Complex128: 85 err = e.encodeComplex128(d) 86 default: 87 if l, ok := d.(List); ok { 88 err = e.encodeList(l) 89 } else { 90 err = UnknownTag{d.Type()} 91 } 92 } 93 return err 94 } 95 96 // EncodeByte will write a single Byte Data 97 func (e Encoder) encodeByte(b Byte) error { 98 _, err := e.w.WriteInt8(int8(b)) 99 return err 100 } 101 102 // EncodeShort will write a single Short Data 103 func (e Encoder) encodeShort(s Short) error { 104 _, err := e.w.WriteInt16(int16(s)) 105 return err 106 } 107 108 // EncodeInt will write a single Int Data 109 func (e Encoder) encodeInt(i Int) error { 110 _, err := e.w.WriteInt32(int32(i)) 111 return err 112 } 113 114 // EncodeLong will write a single Long Data 115 func (e Encoder) encodeLong(l Long) error { 116 _, err := e.w.WriteInt64(int64(l)) 117 return err 118 } 119 120 // EncodeFloat will write a single Float Data 121 func (e Encoder) encodeFloat(f Float) error { 122 _, err := e.w.WriteFloat32(float32(f)) 123 return err 124 } 125 126 // EncodeDouble will write a single Double Data 127 func (e Encoder) encodeDouble(do Double) error { 128 _, err := e.w.WriteFloat64(float64(do)) 129 return err 130 } 131 132 // EncodeByteArray will write a ByteArray Data 133 func (e Encoder) encodeByteArray(ba ByteArray) error { 134 _, err := e.w.WriteUint32(uint32(len(ba))) 135 if err != nil { 136 return err 137 } 138 _, err = e.w.Write(ba.Bytes()) 139 return err 140 } 141 142 // EncodeString will write a String Data 143 func (e Encoder) encodeString(s String) error { 144 _, err := e.w.WriteString16(string(s)) 145 return err 146 } 147 148 // EncodeList will write a List Data 149 func (e Encoder) encodeList(l List) error { 150 tagType := l.TagType() 151 _, err := e.w.WriteUint8(uint8(tagType)) 152 if err != nil { 153 return err 154 } 155 _, err = e.w.WriteUint32(uint32(l.Len())) 156 if err != nil { 157 return err 158 } 159 if l.TagType() != TagEnd { 160 for i := 0; i < l.Len(); i++ { 161 data := l.Get(i) 162 if tagID := data.Type(); tagID != tagType { 163 return WrongTag{tagType, tagID} 164 } 165 err = e.encodeData(data) 166 if err != nil { 167 return err 168 } 169 } 170 } 171 return nil 172 } 173 174 // EncodeCompound will write a Compound Data 175 func (e Encoder) encodeCompound(c Compound) error { 176 for _, data := range c { 177 if data.TagID() == TagEnd { 178 break 179 } 180 err := e.Encode(data) 181 if err != nil { 182 return err 183 } 184 } 185 _, err := e.w.Write([]byte{byte(TagEnd)}) 186 return err 187 } 188 189 // EncodeIntArray will write a IntArray Data 190 func (e Encoder) encodeIntArray(ints IntArray) error { 191 _, err := e.w.WriteUint32(uint32(len(ints))) 192 if err != nil { 193 return err 194 } 195 for _, i := range ints { 196 _, err = e.w.WriteInt32(i) 197 if err != nil { 198 return err 199 } 200 } 201 return nil 202 } 203 204 func (e Encoder) encodeBool(b Bool) error { 205 var err error 206 if b { 207 _, err = e.w.WriteUint8(1) 208 } else { 209 _, err = e.w.WriteUint8(0) 210 } 211 return err 212 } 213 214 func (e Encoder) encodeUint8(u Uint8) error { 215 _, err := e.w.WriteUint8(uint8(u)) 216 return err 217 } 218 219 func (e Encoder) encodeUint16(u Uint16) error { 220 _, err := e.w.WriteUint16(uint16(u)) 221 return err 222 } 223 224 func (e Encoder) encodeUint32(u Uint32) error { 225 _, err := e.w.WriteUint32(uint32(u)) 226 return err 227 } 228 229 func (e Encoder) encodeUint64(u Uint64) error { 230 _, err := e.w.WriteUint64(uint64(u)) 231 return err 232 } 233 234 func (e Encoder) encodeComplex64(c Complex64) error { 235 _, err := e.w.WriteFloat32(real(c)) 236 if err != nil { 237 return err 238 } 239 _, err = e.w.WriteFloat32(imag(c)) 240 return err 241 } 242 243 func (e Encoder) encodeComplex128(c Complex128) error { 244 _, err := e.w.WriteFloat64(real(c)) 245 if err != nil { 246 return err 247 } 248 _, err = e.w.WriteFloat64(imag(c)) 249 return err 250 } 251