    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}