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 }