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 field_71342_m; 020 private RConThreadMain field_71339_n; 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.3.2"); 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.getHostName("127.0.0.1"); 057 } 058 else 059 { 060 this.setOnlineMode(this.settings.getOrSetBoolProperty("online-mode", true)); 061 this.getHostName(this.settings.getOrSetProperty("server-ip", "")); 062 } 063 064 this.setSpawnAnimals(this.settings.getOrSetBoolProperty("spawn-animals", true)); 065 this.setSpawnNpcs(this.settings.getOrSetBoolProperty("spawn-npcs", true)); 066 this.setAllowPvp(this.settings.getOrSetBoolProperty("pvp", true)); 067 this.setAllowFlight(this.settings.getOrSetBoolProperty("allow-flight", false)); 068 this.setTexturePack(this.settings.getOrSetProperty("texture-pack", "")); 069 this.setMOTD(this.settings.getOrSetProperty("motd", "A Minecraft Server")); 070 spawnProtectionSize = this.settings.getOrSetIntProperty("spawn-protection-size", 16); 071 this.canSpawnStructures = this.settings.getOrSetBoolProperty("generate-structures", true); 072 int var2 = this.settings.getOrSetIntProperty("gamemode", EnumGameType.SURVIVAL.getID()); 073 this.gameType = WorldSettings.getGameTypeById(var2); 074 logger.info("Default game type: " + this.gameType); 075 InetAddress var3 = null; 076 077 if (this.getHostname().length() > 0) 078 { 079 var3 = InetAddress.getByName(this.getHostname()); 080 } 081 082 if (this.getServerPort() < 0) 083 { 084 this.setServerPort(this.settings.getOrSetIntProperty("server-port", 25565)); 085 } 086 087 logger.info("Generating keypair"); 088 this.setKeyPair(CryptManager.createNewKeyPair()); 089 logger.info("Starting Minecraft server on " + (this.getHostname().length() == 0 ? "*" : this.getHostname()) + ":" + this.getServerPort()); 090 091 try 092 { 093 this.networkThread = new DedicatedServerListenThread(this, var3, this.getServerPort()); 094 } 095 catch (IOException var15) 096 { 097 logger.warning("**** FAILED TO BIND TO PORT!"); 098 logger.log(Level.WARNING, "The exception was: " + var15.toString()); 099 logger.warning("Perhaps a server is already running on that port?"); 100 return false; 101 } 102 103 if (!this.isServerInOnlineMode()) 104 { 105 logger.warning("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); 106 logger.warning("The server will make no attempt to authenticate usernames. Beware."); 107 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."); 108 logger.warning("To change this, set \"online-mode\" to \"true\" in the server.properties file."); 109 } 110 111 FMLCommonHandler.instance().onServerStarted(); 112 this.setConfigurationManager(new DedicatedPlayerList(this)); 113 long var4 = System.nanoTime(); 114 115 if (this.getFolderName() == null) 116 { 117 this.setFolderName(this.settings.getOrSetProperty("level-name", "world")); 118 } 119 120 String var6 = this.settings.getOrSetProperty("level-seed", ""); 121 String var7 = this.settings.getOrSetProperty("level-type", "DEFAULT"); 122 long var8 = (new Random()).nextLong(); 123 124 if (var6.length() > 0) 125 { 126 try 127 { 128 long var10 = Long.parseLong(var6); 129 130 if (var10 != 0L) 131 { 132 var8 = var10; 133 } 134 } 135 catch (NumberFormatException var14) 136 { 137 var8 = (long)var6.hashCode(); 138 } 139 } 140 141 WorldType var16 = WorldType.parseWorldType(var7); 142 143 if (var16 == null) 144 { 145 var16 = WorldType.DEFAULT; 146 } 147 148 this.setBuildLimit(this.settings.getOrSetIntProperty("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.setArbitraryProperty("max-build-height", Integer.valueOf(this.getBuildLimit())); 152 logger.info("Preparing level \"" + this.getFolderName() + "\""); 153 this.loadAllDimensions(this.getFolderName(), this.getFolderName(), var8, var16); 154 long var11 = System.nanoTime() - var4; 155 String var13 = String.format("%.3fs", new Object[] {Double.valueOf((double)var11 / 1.0E9D)}); 156 logger.info("Done (" + var13 + ")! For help, type \"help\" or \"?\""); 157 158 if (this.settings.getOrSetBoolProperty("enable-query", false)) 159 { 160 logger.info("Starting GS4 status listener"); 161 this.field_71342_m = new RConThreadQuery(this); 162 this.field_71342_m.startThread(); 163 } 164 165 if (this.settings.getOrSetBoolProperty("enable-rcon", false)) 166 { 167 logger.info("Starting remote control listener"); 168 this.field_71339_n = new RConThreadMain(this); 169 this.field_71339_n.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" for the dedicated server 187 */ 188 public int getDifficulty() 189 { 190 return this.settings.getOrSetIntProperty("difficulty", 1); 191 } 192 193 /** 194 * defaults to false 195 */ 196 public boolean isHardcore() 197 { 198 return this.settings.getOrSetBoolProperty("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 * iterates the worldServers and adds their info also 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, 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.getOrSetBoolProperty("allow-nether", true); 248 } 249 250 public boolean allowSpawnMonsters() 251 { 252 return this.settings.getOrSetBoolProperty("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().getIPWhiteList().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.getOrSetBoolProperty("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 public int getOrSetIntProperty(String par1Str, int par2) 300 { 301 return this.settings.getOrSetIntProperty(par1Str, par2); 302 } 303 304 public String getOrSetProperty(String par1Str, String par2Str) 305 { 306 return this.settings.getOrSetProperty(par1Str, par2Str); 307 } 308 309 public boolean getOrSetBoolProperty(String par1Str, boolean par2) 310 { 311 return this.settings.getOrSetBoolProperty(par1Str, par2); 312 } 313 314 public void setArbitraryProperty(String par1Str, Object par2Obj) 315 { 316 this.settings.setArbitraryProperty(par1Str, par2Obj); 317 } 318 319 public void saveSettingsToFile() 320 { 321 this.settings.saveSettingsToFile(); 322 } 323 324 public String getSettingsFilePath() 325 { 326 File var1 = this.settings.getFile(); 327 return var1 != null ? var1.getAbsolutePath() : "No settings file"; 328 } 329 330 public boolean getGuiEnabled() 331 { 332 return this.guiIsEnabled; 333 } 334 335 /** 336 * does nothing on dedicated. on integrated, sets commandsAllowedForAll and gameType and allows external connections 337 */ 338 public String shareToLAN(EnumGameType par1EnumGameType, boolean par2) 339 { 340 return ""; 341 } 342 343 public ServerConfigurationManager getConfigurationManager() 344 { 345 return this.getDedicatedPlayerList(); 346 } 347 348 @SideOnly(Side.SERVER) 349 public void func_79001_aj() 350 { 351 ServerGUI.func_79003_a(this); 352 this.guiIsEnabled = true; 353 } 354 }