001    package net.minecraft.nbt;
002    
003    import java.io.DataInput;
004    import java.io.DataOutput;
005    import java.io.IOException;
006    import java.util.Collection;
007    import java.util.HashMap;
008    import java.util.Iterator;
009    import java.util.Map;
010    import net.minecraft.crash.CrashReport;
011    import net.minecraft.crash.CrashReportCategory;
012    import net.minecraft.util.ReportedException;
013    
014    public 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 var2 = this.tagMap.values().iterator();
037    
038            while (var2.hasNext())
039            {
040                NBTBase var3 = (NBTBase)var2.next();
041                NBTBase.writeNamedTag(var3, 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 var2;
054    
055            while ((var2 = NBTBase.readNamedTag(par1DataInput)).getId() != 0)
056            {
057                this.tagMap.put(var2.getName(), var2);
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 var3)
199            {
200                throw new ReportedException(this.createCrashReport(par1Str, 1, var3));
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 var3)
214            {
215                throw new ReportedException(this.createCrashReport(par1Str, 2, var3));
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 var3)
229            {
230                throw new ReportedException(this.createCrashReport(par1Str, 3, var3));
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 var3)
244            {
245                throw new ReportedException(this.createCrashReport(par1Str, 4, var3));
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 var3)
259            {
260                throw new ReportedException(this.createCrashReport(par1Str, 5, var3));
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 var3)
274            {
275                throw new ReportedException(this.createCrashReport(par1Str, 6, var3));
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 var3)
289            {
290                throw new ReportedException(this.createCrashReport(par1Str, 8, var3));
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 var3)
304            {
305                throw new ReportedException(this.createCrashReport(par1Str, 7, var3));
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 var3)
319            {
320                throw new ReportedException(this.createCrashReport(par1Str, 11, var3));
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 var3)
335            {
336                throw new ReportedException(this.createCrashReport(par1Str, 10, var3));
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 var3)
350            {
351                throw new ReportedException(this.createCrashReport(par1Str, 9, var3));
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            return "" + this.tagMap.size() + " entries";
375        }
376    
377        /**
378         * Return whether this compound has no tags.
379         */
380        public boolean hasNoTags()
381        {
382            return this.tagMap.isEmpty();
383        }
384    
385        /**
386         * Create a crash report which indicates a NBT read error.
387         */
388        private CrashReport createCrashReport(String par1Str, int par2, ClassCastException par3ClassCastException)
389        {
390            CrashReport var4 = CrashReport.func_85055_a(par3ClassCastException, "Reading NBT data");
391            CrashReportCategory var5 = var4.func_85057_a("Corrupt NBT tag", 1);
392            var5.addCrashSectionCallable("Tag type found", new CallableTagCompound1(this, par1Str));
393            var5.addCrashSectionCallable("Tag type expected", new CallableTagCompound2(this, par2));
394            var5.addCrashSection("Tag name", par1Str);
395    
396            if (this.getName() != null && this.getName().length() > 0)
397            {
398                var5.addCrashSection("Tag parent", this.getName());
399            }
400    
401            return var4;
402        }
403    
404        /**
405         * Creates a clone of the tag.
406         */
407        public NBTBase copy()
408        {
409            NBTTagCompound var1 = new NBTTagCompound(this.getName());
410            Iterator var2 = this.tagMap.keySet().iterator();
411    
412            while (var2.hasNext())
413            {
414                String var3 = (String)var2.next();
415                var1.setTag(var3, ((NBTBase)this.tagMap.get(var3)).copy());
416            }
417    
418            return var1;
419        }
420    
421        public boolean equals(Object par1Obj)
422        {
423            if (super.equals(par1Obj))
424            {
425                NBTTagCompound var2 = (NBTTagCompound)par1Obj;
426                return this.tagMap.entrySet().equals(var2.tagMap.entrySet());
427            }
428            else
429            {
430                return false;
431            }
432        }
433    
434        public int hashCode()
435        {
436            return super.hashCode() ^ this.tagMap.hashCode();
437        }
438    
439        /**
440         * Return the tag map for this compound.
441         */
442        static Map getTagMap(NBTTagCompound par0NBTTagCompound)
443        {
444            return par0NBTTagCompound.tagMap;
445        }
446    }