    001package net.minecraft.server;
    002
    003import cpw.mods.fml.common.FMLCommonHandler;
    004import cpw.mods.fml.relauncher.ArgsWrapper;
    005import cpw.mods.fml.relauncher.FMLRelauncher;
    006import cpw.mods.fml.relauncher.Side;
    007import cpw.mods.fml.relauncher.SideOnly;
    008import java.awt.GraphicsEnvironment;
    009import java.io.File;
    010import java.io.IOException;
    011import java.security.KeyPair;
    012import java.text.SimpleDateFormat;
    013import java.util.ArrayList;
    014import java.util.Date;
    015import java.util.Hashtable;
    016import java.util.Iterator;
    017import java.util.List;
    018import java.util.logging.Level;
    019import java.util.logging.Logger;
    020import net.minecraft.block.BlockDispenser;
    021import net.minecraft.command.CommandBase;
    022import net.minecraft.command.ICommandManager;
    023import net.minecraft.command.ICommandSender;
    024import net.minecraft.command.ServerCommandManager;
    025import net.minecraft.crash.CrashReport;
    026import net.minecraft.dispenser.BehaviorArrowDispense;
    027import net.minecraft.dispenser.BehaviorBucketEmptyDispense;
    028import net.minecraft.dispenser.BehaviorBucketFullDispense;
    029import net.minecraft.dispenser.BehaviorDispenseBoat;
    030import net.minecraft.dispenser.BehaviorDispenseFireball;
    031import net.minecraft.dispenser.BehaviorDispenseFirework;
    032import net.minecraft.dispenser.BehaviorDispenseMinecart;
    033import net.minecraft.dispenser.BehaviorEggDispense;
    034import net.minecraft.dispenser.BehaviorExpBottleDispense;
    035import net.minecraft.dispenser.BehaviorMobEggDispense;
    036import net.minecraft.dispenser.BehaviorPotionDispense;
    037import net.minecraft.dispenser.BehaviorSnowballDispense;
    038import net.minecraft.item.Item;
    039import net.minecraft.network.NetworkListenThread;
    040import net.minecraft.network.packet.Packet;
    041import net.minecraft.network.packet.Packet4UpdateTime;
    042import net.minecraft.network.rcon.RConConsoleSource;
    043import net.minecraft.profiler.IPlayerUsage;
    044import net.minecraft.profiler.PlayerUsageSnooper;
    045import net.minecraft.profiler.Profiler;
    046import net.minecraft.server.dedicated.DedicatedServer;
    047import net.minecraft.server.gui.IUpdatePlayerListBox;
    048import net.minecraft.server.management.ServerConfigurationManager;
    049import net.minecraft.stats.StatList;
    050import net.minecraft.util.AxisAlignedBB;
    051import net.minecraft.util.ChunkCoordinates;
    052import net.minecraft.util.IProgressUpdate;
    053import net.minecraft.util.MathHelper;
    054import net.minecraft.util.ReportedException;
    055import net.minecraft.util.StringTranslate;
    056import net.minecraft.util.StringUtils;
    057import net.minecraft.world.EnumGameType;
    058import net.minecraft.world.MinecraftException;
    059import net.minecraft.world.WorldManager;
    060import net.minecraft.world.WorldServer;
    061import net.minecraft.world.WorldServerMulti;
    062import net.minecraft.world.WorldSettings;
    063import net.minecraft.world.WorldType;
    064import net.minecraft.world.chunk.storage.AnvilSaveConverter;
    065import net.minecraft.world.demo.DemoWorldServer;
    066import net.minecraft.world.storage.ISaveFormat;
    067import net.minecraft.world.storage.ISaveHandler;
    068import net.minecraft.world.storage.WorldInfo;
    069
    070import net.minecraftforge.common.DimensionManager;
    071import net.minecraftforge.common.MinecraftForge;
    072import net.minecraftforge.event.world.WorldEvent;
    073
    074public abstract class MinecraftServer implements ICommandSender, Runnable, IPlayerUsage
    075{
    076    /** The logging system. */
    077    public static Logger logger = Logger.getLogger("Minecraft");
    078
    079    /** Instance of Minecraft Server. */
    080    private static MinecraftServer mcServer = null;
    081    private final ISaveFormat anvilConverterForAnvilFile;
    082
    083    /** The PlayerUsageSnooper instance. */
    084    private final PlayerUsageSnooper usageSnooper = new PlayerUsageSnooper("server", this);
    085    private final File anvilFile;
    086
    087    /**
    088     * Collection of objects to update every tick. Type: List<IUpdatePlayerListBox>
    089     */
    090    private final List tickables = new ArrayList();
    091    private final ICommandManager commandManager;
    092    public final Profiler theProfiler = new Profiler();
    093
    094    /** The server's hostname. */
    095    private String hostname;
    096
    097    /** The server's port. */
    098    private int serverPort = -1;
    099
    100    /** The server world instances. */
    101    public WorldServer[] worldServers;
    102
    103    /** The ServerConfigurationManager instance. */
    104    private ServerConfigurationManager serverConfigManager;
    105
    106    /**
    107     * Indicates whether the server is running or not. Set to false to initiate a shutdown.
    108     */
    109    private boolean serverRunning = true;
    110
    111    /** Indicates to other classes that the server is safely stopped. */
    112    private boolean serverStopped = false;
    113
    114    /** Incremented every tick. */
    115    private int tickCounter = 0;
    116
    117    /**
    118     * The task the server is currently working on(and will output on outputPercentRemaining).
    119     */
    120    public String currentTask;
    121
    122    /** The percentage of the current task finished so far. */
    123    public int percentDone;
    124
    125    /** True if the server is in online mode. */
    126    private boolean onlineMode;
    127
    128    /** True if the server has animals turned on. */
    129    private boolean canSpawnAnimals;
    130    private boolean canSpawnNPCs;
    131
    132    /** Indicates whether PvP is active on the server or not. */
    133    private boolean pvpEnabled;
    134
    135    /** Determines if flight is allowed or not. */
    136    private boolean allowFlight;
    137
    138    /** The server MOTD string. */
    139    private String motd;
    140
    141    /** Maximum build height. */
    142    private int buildLimit;
    143    private long lastSentPacketID;
    144    private long lastSentPacketSize;
    145    private long lastReceivedID;
    146    private long lastReceivedSize;
    147    public final long[] sentPacketCountArray = new long[100];
    148    public final long[] sentPacketSizeArray = new long[100];
    149    public final long[] receivedPacketCountArray = new long[100];
    150    public final long[] receivedPacketSizeArray = new long[100];
    151    public final long[] tickTimeArray = new long[100];
    152
    153    /** Stats are [dimension][tick%100] system.nanoTime is stored. */
    154    //public long[][] timeOfLastDimensionTick;
    155    public Hashtable<Integer, long[]> worldTickTimes = new Hashtable<Integer, long[]>();
    156    private KeyPair serverKeyPair;
    157
    158    /** Username of the server owner (for integrated servers) */
    159    private String serverOwner;
    160    private String folderName;
    161    @SideOnly(Side.CLIENT)
    162    private String worldName;
    163    private boolean isDemo;
    164    private boolean enableBonusChest;
    165
    166    /**
    167     * If true, there is no need to save chunks or stop the server, because that is already being done.
    168     */
    169    private boolean worldIsBeingDeleted;
    170    private String texturePack = "";
    171    private boolean serverIsRunning = false;
    172
    173    /**
    174     * Set when warned for "Can't keep up", which triggers again after 15 seconds.
    175     */
    176    private long timeOfLastWarning;
    177    private String userMessage;
    178    private boolean startProfiling;
    179
    180    public MinecraftServer(File par1File)
    181    {
    182        mcServer = this;
    183        this.anvilFile = par1File;
    184        this.commandManager = new ServerCommandManager();
    185        this.anvilConverterForAnvilFile = new AnvilSaveConverter(par1File);
    186        this.registerDispenseBehaviors();
    187    }
    188
    189    /**
    190     * Register all dispense behaviors.
    191     */
    192    private void registerDispenseBehaviors()
    193    {
    194        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.arrow, new BehaviorArrowDispense(this));
    195        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.egg, new BehaviorEggDispense(this));
    196        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.snowball, new BehaviorSnowballDispense(this));
    197        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.expBottle, new BehaviorExpBottleDispense(this));
    198        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.potion, new BehaviorPotionDispense(this));
    199        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.monsterPlacer, new BehaviorMobEggDispense(this));
    200        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.firework, new BehaviorDispenseFirework(this));
    201        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.fireballCharge, new BehaviorDispenseFireball(this));
    202        BehaviorDispenseMinecart var1 = new BehaviorDispenseMinecart(this);
    203        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartEmpty, var1);
    204        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartCrate, var1);
    205        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartPowered, var1);
    206        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.boat, new BehaviorDispenseBoat(this));
    207        BehaviorBucketFullDispense var2 = new BehaviorBucketFullDispense(this);
    208        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketLava, var2);
    209        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketWater, var2);
    210        BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketEmpty, new BehaviorBucketEmptyDispense(this));
    211    }
    212
    213    /**
    214     * Initialises the server and starts it.
    215     */
    216    protected abstract boolean startServer() throws IOException;
    217
    218    protected void convertMapIfNeeded(String par1Str)
    219    {
    220        if (this.getActiveAnvilConverter().isOldMapFormat(par1Str))
    221        {
    222            logger.info("Converting map!");
    223            this.setUserMessage("menu.convertingLevel");
    224            this.getActiveAnvilConverter().convertMapFormat(par1Str, new ConvertingProgressUpdate(this));
    225        }
    226    }
    227
    228    /**
    229     * Typically "menu.convertingLevel", "menu.loadingLevel" or others.
    230     */
    231    protected synchronized void setUserMessage(String par1Str)
    232    {
    233        this.userMessage = par1Str;
    234    }
    235
    236    @SideOnly(Side.CLIENT)
    237
    238    public synchronized String getUserMessage()
    239    {
    240        return this.userMessage;
    241    }
    242
    243    protected void loadAllWorlds(String par1Str, String par2Str, long par3, WorldType par5WorldType, String par6Str)
    244    {
    245        this.convertMapIfNeeded(par1Str);
    246        this.setUserMessage("menu.loadingLevel");
    247        ISaveHandler var7 = this.anvilConverterForAnvilFile.getSaveLoader(par1Str, true);
    248        WorldInfo var9 = var7.loadWorldInfo();
    249        WorldSettings var8;
    250
    251        if (var9 == null)
    252        {
    253            var8 = new WorldSettings(par3, this.getGameType(), this.canStructuresSpawn(), this.isHardcore(), par5WorldType);
    254            var8.func_82750_a(par6Str);
    255        }
    256        else
    257        {
    258            var8 = new WorldSettings(var9);
    259        }
    260
    261        if (this.enableBonusChest)
    262        {
    263            var8.enableBonusChest();
    264        }
    265
    266        WorldServer overWorld = (isDemo() ? new DemoWorldServer(this, var7, par2Str, 0, theProfiler) : new WorldServer(this, var7, par2Str, 0, var8, theProfiler));
    267        for (int dim : DimensionManager.getStaticDimensionIDs())
    268        {
    269            WorldServer world = (dim == 0 ? overWorld : new WorldServerMulti(this, var7, par2Str, dim, var8, overWorld, theProfiler));
    270            world.addWorldAccess(new WorldManager(this, world));
    271
    272            if (!this.isSinglePlayer())
    273            {
    274                world.getWorldInfo().setGameType(this.getGameType());
    275            }
    276
    277            this.serverConfigManager.setPlayerManager(this.worldServers);
    278
    279            MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
    280        }
    281
    282        this.serverConfigManager.setPlayerManager(new WorldServer[]{ overWorld });
    283        this.setDifficultyForAllWorlds(this.getDifficulty());
    284        this.initialWorldChunkLoad();
    285    }
    286
    287    protected void initialWorldChunkLoad()
    288    {
    289        int var5 = 0;
    290        this.setUserMessage("menu.generatingTerrain");
    291        byte var6 = 0;
    292        logger.info("Preparing start region for level " + var6);
    293        WorldServer var7 = this.worldServers[var6];
    294        ChunkCoordinates var8 = var7.getSpawnPoint();
    295        long var9 = System.currentTimeMillis();
    296
    297        for (int var11 = -192; var11 <= 192 && this.isServerRunning(); var11 += 16)
    298        {
    299            for (int var12 = -192; var12 <= 192 && this.isServerRunning(); var12 += 16)
    300            {
    301                long var13 = System.currentTimeMillis();
    302
    303                if (var13 - var9 > 1000L)
    304                {
    305                    this.outputPercentRemaining("Preparing spawn area", var5 * 100 / 625);
    306                    var9 = var13;
    307                }
    308
    309                ++var5;
    310                var7.theChunkProviderServer.loadChunk(var8.posX + var11 >> 4, var8.posZ + var12 >> 4);
    311            }
    312        }
    313
    314        this.clearCurrentTask();
    315    }
    316
    317    public abstract boolean canStructuresSpawn();
    318
    319    public abstract EnumGameType getGameType();
    320
    321    /**
    322     * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on the client.
    323     */
    324    public abstract int getDifficulty();
    325
    326    /**
    327     * Defaults to false.
    328     */
    329    public abstract boolean isHardcore();
    330
    331    /**
    332     * Used to display a percent remaining given text and the percentage.
    333     */
    334    protected void outputPercentRemaining(String par1Str, int par2)
    335    {
    336        this.currentTask = par1Str;
    337        this.percentDone = par2;
    338        logger.info(par1Str + ": " + par2 + "%");
    339    }
    340
    341    /**
    342     * Set current task to null and set its percentage to 0.
    343     */
    344    protected void clearCurrentTask()
    345    {
    346        this.currentTask = null;
    347        this.percentDone = 0;
    348    }
    349
    350    /**
    351     * par1 indicates if a log message should be output.
    352     */
    353    protected void saveAllWorlds(boolean par1)
    354    {
    355        if (!this.worldIsBeingDeleted)
    356        {
    357            WorldServer[] var2 = this.worldServers;
    358            int var3 = var2.length;
    359
    360            for (int var4 = 0; var4 < var3; ++var4)
    361            {
    362                WorldServer var5 = var2[var4];
    363
    364                if (var5 != null)
    365                {
    366                    if (!par1)
    367                    {
    368                        logger.info("Saving chunks for level \'" + var5.getWorldInfo().getWorldName() + "\'/" + var5.provider.getDimensionName());
    369                    }
    370
    371                    try
    372                    {
    373                        var5.saveAllChunks(true, (IProgressUpdate)null);
    374                    }
    375                    catch (MinecraftException var7)
    376                    {
    377                        logger.warning(var7.getMessage());
    378                    }
    379                }
    380            }
    381        }
    382    }
    383
    384    /**
    385     * Saves all necessary data as preparation for stopping the server.
    386     */
    387    public void stopServer()
    388    {
    389        if (!this.worldIsBeingDeleted)
    390        {
    391            logger.info("Stopping server");
    392
    393            if (this.getNetworkThread() != null)
    394            {
    395                this.getNetworkThread().stopListening();
    396            }
    397
    398            if (this.serverConfigManager != null)
    399            {
    400                logger.info("Saving players");
    401                this.serverConfigManager.saveAllPlayerData();
    402                this.serverConfigManager.removeAllPlayers();
    403            }
    404
    405            logger.info("Saving worlds");
    406            this.saveAllWorlds(false);
    407
    408            for (int var1 = 0; var1 < this.worldServers.length; ++var1)
    409            {
    410                WorldServer var2 = this.worldServers[var1];
    411                MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(var2));
    412                var2.flush();
    413            }
    414
    415            WorldServer[] tmp = worldServers;
    416            for (WorldServer world : tmp)
    417            {
    418                DimensionManager.setWorld(world.provider.dimensionId, null);
    419            }
    420
    421            if (this.usageSnooper != null && this.usageSnooper.isSnooperRunning())
    422            {
    423                this.usageSnooper.stopSnooper();
    424            }
    425        }
    426    }
    427
    428    /**
    429     * "getHostname" is already taken, but both return the hostname.
    430     */
    431    public String getServerHostname()
    432    {
    433        return this.hostname;
    434    }
    435
    436    public void setHostname(String par1Str)
    437    {
    438        this.hostname = par1Str;
    439    }
    440
    441    public boolean isServerRunning()
    442    {
    443        return this.serverRunning;
    444    }
    445
    446    /**
    447     * Sets the serverRunning variable to false, in order to get the server to shut down.
    448     */
    449    public void initiateShutdown()
    450    {
    451        this.serverRunning = false;
    452    }
    453
    454    public void run()
    455    {
    456        try
    457        {
    458            if (this.startServer())
    459            {
    460                FMLCommonHandler.instance().handleServerStarted();
    461
    462                long var1 = System.currentTimeMillis();
    463
    464                FMLCommonHandler.instance().onWorldLoadTick(worldServers);
    465
    466                for (long var50 = 0L; this.serverRunning; this.serverIsRunning = true)
    467                {
    468                    long var5 = System.currentTimeMillis();
    469                    long var7 = var5 - var1;
    470
    471                    if (var7 > 2000L && var1 - this.timeOfLastWarning >= 15000L)
    472                    {
    473                        logger.warning("Can\'t keep up! Did the system time change, or is the server overloaded?");
    474                        var7 = 2000L;
    475                        this.timeOfLastWarning = var1;
    476                    }
    477
    478                    if (var7 < 0L)
    479                    {
    480                        logger.warning("Time ran backwards! Did the system time change?");
    481                        var7 = 0L;
    482                    }
    483
    484                    var50 += var7;
    485                    var1 = var5;
    486
    487                    if (this.worldServers[0].areAllPlayersAsleep())
    488                    {
    489                        this.tick();
    490                        var50 = 0L;
    491                    }
    492                    else
    493                    {
    494                        while (var50 > 50L)
    495                        {
    496                            var50 -= 50L;
    497                            this.tick();
    498                        }
    499                    }
    500
    501                    Thread.sleep(1L);
    502                }
    503                FMLCommonHandler.instance().handleServerStopping();
    504            }
    505            else
    506            {
    507                this.finalTick((CrashReport)null);
    508            }
    509        }
    510        catch (Throwable var48)
    511        {
    512            if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
    513            {
    514                return;
    515            }
    516            var48.printStackTrace();
    517            logger.log(Level.SEVERE, "Encountered an unexpected exception " + var48.getClass().getSimpleName(), var48);
    518            CrashReport var2 = null;
    519
    520            if (var48 instanceof ReportedException)
    521            {
    522                var2 = this.addServerInfoToCrashReport(((ReportedException)var48).getCrashReport());
    523            }
    524            else
    525            {
    526                var2 = this.addServerInfoToCrashReport(new CrashReport("Exception in server tick loop", var48));
    527            }
    528
    529            File var3 = new File(new File(this.getDataDirectory(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt");
    530
    531            if (var2.saveToFile(var3))
    532            {
    533                logger.severe("This crash report has been saved to: " + var3.getAbsolutePath());
    534            }
    535            else
    536            {
    537                logger.severe("We were unable to save this crash report to disk.");
    538            }
    539
    540            this.finalTick(var2);
    541        }
    542        finally
    543        {
    544            try
    545            {
    546                if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
    547                {
    548                    return;
    549                }
    550                this.stopServer();
    551                this.serverStopped = true;
    552            }
    553            catch (Throwable var46)
    554            {
    555                var46.printStackTrace();
    556            }
    557            finally
    558            {
    559                FMLCommonHandler.instance().handleServerStopped();
    560                this.systemExitNow();
    561            }
    562        }
    563    }
    564
    565    protected File getDataDirectory()
    566    {
    567        return new File(".");
    568    }
    569
    570    /**
    571     * Called on exit from the main run() loop.
    572     */
    573    protected void finalTick(CrashReport par1CrashReport) {}
    574
    575    /**
    576     * Directly calls System.exit(0), instantly killing the program.
    577     */
    578    protected void systemExitNow() {}
    579
    580    /**
    581     * Main function called by run() every loop.
    582     */
    583    public void tick()
    584    {
    585        FMLCommonHandler.instance().rescheduleTicks(Side.SERVER);
    586        long var1 = System.nanoTime();
    587        AxisAlignedBB.getAABBPool().cleanPool();
    588        FMLCommonHandler.instance().onPreServerTick();
    589        ++this.tickCounter;
    590
    591        if (this.startProfiling)
    592        {
    593            this.startProfiling = false;
    594            this.theProfiler.profilingEnabled = true;
    595            this.theProfiler.clearProfiling();
    596        }
    597
    598        this.theProfiler.startSection("root");
    599        this.updateTimeLightAndEntities();
    600
    601        if (this.tickCounter % 900 == 0)
    602        {
    603            this.theProfiler.startSection("save");
    604            this.serverConfigManager.saveAllPlayerData();
    605            this.saveAllWorlds(true);
    606            this.theProfiler.endSection();
    607        }
    608
    609        this.theProfiler.startSection("tallying");
    610        this.tickTimeArray[this.tickCounter % 100] = System.nanoTime() - var1;
    611        this.sentPacketCountArray[this.tickCounter % 100] = Packet.sentID - this.lastSentPacketID;
    612        this.lastSentPacketID = Packet.sentID;
    613        this.sentPacketSizeArray[this.tickCounter % 100] = Packet.sentSize - this.lastSentPacketSize;
    614        this.lastSentPacketSize = Packet.sentSize;
    615        this.receivedPacketCountArray[this.tickCounter % 100] = Packet.receivedID - this.lastReceivedID;
    616        this.lastReceivedID = Packet.receivedID;
    617        this.receivedPacketSizeArray[this.tickCounter % 100] = Packet.receivedSize - this.lastReceivedSize;
    618        this.lastReceivedSize = Packet.receivedSize;
    619        this.theProfiler.endSection();
    620        this.theProfiler.startSection("snooper");
    621
    622        if (!this.usageSnooper.isSnooperRunning() && this.tickCounter > 100)
    623        {
    624            this.usageSnooper.startSnooper();
    625        }
    626
    627        if (this.tickCounter % 6000 == 0)
    628        {
    629            this.usageSnooper.addMemoryStatsToSnooper();
    630        }
    631
    632        this.theProfiler.endSection();
    633        this.theProfiler.endSection();
    634        FMLCommonHandler.instance().onPostServerTick();
    635    }
    636
    637    public void updateTimeLightAndEntities()
    638    {
    639        this.theProfiler.startSection("levels");
    640        int var1;
    641
    642        Integer[] ids = DimensionManager.getIDs(this.tickCounter % 200 == 0);
    643        for (int x = 0; x < ids.length; x++)
    644        {
    645            int id = ids[x];
    646            long var2 = System.nanoTime();
    647
    648            if (id == 0 || this.getAllowNether())
    649            {
    650                WorldServer var4 = DimensionManager.getWorld(id);
    651                this.theProfiler.startSection(var4.getWorldInfo().getWorldName());
    652                this.theProfiler.startSection("pools");
    653                var4.getWorldVec3Pool().clear();
    654                this.theProfiler.endSection();
    655
    656                if (this.tickCounter % 20 == 0)
    657                {
    658                    this.theProfiler.startSection("timeSync");
    659                    this.serverConfigManager.sendPacketToAllPlayersInDimension(new Packet4UpdateTime(var4.getTotalWorldTime(), var4.getWorldTime()), var4.provider.dimensionId);
    660                    this.theProfiler.endSection();
    661                }
    662
    663                this.theProfiler.startSection("tick");
    664                FMLCommonHandler.instance().onPreWorldTick(var4);
    665                CrashReport var6;
    666
    667                try
    668                {
    669                    var4.tick();
    670                }
    671                catch (Throwable var8)
    672                {
    673                    var6 = CrashReport.makeCrashReport(var8, "Exception ticking world");
    674                    var4.addWorldInfoToCrashReport(var6);
    675                    throw new ReportedException(var6);
    676                }
    677
    678                try
    679                {
    680                    var4.updateEntities();
    681                }
    682                catch (Throwable var7)
    683                {
    684                    var6 = CrashReport.makeCrashReport(var7, "Exception ticking world entities");
    685                    var4.addWorldInfoToCrashReport(var6);
    686                    throw new ReportedException(var6);
    687                }
    688
    689                FMLCommonHandler.instance().onPostWorldTick(var4);
    690                this.theProfiler.endSection();
    691                this.theProfiler.startSection("tracker");
    692                var4.getEntityTracker().updateTrackedEntities();
    693                this.theProfiler.endSection();
    694                this.theProfiler.endSection();
    695            }
    696
    697            worldTickTimes.get(id)[this.tickCounter % 100] = System.nanoTime() - var2;
    698        }
    699
    700        this.theProfiler.endStartSection("dim_unloading");
    701        DimensionManager.unloadWorlds(worldTickTimes);
    702        this.theProfiler.endStartSection("connection");
    703        this.getNetworkThread().networkTick();
    704        this.theProfiler.endStartSection("players");
    705        this.serverConfigManager.sendPlayerInfoToAllPlayers();
    706        this.theProfiler.endStartSection("tickables");
    707
    708        for (var1 = 0; var1 < this.tickables.size(); ++var1)
    709        {
    710            ((IUpdatePlayerListBox)this.tickables.get(var1)).update();
    711        }
    712
    713        this.theProfiler.endSection();
    714    }
    715
    716    public boolean getAllowNether()
    717    {
    718        return true;
    719    }
    720
    721    public void startServerThread()
    722    {
    723        (new ThreadMinecraftServer(this, "Server thread")).start();
    724    }
    725
    726    /**
    727     * Returns a File object from the specified string.
    728     */
    729    public File getFile(String par1Str)
    730    {
    731        return new File(this.getDataDirectory(), par1Str);
    732    }
    733
    734    /**
    735     * Logs the message with a level of INFO.
    736     */
    737    public void logInfo(String par1Str)
    738    {
    739        logger.info(par1Str);
    740    }
    741
    742    /**
    743     * Logs the message with a level of WARN.
    744     */
    745    public void logWarning(String par1Str)
    746    {
    747        logger.warning(par1Str);
    748    }
    749
    750    /**
    751     * Gets the worldServer by the given dimension.
    752     */
    753    public WorldServer worldServerForDimension(int par1)
    754    {
    755        WorldServer ret = DimensionManager.getWorld(par1);
    756        if (ret == null)
    757        {
    758            DimensionManager.initDimension(par1);
    759            ret = DimensionManager.getWorld(par1);
    760        }
    761        return ret;
    762    }
    763
    764    @SideOnly(Side.SERVER)
    765    public void func_82010_a(IUpdatePlayerListBox par1IUpdatePlayerListBox)
    766    {
    767        this.tickables.add(par1IUpdatePlayerListBox);
    768    }
    769
    770    /**
    771     * Returns the server's hostname.
    772     */
    773    public String getHostname()
    774    {
    775        return this.hostname;
    776    }
    777
    778    /**
    779     * Never used, but "getServerPort" is already taken.
    780     */
    781    public int getPort()
    782    {
    783        return this.serverPort;
    784    }
    785
    786    /**
    787     * Returns the server message of the day
    788     */
    789    public String getServerMOTD()
    790    {
    791        return this.motd;
    792    }
    793
    794    /**
    795     * Returns the server's Minecraft version as string.
    796     */
    797    public String getMinecraftVersion()
    798    {
    799        return "1.4.7";
    800    }
    801
    802    /**
    803     * Returns the number of players currently on the server.
    804     */
    805    public int getCurrentPlayerCount()
    806    {
    807        return this.serverConfigManager.getCurrentPlayerCount();
    808    }
    809
    810    /**
    811     * Returns the maximum number of players allowed on the server.
    812     */
    813    public int getMaxPlayers()
    814    {
    815        return this.serverConfigManager.getMaxPlayers();
    816    }
    817
    818    /**
    819     * Returns an array of the usernames of all the connected players.
    820     */
    821    public String[] getAllUsernames()
    822    {
    823        return this.serverConfigManager.getAllUsernames();
    824    }
    825
    826    /**
    827     * Used by RCon's Query in the form of "MajorServerMod 1.2.3: MyPlugin 1.3; AnotherPlugin 2.1; AndSoForth 1.0".
    828     */
    829    public String getPlugins()
    830    {
    831        return "";
    832    }
    833
    834    public String executeCommand(String par1Str)
    835    {
    836        RConConsoleSource.consoleBuffer.resetLog();
    837        this.commandManager.executeCommand(RConConsoleSource.consoleBuffer, par1Str);
    838        return RConConsoleSource.consoleBuffer.getChatBuffer();
    839    }
    840
    841    /**
    842     * Returns true if debugging is enabled, false otherwise.
    843     */
    844    public boolean isDebuggingEnabled()
    845    {
    846        return false;
    847    }
    848
    849    /**
    850     * Logs the error message with a level of SEVERE.
    851     */
    852    public void logSevere(String par1Str)
    853    {
    854        logger.log(Level.SEVERE, par1Str);
    855    }
    856
    857    /**
    858     * If isDebuggingEnabled(), logs the message with a level of INFO.
    859     */
    860    public void logDebug(String par1Str)
    861    {
    862        if (this.isDebuggingEnabled())
    863        {
    864            logger.log(Level.INFO, par1Str);
    865        }
    866    }
    867
    868    public String getServerModName()
    869    {
    870        return "forge,fml";
    871    }
    872
    873    /**
    874     * Adds the server info, including from theWorldServer, to the crash report.
    875     */
    876    public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport)
    877    {
    878        par1CrashReport.func_85056_g().addCrashSectionCallable("Profiler Position", new CallableIsServerModded(this));
    879
    880        if (this.worldServers != null && this.worldServers.length > 0 && this.worldServers[0] != null)
    881        {
    882            par1CrashReport.func_85056_g().addCrashSectionCallable("Vec3 Pool Size", new CallableServerProfiler(this));
    883        }
    884
    885        if (this.serverConfigManager != null)
    886        {
    887            par1CrashReport.func_85056_g().addCrashSectionCallable("Player Count", new CallableServerMemoryStats(this));
    888        }
    889
    890        return par1CrashReport;
    891    }
    892
    893    /**
    894     * If par2Str begins with /, then it searches for commands, otherwise it returns players.
    895     */
    896    public List getPossibleCompletions(ICommandSender par1ICommandSender, String par2Str)
    897    {
    898        ArrayList var3 = new ArrayList();
    899
    900        if (par2Str.startsWith("/"))
    901        {
    902            par2Str = par2Str.substring(1);
    903            boolean var10 = !par2Str.contains(" ");
    904            List var11 = this.commandManager.getPossibleCommands(par1ICommandSender, par2Str);
    905
    906            if (var11 != null)
    907            {
    908                Iterator var12 = var11.iterator();
    909
    910                while (var12.hasNext())
    911                {
    912                    String var13 = (String)var12.next();
    913
    914                    if (var10)
    915                    {
    916                        var3.add("/" + var13);
    917                    }
    918                    else
    919                    {
    920                        var3.add(var13);
    921                    }
    922                }
    923            }
    924
    925            return var3;
    926        }
    927        else
    928        {
    929            String[] var4 = par2Str.split(" ", -1);
    930            String var5 = var4[var4.length - 1];
    931            String[] var6 = this.serverConfigManager.getAllUsernames();
    932            int var7 = var6.length;
    933
    934            for (int var8 = 0; var8 < var7; ++var8)
    935            {
    936                String var9 = var6[var8];
    937
    938                if (CommandBase.doesStringStartWith(var5, var9))
    939                {
    940                    var3.add(var9);
    941                }
    942            }
    943
    944            return var3;
    945        }
    946    }
    947
    948    /**
    949     * Gets mcServer.
    950     */
    951    public static MinecraftServer getServer()
    952    {
    953        return mcServer;
    954    }
    955
    956    /**
    957     * Gets the name of this command sender (usually username, but possibly "Rcon")
    958     */
    959    public String getCommandSenderName()
    960    {
    961        return "Server";
    962    }
    963
    964    public void sendChatToPlayer(String par1Str)
    965    {
    966        logger.info(StringUtils.stripControlCodes(par1Str));
    967    }
    968
    969    /**
    970     * Returns true if the command sender is allowed to use the given command.
    971     */
    972    public boolean canCommandSenderUseCommand(int par1, String par2Str)
    973    {
    974        return true;
    975    }
    976
    977    /**
    978     * Translates and formats the given string key with the given arguments.
    979     */
    980    public String translateString(String par1Str, Object ... par2ArrayOfObj)
    981    {
    982        return StringTranslate.getInstance().translateKeyFormat(par1Str, par2ArrayOfObj);
    983    }
    984
    985    public ICommandManager getCommandManager()
    986    {
    987        return this.commandManager;
    988    }
    989
    990    /**
    991     * Gets KeyPair instanced in MinecraftServer.
    992     */
    993    public KeyPair getKeyPair()
    994    {
    995        return this.serverKeyPair;
    996    }
    997
    998    /**
    999     * Gets serverPort.
    1000     */
    1001    public int getServerPort()
    1002    {
    1003        return this.serverPort;
    1004    }
    1005
    1006    public void setServerPort(int par1)
    1007    {
    1008        this.serverPort = par1;
    1009    }
    1010
    1011    /**
    1012     * Returns the username of the server owner (for integrated servers)
    1013     */
    1014    public String getServerOwner()
    1015    {
    1016        return this.serverOwner;
    1017    }
    1018
    1019    /**
    1020     * Sets the username of the owner of this server (in the case of an integrated server)
    1021     */
    1022    public void setServerOwner(String par1Str)
    1023    {
    1024        this.serverOwner = par1Str;
    1025    }
    1026
    1027    public boolean isSinglePlayer()
    1028    {
    1029        return this.serverOwner != null;
    1030    }
    1031
    1032    public String getFolderName()
    1033    {
    1034        return this.folderName;
    1035    }
    1036
    1037    public void setFolderName(String par1Str)
    1038    {
    1039        this.folderName = par1Str;
    1040    }
    1041
    1042    @SideOnly(Side.CLIENT)
    1043    public void setWorldName(String par1Str)
    1044    {
    1045        this.worldName = par1Str;
    1046    }
    1047
    1048    @SideOnly(Side.CLIENT)
    1049    public String getWorldName()
    1050    {
    1051        return this.worldName;
    1052    }
    1053
    1054    public void setKeyPair(KeyPair par1KeyPair)
    1055    {
    1056        this.serverKeyPair = par1KeyPair;
    1057    }
    1058
    1059    public void setDifficultyForAllWorlds(int par1)
    1060    {
    1061        for (int var2 = 0; var2 < this.worldServers.length; ++var2)
    1062        {
    1063            WorldServer var3 = this.worldServers[var2];
    1064
    1065            if (var3 != null)
    1066            {
    1067                if (var3.getWorldInfo().isHardcoreModeEnabled())
    1068                {
    1069                    var3.difficultySetting = 3;
    1070                    var3.setAllowedSpawnTypes(true, true);
    1071                }
    1072                else if (this.isSinglePlayer())
    1073                {
    1074                    var3.difficultySetting = par1;
    1075                    var3.setAllowedSpawnTypes(var3.difficultySetting > 0, true);
    1076                }
    1077                else
    1078                {
    1079                    var3.difficultySetting = par1;
    1080                    var3.setAllowedSpawnTypes(this.allowSpawnMonsters(), this.canSpawnAnimals);
    1081                }
    1082            }
    1083        }
    1084    }
    1085
    1086    protected boolean allowSpawnMonsters()
    1087    {
    1088        return true;
    1089    }
    1090
    1091    /**
    1092     * Gets whether this is a demo or not.
    1093     */
    1094    public boolean isDemo()
    1095    {
    1096        return this.isDemo;
    1097    }
    1098
    1099    /**
    1100     * Sets whether this is a demo or not.
    1101     */
    1102    public void setDemo(boolean par1)
    1103    {
    1104        this.isDemo = par1;
    1105    }
    1106
    1107    public void canCreateBonusChest(boolean par1)
    1108    {
    1109        this.enableBonusChest = par1;
    1110    }
    1111
    1112    public ISaveFormat getActiveAnvilConverter()
    1113    {
    1114        return this.anvilConverterForAnvilFile;
    1115    }
    1116
    1117    /**
    1118     * WARNING : directly calls
    1119     * getActiveAnvilConverter().deleteWorldDirectory(theWorldServer[0].getSaveHandler().getSaveDirectoryName());
    1120     */
    1121    public void deleteWorldAndStopServer()
    1122    {
    1123        this.worldIsBeingDeleted = true;
    1124        this.getActiveAnvilConverter().flushCache();
    1125
    1126        for (int var1 = 0; var1 < this.worldServers.length; ++var1)
    1127        {
    1128            WorldServer var2 = this.worldServers[var1];
    1129
    1130            if (var2 != null)
    1131            {
    1132                MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(var2));
    1133                var2.flush();
    1134            }
    1135        }
    1136
    1137        this.getActiveAnvilConverter().deleteWorldDirectory(this.worldServers[0].getSaveHandler().getSaveDirectoryName());
    1138        this.initiateShutdown();
    1139    }
    1140
    1141    public String getTexturePack()
    1142    {
    1143        return this.texturePack;
    1144    }
    1145
    1146    public void setTexturePack(String par1Str)
    1147    {
    1148        this.texturePack = par1Str;
    1149    }
    1150
    1151    public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
    1152    {
    1153        par1PlayerUsageSnooper.addData("whitelist_enabled", Boolean.valueOf(false));
    1154        par1PlayerUsageSnooper.addData("whitelist_count", Integer.valueOf(0));
    1155        par1PlayerUsageSnooper.addData("players_current", Integer.valueOf(this.getCurrentPlayerCount()));
    1156        par1PlayerUsageSnooper.addData("players_max", Integer.valueOf(this.getMaxPlayers()));
    1157        par1PlayerUsageSnooper.addData("players_seen", Integer.valueOf(this.serverConfigManager.getAvailablePlayerDat().length));
    1158        par1PlayerUsageSnooper.addData("uses_auth", Boolean.valueOf(this.onlineMode));
    1159        par1PlayerUsageSnooper.addData("gui_state", this.getGuiEnabled() ? "enabled" : "disabled");
    1160        par1PlayerUsageSnooper.addData("avg_tick_ms", Integer.valueOf((int)(MathHelper.average(this.tickTimeArray) * 1.0E-6D)));
    1161        par1PlayerUsageSnooper.addData("avg_sent_packet_count", Integer.valueOf((int)MathHelper.average(this.sentPacketCountArray)));
    1162        par1PlayerUsageSnooper.addData("avg_sent_packet_size", Integer.valueOf((int)MathHelper.average(this.sentPacketSizeArray)));
    1163        par1PlayerUsageSnooper.addData("avg_rec_packet_count", Integer.valueOf((int)MathHelper.average(this.receivedPacketCountArray)));
    1164        par1PlayerUsageSnooper.addData("avg_rec_packet_size", Integer.valueOf((int)MathHelper.average(this.receivedPacketSizeArray)));
    1165        int var2 = 0;
    1166
    1167        for (int var3 = 0; var3 < this.worldServers.length; ++var3)
    1168        {
    1169            if (this.worldServers[var3] != null)
    1170            {
    1171                WorldServer var4 = this.worldServers[var3];
    1172                WorldInfo var5 = var4.getWorldInfo();
    1173                par1PlayerUsageSnooper.addData("world[" + var2 + "][dimension]", Integer.valueOf(var4.provider.dimensionId));
    1174                par1PlayerUsageSnooper.addData("world[" + var2 + "][mode]", var5.getGameType());
    1175                par1PlayerUsageSnooper.addData("world[" + var2 + "][difficulty]", Integer.valueOf(var4.difficultySetting));
    1176                par1PlayerUsageSnooper.addData("world[" + var2 + "][hardcore]", Boolean.valueOf(var5.isHardcoreModeEnabled()));
    1177                par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_name]", var5.getTerrainType().getWorldTypeName());
    1178                par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_version]", Integer.valueOf(var5.getTerrainType().getGeneratorVersion()));
    1179                par1PlayerUsageSnooper.addData("world[" + var2 + "][height]", Integer.valueOf(this.buildLimit));
    1180                par1PlayerUsageSnooper.addData("world[" + var2 + "][chunks_loaded]", Integer.valueOf(var4.getChunkProvider().getLoadedChunkCount()));
    1181                ++var2;
    1182            }
    1183        }
    1184
    1185        par1PlayerUsageSnooper.addData("worlds", Integer.valueOf(var2));
    1186    }
    1187
    1188    public void addServerTypeToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
    1189    {
    1190        par1PlayerUsageSnooper.addData("singleplayer", Boolean.valueOf(this.isSinglePlayer()));
    1191        par1PlayerUsageSnooper.addData("server_brand", this.getServerModName());
    1192        par1PlayerUsageSnooper.addData("gui_supported", GraphicsEnvironment.isHeadless() ? "headless" : "supported");
    1193        par1PlayerUsageSnooper.addData("dedicated", Boolean.valueOf(this.isDedicatedServer()));
    1194    }
    1195
    1196    /**
    1197     * Returns whether snooping is enabled or not.
    1198     */
    1199    public boolean isSnooperEnabled()
    1200    {
    1201        return true;
    1202    }
    1203
    1204    /**
    1205     * This is checked to be 16 upon receiving the packet, otherwise the packet is ignored.
    1206     */
    1207    public int textureSize()
    1208    {
    1209        return 16;
    1210    }
    1211
    1212    public abstract boolean isDedicatedServer();
    1213
    1214    public boolean isServerInOnlineMode()
    1215    {
    1216        return this.onlineMode;
    1217    }
    1218
    1219    public void setOnlineMode(boolean par1)
    1220    {
    1221        this.onlineMode = par1;
    1222    }
    1223
    1224    public boolean getCanSpawnAnimals()
    1225    {
    1226        return this.canSpawnAnimals;
    1227    }
    1228
    1229    public void setCanSpawnAnimals(boolean par1)
    1230    {
    1231        this.canSpawnAnimals = par1;
    1232    }
    1233
    1234    public boolean getCanSpawnNPCs()
    1235    {
    1236        return this.canSpawnNPCs;
    1237    }
    1238
    1239    public void setCanSpawnNPCs(boolean par1)
    1240    {
    1241        this.canSpawnNPCs = par1;
    1242    }
    1243
    1244    public boolean isPVPEnabled()
    1245    {
    1246        return this.pvpEnabled;
    1247    }
    1248
    1249    public void setAllowPvp(boolean par1)
    1250    {
    1251        this.pvpEnabled = par1;
    1252    }
    1253
    1254    public boolean isFlightAllowed()
    1255    {
    1256        return this.allowFlight;
    1257    }
    1258
    1259    public void setAllowFlight(boolean par1)
    1260    {
    1261        this.allowFlight = par1;
    1262    }
    1263
    1264    /**
    1265     * Return whether command blocks are enabled.
    1266     */
    1267    public abstract boolean isCommandBlockEnabled();
    1268
    1269    public String getMOTD()
    1270    {
    1271        return this.motd;
    1272    }
    1273
    1274    public void setMOTD(String par1Str)
    1275    {
    1276        this.motd = par1Str;
    1277    }
    1278
    1279    public int getBuildLimit()
    1280    {
    1281        return this.buildLimit;
    1282    }
    1283
    1284    public void setBuildLimit(int par1)
    1285    {
    1286        this.buildLimit = par1;
    1287    }
    1288
    1289    public boolean isServerStopped()
    1290    {
    1291        return this.serverStopped;
    1292    }
    1293
    1294    public ServerConfigurationManager getConfigurationManager()
    1295    {
    1296        return this.serverConfigManager;
    1297    }
    1298
    1299    public void setConfigurationManager(ServerConfigurationManager par1ServerConfigurationManager)
    1300    {
    1301        this.serverConfigManager = par1ServerConfigurationManager;
    1302    }
    1303
    1304    /**
    1305     * Sets the game type for all worlds.
    1306     */
    1307    public void setGameType(EnumGameType par1EnumGameType)
    1308    {
    1309        for (int var2 = 0; var2 < this.worldServers.length; ++var2)
    1310        {
    1311            getServer().worldServers[var2].getWorldInfo().setGameType(par1EnumGameType);
    1312        }
    1313    }
    1314
    1315    public abstract NetworkListenThread getNetworkThread();
    1316
    1317    @SideOnly(Side.CLIENT)
    1318    public boolean serverIsInRunLoop()
    1319    {
    1320        return this.serverIsRunning;
    1321    }
    1322
    1323    public boolean getGuiEnabled()
    1324    {
    1325        return false;
    1326    }
    1327
    1328    /**
    1329     * On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections.
    1330     */
    1331    public abstract String shareToLAN(EnumGameType var1, boolean var2);
    1332
    1333    public int getTickCounter()
    1334    {
    1335        return this.tickCounter;
    1336    }
    1337
    1338    public void enableProfiling()
    1339    {
    1340        this.startProfiling = true;
    1341    }
    1342
    1343    @SideOnly(Side.CLIENT)
    1344    public PlayerUsageSnooper getPlayerUsageSnooper()
    1345    {
    1346        return this.usageSnooper;
    1347    }
    1348
    1349    /**
    1350     * Return the position for this command sender.
    1351     */
    1352    public ChunkCoordinates getPlayerCoordinates()
    1353    {
    1354        return new ChunkCoordinates(0, 0, 0);
    1355    }
    1356
    1357    /**
    1358     * Return the spawn protection area's size.
    1359     */
    1360    public int getSpawnProtectionSize()
    1361    {
    1362        return 16;
    1363    }
    1364
    1365    /**
    1366     * Gets the current player count, maximum player count, and player entity list.
    1367     */
    1368    public static ServerConfigurationManager getServerConfigurationManager(MinecraftServer par0MinecraftServer)
    1369    {
    1370        return par0MinecraftServer.serverConfigManager;
    1371    }
    1372
    1373    @SideOnly(Side.SERVER)
    1374    public static void main(String[] par0ArrayOfStr)
    1375    {
    1376        FMLRelauncher.handleServerRelaunch(new ArgsWrapper(par0ArrayOfStr));
    1377    }
    1378
    1379    @SideOnly(Side.SERVER)
    1380    public static void fmlReentry(ArgsWrapper wrap)
    1381    {
    1382        String[] par0ArrayOfStr = wrap.args;
    1383        StatList.nopInit();
    1384
    1385        try
    1386        {
    1387            boolean var1 = !GraphicsEnvironment.isHeadless();
    1388            String var2 = null;
    1389            String var3 = ".";
    1390            String var4 = null;
    1391            boolean var5 = false;
    1392            boolean var6 = false;
    1393            int var7 = -1;
    1394
    1395            for (int var8 = 0; var8 < par0ArrayOfStr.length; ++var8)
    1396            {
    1397                String var9 = par0ArrayOfStr[var8];
    1398                String var10 = var8 == par0ArrayOfStr.length - 1 ? null : par0ArrayOfStr[var8 + 1];
    1399                boolean var11 = false;
    1400
    1401                if (!var9.equals("nogui") && !var9.equals("--nogui"))
    1402                {
    1403                    if (var9.equals("--port") && var10 != null)
    1404                    {
    1405                        var11 = true;
    1406
    1407                        try
    1408                        {
    1409                            var7 = Integer.parseInt(var10);
    1410                        }
    1411                        catch (NumberFormatException var13)
    1412                        {
    1413                            ;
    1414                        }
    1415                    }
    1416                    else if (var9.equals("--singleplayer") && var10 != null)
    1417                    {
    1418                        var11 = true;
    1419                        var2 = var10;
    1420                    }
    1421                    else if (var9.equals("--universe") && var10 != null)
    1422                    {
    1423                        var11 = true;
    1424                        var3 = var10;
    1425                    }
    1426                    else if (var9.equals("--world") && var10 != null)
    1427                    {
    1428                        var11 = true;
    1429                        var4 = var10;
    1430                    }
    1431                    else if (var9.equals("--demo"))
    1432                    {
    1433                        var5 = true;
    1434                    }
    1435                    else if (var9.equals("--bonusChest"))
    1436                    {
    1437                        var6 = true;
    1438                    }
    1439                }
    1440                else
    1441                {
    1442                    var1 = false;
    1443                }
    1444
    1445                if (var11)
    1446                {
    1447                    ++var8;
    1448                }
    1449            }
    1450
    1451            DedicatedServer var15 = new DedicatedServer(new File(var3));
    1452
    1453            if (var2 != null)
    1454            {
    1455                var15.setServerOwner(var2);
    1456            }
    1457
    1458            if (var4 != null)
    1459            {
    1460                var15.setFolderName(var4);
    1461            }
    1462
    1463            if (var7 >= 0)
    1464            {
    1465                var15.setServerPort(var7);
    1466            }
    1467
    1468            if (var5)
    1469            {
    1470                var15.setDemo(true);
    1471            }
    1472
    1473            if (var6)
    1474            {
    1475                var15.canCreateBonusChest(true);
    1476            }
    1477
    1478            if (var1)
    1479            {
    1480                var15.enableGui();
    1481            }
    1482
    1483            var15.startServerThread();
    1484            Runtime.getRuntime().addShutdownHook(new ThreadDedicatedServer(var15));
    1485        }
    1486        catch (Exception var14)
    1487        {
    1488            logger.log(Level.SEVERE, "Failed to start the minecraft server", var14);
    1489        }
    1490    }
    1491}