    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.FMLCommonHandler;
    004    import cpw.mods.fml.common.Side;
    005    import cpw.mods.fml.common.asm.SideOnly;
    006    import java.io.File;
    007    import java.io.IOException;
    008    import java.net.InetAddress;
    009    import java.util.ArrayList;
    010    import java.util.Collections;
    011    import java.util.List;
    012    import java.util.Random;
    013    import java.util.logging.Level;
    014    import net.minecraft.server.MinecraftServer;
    015
    016    public class DedicatedServer extends MinecraftServer implements IServer
    017    {
    018        private final List pendingCommandList = Collections.synchronizedList(new ArrayList());
    019        private RConThreadQuery theRConThreadQuery;
    020        private RConThreadMain theRConThreadMain;
    021        private PropertyManager settings;
    022        private boolean canSpawnStructures;
    023        private EnumGameType gameType;
    024        private NetworkListenThread networkThread;
    025        private boolean guiIsEnabled = false;
    026
    027        public DedicatedServer(File par1File)
    028        {
    029            super(par1File);
    030            new DedicatedServerSleepThread(this);
    031        }
    032
    033        /**
    034         * Initialises the server and starts it.
    035         */
    036        protected boolean startServer() throws IOException
    037        {
    038            DedicatedServerCommandThread var1 = new DedicatedServerCommandThread(this);
    039            var1.setDaemon(true);
    040            var1.start();
    041            ConsoleLogManager.init();
    042            logger.info("Starting minecraft server version 1.4.3");
    043
    044            if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L)
    045            {
    046                logger.warning("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
    047            }
    048
    049            FMLCommonHandler.instance().onServerStart(this);
    050
    051            logger.info("Loading properties");
    052            this.settings = new PropertyManager(new File("server.properties"));
    053
    054            if (this.isSinglePlayer())
    055            {
    056                this.setHostname("127.0.0.1");
    057            }
    058            else
    059            {
    060                this.setOnlineMode(this.settings.getBooleanProperty("online-mode", true));
    061                this.setHostname(this.settings.getProperty("server-ip", ""));
    062            }
    063
    064            this.setCanSpawnAnimals(this.settings.getBooleanProperty("spawn-animals", true));
    065            this.setCanSpawnNPCs(this.settings.getBooleanProperty("spawn-npcs", true));
    066            this.setAllowPvp(this.settings.getBooleanProperty("pvp", true));
    067            this.setAllowFlight(this.settings.getBooleanProperty("allow-flight", false));
    068            this.setTexturePack(this.settings.getProperty("texture-pack", ""));
    069            this.setMOTD(this.settings.getProperty("motd", "A Minecraft Server"));
    070
    071            if (this.settings.getIntProperty("difficulty", 1) < 0)
    072            {
    073                this.settings.setProperty("difficulty", Integer.valueOf(0));
    074            }
    075            else if (this.settings.getIntProperty("difficulty", 1) > 3)
    076            {
    077                this.settings.setProperty("difficulty", Integer.valueOf(3));
    078            }
    079
    080            this.canSpawnStructures = this.settings.getBooleanProperty("generate-structures", true);
    081            int var2 = this.settings.getIntProperty("gamemode", EnumGameType.SURVIVAL.getID());
    082            this.gameType = WorldSettings.getGameTypeById(var2);
    083            logger.info("Default game type: " + this.gameType);
    084            InetAddress var3 = null;
    085
    086            if (this.getServerHostname().length() > 0)
    087            {
    088                var3 = InetAddress.getByName(this.getServerHostname());
    089            }
    090
    091            if (this.getServerPort() < 0)
    092            {
    093                this.setServerPort(this.settings.getIntProperty("server-port", 25565));
    094            }
    095
    096            logger.info("Generating keypair");
    097            this.setKeyPair(CryptManager.createNewKeyPair());
    098            logger.info("Starting Minecraft server on " + (this.getServerHostname().length() == 0 ? "*" : this.getServerHostname()) + ":" + this.getServerPort());
    099
    100            try
    101            {
    102                this.networkThread = new DedicatedServerListenThread(this, var3, this.getServerPort());
    103            }
    104            catch (IOException var16)
    105            {
    106                logger.warning("**** FAILED TO BIND TO PORT!");
    107                logger.log(Level.WARNING, "The exception was: " + var16.toString());
    108                logger.warning("Perhaps a server is already running on that port?");
    109                return false;
    110            }
    111
    112            if (!this.isServerInOnlineMode())
    113            {
    114                logger.warning("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
    115                logger.warning("The server will make no attempt to authenticate usernames. Beware.");
    116                logger.warning("While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.");
    117                logger.warning("To change this, set \"online-mode\" to \"true\" in the server.properties file.");
    118            }
    119
    120            FMLCommonHandler.instance().onServerStarted();
    121            this.setConfigurationManager(new DedicatedPlayerList(this));
    122            long var4 = System.nanoTime();
    123
    124            if (this.getFolderName() == null)
    125            {
    126                this.setFolderName(this.settings.getProperty("level-name", "world"));
    127            }
    128
    129            String var6 = this.settings.getProperty("level-seed", "");
    130            String var7 = this.settings.getProperty("level-type", "DEFAULT");
    131            String var8 = this.settings.getProperty("generator-settings", "");
    132            long var9 = (new Random()).nextLong();
    133
    134            if (var6.length() > 0)
    135            {
    136                try
    137                {
    138                    long var11 = Long.parseLong(var6);
    139
    140                    if (var11 != 0L)
    141                    {
    142                        var9 = var11;
    143                    }
    144                }
    145                catch (NumberFormatException var15)
    146                {
    147                    var9 = (long)var6.hashCode();
    148                }
    149            }
    150
    151            WorldType var17 = WorldType.parseWorldType(var7);
    152
    153            if (var17 == null)
    154            {
    155                var17 = WorldType.DEFAULT;
    156            }
    157
    158            this.setBuildLimit(this.settings.getIntProperty("max-build-height", 256));
    159            this.setBuildLimit((this.getBuildLimit() + 8) / 16 * 16);
    160            this.setBuildLimit(MathHelper.clamp_int(this.getBuildLimit(), 64, 256));
    161            this.settings.setProperty("max-build-height", Integer.valueOf(this.getBuildLimit()));
    162            logger.info("Preparing level \"" + this.getFolderName() + "\"");
    163            this.loadAllWorlds(this.getFolderName(), this.getFolderName(), var9, var17, var8);
    164            long var12 = System.nanoTime() - var4;
    165            String var14 = String.format("%.3fs", new Object[] {Double.valueOf((double)var12 / 1.0E9D)});
    166            logger.info("Done (" + var14 + ")! For help, type \"help\" or \"?\"");
    167
    168            if (this.settings.getBooleanProperty("enable-query", false))
    169            {
    170                logger.info("Starting GS4 status listener");
    171                this.theRConThreadQuery = new RConThreadQuery(this);
    172                this.theRConThreadQuery.startThread();
    173            }
    174
    175            if (this.settings.getBooleanProperty("enable-rcon", false))
    176            {
    177                logger.info("Starting remote control listener");
    178                this.theRConThreadMain = new RConThreadMain(this);
    179                this.theRConThreadMain.startThread();
    180            }
    181            FMLCommonHandler.instance().handleServerStarting(this);
    182            return true;
    183        }
    184
    185        public boolean canStructuresSpawn()
    186        {
    187            return this.canSpawnStructures;
    188        }
    189
    190        public EnumGameType getGameType()
    191        {
    192            return this.gameType;
    193        }
    194
    195        /**
    196         * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on the client.
    197         */
    198        public int getDifficulty()
    199        {
    200            return this.settings.getIntProperty("difficulty", 1);
    201        }
    202
    203        /**
    204         * Defaults to false.
    205         */
    206        public boolean isHardcore()
    207        {
    208            return this.settings.getBooleanProperty("hardcore", false);
    209        }
    210
    211        /**
    212         * Called on exit from the main run() loop.
    213         */
    214        protected void finalTick(CrashReport par1CrashReport)
    215        {
    216            while (this.isServerRunning())
    217            {
    218                this.executePendingCommands();
    219
    220                try
    221                {
    222                    Thread.sleep(10L);
    223                }
    224                catch (InterruptedException var3)
    225                {
    226                    var3.printStackTrace();
    227                }
    228            }
    229        }
    230
    231        /**
    232         * Adds the server info, including from theWorldServer, to the crash report.
    233         */
    234        public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport)
    235        {
    236            par1CrashReport = super.addServerInfoToCrashReport(par1CrashReport);
    237            par1CrashReport.func_85056_g().addCrashSectionCallable("Is Modded", new CallableType(this));
    238            par1CrashReport.func_85056_g().addCrashSectionCallable("Type", new CallableServerType(this));
    239            return par1CrashReport;
    240        }
    241
    242        /**
    243         * Directly calls System.exit(0), instantly killing the program.
    244         */
    245        protected void systemExitNow()
    246        {
    247            System.exit(0);
    248        }
    249
    250        public void updateTimeLightAndEntities()
    251        {
    252            super.updateTimeLightAndEntities();
    253            this.executePendingCommands();
    254        }
    255
    256        public boolean getAllowNether()
    257        {
    258            return this.settings.getBooleanProperty("allow-nether", true);
    259        }
    260
    261        public boolean allowSpawnMonsters()
    262        {
    263            return this.settings.getBooleanProperty("spawn-monsters", true);
    264        }
    265
    266        public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
    267        {
    268            par1PlayerUsageSnooper.addData("whitelist_enabled", Boolean.valueOf(this.getDedicatedPlayerList().isWhiteListEnabled()));
    269            par1PlayerUsageSnooper.addData("whitelist_count", Integer.valueOf(this.getDedicatedPlayerList().getWhiteListedPlayers().size()));
    270            super.addServerStatsToSnooper(par1PlayerUsageSnooper);
    271        }
    272
    273        /**
    274         * Returns whether snooping is enabled or not.
    275         */
    276        public boolean isSnooperEnabled()
    277        {
    278            return this.settings.getBooleanProperty("snooper-enabled", true);
    279        }
    280
    281        public void addPendingCommand(String par1Str, ICommandSender par2ICommandSender)
    282        {
    283            this.pendingCommandList.add(new ServerCommand(par1Str, par2ICommandSender));
    284        }
    285
    286        public void executePendingCommands()
    287        {
    288            while (!this.pendingCommandList.isEmpty())
    289            {
    290                ServerCommand var1 = (ServerCommand)this.pendingCommandList.remove(0);
    291                this.getCommandManager().executeCommand(var1.sender, var1.command);
    292            }
    293        }
    294
    295        public boolean isDedicatedServer()
    296        {
    297            return true;
    298        }
    299
    300        public DedicatedPlayerList getDedicatedPlayerList()
    301        {
    302            return (DedicatedPlayerList)super.getConfigurationManager();
    303        }
    304
    305        public NetworkListenThread getNetworkThread()
    306        {
    307            return this.networkThread;
    308        }
    309
    310        /**
    311         * Gets an integer property. If it does not exist, set it to the specified value.
    312         */
    313        public int getIntProperty(String par1Str, int par2)
    314        {
    315            return this.settings.getIntProperty(par1Str, par2);
    316        }
    317
    318        /**
    319         * Gets a string property. If it does not exist, set it to the specified value.
    320         */
    321        public String getStringProperty(String par1Str, String par2Str)
    322        {
    323            return this.settings.getProperty(par1Str, par2Str);
    324        }
    325
    326        /**
    327         * Gets a boolean property. If it does not exist, set it to the specified value.
    328         */
    329        public boolean getBooleanProperty(String par1Str, boolean par2)
    330        {
    331            return this.settings.getBooleanProperty(par1Str, par2);
    332        }
    333
    334        /**
    335         * Saves an Object with the given property name.
    336         */
    337        public void setProperty(String par1Str, Object par2Obj)
    338        {
    339            this.settings.setProperty(par1Str, par2Obj);
    340        }
    341
    342        /**
    343         * Saves all of the server properties to the properties file.
    344         */
    345        public void saveProperties()
    346        {
    347            this.settings.saveProperties();
    348        }
    349
    350        public String getSettingsFilePath()
    351        {
    352            File var1 = this.settings.getPropertiesFile();
    353            return var1 != null ? var1.getAbsolutePath() : "No settings file";
    354        }
    355
    356        public boolean getGuiEnabled()
    357        {
    358            return this.guiIsEnabled;
    359        }
    360
    361        /**
    362         * On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections.
    363         */
    364        public String shareToLAN(EnumGameType par1EnumGameType, boolean par2)
    365        {
    366            return "";
    367        }
    368
    369        /**
    370         * Return whether command blocks are enabled.
    371         */
    372        public boolean isCommandBlockEnabled()
    373        {
    374            return this.settings.getBooleanProperty("enable-command-block", false);
    375        }
    376
    377        /**
    378         * Return the spawn protection area's size.
    379         */
    380        public int getSpawnProtectionSize()
    381        {
    382            return this.settings.getIntProperty("spawn-protection", super.getSpawnProtectionSize());
    383        }
    384
    385        public ServerConfigurationManager getConfigurationManager()
    386        {
    387            return this.getDedicatedPlayerList();
    388        }
    389
    390        @SideOnly(Side.SERVER)
    391        public void func_82011_an()
    392        {
    393            ServerGUI.initGUI(this);
    394            this.guiIsEnabled = true;
    395        }
    396    }