001package net.minecraft.nbt; 002 003import java.io.DataInput; 004import java.io.DataOutput; 005import java.io.IOException; 006import java.util.Collection; 007import java.util.HashMap; 008import java.util.Iterator; 009import java.util.Map; 010import net.minecraft.crash.CrashReport; 011import net.minecraft.crash.CrashReportCategory; 012import net.minecraft.util.ReportedException; 013 014public class NBTTagCompound extends NBTBase 015{ 016 /** 017 * The key-value pairs for the tag. Each key is a UTF string, each value is a tag. 018 */ 019 private Map tagMap = new HashMap(); 020 021 public NBTTagCompound() 022 { 023 super(""); 024 } 025 026 public NBTTagCompound(String par1Str) 027 { 028 super(par1Str); 029 } 030 031 /** 032 * Write the actual data contents of the tag, implemented in NBT extension classes 033 */ 034 void write(DataOutput par1DataOutput) throws IOException 035 { 036 Iterator iterator = this.tagMap.values().iterator(); 037 038 while (iterator.hasNext()) 039 { 040 NBTBase nbtbase = (NBTBase)iterator.next(); 041 NBTBase.writeNamedTag(nbtbase, par1DataOutput); 042 } 043 044 par1DataOutput.writeByte(0); 045 } 046 047 /** 048 * Read the actual data contents of the tag, implemented in NBT extension classes 049 */ 050 void load(DataInput par1DataInput) throws IOException 051 { 052 this.tagMap.clear(); 053 NBTBase nbtbase; 054 055 while ((nbtbase = NBTBase.readNamedTag(par1DataInput)).getId() != 0) 056 { 057 this.tagMap.put(nbtbase.getName(), nbtbase); 058 } 059 } 060 061 /** 062 * Returns all the values in the tagMap HashMap. 063 */ 064 public Collection getTags() 065 { 066 return this.tagMap.values(); 067 } 068 069 /** 070 * Gets the type byte for the tag. 071 */ 072 public byte getId() 073 { 074 return (byte)10; 075 } 076 077 /** 078 * Stores the given tag into the map with the given string key. This is mostly used to store tag lists. 079 */ 080 public void setTag(String par1Str, NBTBase par2NBTBase) 081 { 082 this.tagMap.put(par1Str, par2NBTBase.setName(par1Str)); 083 } 084 085 /** 086 * Stores a new NBTTagByte with the given byte value into the map with the given string key. 087 */ 088 public void setByte(String par1Str, byte par2) 089 { 090 this.tagMap.put(par1Str, new NBTTagByte(par1Str, par2)); 091 } 092 093 /** 094 * Stores a new NBTTagShort with the given short value into the map with the given string key. 095 */ 096 public void setShort(String par1Str, short par2) 097 { 098 this.tagMap.put(par1Str, new NBTTagShort(par1Str, par2)); 099 } 100 101 /** 102 * Stores a new NBTTagInt with the given integer value into the map with the given string key. 103 */ 104 public void setInteger(String par1Str, int par2) 105 { 106 this.tagMap.put(par1Str, new NBTTagInt(par1Str, par2)); 107 } 108 109 /** 110 * Stores a new NBTTagLong with the given long value into the map with the given string key. 111 */ 112 public void setLong(String par1Str, long par2) 113 { 114 this.tagMap.put(par1Str, new NBTTagLong(par1Str, par2)); 115 } 116 117 /** 118 * Stores a new NBTTagFloat with the given float value into the map with the given string key. 119 */ 120 public void setFloat(String par1Str, float par2) 121 { 122 this.tagMap.put(par1Str, new NBTTagFloat(par1Str, par2)); 123 } 124 125 /** 126 * Stores a new NBTTagDouble with the given double value into the map with the given string key. 127 */ 128 public void setDouble(String par1Str, double par2) 129 { 130 this.tagMap.put(par1Str, new NBTTagDouble(par1Str, par2)); 131 } 132 133 /** 134 * Stores a new NBTTagString with the given string value into the map with the given string key. 135 */ 136 public void setString(String par1Str, String par2Str) 137 { 138 this.tagMap.put(par1Str, new NBTTagString(par1Str, par2Str)); 139 } 140 141 /** 142 * Stores a new NBTTagByteArray with the given array as data into the map with the given string key. 143 */ 144 public void setByteArray(String par1Str, byte[] par2ArrayOfByte) 145 { 146 this.tagMap.put(par1Str, new NBTTagByteArray(par1Str, par2ArrayOfByte)); 147 } 148 149 /** 150 * Stores a new NBTTagIntArray with the given array as data into the map with the given string key. 151 */ 152 public void setIntArray(String par1Str, int[] par2ArrayOfInteger) 153 { 154 this.tagMap.put(par1Str, new NBTTagIntArray(par1Str, par2ArrayOfInteger)); 155 } 156 157 /** 158 * Stores the given NBTTagCompound into the map with the given string key. 159 */ 160 public void setCompoundTag(String par1Str, NBTTagCompound par2NBTTagCompound) 161 { 162 this.tagMap.put(par1Str, par2NBTTagCompound.setName(par1Str)); 163 } 164 165 /** 166 * Stores the given boolean value as a NBTTagByte, storing 1 for true and 0 for false, using the given string key. 167 */ 168 public void setBoolean(String par1Str, boolean par2) 169 { 170 this.setByte(par1Str, (byte)(par2 ? 1 : 0)); 171 } 172 173 /** 174 * gets a generic tag with the specified name 175 */ 176 public NBTBase getTag(String par1Str) 177 { 178 return (NBTBase)this.tagMap.get(par1Str); 179 } 180 181 /** 182 * Returns whether the given string has been previously stored as a key in the map. 183 */ 184 public boolean hasKey(String par1Str) 185 { 186 return this.tagMap.containsKey(par1Str); 187 } 188 189 /** 190 * Retrieves a byte value using the specified key, or 0 if no such key was stored. 191 */ 192 public byte getByte(String par1Str) 193 { 194 try 195 { 196 return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagByte)this.tagMap.get(par1Str)).data; 197 } 198 catch (ClassCastException classcastexception) 199 { 200 throw new ReportedException(this.createCrashReport(par1Str, 1, classcastexception)); 201 } 202 } 203 204 /** 205 * Retrieves a short value using the specified key, or 0 if no such key was stored. 206 */ 207 public short getShort(String par1Str) 208 { 209 try 210 { 211 return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagShort)this.tagMap.get(par1Str)).data; 212 } 213 catch (ClassCastException classcastexception) 214 { 215 throw new ReportedException(this.createCrashReport(par1Str, 2, classcastexception)); 216 } 217 } 218 219 /** 220 * Retrieves an integer value using the specified key, or 0 if no such key was stored. 221 */ 222 public int getInteger(String par1Str) 223 { 224 try 225 { 226 return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagInt)this.tagMap.get(par1Str)).data; 227 } 228 catch (ClassCastException classcastexception) 229 { 230 throw new ReportedException(this.createCrashReport(par1Str, 3, classcastexception)); 231 } 232 } 233 234 /** 235 * Retrieves a long value using the specified key, or 0 if no such key was stored. 236 */ 237 public long getLong(String par1Str) 238 { 239 try 240 { 241 return !this.tagMap.containsKey(par1Str) ? 0L : ((NBTTagLong)this.tagMap.get(par1Str)).data; 242 } 243 catch (ClassCastException classcastexception) 244 { 245 throw new ReportedException(this.createCrashReport(par1Str, 4, classcastexception)); 246 } 247 } 248 249 /** 250 * Retrieves a float value using the specified key, or 0 if no such key was stored. 251 */ 252 public float getFloat(String par1Str) 253 { 254 try 255 { 256 return !this.tagMap.containsKey(par1Str) ? 0.0F : ((NBTTagFloat)this.tagMap.get(par1Str)).data; 257 } 258 catch (ClassCastException classcastexception) 259 { 260 throw new ReportedException(this.createCrashReport(par1Str, 5, classcastexception)); 261 } 262 } 263 264 /** 265 * Retrieves a double value using the specified key, or 0 if no such key was stored. 266 */ 267 public double getDouble(String par1Str) 268 { 269 try 270 { 271 return !this.tagMap.containsKey(par1Str) ? 0.0D : ((NBTTagDouble)this.tagMap.get(par1Str)).data; 272 } 273 catch (ClassCastException classcastexception) 274 { 275 throw new ReportedException(this.createCrashReport(par1Str, 6, classcastexception)); 276 } 277 } 278 279 /** 280 * Retrieves a string value using the specified key, or an empty string if no such key was stored. 281 */ 282 public String getString(String par1Str) 283 { 284 try 285 { 286 return !this.tagMap.containsKey(par1Str) ? "" : ((NBTTagString)this.tagMap.get(par1Str)).data; 287 } 288 catch (ClassCastException classcastexception) 289 { 290 throw new ReportedException(this.createCrashReport(par1Str, 8, classcastexception)); 291 } 292 } 293 294 /** 295 * Retrieves a byte array using the specified key, or a zero-length array if no such key was stored. 296 */ 297 public byte[] getByteArray(String par1Str) 298 { 299 try 300 { 301 return !this.tagMap.containsKey(par1Str) ? new byte[0] : ((NBTTagByteArray)this.tagMap.get(par1Str)).byteArray; 302 } 303 catch (ClassCastException classcastexception) 304 { 305 throw new ReportedException(this.createCrashReport(par1Str, 7, classcastexception)); 306 } 307 } 308 309 /** 310 * Retrieves an int array using the specified key, or a zero-length array if no such key was stored. 311 */ 312 public int[] getIntArray(String par1Str) 313 { 314 try 315 { 316 return !this.tagMap.containsKey(par1Str) ? new int[0] : ((NBTTagIntArray)this.tagMap.get(par1Str)).intArray; 317 } 318 catch (ClassCastException classcastexception) 319 { 320 throw new ReportedException(this.createCrashReport(par1Str, 11, classcastexception)); 321 } 322 } 323 324 /** 325 * Retrieves a NBTTagCompound subtag matching the specified key, or a new empty NBTTagCompound if no such key was 326 * stored. 327 */ 328 public NBTTagCompound getCompoundTag(String par1Str) 329 { 330 try 331 { 332 return !this.tagMap.containsKey(par1Str) ? new NBTTagCompound(par1Str) : (NBTTagCompound)this.tagMap.get(par1Str); 333 } 334 catch (ClassCastException classcastexception) 335 { 336 throw new ReportedException(this.createCrashReport(par1Str, 10, classcastexception)); 337 } 338 } 339 340 /** 341 * Retrieves a NBTTagList subtag matching the specified key, or a new empty NBTTagList if no such key was stored. 342 */ 343 public NBTTagList getTagList(String par1Str) 344 { 345 try 346 { 347 return !this.tagMap.containsKey(par1Str) ? new NBTTagList(par1Str) : (NBTTagList)this.tagMap.get(par1Str); 348 } 349 catch (ClassCastException classcastexception) 350 { 351 throw new ReportedException(this.createCrashReport(par1Str, 9, classcastexception)); 352 } 353 } 354 355 /** 356 * Retrieves a boolean value using the specified key, or false if no such key was stored. This uses the getByte 357 * method. 358 */ 359 public boolean getBoolean(String par1Str) 360 { 361 return this.getByte(par1Str) != 0; 362 } 363 364 /** 365 * Remove the specified tag. 366 */ 367 public void removeTag(String par1Str) 368 { 369 this.tagMap.remove(par1Str); 370 } 371 372 public String toString() 373 { 374 String s = this.getName() + ":["; 375 String s1; 376 377 for (Iterator iterator = this.tagMap.keySet().iterator(); iterator.hasNext(); s = s + s1 + ":" + this.tagMap.get(s1) + ",") 378 { 379 s1 = (String)iterator.next(); 380 } 381 382 return s + "]"; 383 } 384 385 /** 386 * Return whether this compound has no tags. 387 */ 388 public boolean hasNoTags() 389 { 390 return this.tagMap.isEmpty(); 391 } 392 393 /** 394 * Create a crash report which indicates a NBT read error. 395 */ 396 private CrashReport createCrashReport(String par1Str, int par2, ClassCastException par3ClassCastException) 397 { 398 CrashReport crashreport = CrashReport.makeCrashReport(par3ClassCastException, "Reading NBT data"); 399 CrashReportCategory crashreportcategory = crashreport.makeCategoryDepth("Corrupt NBT tag", 1); 400 crashreportcategory.addCrashSectionCallable("Tag type found", new CallableTagCompound1(this, par1Str)); 401 crashreportcategory.addCrashSectionCallable("Tag type expected", new CallableTagCompound2(this, par2)); 402 crashreportcategory.addCrashSection("Tag name", par1Str); 403 404 if (this.getName() != null && this.getName().length() > 0) 405 { 406 crashreportcategory.addCrashSection("Tag parent", this.getName()); 407 } 408 409 return crashreport; 410 } 411 412 /** 413 * Creates a clone of the tag. 414 */ 415 public NBTBase copy() 416 { 417 NBTTagCompound nbttagcompound = new NBTTagCompound(this.getName()); 418 Iterator iterator = this.tagMap.keySet().iterator(); 419 420 while (iterator.hasNext()) 421 { 422 String s = (String)iterator.next(); 423 nbttagcompound.setTag(s, ((NBTBase)this.tagMap.get(s)).copy()); 424 } 425 426 return nbttagcompound; 427 } 428 429 public boolean equals(Object par1Obj) 430 { 431 if (super.equals(par1Obj)) 432 { 433 NBTTagCompound nbttagcompound = (NBTTagCompound)par1Obj; 434 return this.tagMap.entrySet().equals(nbttagcompound.tagMap.entrySet()); 435 } 436 else 437 { 438 return false; 439 } 440 } 441 442 public int hashCode() 443 { 444 return super.hashCode() ^ this.tagMap.hashCode(); 445 } 446 447 /** 448 * Return the tag map for this compound. 449 */ 450 static Map getTagMap(NBTTagCompound par0NBTTagCompound) 451 { 452 return par0NBTTagCompound.tagMap; 453 } 454}