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 public 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.filterChunkLoadQueue(par1EntityPlayerMP); 126 } 127 128 /** 129 * Removes all chunks from the given player's chunk load queue that are not in viewing range of the player. 130 */ 131 public void filterChunkLoadQueue(EntityPlayerMP par1EntityPlayerMP) 132 { 133 ArrayList var2 = new ArrayList(par1EntityPlayerMP.loadedChunks); 134 int var3 = 0; 135 int var4 = this.playerViewRadius; 136 int var5 = (int)par1EntityPlayerMP.posX >> 4; 137 int var6 = (int)par1EntityPlayerMP.posZ >> 4; 138 int var7 = 0; 139 int var8 = 0; 140 ChunkCoordIntPair var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5, var6, true)); 141 par1EntityPlayerMP.loadedChunks.clear(); 142 143 if (var2.contains(var9)) 144 { 145 par1EntityPlayerMP.loadedChunks.add(var9); 146 } 147 148 int var10; 149 150 for (var10 = 1; var10 <= var4 * 2; ++var10) 151 { 152 for (int var11 = 0; var11 < 2; ++var11) 153 { 154 int[] var12 = this.xzDirectionsConst[var3++ % 4]; 155 156 for (int var13 = 0; var13 < var10; ++var13) 157 { 158 var7 += var12[0]; 159 var8 += var12[1]; 160 var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5 + var7, var6 + var8, true)); 161 162 if (var2.contains(var9)) 163 { 164 par1EntityPlayerMP.loadedChunks.add(var9); 165 } 166 } 167 } 168 } 169 170 var3 %= 4; 171 172 for (var10 = 0; var10 < var4 * 2; ++var10) 173 { 174 var7 += this.xzDirectionsConst[var3][0]; 175 var8 += this.xzDirectionsConst[var3][1]; 176 var9 = PlayerInstance.getChunkLocation(this.getOrCreateChunkWatcher(var5 + var7, var6 + var8, true)); 177 178 if (var2.contains(var9)) 179 { 180 par1EntityPlayerMP.loadedChunks.add(var9); 181 } 182 } 183 } 184 185 /** 186 * Removes an EntityPlayerMP from the PlayerManager. 187 */ 188 public void removePlayer(EntityPlayerMP par1EntityPlayerMP) 189 { 190 int var2 = (int)par1EntityPlayerMP.managedPosX >> 4; 191 int var3 = (int)par1EntityPlayerMP.managedPosZ >> 4; 192 193 for (int var4 = var2 - this.playerViewRadius; var4 <= var2 + this.playerViewRadius; ++var4) 194 { 195 for (int var5 = var3 - this.playerViewRadius; var5 <= var3 + this.playerViewRadius; ++var5) 196 { 197 PlayerInstance var6 = this.getOrCreateChunkWatcher(var4, var5, false); 198 199 if (var6 != null) 200 { 201 var6.sendThisChunkToPlayer(par1EntityPlayerMP); 202 } 203 } 204 } 205 206 this.players.remove(par1EntityPlayerMP); 207 } 208 209 private boolean func_72684_a(int par1, int par2, int par3, int par4, int par5) 210 { 211 int var6 = par1 - par3; 212 int var7 = par2 - par4; 213 return var6 >= -par5 && var6 <= par5 ? var7 >= -par5 && var7 <= par5 : false; 214 } 215 216 /** 217 * update chunks around a player being moved by server logic (e.g. cart, boat) 218 */ 219 public void updateMountedMovingPlayer(EntityPlayerMP par1EntityPlayerMP) 220 { 221 int var2 = (int)par1EntityPlayerMP.posX >> 4; 222 int var3 = (int)par1EntityPlayerMP.posZ >> 4; 223 double var4 = par1EntityPlayerMP.managedPosX - par1EntityPlayerMP.posX; 224 double var6 = par1EntityPlayerMP.managedPosZ - par1EntityPlayerMP.posZ; 225 double var8 = var4 * var4 + var6 * var6; 226 227 if (var8 >= 64.0D) 228 { 229 int var10 = (int)par1EntityPlayerMP.managedPosX >> 4; 230 int var11 = (int)par1EntityPlayerMP.managedPosZ >> 4; 231 int var12 = this.playerViewRadius; 232 int var13 = var2 - var10; 233 int var14 = var3 - var11; 234 235 if (var13 != 0 || var14 != 0) 236 { 237 for (int var15 = var2 - var12; var15 <= var2 + var12; ++var15) 238 { 239 for (int var16 = var3 - var12; var16 <= var3 + var12; ++var16) 240 { 241 if (!this.func_72684_a(var15, var16, var10, var11, var12)) 242 { 243 this.getOrCreateChunkWatcher(var15, var16, true).addPlayerToChunkWatchingList(par1EntityPlayerMP); 244 } 245 246 if (!this.func_72684_a(var15 - var13, var16 - var14, var2, var3, var12)) 247 { 248 PlayerInstance var17 = this.getOrCreateChunkWatcher(var15 - var13, var16 - var14, false); 249 250 if (var17 != null) 251 { 252 var17.sendThisChunkToPlayer(par1EntityPlayerMP); 253 } 254 } 255 } 256 } 257 258 this.filterChunkLoadQueue(par1EntityPlayerMP); 259 par1EntityPlayerMP.managedPosX = par1EntityPlayerMP.posX; 260 par1EntityPlayerMP.managedPosZ = par1EntityPlayerMP.posZ; 261 } 262 } 263 } 264 265 public boolean isPlayerWatchingChunk(EntityPlayerMP par1EntityPlayerMP, int par2, int par3) 266 { 267 PlayerInstance var4 = this.getOrCreateChunkWatcher(par2, par3, false); 268 return var4 == null ? false : PlayerInstance.getPlayersInChunk(var4).contains(par1EntityPlayerMP) && !par1EntityPlayerMP.loadedChunks.contains(PlayerInstance.getChunkLocation(var4)); 269 } 270 271 public static int func_72686_a(int par0) 272 { 273 return par0 * 16 - 16; 274 } 275 276 static WorldServer getWorldServer(PlayerManager par0PlayerManager) 277 { 278 return par0PlayerManager.theWorldServer; 279 } 280 281 static LongHashMap getChunkWatchers(PlayerManager par0PlayerManager) 282 { 283 return par0PlayerManager.playerInstances; 284 } 285 286 static List getChunkWatchersWithPlayers(PlayerManager par0PlayerManager) 287 { 288 return par0PlayerManager.chunkWatcherWithPlayers; 289 } 290 }