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 }