001package net.minecraft.item;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.List;
006import net.minecraft.block.Block;
007import net.minecraft.block.material.MapColor;
008import net.minecraft.entity.Entity;
009import net.minecraft.entity.player.EntityPlayer;
010import net.minecraft.network.packet.Packet;
011import net.minecraft.network.packet.Packet131MapData;
012import net.minecraft.util.MathHelper;
013import net.minecraft.world.World;
014import net.minecraft.world.chunk.Chunk;
015import net.minecraft.world.storage.MapData;
016import net.minecraft.world.storage.MapInfo;
017
018public 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}