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