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