001    package net.minecraft.world.storage;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.ArrayList;
006    import java.util.HashMap;
007    import java.util.LinkedHashMap;
008    import java.util.List;
009    import java.util.Map;
010    import net.minecraft.entity.player.EntityPlayer;
011    import net.minecraft.item.ItemStack;
012    import net.minecraft.nbt.*;
013    import net.minecraft.world.World;
014    import net.minecraft.world.WorldSavedData;
015    
016    public 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 var2 = par1NBTTagCompound.getShort("width");
073            short var3 = par1NBTTagCompound.getShort("height");
074    
075            if (var2 == 128 && var3 == 128)
076            {
077                this.colors = par1NBTTagCompound.getByteArray("colors");
078            }
079            else
080            {
081                byte[] var4 = par1NBTTagCompound.getByteArray("colors");
082                this.colors = new byte[16384];
083                int var5 = (128 - var2) / 2;
084                int var6 = (128 - var3) / 2;
085    
086                for (int var7 = 0; var7 < var3; ++var7)
087                {
088                    int var8 = var7 + var6;
089    
090                    if (var8 >= 0 || var8 < 128)
091                    {
092                        for (int var9 = 0; var9 < var2; ++var9)
093                        {
094                            int var10 = var9 + var5;
095    
096                            if (var10 >= 0 || var10 < 128)
097                            {
098                                this.colors[var10 + var8 * 128] = var4[var9 + var7 * var2];
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 var3 = new MapInfo(this, par1EntityPlayer);
128                this.playersHashMap.put(par1EntityPlayer, var3);
129                this.playersArrayList.add(var3);
130            }
131    
132            if (!par1EntityPlayer.inventory.hasItemStack(par2ItemStack))
133            {
134                this.playersVisibleOnMap.remove(par1EntityPlayer.getCommandSenderName());
135            }
136    
137            for (int var5 = 0; var5 < this.playersArrayList.size(); ++var5)
138            {
139                MapInfo var4 = (MapInfo)this.playersArrayList.get(var5);
140    
141                if (!var4.entityplayerObj.isDead && (var4.entityplayerObj.inventory.hasItemStack(par2ItemStack) || par2ItemStack.isOnItemFrame()))
142                {
143                    if (!par2ItemStack.isOnItemFrame() && var4.entityplayerObj.dimension == this.dimension)
144                    {
145                        this.func_82567_a(0, var4.entityplayerObj.worldObj, var4.entityplayerObj.getCommandSenderName(), var4.entityplayerObj.posX, var4.entityplayerObj.posZ, (double)var4.entityplayerObj.rotationYaw);
146                    }
147                }
148                else
149                {
150                    this.playersHashMap.remove(var4.entityplayerObj);
151                    this.playersArrayList.remove(var4);
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 var10 = 1 << this.scale;
164            float var11 = (float)(par4 - (double)this.xCenter) / (float)var10;
165            float var12 = (float)(par6 - (double)this.zCenter) / (float)var10;
166            byte var13 = (byte)((int)((double)(var11 * 2.0F) + 0.5D));
167            byte var14 = (byte)((int)((double)(var12 * 2.0F) + 0.5D));
168            byte var16 = 63;
169            byte var15;
170    
171            if (var11 >= (float)(-var16) && var12 >= (float)(-var16) && var11 <= (float)var16 && var12 <= (float)var16)
172            {
173                par8 += par8 < 0.0D ? -8.0D : 8.0D;
174                var15 = (byte)((int)(par8 * 16.0D / 360.0D));
175    
176                if (par2World.provider.shouldMapSpin(par3Str, par4, par6, par8))
177                {
178                    int var17 = (int)(par2World.getWorldInfo().getWorldTime() / 10L);
179                    var15 = (byte)(var17 * var17 * 34187121 + var17 * 121 >> 15 & 15);
180                }
181            }
182            else
183            {
184                if (Math.abs(var11) >= 320.0F || Math.abs(var12) >= 320.0F)
185                {
186                    this.playersVisibleOnMap.remove(par3Str);
187                    return;
188                }
189    
190                par1 = 6;
191                var15 = 0;
192    
193                if (var11 <= (float)(-var16))
194                {
195                    var13 = (byte)((int)((double)(var16 * 2) + 2.5D));
196                }
197    
198                if (var12 <= (float)(-var16))
199                {
200                    var14 = (byte)((int)((double)(var16 * 2) + 2.5D));
201                }
202    
203                if (var11 >= (float)var16)
204                {
205                    var13 = (byte)(var16 * 2 + 1);
206                }
207    
208                if (var12 >= (float)var16)
209                {
210                    var14 = (byte)(var16 * 2 + 1);
211                }
212            }
213    
214            this.playersVisibleOnMap.put(par3Str, new MapCoord(this, (byte)par1, var13, var14, var15));
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 var4 = (MapInfo)this.playersHashMap.get(par3EntityPlayer);
223            return var4 == null ? null : var4.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 var4 = 0; var4 < this.playersArrayList.size(); ++var4)
235            {
236                MapInfo var5 = (MapInfo)this.playersArrayList.get(var4);
237    
238                if (var5.field_76209_b[par1] < 0 || var5.field_76209_b[par1] > par2)
239                {
240                    var5.field_76209_b[par1] = par2;
241                }
242    
243                if (var5.field_76210_c[par1] < 0 || var5.field_76210_c[par1] < par3)
244                {
245                    var5.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 var2;
258    
259            if (par1ArrayOfByte[0] == 0)
260            {
261                var2 = par1ArrayOfByte[1] & 255;
262                int var3 = par1ArrayOfByte[2] & 255;
263    
264                for (int var4 = 0; var4 < par1ArrayOfByte.length - 3; ++var4)
265                {
266                    this.colors[(var4 + var3) * 128 + var2] = par1ArrayOfByte[var4 + 3];
267                }
268    
269                this.markDirty();
270            }
271            else if (par1ArrayOfByte[0] == 1)
272            {
273                this.playersVisibleOnMap.clear();
274    
275                for (var2 = 0; var2 < (par1ArrayOfByte.length - 1) / 3; ++var2)
276                {
277                    byte var7 = (byte)(par1ArrayOfByte[var2 * 3 + 1] >> 4);
278                    byte var8 = par1ArrayOfByte[var2 * 3 + 2];
279                    byte var5 = par1ArrayOfByte[var2 * 3 + 3];
280                    byte var6 = (byte)(par1ArrayOfByte[var2 * 3 + 1] & 15);
281                    this.playersVisibleOnMap.put("icon-" + var2, new MapCoord(this, var7, var8, var5, var6));
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 var2 = (MapInfo)this.playersHashMap.get(par1EntityPlayer);
293    
294            if (var2 == null)
295            {
296                var2 = new MapInfo(this, par1EntityPlayer);
297                this.playersHashMap.put(par1EntityPlayer, var2);
298                this.playersArrayList.add(var2);
299            }
300    
301            return var2;
302        }
303    }