package net.minecraft.server; import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; import java.io.File; import java.net.Proxy; import java.security.KeyPair; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.UUID; import java.util.concurrent.Callable; import javax.imageio.ImageIO; import net.minecraft.util.com.google.common.base.Charsets; import net.minecraft.util.com.mojang.authlib.GameProfile; import net.minecraft.util.com.mojang.authlib.minecraft.MinecraftSessionService; import net.minecraft.util.com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import net.minecraft.util.io.netty.buffer.ByteBuf; import net.minecraft.util.io.netty.buffer.ByteBufOutputStream; import net.minecraft.util.io.netty.buffer.Unpooled; import net.minecraft.util.io.netty.handler.codec.base64.Base64; import net.minecraft.util.org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start import java.io.IOException; import jline.console.ConsoleReader; import joptsimple.OptionSet; import org.bukkit.World.Environment; import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.server.RemoteServerCommandEvent; import org.bukkit.event.world.WorldSaveEvent; // CraftBukkit end public abstract class MinecraftServer implements ICommandListener, Runnable, IMojangStatistics { private static final Logger h = LogManager.getLogger(); private static MinecraftServer i; public Convertable convertable; // CraftBukkit - private final -> public private final MojangStatisticsGenerator k = new MojangStatisticsGenerator("server", this, ap()); public File universe; // CraftBukkit - private final -> public private final List m = new ArrayList(); private final ICommandHandler n; public final MethodProfiler methodProfiler = new MethodProfiler(); private final ServerConnection o; private final ServerPing p = new ServerPing(); private final Random q = new Random(); private String serverIp; private int s = -1; public WorldServer[] worldServer; private PlayerList t; private boolean isRunning = true; private boolean isStopped; private int ticks; protected final Proxy c; public String d; public int e; private boolean onlineMode; private boolean spawnAnimals; private boolean spawnNPCs; private boolean pvpMode; private boolean allowFlight; private String motd; private int D; private int E = 0; public final long[] f = new long[100]; public long[][] g; private KeyPair F; private String G; private String H; private boolean demoMode; private boolean K; private boolean L; private String M = ""; private boolean N; private long O; private String P; private boolean Q; private boolean R; private final MinecraftSessionService S; private long T = 0L; // CraftBukkit start public List worlds = new ArrayList(); public org.bukkit.craftbukkit.CraftServer server; public OptionSet options; public org.bukkit.command.ConsoleCommandSender console; public org.bukkit.command.RemoteConsoleCommandSender remoteConsole; public ConsoleReader reader; public static int currentTick = (int) (System.currentTimeMillis() / 50); public final Thread primaryThread; public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; // CraftBukkit end public MinecraftServer(OptionSet options, Proxy proxy) { // CraftBukkit - signature file -> OptionSet i = this; this.c = proxy; // this.universe = file1; // CraftBukkit this.o = new ServerConnection(this); this.n = new CommandDispatcher(); // this.convertable = new WorldLoaderServer(file1); // CraftBukkit - moved to DedicatedServer.init this.S = (new YggdrasilAuthenticationService(proxy, UUID.randomUUID().toString())).createMinecraftSessionService(); // CraftBukkit start this.options = options; // Try to see if we're actually running in a terminal, disable jline if not if (System.console() == null) { System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); org.bukkit.craftbukkit.Main.useJline = false; } try { this.reader = new ConsoleReader(System.in, System.out); this.reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators } catch (Throwable e) { try { // Try again with jline disabled for Windows users without C++ 2008 Redistributable System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); System.setProperty("user.language", "en"); org.bukkit.craftbukkit.Main.useJline = false; this.reader = new ConsoleReader(System.in, System.out); this.reader.setExpandEvents(false); } catch (IOException ex) { h.warn((String) null, ex); } } Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); primaryThread = new ThreadServerApplication(this, "Server thread"); // Moved from main } public abstract PropertyManager getPropertyManager(); // CraftBukkit end protected abstract boolean init() throws java.net.UnknownHostException; // CraftBukkit - throws UnknownHostException protected void a(String s) { if (this.getConvertable().isConvertable(s)) { h.info("Converting map!"); this.b("menu.convertingLevel"); this.getConvertable().convert(s, new ConvertProgressUpdater(this)); } } protected synchronized void b(String s) { this.P = s; } protected void a(String s, String s1, long i, WorldType worldtype, String s2) { this.a(s); this.b("menu.loadingLevel"); this.worldServer = new WorldServer[3]; // this.g = new long[this.worldServer.length][100]; // CraftBukkit - Removed ticktime arrays // IDataManager idatamanager = this.convertable.a(s, true); // WorldData worlddata = idatamanager.getWorldData(); /* CraftBukkit start - Removed worldsettings WorldSettings worldsettings; if (worlddata == null) { worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); worldsettings.a(s2); } else { worldsettings = new WorldSettings(worlddata); } if (this.K) { worldsettings.a(); } // */ int worldCount = 3; for (int j = 0; j < worldCount; ++j) { WorldServer world; int dimension = 0; if (j == 1) { if (this.getAllowNether()) { dimension = -1; } else { continue; } } if (j == 2) { if (this.server.getAllowEnd()) { dimension = 1; } else { continue; } } String worldType = Environment.getEnvironment(dimension).toString().toLowerCase(); String name = (dimension == 0) ? s : s + "_" + worldType; org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); WorldSettings worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); worldsettings.a(s2); if (j == 0) { IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), s1, true); if (this.P()) { world = new DemoWorldServer(this, idatamanager, s1, dimension, this.methodProfiler); } else { // world =, b0 to dimension, added Environment and gen world = new WorldServer(this, idatamanager, s1, dimension, worldsettings, this.methodProfiler, Environment.getEnvironment(dimension), gen); } this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); } else { String dim = "DIM" + dimension; File newWorld = new File(new File(name), dim); File oldWorld = new File(new File(s), dim); if ((!newWorld.isDirectory()) && (oldWorld.isDirectory())) { h.info("---- Migration of old " + worldType + " folder required ----"); h.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly."); h.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future."); h.info("Attempting to move " + oldWorld + " to " + newWorld + "..."); if (newWorld.exists()) { h.warn("A file or folder already exists at " + newWorld + "!"); h.info("---- Migration of old " + worldType + " folder failed ----"); } else if (newWorld.getParentFile().mkdirs()) { if (oldWorld.renameTo(newWorld)) { h.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); // Migrate world data too. try { com.google.common.io.Files.copy(new File(new File(s), "level.dat"), new File(new File(name), "level.dat")); } catch (IOException exception) { h.warn("Unable to migrate world data."); } h.info("---- Migration of old " + worldType + " folder complete ----"); } else { h.warn("Could not move folder " + oldWorld + " to " + newWorld + "!"); h.info("---- Migration of old " + worldType + " folder failed ----"); } } else { h.warn("Could not create path for " + newWorld + "!"); h.info("---- Migration of old " + worldType + " folder failed ----"); } } IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), name, true); // world =, b0 to dimension, s1 to name, added Environment and gen world = new SecondaryWorldServer(this, idatamanager, name, dimension, worldsettings, this.worlds.get(0), this.methodProfiler, Environment.getEnvironment(dimension), gen); } if (gen != null) { world.getWorld().getPopulators().addAll(gen.getDefaultPopulators(world.getWorld())); } this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(world.getWorld())); world.addIWorldAccess(new WorldManager(this, world)); if (!this.L()) { world.getWorldData().setGameType(this.getGamemode()); } this.worlds.add(world); this.t.setPlayerFileData(this.worlds.toArray(new WorldServer[this.worlds.size()])); // CraftBukkit end } this.a(this.getDifficulty()); this.g(); } protected void g() { boolean flag = true; boolean flag1 = true; boolean flag2 = true; boolean flag3 = true; int i = 0; this.b("menu.generatingTerrain"); byte b0 = 0; // CraftBukkit start for (int m = 0; m < this.worlds.size(); ++m) { WorldServer worldserver = this.worlds.get(m); h.info("Preparing start region for level " + m + " (Seed: " + worldserver.getSeed() + ")"); if (!worldserver.getWorld().getKeepSpawnInMemory()) { continue; } ChunkCoordinates chunkcoordinates = worldserver.getSpawn(); long j = ap(); i = 0; for (int k = -192; k <= 192 && this.isRunning(); k += 16) { for (int l = -192; l <= 192 && this.isRunning(); l += 16) { long i1 = ap(); if (i1 - j > 1000L) { this.a_("Preparing spawn area", i * 100 / 625); j = i1; } ++i; worldserver.chunkProviderServer.getChunkAt(chunkcoordinates.x + k >> 4, chunkcoordinates.z + l >> 4); } } } // CraftBukkit end this.m(); } public abstract boolean getGenerateStructures(); public abstract EnumGamemode getGamemode(); public abstract EnumDifficulty getDifficulty(); public abstract boolean isHardcore(); public abstract int l(); protected void a_(String s, int i) { this.d = s; this.e = i; h.info(s + ": " + i + "%"); } protected void m() { this.d = null; this.e = 0; this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); // CraftBukkit } protected void saveChunks(boolean flag) throws ExceptionWorldConflict { // CraftBukkit - added throws if (!this.L) { // CraftBukkit start // WorldServer[] aworldserver = this.worldServer; int i = this.worlds.size(); for (int j = 0; j < i; ++j) { WorldServer worldserver = this.worlds.get(j); if (worldserver != null) { if (!flag) { h.info("Saving chunks for level \'" + worldserver.getWorldData().getName() + "\'/" + worldserver.worldProvider.getName()); } worldserver.save(true, (IProgressUpdate) null); worldserver.saveLevel(); WorldSaveEvent event = new WorldSaveEvent(worldserver.getWorld()); this.server.getPluginManager().callEvent(event); // CraftBukkit end } } } } public void stop() throws ExceptionWorldConflict { // CraftBukkit - added throws if (!this.L) { h.info("Stopping server"); // CraftBukkit start if (this.server != null) { this.server.disablePlugins(); } // CraftBukkit end if (this.ag() != null) { this.ag().b(); } if (this.t != null) { h.info("Saving players"); this.t.savePlayers(); this.t.r(); } h.info("Saving worlds"); this.saveChunks(false); /* CraftBukkit start - Handled in saveChunks for (int i = 0; i < this.worldServer.length; ++i) { WorldServer worldserver = this.worldServer[i]; worldserver.saveLevel(); } // CraftBukkit end */ if (this.k.d()) { this.k.e(); } } } public String getServerIp() { return this.serverIp; } public void c(String s) { this.serverIp = s; } public boolean isRunning() { return this.isRunning; } public void safeShutdown() { this.isRunning = false; } public void run() { try { if (this.init()) { long i = ap(); long j = 0L; this.p.setMOTD(new ChatComponentText(this.motd)); this.p.setServerInfo(new ServerPingServerData("1.7.2", 4)); this.a(this.p); while (this.isRunning) { long k = ap(); long l = k - i; if (l > 2000L && i - this.O >= 15000L) { if (this.server.getWarnOnOverload()) // CraftBukkit - Added option to suppress warning messages h.warn("Can\'t keep up! Did the system time change, or is the server overloaded? Running {}ms behind, skipping {} tick(s)", new Object[] { Long.valueOf(l), Long.valueOf(l / 50L)}); l = 2000L; this.O = i; } if (l < 0L) { h.warn("Time ran backwards! Did the system time change?"); l = 0L; } j += l; i = k; if (this.worlds.get(0).everyoneDeeplySleeping()) { // CraftBukkit this.t(); j = 0L; } else { while (j > 50L) { MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit j -= 50L; this.t(); } } Thread.sleep(1L); this.N = true; } } else { this.a((CrashReport) null); } } catch (Throwable throwable) { h.error("Encountered an unexpected exception", throwable); CrashReport crashreport = null; if (throwable instanceof ReportedException) { crashreport = this.b(((ReportedException) throwable).a()); } else { crashreport = this.b(new CrashReport("Exception in server tick loop", throwable)); } File file1 = new File(new File(this.r(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt"); if (crashreport.a(file1)) { h.error("This crash report has been saved to: " + file1.getAbsolutePath()); } else { h.error("We were unable to save this crash report to disk."); } this.a(crashreport); } finally { try { this.stop(); this.isStopped = true; } catch (Throwable throwable1) { h.error("Exception stopping the server", throwable1); } finally { // CraftBukkit start - Restore terminal to original settings try { this.reader.getTerminal().restore(); } catch (Exception e) { } // CraftBukkit end this.s(); } } } private void a(ServerPing serverping) { File file1 = this.d("server-icon.png"); if (file1.isFile()) { ByteBuf bytebuf = Unpooled.buffer(); try { BufferedImage bufferedimage = ImageIO.read(file1); Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide", new Object[0]); Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high", new Object[0]); ImageIO.write(bufferedimage, "PNG", new ByteBufOutputStream(bytebuf)); ByteBuf bytebuf1 = Base64.encode(bytebuf); serverping.setFavicon("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8)); } catch (Exception exception) { h.error("Couldn\'t load server icon", exception); } } } protected File r() { return new File("."); } protected void a(CrashReport crashreport) {} protected void s() {} protected void t() throws ExceptionWorldConflict { // CraftBukkit - added throws long i = System.nanoTime(); AxisAlignedBB.a().a(); ++this.ticks; if (this.Q) { this.Q = false; this.methodProfiler.a = true; this.methodProfiler.a(); } this.methodProfiler.a("root"); this.u(); if (i - this.T >= 5000000000L) { this.T = i; this.p.setPlayerSample(new ServerPingPlayerSample(this.C(), this.B())); GameProfile[] agameprofile = new GameProfile[Math.min(this.B(), 12)]; int j = MathHelper.nextInt(this.q, 0, this.B() - agameprofile.length); for (int k = 0; k < agameprofile.length; ++k) { agameprofile[k] = ((EntityPlayer) this.t.players.get(j + k)).getProfile(); } Collections.shuffle(Arrays.asList(agameprofile)); this.p.b().a(agameprofile); } if ((this.autosavePeriod > 0) && ((this.ticks % this.autosavePeriod) == 0)) { // CraftBukkit this.methodProfiler.a("save"); this.t.savePlayers(); this.saveChunks(true); this.methodProfiler.b(); } this.methodProfiler.a("tallying"); this.f[this.ticks % 100] = System.nanoTime() - i; this.methodProfiler.b(); this.methodProfiler.a("snooper"); if (!this.k.d() && this.ticks > 100) { this.k.a(); } if (this.ticks % 6000 == 0) { this.k.b(); } this.methodProfiler.b(); this.methodProfiler.b(); } public void u() { this.methodProfiler.a("levels"); // CraftBukkit start this.server.getScheduler().mainThreadHeartbeat(this.ticks); // Run tasks that are waiting on processing while (!processQueue.isEmpty()) { processQueue.remove().run(); } org.bukkit.craftbukkit.chunkio.ChunkIOExecutor.tick(); // Send time updates to everyone, it will get the right time from the world the player is in. if (this.ticks % 20 == 0) { for (int i = 0; i < this.getPlayerList().players.size(); ++i) { EntityPlayer entityplayer = (EntityPlayer) this.getPlayerList().players.get(i); entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(entityplayer.world.getTime(), entityplayer.getPlayerTime(), entityplayer.world.getGameRules().getBoolean("doDaylightCycle"))); // Add support for per player time } } int i; for (i = 0; i < this.worlds.size(); ++i) { long j = System.nanoTime(); // if (i == 0 || this.getAllowNether()) { WorldServer worldserver = this.worlds.get(i); this.methodProfiler.a(worldserver.getWorldData().getName()); this.methodProfiler.a("pools"); worldserver.getVec3DPool().a(); this.methodProfiler.b(); /* Drop global time updates if (this.ticks % 20 == 0) { this.methodProfiler.a("timeSync"); this.t.a(new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle")), worldserver.worldProvider.dimension); this.methodProfiler.b(); } // CraftBukkit end */ this.methodProfiler.a("tick"); CrashReport crashreport; try { worldserver.doTick(); } catch (Throwable throwable) { crashreport = CrashReport.a(throwable, "Exception ticking world"); worldserver.a(crashreport); throw new ReportedException(crashreport); } try { worldserver.tickEntities(); } catch (Throwable throwable1) { crashreport = CrashReport.a(throwable1, "Exception ticking world entities"); worldserver.a(crashreport); throw new ReportedException(crashreport); } this.methodProfiler.b(); this.methodProfiler.a("tracker"); worldserver.getTracker().updatePlayers(); this.methodProfiler.b(); this.methodProfiler.b(); // } // CraftBukkit // this.g[i][this.ticks % 100] = System.nanoTime() - j; // CraftBukkit } this.methodProfiler.c("connection"); this.ag().c(); this.methodProfiler.c("players"); this.t.tick(); this.methodProfiler.c("tickables"); for (i = 0; i < this.m.size(); ++i) { ((IUpdatePlayerListBox) this.m.get(i)).a(); } this.methodProfiler.b(); } public boolean getAllowNether() { return true; } public void a(IUpdatePlayerListBox iupdateplayerlistbox) { this.m.add(iupdateplayerlistbox); } public static void main(final OptionSet options) { // CraftBukkit - replaces main(String[] astring) DispenserRegistry.b(); try { /* CraftBukkit start - Replace everything boolean flag = !GraphicsEnvironment.isHeadless(); String s = null; String s1 = "."; String s2 = null; boolean flag1 = false; boolean flag2 = false; int i = -1; for (int j = 0; j < astring.length; ++j) { String s3 = astring[j]; String s4 = j == astring.length - 1 ? null : astring[j + 1]; boolean flag3 = false; if (!s3.equals("nogui") && !s3.equals("--nogui")) { if (s3.equals("--port") && s4 != null) { flag3 = true; try { i = Integer.parseInt(s4); } catch (NumberFormatException numberformatexception) { ; } } else if (s3.equals("--singleplayer") && s4 != null) { flag3 = true; s = s4; } else if (s3.equals("--universe") && s4 != null) { flag3 = true; s1 = s4; } else if (s3.equals("--world") && s4 != null) { flag3 = true; s2 = s4; } else if (s3.equals("--demo")) { flag1 = true; } else if (s3.equals("--bonusChest")) { flag2 = true; } } else { flag = false; } if (flag3) { ++j; } } DedicatedServer dedicatedserver = new DedicatedServer(new File(s1)); if (s != null) { dedicatedserver.j(s); } if (s2 != null) { dedicatedserver.k(s2); } if (i >= 0) { dedicatedserver.setPort(i); } if (flag1) { dedicatedserver.b(true); } if (flag2) { dedicatedserver.c(true); } if (flag) { dedicatedserver.ay(); } // */ DedicatedServer dedicatedserver = new DedicatedServer(options); if (options.has("port")) { int port = (Integer) options.valueOf("port"); if (port > 0) { dedicatedserver.setPort(port); } } if (options.has("universe")) { dedicatedserver.universe = (File) options.valueOf("universe"); } if (options.has("world")) { dedicatedserver.k((String) options.valueOf("world")); } dedicatedserver.primaryThread.start(); // Runtime.getRuntime().addShutdownHook(new ThreadShutdown("Server Shutdown Thread", dedicatedserver)); // CraftBukkit end } catch (Exception exception) { h.fatal("Failed to start the minecraft server", exception); } } public void w() { // (new ThreadServerApplication(this, "Server thread")).start(); // CraftBukkit - prevent abuse } public File d(String s) { return new File(this.r(), s); } public void info(String s) { h.info(s); } public void warning(String s) { h.warn(s); } public WorldServer getWorldServer(int i) { // CraftBukkit start for (WorldServer world : this.worlds) { if (world.dimension == i) { return world; } } return this.worlds.get(0); // CraftBukkit end } public String x() { return this.serverIp; } public int y() { return this.s; } public String z() { return this.motd; } public String getVersion() { return "1.7.2"; } public int B() { return this.t.getPlayerCount(); } public int C() { return this.t.getMaxPlayers(); } public String[] getPlayers() { return this.t.d(); } public String getPlugins() { // CraftBukkit start - Whole method StringBuilder result = new StringBuilder(); org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); result.append(server.getName()); result.append(" on Bukkit "); result.append(server.getBukkitVersion()); if (plugins.length > 0 && this.server.getQueryPlugins()) { result.append(": "); for (int i = 0; i < plugins.length; i++) { if (i > 0) { result.append("; "); } result.append(plugins[i].getDescription().getName()); result.append(" "); result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); } } return result.toString(); // CraftBukkit end } // CraftBukkit start public String g(final String s) { // final parameter Waitable waitable = new Waitable() { @Override protected String evaluate() { RemoteControlCommandListener.instance.e(); // Event changes start RemoteServerCommandEvent event = new RemoteServerCommandEvent(MinecraftServer.this.remoteConsole, s); MinecraftServer.this.server.getPluginManager().callEvent(event); // Event changes end ServerCommand servercommand = new ServerCommand(event.getCommand(), RemoteControlCommandListener.instance); MinecraftServer.this.server.dispatchServerCommand(MinecraftServer.this.remoteConsole, servercommand); // CraftBukkit // this.n.a(RemoteControlCommandListener.instance, s); return RemoteControlCommandListener.instance.f(); }}; processQueue.add(waitable); try { return waitable.get(); } catch (java.util.concurrent.ExecutionException e) { throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Maintain interrupted state throw new RuntimeException("Interrupted processing rcon command " + s, e); } // CraftBukkit end } public boolean isDebugging() { return this.getPropertyManager().getBoolean("debug", false); // CraftBukkit - don't hardcode } public void h(String s) { h.error(s); } public void i(String s) { if (this.isDebugging()) { h.info(s); } } public String getServerModName() { return "craftbukkit"; // CraftBukkit - cb > vanilla! } public CrashReport b(CrashReport crashreport) { crashreport.g().a("Profiler Position", (Callable) (new CrashReportProfilerPosition(this))); if (this.worlds != null && this.worlds.size() > 0 && this.worlds.get(0) != null) { // CraftBukkit crashreport.g().a("Vec3 Pool Size", (Callable) (new CrashReportVec3DPoolSize(this))); } if (this.t != null) { crashreport.g().a("Player Count", (Callable) (new CrashReportPlayerCount(this))); } return crashreport; } public List a(ICommandListener icommandlistener, String s) { // CraftBukkit start - Allow tab-completion of Bukkit commands /* ArrayList arraylist = new ArrayList(); if (s.startsWith("/")) { s = s.substring(1); boolean flag = !s.contains(" "); List list = this.n.b(icommandlistener, s); if (list != null) { Iterator iterator = list.iterator(); while (iterator.hasNext()) { String s1 = (String) iterator.next(); if (flag) { arraylist.add("/" + s1); } else { arraylist.add(s1); } } } return arraylist; } else { String[] astring = s.split(" ", -1); String s2 = astring[astring.length - 1]; String[] astring1 = this.t.d(); int i = astring1.length; for (int j = 0; j < i; ++j) { String s3 = astring1[j]; if (CommandAbstract.a(s2, s3)) { arraylist.add(s3); } } return arraylist; } */ return this.server.tabComplete(icommandlistener, s); // CraftBukkit end } public static MinecraftServer getServer() { return i; } public String getName() { return "Server"; } public void sendMessage(IChatBaseComponent ichatbasecomponent) { h.info(ichatbasecomponent.c()); } public boolean a(int i, String s) { return true; } public ICommandHandler getCommandHandler() { return this.n; } public KeyPair I() { return this.F; } public int J() { return this.s; } public void setPort(int i) { this.s = i; } public String K() { return this.G; } public void j(String s) { this.G = s; } public boolean L() { return this.G != null; } public String M() { return this.H; } public void k(String s) { this.H = s; } public void a(KeyPair keypair) { this.F = keypair; } public void a(EnumDifficulty enumdifficulty) { // CraftBukkit start for (int j = 0; j < this.worlds.size(); ++j) { WorldServer worldserver = this.worlds.get(j); // CraftBukkit end if (worldserver != null) { if (worldserver.getWorldData().isHardcore()) { worldserver.difficulty = EnumDifficulty.HARD; worldserver.setSpawnFlags(true, true); } else if (this.L()) { worldserver.difficulty = enumdifficulty; worldserver.setSpawnFlags(worldserver.difficulty != EnumDifficulty.PEACEFUL, true); } else { worldserver.difficulty = enumdifficulty; worldserver.setSpawnFlags(this.getSpawnMonsters(), this.spawnAnimals); } } } } protected boolean getSpawnMonsters() { return true; } public boolean P() { return this.demoMode; } public void b(boolean flag) { this.demoMode = flag; } public void c(boolean flag) { this.K = flag; } public Convertable getConvertable() { return this.convertable; } public void S() { this.L = true; this.getConvertable().d(); // CraftBukkit start for (int i = 0; i < this.worlds.size(); ++i) { WorldServer worldserver = this.worlds.get(i); // CraftBukkit end if (worldserver != null) { worldserver.saveLevel(); } } this.getConvertable().e(this.worlds.get(0).getDataManager().g()); // CraftBukkit this.safeShutdown(); } public String getResourcePack() { return this.M; } public void setTexturePack(String s) { this.M = s; } public void a(MojangStatisticsGenerator mojangstatisticsgenerator) { mojangstatisticsgenerator.a("whitelist_enabled", Boolean.valueOf(false)); mojangstatisticsgenerator.a("whitelist_count", Integer.valueOf(0)); mojangstatisticsgenerator.a("players_current", Integer.valueOf(this.B())); mojangstatisticsgenerator.a("players_max", Integer.valueOf(this.C())); mojangstatisticsgenerator.a("players_seen", Integer.valueOf(this.t.getSeenPlayers().length)); mojangstatisticsgenerator.a("uses_auth", Boolean.valueOf(this.onlineMode)); mojangstatisticsgenerator.a("gui_state", this.ai() ? "enabled" : "disabled"); mojangstatisticsgenerator.a("run_time", Long.valueOf((ap() - mojangstatisticsgenerator.g()) / 60L * 1000L)); mojangstatisticsgenerator.a("avg_tick_ms", Integer.valueOf((int) (MathHelper.a(this.f) * 1.0E-6D))); int i = 0; // CraftBukkit start for (int j = 0; j < this.worlds.size(); ++j) { WorldServer worldserver = this.worlds.get(j); if (worldServer != null) { // CraftBukkit end WorldData worlddata = worldserver.getWorldData(); mojangstatisticsgenerator.a("world[" + i + "][dimension]", Integer.valueOf(worldserver.worldProvider.dimension)); mojangstatisticsgenerator.a("world[" + i + "][mode]", worlddata.getGameType()); mojangstatisticsgenerator.a("world[" + i + "][difficulty]", worldserver.difficulty); mojangstatisticsgenerator.a("world[" + i + "][hardcore]", Boolean.valueOf(worlddata.isHardcore())); mojangstatisticsgenerator.a("world[" + i + "][generator_name]", worlddata.getType().name()); mojangstatisticsgenerator.a("world[" + i + "][generator_version]", Integer.valueOf(worlddata.getType().getVersion())); mojangstatisticsgenerator.a("world[" + i + "][height]", Integer.valueOf(this.D)); mojangstatisticsgenerator.a("world[" + i + "][chunks_loaded]", Integer.valueOf(worldserver.K().getLoadedChunks())); ++i; } } mojangstatisticsgenerator.a("worlds", Integer.valueOf(i)); } public void b(MojangStatisticsGenerator mojangstatisticsgenerator) { mojangstatisticsgenerator.a("singleplayer", Boolean.valueOf(this.L())); mojangstatisticsgenerator.a("server_brand", this.getServerModName()); mojangstatisticsgenerator.a("gui_supported", GraphicsEnvironment.isHeadless() ? "headless" : "supported"); mojangstatisticsgenerator.a("dedicated", Boolean.valueOf(this.V())); } public boolean getSnooperEnabled() { return true; } public abstract boolean V(); public boolean getOnlineMode() { return this.server.getOnlineMode(); // CraftBukkit } public void setOnlineMode(boolean flag) { this.onlineMode = flag; } public boolean getSpawnAnimals() { return this.spawnAnimals; } public void setSpawnAnimals(boolean flag) { this.spawnAnimals = flag; } public boolean getSpawnNPCs() { return this.spawnNPCs; } public void setSpawnNPCs(boolean flag) { this.spawnNPCs = flag; } public boolean getPvP() { return this.pvpMode; } public void setPvP(boolean flag) { this.pvpMode = flag; } public boolean getAllowFlight() { return this.allowFlight; } public void setAllowFlight(boolean flag) { this.allowFlight = flag; } public abstract boolean getEnableCommandBlock(); public String getMotd() { return this.motd; } public void setMotd(String s) { this.motd = s; } public int getMaxBuildHeight() { return this.D; } public void c(int i) { this.D = i; } public boolean isStopped() { return this.isStopped; } public PlayerList getPlayerList() { return this.t; } public void a(PlayerList playerlist) { this.t = playerlist; } public void a(EnumGamemode enumgamemode) { // CraftBukkit start for (int i = 0; i < this.worlds.size(); ++i) { getServer().worlds.get(i).getWorldData().setGameType(enumgamemode); // CraftBukkit end } } public ServerConnection ag() { return this.o; } public boolean ai() { return false; } public abstract String a(EnumGamemode enumgamemode, boolean flag); public int aj() { return this.ticks; } public void ak() { this.Q = true; } public ChunkCoordinates getChunkCoordinates() { return new ChunkCoordinates(0, 0, 0); } public World getWorld() { return this.worlds.get(0); // CraftBukkit } public int getSpawnProtection() { return 16; } public boolean a(World world, int i, int j, int k, EntityHuman entityhuman) { return false; } public void setForceGamemode(boolean flag) { this.R = flag; } public boolean getForceGamemode() { return this.R; } public Proxy ao() { return this.c; } public static long ap() { return System.currentTimeMillis(); } public int aq() { return this.E; } public void d(int i) { this.E = i; } public IChatBaseComponent getScoreboardDisplayName() { return new ChatComponentText(this.getName()); } public boolean ar() { return true; } public MinecraftSessionService as() { return this.S; } public ServerPing at() { return this.p; } public void au() { this.T = 0L; } public static Logger av() { return h; } public static PlayerList a(MinecraftServer minecraftserver) { return minecraftserver.t; } }