mirror of
https://github.com/barkeser2002/CatServer.git
synced 2026-09-25 09:26:08 +03:00
881 lines
36 KiB
Diff
881 lines
36 KiB
Diff
--- ../src-base/minecraft/net/minecraft/server/MinecraftServer.java
|
|
+++ ../src-work/minecraft/net/minecraft/server/MinecraftServer.java
|
|
@@ -16,19 +16,14 @@
|
|
import io.netty.handler.codec.base64.Base64;
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.awt.image.BufferedImage;
|
|
+import java.io.Console;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.net.Proxy;
|
|
import java.security.KeyPair;
|
|
import java.text.SimpleDateFormat;
|
|
-import java.util.Arrays;
|
|
-import java.util.Collections;
|
|
-import java.util.Date;
|
|
-import java.util.List;
|
|
-import java.util.Queue;
|
|
-import java.util.Random;
|
|
-import java.util.UUID;
|
|
+import java.util.*;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.FutureTask;
|
|
@@ -52,6 +47,7 @@
|
|
import net.minecraft.profiler.Profiler;
|
|
import net.minecraft.profiler.Snooper;
|
|
import net.minecraft.server.dedicated.DedicatedServer;
|
|
+import net.minecraft.server.dedicated.PropertyManager;
|
|
import net.minecraft.server.management.PlayerList;
|
|
import net.minecraft.server.management.PlayerProfileCache;
|
|
import net.minecraft.util.IProgressUpdate;
|
|
@@ -66,33 +62,41 @@
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.util.text.ITextComponent;
|
|
import net.minecraft.util.text.TextComponentString;
|
|
-import net.minecraft.world.EnumDifficulty;
|
|
-import net.minecraft.world.GameType;
|
|
-import net.minecraft.world.MinecraftException;
|
|
-import net.minecraft.world.ServerWorldEventHandler;
|
|
-import net.minecraft.world.World;
|
|
-import net.minecraft.world.WorldServer;
|
|
-import net.minecraft.world.WorldServerMulti;
|
|
-import net.minecraft.world.WorldSettings;
|
|
-import net.minecraft.world.WorldType;
|
|
+import net.minecraft.world.*;
|
|
import net.minecraft.world.chunk.storage.AnvilSaveConverter;
|
|
+import net.minecraft.world.chunk.storage.AnvilSaveHandler;
|
|
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.fml.common.Loader;
|
|
+import net.minecraftforge.fml.common.LoaderState;
|
|
+import net.minecraftforge.fml.common.registry.GameData;
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
import org.apache.commons.lang3.Validate;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
+//CraftBukkit start
|
|
+import jline.console.ConsoleReader;
|
|
+import joptsimple.OptionSet;
|
|
+import org.bukkit.Bukkit;
|
|
+import org.bukkit.craftbukkit.*;
|
|
+import org.bukkit.craftbukkit.command.ColouredConsoleSender;
|
|
+import org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager;
|
|
+import org.bukkit.event.world.*;
|
|
+// CraftBukkit end
|
|
+
|
|
public abstract class MinecraftServer implements Runnable, ICommandSender, IThreadListener, ISnooperInfo
|
|
{
|
|
- private static final Logger LOG = LogManager.getLogger();
|
|
+ public static final Logger LOG = LogManager.getLogger();
|
|
public static final File USER_CACHE_FILE = new File("usercache.json");
|
|
- private final ISaveFormat anvilConverterForAnvilFile;
|
|
+ public ISaveFormat anvilConverterForAnvilFile;
|
|
private final Snooper usageSnooper = new Snooper("server", this, getCurrentTimeMillis());
|
|
- private final File anvilFile;
|
|
+ public File anvilFile;
|
|
+ public static File serverConfigDir=new File("./");
|
|
private final List<ITickable> tickables = Lists.<ITickable>newArrayList();
|
|
public final ICommandManager commandManager;
|
|
public final Profiler theProfiler = new Profiler();
|
|
@@ -141,26 +145,71 @@
|
|
private final GameProfileRepository profileRepo;
|
|
private final PlayerProfileCache profileCache;
|
|
private long nanoTimeSinceStatusRefresh;
|
|
- public final Queue < FutureTask<? >> futureTaskQueue = Queues. < FutureTask<? >> newArrayDeque();
|
|
+ public final Queue < FutureTask<? >> futureTaskQueue = new java.util.concurrent.ConcurrentLinkedQueue<FutureTask<?>>(); // Spigot, PAIL: Rename
|
|
private Thread serverThread;
|
|
private long currentTime = getCurrentTimeMillis();
|
|
@SideOnly(Side.CLIENT)
|
|
private boolean worldIconSet;
|
|
+ // CraftBukkit start
|
|
+ public List<WorldServer> worlds = new ArrayList<WorldServer>();
|
|
+ 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<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
|
+ public int autosavePeriod;
|
|
+ private static final int TPS = 20;
|
|
+ private static final int TICK_TIME = 1000000000 / TPS;
|
|
+ private static final int SAMPLE_INTERVAL = 100;
|
|
+ public final double[] recentTps = new double[ 3 ];
|
|
+ // CraftBukkit end
|
|
|
|
- public MinecraftServer(File anvilFileIn, Proxy proxyIn, DataFixer dataFixerIn, YggdrasilAuthenticationService authServiceIn, MinecraftSessionService sessionServiceIn, GameProfileRepository profileRepoIn, PlayerProfileCache profileCacheIn)
|
|
+ public MinecraftServer(OptionSet options, Proxy proxyIn, DataFixer dataFixerIn, YggdrasilAuthenticationService authServiceIn, MinecraftSessionService sessionServiceIn, GameProfileRepository profileRepoIn, PlayerProfileCache profileCacheIn)
|
|
{
|
|
this.serverProxy = proxyIn;
|
|
this.authService = authServiceIn;
|
|
this.sessionService = sessionServiceIn;
|
|
this.profileRepo = profileRepoIn;
|
|
this.profileCache = profileCacheIn;
|
|
- this.anvilFile = anvilFileIn;
|
|
+ //this.anvilFile = anvilFileIn; // CraftBukkit
|
|
this.networkSystem = new NetworkSystem(this);
|
|
this.commandManager = this.createNewCommandManager();
|
|
- this.anvilConverterForAnvilFile = new AnvilSaveConverter(anvilFileIn, dataFixerIn);
|
|
+ //this.anvilConverterForAnvilFile = new AnvilSaveConverter(anvilFileIn, dataFixerIn); // CraftBukkit - moved to DedicatedServer.init
|
|
this.dataFixer = dataFixerIn;
|
|
+ // 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.getProperty("jline.terminal") == null) {
|
|
+ System.setProperty("jline.terminal", "jline.UnsupportedTerminal");
|
|
+ Main.useJline = false;
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ reader = new ConsoleReader(System.in, System.out);
|
|
+ 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");
|
|
+ Main.useJline = false;
|
|
+ reader = new ConsoleReader(System.in, System.out);
|
|
+ reader.setExpandEvents(false);
|
|
+ } catch (IOException ex) {
|
|
+ LOG.warn((String) null, ex);
|
|
+ }
|
|
+ }
|
|
+ ColouredConsoleSender.setTerminal(reader.getTerminal());
|
|
+ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this));
|
|
+ this.serverThread = primaryThread = new Thread(this, "Server thread"); // Moved from main
|
|
}
|
|
|
|
+ public abstract PropertyManager getPropertyManager();
|
|
+ // CraftBukkit end
|
|
+
|
|
public ServerCommandManager createNewCommandManager()
|
|
{
|
|
return new ServerCommandManager(this);
|
|
@@ -217,43 +266,58 @@
|
|
|
|
public void loadAllWorlds(String saveName, String worldNameIn, long seed, WorldType type, String generatorOptions)
|
|
{
|
|
+ // Cauldron start - register vanilla server commands
|
|
+ ServerCommandManager vanillaCommandManager = (ServerCommandManager)this.getCommandManager();
|
|
+ vanillaCommandManager.registerVanillaCommands();
|
|
+ // Cauldron end
|
|
this.convertMapIfNeeded(saveName);
|
|
this.setUserMessage("menu.loadingLevel");
|
|
- ISaveHandler isavehandler = this.anvilConverterForAnvilFile.getSaveLoader(saveName, true);
|
|
- this.setResourcePackFromWorld(this.getFolderName(), isavehandler);
|
|
- WorldInfo worldinfo = isavehandler.loadWorldInfo();
|
|
- WorldSettings worldsettings;
|
|
+ ISaveHandler iSaveHandler = new AnvilSaveHandler(server.getWorldContainer(),worldNameIn,true, this.dataFixer);
|
|
+ this.setResourcePackFromWorld(this.getFolderName(), iSaveHandler);
|
|
+ WorldInfo worldinfo = iSaveHandler.loadWorldInfo();
|
|
+ // CatServer start
|
|
+ if (!GameData.initializedBukkit) { // CatServer - inject bukkit materials before plugins load
|
|
+ GameData.injectBlockBukkitMaterials();
|
|
+ GameData.injectItemBukkitMaterials();
|
|
+ GameData.initializedBukkit = true;
|
|
+ }
|
|
+ server.loadPlugins();
|
|
+ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP);
|
|
+ // CatServer end
|
|
+ WorldSettings worldsettings = new WorldSettings(seed,this.getGameType(),this.canStructuresSpawn(),this.isHardcore(),type);
|
|
+ worldsettings.setGeneratorOptions(generatorOptions);
|
|
+ if(worldinfo == null){
|
|
+ worldinfo = new WorldInfo(worldsettings,worldNameIn);
|
|
+ }
|
|
+ worldinfo.checkName(worldNameIn);
|
|
+ WorldServer overWorld = (WorldServer)(isDemo() ? new DemoWorldServer(this, iSaveHandler, worldinfo, 0, theProfiler).init() : new WorldServer(this, iSaveHandler, worldinfo, 0, theProfiler, org.bukkit.World.Environment.getEnvironment(0), this.server.getGenerator(worldNameIn)).init());
|
|
+ this.server.scoreboardManager = new CraftScoreboardManager(this, overWorld.getScoreboard());
|
|
|
|
- if (worldinfo == null)
|
|
+ for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs())
|
|
{
|
|
- if (this.isDemo())
|
|
- {
|
|
- worldsettings = DemoWorldServer.DEMO_WORLD_SETTINGS;
|
|
- }
|
|
- else
|
|
- {
|
|
- worldsettings = new WorldSettings(seed, this.getGameType(), this.canStructuresSpawn(), this.isHardcore(), type);
|
|
- worldsettings.setGeneratorOptions(generatorOptions);
|
|
+ String worldType = "";
|
|
+ String name = "";
|
|
|
|
- if (this.enableBonusChest)
|
|
- {
|
|
- worldsettings.enableBonusChest();
|
|
+ WorldServer world = overWorld;
|
|
+ org.bukkit.generator.ChunkGenerator gen = null;
|
|
+ org.bukkit.World.Environment env = org.bukkit.World.Environment.getEnvironment(dim);
|
|
+ if(dim != 0) {
|
|
+ if ((dim == -1) && !this.getAllowNether() || (dim == 1 && !this.server.getAllowEnd())) continue;
|
|
+ worldType = env.toString().toLowerCase();
|
|
+ name = "DIM" + dim;
|
|
+ gen = this.server.getGenerator(name);
|
|
+ this.setUserMessage(name);
|
|
+ ISaveHandler worldServerMulti = new AnvilSaveHandler(server.getWorldContainer(), name, true, dataFixer);
|
|
+ worldinfo = worldServerMulti.loadWorldInfo();
|
|
+ if(worldinfo == null){
|
|
+ worldinfo = new WorldInfo(worldsettings,name);
|
|
}
|
|
+ worldinfo.checkName(name);
|
|
+ world=new WorldServerMulti(this, worldServerMulti, dim, overWorld, this.theProfiler, worldinfo, env, gen);
|
|
}
|
|
+ world.initialize(worldsettings);
|
|
|
|
- worldinfo = new WorldInfo(worldsettings, worldNameIn);
|
|
- }
|
|
- else
|
|
- {
|
|
- worldinfo.setWorldName(worldNameIn);
|
|
- worldsettings = new WorldSettings(worldinfo);
|
|
- }
|
|
-
|
|
- WorldServer overWorld = (WorldServer)(isDemo() ? new DemoWorldServer(this, isavehandler, worldinfo, 0, theProfiler).init() : new WorldServer(this, isavehandler, worldinfo, 0, theProfiler).init());
|
|
- overWorld.initialize(worldsettings);
|
|
- for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs())
|
|
- {
|
|
- WorldServer world = (dim == 0 ? overWorld : (WorldServer)new WorldServerMulti(this, isavehandler, dim, overWorld, theProfiler).init());
|
|
+ this.server.getPluginManager().callEvent(new WorldInitEvent(world.getWorld()));
|
|
world.addEventListener(new ServerWorldEventHandler(this, world));
|
|
|
|
if (!this.isSinglePlayer())
|
|
@@ -261,44 +325,52 @@
|
|
world.getWorldInfo().setGameType(this.getGameType());
|
|
}
|
|
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world));
|
|
- }
|
|
+ this.server.getPluginManager().callEvent(new WorldInitEvent(world.getWorld()));
|
|
+ getPlayerList().setPlayerManager(worlds.toArray(new WorldServer[worlds.size()]));
|
|
|
|
- this.playerList.setPlayerManager(new WorldServer[]{ overWorld });
|
|
+ }
|
|
+ this.playerList.setPlayerManager(this.worldServers);
|
|
this.setDifficultyForAllWorlds(this.getDifficulty());
|
|
this.initialWorldChunkLoad();
|
|
}
|
|
|
|
public void initialWorldChunkLoad()
|
|
{
|
|
- int i = 16;
|
|
- int j = 4;
|
|
- int k = 192;
|
|
- int l = 625;
|
|
+ //int i = 16;
|
|
+ //int j = 4;
|
|
+ //int k = 192;
|
|
+ //int l = 625;
|
|
int i1 = 0;
|
|
this.setUserMessage("menu.generatingTerrain");
|
|
- int j1 = 0;
|
|
- LOG.info("Preparing start region for level 0");
|
|
- WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(j1);
|
|
- BlockPos blockpos = worldserver.getSpawnPoint();
|
|
- long k1 = getCurrentTimeMillis();
|
|
-
|
|
- for (int l1 = -192; l1 <= 192 && this.isServerRunning(); l1 += 16)
|
|
- {
|
|
- for (int i2 = -192; i2 <= 192 && this.isServerRunning(); i2 += 16)
|
|
+ for(int m = 0; m < worldServers.length; m++){
|
|
+ WorldServer worldserver = this.worldServers[m];
|
|
+ LOG.info("Preparing start region for level " + m + " (Seed: " + worldserver.getSeed() + ")");
|
|
+ if(!worldserver.getWorld().getKeepSpawnInMemory()){
|
|
+ continue;
|
|
+ }
|
|
+ BlockPos blockpos = worldserver.getSpawnPoint();
|
|
+ long k1 = getCurrentTimeMillis();
|
|
+ i1 = 0;
|
|
+ for (int l1 = -192; l1 <= 192 && this.isServerRunning(); l1 += 16)
|
|
{
|
|
- long j2 = getCurrentTimeMillis();
|
|
-
|
|
- if (j2 - k1 > 1000L)
|
|
+ for (int i2 = -192; i2 <= 192 && this.isServerRunning(); i2 += 16)
|
|
{
|
|
- this.outputPercentRemaining("Preparing spawn area", i1 * 100 / 625);
|
|
- k1 = j2;
|
|
- }
|
|
+ long j2 = getCurrentTimeMillis();
|
|
|
|
- ++i1;
|
|
- worldserver.getChunkProvider().provideChunk(blockpos.getX() + l1 >> 4, blockpos.getZ() + i2 >> 4);
|
|
+ if (j2 - k1 > 1000L)
|
|
+ {
|
|
+ this.outputPercentRemaining("Preparing spawn area", i1 * 100 / 625);
|
|
+ k1 = j2;
|
|
+ }
|
|
+
|
|
+ ++i1;
|
|
+ worldserver.getChunkProvider().loadChunk(blockpos.getX() + l1 >> 4, blockpos.getZ() + i2 >> 4);
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
+ for(WorldServer worldServer : this.worldServers){
|
|
+ this.server.getPluginManager().callEvent(new WorldLoadEvent(worldServer.getWorld()));
|
|
+ }
|
|
this.clearCurrentTask();
|
|
}
|
|
|
|
@@ -337,81 +409,104 @@
|
|
{
|
|
this.currentTask = null;
|
|
this.percentDone = 0;
|
|
+ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); // CraftBukkit
|
|
}
|
|
|
|
- public void saveAllWorlds(boolean isSilent)
|
|
+ public void saveAllWorlds(boolean isSilent) throws MinecraftException
|
|
{
|
|
- for (WorldServer worldserver : this.worldServers)
|
|
- {
|
|
+
|
|
+ for(int m = 0; m < worlds.size(); m++){
|
|
+ WorldServer worldserver = this.worlds.get(m);
|
|
if (worldserver != null)
|
|
{
|
|
if (!isSilent)
|
|
{
|
|
LOG.info("Saving chunks for level \'{}\'/{}", new Object[] {worldserver.getWorldInfo().getWorldName(), worldserver.provider.getDimensionType().getName()});
|
|
}
|
|
-
|
|
- try
|
|
- {
|
|
+ try {
|
|
worldserver.saveAllChunks(true, (IProgressUpdate)null);
|
|
+ worldserver.saveLevel();
|
|
+ worldserver.flush();
|
|
+ } catch (MinecraftException e){
|
|
+
|
|
}
|
|
- catch (MinecraftException minecraftexception)
|
|
- {
|
|
- LOG.warn(minecraftexception.getMessage());
|
|
- }
|
|
+
|
|
+ WorldSaveEvent event = new WorldSaveEvent(worldserver.getWorld());
|
|
+ this.server.getPluginManager().callEvent(event);
|
|
+
|
|
}
|
|
}
|
|
}
|
|
|
|
- public void stopServer()
|
|
+ public void stopServer() throws MinecraftException
|
|
{
|
|
- LOG.info("Stopping server");
|
|
+ if(Loader.instance().hasReachedState(LoaderState.SERVER_STARTED) && !serverStopped){
|
|
+ LOG.info("Stopping server");
|
|
|
|
- if (this.getNetworkSystem() != null)
|
|
- {
|
|
- this.getNetworkSystem().terminateEndpoints();
|
|
- }
|
|
+ // CraftBukkit start
|
|
+ if (this.server != null)
|
|
+ {
|
|
+ this.server.disablePlugins();
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+ if (this.getNetworkSystem() != null)
|
|
+ {
|
|
+ this.getNetworkSystem().terminateEndpoints();
|
|
+ }
|
|
|
|
- if (this.playerList != null)
|
|
- {
|
|
- LOG.info("Saving players");
|
|
- this.playerList.saveAllPlayerData();
|
|
- this.playerList.removeAllPlayers();
|
|
- }
|
|
-
|
|
- if (this.worldServers != null)
|
|
- {
|
|
- LOG.info("Saving worlds");
|
|
-
|
|
- for (WorldServer worldserver : this.worldServers)
|
|
+ if (this.playerList != null)
|
|
{
|
|
- if (worldserver != null)
|
|
+ LOG.info("Saving players");
|
|
+ this.playerList.saveAllPlayerData();
|
|
+ this.playerList.removeAllPlayers();
|
|
+ }
|
|
+ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets
|
|
+ if (this.worldServers != null)
|
|
+ {
|
|
+ LOG.info("Saving worlds");
|
|
+
|
|
+ for (WorldServer worldserver : this.worldServers)
|
|
{
|
|
- worldserver.disableLevelSaving = false;
|
|
+ if (worldserver != null)
|
|
+ {
|
|
+ worldserver.disableLevelSaving = false;
|
|
+ }
|
|
}
|
|
- }
|
|
|
|
- this.saveAllWorlds(false);
|
|
+ try {
|
|
+ this.saveAllWorlds(false);
|
|
+ } catch (MinecraftException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
|
|
- for (WorldServer worldserver1 : this.worldServers)
|
|
- {
|
|
- if (worldserver1 != null)
|
|
+ for (WorldServer worldserver1 : this.worldServers)
|
|
{
|
|
- net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Unload(worldserver1));
|
|
- worldserver1.flush();
|
|
+ if (worldserver1 != null)
|
|
+ {
|
|
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Unload(worldserver1));
|
|
+ worldserver1.flush();
|
|
+ }
|
|
}
|
|
+
|
|
+ WorldServer[] tmp = worldServers;
|
|
+ for (WorldServer world : tmp)
|
|
+ {
|
|
+ net.minecraftforge.common.DimensionManager.setWorld(world.provider.getDimension(), null, this);
|
|
+ }
|
|
}
|
|
|
|
- WorldServer[] tmp = worldServers;
|
|
- for (WorldServer world : tmp)
|
|
+ if (this.usageSnooper.isSnooperRunning())
|
|
{
|
|
- net.minecraftforge.common.DimensionManager.setWorld(world.provider.getDimension(), null, this);
|
|
+ this.usageSnooper.stopSnooper();
|
|
}
|
|
}
|
|
|
|
- if (this.usageSnooper.isSnooperRunning())
|
|
- {
|
|
- this.usageSnooper.stopSnooper();
|
|
+ // Spigot start
|
|
+ if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
|
|
+ LOG.info("Saving usercache.json");
|
|
+ this.profileCache.save();
|
|
}
|
|
+ // Spigot end
|
|
}
|
|
|
|
public boolean isServerRunning()
|
|
@@ -436,43 +531,34 @@
|
|
this.statusResponse.setServerDescription(new TextComponentString(this.motd));
|
|
this.statusResponse.setVersion(new ServerStatusResponse.Version("1.10.2", 210));
|
|
this.applyServerIconToResponse(this.statusResponse);
|
|
+ DedicatedServer.allowPlayerLogins = true;
|
|
|
|
+ Arrays.fill( recentTps, 20 );
|
|
+ long lastTick = System.nanoTime(), catchupTime = 0, curTime, wait, tickSection = lastTick;
|
|
while (this.serverRunning)
|
|
{
|
|
long k = getCurrentTimeMillis();
|
|
long j = k - this.currentTime;
|
|
+ curTime = System.nanoTime();
|
|
+ wait = TICK_TIME - (curTime - lastTick) - catchupTime;
|
|
|
|
- if (j > 2000L && this.currentTime - this.timeOfLastWarning >= 15000L)
|
|
- {
|
|
- LOG.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(j), Long.valueOf(j / 50L)});
|
|
- j = 2000L;
|
|
- this.timeOfLastWarning = this.currentTime;
|
|
+ if (wait > 0) {
|
|
+ Thread.sleep(wait / 1000000);
|
|
+ catchupTime = 0;
|
|
+ continue;
|
|
+ } else {
|
|
+ catchupTime = Math.min(1000000000, Math.abs(wait));
|
|
}
|
|
-
|
|
- if (j < 0L)
|
|
+ if ( MinecraftServer.currentTick++ % SAMPLE_INTERVAL == 0 )
|
|
{
|
|
- LOG.warn("Time ran backwards! Did the system time change?");
|
|
- j = 0L;
|
|
+ double currentTps = 1E9 / ( curTime - tickSection ) * SAMPLE_INTERVAL;
|
|
+ recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min)
|
|
+ recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min)
|
|
+ recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min)
|
|
+ tickSection = curTime;
|
|
}
|
|
-
|
|
- i += j;
|
|
- this.currentTime = k;
|
|
-
|
|
- if (this.worldServers[0].areAllPlayersAsleep())
|
|
- {
|
|
- this.tick();
|
|
- i = 0L;
|
|
- }
|
|
- else
|
|
- {
|
|
- while (i > 50L)
|
|
- {
|
|
- i -= 50L;
|
|
- this.tick();
|
|
- }
|
|
- }
|
|
-
|
|
- Thread.sleep(Math.max(1L, 50L - i));
|
|
+ lastTick = curTime;
|
|
+ this.tick();
|
|
this.serverIsRunning = true;
|
|
}
|
|
net.minecraftforge.fml.common.FMLCommonHandler.instance().handleServerStopping();
|
|
@@ -521,6 +607,7 @@
|
|
{
|
|
try
|
|
{
|
|
+ org.spigotmc.WatchdogThread.doStop();
|
|
this.stopServer();
|
|
this.serverStopped = true;
|
|
}
|
|
@@ -537,6 +624,10 @@
|
|
}
|
|
}
|
|
|
|
+ private double calcTps(double avg, double exp, double tps) {
|
|
+ return (avg * exp) + (tps * (1 - exp));
|
|
+ }
|
|
+
|
|
public void applyServerIconToResponse(ServerStatusResponse response)
|
|
{
|
|
File file1 = this.getFile("server-icon.png");
|
|
@@ -596,8 +687,9 @@
|
|
{
|
|
}
|
|
|
|
- public void tick()
|
|
+ public void tick() throws MinecraftException
|
|
{
|
|
+ SpigotTimings.serverTickTimer.startTiming();
|
|
long i = System.nanoTime();
|
|
net.minecraftforge.fml.common.FMLCommonHandler.instance().onPreServerTick();
|
|
++this.tickCounter;
|
|
@@ -629,12 +721,18 @@
|
|
this.statusResponse.invalidateJson();
|
|
}
|
|
|
|
- if (this.tickCounter % 900 == 0)
|
|
+ if ((autosavePeriod > 0) && ((this.tickCounter % autosavePeriod) == 0)) //CatServer
|
|
{
|
|
+ SpigotTimings.worldSaveTimer.startTiming();
|
|
this.theProfiler.startSection("save");
|
|
this.playerList.saveAllPlayerData();
|
|
- this.saveAllWorlds(true);
|
|
+ try {
|
|
+ this.saveAllWorlds(true);
|
|
+ } catch (MinecraftException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
this.theProfiler.endSection();
|
|
+ SpigotTimings.worldSaveTimer.stopTiming();
|
|
}
|
|
|
|
this.theProfiler.startSection("tallying");
|
|
@@ -655,23 +753,55 @@
|
|
this.theProfiler.endSection();
|
|
this.theProfiler.endSection();
|
|
net.minecraftforge.fml.common.FMLCommonHandler.instance().onPostServerTick();
|
|
+ org.spigotmc.WatchdogThread.tick(); // Spigot
|
|
+ SpigotTimings.serverTickTimer.stopTiming();
|
|
+ org.spigotmc.CustomTimingsHandler.tick();
|
|
}
|
|
|
|
public void updateTimeLightAndEntities()
|
|
{
|
|
+ SpigotTimings.schedulerTimer.startTiming();
|
|
+ this.server.getScheduler().mainThreadHeartbeat(this.tickCounter);
|
|
+ SpigotTimings.schedulerTimer.stopTiming();
|
|
this.theProfiler.startSection("jobs");
|
|
|
|
- synchronized (this.futureTaskQueue)
|
|
- {
|
|
- while (!this.futureTaskQueue.isEmpty())
|
|
- {
|
|
- Util.runTask((FutureTask)this.futureTaskQueue.poll(), LOG);
|
|
- }
|
|
+ // Spigot start
|
|
+ FutureTask<?> entry;
|
|
+ int count = this.futureTaskQueue.size();
|
|
+ while (count-- > 0 && (entry = this.futureTaskQueue.poll()) != null) {
|
|
+ Util.runTask(entry, MinecraftServer.LOG);
|
|
}
|
|
+ // Spigot end
|
|
|
|
this.theProfiler.endStartSection("levels");
|
|
+
|
|
net.minecraftforge.common.chunkio.ChunkIOExecutor.tick();
|
|
|
|
+ // CraftBukkit start
|
|
+ SpigotTimings.processQueueTimer.startTiming();
|
|
+ // Run tasks that are waiting on processing
|
|
+ while (!processQueue.isEmpty()) {
|
|
+ processQueue.remove().run();
|
|
+ }
|
|
+ SpigotTimings.processQueueTimer.stopTiming();
|
|
+
|
|
+ SpigotTimings.chunkIOTickTimer.startTiming();
|
|
+ org.bukkit.craftbukkit.chunkio.ChunkIOExecutor.tick();
|
|
+ SpigotTimings.chunkIOTickTimer.stopTiming();
|
|
+ // CraftBukkit end
|
|
+
|
|
+ SpigotTimings.timeUpdateTimer.startTiming();
|
|
+ // Send time updates to everyone, it will get the right time from the world the player is in.
|
|
+ if (this.tickCounter % 20 == 0)
|
|
+ {
|
|
+ for (int i = 0; i < this.getPlayerList().playerEntityList.size(); i++)
|
|
+ {
|
|
+ EntityPlayerMP entityplayer = (EntityPlayerMP) this.getPlayerList().playerEntityList.get(i);
|
|
+ entityplayer.connection.sendPacket(new SPacketTimeUpdate(entityplayer.worldObj.getTotalWorldTime(), entityplayer.getPlayerTime(), entityplayer.worldObj.getGameRules().getBoolean("doDaylightCycle"))); // Add support for per player time
|
|
+ }
|
|
+ }
|
|
+ SpigotTimings.timeUpdateTimer.stopTiming();
|
|
+
|
|
Integer[] ids = net.minecraftforge.common.DimensionManager.getIDs(this.tickCounter % 200 == 0);
|
|
for (int x = 0; x < ids.length; x++)
|
|
{
|
|
@@ -682,20 +812,22 @@
|
|
{
|
|
WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(id);
|
|
this.theProfiler.startSection(worldserver.getWorldInfo().getWorldName());
|
|
-
|
|
+ /* Drop global time updates
|
|
if (this.tickCounter % 20 == 0)
|
|
{
|
|
this.theProfiler.startSection("timeSync");
|
|
this.playerList.sendPacketToAllPlayersInDimension(new SPacketTimeUpdate(worldserver.getTotalWorldTime(), worldserver.getWorldTime(), worldserver.getGameRules().getBoolean("doDaylightCycle")), worldserver.provider.getDimension());
|
|
this.theProfiler.endSection();
|
|
}
|
|
-
|
|
+ // CraftBukkit end */
|
|
this.theProfiler.startSection("tick");
|
|
net.minecraftforge.fml.common.FMLCommonHandler.instance().onPreWorldTick(worldserver);
|
|
|
|
try
|
|
{
|
|
+ worldserver.timings.doTick.startTiming();
|
|
worldserver.tick();
|
|
+ worldserver.timings.doTick.stopTiming();
|
|
}
|
|
catch (Throwable throwable1)
|
|
{
|
|
@@ -706,7 +838,9 @@
|
|
|
|
try
|
|
{
|
|
+ worldserver.timings.tickEntities.startTiming();
|
|
worldserver.updateEntities();
|
|
+ worldserver.timings.tickEntities.stopTiming();
|
|
}
|
|
catch (Throwable throwable)
|
|
{
|
|
@@ -718,7 +852,9 @@
|
|
net.minecraftforge.fml.common.FMLCommonHandler.instance().onPostWorldTick(worldserver);
|
|
this.theProfiler.endSection();
|
|
this.theProfiler.startSection("tracker");
|
|
+ worldserver.timings.tracker.startTiming();
|
|
worldserver.getEntityTracker().updateTrackedEntities();
|
|
+ worldserver.timings.tracker.stopTiming();
|
|
this.theProfiler.endSection();
|
|
this.theProfiler.endSection();
|
|
}
|
|
@@ -729,15 +865,21 @@
|
|
this.theProfiler.endStartSection("dim_unloading");
|
|
net.minecraftforge.common.DimensionManager.unloadWorlds(worldTickTimes);
|
|
this.theProfiler.endStartSection("connection");
|
|
+ SpigotTimings.connectionTimer.startTiming();
|
|
this.getNetworkSystem().networkTick();
|
|
+ SpigotTimings.connectionTimer.stopTiming();
|
|
this.theProfiler.endStartSection("players");
|
|
+ SpigotTimings.playerListTimer.startTiming();
|
|
this.playerList.onTick();
|
|
+ SpigotTimings.playerListTimer.stopTiming();
|
|
this.theProfiler.endStartSection("tickables");
|
|
|
|
+ SpigotTimings.tickablesTimer.startTiming();
|
|
for (int k = 0; k < this.tickables.size(); ++k)
|
|
{
|
|
((ITickable)this.tickables.get(k)).update();
|
|
}
|
|
+ SpigotTimings.tickablesTimer.stopTiming();
|
|
|
|
this.theProfiler.endSection();
|
|
}
|
|
@@ -831,56 +973,12 @@
|
|
|
|
public List<String> getTabCompletions(ICommandSender sender, String input, @Nullable BlockPos pos, boolean hasTargetBlock)
|
|
{
|
|
- List<String> list = Lists.<String>newArrayList();
|
|
- boolean flag = input.startsWith("/");
|
|
-
|
|
- if (flag)
|
|
- {
|
|
- input = input.substring(1);
|
|
- }
|
|
-
|
|
- if (!flag && !hasTargetBlock)
|
|
- {
|
|
- String[] astring = input.split(" ", -1);
|
|
- String s2 = astring[astring.length - 1];
|
|
-
|
|
- for (String s1 : this.playerList.getAllUsernames())
|
|
- {
|
|
- if (CommandBase.doesStringStartWith(s2, s1))
|
|
- {
|
|
- list.add(s1);
|
|
- }
|
|
- }
|
|
-
|
|
- return list;
|
|
- }
|
|
- else
|
|
- {
|
|
- boolean flag1 = !input.contains(" ");
|
|
- List<String> list1 = this.commandManager.getTabCompletionOptions(sender, input, pos);
|
|
-
|
|
- if (!list1.isEmpty())
|
|
- {
|
|
- for (String s : list1)
|
|
- {
|
|
- if (flag1)
|
|
- {
|
|
- list.add("/" + s);
|
|
- }
|
|
- else
|
|
- {
|
|
- list.add(s);
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- return list;
|
|
- }
|
|
+ return server.tabComplete(sender, input, pos);
|
|
}
|
|
|
|
public boolean isAnvilFileSet()
|
|
{
|
|
- return this.anvilFile != null;
|
|
+ return true; // CraftBukkit
|
|
}
|
|
|
|
public String getName()
|
|
@@ -1320,6 +1418,13 @@
|
|
{
|
|
return this;
|
|
}
|
|
+
|
|
+ // CraftBukkit start
|
|
+ @Deprecated
|
|
+ public static MinecraftServer getServerInst() {
|
|
+ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
|
|
public int getMaxWorldSize()
|
|
{
|
|
@@ -1334,11 +1439,10 @@
|
|
{
|
|
ListenableFutureTask<V> listenablefuturetask = ListenableFutureTask.<V>create(callable);
|
|
|
|
- synchronized (this.futureTaskQueue)
|
|
- {
|
|
- this.futureTaskQueue.add(listenablefuturetask);
|
|
- return listenablefuturetask;
|
|
- }
|
|
+ // Spigot start
|
|
+ this.futureTaskQueue.add(listenablefuturetask);
|
|
+ return listenablefuturetask;
|
|
+ // Spigot end
|
|
}
|
|
else
|
|
{
|
|
@@ -1400,10 +1504,14 @@
|
|
@SideOnly(Side.SERVER)
|
|
public static void main(String[] p_main_0_)
|
|
{
|
|
+ OptionSet options = org.bukkit.craftbukkit.Main.main(p_main_0_);
|
|
+ if(options == null)
|
|
+ return;
|
|
Bootstrap.register();
|
|
|
|
try
|
|
{
|
|
+ /*
|
|
boolean flag = true;
|
|
String s = null;
|
|
String s1 = ".";
|
|
@@ -1466,14 +1574,19 @@
|
|
{
|
|
++j;
|
|
}
|
|
+ }*/
|
|
+
|
|
+ if (options.has("server-config-dir")) {
|
|
+ MinecraftServer.serverConfigDir = (File) options.valueOf("server-config-dir");
|
|
}
|
|
-
|
|
YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString());
|
|
MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService();
|
|
GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository();
|
|
- PlayerProfileCache playerprofilecache = new PlayerProfileCache(gameprofilerepository, new File(s1, USER_CACHE_FILE.getName()));
|
|
- final DedicatedServer dedicatedserver = new DedicatedServer(new File(s1), DataFixesManager.createFixer(), yggdrasilauthenticationservice, minecraftsessionservice, gameprofilerepository, playerprofilecache);
|
|
+ PlayerProfileCache playerprofilecache = new PlayerProfileCache(gameprofilerepository, new File(MinecraftServer.serverConfigDir, USER_CACHE_FILE.getName()));
|
|
+ //final DedicatedServer dedicatedserver = new DedicatedServer(new File(s1), DataFixesManager.createFixer(), yggdrasilauthenticationservice, minecraftsessionservice, gameprofilerepository, playerprofilecache);
|
|
+ final DedicatedServer dedicatedserver = new DedicatedServer(options, DataFixesManager.createFixer(), yggdrasilauthenticationservice, minecraftsessionservice, gameprofilerepository, playerprofilecache);
|
|
|
|
+ /*
|
|
if (s != null)
|
|
{
|
|
dedicatedserver.setServerOwner(s);
|
|
@@ -1512,6 +1625,24 @@
|
|
dedicatedserver.stopServer();
|
|
}
|
|
});
|
|
+ */
|
|
+ if (options.has("port")) {
|
|
+ int port = (Integer) options.valueOf("port");
|
|
+ if (port > 0) {
|
|
+ dedicatedserver.setServerPort(port);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (options.has("universe")) {
|
|
+ dedicatedserver.anvilFile = (File) options.valueOf("universe");
|
|
+ }
|
|
+
|
|
+ if (options.has("world")) {
|
|
+ dedicatedserver.setWorldName((String) options.valueOf("world"));
|
|
+ }
|
|
+
|
|
+ dedicatedserver.primaryThread.start();
|
|
+ // CraftBukkit end
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
@@ -1528,7 +1659,8 @@
|
|
@SideOnly(Side.SERVER)
|
|
public boolean isDebuggingEnabled()
|
|
{
|
|
- return false;
|
|
+ //return false;
|
|
+ return this.getPropertyManager().getBooleanProperty("debug", false); // CraftBukkit - don't hardcode
|
|
}
|
|
|
|
@SideOnly(Side.SERVER)
|