    001package net.minecraft.nbt;
    002
    003import java.io.DataInput;
    004import java.io.DataOutput;
    005import java.io.IOException;
    006import net.minecraft.crash.CrashReport;
    007import net.minecraft.crash.CrashReportCategory;
    008import net.minecraft.util.ReportedException;
    009
    010public abstract class NBTBase
    011{
    012    public static final String[] NBTTypes = new String[] {"END", "BYTE", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE", "BYTE[]", "STRING", "LIST", "COMPOUND", "INT[]"};
    013
    014    /** The UTF string key used to lookup values. */
    015    private String name;
    016
    017    /**
    018     * Write the actual data contents of the tag, implemented in NBT extension classes
    019     */
    020    abstract void write(DataOutput dataoutput) throws IOException;
    021
    022    /**
    023     * Read the actual data contents of the tag, implemented in NBT extension classes
    024     */
    025    abstract void load(DataInput datainput) throws IOException;
    026
    027    /**
    028     * Gets the type byte for the tag.
    029     */
    030    public abstract byte getId();
    031
    032    protected NBTBase(String par1Str)
    033    {
    034        if (par1Str == null)
    035        {
    036            this.name = "";
    037        }
    038        else
    039        {
    040            this.name = par1Str;
    041        }
    042    }
    043
    044    /**
    045     * Sets the name for this tag and returns this for convenience.
    046     */
    047    public NBTBase setName(String par1Str)
    048    {
    049        if (par1Str == null)
    050        {
    051            this.name = "";
    052        }
    053        else
    054        {
    055            this.name = par1Str;
    056        }
    057
    058        return this;
    059    }
    060
    061    /**
    062     * Gets the name corresponding to the tag, or an empty string if none set.
    063     */
    064    public String getName()
    065    {
    066        return this.name == null ? "" : this.name;
    067    }
    068
    069    /**
    070     * Reads and returns a tag from the given DataInput, or the End tag if no tag could be read.
    071     */
    072    public static NBTBase readNamedTag(DataInput par0DataInput) throws IOException
    073    {
    074        byte b0 = par0DataInput.readByte();
    075
    076        if (b0 == 0)
    077        {
    078            return new NBTTagEnd();
    079        }
    080        else
    081        {
    082            String s = par0DataInput.readUTF();
    083            NBTBase nbtbase = newTag(b0, s);
    084
    085            try
    086            {
    087                nbtbase.load(par0DataInput);
    088                return nbtbase;
    089            }
    090            catch (IOException ioexception)
    091            {
    092                CrashReport crashreport = CrashReport.makeCrashReport(ioexception, "Loading NBT data");
    093                CrashReportCategory crashreportcategory = crashreport.makeCategory("NBT Tag");
    094                crashreportcategory.addCrashSection("Tag name", s);
    095                crashreportcategory.addCrashSection("Tag type", Byte.valueOf(b0));
    096                throw new ReportedException(crashreport);
    097            }
    098        }
    099    }
    100
    101    /**
    102     * Writes the specified tag to the given DataOutput, writing the type byte, the UTF string key and then calling the
    103     * tag to write its data.
    104     */
    105    public static void writeNamedTag(NBTBase par0NBTBase, DataOutput par1DataOutput) throws IOException
    106    {
    107        par1DataOutput.writeByte(par0NBTBase.getId());
    108
    109        if (par0NBTBase.getId() != 0)
    110        {
    111            par1DataOutput.writeUTF(par0NBTBase.getName());
    112            par0NBTBase.write(par1DataOutput);
    113        }
    114    }
    115
    116    /**
    117     * Creates and returns a new tag of the specified type, or null if invalid.
    118     */
    119    public static NBTBase newTag(byte par0, String par1Str)
    120    {
    121        switch (par0)
    122        {
    123            case 0:
    124                return new NBTTagEnd();
    125            case 1:
    126                return new NBTTagByte(par1Str);
    127            case 2:
    128                return new NBTTagShort(par1Str);
    129            case 3:
    130                return new NBTTagInt(par1Str);
    131            case 4:
    132                return new NBTTagLong(par1Str);
    133            case 5:
    134                return new NBTTagFloat(par1Str);
    135            case 6:
    136                return new NBTTagDouble(par1Str);
    137            case 7:
    138                return new NBTTagByteArray(par1Str);
    139            case 8:
    140                return new NBTTagString(par1Str);
    141            case 9:
    142                return new NBTTagList(par1Str);
    143            case 10:
    144                return new NBTTagCompound(par1Str);
    145            case 11:
    146                return new NBTTagIntArray(par1Str);
    147            default:
    148                return null;
    149        }
    150    }
    151
    152    /**
    153     * Returns the string name of a tag with the specified type, or 'UNKNOWN' if invalid.
    154     */
    155    public static String getTagName(byte par0)
    156    {
    157        switch (par0)
    158        {
    159            case 0:
    160                return "TAG_End";
    161            case 1:
    162                return "TAG_Byte";
    163            case 2:
    164                return "TAG_Short";
    165            case 3:
    166                return "TAG_Int";
    167            case 4:
    168                return "TAG_Long";
    169            case 5:
    170                return "TAG_Float";
    171            case 6:
    172                return "TAG_Double";
    173            case 7:
    174                return "TAG_Byte_Array";
    175            case 8:
    176                return "TAG_String";
    177            case 9:
    178                return "TAG_List";
    179            case 10:
    180                return "TAG_Compound";
    181            case 11:
    182                return "TAG_Int_Array";
    183            default:
    184                return "UNKNOWN";
    185        }
    186    }
    187
    188    /**
    189     * Creates a clone of the tag.
    190     */
    191    public abstract NBTBase copy();
    192
    193    public boolean equals(Object par1Obj)
    194    {
    195        if (!(par1Obj instanceof NBTBase))
    196        {
    197            return false;
    198        }
    199        else
    200        {
    201            NBTBase nbtbase = (NBTBase)par1Obj;
    202            return this.getId() != nbtbase.getId() ? false : ((this.name != null || nbtbase.name == null) && (this.name == null || nbtbase.name != null) ? this.name == null || this.name.equals(nbtbase.name) : false);
    203        }
    204    }
    205
    206    public int hashCode()
    207    {
    208        return this.name.hashCode() ^ this.getId();
    209    }
    210}