    001    package net.minecraft.src;
    002
    003    import java.util.ArrayList;
    004    import java.util.List;
    005
    006    public class PlayerManager
    007    {
    008        private final WorldServer theWorldServer;
    009
    010        /** players in the current instance */
    011        private final List players = new ArrayList();
    012
    013        /**
    014         * A map of chunk position (two ints concatenated into a long) to PlayerInstance
    015         */
    016        private final LongHashMap playerInstances = new LongHashMap();
    017
    018        /**
    019         * contains a PlayerInstance for every chunk they can see. the "player instance" cotains a list of all players who
    020         * can also that chunk
    021         */
    022        private final List chunkWatcherWithPlayers = new ArrayList();
    023
    024        /**
    025         * Number of chunks the server sends to the client. Valid 3<=x<=15. In server.properties.
    026         */
    027        private final int playerViewRadius;
    028
    029        /** x, z direction vectors: east, south, west, north */
    030        private final int[][] xzDirectionsConst = new int[][] {{1, 0}, {0, 1}, { -1, 0}, {0, -1}};
    031
    032        public PlayerManager(WorldServer par1WorldServer, int par2)
    033        {
    034            if (par2 > 15)
    035            {
    036                throw new IllegalArgumentException("Too big view radius!");
    037            }
    038            else if (par2 < 3)
    039            {
    040                throw new IllegalArgumentException("Too small view radius!");
    041            }
    042            else
    043            {
    044                this.playerViewRadius = par2;
    045                this.theWorldServer = par1WorldServer;
    046            }
    047        }
    048
    049        public WorldServer getWorldServer()
    050        {
    051            return this.theWorldServer;
    052        }
    053
    054        /**
    055         * updates all the player instances that need to be updated
    056         */
    057        public void updatePlayerInstances()
    058        {
    059            for (int var1 = 0; var1 < this.chunkWatcherWithPlayers.size(); ++var1)
    060            {
    061                ((PlayerInstance)this.chunkWatcherWithPlayers.get(var1)).sendChunkUpdate();
    062            }
    063
    064            this.chunkWatcherWithPlayers.clear();
    065
    066            if (this.players.isEmpty())
    067            {
    068                WorldProvider var2 = this.theWorldServer.provider;
    069
    070                if (!var2.canRespawnHere())
    071                {
    072                    this.theWorldServer.theChunkProviderServer.unloadAllChunks();
    073                }
    074            }
    075        }
    076
    077        PlayerInstance getOrCreateChunkWatcher(int par1, int par2, boolean par3)
    078        {
    079            long var4 = (long)par1 + 2147483647L | (long)par2 + 2147483647L << 32;
    080            PlayerInstance var6 = (PlayerInstance)this.playerInstances.getValueByKey(var4);
    081
    082            if (var6 == null && par3)
    083            {
    084                var6 = new PlayerInstance(this, par1, par2);
    085                this.playerInstances.add(var4, var6);
    086            }
    087
    088            return var6;
    089        }
    090
    091        /**
    092         * the "PlayerInstance"/ chunkWatcher will send this chunk to all players who are in line of sight
    093         */
    094        public void flagChunkForUpdate(int par1, int par2, int par3)
    095        {
    096            int var4 = par1 >> 4;
    097            int var5 = par3 >> 4;
    098            PlayerInstance var6 = this.getOrCreateChunkWatcher(var4, var5, false);
    099
    100            if (var6 != null)
    101            {
    102                var6.flagChunkForUpdate(par1 & 15, par2, par3 & 15);
    103            }
    104        }
    105
    106        /**
    107         * Adds an EntityPlayerMP to the PlayerManager.
    108         */
    109        public void addPlayer(EntityPlayerMP par1EntityPlayerMP)
    110        {
    111            int var2 = (int)par1EntityPlayerMP.posX >> 4;
    112            int var3 = (int)par1EntityPlayerMP.posZ >> 4;
    113            par1EntityPlayerMP.managedPosX = par1EntityPlayerMP.posX;
    114            par1EntityPlayerMP.managedPosZ = par1EntityPlayerMP.posZ;
    115
    116            for (int var4 = var2 - this.playerViewRadius; var4 <= var2 + this.playerViewRadius; ++var4)
    117            {
    118                for (int var5 = var3 - this.playerViewRadius; var5 <= var3 + this.playerViewRadius; ++var5)
    119                {
    120                    this.getOrCreateChunkWatcher(var4, var5, true).addPlayerToChunkWatchingList(par1EntityPlayerMP);
    121                }
    122            }
    123
    124            this.players.add(par1EntityPlayerMP);
    125            this.func_72691_b(par1EntityPlayerMP);
    126        }
    127
    128        public void func_72691_b(EntityPlayerMP par1EntityPlayerMP)
    129        {
    130            ArrayList var2 = new ArrayList(par1EntityPlayerMP.loadedChunks);
    131            int var3 = 0;
    132            int var4 = this.playerViewRadius;
    133            int var5 = (int)par1EntityPlayerMP.posX >> 4;
    134            int var6 = (int)par1EntityPlayerMP.posZ >> 4;
    135            int var7 = 0;
    136            int var8 = 0;
    137            ChunkCoordIntPair var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5, var6, true));
    138            par1EntityPlayerMP.loadedChunks.clear();
    139
    140            if (var2.contains(var9))
    141            {
    142                par1EntityPlayerMP.loadedChunks.add(var9);
    143            }
    144
    145            int var10;
    146
    147            for (var10 = 1; var10 <= var4 * 2; ++var10)
    148            {
    149                for (int var11 = 0; var11 < 2; ++var11)
    150                {
    151                    int[] var12 = this.xzDirectionsConst[var3++ % 4];
    152
    153                    for (int var13 = 0; var13 < var10; ++var13)
    154                    {
    155                        var7 += var12[0];
    156                        var8 += var12[1];
    157                        var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5 + var7, var6 + var8, true));
    158
    159                        if (var2.contains(var9))
    160                        {
    161                            par1EntityPlayerMP.loadedChunks.add(var9);
    162                        }
    163                    }
    164                }
    165            }
    166
    167            var3 %= 4;
    168
    169            for (var10 = 0; var10 < var4 * 2; ++var10)
    170            {
    171                var7 += this.xzDirectionsConst[var3][0];
    172                var8 += this.xzDirectionsConst[var3][1];
    173                var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5 + var7, var6 + var8, true));
    174
    175                if (var2.contains(var9))
    176                {
    177                    par1EntityPlayerMP.loadedChunks.add(var9);
    178                }
    179            }
    180        }
    181
    182        /**
    183         * Removes an EntityPlayerMP from the PlayerManager.
    184         */
    185        public void removePlayer(EntityPlayerMP par1EntityPlayerMP)
    186        {
    187            int var2 = (int)par1EntityPlayerMP.managedPosX >> 4;
    188            int var3 = (int)par1EntityPlayerMP.managedPosZ >> 4;
    189
    190            for (int var4 = var2 - this.playerViewRadius; var4 <= var2 + this.playerViewRadius; ++var4)
    191            {
    192                for (int var5 = var3 - this.playerViewRadius; var5 <= var3 + this.playerViewRadius; ++var5)
    193                {
    194                    PlayerInstance var6 = this.getOrCreateChunkWatcher(var4, var5, false);
    195
    196                    if (var6 != null)
    197                    {
    198                        var6.sendThisChunkToPlayer(par1EntityPlayerMP);
    199                    }
    200                }
    201            }
    202
    203            this.players.remove(par1EntityPlayerMP);
    204        }
    205
    206        private boolean func_72684_a(int par1, int par2, int par3, int par4, int par5)
    207        {
    208            int var6 = par1 - par3;
    209            int var7 = par2 - par4;
    210            return var6 >= -par5 && var6 <= par5 ? var7 >= -par5 && var7 <= par5 : false;
    211        }
    212
    213        /**
    214         * update chunks around a player being moved by server logic (e.g. cart, boat)
    215         */
    216        public void updateMountedMovingPlayer(EntityPlayerMP par1EntityPlayerMP)
    217        {
    218            int var2 = (int)par1EntityPlayerMP.posX >> 4;
    219            int var3 = (int)par1EntityPlayerMP.posZ >> 4;
    220            double var4 = par1EntityPlayerMP.managedPosX - par1EntityPlayerMP.posX;
    221            double var6 = par1EntityPlayerMP.managedPosZ - par1EntityPlayerMP.posZ;
    222            double var8 = var4 * var4 + var6 * var6;
    223
    224            if (var8 >= 64.0D)
    225            {
    226                int var10 = (int)par1EntityPlayerMP.managedPosX >> 4;
    227                int var11 = (int)par1EntityPlayerMP.managedPosZ >> 4;
    228                int var12 = this.playerViewRadius;
    229                int var13 = var2 - var10;
    230                int var14 = var3 - var11;
    231
    232                if (var13 != 0 || var14 != 0)
    233                {
    234                    for (int var15 = var2 - var12; var15 <= var2 + var12; ++var15)
    235                    {
    236                        for (int var16 = var3 - var12; var16 <= var3 + var12; ++var16)
    237                        {
    238                            if (!this.func_72684_a(var15, var16, var10, var11, var12))
    239                            {
    240                                this.getOrCreateChunkWatcher(var15, var16, true).addPlayerToChunkWatchingList(par1EntityPlayerMP);
    241                            }
    242
    243                            if (!this.func_72684_a(var15 - var13, var16 - var14, var2, var3, var12))
    244                            {
    245                                PlayerInstance var17 = this.getOrCreateChunkWatcher(var15 - var13, var16 - var14, false);
    246
    247                                if (var17 != null)
    248                                {
    249                                    var17.sendThisChunkToPlayer(par1EntityPlayerMP);
    250                                }
    251                            }
    252                        }
    253                    }
    254
    255                    this.func_72691_b(par1EntityPlayerMP);
    256                    par1EntityPlayerMP.managedPosX = par1EntityPlayerMP.posX;
    257                    par1EntityPlayerMP.managedPosZ = par1EntityPlayerMP.posZ;
    258                }
    259            }
    260        }
    261
    262        public boolean isPlayerWatchingChunk(EntityPlayerMP par1EntityPlayerMP, int par2, int par3)
    263        {
    264            PlayerInstance var4 = this.getOrCreateChunkWatcher(par2, par3, false);
    265            return var4 == null ? false : PlayerInstance.getPlayersInChunk(var4).contains(par1EntityPlayerMP) && !par1EntityPlayerMP.loadedChunks.contains(PlayerInstance.getChunkLocation(var4));
    266        }
    267
    268        public static int func_72686_a(int par0)
    269        {
    270            return par0 * 16 - 16;
    271        }
    272
    273        static WorldServer getWorldServer(PlayerManager par0PlayerManager)
    274        {
    275            return par0PlayerManager.theWorldServer;
    276        }
    277
    278        static LongHashMap getChunkWatchers(PlayerManager par0PlayerManager)
    279        {
    280            return par0PlayerManager.playerInstances;
    281        }
    282
    283        static List getChunkWatchersWithPlayers(PlayerManager par0PlayerManager)
    284        {
    285            return par0PlayerManager.chunkWatcherWithPlayers;
    286        }
    287    }