    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 s = "map_" + par0;
    030        MapData mapdata = (MapData)par1World.loadItemData(MapData.class, s);
    031
    032        if (mapdata == null)
    033        {
    034            mapdata = new MapData(s);
    035            par1World.setItemData(s, mapdata);
    036        }
    037
    038        return mapdata;
    039    }
    040
    041    public MapData getMapData(ItemStack par1ItemStack, World par2World)
    042    {
    043        String s = "map_" + par1ItemStack.getItemDamage();
    044        MapData mapdata = (MapData)par2World.loadItemData(MapData.class, s);
    045
    046        if (mapdata == null && !par2World.isRemote)
    047        {
    048            par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
    049            s = "map_" + par1ItemStack.getItemDamage();
    050            mapdata = new MapData(s);
    051            mapdata.scale = 3;
    052            int i = 128 * (1 << mapdata.scale);
    053            mapdata.xCenter = Math.round((float)par2World.getWorldInfo().getSpawnX() / (float)i) * i;
    054            mapdata.zCenter = Math.round((float)(par2World.getWorldInfo().getSpawnZ() / i)) * i;
    055            mapdata.dimension = par2World.provider.dimensionId;
    056            mapdata.markDirty();
    057            par2World.setItemData(s, mapdata);
    058        }
    059
    060        return mapdata;
    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 short1 = 128;
    068            short short2 = 128;
    069            int i = 1 << par3MapData.scale;
    070            int j = par3MapData.xCenter;
    071            int k = par3MapData.zCenter;
    072            int l = MathHelper.floor_double(par2Entity.posX - (double)j) / i + short1 / 2;
    073            int i1 = MathHelper.floor_double(par2Entity.posZ - (double)k) / i + short2 / 2;
    074            int j1 = 128 / i;
    075
    076            if (par1World.provider.hasNoSky)
    077            {
    078                j1 /= 2;
    079            }
    080
    081            MapInfo mapinfo = par3MapData.func_82568_a((EntityPlayer)par2Entity);
    082            ++mapinfo.field_82569_d;
    083
    084            for (int k1 = l - j1 + 1; k1 < l + j1; ++k1)
    085            {
    086                if ((k1 & 15) == (mapinfo.field_82569_d & 15))
    087                {
    088                    int l1 = 255;
    089                    int i2 = 0;
    090                    double d0 = 0.0D;
    091
    092                    for (int j2 = i1 - j1 - 1; j2 < i1 + j1; ++j2)
    093                    {
    094                        if (k1 >= 0 && j2 >= -1 && k1 < short1 && j2 < short2)
    095                        {
    096                            int k2 = k1 - l;
    097                            int l2 = j2 - i1;
    098                            boolean flag = k2 * k2 + l2 * l2 > (j1 - 2) * (j1 - 2);
    099                            int i3 = (j / i + k1 - short1 / 2) * i;
    100                            int j3 = (k / i + j2 - short2 / 2) * i;
    101                            int[] aint = new int[Block.blocksList.length];
    102                            Chunk chunk = par1World.getChunkFromBlockCoords(i3, j3);
    103
    104                            if (!chunk.isEmpty())
    105                            {
    106                                int k3 = i3 & 15;
    107                                int l3 = j3 & 15;
    108                                int i4 = 0;
    109                                double d1 = 0.0D;
    110                                int j4;
    111                                int k4;
    112                                int l4;
    113                                int i5;
    114
    115                                if (par1World.provider.hasNoSky)
    116                                {
    117                                    j4 = i3 + j3 * 231871;
    118                                    j4 = j4 * j4 * 31287121 + j4 * 11;
    119
    120                                    if ((j4 >> 20 & 1) == 0)
    121                                    {
    122                                        aint[Block.dirt.blockID] += 10;
    123                                    }
    124                                    else
    125                                    {
    126                                        aint[Block.stone.blockID] += 10;
    127                                    }
    128
    129                                    d1 = 100.0D;
    130                                }
    131                                else
    132                                {
    133                                    for (j4 = 0; j4 < i; ++j4)
    134                                    {
    135                                        for (k4 = 0; k4 < i; ++k4)
    136                                        {
    137                                            l4 = chunk.getHeightValue(j4 + k3, k4 + l3) + 1;
    138                                            int j5 = 0;
    139
    140                                            if (l4 > 1)
    141                                            {
    142                                                boolean flag1;
    143
    144                                                do
    145                                                {
    146                                                    flag1 = true;
    147                                                    j5 = chunk.getBlockID(j4 + k3, l4 - 1, k4 + l3);
    148
    149                                                    if (j5 == 0)
    150                                                    {
    151                                                        flag1 = false;
    152                                                    }
    153                                                    else if (l4 > 0 && j5 > 0 && Block.blocksList[j5].blockMaterial.materialMapColor == MapColor.airColor)
    154                                                    {
    155                                                        flag1 = false;
    156                                                    }
    157
    158                                                    if (!flag1)
    159                                                    {
    160                                                        --l4;
    161
    162                                                        if (l4 <= 0)
    163                                                        {
    164                                                            break;
    165                                                        }
    166
    167                                                        j5 = chunk.getBlockID(j4 + k3, l4 - 1, k4 + l3);
    168                                                    }
    169                                                }
    170                                                while (l4 > 0 && !flag1);
    171
    172                                                if (l4 > 0 && j5 != 0 && Block.blocksList[j5].blockMaterial.isLiquid())
    173                                                {
    174                                                    i5 = l4 - 1;
    175                                                    boolean flag2 = false;
    176                                                    int k5;
    177
    178                                                    do
    179                                                    {
    180                                                        k5 = chunk.getBlockID(j4 + k3, i5--, k4 + l3);
    181                                                        ++i4;
    182                                                    }
    183                                                    while (i5 > 0 && k5 != 0 && Block.blocksList[k5].blockMaterial.isLiquid());
    184                                                }
    185                                            }
    186
    187                                            d1 += (double)l4 / (double)(i * i);
    188                                            ++aint[j5];
    189                                        }
    190                                    }
    191                                }
    192
    193                                i4 /= i * i;
    194                                j4 = 0;
    195                                k4 = 0;
    196
    197                                for (l4 = 0; l4 < Block.blocksList.length; ++l4)
    198                                {
    199                                    if (aint[l4] > j4)
    200                                    {
    201                                        k4 = l4;
    202                                        j4 = aint[l4];
    203                                    }
    204                                }
    205
    206                                double d2 = (d1 - d0) * 4.0D / (double)(i + 4) + ((double)(k1 + j2 & 1) - 0.5D) * 0.4D;
    207                                byte b0 = 1;
    208
    209                                if (d2 > 0.6D)
    210                                {
    211                                    b0 = 2;
    212                                }
    213
    214                                if (d2 < -0.6D)
    215                                {
    216                                    b0 = 0;
    217                                }
    218
    219                                i5 = 0;
    220
    221                                if (k4 > 0)
    222                                {
    223                                    MapColor mapcolor = Block.blocksList[k4].blockMaterial.materialMapColor;
    224
    225                                    if (mapcolor == MapColor.waterColor)
    226                                    {
    227                                        d2 = (double)i4 * 0.1D + (double)(k1 + j2 & 1) * 0.2D;
    228                                        b0 = 1;
    229
    230                                        if (d2 < 0.5D)
    231                                        {
    232                                            b0 = 2;
    233                                        }
    234
    235                                        if (d2 > 0.9D)
    236                                        {
    237                                            b0 = 0;
    238                                        }
    239                                    }
    240
    241                                    i5 = mapcolor.colorIndex;
    242                                }
    243
    244                                d0 = d1;
    245
    246                                if (j2 >= 0 && k2 * k2 + l2 * l2 < j1 * j1 && (!flag || (k1 + j2 & 1) != 0))
    247                                {
    248                                    byte b1 = par3MapData.colors[k1 + j2 * short1];
    249                                    byte b2 = (byte)(i5 * 4 + b0);
    250
    251                                    if (b1 != b2)
    252                                    {
    253                                        if (l1 > j2)
    254                                        {
    255                                            l1 = j2;
    256                                        }
    257
    258                                        if (i2 < j2)
    259                                        {
    260                                            i2 = j2;
    261                                        }
    262
    263                                        par3MapData.colors[k1 + j2 * short1] = b2;
    264                                    }
    265                                }
    266                            }
    267                        }
    268                    }
    269
    270                    if (l1 <= i2)
    271                    {
    272                        par3MapData.setColumnDirty(k1, l1, i2);
    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 mapdata = this.getMapData(par1ItemStack, par2World);
    288
    289            if (par3Entity instanceof EntityPlayer)
    290            {
    291                EntityPlayer entityplayer = (EntityPlayer)par3Entity;
    292                mapdata.updateVisiblePlayers(entityplayer, par1ItemStack);
    293            }
    294
    295            if (par5)
    296            {
    297                this.updateMapData(par2World, par3Entity, mapdata);
    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[] abyte = this.getMapData(par1ItemStack, par2World).getUpdatePacketData(par1ItemStack, par2World, par3EntityPlayer);
    308        return abyte == null ? null : new Packet131MapData((short)Item.map.itemID, (short)par1ItemStack.getItemDamage(), abyte);
    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 mapdata = Item.map.getMapData(par1ItemStack, par2World);
    319            par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
    320            MapData mapdata1 = new MapData("map_" + par1ItemStack.getItemDamage());
    321            mapdata1.scale = (byte)(mapdata.scale + 1);
    322
    323            if (mapdata1.scale > 4)
    324            {
    325                mapdata1.scale = 4;
    326            }
    327
    328            mapdata1.xCenter = mapdata.xCenter;
    329            mapdata1.zCenter = mapdata.zCenter;
    330            mapdata1.dimension = mapdata.dimension;
    331            mapdata1.markDirty();
    332            par2World.setItemData("map_" + par1ItemStack.getItemDamage(), mapdata1);
    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 mapdata = this.getMapData(par1ItemStack, par2EntityPlayer.worldObj);
    344
    345        if (par4)
    346        {
    347            if (mapdata == null)
    348            {
    349                par3List.add("Unknown map");
    350            }
    351            else
    352            {
    353                par3List.add("Scaling at 1:" + (1 << mapdata.scale));
    354                par3List.add("(Level " + mapdata.scale + "/" + 4 + ")");
    355            }
    356        }
    357    }
    358}