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");
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.addCrashSectionCallable("Type", new CallableType3(this));
173            par1CrashReport.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        public boolean func_82356_Z()
258        {
259            return true;
260        }
261    
262        public NetworkListenThread getNetworkThread()
263        {
264            return this.getServerListeningThread();
265        }
266    }