    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.getLogAgent().logInfo(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.getScoreboard(), 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.getObjective(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}