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