001    package net.minecraft.item;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.List;
006    import net.minecraft.block.Block;
007    import net.minecraft.block.material.MapColor;
008    import net.minecraft.entity.Entity;
009    import net.minecraft.entity.player.EntityPlayer;
010    import net.minecraft.network.packet.Packet;
011    import net.minecraft.network.packet.Packet131MapData;
012    import net.minecraft.util.MathHelper;
013    import net.minecraft.world.World;
014    import net.minecraft.world.chunk.Chunk;
015    import net.minecraft.world.storage.MapData;
016    import net.minecraft.world.storage.MapInfo;
017    
018    public class ItemMap extends ItemMapBase
019    {
020        protected ItemMap(int par1)
021        {
022            super(par1);
023            this.setHasSubtypes(true);
024        }
025    
026        @SideOnly(Side.CLIENT)
027        public static MapData getMPMapData(short par0, World par1World)
028        {
029            String var2 = "map_" + par0;
030            MapData var3 = (MapData)par1World.loadItemData(MapData.class, var2);
031    
032            if (var3 == null)
033            {
034                var3 = new MapData(var2);
035                par1World.setItemData(var2, var3);
036            }
037    
038            return var3;
039        }
040    
041        public MapData getMapData(ItemStack par1ItemStack, World par2World)
042        {
043            String var3 = "map_" + par1ItemStack.getItemDamage();
044            MapData var4 = (MapData)par2World.loadItemData(MapData.class, var3);
045    
046            if (var4 == null && !par2World.isRemote)
047            {
048                par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
049                var3 = "map_" + par1ItemStack.getItemDamage();
050                var4 = new MapData(var3);
051                var4.scale = 3;
052                int var5 = 128 * (1 << var4.scale);
053                var4.xCenter = Math.round((float)par2World.getWorldInfo().getSpawnX() / (float)var5) * var5;
054                var4.zCenter = Math.round((float)(par2World.getWorldInfo().getSpawnZ() / var5)) * var5;
055                var4.dimension = par2World.provider.dimensionId;
056                var4.markDirty();
057                par2World.setItemData(var3, var4);
058            }
059    
060            return var4;
061        }
062    
063        public void updateMapData(World par1World, Entity par2Entity, MapData par3MapData)
064        {
065            if (par1World.provider.dimensionId == par3MapData.dimension && par2Entity instanceof EntityPlayer)
066            {
067                short var4 = 128;
068                short var5 = 128;
069                int var6 = 1 << par3MapData.scale;
070                int var7 = par3MapData.xCenter;
071                int var8 = par3MapData.zCenter;
072                int var9 = MathHelper.floor_double(par2Entity.posX - (double)var7) / var6 + var4 / 2;
073                int var10 = MathHelper.floor_double(par2Entity.posZ - (double)var8) / var6 + var5 / 2;
074                int var11 = 128 / var6;
075    
076                if (par1World.provider.hasNoSky)
077                {
078                    var11 /= 2;
079                }
080    
081                MapInfo var12 = par3MapData.func_82568_a((EntityPlayer)par2Entity);
082                ++var12.field_82569_d;
083    
084                for (int var13 = var9 - var11 + 1; var13 < var9 + var11; ++var13)
085                {
086                    if ((var13 & 15) == (var12.field_82569_d & 15))
087                    {
088                        int var14 = 255;
089                        int var15 = 0;
090                        double var16 = 0.0D;
091    
092                        for (int var18 = var10 - var11 - 1; var18 < var10 + var11; ++var18)
093                        {
094                            if (var13 >= 0 && var18 >= -1 && var13 < var4 && var18 < var5)
095                            {
096                                int var19 = var13 - var9;
097                                int var20 = var18 - var10;
098                                boolean var21 = var19 * var19 + var20 * var20 > (var11 - 2) * (var11 - 2);
099                                int var22 = (var7 / var6 + var13 - var4 / 2) * var6;
100                                int var23 = (var8 / var6 + var18 - var5 / 2) * var6;
101                                int[] var24 = new int[Block.blocksList.length];
102                                Chunk var25 = par1World.getChunkFromBlockCoords(var22, var23);
103    
104                                if (!var25.isEmpty())
105                                {
106                                    int var26 = var22 & 15;
107                                    int var27 = var23 & 15;
108                                    int var28 = 0;
109                                    double var29 = 0.0D;
110                                    int var31;
111                                    int var32;
112                                    int var33;
113                                    int var36;
114    
115                                    if (par1World.provider.hasNoSky)
116                                    {
117                                        var31 = var22 + var23 * 231871;
118                                        var31 = var31 * var31 * 31287121 + var31 * 11;
119    
120                                        if ((var31 >> 20 & 1) == 0)
121                                        {
122                                            var24[Block.dirt.blockID] += 10;
123                                        }
124                                        else
125                                        {
126                                            var24[Block.stone.blockID] += 10;
127                                        }
128    
129                                        var29 = 100.0D;
130                                    }
131                                    else
132                                    {
133                                        for (var31 = 0; var31 < var6; ++var31)
134                                        {
135                                            for (var32 = 0; var32 < var6; ++var32)
136                                            {
137                                                var33 = var25.getHeightValue(var31 + var26, var32 + var27) + 1;
138                                                int var34 = 0;
139    
140                                                if (var33 > 1)
141                                                {
142                                                    boolean var35;
143    
144                                                    do
145                                                    {
146                                                        var35 = true;
147                                                        var34 = var25.getBlockID(var31 + var26, var33 - 1, var32 + var27);
148    
149                                                        if (var34 == 0)
150                                                        {
151                                                            var35 = false;
152                                                        }
153                                                        else if (var33 > 0 && var34 > 0 && Block.blocksList[var34].blockMaterial.materialMapColor == MapColor.airColor)
154                                                        {
155                                                            var35 = false;
156                                                        }
157    
158                                                        if (!var35)
159                                                        {
160                                                            --var33;
161    
162                                                            if (var33 <= 0)
163                                                            {
164                                                                break;
165                                                            }
166    
167                                                            var34 = var25.getBlockID(var31 + var26, var33 - 1, var32 + var27);
168                                                        }
169                                                    }
170                                                    while (var33 > 0 && !var35);
171    
172                                                    if (var33 > 0 && var34 != 0 && Block.blocksList[var34].blockMaterial.isLiquid())
173                                                    {
174                                                        var36 = var33 - 1;
175                                                        boolean var37 = false;
176                                                        int var43;
177    
178                                                        do
179                                                        {
180                                                            var43 = var25.getBlockID(var31 + var26, var36--, var32 + var27);
181                                                            ++var28;
182                                                        }
183                                                        while (var36 > 0 && var43 != 0 && Block.blocksList[var43].blockMaterial.isLiquid());
184                                                    }
185                                                }
186    
187                                                var29 += (double)var33 / (double)(var6 * var6);
188                                                ++var24[var34];
189                                            }
190                                        }
191                                    }
192    
193                                    var28 /= var6 * var6;
194                                    var31 = 0;
195                                    var32 = 0;
196    
197                                    for (var33 = 0; var33 < Block.blocksList.length; ++var33)
198                                    {
199                                        if (var24[var33] > var31)
200                                        {
201                                            var32 = var33;
202                                            var31 = var24[var33];
203                                        }
204                                    }
205    
206                                    double var40 = (var29 - var16) * 4.0D / (double)(var6 + 4) + ((double)(var13 + var18 & 1) - 0.5D) * 0.4D;
207                                    byte var39 = 1;
208    
209                                    if (var40 > 0.6D)
210                                    {
211                                        var39 = 2;
212                                    }
213    
214                                    if (var40 < -0.6D)
215                                    {
216                                        var39 = 0;
217                                    }
218    
219                                    var36 = 0;
220    
221                                    if (var32 > 0)
222                                    {
223                                        MapColor var42 = Block.blocksList[var32].blockMaterial.materialMapColor;
224    
225                                        if (var42 == MapColor.waterColor)
226                                        {
227                                            var40 = (double)var28 * 0.1D + (double)(var13 + var18 & 1) * 0.2D;
228                                            var39 = 1;
229    
230                                            if (var40 < 0.5D)
231                                            {
232                                                var39 = 2;
233                                            }
234    
235                                            if (var40 > 0.9D)
236                                            {
237                                                var39 = 0;
238                                            }
239                                        }
240    
241                                        var36 = var42.colorIndex;
242                                    }
243    
244                                    var16 = var29;
245    
246                                    if (var18 >= 0 && var19 * var19 + var20 * var20 < var11 * var11 && (!var21 || (var13 + var18 & 1) != 0))
247                                    {
248                                        byte var41 = par3MapData.colors[var13 + var18 * var4];
249                                        byte var38 = (byte)(var36 * 4 + var39);
250    
251                                        if (var41 != var38)
252                                        {
253                                            if (var14 > var18)
254                                            {
255                                                var14 = var18;
256                                            }
257    
258                                            if (var15 < var18)
259                                            {
260                                                var15 = var18;
261                                            }
262    
263                                            par3MapData.colors[var13 + var18 * var4] = var38;
264                                        }
265                                    }
266                                }
267                            }
268                        }
269    
270                        if (var14 <= var15)
271                        {
272                            par3MapData.setColumnDirty(var13, var14, var15);
273                        }
274                    }
275                }
276            }
277        }
278    
279        /**
280         * Called each tick as long the item is on a player inventory. Uses by maps to check if is on a player hand and
281         * update it's contents.
282         */
283        public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
284        {
285            if (!par2World.isRemote)
286            {
287                MapData var6 = this.getMapData(par1ItemStack, par2World);
288    
289                if (par3Entity instanceof EntityPlayer)
290                {
291                    EntityPlayer var7 = (EntityPlayer)par3Entity;
292                    var6.updateVisiblePlayers(var7, par1ItemStack);
293                }
294    
295                if (par5)
296                {
297                    this.updateMapData(par2World, par3Entity, var6);
298                }
299            }
300        }
301    
302        /**
303         * returns null if no update is to be sent
304         */
305        public Packet createMapDataPacket(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
306        {
307            byte[] var4 = this.getMapData(par1ItemStack, par2World).getUpdatePacketData(par1ItemStack, par2World, par3EntityPlayer);
308            return var4 == null ? null : new Packet131MapData((short)Item.map.itemID, (short)par1ItemStack.getItemDamage(), var4);
309        }
310    
311        /**
312         * Called when item is crafted/smelted. Used only by maps so far.
313         */
314        public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
315        {
316            if (par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().getBoolean("map_is_scaling"))
317            {
318                MapData var4 = Item.map.getMapData(par1ItemStack, par2World);
319                par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
320                MapData var5 = new MapData("map_" + par1ItemStack.getItemDamage());
321                var5.scale = (byte)(var4.scale + 1);
322    
323                if (var5.scale > 4)
324                {
325                    var5.scale = 4;
326                }
327    
328                var5.xCenter = var4.xCenter;
329                var5.zCenter = var4.zCenter;
330                var5.dimension = var4.dimension;
331                var5.markDirty();
332                par2World.setItemData("map_" + par1ItemStack.getItemDamage(), var5);
333            }
334        }
335    
336        @SideOnly(Side.CLIENT)
337    
338        /**
339         * allows items to add custom lines of information to the mouseover description
340         */
341        public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
342        {
343            MapData var5 = this.getMapData(par1ItemStack, par2EntityPlayer.worldObj);
344    
345            if (par4)
346            {
347                if (var5 == null)
348                {
349                    par3List.add("Unknown map");
350                }
351                else
352                {
353                    par3List.add("Scaling at 1:" + (1 << var5.scale));
354                    par3List.add("(Level " + var5.scale + "/" + 4 + ")");
355                }
356            }
357        }
358    }