package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.ReportedException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class NBTTagCompound extends NBTBase
{
private static final Logger logger = LogManager.getLogger();
/** The key-value pairs for the tag. Each key is a UTF string, each value is a tag. */
private Map tagMap = new HashMap();
private static final String __OBFID = "CL_00001215";
/**
* Write the actual data contents of the tag, implemented in NBT extension classes
*/
void write(DataOutput output) throws IOException
{
Iterator iterator = this.tagMap.keySet().iterator();
while (iterator.hasNext())
{
String s = (String)iterator.next();
NBTBase nbtbase = (NBTBase)this.tagMap.get(s);
writeEntry(s, nbtbase, output);
}
output.writeByte(0);
}
void read(DataInput input, int depth, NBTSizeTracker sizeTracker) throws IOException
{
if (depth > 512)
{
throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512");
}
else
{
this.tagMap.clear();
byte b0;
while ((b0 = readType(input, sizeTracker)) != 0)
{
String s = readKey(input, sizeTracker);
NBTSizeTracker.readUTF(sizeTracker, s); // Forge: Correctly read String length including header.
NBTBase nbtbase = readNBT(b0, s, input, depth + 1, sizeTracker);
this.tagMap.put(s, nbtbase);
}
}
}
/**
* Gets a set with the names of the keys in the tag compound.
*/
public Set getKeySet()
{
return this.tagMap.keySet();
}
/**
* Gets the type byte for the tag.
*/
public byte getId()
{
return (byte)10;
}
/**
* Stores the given tag into the map with the given string key. This is mostly used to store tag lists.
*/
public void setTag(String key, NBTBase value)
{
this.tagMap.put(key, value);
}
/**
* Stores a new NBTTagByte with the given byte value into the map with the given string key.
*/
public void setByte(String key, byte value)
{
this.tagMap.put(key, new NBTTagByte(value));
}
/**
* Stores a new NBTTagShort with the given short value into the map with the given string key.
*/
public void setShort(String key, short value)
{
this.tagMap.put(key, new NBTTagShort(value));
}
/**
* Stores a new NBTTagInt with the given integer value into the map with the given string key.
*/
public void setInteger(String key, int value)
{
this.tagMap.put(key, new NBTTagInt(value));
}
/**
* Stores a new NBTTagLong with the given long value into the map with the given string key.
*/
public void setLong(String key, long value)
{
this.tagMap.put(key, new NBTTagLong(value));
}
/**
* Stores a new NBTTagFloat with the given float value into the map with the given string key.
*/
public void setFloat(String key, float value)
{
this.tagMap.put(key, new NBTTagFloat(value));
}
/**
* Stores a new NBTTagDouble with the given double value into the map with the given string key.
*/
public void setDouble(String key, double value)
{
this.tagMap.put(key, new NBTTagDouble(value));
}
/**
* Stores a new NBTTagString with the given string value into the map with the given string key.
*/
public void setString(String key, String value)
{
this.tagMap.put(key, new NBTTagString(value));
}
/**
* Stores a new NBTTagByteArray with the given array as data into the map with the given string key.
*/
public void setByteArray(String key, byte[] value)
{
this.tagMap.put(key, new NBTTagByteArray(value));
}
/**
* Stores a new NBTTagIntArray with the given array as data into the map with the given string key.
*/
public void setIntArray(String key, int[] value)
{
this.tagMap.put(key, new NBTTagIntArray(value));
}
/**
* Stores the given boolean value as a NBTTagByte, storing 1 for true and 0 for false, using the given string key.
*/
public void setBoolean(String key, boolean value)
{
this.setByte(key, (byte)(value ? 1 : 0));
}
/**
* gets a generic tag with the specified name
*/
public NBTBase getTag(String key)
{
return (NBTBase)this.tagMap.get(key);
}
/**
* Gets the ID byte for the given tag key
*/
public byte getTagId(String key)
{
NBTBase nbtbase = (NBTBase)this.tagMap.get(key);
return nbtbase != null ? nbtbase.getId() : 0;
}
/**
* Returns whether the given string has been previously stored as a key in the map.
*/
public boolean hasKey(String key)
{
return this.tagMap.containsKey(key);
}
public boolean hasKey(String key, int type)
{
byte b0 = this.getTagId(key);
return b0 == type ? true : (type != 99 ? false : b0 == 1 || b0 == 2 || b0 == 3 || b0 == 4 || b0 == 5 || b0 == 6);
}
/**
* Retrieves a byte value using the specified key, or 0 if no such key was stored.
*/
public byte getByte(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0 : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getByte();
}
catch (ClassCastException classcastexception)
{
return (byte)0;
}
}
/**
* Retrieves a short value using the specified key, or 0 if no such key was stored.
*/
public short getShort(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0 : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getShort();
}
catch (ClassCastException classcastexception)
{
return (short)0;
}
}
/**
* Retrieves an integer value using the specified key, or 0 if no such key was stored.
*/
public int getInteger(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0 : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getInt();
}
catch (ClassCastException classcastexception)
{
return 0;
}
}
/**
* Retrieves a long value using the specified key, or 0 if no such key was stored.
*/
public long getLong(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0L : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getLong();
}
catch (ClassCastException classcastexception)
{
return 0L;
}
}
/**
* Retrieves a float value using the specified key, or 0 if no such key was stored.
*/
public float getFloat(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0.0F : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getFloat();
}
catch (ClassCastException classcastexception)
{
return 0.0F;
}
}
/**
* Retrieves a double value using the specified key, or 0 if no such key was stored.
*/
public double getDouble(String key)
{
try
{
return !this.tagMap.containsKey(key) ? 0.0D : ((NBTBase.NBTPrimitive)this.tagMap.get(key)).getDouble();
}
catch (ClassCastException classcastexception)
{
return 0.0D;
}
}
/**
* Retrieves a string value using the specified key, or an empty string if no such key was stored.
*/
public String getString(String key)
{
try
{
return !this.tagMap.containsKey(key) ? "" : ((NBTBase)this.tagMap.get(key)).getString();
}
catch (ClassCastException classcastexception)
{
return "";
}
}
/**
* Retrieves a byte array using the specified key, or a zero-length array if no such key was stored.
*/
public byte[] getByteArray(String key)
{
try
{
return !this.tagMap.containsKey(key) ? new byte[0] : ((NBTTagByteArray)this.tagMap.get(key)).getByteArray();
}
catch (ClassCastException classcastexception)
{
throw new ReportedException(this.createCrashReport(key, 7, classcastexception));
}
}
/**
* Retrieves an int array using the specified key, or a zero-length array if no such key was stored.
*/
public int[] getIntArray(String key)
{
try
{
return !this.tagMap.containsKey(key) ? new int[0] : ((NBTTagIntArray)this.tagMap.get(key)).getIntArray();
}
catch (ClassCastException classcastexception)
{
throw new ReportedException(this.createCrashReport(key, 11, classcastexception));
}
}
/**
* Retrieves a NBTTagCompound subtag matching the specified key, or a new empty NBTTagCompound if no such key was
* stored.
*/
public NBTTagCompound getCompoundTag(String key)
{
try
{
return !this.tagMap.containsKey(key) ? new NBTTagCompound() : (NBTTagCompound)this.tagMap.get(key);
}
catch (ClassCastException classcastexception)
{
throw new ReportedException(this.createCrashReport(key, 10, classcastexception));
}
}
/**
* Gets the NBTTagList object with the given name. Args: name, NBTBase type
*/
public NBTTagList getTagList(String key, int type)
{
try
{
if (this.getTagId(key) != 9)
{
return new NBTTagList();
}
else
{
NBTTagList nbttaglist = (NBTTagList)this.tagMap.get(key);
return nbttaglist.tagCount() > 0 && nbttaglist.getTagType() != type ? new NBTTagList() : nbttaglist;
}
}
catch (ClassCastException classcastexception)
{
throw new ReportedException(this.createCrashReport(key, 9, classcastexception));
}
}
/**
* Retrieves a boolean value using the specified key, or false if no such key was stored. This uses the getByte
* method.
*/
public boolean getBoolean(String key)
{
return this.getByte(key) != 0;
}
/**
* Remove the specified tag.
*/
public void removeTag(String key)
{
this.tagMap.remove(key);
}
public String toString()
{
String s = "{";
String s1;
for (Iterator iterator = this.tagMap.keySet().iterator(); iterator.hasNext(); s = s + s1 + ':' + this.tagMap.get(s1) + ',')
{
s1 = (String)iterator.next();
}
return s + "}";
}
/**
* Return whether this compound has no tags.
*/
public boolean hasNoTags()
{
return this.tagMap.isEmpty();
}
/**
* Create a crash report which indicates a NBT read error.
*/
private CrashReport createCrashReport(final String p_82581_1_, final int p_82581_2_, ClassCastException p_82581_3_)
{
CrashReport crashreport = CrashReport.makeCrashReport(p_82581_3_, "Reading NBT data");
CrashReportCategory crashreportcategory = crashreport.makeCategoryDepth("Corrupt NBT tag", 1);
crashreportcategory.addCrashSectionCallable("Tag type found", new Callable()
{
private static final String __OBFID = "CL_00001216";
public String call()
{
return NBTBase.NBT_TYPES[((NBTBase)NBTTagCompound.this.tagMap.get(p_82581_1_)).getId()];
}
});
crashreportcategory.addCrashSectionCallable("Tag type expected", new Callable()
{
private static final String __OBFID = "CL_00001217";
public String call()
{
return NBTBase.NBT_TYPES[p_82581_2_];
}
});
crashreportcategory.addCrashSection("Tag name", p_82581_1_);
return crashreport;
}
/**
* Creates a clone of the tag.
*/
public NBTBase copy()
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
Iterator iterator = this.tagMap.keySet().iterator();
while (iterator.hasNext())
{
String s = (String)iterator.next();
nbttagcompound.setTag(s, ((NBTBase)this.tagMap.get(s)).copy());
}
return nbttagcompound;
}
public boolean equals(Object p_equals_1_)
{
if (super.equals(p_equals_1_))
{
NBTTagCompound nbttagcompound = (NBTTagCompound)p_equals_1_;
return this.tagMap.entrySet().equals(nbttagcompound.tagMap.entrySet());
}
else
{
return false;
}
}
public int hashCode()
{
return super.hashCode() ^ this.tagMap.hashCode();
}
private static void writeEntry(String name, NBTBase data, DataOutput output) throws IOException
{
output.writeByte(data.getId());
if (data.getId() != 0)
{
output.writeUTF(name);
data.write(output);
}
}
private static byte readType(DataInput input, NBTSizeTracker sizeTracker) throws IOException
{
sizeTracker.addSpaceRead(8);
return input.readByte();
}
private static String readKey(DataInput input, NBTSizeTracker sizeTracker) throws IOException
{
return input.readUTF();
}
static NBTBase readNBT(byte id, String key, DataInput input, int depth, NBTSizeTracker sizeTracker)
{
sizeTracker.addSpaceRead(32); //Forge: 4 extra bytes for the object allocation.
NBTBase nbtbase = NBTBase.createNewByType(id);
try
{
nbtbase.read(input, depth, sizeTracker);
return nbtbase;
}
catch (IOException ioexception)
{
CrashReport crashreport = CrashReport.makeCrashReport(ioexception, "Loading NBT data");
CrashReportCategory crashreportcategory = crashreport.makeCategory("NBT Tag");
crashreportcategory.addCrashSection("Tag name", key);
crashreportcategory.addCrashSection("Tag type", Byte.valueOf(id));
throw new ReportedException(crashreport);
}
}
}