001package net.minecraft.server.management;
002
003import cpw.mods.fml.common.network.FMLNetworkHandler;
004import cpw.mods.fml.common.registry.GameRegistry;
005import cpw.mods.fml.relauncher.Side;
006import cpw.mods.fml.relauncher.SideOnly;
007import java.io.File;
008import java.net.SocketAddress;
009import java.text.SimpleDateFormat;
010import java.util.ArrayList;
011import java.util.Collections;
012import java.util.HashSet;
013import java.util.Iterator;
014import java.util.List;
015import java.util.Set;
016import java.util.logging.Logger;
017import net.minecraft.entity.Entity;
018import net.minecraft.entity.player.EntityPlayer;
019import net.minecraft.entity.player.EntityPlayerMP;
020import net.minecraft.item.ItemInWorldManager;
021import net.minecraft.nbt.NBTTagCompound;
022import net.minecraft.network.INetworkManager;
023import net.minecraft.network.NetServerHandler;
024import net.minecraft.network.packet.Packet;
025import net.minecraft.network.packet.Packet16BlockItemSwitch;
026import net.minecraft.network.packet.Packet1Login;
027import net.minecraft.network.packet.Packet201PlayerInfo;
028import net.minecraft.network.packet.Packet202PlayerAbilities;
029import net.minecraft.network.packet.Packet3Chat;
030import net.minecraft.network.packet.Packet41EntityEffect;
031import net.minecraft.network.packet.Packet43Experience;
032import net.minecraft.network.packet.Packet4UpdateTime;
033import net.minecraft.network.packet.Packet6SpawnPosition;
034import net.minecraft.network.packet.Packet70GameEvent;
035import net.minecraft.network.packet.Packet9Respawn;
036import net.minecraft.potion.PotionEffect;
037import net.minecraft.server.MinecraftServer;
038import net.minecraft.util.ChunkCoordinates;
039import net.minecraft.util.MathHelper;
040import net.minecraft.world.EnumGameType;
041import net.minecraft.world.Teleporter;
042import net.minecraft.world.World;
043import net.minecraft.world.WorldProvider;
044import net.minecraft.world.WorldServer;
045import net.minecraft.world.demo.DemoWorldManager;
046import net.minecraft.world.storage.IPlayerFileData;
047
048import net.minecraftforge.common.DimensionManager;
049
050public 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.removeEntity(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).removePlayerEntityDangerously(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.removePlayerEntityDangerously(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    /**
915     * Sends the given string to every player as chat message.
916     */
917    public void sendChatMsg(String par1Str)
918    {
919        this.mcServer.logInfo(par1Str);
920        this.sendPacketToAllPlayers(new Packet3Chat(par1Str));
921    }
922}