    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 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}