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