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    }