001    package net.minecraft.server.management;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import cpw.mods.fml.common.network.FMLNetworkHandler;
006    import cpw.mods.fml.common.registry.GameRegistry;
007    
008    import java.io.File;
009    import java.net.SocketAddress;
010    import java.text.SimpleDateFormat;
011    import java.util.ArrayList;
012    import java.util.Collections;
013    import java.util.HashSet;
014    import java.util.Iterator;
015    import java.util.List;
016    import java.util.Set;
017    import java.util.logging.Logger;
018    import net.minecraft.entity.Entity;
019    import net.minecraft.entity.player.EntityPlayer;
020    import net.minecraft.entity.player.EntityPlayerMP;
021    import net.minecraft.item.ItemInWorldManager;
022    import net.minecraft.nbt.NBTTagCompound;
023    import net.minecraft.network.INetworkManager;
024    import net.minecraft.network.NetServerHandler;
025    import net.minecraft.network.packet.Packet;
026    import net.minecraft.network.packet.Packet1Login;
027    import net.minecraft.network.packet.Packet201PlayerInfo;
028    import net.minecraft.network.packet.Packet202PlayerAbilities;
029    import net.minecraft.network.packet.Packet3Chat;
030    import net.minecraft.network.packet.Packet41EntityEffect;
031    import net.minecraft.network.packet.Packet43Experience;
032    import net.minecraft.network.packet.Packet4UpdateTime;
033    import net.minecraft.network.packet.Packet6SpawnPosition;
034    import net.minecraft.network.packet.Packet70GameEvent;
035    import net.minecraft.network.packet.Packet9Respawn;
036    import net.minecraft.potion.PotionEffect;
037    import net.minecraft.server.MinecraftServer;
038    import net.minecraft.util.ChunkCoordinates;
039    import net.minecraft.util.MathHelper;
040    import net.minecraft.world.EnumGameType;
041    import net.minecraft.world.Teleporter;
042    import net.minecraft.world.World;
043    import net.minecraft.world.WorldProvider;
044    import net.minecraft.world.WorldServer;
045    import net.minecraft.world.demo.DemoWorldManager;
046    import net.minecraft.world.storage.IPlayerFileData;
047    
048    import net.minecraftforge.common.DimensionManager;
049    
050    public abstract class ServerConfigurationManager
051    {
052        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd \'at\' HH:mm:ss z");
053    
054        /** Reference to the logger. */
055        public static final Logger logger = Logger.getLogger("Minecraft");
056    
057        /** Reference to the MinecraftServer object. */
058        private final MinecraftServer mcServer;
059    
060        /** A list of player entities that exist on this server. */
061        public final List playerEntityList = new ArrayList();
062        private final BanList bannedPlayers = new BanList(new File("banned-players.txt"));
063        private final BanList bannedIPs = new BanList(new File("banned-ips.txt"));
064    
065        /** A set containing the OPs. */
066        private Set ops = new HashSet();
067    
068        /** The Set of all whitelisted players. */
069        private Set whiteListedPlayers = new HashSet();
070    
071        /** Reference to the PlayerNBTManager object. */
072        private IPlayerFileData playerNBTManagerObj;
073    
074        /**
075         * Server setting to only allow OPs and whitelisted players to join the server.
076         */
077        private boolean whiteListEnforced;
078    
079        /** The maximum number of players that can be connected at a time. */
080        protected int maxPlayers;
081        protected int viewDistance;
082        private EnumGameType gameType;
083    
084        /** True if all players are allowed to use commands (cheats). */
085        private boolean commandsAllowedForAll;
086    
087        /**
088         * index into playerEntities of player to ping, updated every tick; currently hardcoded to max at 200 players
089         */
090        private int playerPingIndex = 0;
091    
092        public ServerConfigurationManager(MinecraftServer par1MinecraftServer)
093        {
094            this.mcServer = par1MinecraftServer;
095            this.bannedPlayers.setListActive(false);
096            this.bannedIPs.setListActive(false);
097            this.maxPlayers = 8;
098        }
099    
100        public void initializeConnectionToPlayer(INetworkManager par1INetworkManager, EntityPlayerMP par2EntityPlayerMP)
101        {
102            this.readPlayerDataFromFile(par2EntityPlayerMP);
103            par2EntityPlayerMP.setWorld(this.mcServer.worldServerForDimension(par2EntityPlayerMP.dimension));
104            par2EntityPlayerMP.theItemInWorldManager.setWorld((WorldServer)par2EntityPlayerMP.worldObj);
105            String var3 = "local";
106    
107            if (par1INetworkManager.getSocketAddress() != null)
108            {
109                var3 = par1INetworkManager.getSocketAddress().toString();
110            }
111    
112            logger.info(par2EntityPlayerMP.username + "[" + var3 + "] logged in with entity id " + par2EntityPlayerMP.entityId + " at (" + par2EntityPlayerMP.posX + ", " + par2EntityPlayerMP.posY + ", " + par2EntityPlayerMP.posZ + ")");
113            WorldServer var4 = this.mcServer.worldServerForDimension(par2EntityPlayerMP.dimension);
114            ChunkCoordinates var5 = var4.getSpawnPoint();
115            this.func_72381_a(par2EntityPlayerMP, (EntityPlayerMP)null, var4);
116            NetServerHandler var6 = new NetServerHandler(this.mcServer, par1INetworkManager, par2EntityPlayerMP);
117            var6.sendPacketToPlayer(new Packet1Login(par2EntityPlayerMP.entityId, var4.getWorldInfo().getTerrainType(), par2EntityPlayerMP.theItemInWorldManager.getGameType(), var4.getWorldInfo().isHardcoreModeEnabled(), var4.provider.dimensionId, var4.difficultySetting, var4.getHeight(), this.getMaxPlayers()));
118            var6.sendPacketToPlayer(new Packet6SpawnPosition(var5.posX, var5.posY, var5.posZ));
119            var6.sendPacketToPlayer(new Packet202PlayerAbilities(par2EntityPlayerMP.capabilities));
120            this.updateTimeAndWeatherForPlayer(par2EntityPlayerMP, var4);
121            this.sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + par2EntityPlayerMP.username + " joined the game."));
122            this.playerLoggedIn(par2EntityPlayerMP);
123            var6.setPlayerLocation(par2EntityPlayerMP.posX, par2EntityPlayerMP.posY, par2EntityPlayerMP.posZ, par2EntityPlayerMP.rotationYaw, par2EntityPlayerMP.rotationPitch);
124            this.mcServer.getNetworkThread().addPlayer(var6);
125            var6.sendPacketToPlayer(new Packet4UpdateTime(var4.getTotalWorldTime(), var4.getWorldTime()));
126    
127            if (this.mcServer.getTexturePack().length() > 0)
128            {
129                par2EntityPlayerMP.requestTexturePackLoad(this.mcServer.getTexturePack(), this.mcServer.textureSize());
130            }
131    
132            Iterator var7 = par2EntityPlayerMP.getActivePotionEffects().iterator();
133    
134            while (var7.hasNext())
135            {
136                PotionEffect var8 = (PotionEffect)var7.next();
137                var6.sendPacketToPlayer(new Packet41EntityEffect(par2EntityPlayerMP.entityId, var8));
138            }
139    
140            par2EntityPlayerMP.addSelfToInternalCraftingInventory();
141    
142            FMLNetworkHandler.handlePlayerLogin(par2EntityPlayerMP, var6, par1INetworkManager);
143        }
144    
145        /**
146         * Sets the NBT manager to the one for the WorldServer given.
147         */
148        public void setPlayerManager(WorldServer[] par1ArrayOfWorldServer)
149        {
150            this.playerNBTManagerObj = par1ArrayOfWorldServer[0].getSaveHandler().getSaveHandler();
151        }
152    
153        public void func_72375_a(EntityPlayerMP par1EntityPlayerMP, WorldServer par2WorldServer)
154        {
155            WorldServer var3 = par1EntityPlayerMP.getServerForPlayer();
156    
157            if (par2WorldServer != null)
158            {
159                par2WorldServer.getPlayerManager().removePlayer(par1EntityPlayerMP);
160            }
161    
162            var3.getPlayerManager().addPlayer(par1EntityPlayerMP);
163            var3.theChunkProviderServer.loadChunk((int)par1EntityPlayerMP.posX >> 4, (int)par1EntityPlayerMP.posZ >> 4);
164        }
165    
166        public int getEntityViewDistance()
167        {
168            return PlayerManager.func_72686_a(this.getViewDistance());
169        }
170    
171        /**
172         * called during player login. reads the player information from disk.
173         */
174        public void readPlayerDataFromFile(EntityPlayerMP par1EntityPlayerMP)
175        {
176            NBTTagCompound var2 = this.mcServer.worldServers[0].getWorldInfo().getPlayerNBTTagCompound();
177    
178            if (par1EntityPlayerMP.getCommandSenderName().equals(this.mcServer.getServerOwner()) && var2 != null)
179            {
180                par1EntityPlayerMP.readFromNBT(var2);
181            }
182            else
183            {
184                this.playerNBTManagerObj.readPlayerData(par1EntityPlayerMP);
185            }
186        }
187    
188        /**
189         * also stores the NBTTags if this is an intergratedPlayerList
190         */
191        protected void writePlayerData(EntityPlayerMP par1EntityPlayerMP)
192        {
193            this.playerNBTManagerObj.writePlayerData(par1EntityPlayerMP);
194        }
195    
196        /**
197         * Called when a player successfully logs in. Reads player data from disk and inserts the player into the world.
198         */
199        public void playerLoggedIn(EntityPlayerMP par1EntityPlayerMP)
200        {
201            this.sendPacketToAllPlayers(new Packet201PlayerInfo(par1EntityPlayerMP.username, true, 1000));
202            this.playerEntityList.add(par1EntityPlayerMP);
203            WorldServer var2 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
204            var2.spawnEntityInWorld(par1EntityPlayerMP);
205            this.func_72375_a(par1EntityPlayerMP, (WorldServer)null);
206    
207            for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3)
208            {
209                EntityPlayerMP var4 = (EntityPlayerMP)this.playerEntityList.get(var3);
210                par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet201PlayerInfo(var4.username, true, var4.ping));
211            }
212        }
213    
214        /**
215         * using player's dimension, update their movement when in a vehicle (e.g. cart, boat)
216         */
217        public void serverUpdateMountedMovingPlayer(EntityPlayerMP par1EntityPlayerMP)
218        {
219            par1EntityPlayerMP.getServerForPlayer().getPlayerManager().updateMountedMovingPlayer(par1EntityPlayerMP);
220        }
221    
222        /**
223         * Called when a player disconnects from the game. Writes player data to disk and removes them from the world.
224         */
225        public void playerLoggedOut(EntityPlayerMP par1EntityPlayerMP)
226        {
227            GameRegistry.onPlayerLogout(par1EntityPlayerMP);
228            this.writePlayerData(par1EntityPlayerMP);
229            WorldServer var2 = par1EntityPlayerMP.getServerForPlayer();
230            var2.setEntityDead(par1EntityPlayerMP);
231            var2.getPlayerManager().removePlayer(par1EntityPlayerMP);
232            this.playerEntityList.remove(par1EntityPlayerMP);
233            this.sendPacketToAllPlayers(new Packet201PlayerInfo(par1EntityPlayerMP.username, false, 9999));
234        }
235    
236        /**
237         * checks ban-lists, then white-lists, then space for the server. Returns null on success, or an error message
238         */
239        public String allowUserToConnect(SocketAddress par1SocketAddress, String par2Str)
240        {
241            if (this.bannedPlayers.isBanned(par2Str))
242            {
243                BanEntry var6 = (BanEntry)this.bannedPlayers.getBannedList().get(par2Str);
244                String var7 = "You are banned from this server!\nReason: " + var6.getBanReason();
245    
246                if (var6.getBanEndDate() != null)
247                {
248                    var7 = var7 + "\nYour ban will be removed on " + dateFormat.format(var6.getBanEndDate());
249                }
250    
251                return var7;
252            }
253            else if (!this.isAllowedToLogin(par2Str))
254            {
255                return "You are not white-listed on this server!";
256            }
257            else
258            {
259                String var3 = par1SocketAddress.toString();
260                var3 = var3.substring(var3.indexOf("/") + 1);
261                var3 = var3.substring(0, var3.indexOf(":"));
262    
263                if (this.bannedIPs.isBanned(var3))
264                {
265                    BanEntry var4 = (BanEntry)this.bannedIPs.getBannedList().get(var3);
266                    String var5 = "Your IP address is banned from this server!\nReason: " + var4.getBanReason();
267    
268                    if (var4.getBanEndDate() != null)
269                    {
270                        var5 = var5 + "\nYour ban will be removed on " + dateFormat.format(var4.getBanEndDate());
271                    }
272    
273                    return var5;
274                }
275                else
276                {
277                    return this.playerEntityList.size() >= this.maxPlayers ? "The server is full!" : null;
278                }
279            }
280        }
281    
282        /**
283         * also checks for multiple logins
284         */
285        public EntityPlayerMP createPlayerForUser(String par1Str)
286        {
287            ArrayList var2 = new ArrayList();
288            EntityPlayerMP var4;
289    
290            for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3)
291            {
292                var4 = (EntityPlayerMP)this.playerEntityList.get(var3);
293    
294                if (var4.username.equalsIgnoreCase(par1Str))
295                {
296                    var2.add(var4);
297                }
298            }
299    
300            Iterator var5 = var2.iterator();
301    
302            while (var5.hasNext())
303            {
304                var4 = (EntityPlayerMP)var5.next();
305                var4.playerNetServerHandler.kickPlayerFromServer("You logged in from another location");
306            }
307    
308            Object var6;
309    
310            if (this.mcServer.isDemo())
311            {
312                var6 = new DemoWorldManager(this.mcServer.worldServerForDimension(0));
313            }
314            else
315            {
316                var6 = new ItemInWorldManager(this.mcServer.worldServerForDimension(0));
317            }
318    
319            return new EntityPlayerMP(this.mcServer, this.mcServer.worldServerForDimension(0), par1Str, (ItemInWorldManager)var6);
320        }
321    
322        /**
323         * creates and returns a respawned player based on the provided PlayerEntity. Args are the PlayerEntityMP to
324         * respawn, an INT for the dimension to respawn into (usually 0), and a boolean value that is true if the player
325         * beat the game rather than dying
326         */
327        public EntityPlayerMP respawnPlayer(EntityPlayerMP par1EntityPlayerMP, int par2, boolean par3)
328        {
329            World world = mcServer.worldServerForDimension(par2);
330            if (world == null)
331            {
332                par2 = 0;
333            }
334            else if (!world.provider.canRespawnHere())
335            {
336                par2 = world.provider.getRespawnDimension(par1EntityPlayerMP);
337            }
338    
339            par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removeAllTrackingPlayers(par1EntityPlayerMP);
340            par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removeEntityFromAllTrackingPlayers(par1EntityPlayerMP);
341            par1EntityPlayerMP.getServerForPlayer().getPlayerManager().removePlayer(par1EntityPlayerMP);
342            this.playerEntityList.remove(par1EntityPlayerMP);
343            this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension).removeEntity(par1EntityPlayerMP);
344            ChunkCoordinates var4 = par1EntityPlayerMP.getBedLocation();
345            boolean var5 = par1EntityPlayerMP.isSpawnForced();
346            par1EntityPlayerMP.dimension = par2;
347            Object var6;
348    
349            if (this.mcServer.isDemo())
350            {
351                var6 = new DemoWorldManager(this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension));
352            }
353            else
354            {
355                var6 = new ItemInWorldManager(this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension));
356            }
357    
358            EntityPlayerMP var7 = new EntityPlayerMP(this.mcServer, this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension), par1EntityPlayerMP.username, (ItemInWorldManager)var6);
359            var7.playerNetServerHandler = par1EntityPlayerMP.playerNetServerHandler;
360            var7.clonePlayer(par1EntityPlayerMP, par3);
361            var7.dimension = par2;
362            var7.entityId = par1EntityPlayerMP.entityId;
363            WorldServer var8 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
364            this.func_72381_a(var7, par1EntityPlayerMP, var8);
365            ChunkCoordinates var9;
366    
367            if (var4 != null)
368            {
369                var9 = EntityPlayer.verifyRespawnCoordinates(this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension), var4, var5);
370    
371                if (var9 != null)
372                {
373                    var7.setLocationAndAngles((double)((float)var9.posX + 0.5F), (double)((float)var9.posY + 0.1F), (double)((float)var9.posZ + 0.5F), 0.0F, 0.0F);
374                    var7.setSpawnChunk(var4, var5);
375                }
376                else
377                {
378                    var7.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(0, 0));
379                }
380            }
381    
382            var8.theChunkProviderServer.loadChunk((int)var7.posX >> 4, (int)var7.posZ >> 4);
383    
384            while (!var8.getCollidingBoundingBoxes(var7, var7.boundingBox).isEmpty())
385            {
386                var7.setPosition(var7.posX, var7.posY + 1.0D, var7.posZ);
387            }
388    
389            var7.playerNetServerHandler.sendPacketToPlayer(new Packet9Respawn(var7.dimension, (byte)var7.worldObj.difficultySetting, var7.worldObj.getWorldInfo().getTerrainType(), var7.worldObj.getHeight(), var7.theItemInWorldManager.getGameType()));
390            var9 = var8.getSpawnPoint();
391            var7.playerNetServerHandler.setPlayerLocation(var7.posX, var7.posY, var7.posZ, var7.rotationYaw, var7.rotationPitch);
392            var7.playerNetServerHandler.sendPacketToPlayer(new Packet6SpawnPosition(var9.posX, var9.posY, var9.posZ));
393            var7.playerNetServerHandler.sendPacketToPlayer(new Packet43Experience(var7.experience, var7.experienceTotal, var7.experienceLevel));
394            this.updateTimeAndWeatherForPlayer(var7, var8);
395            var8.getPlayerManager().addPlayer(var7);
396            var8.spawnEntityInWorld(var7);
397            this.playerEntityList.add(var7);
398            var7.addSelfToInternalCraftingInventory();
399            GameRegistry.onPlayerRespawn(var7);
400            return var7;
401        }
402    
403        public void transferPlayerToDimension(EntityPlayerMP par1EntityPlayerMP, int par2)
404        {
405            transferPlayerToDimension(par1EntityPlayerMP, par2, mcServer.worldServerForDimension(par2).func_85176_s());
406        }
407    
408        public void transferPlayerToDimension(EntityPlayerMP par1EntityPlayerMP, int par2, Teleporter teleporter)
409        {
410            int var3 = par1EntityPlayerMP.dimension;
411            WorldServer var4 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
412            par1EntityPlayerMP.dimension = par2;
413            WorldServer var5 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
414    
415            par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet9Respawn(par1EntityPlayerMP.dimension, (byte)par1EntityPlayerMP.worldObj.difficultySetting, var5.getWorldInfo().getTerrainType(), var5.getHeight(), par1EntityPlayerMP.theItemInWorldManager.getGameType()));
416            var4.removeEntity(par1EntityPlayerMP);
417            par1EntityPlayerMP.isDead = false;
418            this.transferEntityToWorld(par1EntityPlayerMP, var3, var4, var5, teleporter);
419            this.func_72375_a(par1EntityPlayerMP, var4);
420            par1EntityPlayerMP.playerNetServerHandler.setPlayerLocation(par1EntityPlayerMP.posX, par1EntityPlayerMP.posY, par1EntityPlayerMP.posZ, par1EntityPlayerMP.rotationYaw, par1EntityPlayerMP.rotationPitch);
421            par1EntityPlayerMP.theItemInWorldManager.setWorld(var5);
422            this.updateTimeAndWeatherForPlayer(par1EntityPlayerMP, var5);
423            this.syncPlayerInventory(par1EntityPlayerMP);
424            Iterator var6 = par1EntityPlayerMP.getActivePotionEffects().iterator();
425    
426            while (var6.hasNext())
427            {
428                PotionEffect var7 = (PotionEffect)var6.next();
429                par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(par1EntityPlayerMP.entityId, var7));
430            }
431    
432            GameRegistry.onPlayerChangedDimension(par1EntityPlayerMP);
433        }
434    
435        /**
436         * Transfers an entity from a world to another world.
437         */
438        public void transferEntityToWorld(Entity par1Entity, int par2, WorldServer par3WorldServer, WorldServer par4WorldServer)
439        {
440            transferEntityToWorld(par1Entity, par2, par3WorldServer, par4WorldServer, par4WorldServer.func_85176_s());
441        }
442    
443        public void transferEntityToWorld(Entity par1Entity, int par2, WorldServer par3WorldServer, WorldServer par4WorldServer, Teleporter teleporter)
444        {
445            WorldProvider pOld = par3WorldServer.provider;
446            WorldProvider pNew = par4WorldServer.provider;
447            double moveFactor = pOld.getMovementFactor() / pNew.getMovementFactor();
448            double var5 = par1Entity.posX * moveFactor;
449            double var7 = par1Entity.posZ * moveFactor;
450            double var11 = par1Entity.posX;
451            double var13 = par1Entity.posY;
452            double var15 = par1Entity.posZ;
453            float var17 = par1Entity.rotationYaw;
454            par3WorldServer.theProfiler.startSection("moving");
455    
456            if (par1Entity.dimension == 1)
457            {
458                ChunkCoordinates var18;
459    
460                if (par2 == 1)
461                {
462                    var18 = par4WorldServer.getSpawnPoint();
463                }
464                else
465                {
466                    var18 = par4WorldServer.getEntrancePortalLocation();
467                }
468    
469                var5 = (double)var18.posX;
470                par1Entity.posY = (double)var18.posY;
471                var7 = (double)var18.posZ;
472                par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, 90.0F, 0.0F);
473    
474                if (par1Entity.isEntityAlive())
475                {
476                    par3WorldServer.updateEntityWithOptionalForce(par1Entity, false);
477                }
478            }
479    
480            par3WorldServer.theProfiler.endSection();
481    
482            if (par2 != 1)
483            {
484                par3WorldServer.theProfiler.startSection("placing");
485                var5 = (double)MathHelper.clamp_int((int)var5, -29999872, 29999872);
486                var7 = (double)MathHelper.clamp_int((int)var7, -29999872, 29999872);
487    
488                if (par1Entity.isEntityAlive())
489                {
490                    par4WorldServer.spawnEntityInWorld(par1Entity);
491                    par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, par1Entity.rotationYaw, par1Entity.rotationPitch);
492                    par4WorldServer.updateEntityWithOptionalForce(par1Entity, false);
493                    teleporter.placeInPortal(par1Entity, var11, var13, var15, var17);
494                }
495    
496                par3WorldServer.theProfiler.endSection();
497            }
498    
499            par1Entity.setWorld(par4WorldServer);
500        }
501    
502        /**
503         * sends 1 player per tick, but only sends a player once every 600 ticks
504         */
505        public void sendPlayerInfoToAllPlayers()
506        {
507            if (++this.playerPingIndex > 600)
508            {
509                this.playerPingIndex = 0;
510            }
511    
512            if (this.playerPingIndex < this.playerEntityList.size())
513            {
514                EntityPlayerMP var1 = (EntityPlayerMP)this.playerEntityList.get(this.playerPingIndex);
515                this.sendPacketToAllPlayers(new Packet201PlayerInfo(var1.username, true, var1.ping));
516            }
517        }
518    
519        /**
520         * sends a packet to all players
521         */
522        public void sendPacketToAllPlayers(Packet par1Packet)
523        {
524            for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2)
525            {
526                ((EntityPlayerMP)this.playerEntityList.get(var2)).playerNetServerHandler.sendPacketToPlayer(par1Packet);
527            }
528        }
529    
530        /**
531         * Sends a packet to all players in the specified Dimension
532         */
533        public void sendPacketToAllPlayersInDimension(Packet par1Packet, int par2)
534        {
535            for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3)
536            {
537                EntityPlayerMP var4 = (EntityPlayerMP)this.playerEntityList.get(var3);
538    
539                if (var4.dimension == par2)
540                {
541                    var4.playerNetServerHandler.sendPacketToPlayer(par1Packet);
542                }
543            }
544        }
545    
546        /**
547         * returns a string containing a comma-seperated list of player names
548         */
549        public String getPlayerListAsString()
550        {
551            String var1 = "";
552    
553            for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2)
554            {
555                if (var2 > 0)
556                {
557                    var1 = var1 + ", ";
558                }
559    
560                var1 = var1 + ((EntityPlayerMP)this.playerEntityList.get(var2)).username;
561            }
562    
563            return var1;
564        }
565    
566        /**
567         * Returns an array of the usernames of all the connected players.
568         */
569        public String[] getAllUsernames()
570        {
571            String[] var1 = new String[this.playerEntityList.size()];
572    
573            for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2)
574            {
575                var1[var2] = ((EntityPlayerMP)this.playerEntityList.get(var2)).username;
576            }
577    
578            return var1;
579        }
580    
581        public BanList getBannedPlayers()
582        {
583            return this.bannedPlayers;
584        }
585    
586        public BanList getBannedIPs()
587        {
588            return this.bannedIPs;
589        }
590    
591        /**
592         * This adds a username to the ops list, then saves the op list
593         */
594        public void addOp(String par1Str)
595        {
596            this.ops.add(par1Str.toLowerCase());
597        }
598    
599        /**
600         * This removes a username from the ops list, then saves the op list
601         */
602        public void removeOp(String par1Str)
603        {
604            this.ops.remove(par1Str.toLowerCase());
605        }
606    
607        /**
608         * Determine if the player is allowed to connect based on current server settings.
609         */
610        public boolean isAllowedToLogin(String par1Str)
611        {
612            par1Str = par1Str.trim().toLowerCase();
613            return !this.whiteListEnforced || this.ops.contains(par1Str) || this.whiteListedPlayers.contains(par1Str);
614        }
615    
616        /**
617         * Returns true if the specific player is allowed to use commands.
618         */
619        public boolean areCommandsAllowed(String par1Str)
620        {
621            return this.ops.contains(par1Str.trim().toLowerCase()) || this.mcServer.isSinglePlayer() && this.mcServer.worldServers[0].getWorldInfo().areCommandsAllowed() && this.mcServer.getServerOwner().equalsIgnoreCase(par1Str) || this.commandsAllowedForAll;
622        }
623    
624        public EntityPlayerMP getPlayerForUsername(String par1Str)
625        {
626            Iterator var2 = this.playerEntityList.iterator();
627            EntityPlayerMP var3;
628    
629            do
630            {
631                if (!var2.hasNext())
632                {
633                    return null;
634                }
635    
636                var3 = (EntityPlayerMP)var2.next();
637            }
638            while (!var3.username.equalsIgnoreCase(par1Str));
639    
640            return var3;
641        }
642    
643        /**
644         * Find all players in a specified range and narrowing down by other parameters
645         */
646        public List findPlayers(ChunkCoordinates par1ChunkCoordinates, int par2, int par3, int par4, int par5, int par6, int par7)
647        {
648            if (this.playerEntityList.isEmpty())
649            {
650                return null;
651            }
652            else
653            {
654                Object var8 = new ArrayList();
655                boolean var9 = par4 < 0;
656                int var10 = par2 * par2;
657                int var11 = par3 * par3;
658                par4 = MathHelper.abs_int(par4);
659    
660                for (int var12 = 0; var12 < this.playerEntityList.size(); ++var12)
661                {
662                    EntityPlayerMP var13 = (EntityPlayerMP)this.playerEntityList.get(var12);
663    
664                    if (par1ChunkCoordinates != null && (par2 > 0 || par3 > 0))
665                    {
666                        float var14 = par1ChunkCoordinates.getDistanceSquaredToChunkCoordinates(var13.getPlayerCoordinates());
667    
668                        if (par2 > 0 && var14 < (float)var10 || par3 > 0 && var14 > (float)var11)
669                        {
670                            continue;
671                        }
672                    }
673    
674                    if ((par5 == EnumGameType.NOT_SET.getID() || par5 == var13.theItemInWorldManager.getGameType().getID()) && (par6 <= 0 || var13.experienceLevel >= par6) && var13.experienceLevel <= par7)
675                    {
676                        ((List)var8).add(var13);
677                    }
678                }
679    
680                if (par1ChunkCoordinates != null)
681                {
682                    Collections.sort((List)var8, new PlayerPositionComparator(par1ChunkCoordinates));
683                }
684    
685                if (var9)
686                {
687                    Collections.reverse((List)var8);
688                }
689    
690                if (par4 > 0)
691                {
692                    var8 = ((List)var8).subList(0, Math.min(par4, ((List)var8).size()));
693                }
694    
695                return (List)var8;
696            }
697        }
698    
699        /**
700         * params: x,y,z,d,dimension. The packet is sent to all players within d distance of x,y,z (d^2<x^2+y^2+z^2)
701         */
702        public void sendToAllNear(double par1, double par3, double par5, double par7, int par9, Packet par10Packet)
703        {
704            this.sendToAllNearExcept((EntityPlayer)null, par1, par3, par5, par7, par9, par10Packet);
705        }
706    
707        /**
708         * params: srcPlayer,x,y,z,d,dimension. The packet is not sent to the srcPlayer, but all other players where
709         * dx*dx+dy*dy+dz*dz<d*d
710         */
711        public void sendToAllNearExcept(EntityPlayer par1EntityPlayer, double par2, double par4, double par6, double par8, int par10, Packet par11Packet)
712        {
713            for (int var12 = 0; var12 < this.playerEntityList.size(); ++var12)
714            {
715                EntityPlayerMP var13 = (EntityPlayerMP)this.playerEntityList.get(var12);
716    
717                if (var13 != par1EntityPlayer && var13.dimension == par10)
718                {
719                    double var14 = par2 - var13.posX;
720                    double var16 = par4 - var13.posY;
721                    double var18 = par6 - var13.posZ;
722    
723                    if (var14 * var14 + var16 * var16 + var18 * var18 < par8 * par8)
724                    {
725                        var13.playerNetServerHandler.sendPacketToPlayer(par11Packet);
726                    }
727                }
728            }
729        }
730    
731        /**
732         * Saves all of the players' current states.
733         */
734        public void saveAllPlayerData()
735        {
736            for (int var1 = 0; var1 < this.playerEntityList.size(); ++var1)
737            {
738                this.writePlayerData((EntityPlayerMP)this.playerEntityList.get(var1));
739            }
740        }
741    
742        /**
743         * Add the specified player to the white list.
744         */
745        public void addToWhiteList(String par1Str)
746        {
747            this.whiteListedPlayers.add(par1Str);
748        }
749    
750        /**
751         * Remove the specified player from the whitelist.
752         */
753        public void removeFromWhitelist(String par1Str)
754        {
755            this.whiteListedPlayers.remove(par1Str);
756        }
757    
758        /**
759         * Returns the whitelisted players.
760         */
761        public Set getWhiteListedPlayers()
762        {
763            return this.whiteListedPlayers;
764        }
765    
766        public Set getOps()
767        {
768            return this.ops;
769        }
770    
771        /**
772         * Either does nothing, or calls readWhiteList.
773         */
774        public void loadWhiteList() {}
775    
776        /**
777         * Updates the time and weather for the given player to those of the given world
778         */
779        public void updateTimeAndWeatherForPlayer(EntityPlayerMP par1EntityPlayerMP, WorldServer par2WorldServer)
780        {
781            par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet4UpdateTime(par2WorldServer.getTotalWorldTime(), par2WorldServer.getWorldTime()));
782    
783            if (par2WorldServer.isRaining())
784            {
785                par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(1, 0));
786            }
787        }
788    
789        /**
790         * sends the players inventory to himself
791         */
792        public void syncPlayerInventory(EntityPlayerMP par1EntityPlayerMP)
793        {
794            par1EntityPlayerMP.sendContainerToPlayer(par1EntityPlayerMP.inventoryContainer);
795            par1EntityPlayerMP.setPlayerHealthUpdated();
796        }
797    
798        /**
799         * Returns the number of players currently on the server.
800         */
801        public int getCurrentPlayerCount()
802        {
803            return this.playerEntityList.size();
804        }
805    
806        /**
807         * Returns the maximum number of players allowed on the server.
808         */
809        public int getMaxPlayers()
810        {
811            return this.maxPlayers;
812        }
813    
814        /**
815         * Returns an array of usernames for which player.dat exists for.
816         */
817        public String[] getAvailablePlayerDat()
818        {
819            return this.mcServer.worldServers[0].getSaveHandler().getSaveHandler().getAvailablePlayerDat();
820        }
821    
822        public boolean isWhiteListEnabled()
823        {
824            return this.whiteListEnforced;
825        }
826    
827        public void setWhiteListEnabled(boolean par1)
828        {
829            this.whiteListEnforced = par1;
830        }
831    
832        public List getPlayerList(String par1Str)
833        {
834            ArrayList var2 = new ArrayList();
835            Iterator var3 = this.playerEntityList.iterator();
836    
837            while (var3.hasNext())
838            {
839                EntityPlayerMP var4 = (EntityPlayerMP)var3.next();
840    
841                if (var4.func_71114_r().equals(par1Str))
842                {
843                    var2.add(var4);
844                }
845            }
846    
847            return var2;
848        }
849    
850        /**
851         * Gets the View Distance.
852         */
853        public int getViewDistance()
854        {
855            return this.viewDistance;
856        }
857    
858        public MinecraftServer getServerInstance()
859        {
860            return this.mcServer;
861        }
862    
863        /**
864         * gets the tags created in the last writePlayerData call
865         */
866        public NBTTagCompound getTagsFromLastWrite()
867        {
868            return null;
869        }
870    
871        @SideOnly(Side.CLIENT)
872        public void setGameType(EnumGameType par1EnumGameType)
873        {
874            this.gameType = par1EnumGameType;
875        }
876    
877        private void func_72381_a(EntityPlayerMP par1EntityPlayerMP, EntityPlayerMP par2EntityPlayerMP, World par3World)
878        {
879            if (par2EntityPlayerMP != null)
880            {
881                par1EntityPlayerMP.theItemInWorldManager.setGameType(par2EntityPlayerMP.theItemInWorldManager.getGameType());
882            }
883            else if (this.gameType != null)
884            {
885                par1EntityPlayerMP.theItemInWorldManager.setGameType(this.gameType);
886            }
887    
888            par1EntityPlayerMP.theItemInWorldManager.initializeGameType(par3World.getWorldInfo().getGameType());
889        }
890    
891        @SideOnly(Side.CLIENT)
892    
893        /**
894         * Sets whether all players are allowed to use commands (cheats) on the server.
895         */
896        public void setCommandsAllowedForAll(boolean par1)
897        {
898            this.commandsAllowedForAll = par1;
899        }
900    
901        /**
902         * Kicks everyone with "Server closed" as reason.
903         */
904        public void removeAllPlayers()
905        {
906            while (!this.playerEntityList.isEmpty())
907            {
908                ((EntityPlayerMP)this.playerEntityList.get(0)).playerNetServerHandler.kickPlayerFromServer("Server closed");
909            }
910        }
911    }