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