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}