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