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"); 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 this.canSpawnStructures = this.settings.getBooleanProperty("generate-structures", true); 071 int var2 = this.settings.getIntProperty("gamemode", EnumGameType.SURVIVAL.getID()); 072 this.gameType = WorldSettings.getGameTypeById(var2); 073 logger.info("Default game type: " + this.gameType); 074 InetAddress var3 = null; 075 076 if (this.getServerHostname().length() > 0) 077 { 078 var3 = InetAddress.getByName(this.getServerHostname()); 079 } 080 081 if (this.getServerPort() < 0) 082 { 083 this.setServerPort(this.settings.getIntProperty("server-port", 25565)); 084 } 085 086 logger.info("Generating keypair"); 087 this.setKeyPair(CryptManager.createNewKeyPair()); 088 logger.info("Starting Minecraft server on " + (this.getServerHostname().length() == 0 ? "*" : this.getServerHostname()) + ":" + this.getServerPort()); 089 090 try 091 { 092 this.networkThread = new DedicatedServerListenThread(this, var3, this.getServerPort()); 093 } 094 catch (IOException var16) 095 { 096 logger.warning("**** FAILED TO BIND TO PORT!"); 097 logger.log(Level.WARNING, "The exception was: " + var16.toString()); 098 logger.warning("Perhaps a server is already running on that port?"); 099 return false; 100 } 101 102 if (!this.isServerInOnlineMode()) 103 { 104 logger.warning("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); 105 logger.warning("The server will make no attempt to authenticate usernames. Beware."); 106 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."); 107 logger.warning("To change this, set \"online-mode\" to \"true\" in the server.properties file."); 108 } 109 110 FMLCommonHandler.instance().onServerStarted(); 111 this.setConfigurationManager(new DedicatedPlayerList(this)); 112 long var4 = System.nanoTime(); 113 114 if (this.getFolderName() == null) 115 { 116 this.setFolderName(this.settings.getProperty("level-name", "world")); 117 } 118 119 String var6 = this.settings.getProperty("level-seed", ""); 120 String var7 = this.settings.getProperty("level-type", "DEFAULT"); 121 String var8 = this.settings.getProperty("generator-settings", ""); 122 long var9 = (new Random()).nextLong(); 123 124 if (var6.length() > 0) 125 { 126 try 127 { 128 long var11 = Long.parseLong(var6); 129 130 if (var11 != 0L) 131 { 132 var9 = var11; 133 } 134 } 135 catch (NumberFormatException var15) 136 { 137 var9 = (long)var6.hashCode(); 138 } 139 } 140 141 WorldType var17 = WorldType.parseWorldType(var7); 142 143 if (var17 == null) 144 { 145 var17 = WorldType.DEFAULT; 146 } 147 148 this.setBuildLimit(this.settings.getIntProperty("max-build-height", 256)); 149 this.setBuildLimit((this.getBuildLimit() + 8) / 16 * 16); 150 this.setBuildLimit(MathHelper.clamp_int(this.getBuildLimit(), 64, 256)); 151 this.settings.setProperty("max-build-height", Integer.valueOf(this.getBuildLimit())); 152 logger.info("Preparing level \"" + this.getFolderName() + "\""); 153 this.loadAllWorlds(this.getFolderName(), this.getFolderName(), var9, var17, var8); 154 long var12 = System.nanoTime() - var4; 155 String var14 = String.format("%.3fs", new Object[] {Double.valueOf((double)var12 / 1.0E9D)}); 156 logger.info("Done (" + var14 + ")! For help, type \"help\" or \"?\""); 157 158 if (this.settings.getBooleanProperty("enable-query", false)) 159 { 160 logger.info("Starting GS4 status listener"); 161 this.theRConThreadQuery = new RConThreadQuery(this); 162 this.theRConThreadQuery.startThread(); 163 } 164 165 if (this.settings.getBooleanProperty("enable-rcon", false)) 166 { 167 logger.info("Starting remote control listener"); 168 this.theRConThreadMain = new RConThreadMain(this); 169 this.theRConThreadMain.startThread(); 170 } 171 FMLCommonHandler.instance().handleServerStarting(this); 172 return true; 173 } 174 175 public boolean canStructuresSpawn() 176 { 177 return this.canSpawnStructures; 178 } 179 180 public EnumGameType getGameType() 181 { 182 return this.gameType; 183 } 184 185 /** 186 * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on the client. 187 */ 188 public int getDifficulty() 189 { 190 return this.settings.getIntProperty("difficulty", 1); 191 } 192 193 /** 194 * Defaults to false. 195 */ 196 public boolean isHardcore() 197 { 198 return this.settings.getBooleanProperty("hardcore", false); 199 } 200 201 /** 202 * Called on exit from the main run() loop. 203 */ 204 protected void finalTick(CrashReport par1CrashReport) 205 { 206 while (this.isServerRunning()) 207 { 208 this.executePendingCommands(); 209 210 try 211 { 212 Thread.sleep(10L); 213 } 214 catch (InterruptedException var3) 215 { 216 var3.printStackTrace(); 217 } 218 } 219 } 220 221 /** 222 * Adds the server info, including from theWorldServer, to the crash report. 223 */ 224 public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport) 225 { 226 par1CrashReport = super.addServerInfoToCrashReport(par1CrashReport); 227 par1CrashReport.addCrashSectionCallable("Type", new CallableType(this)); 228 return par1CrashReport; 229 } 230 231 /** 232 * Directly calls System.exit(0), instantly killing the program. 233 */ 234 protected void systemExitNow() 235 { 236 System.exit(0); 237 } 238 239 public void updateTimeLightAndEntities() 240 { 241 super.updateTimeLightAndEntities(); 242 this.executePendingCommands(); 243 } 244 245 public boolean getAllowNether() 246 { 247 return this.settings.getBooleanProperty("allow-nether", true); 248 } 249 250 public boolean allowSpawnMonsters() 251 { 252 return this.settings.getBooleanProperty("spawn-monsters", true); 253 } 254 255 public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper) 256 { 257 par1PlayerUsageSnooper.addData("whitelist_enabled", Boolean.valueOf(this.getDedicatedPlayerList().isWhiteListEnabled())); 258 par1PlayerUsageSnooper.addData("whitelist_count", Integer.valueOf(this.getDedicatedPlayerList().getWhiteListedPlayers().size())); 259 super.addServerStatsToSnooper(par1PlayerUsageSnooper); 260 } 261 262 /** 263 * Returns whether snooping is enabled or not. 264 */ 265 public boolean isSnooperEnabled() 266 { 267 return this.settings.getBooleanProperty("snooper-enabled", true); 268 } 269 270 public void addPendingCommand(String par1Str, ICommandSender par2ICommandSender) 271 { 272 this.pendingCommandList.add(new ServerCommand(par1Str, par2ICommandSender)); 273 } 274 275 public void executePendingCommands() 276 { 277 while (!this.pendingCommandList.isEmpty()) 278 { 279 ServerCommand var1 = (ServerCommand)this.pendingCommandList.remove(0); 280 this.getCommandManager().executeCommand(var1.sender, var1.command); 281 } 282 } 283 284 public boolean isDedicatedServer() 285 { 286 return true; 287 } 288 289 public DedicatedPlayerList getDedicatedPlayerList() 290 { 291 return (DedicatedPlayerList)super.getConfigurationManager(); 292 } 293 294 public NetworkListenThread getNetworkThread() 295 { 296 return this.networkThread; 297 } 298 299 /** 300 * Gets an integer property. If it does not exist, set it to the specified value. 301 */ 302 public int getIntProperty(String par1Str, int par2) 303 { 304 return this.settings.getIntProperty(par1Str, par2); 305 } 306 307 /** 308 * Gets a string property. If it does not exist, set it to the specified value. 309 */ 310 public String getStringProperty(String par1Str, String par2Str) 311 { 312 return this.settings.getProperty(par1Str, par2Str); 313 } 314 315 /** 316 * Gets a boolean property. If it does not exist, set it to the specified value. 317 */ 318 public boolean getBooleanProperty(String par1Str, boolean par2) 319 { 320 return this.settings.getBooleanProperty(par1Str, par2); 321 } 322 323 /** 324 * Saves an Object with the given property name. 325 */ 326 public void setProperty(String par1Str, Object par2Obj) 327 { 328 this.settings.setProperty(par1Str, par2Obj); 329 } 330 331 /** 332 * Saves all of the server properties to the properties file. 333 */ 334 public void saveProperties() 335 { 336 this.settings.saveProperties(); 337 } 338 339 public String getSettingsFilePath() 340 { 341 File var1 = this.settings.getPropertiesFile(); 342 return var1 != null ? var1.getAbsolutePath() : "No settings file"; 343 } 344 345 public boolean getGuiEnabled() 346 { 347 return this.guiIsEnabled; 348 } 349 350 /** 351 * On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections. 352 */ 353 public String shareToLAN(EnumGameType par1EnumGameType, boolean par2) 354 { 355 return ""; 356 } 357 358 public boolean func_82356_Z() 359 { 360 return this.settings.getBooleanProperty("enable-command-block", false); 361 } 362 363 public int func_82357_ak() 364 { 365 return this.settings.getIntProperty("spawn-protection", super.func_82357_ak()); 366 } 367 368 public ServerConfigurationManager getConfigurationManager() 369 { 370 return this.getDedicatedPlayerList(); 371 } 372 373 @SideOnly(Side.SERVER) 374 public void func_82011_an() 375 { 376 ServerGUI.initGUI(this); 377 this.guiIsEnabled = true; 378 } 379 }