    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.6");
    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    }