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 }