    001    package net.minecraft.server;
    002
    003    import cpw.mods.fml.common.FMLCommonHandler;
    004    import cpw.mods.fml.relauncher.ArgsWrapper;
    005    import cpw.mods.fml.relauncher.FMLRelauncher;
    006    import cpw.mods.fml.relauncher.Side;
    007    import cpw.mods.fml.relauncher.SideOnly;
    008    import java.awt.GraphicsEnvironment;
    009    import java.io.File;
    010    import java.io.IOException;
    011    import java.security.KeyPair;
    012    import java.text.SimpleDateFormat;
    013    import java.util.ArrayList;
    014    import java.util.Date;
    015    import java.util.Hashtable;
    016    import java.util.Iterator;
    017    import java.util.List;
    018    import java.util.logging.Level;
    019    import java.util.logging.Logger;
    020    import net.minecraft.block.BlockDispenser;
    021    import net.minecraft.command.CommandBase;
    022    import net.minecraft.command.ICommandManager;
    023    import net.minecraft.command.ICommandSender;
    024    import net.minecraft.command.ServerCommandManager;
    025    import net.minecraft.crash.CrashReport;
    026    import net.minecraft.dispenser.BehaviorArrowDispense;
    027    import net.minecraft.dispenser.BehaviorBucketEmptyDispense;
    028    import net.minecraft.dispenser.BehaviorBucketFullDispense;
    029    import net.minecraft.dispenser.BehaviorDispenseBoat;
    030    import net.minecraft.dispenser.BehaviorDispenseFireball;
    031    import net.minecraft.dispenser.BehaviorDispenseFirework;
    032    import net.minecraft.dispenser.BehaviorDispenseMinecart;
    033    import net.minecraft.dispenser.BehaviorEggDispense;
    034    import net.minecraft.dispenser.BehaviorExpBottleDispense;
    035    import net.minecraft.dispenser.BehaviorMobEggDispense;
    036    import net.minecraft.dispenser.BehaviorPotionDispense;
    037    import net.minecraft.dispenser.BehaviorSnowballDispense;
    038    import net.minecraft.item.Item;
    039    import net.minecraft.network.NetworkListenThread;
    040    import net.minecraft.network.packet.Packet;
    041    import net.minecraft.network.packet.Packet4UpdateTime;
    042    import net.minecraft.network.rcon.RConConsoleSource;
    043    import net.minecraft.profiler.IPlayerUsage;
    044    import net.minecraft.profiler.PlayerUsageSnooper;
    045    import net.minecraft.profiler.Profiler;
    046    import net.minecraft.server.dedicated.DedicatedServer;
    047    import net.minecraft.server.gui.IUpdatePlayerListBox;
    048    import net.minecraft.server.management.ServerConfigurationManager;
    049    import net.minecraft.stats.StatList;
    050    import net.minecraft.util.AxisAlignedBB;
    051    import net.minecraft.util.ChunkCoordinates;
    052    import net.minecraft.util.IProgressUpdate;
    053    import net.minecraft.util.MathHelper;
    054    import net.minecraft.util.ReportedException;
    055    import net.minecraft.util.StringTranslate;
    056    import net.minecraft.util.StringUtils;
    057    import net.minecraft.world.EnumGameType;
    058    import net.minecraft.world.MinecraftException;
    059    import net.minecraft.world.WorldManager;
    060    import net.minecraft.world.WorldServer;
    061    import net.minecraft.world.WorldServerMulti;
    062    import net.minecraft.world.WorldSettings;
    063    import net.minecraft.world.WorldType;
    064    import net.minecraft.world.chunk.storage.AnvilSaveConverter;
    065    import net.minecraft.world.demo.DemoWorldServer;
    066    import net.minecraft.world.storage.ISaveFormat;
    067    import net.minecraft.world.storage.ISaveHandler;
    068    import net.minecraft.world.storage.WorldInfo;
    069
    070    import net.minecraftforge.common.DimensionManager;
    071    import net.minecraftforge.common.MinecraftForge;
    072    import net.minecraftforge.event.world.WorldEvent;
    073
    074    public 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.field_92052_bU, 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                    this.systemExitNow();
    560                }
    561            }
    562        }
    563
    564        protected File getDataDirectory()
    565        {
    566            return new File(".");
    567        }
    568
    569        /**
    570         * Called on exit from the main run() loop.
    571         */
    572        protected void finalTick(CrashReport par1CrashReport) {}
    573
    574        /**
    575         * Directly calls System.exit(0), instantly killing the program.
    576         */
    577        protected void systemExitNow() {}
    578
    579        /**
    580         * Main function called by run() every loop.
    581         */
    582        public void tick()
    583        {
    584            FMLCommonHandler.instance().rescheduleTicks(Side.SERVER);
    585            long var1 = System.nanoTime();
    586            AxisAlignedBB.getAABBPool().cleanPool();
    587            FMLCommonHandler.instance().onPreServerTick();
    588            ++this.tickCounter;
    589
    590            if (this.startProfiling)
    591            {
    592                this.startProfiling = false;
    593                this.theProfiler.profilingEnabled = true;
    594                this.theProfiler.clearProfiling();
    595            }
    596
    597            this.theProfiler.startSection("root");
    598            this.updateTimeLightAndEntities();
    599
    600            if (this.tickCounter % 900 == 0)
    601            {
    602                this.theProfiler.startSection("save");
    603                this.serverConfigManager.saveAllPlayerData();
    604                this.saveAllWorlds(true);
    605                this.theProfiler.endSection();
    606            }
    607
    608            this.theProfiler.startSection("tallying");
    609            this.tickTimeArray[this.tickCounter % 100] = System.nanoTime() - var1;
    610            this.sentPacketCountArray[this.tickCounter % 100] = Packet.sentID - this.lastSentPacketID;
    611            this.lastSentPacketID = Packet.sentID;
    612            this.sentPacketSizeArray[this.tickCounter % 100] = Packet.sentSize - this.lastSentPacketSize;
    613            this.lastSentPacketSize = Packet.sentSize;
    614            this.receivedPacketCountArray[this.tickCounter % 100] = Packet.receivedID - this.lastReceivedID;
    615            this.lastReceivedID = Packet.receivedID;
    616            this.receivedPacketSizeArray[this.tickCounter % 100] = Packet.receivedSize - this.lastReceivedSize;
    617            this.lastReceivedSize = Packet.receivedSize;
    618            this.theProfiler.endSection();
    619            this.theProfiler.startSection("snooper");
    620
    621            if (!this.usageSnooper.isSnooperRunning() && this.tickCounter > 100)
    622            {
    623                this.usageSnooper.startSnooper();
    624            }
    625
    626            if (this.tickCounter % 6000 == 0)
    627            {
    628                this.usageSnooper.addMemoryStatsToSnooper();
    629            }
    630
    631            this.theProfiler.endSection();
    632            this.theProfiler.endSection();
    633            FMLCommonHandler.instance().onPostServerTick();
    634        }
    635
    636        public void updateTimeLightAndEntities()
    637        {
    638            this.theProfiler.startSection("levels");
    639            int var1;
    640
    641            Integer[] ids = DimensionManager.getIDs();
    642            for (int x = 0; x < ids.length; x++)
    643            {
    644                int id = ids[x];
    645                long var2 = System.nanoTime();
    646
    647                if (id == 0 || this.getAllowNether())
    648                {
    649                    WorldServer var4 = DimensionManager.getWorld(id);
    650                    this.theProfiler.startSection(var4.getWorldInfo().getWorldName());
    651                    this.theProfiler.startSection("pools");
    652                    var4.getWorldVec3Pool().clear();
    653                    this.theProfiler.endSection();
    654
    655                    if (this.tickCounter % 20 == 0)
    656                    {
    657                        this.theProfiler.startSection("timeSync");
    658                        this.serverConfigManager.sendPacketToAllPlayersInDimension(new Packet4UpdateTime(var4.getTotalWorldTime(), var4.getWorldTime()), var4.provider.dimensionId);
    659                        this.theProfiler.endSection();
    660                    }
    661
    662                    this.theProfiler.startSection("tick");
    663                    FMLCommonHandler.instance().onPreWorldTick(var4);
    664                    CrashReport var6;
    665
    666                    try
    667                    {
    668                        var4.tick();
    669                    }
    670                    catch (Throwable var8)
    671                    {
    672                        var6 = CrashReport.makeCrashReport(var8, "Exception ticking world");
    673                        var4.addWorldInfoToCrashReport(var6);
    674                        throw new ReportedException(var6);
    675                    }
    676
    677                    try
    678                    {
    679                        var4.updateEntities();
    680                    }
    681                    catch (Throwable var7)
    682                    {
    683                        var6 = CrashReport.makeCrashReport(var7, "Exception ticking world entities");
    684                        var4.addWorldInfoToCrashReport(var6);
    685                        throw new ReportedException(var6);
    686                    }
    687
    688                    FMLCommonHandler.instance().onPostWorldTick(var4);
    689                    this.theProfiler.endSection();
    690                    this.theProfiler.startSection("tracker");
    691                    var4.getEntityTracker().updateTrackedEntities();
    692                    this.theProfiler.endSection();
    693                    this.theProfiler.endSection();
    694                }
    695
    696                worldTickTimes.get(id)[this.tickCounter % 100] = System.nanoTime() - var2;
    697            }
    698
    699            this.theProfiler.endStartSection("dim_unloading");
    700            DimensionManager.unloadWorlds(worldTickTimes);
    701            this.theProfiler.endStartSection("connection");
    702            this.getNetworkThread().networkTick();
    703            this.theProfiler.endStartSection("players");
    704            this.serverConfigManager.sendPlayerInfoToAllPlayers();
    705            this.theProfiler.endStartSection("tickables");
    706
    707            for (var1 = 0; var1 < this.tickables.size(); ++var1)
    708            {
    709                ((IUpdatePlayerListBox)this.tickables.get(var1)).update();
    710            }
    711
    712            this.theProfiler.endSection();
    713        }
    714
    715        public boolean getAllowNether()
    716        {
    717            return true;
    718        }
    719
    720        public void startServerThread()
    721        {
    722            (new ThreadMinecraftServer(this, "Server thread")).start();
    723        }
    724
    725        /**
    726         * Returns a File object from the specified string.
    727         */
    728        public File getFile(String par1Str)
    729        {
    730            return new File(this.getDataDirectory(), par1Str);
    731        }
    732
    733        /**
    734         * Logs the message with a level of INFO.
    735         */
    736        public void logInfo(String par1Str)
    737        {
    738            logger.info(par1Str);
    739        }
    740
    741        /**
    742         * Logs the message with a level of WARN.
    743         */
    744        public void logWarning(String par1Str)
    745        {
    746            logger.warning(par1Str);
    747        }
    748
    749        /**
    750         * Gets the worldServer by the given dimension.
    751         */
    752        public WorldServer worldServerForDimension(int par1)
    753        {
    754            WorldServer ret = DimensionManager.getWorld(par1);
    755            if (ret == null)
    756            {
    757                DimensionManager.initDimension(par1);
    758                ret = DimensionManager.getWorld(par1);
    759            }
    760            return ret;
    761        }
    762
    763        @SideOnly(Side.SERVER)
    764        public void func_82010_a(IUpdatePlayerListBox par1IUpdatePlayerListBox)
    765        {
    766            this.tickables.add(par1IUpdatePlayerListBox);
    767        }
    768
    769        /**
    770         * Returns the server's hostname.
    771         */
    772        public String getHostname()
    773        {
    774            return this.hostname;
    775        }
    776
    777        /**
    778         * Never used, but "getServerPort" is already taken.
    779         */
    780        public int getPort()
    781        {
    782            return this.serverPort;
    783        }
    784
    785        /**
    786         * minecraftServer.getMOTD is used in 2 places instead (it is a non-virtual function which returns the same thing)
    787         */
    788        public String getServerMOTD()
    789        {
    790            return this.motd;
    791        }
    792
    793        /**
    794         * Returns the server's Minecraft version as string.
    795         */
    796        public String getMinecraftVersion()
    797        {
    798            return "1.4.6";
    799        }
    800
    801        /**
    802         * Returns the number of players currently on the server.
    803         */
    804        public int getCurrentPlayerCount()
    805        {
    806            return this.serverConfigManager.getCurrentPlayerCount();
    807        }
    808
    809        /**
    810         * Returns the maximum number of players allowed on the server.
    811         */
    812        public int getMaxPlayers()
    813        {
    814            return this.serverConfigManager.getMaxPlayers();
    815        }
    816
    817        /**
    818         * Returns an array of the usernames of all the connected players.
    819         */
    820        public String[] getAllUsernames()
    821        {
    822            return this.serverConfigManager.getAllUsernames();
    823        }
    824
    825        /**
    826         * Used by RCon's Query in the form of "MajorServerMod 1.2.3: MyPlugin 1.3; AnotherPlugin 2.1; AndSoForth 1.0".
    827         */
    828        public String getPlugins()
    829        {
    830            return "";
    831        }
    832
    833        public String executeCommand(String par1Str)
    834        {
    835            RConConsoleSource.consoleBuffer.resetLog();
    836            this.commandManager.executeCommand(RConConsoleSource.consoleBuffer, par1Str);
    837            return RConConsoleSource.consoleBuffer.getChatBuffer();
    838        }
    839
    840        /**
    841         * Returns true if debugging is enabled, false otherwise.
    842         */
    843        public boolean isDebuggingEnabled()
    844        {
    845            return false;
    846        }
    847
    848        /**
    849         * Logs the error message with a level of SEVERE.
    850         */
    851        public void logSevere(String par1Str)
    852        {
    853            logger.log(Level.SEVERE, par1Str);
    854        }
    855
    856        /**
    857         * If isDebuggingEnabled(), logs the message with a level of INFO.
    858         */
    859        public void logDebug(String par1Str)
    860        {
    861            if (this.isDebuggingEnabled())
    862            {
    863                logger.log(Level.INFO, par1Str);
    864            }
    865        }
    866
    867        public String getServerModName()
    868        {
    869            return "fml";
    870        }
    871
    872        /**
    873         * Adds the server info, including from theWorldServer, to the crash report.
    874         */
    875        public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport)
    876        {
    877            par1CrashReport.func_85056_g().addCrashSectionCallable("Profiler Position", new CallableIsServerModded(this));
    878
    879            if (this.worldServers != null && this.worldServers.length > 0 && this.worldServers[0] != null)
    880            {
    881                par1CrashReport.func_85056_g().addCrashSectionCallable("Vec3 Pool Size", new CallableServerProfiler(this));
    882            }
    883
    884            if (this.serverConfigManager != null)
    885            {
    886                par1CrashReport.func_85056_g().addCrashSectionCallable("Player Count", new CallableServerMemoryStats(this));
    887            }
    888
    889            return par1CrashReport;
    890        }
    891
    892        /**
    893         * If par2Str begins with /, then it searches for commands, otherwise it returns players.
    894         */
    895        public List getPossibleCompletions(ICommandSender par1ICommandSender, String par2Str)
    896        {
    897            ArrayList var3 = new ArrayList();
    898
    899            if (par2Str.startsWith("/"))
    900            {
    901                par2Str = par2Str.substring(1);
    902                boolean var10 = !par2Str.contains(" ");
    903                List var11 = this.commandManager.getPossibleCommands(par1ICommandSender, par2Str);
    904
    905                if (var11 != null)
    906                {
    907                    Iterator var12 = var11.iterator();
    908
    909                    while (var12.hasNext())
    910                    {
    911                        String var13 = (String)var12.next();
    912
    913                        if (var10)
    914                        {
    915                            var3.add("/" + var13);
    916                        }
    917                        else
    918                        {
    919                            var3.add(var13);
    920                        }
    921                    }
    922                }
    923
    924                return var3;
    925            }
    926            else
    927            {
    928                String[] var4 = par2Str.split(" ", -1);
    929                String var5 = var4[var4.length - 1];
    930                String[] var6 = this.serverConfigManager.getAllUsernames();
    931                int var7 = var6.length;
    932
    933                for (int var8 = 0; var8 < var7; ++var8)
    934                {
    935                    String var9 = var6[var8];
    936
    937                    if (CommandBase.doesStringStartWith(var5, var9))
    938                    {
    939                        var3.add(var9);
    940                    }
    941                }
    942
    943                return var3;
    944            }
    945        }
    946
    947        /**
    948         * Gets mcServer.
    949         */
    950        public static MinecraftServer getServer()
    951        {
    952            return mcServer;
    953        }
    954
    955        /**
    956         * Gets the name of this command sender (usually username, but possibly "Rcon")
    957         */
    958        public String getCommandSenderName()
    959        {
    960            return "Server";
    961        }
    962
    963        public void sendChatToPlayer(String par1Str)
    964        {
    965            logger.info(StringUtils.stripControlCodes(par1Str));
    966        }
    967
    968        /**
    969         * Returns true if the command sender is allowed to use the given command.
    970         */
    971        public boolean canCommandSenderUseCommand(int par1, String par2Str)
    972        {
    973            return true;
    974        }
    975
    976        /**
    977         * Translates and formats the given string key with the given arguments.
    978         */
    979        public String translateString(String par1Str, Object ... par2ArrayOfObj)
    980        {
    981            return StringTranslate.getInstance().translateKeyFormat(par1Str, par2ArrayOfObj);
    982        }
    983
    984        public ICommandManager getCommandManager()
    985        {
    986            return this.commandManager;
    987        }
    988
    989        /**
    990         * Gets KeyPair instanced in MinecraftServer.
    991         */
    992        public KeyPair getKeyPair()
    993        {
    994            return this.serverKeyPair;
    995        }
    996
    997        /**
    998         * Gets serverPort.
    999         */
    1000        public int getServerPort()
    1001        {
    1002            return this.serverPort;
    1003        }
    1004
    1005        public void setServerPort(int par1)
    1006        {
    1007            this.serverPort = par1;
    1008        }
    1009
    1010        /**
    1011         * Returns the username of the server owner (for integrated servers)
    1012         */
    1013        public String getServerOwner()
    1014        {
    1015            return this.serverOwner;
    1016        }
    1017
    1018        /**
    1019         * Sets the username of the owner of this server (in the case of an integrated server)
    1020         */
    1021        public void setServerOwner(String par1Str)
    1022        {
    1023            this.serverOwner = par1Str;
    1024        }
    1025
    1026        public boolean isSinglePlayer()
    1027        {
    1028            return this.serverOwner != null;
    1029        }
    1030
    1031        public String getFolderName()
    1032        {
    1033            return this.folderName;
    1034        }
    1035
    1036        public void setFolderName(String par1Str)
    1037        {
    1038            this.folderName = par1Str;
    1039        }
    1040
    1041        @SideOnly(Side.CLIENT)
    1042        public void setWorldName(String par1Str)
    1043        {
    1044            this.worldName = par1Str;
    1045        }
    1046
    1047        @SideOnly(Side.CLIENT)
    1048        public String getWorldName()
    1049        {
    1050            return this.worldName;
    1051        }
    1052
    1053        public void setKeyPair(KeyPair par1KeyPair)
    1054        {
    1055            this.serverKeyPair = par1KeyPair;
    1056        }
    1057
    1058        public void setDifficultyForAllWorlds(int par1)
    1059        {
    1060            for (int var2 = 0; var2 < this.worldServers.length; ++var2)
    1061            {
    1062                WorldServer var3 = this.worldServers[var2];
    1063
    1064                if (var3 != null)
    1065                {
    1066                    if (var3.getWorldInfo().isHardcoreModeEnabled())
    1067                    {
    1068                        var3.difficultySetting = 3;
    1069                        var3.setAllowedSpawnTypes(true, true);
    1070                    }
    1071                    else if (this.isSinglePlayer())
    1072                    {
    1073                        var3.difficultySetting = par1;
    1074                        var3.setAllowedSpawnTypes(var3.difficultySetting > 0, true);
    1075                    }
    1076                    else
    1077                    {
    1078                        var3.difficultySetting = par1;
    1079                        var3.setAllowedSpawnTypes(this.allowSpawnMonsters(), this.canSpawnAnimals);
    1080                    }
    1081                }
    1082            }
    1083        }
    1084
    1085        protected boolean allowSpawnMonsters()
    1086        {
    1087            return true;
    1088        }
    1089
    1090        /**
    1091         * Gets whether this is a demo or not.
    1092         */
    1093        public boolean isDemo()
    1094        {
    1095            return this.isDemo;
    1096        }
    1097
    1098        /**
    1099         * Sets whether this is a demo or not.
    1100         */
    1101        public void setDemo(boolean par1)
    1102        {
    1103            this.isDemo = par1;
    1104        }
    1105
    1106        public void canCreateBonusChest(boolean par1)
    1107        {
    1108            this.enableBonusChest = par1;
    1109        }
    1110
    1111        public ISaveFormat getActiveAnvilConverter()
    1112        {
    1113            return this.anvilConverterForAnvilFile;
    1114        }
    1115
    1116        /**
    1117         * WARNING : directly calls
    1118         * getActiveAnvilConverter().deleteWorldDirectory(theWorldServer[0].getSaveHandler().getSaveDirectoryName());
    1119         */
    1120        public void deleteWorldAndStopServer()
    1121        {
    1122            this.worldIsBeingDeleted = true;
    1123            this.getActiveAnvilConverter().flushCache();
    1124
    1125            for (int var1 = 0; var1 < this.worldServers.length; ++var1)
    1126            {
    1127                WorldServer var2 = this.worldServers[var1];
    1128
    1129                if (var2 != null)
    1130                {
    1131                    MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(var2));
    1132                    var2.flush();
    1133                }
    1134            }
    1135
    1136            this.getActiveAnvilConverter().deleteWorldDirectory(this.worldServers[0].getSaveHandler().getSaveDirectoryName());
    1137            this.initiateShutdown();
    1138        }
    1139
    1140        public String getTexturePack()
    1141        {
    1142            return this.texturePack;
    1143        }
    1144
    1145        public void setTexturePack(String par1Str)
    1146        {
    1147            this.texturePack = par1Str;
    1148        }
    1149
    1150        public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
    1151        {
    1152            par1PlayerUsageSnooper.addData("whitelist_enabled", Boolean.valueOf(false));
    1153            par1PlayerUsageSnooper.addData("whitelist_count", Integer.valueOf(0));
    1154            par1PlayerUsageSnooper.addData("players_current", Integer.valueOf(this.getCurrentPlayerCount()));
    1155            par1PlayerUsageSnooper.addData("players_max", Integer.valueOf(this.getMaxPlayers()));
    1156            par1PlayerUsageSnooper.addData("players_seen", Integer.valueOf(this.serverConfigManager.getAvailablePlayerDat().length));
    1157            par1PlayerUsageSnooper.addData("uses_auth", Boolean.valueOf(this.onlineMode));
    1158            par1PlayerUsageSnooper.addData("gui_state", this.getGuiEnabled() ? "enabled" : "disabled");
    1159            par1PlayerUsageSnooper.addData("avg_tick_ms", Integer.valueOf((int)(MathHelper.average(this.tickTimeArray) * 1.0E-6D)));
    1160            par1PlayerUsageSnooper.addData("avg_sent_packet_count", Integer.valueOf((int)MathHelper.average(this.sentPacketCountArray)));
    1161            par1PlayerUsageSnooper.addData("avg_sent_packet_size", Integer.valueOf((int)MathHelper.average(this.sentPacketSizeArray)));
    1162            par1PlayerUsageSnooper.addData("avg_rec_packet_count", Integer.valueOf((int)MathHelper.average(this.receivedPacketCountArray)));
    1163            par1PlayerUsageSnooper.addData("avg_rec_packet_size", Integer.valueOf((int)MathHelper.average(this.receivedPacketSizeArray)));
    1164            int var2 = 0;
    1165
    1166            for (int var3 = 0; var3 < this.worldServers.length; ++var3)
    1167            {
    1168                if (this.worldServers[var3] != null)
    1169                {
    1170                    WorldServer var4 = this.worldServers[var3];
    1171                    WorldInfo var5 = var4.getWorldInfo();
    1172                    par1PlayerUsageSnooper.addData("world[" + var2 + "][dimension]", Integer.valueOf(var4.provider.dimensionId));
    1173                    par1PlayerUsageSnooper.addData("world[" + var2 + "][mode]", var5.getGameType());
    1174                    par1PlayerUsageSnooper.addData("world[" + var2 + "][difficulty]", Integer.valueOf(var4.difficultySetting));
    1175                    par1PlayerUsageSnooper.addData("world[" + var2 + "][hardcore]", Boolean.valueOf(var5.isHardcoreModeEnabled()));
    1176                    par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_name]", var5.getTerrainType().getWorldTypeName());
    1177                    par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_version]", Integer.valueOf(var5.getTerrainType().getGeneratorVersion()));
    1178                    par1PlayerUsageSnooper.addData("world[" + var2 + "][height]", Integer.valueOf(this.buildLimit));
    1179                    par1PlayerUsageSnooper.addData("world[" + var2 + "][chunks_loaded]", Integer.valueOf(var4.getChunkProvider().getLoadedChunkCount()));
    1180                    ++var2;
    1181                }
    1182            }
    1183
    1184            par1PlayerUsageSnooper.addData("worlds", Integer.valueOf(var2));
    1185        }
    1186
    1187        public void addServerTypeToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
    1188        {
    1189            par1PlayerUsageSnooper.addData("singleplayer", Boolean.valueOf(this.isSinglePlayer()));
    1190            par1PlayerUsageSnooper.addData("server_brand", this.getServerModName());
    1191            par1PlayerUsageSnooper.addData("gui_supported", GraphicsEnvironment.isHeadless() ? "headless" : "supported");
    1192            par1PlayerUsageSnooper.addData("dedicated", Boolean.valueOf(this.isDedicatedServer()));
    1193        }
    1194
    1195        /**
    1196         * Returns whether snooping is enabled or not.
    1197         */
    1198        public boolean isSnooperEnabled()
    1199        {
    1200            return true;
    1201        }
    1202
    1203        /**
    1204         * This is checked to be 16 upon receiving the packet, otherwise the packet is ignored.
    1205         */
    1206        public int textureSize()
    1207        {
    1208            return 16;
    1209        }
    1210
    1211        public abstract boolean isDedicatedServer();
    1212
    1213        public boolean isServerInOnlineMode()
    1214        {
    1215            return this.onlineMode;
    1216        }
    1217
    1218        public void setOnlineMode(boolean par1)
    1219        {
    1220            this.onlineMode = par1;
    1221        }
    1222
    1223        public boolean getCanSpawnAnimals()
    1224        {
    1225            return this.canSpawnAnimals;
    1226        }
    1227
    1228        public void setCanSpawnAnimals(boolean par1)
    1229        {
    1230            this.canSpawnAnimals = par1;
    1231        }
    1232
    1233        public boolean getCanSpawnNPCs()
    1234        {
    1235            return this.canSpawnNPCs;
    1236        }
    1237
    1238        public void setCanSpawnNPCs(boolean par1)
    1239        {
    1240            this.canSpawnNPCs = par1;
    1241        }
    1242
    1243        public boolean isPVPEnabled()
    1244        {
    1245            return this.pvpEnabled;
    1246        }
    1247
    1248        public void setAllowPvp(boolean par1)
    1249        {
    1250            this.pvpEnabled = par1;
    1251        }
    1252
    1253        public boolean isFlightAllowed()
    1254        {
    1255            return this.allowFlight;
    1256        }
    1257
    1258        public void setAllowFlight(boolean par1)
    1259        {
    1260            this.allowFlight = par1;
    1261        }
    1262
    1263        /**
    1264         * Return whether command blocks are enabled.
    1265         */
    1266        public abstract boolean isCommandBlockEnabled();
    1267
    1268        public String getMOTD()
    1269        {
    1270            return this.motd;
    1271        }
    1272
    1273        public void setMOTD(String par1Str)
    1274        {
    1275            this.motd = par1Str;
    1276        }
    1277
    1278        public int getBuildLimit()
    1279        {
    1280            return this.buildLimit;
    1281        }
    1282
    1283        public void setBuildLimit(int par1)
    1284        {
    1285            this.buildLimit = par1;
    1286        }
    1287
    1288        public boolean isServerStopped()
    1289        {
    1290            return this.serverStopped;
    1291        }
    1292
    1293        public ServerConfigurationManager getConfigurationManager()
    1294        {
    1295            return this.serverConfigManager;
    1296        }
    1297
    1298        public void setConfigurationManager(ServerConfigurationManager par1ServerConfigurationManager)
    1299        {
    1300            this.serverConfigManager = par1ServerConfigurationManager;
    1301        }
    1302
    1303        /**
    1304         * Sets the game type for all worlds.
    1305         */
    1306        public void setGameType(EnumGameType par1EnumGameType)
    1307        {
    1308            for (int var2 = 0; var2 < this.worldServers.length; ++var2)
    1309            {
    1310                getServer().worldServers[var2].getWorldInfo().setGameType(par1EnumGameType);
    1311            }
    1312        }
    1313
    1314        public abstract NetworkListenThread getNetworkThread();
    1315
    1316        @SideOnly(Side.CLIENT)
    1317        public boolean serverIsInRunLoop()
    1318        {
    1319            return this.serverIsRunning;
    1320        }
    1321
    1322        public boolean getGuiEnabled()
    1323        {
    1324            return false;
    1325        }
    1326
    1327        /**
    1328         * On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections.
    1329         */
    1330        public abstract String shareToLAN(EnumGameType var1, boolean var2);
    1331
    1332        public int getTickCounter()
    1333        {
    1334            return this.tickCounter;
    1335        }
    1336
    1337        public void enableProfiling()
    1338        {
    1339            this.startProfiling = true;
    1340        }
    1341
    1342        @SideOnly(Side.CLIENT)
    1343        public PlayerUsageSnooper getPlayerUsageSnooper()
    1344        {
    1345            return this.usageSnooper;
    1346        }
    1347
    1348        /**
    1349         * Return the coordinates for this player as ChunkCoordinates.
    1350         */
    1351        public ChunkCoordinates getPlayerCoordinates()
    1352        {
    1353            return new ChunkCoordinates(0, 0, 0);
    1354        }
    1355
    1356        /**
    1357         * Return the spawn protection area's size.
    1358         */
    1359        public int getSpawnProtectionSize()
    1360        {
    1361            return 16;
    1362        }
    1363
    1364        /**
    1365         * Gets the current player count, maximum player count, and player entity list.
    1366         */
    1367        public static ServerConfigurationManager getServerConfigurationManager(MinecraftServer par0MinecraftServer)
    1368        {
    1369            return par0MinecraftServer.serverConfigManager;
    1370        }
    1371
    1372        @SideOnly(Side.SERVER)
    1373        public static void main(String[] par0ArrayOfStr)
    1374        {
    1375            FMLRelauncher.handleServerRelaunch(new ArgsWrapper(par0ArrayOfStr));
    1376        }
    1377
    1378        @SideOnly(Side.SERVER)
    1379        public static void fmlReentry(ArgsWrapper wrap)
    1380        {
    1381            String[] par0ArrayOfStr = wrap.args;
    1382            StatList.nopInit();
    1383
    1384            try
    1385            {
    1386                boolean var1 = !GraphicsEnvironment.isHeadless();
    1387                String var2 = null;
    1388                String var3 = ".";
    1389                String var4 = null;
    1390                boolean var5 = false;
    1391                boolean var6 = false;
    1392                int var7 = -1;
    1393
    1394                for (int var8 = 0; var8 < par0ArrayOfStr.length; ++var8)
    1395                {
    1396                    String var9 = par0ArrayOfStr[var8];
    1397                    String var10 = var8 == par0ArrayOfStr.length - 1 ? null : par0ArrayOfStr[var8 + 1];
    1398                    boolean var11 = false;
    1399
    1400                    if (!var9.equals("nogui") && !var9.equals("--nogui"))
    1401                    {
    1402                        if (var9.equals("--port") && var10 != null)
    1403                        {
    1404                            var11 = true;
    1405
    1406                            try
    1407                            {
    1408                                var7 = Integer.parseInt(var10);
    1409                            }
    1410                            catch (NumberFormatException var13)
    1411                            {
    1412                                ;
    1413                            }
    1414                        }
    1415                        else if (var9.equals("--singleplayer") && var10 != null)
    1416                        {
    1417                            var11 = true;
    1418                            var2 = var10;
    1419                        }
    1420                        else if (var9.equals("--universe") && var10 != null)
    1421                        {
    1422                            var11 = true;
    1423                            var3 = var10;
    1424                        }
    1425                        else if (var9.equals("--world") && var10 != null)
    1426                        {
    1427                            var11 = true;
    1428                            var4 = var10;
    1429                        }
    1430                        else if (var9.equals("--demo"))
    1431                        {
    1432                            var5 = true;
    1433                        }
    1434                        else if (var9.equals("--bonusChest"))
    1435                        {
    1436                            var6 = true;
    1437                        }
    1438                    }
    1439                    else
    1440                    {
    1441                        var1 = false;
    1442                    }
    1443
    1444                    if (var11)
    1445                    {
    1446                        ++var8;
    1447                    }
    1448                }
    1449
    1450                DedicatedServer var15 = new DedicatedServer(new File(var3));
    1451
    1452                if (var2 != null)
    1453                {
    1454                    var15.setServerOwner(var2);
    1455                }
    1456
    1457                if (var4 != null)
    1458                {
    1459                    var15.setFolderName(var4);
    1460                }
    1461
    1462                if (var7 >= 0)
    1463                {
    1464                    var15.setServerPort(var7);
    1465                }
    1466
    1467                if (var5)
    1468                {
    1469                    var15.setDemo(true);
    1470                }
    1471
    1472                if (var6)
    1473                {
    1474                    var15.canCreateBonusChest(true);
    1475                }
    1476
    1477                if (var1)
    1478                {
    1479                    var15.enableGui();
    1480                }
    1481
    1482                var15.startServerThread();
    1483                Runtime.getRuntime().addShutdownHook(new ThreadDedicatedServer(var15));
    1484            }
    1485            catch (Exception var14)
    1486            {
    1487                logger.log(Level.SEVERE, "Failed to start the minecraft server", var14);
    1488            }
    1489        }
    1490    }