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