001package net.minecraft.world.storage; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.ArrayList; 006import java.util.HashMap; 007import java.util.LinkedHashMap; 008import java.util.List; 009import java.util.Map; 010import net.minecraft.entity.player.EntityPlayer; 011import net.minecraft.item.ItemStack; 012import net.minecraft.nbt.*; 013import net.minecraft.world.World; 014import net.minecraft.world.WorldSavedData; 015 016public class MapData extends WorldSavedData 017{ 018 public int xCenter; 019 public int zCenter; 020 public int dimension; 021 public byte scale; 022 023 /** colours */ 024 public byte[] colors = new byte[16384]; 025 026 /** 027 * Holds a reference to the MapInfo of the players who own a copy of the map 028 */ 029 public List playersArrayList = new ArrayList(); 030 031 /** 032 * Holds a reference to the players who own a copy of the map and a reference to their MapInfo 033 */ 034 private Map playersHashMap = new HashMap(); 035 public Map playersVisibleOnMap = new LinkedHashMap(); 036 037 public MapData(String par1Str) 038 { 039 super(par1Str); 040 } 041 042 /** 043 * reads in data from the NBTTagCompound into this MapDataBase 044 */ 045 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 046 { 047 NBTBase dimension = par1NBTTagCompound.getTag("dimension"); 048 049 if (dimension instanceof NBTTagByte) 050 { 051 this.dimension = ((NBTTagByte)dimension).data; 052 } 053 else 054 { 055 this.dimension = ((NBTTagInt)dimension).data; 056 } 057 058 this.xCenter = par1NBTTagCompound.getInteger("xCenter"); 059 this.zCenter = par1NBTTagCompound.getInteger("zCenter"); 060 this.scale = par1NBTTagCompound.getByte("scale"); 061 062 if (this.scale < 0) 063 { 064 this.scale = 0; 065 } 066 067 if (this.scale > 4) 068 { 069 this.scale = 4; 070 } 071 072 short short1 = par1NBTTagCompound.getShort("width"); 073 short short2 = par1NBTTagCompound.getShort("height"); 074 075 if (short1 == 128 && short2 == 128) 076 { 077 this.colors = par1NBTTagCompound.getByteArray("colors"); 078 } 079 else 080 { 081 byte[] abyte = par1NBTTagCompound.getByteArray("colors"); 082 this.colors = new byte[16384]; 083 int i = (128 - short1) / 2; 084 int j = (128 - short2) / 2; 085 086 for (int k = 0; k < short2; ++k) 087 { 088 int l = k + j; 089 090 if (l >= 0 || l < 128) 091 { 092 for (int i1 = 0; i1 < short1; ++i1) 093 { 094 int j1 = i1 + i; 095 096 if (j1 >= 0 || j1 < 128) 097 { 098 this.colors[j1 + l * 128] = abyte[i1 + k * short1]; 099 } 100 } 101 } 102 } 103 } 104 } 105 106 /** 107 * write data to NBTTagCompound from this MapDataBase, similar to Entities and TileEntities 108 */ 109 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 110 { 111 par1NBTTagCompound.setInteger("dimension", this.dimension); 112 par1NBTTagCompound.setInteger("xCenter", this.xCenter); 113 par1NBTTagCompound.setInteger("zCenter", this.zCenter); 114 par1NBTTagCompound.setByte("scale", this.scale); 115 par1NBTTagCompound.setShort("width", (short)128); 116 par1NBTTagCompound.setShort("height", (short)128); 117 par1NBTTagCompound.setByteArray("colors", this.colors); 118 } 119 120 /** 121 * Adds the player passed to the list of visible players and checks to see which players are visible 122 */ 123 public void updateVisiblePlayers(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) 124 { 125 if (!this.playersHashMap.containsKey(par1EntityPlayer)) 126 { 127 MapInfo mapinfo = new MapInfo(this, par1EntityPlayer); 128 this.playersHashMap.put(par1EntityPlayer, mapinfo); 129 this.playersArrayList.add(mapinfo); 130 } 131 132 if (!par1EntityPlayer.inventory.hasItemStack(par2ItemStack)) 133 { 134 this.playersVisibleOnMap.remove(par1EntityPlayer.getCommandSenderName()); 135 } 136 137 for (int i = 0; i < this.playersArrayList.size(); ++i) 138 { 139 MapInfo mapinfo1 = (MapInfo)this.playersArrayList.get(i); 140 141 if (!mapinfo1.entityplayerObj.isDead && (mapinfo1.entityplayerObj.inventory.hasItemStack(par2ItemStack) || par2ItemStack.isOnItemFrame())) 142 { 143 if (!par2ItemStack.isOnItemFrame() && mapinfo1.entityplayerObj.dimension == this.dimension) 144 { 145 this.func_82567_a(0, mapinfo1.entityplayerObj.worldObj, mapinfo1.entityplayerObj.getCommandSenderName(), mapinfo1.entityplayerObj.posX, mapinfo1.entityplayerObj.posZ, (double)mapinfo1.entityplayerObj.rotationYaw); 146 } 147 } 148 else 149 { 150 this.playersHashMap.remove(mapinfo1.entityplayerObj); 151 this.playersArrayList.remove(mapinfo1); 152 } 153 } 154 155 if (par2ItemStack.isOnItemFrame()) 156 { 157 this.func_82567_a(1, par1EntityPlayer.worldObj, "frame-" + par2ItemStack.getItemFrame().entityId, (double)par2ItemStack.getItemFrame().xPosition, (double)par2ItemStack.getItemFrame().zPosition, (double)(par2ItemStack.getItemFrame().hangingDirection * 90)); 158 } 159 } 160 161 private void func_82567_a(int par1, World par2World, String par3Str, double par4, double par6, double par8) 162 { 163 int j = 1 << this.scale; 164 float f = (float)(par4 - (double)this.xCenter) / (float)j; 165 float f1 = (float)(par6 - (double)this.zCenter) / (float)j; 166 byte b0 = (byte)((int)((double)(f * 2.0F) + 0.5D)); 167 byte b1 = (byte)((int)((double)(f1 * 2.0F) + 0.5D)); 168 byte b2 = 63; 169 byte b3; 170 171 if (f >= (float)(-b2) && f1 >= (float)(-b2) && f <= (float)b2 && f1 <= (float)b2) 172 { 173 par8 += par8 < 0.0D ? -8.0D : 8.0D; 174 b3 = (byte)((int)(par8 * 16.0D / 360.0D)); 175 176 if (par2World.provider.shouldMapSpin(par3Str, par4, par6, par8)) 177 { 178 int k = (int)(par2World.getWorldInfo().getWorldTime() / 10L); 179 b3 = (byte)(k * k * 34187121 + k * 121 >> 15 & 15); 180 } 181 } 182 else 183 { 184 if (Math.abs(f) >= 320.0F || Math.abs(f1) >= 320.0F) 185 { 186 this.playersVisibleOnMap.remove(par3Str); 187 return; 188 } 189 190 par1 = 6; 191 b3 = 0; 192 193 if (f <= (float)(-b2)) 194 { 195 b0 = (byte)((int)((double)(b2 * 2) + 2.5D)); 196 } 197 198 if (f1 <= (float)(-b2)) 199 { 200 b1 = (byte)((int)((double)(b2 * 2) + 2.5D)); 201 } 202 203 if (f >= (float)b2) 204 { 205 b0 = (byte)(b2 * 2 + 1); 206 } 207 208 if (f1 >= (float)b2) 209 { 210 b1 = (byte)(b2 * 2 + 1); 211 } 212 } 213 214 this.playersVisibleOnMap.put(par3Str, new MapCoord(this, (byte)par1, b0, b1, b3)); 215 } 216 217 /** 218 * Get byte array of packet data to send to players on map for updating map data 219 */ 220 public byte[] getUpdatePacketData(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) 221 { 222 MapInfo mapinfo = (MapInfo)this.playersHashMap.get(par3EntityPlayer); 223 return mapinfo == null ? null : mapinfo.getPlayersOnMap(par1ItemStack); 224 } 225 226 /** 227 * Marks a vertical range of pixels as being modified so they will be resent to clients. Parameters: X, lowest Y, 228 * highest Y 229 */ 230 public void setColumnDirty(int par1, int par2, int par3) 231 { 232 super.markDirty(); 233 234 for (int l = 0; l < this.playersArrayList.size(); ++l) 235 { 236 MapInfo mapinfo = (MapInfo)this.playersArrayList.get(l); 237 238 if (mapinfo.field_76209_b[par1] < 0 || mapinfo.field_76209_b[par1] > par2) 239 { 240 mapinfo.field_76209_b[par1] = par2; 241 } 242 243 if (mapinfo.field_76210_c[par1] < 0 || mapinfo.field_76210_c[par1] < par3) 244 { 245 mapinfo.field_76210_c[par1] = par3; 246 } 247 } 248 } 249 250 @SideOnly(Side.CLIENT) 251 252 /** 253 * Updates the client's map with information from other players in MP 254 */ 255 public void updateMPMapData(byte[] par1ArrayOfByte) 256 { 257 int i; 258 259 if (par1ArrayOfByte[0] == 0) 260 { 261 i = par1ArrayOfByte[1] & 255; 262 int j = par1ArrayOfByte[2] & 255; 263 264 for (int k = 0; k < par1ArrayOfByte.length - 3; ++k) 265 { 266 this.colors[(k + j) * 128 + i] = par1ArrayOfByte[k + 3]; 267 } 268 269 this.markDirty(); 270 } 271 else if (par1ArrayOfByte[0] == 1) 272 { 273 this.playersVisibleOnMap.clear(); 274 275 for (i = 0; i < (par1ArrayOfByte.length - 1) / 3; ++i) 276 { 277 byte b0 = (byte)(par1ArrayOfByte[i * 3 + 1] >> 4); 278 byte b1 = par1ArrayOfByte[i * 3 + 2]; 279 byte b2 = par1ArrayOfByte[i * 3 + 3]; 280 byte b3 = (byte)(par1ArrayOfByte[i * 3 + 1] & 15); 281 this.playersVisibleOnMap.put("icon-" + i, new MapCoord(this, b0, b1, b2, b3)); 282 } 283 } 284 else if (par1ArrayOfByte[0] == 2) 285 { 286 this.scale = par1ArrayOfByte[1]; 287 } 288 } 289 290 public MapInfo func_82568_a(EntityPlayer par1EntityPlayer) 291 { 292 MapInfo mapinfo = (MapInfo)this.playersHashMap.get(par1EntityPlayer); 293 294 if (mapinfo == null) 295 { 296 mapinfo = new MapInfo(this, par1EntityPlayer); 297 this.playersHashMap.put(par1EntityPlayer, mapinfo); 298 this.playersArrayList.add(mapinfo); 299 } 300 301 return mapinfo; 302 } 303}