package net.minecraft.server;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.ArgsWrapper;
import cpw.mods.fml.relauncher.FMLRelauncher;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.IOException;
import java.security.KeyPair;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.block.BlockDispenser;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandManager;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.ServerCommandManager;
import net.minecraft.crash.CrashReport;
import net.minecraft.dispenser.BehaviorArrowDispense;
import net.minecraft.dispenser.BehaviorBucketEmptyDispense;
import net.minecraft.dispenser.BehaviorBucketFullDispense;
import net.minecraft.dispenser.BehaviorDispenseBoat;
import net.minecraft.dispenser.BehaviorDispenseFireball;
import net.minecraft.dispenser.BehaviorDispenseFirework;
import net.minecraft.dispenser.BehaviorDispenseMinecart;
import net.minecraft.dispenser.BehaviorEggDispense;
import net.minecraft.dispenser.BehaviorExpBottleDispense;
import net.minecraft.dispenser.BehaviorMobEggDispense;
import net.minecraft.dispenser.BehaviorPotionDispense;
import net.minecraft.dispenser.BehaviorSnowballDispense;
import net.minecraft.item.Item;
import net.minecraft.network.NetworkListenThread;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet4UpdateTime;
import net.minecraft.network.rcon.RConConsoleSource;
import net.minecraft.profiler.IPlayerUsage;
import net.minecraft.profiler.PlayerUsageSnooper;
import net.minecraft.profiler.Profiler;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.gui.IUpdatePlayerListBox;
import net.minecraft.server.management.ServerConfigurationManager;
import net.minecraft.stats.StatList;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.IProgressUpdate;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ReportedException;
import net.minecraft.util.StringTranslate;
import net.minecraft.util.StringUtils;
import net.minecraft.world.EnumGameType;
import net.minecraft.world.MinecraftException;
import net.minecraft.world.WorldManager;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldServerMulti;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
import net.minecraft.world.chunk.storage.AnvilSaveConverter;
import net.minecraft.world.demo.DemoWorldServer;
import net.minecraft.world.storage.ISaveFormat;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
public abstract class MinecraftServer implements ICommandSender, Runnable, IPlayerUsage
{
/** The logging system. */
public static Logger logger = Logger.getLogger("Minecraft");
/** Instance of Minecraft Server. */
private static MinecraftServer mcServer = null;
private final ISaveFormat anvilConverterForAnvilFile;
/** The PlayerUsageSnooper instance. */
private final PlayerUsageSnooper usageSnooper = new PlayerUsageSnooper("server", this);
private final File anvilFile;
/**
* Collection of objects to update every tick. Type: List<IUpdatePlayerListBox>
*/
private final List tickables = new ArrayList();
private final ICommandManager commandManager;
public final Profiler theProfiler = new Profiler();
/** The server's hostname. */
private String hostname;
/** The server's port. */
private int serverPort = -1;
/** The server world instances. */
public WorldServer[] worldServers;
/** The ServerConfigurationManager instance. */
private ServerConfigurationManager serverConfigManager;
/**
* Indicates whether the server is running or not. Set to false to initiate a shutdown.
*/
private boolean serverRunning = true;
/** Indicates to other classes that the server is safely stopped. */
private boolean serverStopped = false;
/** Incremented every tick. */
private int tickCounter = 0;
/**
* The task the server is currently working on(and will output on outputPercentRemaining).
*/
public String currentTask;
/** The percentage of the current task finished so far. */
public int percentDone;
/** True if the server is in online mode. */
private boolean onlineMode;
/** True if the server has animals turned on. */
private boolean canSpawnAnimals;
private boolean canSpawnNPCs;
/** Indicates whether PvP is active on the server or not. */
private boolean pvpEnabled;
/** Determines if flight is allowed or not. */
private boolean allowFlight;
/** The server MOTD string. */
private String motd;
/** Maximum build height. */
private int buildLimit;
private long lastSentPacketID;
private long lastSentPacketSize;
private long lastReceivedID;
private long lastReceivedSize;
public final long[] sentPacketCountArray = new long[100];
public final long[] sentPacketSizeArray = new long[100];
public final long[] receivedPacketCountArray = new long[100];
public final long[] receivedPacketSizeArray = new long[100];
public final long[] tickTimeArray = new long[100];
/** Stats are [dimension][tick%100] system.nanoTime is stored. */
//public long[][] timeOfLastDimensionTick;
public Hashtable<Integer, long[]> worldTickTimes = new Hashtable<Integer, long[]>();
private KeyPair serverKeyPair;
/** Username of the server owner (for integrated servers) */
private String serverOwner;
private String folderName;
@SideOnly(Side.CLIENT)
private String worldName;
private boolean isDemo;
private boolean enableBonusChest;
/**
* If true, there is no need to save chunks or stop the server, because that is already being done.
*/
private boolean worldIsBeingDeleted;
private String texturePack = "";
private boolean serverIsRunning = false;
/**
* Set when warned for "Can't keep up", which triggers again after 15 seconds.
*/
private long timeOfLastWarning;
private String userMessage;
private boolean startProfiling;
public MinecraftServer(File par1File)
{
mcServer = this;
this.anvilFile = par1File;
this.commandManager = new ServerCommandManager();
this.anvilConverterForAnvilFile = new AnvilSaveConverter(par1File);
this.registerDispenseBehaviors();
}
/**
* Register all dispense behaviors.
*/
private void registerDispenseBehaviors()
{
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.arrow, new BehaviorArrowDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.egg, new BehaviorEggDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.snowball, new BehaviorSnowballDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.expBottle, new BehaviorExpBottleDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.potion, new BehaviorPotionDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.monsterPlacer, new BehaviorMobEggDispense(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.field_92052_bU, new BehaviorDispenseFirework(this));
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.fireballCharge, new BehaviorDispenseFireball(this));
BehaviorDispenseMinecart var1 = new BehaviorDispenseMinecart(this);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartEmpty, var1);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartCrate, var1);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.minecartPowered, var1);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.boat, new BehaviorDispenseBoat(this));
BehaviorBucketFullDispense var2 = new BehaviorBucketFullDispense(this);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketLava, var2);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketWater, var2);
BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketEmpty, new BehaviorBucketEmptyDispense(this));
}
/**
* Initialises the server and starts it.
*/
protected abstract boolean startServer() throws IOException;
protected void convertMapIfNeeded(String par1Str)
{
if (this.getActiveAnvilConverter().isOldMapFormat(par1Str))
{
logger.info("Converting map!");
this.setUserMessage("menu.convertingLevel");
this.getActiveAnvilConverter().convertMapFormat(par1Str, new ConvertingProgressUpdate(this));
}
}
/**
* Typically "menu.convertingLevel", "menu.loadingLevel" or others.
*/
protected synchronized void setUserMessage(String par1Str)
{
this.userMessage = par1Str;
}
@SideOnly(Side.CLIENT)
public synchronized String getUserMessage()
{
return this.userMessage;
}
protected void loadAllWorlds(String par1Str, String par2Str, long par3, WorldType par5WorldType, String par6Str)
{
this.convertMapIfNeeded(par1Str);
this.setUserMessage("menu.loadingLevel");
ISaveHandler var7 = this.anvilConverterForAnvilFile.getSaveLoader(par1Str, true);
WorldInfo var9 = var7.loadWorldInfo();
WorldSettings var8;
if (var9 == null)
{
var8 = new WorldSettings(par3, this.getGameType(), this.canStructuresSpawn(), this.isHardcore(), par5WorldType);
var8.func_82750_a(par6Str);
}
else
{
var8 = new WorldSettings(var9);
}
if (this.enableBonusChest)
{
var8.enableBonusChest();
}
WorldServer overWorld = (isDemo() ? new DemoWorldServer(this, var7, par2Str, 0, theProfiler) : new WorldServer(this, var7, par2Str, 0, var8, theProfiler));
for (int dim : DimensionManager.getStaticDimensionIDs())
{
WorldServer world = (dim == 0 ? overWorld : new WorldServerMulti(this, var7, par2Str, dim, var8, overWorld, theProfiler));
world.addWorldAccess(new WorldManager(this, world));
if (!this.isSinglePlayer())
{
world.getWorldInfo().setGameType(this.getGameType());
}
this.serverConfigManager.setPlayerManager(this.worldServers);
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
}
this.serverConfigManager.setPlayerManager(new WorldServer[]{ overWorld });
this.setDifficultyForAllWorlds(this.getDifficulty());
this.initialWorldChunkLoad();
}
protected void initialWorldChunkLoad()
{
int var5 = 0;
this.setUserMessage("menu.generatingTerrain");
byte var6 = 0;
logger.info("Preparing start region for level " + var6);
WorldServer var7 = this.worldServers[var6];
ChunkCoordinates var8 = var7.getSpawnPoint();
long var9 = System.currentTimeMillis();
for (int var11 = -192; var11 <= 192 && this.isServerRunning(); var11 += 16)
{
for (int var12 = -192; var12 <= 192 && this.isServerRunning(); var12 += 16)
{
long var13 = System.currentTimeMillis();
if (var13 - var9 > 1000L)
{
this.outputPercentRemaining("Preparing spawn area", var5 * 100 / 625);
var9 = var13;
}
++var5;
var7.theChunkProviderServer.loadChunk(var8.posX + var11 >> 4, var8.posZ + var12 >> 4);
}
}
this.clearCurrentTask();
}
public abstract boolean canStructuresSpawn();
public abstract EnumGameType getGameType();
/**
* Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on the client.
*/
public abstract int getDifficulty();
/**
* Defaults to false.
*/
public abstract boolean isHardcore();
/**
* Used to display a percent remaining given text and the percentage.
*/
protected void outputPercentRemaining(String par1Str, int par2)
{
this.currentTask = par1Str;
this.percentDone = par2;
logger.info(par1Str + ": " + par2 + "%");
}
/**
* Set current task to null and set its percentage to 0.
*/
protected void clearCurrentTask()
{
this.currentTask = null;
this.percentDone = 0;
}
/**
* par1 indicates if a log message should be output.
*/
protected void saveAllWorlds(boolean par1)
{
if (!this.worldIsBeingDeleted)
{
WorldServer[] var2 = this.worldServers;
int var3 = var2.length;
for (int var4 = 0; var4 < var3; ++var4)
{
WorldServer var5 = var2[var4];
if (var5 != null)
{
if (!par1)
{
logger.info("Saving chunks for level \'" + var5.getWorldInfo().getWorldName() + "\'/" + var5.provider.getDimensionName());
}
try
{
var5.saveAllChunks(true, (IProgressUpdate)null);
}
catch (MinecraftException var7)
{
logger.warning(var7.getMessage());
}
}
}
}
}
/**
* Saves all necessary data as preparation for stopping the server.
*/
public void stopServer()
{
if (!this.worldIsBeingDeleted)
{
logger.info("Stopping server");
if (this.getNetworkThread() != null)
{
this.getNetworkThread().stopListening();
}
if (this.serverConfigManager != null)
{
logger.info("Saving players");
this.serverConfigManager.saveAllPlayerData();
this.serverConfigManager.removeAllPlayers();
}
logger.info("Saving worlds");
this.saveAllWorlds(false);
for (int var1 = 0; var1 < this.worldServers.length; ++var1)
{
WorldServer var2 = this.worldServers[var1];
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(var2));
var2.flush();
}
WorldServer[] tmp = worldServers;
for (WorldServer world : tmp)
{
DimensionManager.setWorld(world.provider.dimensionId, null);
}
if (this.usageSnooper != null && this.usageSnooper.isSnooperRunning())
{
this.usageSnooper.stopSnooper();
}
}
}
/**
* "getHostname" is already taken, but both return the hostname.
*/
public String getServerHostname()
{
return this.hostname;
}
public void setHostname(String par1Str)
{
this.hostname = par1Str;
}
public boolean isServerRunning()
{
return this.serverRunning;
}
/**
* Sets the serverRunning variable to false, in order to get the server to shut down.
*/
public void initiateShutdown()
{
this.serverRunning = false;
}
public void run()
{
try
{
if (this.startServer())
{
FMLCommonHandler.instance().handleServerStarted();
long var1 = System.currentTimeMillis();
FMLCommonHandler.instance().onWorldLoadTick(worldServers);
for (long var50 = 0L; this.serverRunning; this.serverIsRunning = true)
{
long var5 = System.currentTimeMillis();
long var7 = var5 - var1;
if (var7 > 2000L && var1 - this.timeOfLastWarning >= 15000L)
{
logger.warning("Can\'t keep up! Did the system time change, or is the server overloaded?");
var7 = 2000L;
this.timeOfLastWarning = var1;
}
if (var7 < 0L)
{
logger.warning("Time ran backwards! Did the system time change?");
var7 = 0L;
}
var50 += var7;
var1 = var5;
if (this.worldServers[0].areAllPlayersAsleep())
{
this.tick();
var50 = 0L;
}
else
{
while (var50 > 50L)
{
var50 -= 50L;
this.tick();
}
}
Thread.sleep(1L);
}
FMLCommonHandler.instance().handleServerStopping();
}
else
{
this.finalTick((CrashReport)null);
}
}
catch (Throwable var48)
{
if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
{
return;
}
var48.printStackTrace();
logger.log(Level.SEVERE, "Encountered an unexpected exception " + var48.getClass().getSimpleName(), var48);
CrashReport var2 = null;
if (var48 instanceof ReportedException)
{
var2 = this.addServerInfoToCrashReport(((ReportedException)var48).getCrashReport());
}
else
{
var2 = this.addServerInfoToCrashReport(new CrashReport("Exception in server tick loop", var48));
}
File var3 = new File(new File(this.getDataDirectory(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt");
if (var2.saveToFile(var3))
{
logger.severe("This crash report has been saved to: " + var3.getAbsolutePath());
}
else
{
logger.severe("We were unable to save this crash report to disk.");
}
this.finalTick(var2);
}
finally
{
try
{
if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
{
return;
}
this.stopServer();
this.serverStopped = true;
}
catch (Throwable var46)
{
var46.printStackTrace();
}
finally
{
FMLCommonHandler.instance().handleServerStopped();
this.systemExitNow();
}
}
}
protected File getDataDirectory()
{
return new File(".");
}
/**
* Called on exit from the main run() loop.
*/
protected void finalTick(CrashReport par1CrashReport) {}
/**
* Directly calls System.exit(0), instantly killing the program.
*/
protected void systemExitNow() {}
/**
* Main function called by run() every loop.
*/
public void tick()
{
FMLCommonHandler.instance().rescheduleTicks(Side.SERVER);
long var1 = System.nanoTime();
AxisAlignedBB.getAABBPool().cleanPool();
FMLCommonHandler.instance().onPreServerTick();
++this.tickCounter;
if (this.startProfiling)
{
this.startProfiling = false;
this.theProfiler.profilingEnabled = true;
this.theProfiler.clearProfiling();
}
this.theProfiler.startSection("root");
this.updateTimeLightAndEntities();
if (this.tickCounter % 900 == 0)
{
this.theProfiler.startSection("save");
this.serverConfigManager.saveAllPlayerData();
this.saveAllWorlds(true);
this.theProfiler.endSection();
}
this.theProfiler.startSection("tallying");
this.tickTimeArray[this.tickCounter % 100] = System.nanoTime() - var1;
this.sentPacketCountArray[this.tickCounter % 100] = Packet.sentID - this.lastSentPacketID;
this.lastSentPacketID = Packet.sentID;
this.sentPacketSizeArray[this.tickCounter % 100] = Packet.sentSize - this.lastSentPacketSize;
this.lastSentPacketSize = Packet.sentSize;
this.receivedPacketCountArray[this.tickCounter % 100] = Packet.receivedID - this.lastReceivedID;
this.lastReceivedID = Packet.receivedID;
this.receivedPacketSizeArray[this.tickCounter % 100] = Packet.receivedSize - this.lastReceivedSize;
this.lastReceivedSize = Packet.receivedSize;
this.theProfiler.endSection();
this.theProfiler.startSection("snooper");
if (!this.usageSnooper.isSnooperRunning() && this.tickCounter > 100)
{
this.usageSnooper.startSnooper();
}
if (this.tickCounter % 6000 == 0)
{
this.usageSnooper.addMemoryStatsToSnooper();
}
this.theProfiler.endSection();
this.theProfiler.endSection();
FMLCommonHandler.instance().onPostServerTick();
}
public void updateTimeLightAndEntities()
{
this.theProfiler.startSection("levels");
int var1;
Integer[] ids = DimensionManager.getIDs();
for (int x = 0; x < ids.length; x++)
{
int id = ids[x];
long var2 = System.nanoTime();
if (id == 0 || this.getAllowNether())
{
WorldServer var4 = DimensionManager.getWorld(id);
this.theProfiler.startSection(var4.getWorldInfo().getWorldName());
this.theProfiler.startSection("pools");
var4.getWorldVec3Pool().clear();
this.theProfiler.endSection();
if (this.tickCounter % 20 == 0)
{
this.theProfiler.startSection("timeSync");
this.serverConfigManager.sendPacketToAllPlayersInDimension(new Packet4UpdateTime(var4.getTotalWorldTime(), var4.getWorldTime()), var4.provider.dimensionId);
this.theProfiler.endSection();
}
this.theProfiler.startSection("tick");
FMLCommonHandler.instance().onPreWorldTick(var4);
CrashReport var6;
try
{
var4.tick();
}
catch (Throwable var8)
{
var6 = CrashReport.makeCrashReport(var8, "Exception ticking world");
var4.addWorldInfoToCrashReport(var6);
throw new ReportedException(var6);
}
try
{
var4.updateEntities();
}
catch (Throwable var7)
{
var6 = CrashReport.makeCrashReport(var7, "Exception ticking world entities");
var4.addWorldInfoToCrashReport(var6);
throw new ReportedException(var6);
}
FMLCommonHandler.instance().onPostWorldTick(var4);
this.theProfiler.endSection();
this.theProfiler.startSection("tracker");
var4.getEntityTracker().updateTrackedEntities();
this.theProfiler.endSection();
this.theProfiler.endSection();
}
worldTickTimes.get(id)[this.tickCounter % 100] = System.nanoTime() - var2;
}
this.theProfiler.endStartSection("dim_unloading");
DimensionManager.unloadWorlds(worldTickTimes);
this.theProfiler.endStartSection("connection");
this.getNetworkThread().networkTick();
this.theProfiler.endStartSection("players");
this.serverConfigManager.sendPlayerInfoToAllPlayers();
this.theProfiler.endStartSection("tickables");
for (var1 = 0; var1 < this.tickables.size(); ++var1)
{
((IUpdatePlayerListBox)this.tickables.get(var1)).update();
}
this.theProfiler.endSection();
}
public boolean getAllowNether()
{
return true;
}
public void startServerThread()
{
(new ThreadMinecraftServer(this, "Server thread")).start();
}
/**
* Returns a File object from the specified string.
*/
public File getFile(String par1Str)
{
return new File(this.getDataDirectory(), par1Str);
}
/**
* Logs the message with a level of INFO.
*/
public void logInfo(String par1Str)
{
logger.info(par1Str);
}
/**
* Logs the message with a level of WARN.
*/
public void logWarning(String par1Str)
{
logger.warning(par1Str);
}
/**
* Gets the worldServer by the given dimension.
*/
public WorldServer worldServerForDimension(int par1)
{
WorldServer ret = DimensionManager.getWorld(par1);
if (ret == null)
{
DimensionManager.initDimension(par1);
ret = DimensionManager.getWorld(par1);
}
return ret;
}
@SideOnly(Side.SERVER)
public void func_82010_a(IUpdatePlayerListBox par1IUpdatePlayerListBox)
{
this.tickables.add(par1IUpdatePlayerListBox);
}
/**
* Returns the server's hostname.
*/
public String getHostname()
{
return this.hostname;
}
/**
* Never used, but "getServerPort" is already taken.
*/
public int getPort()
{
return this.serverPort;
}
/**
* minecraftServer.getMOTD is used in 2 places instead (it is a non-virtual function which returns the same thing)
*/
public String getServerMOTD()
{
return this.motd;
}
/**
* Returns the server's Minecraft version as string.
*/
public String getMinecraftVersion()
{
return "1.4.7";
}
/**
* Returns the number of players currently on the server.
*/
public int getCurrentPlayerCount()
{
return this.serverConfigManager.getCurrentPlayerCount();
}
/**
* Returns the maximum number of players allowed on the server.
*/
public int getMaxPlayers()
{
return this.serverConfigManager.getMaxPlayers();
}
/**
* Returns an array of the usernames of all the connected players.
*/
public String[] getAllUsernames()
{
return this.serverConfigManager.getAllUsernames();
}
/**
* Used by RCon's Query in the form of "MajorServerMod 1.2.3: MyPlugin 1.3; AnotherPlugin 2.1; AndSoForth 1.0".
*/
public String getPlugins()
{
return "";
}
public String executeCommand(String par1Str)
{
RConConsoleSource.consoleBuffer.resetLog();
this.commandManager.executeCommand(RConConsoleSource.consoleBuffer, par1Str);
return RConConsoleSource.consoleBuffer.getChatBuffer();
}
/**
* Returns true if debugging is enabled, false otherwise.
*/
public boolean isDebuggingEnabled()
{
return false;
}
/**
* Logs the error message with a level of SEVERE.
*/
public void logSevere(String par1Str)
{
logger.log(Level.SEVERE, par1Str);
}
/**
* If isDebuggingEnabled(), logs the message with a level of INFO.
*/
public void logDebug(String par1Str)
{
if (this.isDebuggingEnabled())
{
logger.log(Level.INFO, par1Str);
}
}
public String getServerModName()
{
return "fml";
}
/**
* Adds the server info, including from theWorldServer, to the crash report.
*/
public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport)
{
par1CrashReport.func_85056_g().addCrashSectionCallable("Profiler Position", new CallableIsServerModded(this));
if (this.worldServers != null && this.worldServers.length > 0 && this.worldServers[0] != null)
{
par1CrashReport.func_85056_g().addCrashSectionCallable("Vec3 Pool Size", new CallableServerProfiler(this));
}
if (this.serverConfigManager != null)
{
par1CrashReport.func_85056_g().addCrashSectionCallable("Player Count", new CallableServerMemoryStats(this));
}
return par1CrashReport;
}
/**
* If par2Str begins with /, then it searches for commands, otherwise it returns players.
*/
public List getPossibleCompletions(ICommandSender par1ICommandSender, String par2Str)
{
ArrayList var3 = new ArrayList();
if (par2Str.startsWith("/"))
{
par2Str = par2Str.substring(1);
boolean var10 = !par2Str.contains(" ");
List var11 = this.commandManager.getPossibleCommands(par1ICommandSender, par2Str);
if (var11 != null)
{
Iterator var12 = var11.iterator();
while (var12.hasNext())
{
String var13 = (String)var12.next();
if (var10)
{
var3.add("/" + var13);
}
else
{
var3.add(var13);
}
}
}
return var3;
}
else
{
String[] var4 = par2Str.split(" ", -1);
String var5 = var4[var4.length - 1];
String[] var6 = this.serverConfigManager.getAllUsernames();
int var7 = var6.length;
for (int var8 = 0; var8 < var7; ++var8)
{
String var9 = var6[var8];
if (CommandBase.doesStringStartWith(var5, var9))
{
var3.add(var9);
}
}
return var3;
}
}
/**
* Gets mcServer.
*/
public static MinecraftServer getServer()
{
return mcServer;
}
/**
* Gets the name of this command sender (usually username, but possibly "Rcon")
*/
public String getCommandSenderName()
{
return "Server";
}
public void sendChatToPlayer(String par1Str)
{
logger.info(StringUtils.stripControlCodes(par1Str));
}
/**
* Returns true if the command sender is allowed to use the given command.
*/
public boolean canCommandSenderUseCommand(int par1, String par2Str)
{
return true;
}
/**
* Translates and formats the given string key with the given arguments.
*/
public String translateString(String par1Str, Object ... par2ArrayOfObj)
{
return StringTranslate.getInstance().translateKeyFormat(par1Str, par2ArrayOfObj);
}
public ICommandManager getCommandManager()
{
return this.commandManager;
}
/**
* Gets KeyPair instanced in MinecraftServer.
*/
public KeyPair getKeyPair()
{
return this.serverKeyPair;
}
/**
* Gets serverPort.
*/
public int getServerPort()
{
return this.serverPort;
}
public void setServerPort(int par1)
{
this.serverPort = par1;
}
/**
* Returns the username of the server owner (for integrated servers)
*/
public String getServerOwner()
{
return this.serverOwner;
}
/**
* Sets the username of the owner of this server (in the case of an integrated server)
*/
public void setServerOwner(String par1Str)
{
this.serverOwner = par1Str;
}
public boolean isSinglePlayer()
{
return this.serverOwner != null;
}
public String getFolderName()
{
return this.folderName;
}
public void setFolderName(String par1Str)
{
this.folderName = par1Str;
}
@SideOnly(Side.CLIENT)
public void setWorldName(String par1Str)
{
this.worldName = par1Str;
}
@SideOnly(Side.CLIENT)
public String getWorldName()
{
return this.worldName;
}
public void setKeyPair(KeyPair par1KeyPair)
{
this.serverKeyPair = par1KeyPair;
}
public void setDifficultyForAllWorlds(int par1)
{
for (int var2 = 0; var2 < this.worldServers.length; ++var2)
{
WorldServer var3 = this.worldServers[var2];
if (var3 != null)
{
if (var3.getWorldInfo().isHardcoreModeEnabled())
{
var3.difficultySetting = 3;
var3.setAllowedSpawnTypes(true, true);
}
else if (this.isSinglePlayer())
{
var3.difficultySetting = par1;
var3.setAllowedSpawnTypes(var3.difficultySetting > 0, true);
}
else
{
var3.difficultySetting = par1;
var3.setAllowedSpawnTypes(this.allowSpawnMonsters(), this.canSpawnAnimals);
}
}
}
}
protected boolean allowSpawnMonsters()
{
return true;
}
/**
* Gets whether this is a demo or not.
*/
public boolean isDemo()
{
return this.isDemo;
}
/**
* Sets whether this is a demo or not.
*/
public void setDemo(boolean par1)
{
this.isDemo = par1;
}
public void canCreateBonusChest(boolean par1)
{
this.enableBonusChest = par1;
}
public ISaveFormat getActiveAnvilConverter()
{
return this.anvilConverterForAnvilFile;
}
/**
* WARNING : directly calls
* getActiveAnvilConverter().deleteWorldDirectory(theWorldServer[0].getSaveHandler().getSaveDirectoryName());
*/
public void deleteWorldAndStopServer()
{
this.worldIsBeingDeleted = true;
this.getActiveAnvilConverter().flushCache();
for (int var1 = 0; var1 < this.worldServers.length; ++var1)
{
WorldServer var2 = this.worldServers[var1];
if (var2 != null)
{
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(var2));
var2.flush();
}
}
this.getActiveAnvilConverter().deleteWorldDirectory(this.worldServers[0].getSaveHandler().getSaveDirectoryName());
this.initiateShutdown();
}
public String getTexturePack()
{
return this.texturePack;
}
public void setTexturePack(String par1Str)
{
this.texturePack = par1Str;
}
public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
{
par1PlayerUsageSnooper.addData("whitelist_enabled", Boolean.valueOf(false));
par1PlayerUsageSnooper.addData("whitelist_count", Integer.valueOf(0));
par1PlayerUsageSnooper.addData("players_current", Integer.valueOf(this.getCurrentPlayerCount()));
par1PlayerUsageSnooper.addData("players_max", Integer.valueOf(this.getMaxPlayers()));
par1PlayerUsageSnooper.addData("players_seen", Integer.valueOf(this.serverConfigManager.getAvailablePlayerDat().length));
par1PlayerUsageSnooper.addData("uses_auth", Boolean.valueOf(this.onlineMode));
par1PlayerUsageSnooper.addData("gui_state", this.getGuiEnabled() ? "enabled" : "disabled");
par1PlayerUsageSnooper.addData("avg_tick_ms", Integer.valueOf((int)(MathHelper.average(this.tickTimeArray) * 1.0E-6D)));
par1PlayerUsageSnooper.addData("avg_sent_packet_count", Integer.valueOf((int)MathHelper.average(this.sentPacketCountArray)));
par1PlayerUsageSnooper.addData("avg_sent_packet_size", Integer.valueOf((int)MathHelper.average(this.sentPacketSizeArray)));
par1PlayerUsageSnooper.addData("avg_rec_packet_count", Integer.valueOf((int)MathHelper.average(this.receivedPacketCountArray)));
par1PlayerUsageSnooper.addData("avg_rec_packet_size", Integer.valueOf((int)MathHelper.average(this.receivedPacketSizeArray)));
int var2 = 0;
for (int var3 = 0; var3 < this.worldServers.length; ++var3)
{
if (this.worldServers[var3] != null)
{
WorldServer var4 = this.worldServers[var3];
WorldInfo var5 = var4.getWorldInfo();
par1PlayerUsageSnooper.addData("world[" + var2 + "][dimension]", Integer.valueOf(var4.provider.dimensionId));
par1PlayerUsageSnooper.addData("world[" + var2 + "][mode]", var5.getGameType());
par1PlayerUsageSnooper.addData("world[" + var2 + "][difficulty]", Integer.valueOf(var4.difficultySetting));
par1PlayerUsageSnooper.addData("world[" + var2 + "][hardcore]", Boolean.valueOf(var5.isHardcoreModeEnabled()));
par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_name]", var5.getTerrainType().getWorldTypeName());
par1PlayerUsageSnooper.addData("world[" + var2 + "][generator_version]", Integer.valueOf(var5.getTerrainType().getGeneratorVersion()));
par1PlayerUsageSnooper.addData("world[" + var2 + "][height]", Integer.valueOf(this.buildLimit));
par1PlayerUsageSnooper.addData("world[" + var2 + "][chunks_loaded]", Integer.valueOf(var4.getChunkProvider().getLoadedChunkCount()));
++var2;
}
}
par1PlayerUsageSnooper.addData("worlds", Integer.valueOf(var2));
}
public void addServerTypeToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
{
par1PlayerUsageSnooper.addData("singleplayer", Boolean.valueOf(this.isSinglePlayer()));
par1PlayerUsageSnooper.addData("server_brand", this.getServerModName());
par1PlayerUsageSnooper.addData("gui_supported", GraphicsEnvironment.isHeadless() ? "headless" : "supported");
par1PlayerUsageSnooper.addData("dedicated", Boolean.valueOf(this.isDedicatedServer()));
}
/**
* Returns whether snooping is enabled or not.
*/
public boolean isSnooperEnabled()
{
return true;
}
/**
* This is checked to be 16 upon receiving the packet, otherwise the packet is ignored.
*/
public int textureSize()
{
return 16;
}
public abstract boolean isDedicatedServer();
public boolean isServerInOnlineMode()
{
return this.onlineMode;
}
public void setOnlineMode(boolean par1)
{
this.onlineMode = par1;
}
public boolean getCanSpawnAnimals()
{
return this.canSpawnAnimals;
}
public void setCanSpawnAnimals(boolean par1)
{
this.canSpawnAnimals = par1;
}
public boolean getCanSpawnNPCs()
{
return this.canSpawnNPCs;
}
public void setCanSpawnNPCs(boolean par1)
{
this.canSpawnNPCs = par1;
}
public boolean isPVPEnabled()
{
return this.pvpEnabled;
}
public void setAllowPvp(boolean par1)
{
this.pvpEnabled = par1;
}
public boolean isFlightAllowed()
{
return this.allowFlight;
}
public void setAllowFlight(boolean par1)
{
this.allowFlight = par1;
}
/**
* Return whether command blocks are enabled.
*/
public abstract boolean isCommandBlockEnabled();
public String getMOTD()
{
return this.motd;
}
public void setMOTD(String par1Str)
{
this.motd = par1Str;
}
public int getBuildLimit()
{
return this.buildLimit;
}
public void setBuildLimit(int par1)
{
this.buildLimit = par1;
}
public boolean isServerStopped()
{
return this.serverStopped;
}
public ServerConfigurationManager getConfigurationManager()
{
return this.serverConfigManager;
}
public void setConfigurationManager(ServerConfigurationManager par1ServerConfigurationManager)
{
this.serverConfigManager = par1ServerConfigurationManager;
}
/**
* Sets the game type for all worlds.
*/
public void setGameType(EnumGameType par1EnumGameType)
{
for (int var2 = 0; var2 < this.worldServers.length; ++var2)
{
getServer().worldServers[var2].getWorldInfo().setGameType(par1EnumGameType);
}
}
public abstract NetworkListenThread getNetworkThread();
@SideOnly(Side.CLIENT)
public boolean serverIsInRunLoop()
{
return this.serverIsRunning;
}
public boolean getGuiEnabled()
{
return false;
}
/**
* On dedicated does nothing. On integrated, sets commandsAllowedForAll, gameType and allows external connections.
*/
public abstract String shareToLAN(EnumGameType var1, boolean var2);
public int getTickCounter()
{
return this.tickCounter;
}
public void enableProfiling()
{
this.startProfiling = true;
}
@SideOnly(Side.CLIENT)
public PlayerUsageSnooper getPlayerUsageSnooper()
{
return this.usageSnooper;
}
/**
* Return the coordinates for this player as ChunkCoordinates.
*/
public ChunkCoordinates getPlayerCoordinates()
{
return new ChunkCoordinates(0, 0, 0);
}
/**
* Return the spawn protection area's size.
*/
public int getSpawnProtectionSize()
{
return 16;
}
/**
* Gets the current player count, maximum player count, and player entity list.
*/
public static ServerConfigurationManager getServerConfigurationManager(MinecraftServer par0MinecraftServer)
{
return par0MinecraftServer.serverConfigManager;
}
@SideOnly(Side.SERVER)
public static void main(String[] par0ArrayOfStr)
{
FMLRelauncher.handleServerRelaunch(new ArgsWrapper(par0ArrayOfStr));
}
@SideOnly(Side.SERVER)
public static void fmlReentry(ArgsWrapper wrap)
{
String[] par0ArrayOfStr = wrap.args;
StatList.nopInit();
try
{
boolean var1 = !GraphicsEnvironment.isHeadless();
String var2 = null;
String var3 = ".";
String var4 = null;
boolean var5 = false;
boolean var6 = false;
int var7 = -1;
for (int var8 = 0; var8 < par0ArrayOfStr.length; ++var8)
{
String var9 = par0ArrayOfStr[var8];
String var10 = var8 == par0ArrayOfStr.length - 1 ? null : par0ArrayOfStr[var8 + 1];
boolean var11 = false;
if (!var9.equals("nogui") && !var9.equals("--nogui"))
{
if (var9.equals("--port") && var10 != null)
{
var11 = true;
try
{
var7 = Integer.parseInt(var10);
}
catch (NumberFormatException var13)
{
;
}
}
else if (var9.equals("--singleplayer") && var10 != null)
{
var11 = true;
var2 = var10;
}
else if (var9.equals("--universe") && var10 != null)
{
var11 = true;
var3 = var10;
}
else if (var9.equals("--world") && var10 != null)
{
var11 = true;
var4 = var10;
}
else if (var9.equals("--demo"))
{
var5 = true;
}
else if (var9.equals("--bonusChest"))
{
var6 = true;
}
}
else
{
var1 = false;
}
if (var11)
{
++var8;
}
}
DedicatedServer var15 = new DedicatedServer(new File(var3));
if (var2 != null)
{
var15.setServerOwner(var2);
}
if (var4 != null)
{
var15.setFolderName(var4);
}
if (var7 >= 0)
{
var15.setServerPort(var7);
}
if (var5)
{
var15.setDemo(true);
}
if (var6)
{
var15.canCreateBonusChest(true);
}
if (var1)
{
var15.enableGui();
}
var15.startServerThread();
Runtime.getRuntime().addShutdownHook(new ThreadDedicatedServer(var15));
}
catch (Exception var14)
{
logger.log(Level.SEVERE, "Failed to start the minecraft server", var14);
}
}
}