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 }