001 package net.minecraft.server.integrated; 002 003 import cpw.mods.fml.common.FMLCommonHandler; 004 import cpw.mods.fml.relauncher.Side; 005 import cpw.mods.fml.relauncher.SideOnly; 006 import java.io.File; 007 import java.io.IOException; 008 import net.minecraft.client.Minecraft; 009 import net.minecraft.client.multiplayer.ThreadLanServerPing; 010 import net.minecraft.crash.CrashReport; 011 import net.minecraft.network.NetworkListenThread; 012 import net.minecraft.profiler.PlayerUsageSnooper; 013 import net.minecraft.server.MinecraftServer; 014 import net.minecraft.util.CryptManager; 015 import net.minecraft.world.EnumGameType; 016 import net.minecraft.world.WorldManager; 017 import net.minecraft.world.WorldServer; 018 import net.minecraft.world.WorldServerMulti; 019 import net.minecraft.world.WorldSettings; 020 import net.minecraft.world.WorldType; 021 import net.minecraft.world.demo.DemoWorldServer; 022 import net.minecraft.world.storage.ISaveHandler; 023 024 import net.minecraftforge.common.DimensionManager; 025 import net.minecraftforge.common.MinecraftForge; 026 import net.minecraftforge.event.world.WorldEvent; 027 028 @SideOnly(Side.CLIENT) 029 public class IntegratedServer extends MinecraftServer 030 { 031 /** The Minecraft instance. */ 032 private final Minecraft mc; 033 private final WorldSettings theWorldSettings; 034 035 /** Instance of IntegratedServerListenThread. */ 036 private IntegratedServerListenThread theServerListeningThread; 037 private boolean isGamePaused = false; 038 private boolean isPublic; 039 private ThreadLanServerPing lanServerPing; 040 041 public IntegratedServer(Minecraft par1Minecraft, String par2Str, String par3Str, WorldSettings par4WorldSettings) 042 { 043 super(new File(Minecraft.getMinecraftDir(), "saves")); 044 this.setServerOwner(par1Minecraft.session.username); 045 this.setFolderName(par2Str); 046 this.setWorldName(par3Str); 047 this.setDemo(par1Minecraft.isDemo()); 048 this.canCreateBonusChest(par4WorldSettings.isBonusChestEnabled()); 049 this.setBuildLimit(256); 050 this.setConfigurationManager(new IntegratedPlayerList(this)); 051 this.mc = par1Minecraft; 052 this.theWorldSettings = par4WorldSettings; 053 054 try 055 { 056 this.theServerListeningThread = new IntegratedServerListenThread(this); 057 } 058 catch (IOException var6) 059 { 060 throw new Error(); 061 } 062 } 063 064 protected void loadAllWorlds(String par1Str, String par2Str, long par3, WorldType par5WorldType, String par6Str) 065 { 066 this.convertMapIfNeeded(par1Str); 067 ISaveHandler var7 = this.getActiveAnvilConverter().getSaveLoader(par1Str, true); 068 069 WorldServer overWorld = (isDemo() ? new DemoWorldServer(this, var7, par2Str, 0, theProfiler) : new WorldServer(this, var7, par2Str, 0, theWorldSettings, theProfiler)); 070 for (int dim : DimensionManager.getStaticDimensionIDs()) 071 { 072 WorldServer world = (dim == 0 ? overWorld : new WorldServerMulti(this, var7, par2Str, dim, theWorldSettings, overWorld, theProfiler)); 073 world.addWorldAccess(new WorldManager(this, world)); 074 if (!this.isSinglePlayer()) 075 { 076 world.getWorldInfo().setGameType(this.getGameType()); 077 } 078 079 MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world)); 080 } 081 082 this.getConfigurationManager().setPlayerManager(new WorldServer[]{ overWorld }); 083 this.setDifficultyForAllWorlds(this.getDifficulty()); 084 this.initialWorldChunkLoad(); 085 } 086 087 /** 088 * Initialises the server and starts it. 089 */ 090 protected boolean startServer() throws IOException 091 { 092 logger.info("Starting integrated minecraft server version 1.4.7"); 093 this.setOnlineMode(false); 094 this.setCanSpawnAnimals(true); 095 this.setCanSpawnNPCs(true); 096 this.setAllowPvp(true); 097 this.setAllowFlight(true); 098 logger.info("Generating keypair"); 099 this.setKeyPair(CryptManager.createNewKeyPair()); 100 this.loadAllWorlds(this.getFolderName(), this.getWorldName(), this.theWorldSettings.getSeed(), this.theWorldSettings.getTerrainType(), this.theWorldSettings.func_82749_j()); 101 this.setMOTD(this.getServerOwner() + " - " + this.worldServers[0].getWorldInfo().getWorldName()); 102 FMLCommonHandler.instance().handleServerStarting(this); 103 return true; 104 } 105 106 /** 107 * Main function called by run() every loop. 108 */ 109 public void tick() 110 { 111 boolean var1 = this.isGamePaused; 112 this.isGamePaused = this.theServerListeningThread.isGamePaused(); 113 114 if (!var1 && this.isGamePaused) 115 { 116 logger.info("Saving and pausing game..."); 117 this.getConfigurationManager().saveAllPlayerData(); 118 this.saveAllWorlds(false); 119 } 120 121 if (!this.isGamePaused) 122 { 123 super.tick(); 124 } 125 } 126 127 public boolean canStructuresSpawn() 128 { 129 return false; 130 } 131 132 public EnumGameType getGameType() 133 { 134 return this.theWorldSettings.getGameType(); 135 } 136 137 /** 138 * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on the client. 139 */ 140 public int getDifficulty() 141 { 142 return this.mc.gameSettings.difficulty; 143 } 144 145 /** 146 * Defaults to false. 147 */ 148 public boolean isHardcore() 149 { 150 return this.theWorldSettings.getHardcoreEnabled(); 151 } 152 153 protected File getDataDirectory() 154 { 155 return this.mc.mcDataDir; 156 } 157 158 public boolean isDedicatedServer() 159 { 160 return false; 161 } 162 163 /** 164 * Gets the IntergratedServerListenThread. 165 */ 166 public IntegratedServerListenThread getServerListeningThread() 167 { 168 return this.theServerListeningThread; 169 } 170 171 /** 172 * Called on exit from the main run() loop. 173 */ 174 protected void finalTick(CrashReport par1CrashReport) 175 { 176 this.mc.crashed(par1CrashReport); 177 } 178 179 /** 180 * Adds the server info, including from theWorldServer, to the crash report. 181 */ 182 public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport) 183 { 184 par1CrashReport = super.addServerInfoToCrashReport(par1CrashReport); 185 par1CrashReport.func_85056_g().addCrashSectionCallable("Type", new CallableType3(this)); 186 par1CrashReport.func_85056_g().addCrashSectionCallable("Is Modded", new CallableIsModded(this)); 187 return par1CrashReport; 188 } 189 190 public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper) 191 { 192 super.addServerStatsToSnooper(par1PlayerUsageSnooper); 193 par1PlayerUsageSnooper.addData("snooper_partner", this.mc.getPlayerUsageSnooper().getUniqueID()); 194 } 195 196 /** 197 * Returns whether snooping is enabled or not. 198 */ 199 public boolean isSnooperEnabled() 200 { 201 return Minecraft.getMinecraft().isSnooperEnabled(); 202 } 203 204 /** 205 * On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections. 206 */ 207 public String shareToLAN(EnumGameType par1EnumGameType, boolean par2) 208 { 209 try 210 { 211 String var3 = this.theServerListeningThread.func_71755_c(); 212 System.out.println("Started on " + var3); 213 this.isPublic = true; 214 this.lanServerPing = new ThreadLanServerPing(this.getMOTD(), var3); 215 this.lanServerPing.start(); 216 this.getConfigurationManager().setGameType(par1EnumGameType); 217 this.getConfigurationManager().setCommandsAllowedForAll(par2); 218 return var3; 219 } 220 catch (IOException var4) 221 { 222 return null; 223 } 224 } 225 226 /** 227 * Saves all necessary data as preparation for stopping the server. 228 */ 229 public void stopServer() 230 { 231 super.stopServer(); 232 233 if (this.lanServerPing != null) 234 { 235 this.lanServerPing.interrupt(); 236 this.lanServerPing = null; 237 } 238 } 239 240 /** 241 * Sets the serverRunning variable to false, in order to get the server to shut down. 242 */ 243 public void initiateShutdown() 244 { 245 super.initiateShutdown(); 246 247 if (this.lanServerPing != null) 248 { 249 this.lanServerPing.interrupt(); 250 this.lanServerPing = null; 251 } 252 } 253 254 /** 255 * Returns true if this integrated server is open to LAN 256 */ 257 public boolean getPublic() 258 { 259 return this.isPublic; 260 } 261 262 /** 263 * Sets the game type for all worlds. 264 */ 265 public void setGameType(EnumGameType par1EnumGameType) 266 { 267 this.getConfigurationManager().setGameType(par1EnumGameType); 268 } 269 270 /** 271 * Return whether command blocks are enabled. 272 */ 273 public boolean isCommandBlockEnabled() 274 { 275 return true; 276 } 277 278 public NetworkListenThread getNetworkThread() 279 { 280 return this.getServerListeningThread(); 281 } 282 }