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