    001package net.minecraft.server.integrated;
    002
    003import cpw.mods.fml.common.FMLCommonHandler;
    004import cpw.mods.fml.relauncher.Side;
    005import cpw.mods.fml.relauncher.SideOnly;
    006import java.io.File;
    007import java.io.IOException;
    008import net.minecraft.client.Minecraft;
    009import net.minecraft.client.multiplayer.ThreadLanServerPing;
    010import net.minecraft.crash.CrashReport;
    011import net.minecraft.network.NetworkListenThread;
    012import net.minecraft.profiler.PlayerUsageSnooper;
    013import net.minecraft.server.MinecraftServer;
    014import net.minecraft.util.CryptManager;
    015import net.minecraft.world.EnumGameType;
    016import net.minecraft.world.WorldManager;
    017import net.minecraft.world.WorldServer;
    018import net.minecraft.world.WorldServerMulti;
    019import net.minecraft.world.WorldSettings;
    020import net.minecraft.world.WorldType;
    021import net.minecraft.world.demo.DemoWorldServer;
    022import net.minecraft.world.storage.ISaveHandler;
    023
    024import net.minecraftforge.common.DimensionManager;
    025import net.minecraftforge.common.MinecraftForge;
    026import net.minecraftforge.event.world.WorldEvent;
    027
    028@SideOnly(Side.CLIENT)
    029public 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        if (!FMLCommonHandler.instance().handleServerAboutToStart(this)) { return false; }
    101        this.loadAllWorlds(this.getFolderName(), this.getWorldName(), this.theWorldSettings.getSeed(), this.theWorldSettings.getTerrainType(), this.theWorldSettings.func_82749_j());
    102        this.setMOTD(this.getServerOwner() + " - " + this.worldServers[0].getWorldInfo().getWorldName());
    103        return FMLCommonHandler.instance().handleServerStarting(this);
    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}