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