geforkt von Mirrors/Paper
reformat spigot package
Dieser Commit ist enthalten in:
Ursprung
7d29c678f7
Commit
57c683647f
@ -2,17 +2,14 @@ package org.spigotmc;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class AsyncCatcher
|
||||
{
|
||||
public class AsyncCatcher {
|
||||
|
||||
public static boolean enabled = true;
|
||||
|
||||
public static void catchOp(String reason)
|
||||
{
|
||||
if ( AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread )
|
||||
{
|
||||
MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper
|
||||
throw new IllegalStateException( "Asynchronous " + reason + "!" );
|
||||
public static void catchOp(String reason) {
|
||||
if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) {
|
||||
MinecraftServer.LOGGER.error("Thread {} failed main thread check: {}", Thread.currentThread().getName(), reason, new Throwable()); // Paper
|
||||
throw new IllegalStateException("Asynchronous " + reason + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,35 +5,30 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
|
||||
public class LimitStream extends FilterInputStream
|
||||
{
|
||||
public class LimitStream extends FilterInputStream {
|
||||
|
||||
private final NbtAccounter limit;
|
||||
|
||||
public LimitStream(InputStream is, NbtAccounter limit)
|
||||
{
|
||||
super( is );
|
||||
public LimitStream(InputStream is, NbtAccounter limit) {
|
||||
super(is);
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
this.limit.accountBytes( 1 );
|
||||
public int read() throws IOException {
|
||||
this.limit.accountBytes(1);
|
||||
return super.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException
|
||||
{
|
||||
this.limit.accountBytes( b.length );
|
||||
return super.read( b );
|
||||
public int read(byte[] b) throws IOException {
|
||||
this.limit.accountBytes(b.length);
|
||||
return super.read(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
this.limit.accountBytes( len );
|
||||
return super.read( b, off, len );
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
this.limit.accountBytes(len);
|
||||
return super.read(b, off, len);
|
||||
}
|
||||
}
|
||||
|
@ -1,641 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
package org.spigotmc;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
/**
|
||||
* <p> The metrics class obtains data about a plugin and submits statistics about it to the metrics backend. </p> <p>
|
||||
* Public methods provided by this class: </p>
|
||||
* <code>
|
||||
* Graph createGraph(String name); <br/>
|
||||
* void addCustomData(BukkitMetrics.Plotter plotter); <br/>
|
||||
* void start(); <br/>
|
||||
* </code>
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private static final int REVISION = 6;
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "https://mcstats.spigotmc.org";
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/report/%s";
|
||||
/**
|
||||
* The separator to use for custom data. This MUST NOT change unless you are hosting your own version of metrics and
|
||||
* want to change it.
|
||||
*/
|
||||
private static final String CUSTOM_DATA_SEPARATOR = "~~";
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 10;
|
||||
/**
|
||||
* All of the custom graphs to submit to metrics
|
||||
*/
|
||||
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
|
||||
/**
|
||||
* The default graph, used for addCustomData when you don't want a specific graph
|
||||
*/
|
||||
private final Graph defaultGraph = new Graph("Default");
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final YamlConfiguration configuration;
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
/**
|
||||
* Lock for synchronization
|
||||
*/
|
||||
private final Object optOutLock = new Object();
|
||||
/**
|
||||
* The scheduled task
|
||||
*/
|
||||
private volatile Timer task = null;
|
||||
|
||||
public Metrics() throws IOException {
|
||||
// load the config
|
||||
this.configurationFile = this.getConfigFile();
|
||||
this.configuration = YamlConfiguration.loadConfiguration(this.configurationFile);
|
||||
|
||||
// add some defaults
|
||||
this.configuration.addDefault("opt-out", false);
|
||||
this.configuration.addDefault("guid", UUID.randomUUID().toString());
|
||||
this.configuration.addDefault("debug", false);
|
||||
|
||||
// Do we need to create the file?
|
||||
if (this.configuration.get("guid", null) == null) {
|
||||
this.configuration.options().header("http://mcstats.org").copyDefaults(true);
|
||||
this.configuration.save(this.configurationFile);
|
||||
}
|
||||
|
||||
// Load the guid then
|
||||
this.guid = this.configuration.getString("guid");
|
||||
this.debug = this.configuration.getBoolean("debug", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
|
||||
* website. Plotters can be added to the graph object returned.
|
||||
*
|
||||
* @param name The name of the graph
|
||||
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
|
||||
*/
|
||||
public Graph createGraph(final String name) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Graph name cannot be null");
|
||||
}
|
||||
|
||||
// Construct the graph object
|
||||
final Graph graph = new Graph(name);
|
||||
|
||||
// Now we can add our graph
|
||||
this.graphs.add(graph);
|
||||
|
||||
// and return back
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
|
||||
*
|
||||
* @param graph The name of the graph
|
||||
*/
|
||||
public void addGraph(final Graph graph) {
|
||||
if (graph == null) {
|
||||
throw new IllegalArgumentException("Graph cannot be null");
|
||||
}
|
||||
|
||||
this.graphs.add(graph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom data plotter to the default graph
|
||||
*
|
||||
* @param plotter The plotter to use to plot custom data
|
||||
*/
|
||||
public void addCustomData(final Plotter plotter) {
|
||||
if (plotter == null) {
|
||||
throw new IllegalArgumentException("Plotter cannot be null");
|
||||
}
|
||||
|
||||
// Add the plotter to the graph o/
|
||||
this.defaultGraph.addPlotter(plotter);
|
||||
|
||||
// Ensure the default graph is included in the submitted graphs
|
||||
this.graphs.add(this.defaultGraph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
|
||||
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
|
||||
* ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
synchronized (this.optOutLock) {
|
||||
// Did we opt out?
|
||||
if (this.isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is metrics already running?
|
||||
if (this.task != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Begin hitting the server with glorious data
|
||||
this.task = new Timer("Spigot Metrics Thread", true);
|
||||
|
||||
this.task.scheduleAtFixedRate(new TimerTask() {
|
||||
private boolean firstPost = true;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// This has to be synchronized or it can collide with the disable method.
|
||||
synchronized (Metrics.this.optOutLock) {
|
||||
// Disable Task, if it is running and the server owner decided to opt-out
|
||||
if (Metrics.this.isOptOut() && Metrics.this.task != null) {
|
||||
Metrics.this.task.cancel();
|
||||
Metrics.this.task = null;
|
||||
// Tell all plotters to stop gathering information.
|
||||
for (Graph graph : Metrics.this.graphs) {
|
||||
graph.onOptOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We use the inverse of firstPost because if it is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to FALSE
|
||||
// Each time thereafter it will evaluate to TRUE, i.e PING!
|
||||
Metrics.this.postPlugin(!this.firstPost);
|
||||
|
||||
// After the first post we set firstPost to false
|
||||
// Each post thereafter will be a ping
|
||||
this.firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (Metrics.this.debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, TimeUnit.MINUTES.toMillis(Metrics.PING_INTERVAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
synchronized (this.optOutLock) {
|
||||
try {
|
||||
// Reload the metrics file
|
||||
this.configuration.load(this.getConfigFile());
|
||||
} catch (IOException ex) {
|
||||
if (this.debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
if (this.debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return this.configuration.getBoolean("opt-out", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (this.optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (this.isOptOut()) {
|
||||
this.configuration.set("opt-out", false);
|
||||
this.configuration.save(this.configurationFile);
|
||||
}
|
||||
|
||||
// Enable Task, if it is not running
|
||||
if (this.task == null) {
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (this.optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!this.isOptOut()) {
|
||||
this.configuration.set("opt-out", true);
|
||||
this.configuration.save(this.configurationFile);
|
||||
}
|
||||
|
||||
// Disable Task, if it is running
|
||||
if (this.task != null) {
|
||||
this.task.cancel();
|
||||
this.task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
|
||||
// is to abuse the plugin object we already have
|
||||
// plugin.getDataFolder() => base/plugins/PluginA/
|
||||
// pluginsFolder => base/plugins/
|
||||
// The base is not necessarily relative to the startup directory.
|
||||
// File pluginsFolder = plugin.getDataFolder().getParentFile();
|
||||
|
||||
// return => base/plugins/PluginMetrics/config.yml
|
||||
return new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "PluginMetrics"), "config.yml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
String pluginName = "Spigot";
|
||||
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
|
||||
String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown";
|
||||
String serverVersion = Bukkit.getVersion();
|
||||
int playersOnline = Bukkit.getServer().getOnlinePlayers().size();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
final StringBuilder data = new StringBuilder();
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
data.append(Metrics.encode("guid")).append('=').append(Metrics.encode(this.guid));
|
||||
Metrics.encodeDataPair(data, "version", pluginVersion);
|
||||
Metrics.encodeDataPair(data, "server", serverVersion);
|
||||
Metrics.encodeDataPair(data, "players", Integer.toString(playersOnline));
|
||||
Metrics.encodeDataPair(data, "revision", String.valueOf(Metrics.REVISION));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
Metrics.encodeDataPair(data, "osname", osname);
|
||||
Metrics.encodeDataPair(data, "osarch", osarch);
|
||||
Metrics.encodeDataPair(data, "osversion", osversion);
|
||||
Metrics.encodeDataPair(data, "cores", Integer.toString(coreCount));
|
||||
Metrics.encodeDataPair(data, "online-mode", Boolean.toString(onlineMode));
|
||||
Metrics.encodeDataPair(data, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
Metrics.encodeDataPair(data, "ping", "true");
|
||||
}
|
||||
|
||||
// Acquire a lock on the graphs, which lets us make the assumption we also lock everything
|
||||
// inside of the graph (e.g plotters)
|
||||
synchronized (this.graphs) {
|
||||
final Iterator<Graph> iter = this.graphs.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
final Graph graph = iter.next();
|
||||
|
||||
for (Plotter plotter : graph.getPlotters()) {
|
||||
// The key name to send to the metrics server
|
||||
// The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top
|
||||
// Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME
|
||||
final String key = String.format("C%s%s%s%s", Metrics.CUSTOM_DATA_SEPARATOR, graph.getName(), Metrics.CUSTOM_DATA_SEPARATOR, plotter.getColumnName());
|
||||
|
||||
// The value to send, which for the foreseeable future is just the string
|
||||
// value of plotter.getValue()
|
||||
final String value = Integer.toString(plotter.getValue());
|
||||
|
||||
// Add it to the http post data :)
|
||||
Metrics.encodeDataPair(data, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(Metrics.BASE_URL + String.format(Metrics.REPORT_URL, Metrics.encode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (this.isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
|
||||
writer.write(data.toString());
|
||||
writer.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR")) {
|
||||
throw new IOException(response); //Throw the exception
|
||||
} else {
|
||||
// Is this the first update this hour?
|
||||
if (response.contains("OK This is your first update this hour")) {
|
||||
synchronized (this.graphs) {
|
||||
final Iterator<Graph> iter = this.graphs.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
final Graph graph = iter.next();
|
||||
|
||||
for (Plotter plotter : graph.getPlotters()) {
|
||||
plotter.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first key/value pair
|
||||
* MUST be included manually, e.g:</p>
|
||||
* <code>
|
||||
* StringBuffer data = new StringBuffer();
|
||||
* data.append(encode("guid")).append('=').append(encode(guid));
|
||||
* encodeDataPair(data, "version", description.getVersion());
|
||||
* </code>
|
||||
*
|
||||
* @param buffer the stringbuilder to append the data pair onto
|
||||
* @param key the key value
|
||||
* @param value the value
|
||||
*/
|
||||
private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException {
|
||||
buffer.append('&').append(Metrics.encode(key)).append('=').append(Metrics.encode(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String encode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom graph on the website
|
||||
*/
|
||||
public static class Graph {
|
||||
|
||||
/**
|
||||
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
|
||||
* rejected
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* The set of plotters that are contained within this graph
|
||||
*/
|
||||
private final Set<Plotter> plotters = new LinkedHashSet<Plotter>();
|
||||
|
||||
private Graph(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graph's name
|
||||
*
|
||||
* @return the Graph's name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a plotter to the graph, which will be used to plot entries
|
||||
*
|
||||
* @param plotter the plotter to add to the graph
|
||||
*/
|
||||
public void addPlotter(final Plotter plotter) {
|
||||
this.plotters.add(plotter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a plotter from the graph
|
||||
*
|
||||
* @param plotter the plotter to remove from the graph
|
||||
*/
|
||||
public void removePlotter(final Plotter plotter) {
|
||||
this.plotters.remove(plotter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
|
||||
*
|
||||
* @return an unmodifiable {@link java.util.Set} of the plotter objects
|
||||
*/
|
||||
public Set<Plotter> getPlotters() {
|
||||
return Collections.unmodifiableSet(this.plotters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (!(object instanceof Graph)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Graph graph = (Graph) object;
|
||||
return graph.name.equals(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
|
||||
*/
|
||||
protected void onOptOut() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to collect custom data for a plugin
|
||||
*/
|
||||
public abstract static class Plotter {
|
||||
|
||||
/**
|
||||
* The plot's name
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Construct a plotter with the default plot name
|
||||
*/
|
||||
public Plotter() {
|
||||
this("Default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a plotter with a specific plot name
|
||||
*
|
||||
* @param name the name of the plotter to use, which will show up on the website
|
||||
*/
|
||||
public Plotter(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value for the plotted point. Since this function defers to an external function it may or may
|
||||
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
|
||||
* from any thread so care should be taken when accessing resources that need to be synchronized.
|
||||
*
|
||||
* @return the current value for the point to be plotted.
|
||||
*/
|
||||
public abstract int getValue();
|
||||
|
||||
/**
|
||||
* Get the column name for the plotted point
|
||||
*
|
||||
* @return the plotted point's column name
|
||||
*/
|
||||
public String getColumnName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the website graphs have been updated
|
||||
*/
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getColumnName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (!(object instanceof Plotter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Plotter plotter = (Plotter) object;
|
||||
return plotter.name.equals(this.name) && plotter.getValue() == this.getValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,115 +1,85 @@
|
||||
package org.spigotmc;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
|
||||
public class RestartCommand extends Command
|
||||
{
|
||||
public class RestartCommand extends Command {
|
||||
|
||||
public RestartCommand(String name)
|
||||
{
|
||||
super( name );
|
||||
public RestartCommand(String name) {
|
||||
super(name);
|
||||
this.description = "Restarts the server";
|
||||
this.usageMessage = "/restart";
|
||||
this.setPermission( "bukkit.command.restart" );
|
||||
this.setPermission("bukkit.command.restart");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args)
|
||||
{
|
||||
if ( this.testPermission( sender ) )
|
||||
{
|
||||
MinecraftServer.getServer().processQueue.add( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
RestartCommand.restart();
|
||||
}
|
||||
} );
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||
if (this.testPermission(sender)) {
|
||||
MinecraftServer.getServer().processQueue.add(RestartCommand::restart);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void restart()
|
||||
{
|
||||
RestartCommand.restart( SpigotConfig.restartScript );
|
||||
public static void restart() {
|
||||
RestartCommand.restart(SpigotConfig.restartScript);
|
||||
}
|
||||
|
||||
private static void restart(final String restartScript)
|
||||
{
|
||||
AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us
|
||||
try
|
||||
{
|
||||
private static void restart(final String restartScript) {
|
||||
AsyncCatcher.enabled = false; // Disable async catcher in case it interferes with us
|
||||
try {
|
||||
// Paper - extract method and cleanup
|
||||
boolean isRestarting = addShutdownHook( restartScript );
|
||||
if ( isRestarting )
|
||||
{
|
||||
System.out.println( "Attempting to restart with " + SpigotConfig.restartScript );
|
||||
} else
|
||||
{
|
||||
System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." );
|
||||
boolean isRestarting = addShutdownHook(restartScript);
|
||||
if (isRestarting) {
|
||||
System.out.println("Attempting to restart with " + SpigotConfig.restartScript);
|
||||
} else {
|
||||
System.out.println("Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server.");
|
||||
}
|
||||
// Stop the watchdog
|
||||
WatchdogThread.doStop();
|
||||
|
||||
shutdownServer( isRestarting );
|
||||
shutdownServer(isRestarting);
|
||||
// Paper end
|
||||
} catch ( Exception ex )
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Paper start - sync copied from above with minor changes, async added
|
||||
private static void shutdownServer(boolean isRestarting)
|
||||
{
|
||||
if ( MinecraftServer.getServer().isSameThread() )
|
||||
{
|
||||
private static void shutdownServer(boolean isRestarting) {
|
||||
if (MinecraftServer.getServer().isSameThread()) {
|
||||
// Kick all players
|
||||
for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) )
|
||||
{
|
||||
p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage, true ), org.bukkit.event.player.PlayerKickEvent.Cause.RESTART_COMMAND); // Paper - kick event reason (cause is never used))
|
||||
for (ServerPlayer p : com.google.common.collect.ImmutableList.copyOf(MinecraftServer.getServer().getPlayerList().players)) {
|
||||
p.connection.disconnect(CraftChatMessage.fromStringOrEmpty(SpigotConfig.restartMessage, true), org.bukkit.event.player.PlayerKickEvent.Cause.RESTART_COMMAND); // Paper - kick event reason (cause is never used)
|
||||
}
|
||||
// Give the socket a chance to send the packets
|
||||
try
|
||||
{
|
||||
Thread.sleep( 100 );
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
|
||||
// Actually shutdown
|
||||
try
|
||||
{
|
||||
try {
|
||||
MinecraftServer.getServer().close(); // calls stop()
|
||||
} catch ( Throwable t )
|
||||
{
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
|
||||
// Actually stop the JVM
|
||||
System.exit( 0 );
|
||||
|
||||
} else
|
||||
{
|
||||
System.exit(0);
|
||||
} else {
|
||||
// Mark the server to shutdown at the end of the tick
|
||||
MinecraftServer.getServer().safeShutdown( false, isRestarting );
|
||||
MinecraftServer.getServer().safeShutdown(false, isRestarting);
|
||||
|
||||
// wait 10 seconds to see if we're actually going to try shutdown
|
||||
try
|
||||
{
|
||||
Thread.sleep( 10000 );
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
// Check if we've actually hit a state where the server is going to safely shutdown
|
||||
// if we have, let the server stop as usual
|
||||
@ -117,63 +87,46 @@ public class RestartCommand extends Command
|
||||
|
||||
// If the server hasn't stopped by now, assume worse case and kill
|
||||
closeSocket();
|
||||
System.exit( 0 );
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
// Paper - Split from moved code
|
||||
private static void closeSocket()
|
||||
{
|
||||
private static void closeSocket() {
|
||||
// Close the socket so we can rebind with the new process
|
||||
MinecraftServer.getServer().getConnection().stop();
|
||||
|
||||
// Give time for it to kick in
|
||||
try
|
||||
{
|
||||
Thread.sleep( 100 );
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
// Paper start - copied from above and modified to return if the hook registered
|
||||
private static boolean addShutdownHook(String restartScript)
|
||||
{
|
||||
String[] split = restartScript.split( " " );
|
||||
if ( split.length > 0 && new File( split[0] ).isFile() )
|
||||
{
|
||||
Thread shutdownHook = new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH);
|
||||
if ( os.contains( "win" ) )
|
||||
{
|
||||
Runtime.getRuntime().exec( "cmd /c start " + restartScript );
|
||||
} else
|
||||
{
|
||||
Runtime.getRuntime().exec( "sh " + restartScript );
|
||||
}
|
||||
} catch ( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
private static boolean addShutdownHook(String restartScript) {
|
||||
String[] split = restartScript.split(" ");
|
||||
if (split.length > 0 && new File(split[0]).isFile()) {
|
||||
Thread shutdownHook = new Thread(() -> {
|
||||
try {
|
||||
String os = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
|
||||
if (os.contains("win")) {
|
||||
Runtime.getRuntime().exec("cmd /c start " + restartScript);
|
||||
} else {
|
||||
Runtime.getRuntime().exec("sh " + restartScript);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
shutdownHook.setDaemon( true );
|
||||
Runtime.getRuntime().addShutdownHook( shutdownHook );
|
||||
shutdownHook.setDaemon(true);
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
package org.spigotmc;
|
||||
|
||||
import java.io.File;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public class SpigotCommand extends Command {
|
||||
|
||||
public SpigotCommand(String name) {
|
||||
@ -21,13 +23,17 @@ public class SpigotCommand extends Command {
|
||||
if (!this.testPermission(sender)) return true;
|
||||
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(ChatColor.RED + "Usage: " + this.usageMessage);
|
||||
sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args[0].equals("reload")) {
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues.");
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server.");
|
||||
Command.broadcastCommandMessage(sender, text().color(NamedTextColor.RED)
|
||||
.append(text("Please note that this command is not supported and may cause issues."))
|
||||
.appendNewline()
|
||||
.append(text("If you encounter any issues please use the /stop command to restart your server."))
|
||||
.build()
|
||||
);
|
||||
|
||||
MinecraftServer console = MinecraftServer.getServer();
|
||||
org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings"));
|
||||
@ -36,7 +42,7 @@ public class SpigotCommand extends Command {
|
||||
}
|
||||
console.server.reloadCount++;
|
||||
|
||||
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Reload complete.");
|
||||
Command.broadcastCommandMessage(sender, text("Reload complete.", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -28,360 +28,289 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class SpigotConfig
|
||||
{
|
||||
public class SpigotConfig {
|
||||
|
||||
private static File CONFIG_FILE;
|
||||
private static final String HEADER = "This is the main configuration file for Spigot.\n"
|
||||
+ "As you can see, there's tons to configure. Some options may impact gameplay, so use\n"
|
||||
+ "with caution, and make sure you know what each option does before configuring.\n"
|
||||
+ "For a reference for any variable inside this file, check out the Spigot wiki at\n"
|
||||
+ "http://www.spigotmc.org/wiki/spigot-configuration/\n"
|
||||
+ "\n"
|
||||
+ "If you need help with the configuration or have any questions related to Spigot,\n"
|
||||
+ "join us at the Discord or drop by our forums and leave a post.\n"
|
||||
+ "\n"
|
||||
+ "Discord: https://www.spigotmc.org/go/discord\n"
|
||||
+ "Forums: http://www.spigotmc.org/\n";
|
||||
private static final String HEADER = """
|
||||
This is the main configuration file for Spigot.
|
||||
As you can see, there's tons to configure. Some options may impact gameplay, so use
|
||||
with caution, and make sure you know what each option does before configuring.
|
||||
For a reference for any variable inside this file, check out the Spigot wiki at
|
||||
http://www.spigotmc.org/wiki/spigot-configuration/
|
||||
|
||||
If you need help with the configuration or have any questions related to Spigot,
|
||||
join us at the Discord or drop by our forums and leave a post.
|
||||
|
||||
Discord: https://www.spigotmc.org/go/discord
|
||||
Forums: http://www.spigotmc.org/
|
||||
""";
|
||||
/*========================================================================*/
|
||||
public static YamlConfiguration config;
|
||||
static int version;
|
||||
static Map<String, Command> commands;
|
||||
/*========================================================================*/
|
||||
private static Metrics metrics;
|
||||
|
||||
public static void init(File configFile)
|
||||
{
|
||||
public static void init(File configFile) {
|
||||
SpigotConfig.CONFIG_FILE = configFile;
|
||||
SpigotConfig.config = new YamlConfiguration();
|
||||
try
|
||||
{
|
||||
SpigotConfig.config.load( SpigotConfig.CONFIG_FILE );
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
} catch ( InvalidConfigurationException ex )
|
||||
{
|
||||
Bukkit.getLogger().log( Level.SEVERE, "Could not load spigot.yml, please correct your syntax errors", ex );
|
||||
throw Throwables.propagate( ex );
|
||||
try {
|
||||
SpigotConfig.config.load(SpigotConfig.CONFIG_FILE);
|
||||
} catch (IOException ignored) {
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Could not load spigot.yml, please correct your syntax errors", ex);
|
||||
throw Throwables.propagate(ex);
|
||||
}
|
||||
|
||||
SpigotConfig.config.options().header( SpigotConfig.HEADER );
|
||||
SpigotConfig.config.options().copyDefaults( true );
|
||||
SpigotConfig.config.options().header(SpigotConfig.HEADER);
|
||||
SpigotConfig.config.options().copyDefaults(true);
|
||||
|
||||
SpigotConfig.commands = new HashMap<String, Command>();
|
||||
SpigotConfig.commands.put( "spigot", new SpigotCommand( "spigot" ) );
|
||||
SpigotConfig.commands = new HashMap<>();
|
||||
SpigotConfig.commands.put("spigot", new SpigotCommand("spigot"));
|
||||
|
||||
SpigotConfig.version = SpigotConfig.getInt( "config-version", 12 );
|
||||
SpigotConfig.set( "config-version", 12 );
|
||||
SpigotConfig.readConfig( SpigotConfig.class, null );
|
||||
SpigotConfig.version = SpigotConfig.getInt("config-version", 12);
|
||||
SpigotConfig.set("config-version", 12);
|
||||
SpigotConfig.readConfig(SpigotConfig.class, null);
|
||||
}
|
||||
|
||||
public static void registerCommands()
|
||||
{
|
||||
for ( Map.Entry<String, Command> entry : SpigotConfig.commands.entrySet() )
|
||||
{
|
||||
MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() );
|
||||
public static void registerCommands() {
|
||||
for (Map.Entry<String, Command> entry : SpigotConfig.commands.entrySet()) {
|
||||
MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Spigot", entry.getValue());
|
||||
}
|
||||
|
||||
/* // Paper - Replace with our own
|
||||
if ( SpigotConfig.metrics == null )
|
||||
{
|
||||
try
|
||||
{
|
||||
SpigotConfig.metrics = new Metrics();
|
||||
SpigotConfig.metrics.start();
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex );
|
||||
}
|
||||
}
|
||||
*/ // Paper end
|
||||
}
|
||||
|
||||
public static void readConfig(Class<?> clazz, Object instance) // Paper - package-private -> public
|
||||
{
|
||||
for ( Method method : clazz.getDeclaredMethods() )
|
||||
{
|
||||
if ( Modifier.isPrivate( method.getModifiers() ) )
|
||||
{
|
||||
if ( method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE )
|
||||
{
|
||||
try
|
||||
{
|
||||
method.setAccessible( true );
|
||||
method.invoke( instance );
|
||||
} catch ( InvocationTargetException ex )
|
||||
{
|
||||
throw Throwables.propagate( ex.getCause() );
|
||||
} catch ( Exception ex )
|
||||
{
|
||||
Bukkit.getLogger().log( Level.SEVERE, "Error invoking " + method, ex );
|
||||
public static void readConfig(Class<?> clazz, Object instance) { // Paper - package-private -> public
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (Modifier.isPrivate(method.getModifiers())) {
|
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
method.invoke(instance);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw Throwables.propagate(ex.getCause());
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SpigotConfig.config.save( SpigotConfig.CONFIG_FILE );
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
Bukkit.getLogger().log( Level.SEVERE, "Could not save " + SpigotConfig.CONFIG_FILE, ex );
|
||||
try {
|
||||
SpigotConfig.config.save(SpigotConfig.CONFIG_FILE);
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Could not save " + SpigotConfig.CONFIG_FILE, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void set(String path, Object val)
|
||||
{
|
||||
SpigotConfig.config.set( path, val );
|
||||
private static void set(String path, Object val) {
|
||||
SpigotConfig.config.set(path, val);
|
||||
}
|
||||
|
||||
private static boolean getBoolean(String path, boolean def)
|
||||
{
|
||||
SpigotConfig.config.addDefault( path, def );
|
||||
return SpigotConfig.config.getBoolean( path, SpigotConfig.config.getBoolean( path ) );
|
||||
private static boolean getBoolean(String path, boolean def) {
|
||||
SpigotConfig.config.addDefault(path, def);
|
||||
return SpigotConfig.config.getBoolean(path, SpigotConfig.config.getBoolean(path));
|
||||
}
|
||||
|
||||
private static int getInt(String path, int def)
|
||||
{
|
||||
SpigotConfig.config.addDefault( path, def );
|
||||
return SpigotConfig.config.getInt( path, SpigotConfig.config.getInt( path ) );
|
||||
private static int getInt(String path, int def) {
|
||||
SpigotConfig.config.addDefault(path, def);
|
||||
return SpigotConfig.config.getInt(path, SpigotConfig.config.getInt(path));
|
||||
}
|
||||
|
||||
private static <T> List getList(String path, T def)
|
||||
{
|
||||
SpigotConfig.config.addDefault( path, def );
|
||||
return (List<T>) SpigotConfig.config.getList( path, SpigotConfig.config.getList( path ) );
|
||||
private static <T> List getList(String path, T def) {
|
||||
SpigotConfig.config.addDefault(path, def);
|
||||
return (List<T>) SpigotConfig.config.getList(path, SpigotConfig.config.getList(path));
|
||||
}
|
||||
|
||||
private static String getString(String path, String def)
|
||||
{
|
||||
SpigotConfig.config.addDefault( path, def );
|
||||
return SpigotConfig.config.getString( path, SpigotConfig.config.getString( path ) );
|
||||
private static String getString(String path, String def) {
|
||||
SpigotConfig.config.addDefault(path, def);
|
||||
return SpigotConfig.config.getString(path, SpigotConfig.config.getString(path));
|
||||
}
|
||||
|
||||
private static double getDouble(String path, double def)
|
||||
{
|
||||
SpigotConfig.config.addDefault( path, def );
|
||||
return SpigotConfig.config.getDouble( path, SpigotConfig.config.getDouble( path ) );
|
||||
private static double getDouble(String path, double def) {
|
||||
SpigotConfig.config.addDefault(path, def);
|
||||
return SpigotConfig.config.getDouble(path, SpigotConfig.config.getDouble(path));
|
||||
}
|
||||
|
||||
public static boolean logCommands;
|
||||
private static void logCommands()
|
||||
{
|
||||
SpigotConfig.logCommands = SpigotConfig.getBoolean( "commands.log", true );
|
||||
private static void logCommands() {
|
||||
SpigotConfig.logCommands = SpigotConfig.getBoolean("commands.log", true);
|
||||
}
|
||||
|
||||
public static int tabComplete;
|
||||
public static boolean sendNamespaced;
|
||||
private static void tabComplete()
|
||||
{
|
||||
if ( SpigotConfig.version < 6 )
|
||||
{
|
||||
boolean oldValue = SpigotConfig.getBoolean( "commands.tab-complete", true );
|
||||
if ( oldValue )
|
||||
{
|
||||
SpigotConfig.set( "commands.tab-complete", 0 );
|
||||
} else
|
||||
{
|
||||
SpigotConfig.set( "commands.tab-complete", -1 );
|
||||
private static void tabComplete() {
|
||||
if (SpigotConfig.version < 6) {
|
||||
boolean oldValue = SpigotConfig.getBoolean("commands.tab-complete", true);
|
||||
if (oldValue) {
|
||||
SpigotConfig.set("commands.tab-complete", 0);
|
||||
} else {
|
||||
SpigotConfig.set("commands.tab-complete", -1);
|
||||
}
|
||||
}
|
||||
SpigotConfig.tabComplete = SpigotConfig.getInt( "commands.tab-complete", 0 );
|
||||
SpigotConfig.sendNamespaced = SpigotConfig.getBoolean( "commands.send-namespaced", true );
|
||||
SpigotConfig.tabComplete = SpigotConfig.getInt("commands.tab-complete", 0);
|
||||
SpigotConfig.sendNamespaced = SpigotConfig.getBoolean("commands.send-namespaced", true);
|
||||
}
|
||||
|
||||
public static String whitelistMessage;
|
||||
public static String unknownCommandMessage;
|
||||
public static String serverFullMessage;
|
||||
public static String outdatedClientMessage = "Outdated client! Please use {0}";
|
||||
public static String outdatedServerMessage = "Outdated server! I\'m still on {0}";
|
||||
private static String transform(String s)
|
||||
{
|
||||
return ChatColor.translateAlternateColorCodes( '&', s ).replaceAll( "\\\\n", "\n" );
|
||||
public static String outdatedServerMessage = "Outdated server! I'm still on {0}";
|
||||
|
||||
private static String transform(String s) {
|
||||
return ChatColor.translateAlternateColorCodes('&', s).replaceAll("\\\\n", "\n");
|
||||
}
|
||||
private static void messages()
|
||||
{
|
||||
if (SpigotConfig.version < 8)
|
||||
{
|
||||
SpigotConfig.set( "messages.outdated-client", SpigotConfig.outdatedClientMessage );
|
||||
SpigotConfig.set( "messages.outdated-server", SpigotConfig.outdatedServerMessage );
|
||||
|
||||
private static void messages() {
|
||||
if (SpigotConfig.version < 8) {
|
||||
SpigotConfig.set("messages.outdated-client", SpigotConfig.outdatedClientMessage);
|
||||
SpigotConfig.set("messages.outdated-server", SpigotConfig.outdatedServerMessage);
|
||||
}
|
||||
|
||||
SpigotConfig.whitelistMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.whitelist", "You are not whitelisted on this server!" ) );
|
||||
SpigotConfig.unknownCommandMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.unknown-command", "Unknown command. Type \"/help\" for help." ) );
|
||||
SpigotConfig.serverFullMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.server-full", "The server is full!" ) );
|
||||
SpigotConfig.outdatedClientMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.outdated-client", SpigotConfig.outdatedClientMessage ) );
|
||||
SpigotConfig.outdatedServerMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.outdated-server", SpigotConfig.outdatedServerMessage ) );
|
||||
SpigotConfig.whitelistMessage = SpigotConfig.transform(SpigotConfig.getString("messages.whitelist", "You are not whitelisted on this server!"));
|
||||
SpigotConfig.unknownCommandMessage = SpigotConfig.transform(SpigotConfig.getString("messages.unknown-command", "Unknown command. Type \"/help\" for help."));
|
||||
SpigotConfig.serverFullMessage = SpigotConfig.transform(SpigotConfig.getString("messages.server-full", "The server is full!"));
|
||||
SpigotConfig.outdatedClientMessage = SpigotConfig.transform(SpigotConfig.getString("messages.outdated-client", SpigotConfig.outdatedClientMessage));
|
||||
SpigotConfig.outdatedServerMessage = SpigotConfig.transform(SpigotConfig.getString("messages.outdated-server", SpigotConfig.outdatedServerMessage));
|
||||
}
|
||||
|
||||
public static int timeoutTime = 60;
|
||||
public static boolean restartOnCrash = true;
|
||||
public static String restartScript = "./start.sh";
|
||||
public static String restartMessage;
|
||||
private static void watchdog()
|
||||
{
|
||||
SpigotConfig.timeoutTime = SpigotConfig.getInt( "settings.timeout-time", SpigotConfig.timeoutTime );
|
||||
SpigotConfig.restartOnCrash = SpigotConfig.getBoolean( "settings.restart-on-crash", SpigotConfig.restartOnCrash );
|
||||
SpigotConfig.restartScript = SpigotConfig.getString( "settings.restart-script", SpigotConfig.restartScript );
|
||||
SpigotConfig.restartMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.restart", "Server is restarting" ) );
|
||||
SpigotConfig.commands.put( "restart", new RestartCommand( "restart" ) );
|
||||
// WatchdogThread.doStart( SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); // Paper - moved to after paper config initialization
|
||||
private static void watchdog() {
|
||||
SpigotConfig.timeoutTime = SpigotConfig.getInt("settings.timeout-time", SpigotConfig.timeoutTime);
|
||||
SpigotConfig.restartOnCrash = SpigotConfig.getBoolean("settings.restart-on-crash", SpigotConfig.restartOnCrash);
|
||||
SpigotConfig.restartScript = SpigotConfig.getString("settings.restart-script", SpigotConfig.restartScript);
|
||||
SpigotConfig.restartMessage = SpigotConfig.transform(SpigotConfig.getString("messages.restart", "Server is restarting"));
|
||||
SpigotConfig.commands.put("restart", new RestartCommand("restart"));
|
||||
}
|
||||
|
||||
public static boolean bungee;
|
||||
private static void bungee() {
|
||||
if ( SpigotConfig.version < 4 )
|
||||
{
|
||||
SpigotConfig.set( "settings.bungeecord", false );
|
||||
System.out.println( "Outdated config, disabling BungeeCord support!" );
|
||||
if (SpigotConfig.version < 4) {
|
||||
SpigotConfig.set("settings.bungeecord", false);
|
||||
System.out.println("Outdated config, disabling BungeeCord support!");
|
||||
}
|
||||
SpigotConfig.bungee = SpigotConfig.getBoolean( "settings.bungeecord", false );
|
||||
SpigotConfig.bungee = SpigotConfig.getBoolean("settings.bungeecord", false);
|
||||
}
|
||||
|
||||
private static void nettyThreads()
|
||||
{
|
||||
int count = SpigotConfig.getInt( "settings.netty-threads", 4 );
|
||||
System.setProperty( "io.netty.eventLoopThreads", Integer.toString( count ) );
|
||||
Bukkit.getLogger().log( Level.INFO, "Using {0} threads for Netty based IO", count );
|
||||
private static void nettyThreads() {
|
||||
int count = SpigotConfig.getInt("settings.netty-threads", 4);
|
||||
System.setProperty("io.netty.eventLoopThreads", Integer.toString(count));
|
||||
Bukkit.getLogger().log(Level.INFO, "Using {0} threads for Netty based IO", count);
|
||||
}
|
||||
|
||||
public static boolean disableStatSaving;
|
||||
public static Map<ResourceLocation, Integer> forcedStats = new HashMap<>();
|
||||
private static void stats()
|
||||
{
|
||||
SpigotConfig.disableStatSaving = SpigotConfig.getBoolean( "stats.disable-saving", false );
|
||||
|
||||
if ( !SpigotConfig.config.contains( "stats.forced-stats" ) ) {
|
||||
SpigotConfig.config.createSection( "stats.forced-stats" );
|
||||
private static void stats() {
|
||||
SpigotConfig.disableStatSaving = SpigotConfig.getBoolean("stats.disable-saving", false);
|
||||
|
||||
if (!SpigotConfig.config.contains("stats.forced-stats")) {
|
||||
SpigotConfig.config.createSection("stats.forced-stats");
|
||||
}
|
||||
|
||||
ConfigurationSection section = SpigotConfig.config.getConfigurationSection( "stats.forced-stats" );
|
||||
for ( String name : section.getKeys( true ) )
|
||||
{
|
||||
if ( section.isInt( name ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
ResourceLocation key = ResourceLocation.parse( name );
|
||||
if ( BuiltInRegistries.CUSTOM_STAT.get( key ) == null )
|
||||
{
|
||||
ConfigurationSection section = SpigotConfig.config.getConfigurationSection("stats.forced-stats");
|
||||
for (String name : section.getKeys(true)) {
|
||||
if (section.isInt(name)) {
|
||||
try {
|
||||
ResourceLocation key = ResourceLocation.parse(name);
|
||||
if (BuiltInRegistries.CUSTOM_STAT.get(key) == null) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Ignoring non existent stats.forced-stats " + name);
|
||||
continue;
|
||||
}
|
||||
SpigotConfig.forcedStats.put( key, section.getInt( name ) );
|
||||
} catch (Exception ex)
|
||||
{
|
||||
SpigotConfig.forcedStats.put(key, section.getInt(name));
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Ignoring invalid stats.forced-stats " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void tpsCommand()
|
||||
{
|
||||
SpigotConfig.commands.put( "tps", new TicksPerSecondCommand( "tps" ) );
|
||||
private static void tpsCommand() {
|
||||
SpigotConfig.commands.put("tps", new TicksPerSecondCommand("tps"));
|
||||
}
|
||||
|
||||
public static int playerSample;
|
||||
private static void playerSample()
|
||||
{
|
||||
SpigotConfig.playerSample = Math.max( SpigotConfig.getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts
|
||||
Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger
|
||||
private static void playerSample() {
|
||||
SpigotConfig.playerSample = Math.max(SpigotConfig.getInt("settings.sample-count", 12), 0); // Paper - Avoid negative counts
|
||||
Bukkit.getLogger().log(Level.INFO, "Server Ping Player Sample Count: {0}", playerSample); // Paper - Use logger
|
||||
}
|
||||
|
||||
public static int playerShuffle;
|
||||
private static void playerShuffle()
|
||||
{
|
||||
SpigotConfig.playerShuffle = SpigotConfig.getInt( "settings.player-shuffle", 0 );
|
||||
private static void playerShuffle() {
|
||||
SpigotConfig.playerShuffle = SpigotConfig.getInt("settings.player-shuffle", 0);
|
||||
}
|
||||
|
||||
public static List<String> spamExclusions;
|
||||
private static void spamExclusions()
|
||||
{
|
||||
SpigotConfig.spamExclusions = SpigotConfig.getList( "commands.spam-exclusions", Arrays.asList( new String[]
|
||||
{
|
||||
"/skill"
|
||||
} ) );
|
||||
private static void spamExclusions() {
|
||||
SpigotConfig.spamExclusions = SpigotConfig.getList("commands.spam-exclusions", List.of("/skill"));
|
||||
}
|
||||
|
||||
public static boolean silentCommandBlocks;
|
||||
private static void silentCommandBlocks()
|
||||
{
|
||||
SpigotConfig.silentCommandBlocks = SpigotConfig.getBoolean( "commands.silent-commandblock-console", false );
|
||||
private static void silentCommandBlocks() {
|
||||
SpigotConfig.silentCommandBlocks = SpigotConfig.getBoolean("commands.silent-commandblock-console", false);
|
||||
}
|
||||
|
||||
public static Set<String> replaceCommands;
|
||||
private static void replaceCommands()
|
||||
{
|
||||
if ( SpigotConfig.config.contains( "replace-commands" ) )
|
||||
{
|
||||
SpigotConfig.set( "commands.replace-commands", SpigotConfig.config.getStringList( "replace-commands" ) );
|
||||
SpigotConfig.config.set( "replace-commands", null );
|
||||
private static void replaceCommands() {
|
||||
if (SpigotConfig.config.contains("replace-commands")) {
|
||||
SpigotConfig.set("commands.replace-commands", SpigotConfig.config.getStringList("replace-commands"));
|
||||
SpigotConfig.config.set("replace-commands", null);
|
||||
}
|
||||
SpigotConfig.replaceCommands = new HashSet<String>( (List<String>) SpigotConfig.getList( "commands.replace-commands",
|
||||
Arrays.asList( "setblock", "summon", "testforblock", "tellraw" ) ) );
|
||||
SpigotConfig.replaceCommands = new HashSet<>(SpigotConfig.getList("commands.replace-commands",
|
||||
Arrays.asList("setblock", "summon", "testforblock", "tellraw")));
|
||||
}
|
||||
|
||||
public static int userCacheCap;
|
||||
private static void userCacheCap()
|
||||
{
|
||||
SpigotConfig.userCacheCap = SpigotConfig.getInt( "settings.user-cache-size", 1000 );
|
||||
private static void userCacheCap() {
|
||||
SpigotConfig.userCacheCap = SpigotConfig.getInt("settings.user-cache-size", 1000);
|
||||
}
|
||||
|
||||
public static boolean saveUserCacheOnStopOnly;
|
||||
private static void saveUserCacheOnStopOnly()
|
||||
{
|
||||
SpigotConfig.saveUserCacheOnStopOnly = SpigotConfig.getBoolean( "settings.save-user-cache-on-stop-only", false );
|
||||
private static void saveUserCacheOnStopOnly() {
|
||||
SpigotConfig.saveUserCacheOnStopOnly = SpigotConfig.getBoolean("settings.save-user-cache-on-stop-only", false);
|
||||
}
|
||||
|
||||
public static double movedWronglyThreshold;
|
||||
private static void movedWronglyThreshold()
|
||||
{
|
||||
SpigotConfig.movedWronglyThreshold = SpigotConfig.getDouble( "settings.moved-wrongly-threshold", 0.0625D );
|
||||
private static void movedWronglyThreshold() {
|
||||
SpigotConfig.movedWronglyThreshold = SpigotConfig.getDouble("settings.moved-wrongly-threshold", 0.0625D);
|
||||
}
|
||||
|
||||
public static double movedTooQuicklyMultiplier;
|
||||
private static void movedTooQuicklyMultiplier()
|
||||
{
|
||||
SpigotConfig.movedTooQuicklyMultiplier = SpigotConfig.getDouble( "settings.moved-too-quickly-multiplier", 10.0D );
|
||||
private static void movedTooQuicklyMultiplier() {
|
||||
SpigotConfig.movedTooQuicklyMultiplier = SpigotConfig.getDouble("settings.moved-too-quickly-multiplier", 10.0D);
|
||||
}
|
||||
|
||||
public static double maxAbsorption = 2048;
|
||||
public static double maxHealth = 2048;
|
||||
public static double movementSpeed = 2048;
|
||||
public static double maxHealth = 1024;
|
||||
public static double movementSpeed = 1024;
|
||||
public static double attackDamage = 2048;
|
||||
private static void attributeMaxes()
|
||||
{
|
||||
SpigotConfig.maxAbsorption = SpigotConfig.getDouble( "settings.attribute.maxAbsorption.max", SpigotConfig.maxAbsorption );
|
||||
( (RangedAttribute) Attributes.MAX_ABSORPTION.value() ).maxValue = SpigotConfig.maxAbsorption;
|
||||
SpigotConfig.maxHealth = SpigotConfig.getDouble( "settings.attribute.maxHealth.max", SpigotConfig.maxHealth );
|
||||
( (RangedAttribute) Attributes.MAX_HEALTH.value() ).maxValue = SpigotConfig.maxHealth;
|
||||
SpigotConfig.movementSpeed = SpigotConfig.getDouble( "settings.attribute.movementSpeed.max", SpigotConfig.movementSpeed );
|
||||
( (RangedAttribute) Attributes.MOVEMENT_SPEED.value() ).maxValue = SpigotConfig.movementSpeed;
|
||||
SpigotConfig.attackDamage = SpigotConfig.getDouble( "settings.attribute.attackDamage.max", SpigotConfig.attackDamage );
|
||||
( (RangedAttribute) Attributes.ATTACK_DAMAGE.value() ).maxValue = SpigotConfig.attackDamage;
|
||||
private static void attributeMaxes() {
|
||||
SpigotConfig.maxAbsorption = SpigotConfig.getDouble("settings.attribute.maxAbsorption.max", SpigotConfig.maxAbsorption);
|
||||
((RangedAttribute) Attributes.MAX_ABSORPTION.value()).maxValue = SpigotConfig.maxAbsorption;
|
||||
SpigotConfig.maxHealth = SpigotConfig.getDouble("settings.attribute.maxHealth.max", SpigotConfig.maxHealth);
|
||||
((RangedAttribute) Attributes.MAX_HEALTH.value()).maxValue = SpigotConfig.maxHealth;
|
||||
SpigotConfig.movementSpeed = SpigotConfig.getDouble("settings.attribute.movementSpeed.max", SpigotConfig.movementSpeed);
|
||||
((RangedAttribute) Attributes.MOVEMENT_SPEED.value()).maxValue = SpigotConfig.movementSpeed;
|
||||
SpigotConfig.attackDamage = SpigotConfig.getDouble("settings.attribute.attackDamage.max", SpigotConfig.attackDamage);
|
||||
((RangedAttribute) Attributes.ATTACK_DAMAGE.value()).maxValue = SpigotConfig.attackDamage;
|
||||
}
|
||||
|
||||
public static boolean debug;
|
||||
private static void debug()
|
||||
{
|
||||
SpigotConfig.debug = SpigotConfig.getBoolean( "settings.debug", false );
|
||||
private static void debug() {
|
||||
SpigotConfig.debug = SpigotConfig.getBoolean("settings.debug", false);
|
||||
|
||||
if ( SpigotConfig.debug && !LogManager.getRootLogger().isTraceEnabled() )
|
||||
{
|
||||
if (SpigotConfig.debug && !LogManager.getRootLogger().isTraceEnabled()) {
|
||||
// Enable debug logging
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext( false );
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration conf = ctx.getConfiguration();
|
||||
conf.getLoggerConfig( LogManager.ROOT_LOGGER_NAME ).setLevel( org.apache.logging.log4j.Level.ALL );
|
||||
ctx.updateLoggers( conf );
|
||||
conf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(org.apache.logging.log4j.Level.ALL);
|
||||
ctx.updateLoggers(conf);
|
||||
}
|
||||
|
||||
if ( LogManager.getRootLogger().isTraceEnabled() )
|
||||
{
|
||||
Bukkit.getLogger().info( "Debug logging is enabled" );
|
||||
} else
|
||||
{
|
||||
// Bukkit.getLogger().info( "Debug logging is disabled" ); // Paper - Don't log if debug logging isn't enabled.
|
||||
if (LogManager.getRootLogger().isTraceEnabled()) {
|
||||
Bukkit.getLogger().info("Debug logging is enabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,7 +318,7 @@ public class SpigotConfig
|
||||
public static List<String> disabledAdvancements;
|
||||
private static void disabledAdvancements() {
|
||||
SpigotConfig.disableAdvancementSaving = SpigotConfig.getBoolean("advancements.disable-saving", false);
|
||||
SpigotConfig.disabledAdvancements = SpigotConfig.getList("advancements.disabled", Arrays.asList(new String[]{"minecraft:story/disabled"}));
|
||||
SpigotConfig.disabledAdvancements = SpigotConfig.getList("advancements.disabled", List.of("minecraft:story/disabled"));
|
||||
}
|
||||
|
||||
public static boolean logVillagerDeaths;
|
||||
|
@ -4,86 +4,73 @@ import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class SpigotWorldConfig
|
||||
{
|
||||
public class SpigotWorldConfig {
|
||||
|
||||
private final String worldName;
|
||||
private final YamlConfiguration config;
|
||||
private boolean verbose;
|
||||
|
||||
public SpigotWorldConfig(String worldName)
|
||||
{
|
||||
public SpigotWorldConfig(String worldName) {
|
||||
this.worldName = worldName;
|
||||
this.config = SpigotConfig.config;
|
||||
this.init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.verbose = this.getBoolean( "verbose", false ); // Paper
|
||||
public void init() {
|
||||
this.verbose = this.getBoolean("verbose", false); // Paper
|
||||
|
||||
this.log( "-------- World Settings For [" + this.worldName + "] --------" );
|
||||
SpigotConfig.readConfig( SpigotWorldConfig.class, this );
|
||||
this.log("-------- World Settings For [" + this.worldName + "] --------");
|
||||
SpigotConfig.readConfig(SpigotWorldConfig.class, this);
|
||||
}
|
||||
|
||||
private void log(String s)
|
||||
{
|
||||
if ( this.verbose )
|
||||
{
|
||||
Bukkit.getLogger().info( s );
|
||||
private void log(String s) {
|
||||
if (this.verbose) {
|
||||
Bukkit.getLogger().info(s);
|
||||
}
|
||||
}
|
||||
|
||||
private void set(String path, Object val)
|
||||
{
|
||||
this.config.set( "world-settings.default." + path, val );
|
||||
private void set(String path, Object val) {
|
||||
this.config.set("world-settings.default." + path, val);
|
||||
}
|
||||
|
||||
public boolean getBoolean(String path, boolean def)
|
||||
{
|
||||
this.config.addDefault( "world-settings.default." + path, def );
|
||||
return this.config.getBoolean( "world-settings." + this.worldName + "." + path, this.config.getBoolean( "world-settings.default." + path ) );
|
||||
public boolean getBoolean(String path, boolean def) {
|
||||
this.config.addDefault("world-settings.default." + path, def);
|
||||
return this.config.getBoolean("world-settings." + this.worldName + "." + path, this.config.getBoolean("world-settings.default." + path));
|
||||
}
|
||||
|
||||
public double getDouble(String path, double def)
|
||||
{
|
||||
this.config.addDefault( "world-settings.default." + path, def );
|
||||
return this.config.getDouble( "world-settings." + this.worldName + "." + path, this.config.getDouble( "world-settings.default." + path ) );
|
||||
public double getDouble(String path, double def) {
|
||||
this.config.addDefault("world-settings.default." + path, def);
|
||||
return this.config.getDouble("world-settings." + this.worldName + "." + path, this.config.getDouble("world-settings.default." + path));
|
||||
}
|
||||
|
||||
public int getInt(String path)
|
||||
{
|
||||
return this.config.getInt( "world-settings." + this.worldName + "." + path );
|
||||
public int getInt(String path) {
|
||||
return this.config.getInt("world-settings." + this.worldName + "." + path);
|
||||
}
|
||||
|
||||
public int getInt(String path, int def)
|
||||
{
|
||||
public int getInt(String path, int def) {
|
||||
// Paper start - get int without setting default
|
||||
return this.getInt(path, def, true);
|
||||
}
|
||||
public int getInt(String path, int def, boolean setDef)
|
||||
{
|
||||
if (setDef) this.config.addDefault( "world-settings.default." + path, def );
|
||||
return this.config.getInt( "world-settings." + this.worldName + "." + path, this.config.getInt( "world-settings.default." + path, def ) );
|
||||
|
||||
public int getInt(String path, int def, boolean setDef) {
|
||||
if (setDef) this.config.addDefault("world-settings.default." + path, def);
|
||||
return this.config.getInt("world-settings." + this.worldName + "." + path, this.config.getInt("world-settings.default." + path, def));
|
||||
// Paper end
|
||||
}
|
||||
|
||||
public <T> List getList(String path, T def)
|
||||
{
|
||||
this.config.addDefault( "world-settings.default." + path, def );
|
||||
return (List<T>) this.config.getList( "world-settings." + this.worldName + "." + path, this.config.getList( "world-settings.default." + path ) );
|
||||
public <T> List getList(String path, T def) {
|
||||
this.config.addDefault("world-settings.default." + path, def);
|
||||
return (List<T>) this.config.getList("world-settings." + this.worldName + "." + path, this.config.getList("world-settings.default." + path));
|
||||
}
|
||||
|
||||
public String getString(String path, String def)
|
||||
{
|
||||
this.config.addDefault( "world-settings.default." + path, def );
|
||||
return this.config.getString( "world-settings." + this.worldName + "." + path, this.config.getString( "world-settings.default." + path ) );
|
||||
public String getString(String path, String def) {
|
||||
this.config.addDefault("world-settings.default." + path, def);
|
||||
return this.config.getString("world-settings." + this.worldName + "." + path, this.config.getString("world-settings.default." + path));
|
||||
}
|
||||
|
||||
private Object get(String path, Object def)
|
||||
{
|
||||
this.config.addDefault( "world-settings.default." + path, def );
|
||||
return this.config.get( "world-settings." + this.worldName + "." + path, this.config.get( "world-settings.default." + path ) );
|
||||
private Object get(String path, Object def) {
|
||||
this.config.addDefault("world-settings.default." + path, def);
|
||||
return this.config.get("world-settings." + this.worldName + "." + path, this.config.get("world-settings.default." + path));
|
||||
}
|
||||
|
||||
// Crop growth rates
|
||||
@ -109,102 +96,92 @@ public class SpigotWorldConfig
|
||||
public int caveVinesModifier;
|
||||
public int glowBerryModifier; // Paper
|
||||
public int pitcherPlantModifier; // Paper
|
||||
private int getAndValidateGrowth(String crop)
|
||||
{
|
||||
int modifier = this.getInt( "growth." + crop.toLowerCase(java.util.Locale.ENGLISH) + "-modifier", 100 );
|
||||
if ( modifier == 0 )
|
||||
{
|
||||
this.log( "Cannot set " + crop + " growth to zero, defaulting to 100" );
|
||||
|
||||
private int getAndValidateGrowth(String crop) {
|
||||
int modifier = this.getInt("growth." + crop.toLowerCase(java.util.Locale.ENGLISH) + "-modifier", 100);
|
||||
if (modifier == 0) {
|
||||
this.log("Cannot set " + crop + " growth to zero, defaulting to 100");
|
||||
modifier = 100;
|
||||
}
|
||||
this.log( crop + " Growth Modifier: " + modifier + "%" );
|
||||
this.log(crop + " Growth Modifier: " + modifier + "%");
|
||||
|
||||
return modifier;
|
||||
}
|
||||
private void growthModifiers()
|
||||
{
|
||||
this.cactusModifier = this.getAndValidateGrowth( "Cactus" );
|
||||
this.caneModifier = this.getAndValidateGrowth( "Cane" );
|
||||
this.melonModifier = this.getAndValidateGrowth( "Melon" );
|
||||
this.mushroomModifier = this.getAndValidateGrowth( "Mushroom" );
|
||||
this.pumpkinModifier = this.getAndValidateGrowth( "Pumpkin" );
|
||||
this.saplingModifier = this.getAndValidateGrowth( "Sapling" );
|
||||
this.beetrootModifier = this.getAndValidateGrowth( "Beetroot" );
|
||||
this.carrotModifier = this.getAndValidateGrowth( "Carrot" );
|
||||
this.potatoModifier = this.getAndValidateGrowth( "Potato" );
|
||||
|
||||
private void growthModifiers() {
|
||||
this.cactusModifier = this.getAndValidateGrowth("Cactus");
|
||||
this.caneModifier = this.getAndValidateGrowth("Cane");
|
||||
this.melonModifier = this.getAndValidateGrowth("Melon");
|
||||
this.mushroomModifier = this.getAndValidateGrowth("Mushroom");
|
||||
this.pumpkinModifier = this.getAndValidateGrowth("Pumpkin");
|
||||
this.saplingModifier = this.getAndValidateGrowth("Sapling");
|
||||
this.beetrootModifier = this.getAndValidateGrowth("Beetroot");
|
||||
this.carrotModifier = this.getAndValidateGrowth("Carrot");
|
||||
this.potatoModifier = this.getAndValidateGrowth("Potato");
|
||||
this.torchFlowerModifier = this.getAndValidateGrowth("TorchFlower"); // Paper
|
||||
this.wheatModifier = this.getAndValidateGrowth( "Wheat" );
|
||||
this.wartModifier = this.getAndValidateGrowth( "NetherWart" );
|
||||
this.vineModifier = this.getAndValidateGrowth( "Vine" );
|
||||
this.cocoaModifier = this.getAndValidateGrowth( "Cocoa" );
|
||||
this.bambooModifier = this.getAndValidateGrowth( "Bamboo" );
|
||||
this.sweetBerryModifier = this.getAndValidateGrowth( "SweetBerry" );
|
||||
this.kelpModifier = this.getAndValidateGrowth( "Kelp" );
|
||||
this.twistingVinesModifier = this.getAndValidateGrowth( "TwistingVines" );
|
||||
this.weepingVinesModifier = this.getAndValidateGrowth( "WeepingVines" );
|
||||
this.caveVinesModifier = this.getAndValidateGrowth( "CaveVines" );
|
||||
this.wheatModifier = this.getAndValidateGrowth("Wheat");
|
||||
this.wartModifier = this.getAndValidateGrowth("NetherWart");
|
||||
this.vineModifier = this.getAndValidateGrowth("Vine");
|
||||
this.cocoaModifier = this.getAndValidateGrowth("Cocoa");
|
||||
this.bambooModifier = this.getAndValidateGrowth("Bamboo");
|
||||
this.sweetBerryModifier = this.getAndValidateGrowth("SweetBerry");
|
||||
this.kelpModifier = this.getAndValidateGrowth("Kelp");
|
||||
this.twistingVinesModifier = this.getAndValidateGrowth("TwistingVines");
|
||||
this.weepingVinesModifier = this.getAndValidateGrowth("WeepingVines");
|
||||
this.caveVinesModifier = this.getAndValidateGrowth("CaveVines");
|
||||
this.glowBerryModifier = this.getAndValidateGrowth("GlowBerry"); // Paper
|
||||
this.pitcherPlantModifier = this.getAndValidateGrowth("PitcherPlant"); // Paper
|
||||
}
|
||||
|
||||
public double itemMerge;
|
||||
private void itemMerge()
|
||||
{
|
||||
this.itemMerge = this.getDouble("merge-radius.item", 0.5 );
|
||||
this.log( "Item Merge Radius: " + this.itemMerge );
|
||||
private void itemMerge() {
|
||||
this.itemMerge = this.getDouble("merge-radius.item", 0.5);
|
||||
this.log("Item Merge Radius: " + this.itemMerge);
|
||||
}
|
||||
|
||||
public double expMerge;
|
||||
private void expMerge()
|
||||
{
|
||||
this.expMerge = this.getDouble("merge-radius.exp", -1 );
|
||||
this.log( "Experience Merge Radius: " + this.expMerge );
|
||||
private void expMerge() {
|
||||
this.expMerge = this.getDouble("merge-radius.exp", -1);
|
||||
this.log("Experience Merge Radius: " + this.expMerge);
|
||||
}
|
||||
|
||||
public int viewDistance;
|
||||
private void viewDistance()
|
||||
{
|
||||
if ( SpigotConfig.version < 12 )
|
||||
{
|
||||
this.set( "view-distance", null );
|
||||
private void viewDistance() {
|
||||
if (SpigotConfig.version < 12) {
|
||||
this.set("view-distance", null);
|
||||
}
|
||||
|
||||
Object viewDistanceObject = this.get( "view-distance", "default" );
|
||||
this.viewDistance = ( viewDistanceObject ) instanceof Number ? ( (Number) viewDistanceObject ).intValue() : -1;
|
||||
if ( this.viewDistance <= 0 )
|
||||
{
|
||||
Object viewDistanceObject = this.get("view-distance", "default");
|
||||
this.viewDistance = (viewDistanceObject) instanceof Number ? ((Number) viewDistanceObject).intValue() : -1;
|
||||
if (this.viewDistance <= 0) {
|
||||
this.viewDistance = Bukkit.getViewDistance();
|
||||
}
|
||||
|
||||
this.viewDistance = Math.max( Math.min( this.viewDistance, 32 ), 3 );
|
||||
this.log( "View Distance: " + this.viewDistance );
|
||||
this.viewDistance = Math.max(Math.min(this.viewDistance, 32), 3);
|
||||
this.log("View Distance: " + this.viewDistance);
|
||||
}
|
||||
|
||||
public int simulationDistance;
|
||||
private void simulationDistance()
|
||||
{
|
||||
Object simulationDistanceObject = this.get( "simulation-distance", "default" );
|
||||
this.simulationDistance = ( simulationDistanceObject ) instanceof Number ? ( (Number) simulationDistanceObject ).intValue() : -1;
|
||||
if ( this.simulationDistance <= 0 )
|
||||
{
|
||||
private void simulationDistance() {
|
||||
Object simulationDistanceObject = this.get("simulation-distance", "default");
|
||||
this.simulationDistance = (simulationDistanceObject) instanceof Number ? ((Number) simulationDistanceObject).intValue() : -1;
|
||||
if (this.simulationDistance <= 0) {
|
||||
this.simulationDistance = Bukkit.getSimulationDistance();
|
||||
}
|
||||
|
||||
this.log( "Simulation Distance: " + this.simulationDistance );
|
||||
this.log("Simulation Distance: " + this.simulationDistance);
|
||||
}
|
||||
|
||||
public byte mobSpawnRange;
|
||||
private void mobSpawnRange()
|
||||
{
|
||||
this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla
|
||||
this.log( "Mob Spawn Range: " + this.mobSpawnRange );
|
||||
private void mobSpawnRange() {
|
||||
this.mobSpawnRange = (byte) getInt("mob-spawn-range", 8); // Paper - Vanilla
|
||||
this.log("Mob Spawn Range: " + this.mobSpawnRange);
|
||||
}
|
||||
|
||||
public int itemDespawnRate;
|
||||
private void itemDespawnRate()
|
||||
{
|
||||
this.itemDespawnRate = this.getInt( "item-despawn-rate", 6000 );
|
||||
this.log( "Item Despawn Rate: " + this.itemDespawnRate );
|
||||
private void itemDespawnRate() {
|
||||
this.itemDespawnRate = this.getInt("item-despawn-rate", 6000);
|
||||
this.log("Item Despawn Rate: " + this.itemDespawnRate);
|
||||
}
|
||||
|
||||
public int animalActivationRange = 32;
|
||||
@ -216,34 +193,34 @@ public class SpigotWorldConfig
|
||||
public int waterActivationRange = 16;
|
||||
public int villagerActivationRange = 32;
|
||||
public int wakeUpInactiveAnimals = 4;
|
||||
public int wakeUpInactiveAnimalsEvery = 60*20;
|
||||
public int wakeUpInactiveAnimalsFor = 5*20;
|
||||
public int wakeUpInactiveAnimalsEvery = 60 * 20;
|
||||
public int wakeUpInactiveAnimalsFor = 5 * 20;
|
||||
public int wakeUpInactiveMonsters = 8;
|
||||
public int wakeUpInactiveMonstersEvery = 20*20;
|
||||
public int wakeUpInactiveMonstersFor = 5*20;
|
||||
public int wakeUpInactiveMonstersEvery = 20 * 20;
|
||||
public int wakeUpInactiveMonstersFor = 5 * 20;
|
||||
public int wakeUpInactiveVillagers = 4;
|
||||
public int wakeUpInactiveVillagersEvery = 30*20;
|
||||
public int wakeUpInactiveVillagersFor = 5*20;
|
||||
public int wakeUpInactiveVillagersEvery = 30 * 20;
|
||||
public int wakeUpInactiveVillagersFor = 5 * 20;
|
||||
public int wakeUpInactiveFlying = 8;
|
||||
public int wakeUpInactiveFlyingEvery = 10*20;
|
||||
public int wakeUpInactiveFlyingFor = 5*20;
|
||||
public int villagersWorkImmunityAfter = 5*20;
|
||||
public int wakeUpInactiveFlyingEvery = 10 * 20;
|
||||
public int wakeUpInactiveFlyingFor = 5 * 20;
|
||||
public int villagersWorkImmunityAfter = 5 * 20;
|
||||
public int villagersWorkImmunityFor = 20;
|
||||
public boolean villagersActiveForPanic = true;
|
||||
// Paper end
|
||||
public boolean tickInactiveVillagers = true;
|
||||
public boolean ignoreSpectatorActivation = false;
|
||||
private void activationRange()
|
||||
{
|
||||
|
||||
private void activationRange() {
|
||||
boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", this.animalActivationRange) != this.animalActivationRange; // Paper
|
||||
this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange );
|
||||
this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange );
|
||||
this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange );
|
||||
this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange );
|
||||
this.animalActivationRange = this.getInt("entity-activation-range.animals", this.animalActivationRange);
|
||||
this.monsterActivationRange = this.getInt("entity-activation-range.monsters", this.monsterActivationRange);
|
||||
this.raiderActivationRange = this.getInt("entity-activation-range.raiders", this.raiderActivationRange);
|
||||
this.miscActivationRange = this.getInt("entity-activation-range.misc", this.miscActivationRange);
|
||||
// Paper start
|
||||
this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange );
|
||||
this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange );
|
||||
this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange );
|
||||
this.waterActivationRange = this.getInt("entity-activation-range.water", this.waterActivationRange);
|
||||
this.villagerActivationRange = this.getInt("entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange);
|
||||
this.flyingMonsterActivationRange = this.getInt("entity-activation-range.flying-monsters", this.flyingMonsterActivationRange);
|
||||
|
||||
this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals);
|
||||
this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery);
|
||||
@ -261,13 +238,13 @@ public class SpigotWorldConfig
|
||||
this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery);
|
||||
this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor);
|
||||
|
||||
this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter );
|
||||
this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor );
|
||||
this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic );
|
||||
this.villagersWorkImmunityAfter = this.getInt("entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter);
|
||||
this.villagersWorkImmunityFor = this.getInt("entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor);
|
||||
this.villagersActiveForPanic = this.getBoolean("entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic);
|
||||
// Paper end
|
||||
this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers );
|
||||
this.ignoreSpectatorActivation = this.getBoolean( "entity-activation-range.ignore-spectators", this.ignoreSpectatorActivation );
|
||||
this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers + " / Isa " + this.ignoreSpectatorActivation );
|
||||
this.tickInactiveVillagers = this.getBoolean("entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers);
|
||||
this.ignoreSpectatorActivation = this.getBoolean("entity-activation-range.ignore-spectators", this.ignoreSpectatorActivation);
|
||||
this.log("Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers + " / Isa " + this.ignoreSpectatorActivation);
|
||||
}
|
||||
|
||||
public int playerTrackingRange = 128;
|
||||
@ -276,81 +253,71 @@ public class SpigotWorldConfig
|
||||
public int miscTrackingRange = 96;
|
||||
public int displayTrackingRange = 128;
|
||||
public int otherTrackingRange = 64;
|
||||
private void trackingRange()
|
||||
{
|
||||
this.playerTrackingRange = this.getInt( "entity-tracking-range.players", this.playerTrackingRange );
|
||||
this.animalTrackingRange = this.getInt( "entity-tracking-range.animals", this.animalTrackingRange );
|
||||
this.monsterTrackingRange = this.getInt( "entity-tracking-range.monsters", this.monsterTrackingRange );
|
||||
this.miscTrackingRange = this.getInt( "entity-tracking-range.misc", this.miscTrackingRange );
|
||||
this.displayTrackingRange = this.getInt( "entity-tracking-range.display", this.displayTrackingRange );
|
||||
this.otherTrackingRange = this.getInt( "entity-tracking-range.other", this.otherTrackingRange );
|
||||
this.log( "Entity Tracking Range: Pl " + this.playerTrackingRange + " / An " + this.animalTrackingRange + " / Mo " + this.monsterTrackingRange + " / Mi " + this.miscTrackingRange + " / Di " + this.displayTrackingRange + " / Other " + this.otherTrackingRange );
|
||||
private void trackingRange() {
|
||||
this.playerTrackingRange = this.getInt("entity-tracking-range.players", this.playerTrackingRange);
|
||||
this.animalTrackingRange = this.getInt("entity-tracking-range.animals", this.animalTrackingRange);
|
||||
this.monsterTrackingRange = this.getInt("entity-tracking-range.monsters", this.monsterTrackingRange);
|
||||
this.miscTrackingRange = this.getInt("entity-tracking-range.misc", this.miscTrackingRange);
|
||||
this.displayTrackingRange = this.getInt("entity-tracking-range.display", this.displayTrackingRange);
|
||||
this.otherTrackingRange = this.getInt("entity-tracking-range.other", this.otherTrackingRange);
|
||||
this.log("Entity Tracking Range: Pl " + this.playerTrackingRange + " / An " + this.animalTrackingRange + " / Mo " + this.monsterTrackingRange + " / Mi " + this.miscTrackingRange + " / Di " + this.displayTrackingRange + " / Other " + this.otherTrackingRange);
|
||||
}
|
||||
|
||||
public int hopperTransfer;
|
||||
public int hopperCheck;
|
||||
public int hopperAmount;
|
||||
public boolean hopperCanLoadChunks;
|
||||
private void hoppers()
|
||||
{
|
||||
private void hoppers() {
|
||||
// Set the tick delay between hopper item movements
|
||||
this.hopperTransfer = this.getInt( "ticks-per.hopper-transfer", 8 );
|
||||
if ( SpigotConfig.version < 11 )
|
||||
{
|
||||
this.set( "ticks-per.hopper-check", 1 );
|
||||
this.hopperTransfer = this.getInt("ticks-per.hopper-transfer", 8);
|
||||
if (SpigotConfig.version < 11) {
|
||||
this.set("ticks-per.hopper-check", 1);
|
||||
}
|
||||
this.hopperCheck = this.getInt( "ticks-per.hopper-check", 1 );
|
||||
this.hopperAmount = this.getInt( "hopper-amount", 1 );
|
||||
this.hopperCanLoadChunks = this.getBoolean( "hopper-can-load-chunks", false );
|
||||
this.log( "Hopper Transfer: " + this.hopperTransfer + " Hopper Check: " + this.hopperCheck + " Hopper Amount: " + this.hopperAmount + " Hopper Can Load Chunks: " + this.hopperCanLoadChunks );
|
||||
this.hopperCheck = this.getInt("ticks-per.hopper-check", 1);
|
||||
this.hopperAmount = this.getInt("hopper-amount", 1);
|
||||
this.hopperCanLoadChunks = this.getBoolean("hopper-can-load-chunks", false);
|
||||
this.log("Hopper Transfer: " + this.hopperTransfer + " Hopper Check: " + this.hopperCheck + " Hopper Amount: " + this.hopperAmount + " Hopper Can Load Chunks: " + this.hopperCanLoadChunks);
|
||||
}
|
||||
|
||||
public int arrowDespawnRate;
|
||||
public int tridentDespawnRate;
|
||||
private void arrowDespawnRate()
|
||||
{
|
||||
this.arrowDespawnRate = this.getInt( "arrow-despawn-rate", 1200 );
|
||||
this.tridentDespawnRate = this.getInt( "trident-despawn-rate", this.arrowDespawnRate );
|
||||
this.log( "Arrow Despawn Rate: " + this.arrowDespawnRate + " Trident Respawn Rate:" + this.tridentDespawnRate );
|
||||
private void arrowDespawnRate() {
|
||||
this.arrowDespawnRate = this.getInt("arrow-despawn-rate", 1200);
|
||||
this.tridentDespawnRate = this.getInt("trident-despawn-rate", this.arrowDespawnRate);
|
||||
this.log("Arrow Despawn Rate: " + this.arrowDespawnRate + " Trident Respawn Rate:" + this.tridentDespawnRate);
|
||||
}
|
||||
|
||||
public boolean zombieAggressiveTowardsVillager;
|
||||
private void zombieAggressiveTowardsVillager()
|
||||
{
|
||||
this.zombieAggressiveTowardsVillager = this.getBoolean( "zombie-aggressive-towards-villager", true );
|
||||
this.log( "Zombie Aggressive Towards Villager: " + this.zombieAggressiveTowardsVillager );
|
||||
private void zombieAggressiveTowardsVillager() {
|
||||
this.zombieAggressiveTowardsVillager = this.getBoolean("zombie-aggressive-towards-villager", true);
|
||||
this.log("Zombie Aggressive Towards Villager: " + this.zombieAggressiveTowardsVillager);
|
||||
}
|
||||
|
||||
public boolean nerfSpawnerMobs;
|
||||
private void nerfSpawnerMobs()
|
||||
{
|
||||
this.nerfSpawnerMobs = this.getBoolean( "nerf-spawner-mobs", false );
|
||||
this.log( "Nerfing mobs spawned from spawners: " + this.nerfSpawnerMobs );
|
||||
private void nerfSpawnerMobs() {
|
||||
this.nerfSpawnerMobs = this.getBoolean("nerf-spawner-mobs", false);
|
||||
this.log("Nerfing mobs spawned from spawners: " + this.nerfSpawnerMobs);
|
||||
}
|
||||
|
||||
public boolean enableZombiePigmenPortalSpawns;
|
||||
private void enableZombiePigmenPortalSpawns()
|
||||
{
|
||||
this.enableZombiePigmenPortalSpawns = this.getBoolean( "enable-zombie-pigmen-portal-spawns", true );
|
||||
this.log( "Allow Zombie Pigmen to spawn from portal blocks: " + this.enableZombiePigmenPortalSpawns );
|
||||
private void enableZombiePigmenPortalSpawns() {
|
||||
this.enableZombiePigmenPortalSpawns = this.getBoolean("enable-zombie-pigmen-portal-spawns", true);
|
||||
this.log("Allow Zombie Pigmen to spawn from portal blocks: " + this.enableZombiePigmenPortalSpawns);
|
||||
}
|
||||
|
||||
public int dragonDeathSoundRadius;
|
||||
private void keepDragonDeathPerWorld()
|
||||
{
|
||||
this.dragonDeathSoundRadius = this.getInt( "dragon-death-sound-radius", 0 );
|
||||
private void keepDragonDeathPerWorld() {
|
||||
this.dragonDeathSoundRadius = this.getInt("dragon-death-sound-radius", 0);
|
||||
}
|
||||
|
||||
public int witherSpawnSoundRadius;
|
||||
private void witherSpawnSoundRadius()
|
||||
{
|
||||
this.witherSpawnSoundRadius = this.getInt( "wither-spawn-sound-radius", 0 );
|
||||
private void witherSpawnSoundRadius() {
|
||||
this.witherSpawnSoundRadius = this.getInt("wither-spawn-sound-radius", 0);
|
||||
}
|
||||
|
||||
public int endPortalSoundRadius;
|
||||
private void endPortalSoundRadius()
|
||||
{
|
||||
this.endPortalSoundRadius = this.getInt( "end-portal-sound-radius", 0 );
|
||||
private void endPortalSoundRadius() {
|
||||
this.endPortalSoundRadius = this.getInt("end-portal-sound-radius", 0);
|
||||
}
|
||||
|
||||
public int villageSeed;
|
||||
@ -375,28 +342,29 @@ public class SpigotWorldConfig
|
||||
public int buriedTreasureSeed;
|
||||
public Integer mineshaftSeed;
|
||||
public Long strongholdSeed;
|
||||
|
||||
private <N extends Number> N getSeed(String path, java.util.function.Function<String, N> toNumberFunc) {
|
||||
final String value = this.getString(path, "default");
|
||||
return org.apache.commons.lang3.math.NumberUtils.isParsable(value) ? toNumberFunc.apply(value) : null;
|
||||
}
|
||||
|
||||
// Paper end
|
||||
private void initWorldGenSeeds()
|
||||
{
|
||||
this.villageSeed = this.getInt( "seed-village", 10387312 );
|
||||
this.desertSeed = this.getInt( "seed-desert", 14357617 );
|
||||
this.iglooSeed = this.getInt( "seed-igloo", 14357618 );
|
||||
this.jungleSeed = this.getInt( "seed-jungle", 14357619 );
|
||||
this.swampSeed = this.getInt( "seed-swamp", 14357620 );
|
||||
this.monumentSeed = this.getInt( "seed-monument", 10387313 );
|
||||
this.shipwreckSeed = this.getInt( "seed-shipwreck", 165745295 );
|
||||
this.oceanSeed = this.getInt( "seed-ocean", 14357621 );
|
||||
this.outpostSeed = this.getInt( "seed-outpost", 165745296 );
|
||||
this.endCitySeed = this.getInt( "seed-endcity", 10387313 );
|
||||
this.slimeSeed = this.getInt( "seed-slime", 987234911 );
|
||||
this.netherSeed = this.getInt( "seed-nether", 30084232 );
|
||||
this.mansionSeed = this.getInt( "seed-mansion", 10387319 );
|
||||
this.fossilSeed = this.getInt( "seed-fossil", 14357921 );
|
||||
this.portalSeed = this.getInt( "seed-portal", 34222645 );
|
||||
private void initWorldGenSeeds() {
|
||||
this.villageSeed = this.getInt("seed-village", 10387312);
|
||||
this.desertSeed = this.getInt("seed-desert", 14357617);
|
||||
this.iglooSeed = this.getInt("seed-igloo", 14357618);
|
||||
this.jungleSeed = this.getInt("seed-jungle", 14357619);
|
||||
this.swampSeed = this.getInt("seed-swamp", 14357620);
|
||||
this.monumentSeed = this.getInt("seed-monument", 10387313);
|
||||
this.shipwreckSeed = this.getInt("seed-shipwreck", 165745295);
|
||||
this.oceanSeed = this.getInt("seed-ocean", 14357621);
|
||||
this.outpostSeed = this.getInt("seed-outpost", 165745296);
|
||||
this.endCitySeed = this.getInt("seed-endcity", 10387313);
|
||||
this.slimeSeed = this.getInt("seed-slime", 987234911);
|
||||
this.netherSeed = this.getInt("seed-nether", 30084232);
|
||||
this.mansionSeed = this.getInt("seed-mansion", 10387319);
|
||||
this.fossilSeed = this.getInt("seed-fossil", 14357921);
|
||||
this.portalSeed = this.getInt("seed-portal", 34222645);
|
||||
// Paper start - add missing structure set configs
|
||||
this.ancientCitySeed = this.getInt("seed-ancientcity", 20083232);
|
||||
this.trailRuinsSeed = this.getInt("seed-trailruins", 83469867);
|
||||
@ -405,8 +373,8 @@ public class SpigotWorldConfig
|
||||
this.mineshaftSeed = this.getSeed("seed-mineshaft", Integer::parseInt);
|
||||
this.strongholdSeed = this.getSeed("seed-stronghold", Long::parseLong);
|
||||
// Paper end
|
||||
this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
|
||||
+ " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed );
|
||||
this.log("Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
|
||||
+ " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed);
|
||||
}
|
||||
|
||||
public float jumpWalkExhaustion;
|
||||
@ -416,54 +384,48 @@ public class SpigotWorldConfig
|
||||
public float swimMultiplier;
|
||||
public float sprintMultiplier;
|
||||
public float otherMultiplier;
|
||||
private void initHunger()
|
||||
{
|
||||
if ( SpigotConfig.version < 10 )
|
||||
{
|
||||
this.set( "hunger.walk-exhaustion", null );
|
||||
this.set( "hunger.sprint-exhaustion", null );
|
||||
this.set( "hunger.combat-exhaustion", 0.1 );
|
||||
this.set( "hunger.regen-exhaustion", 6.0 );
|
||||
private void initHunger() {
|
||||
if (SpigotConfig.version < 10) {
|
||||
this.set("hunger.walk-exhaustion", null);
|
||||
this.set("hunger.sprint-exhaustion", null);
|
||||
this.set("hunger.combat-exhaustion", 0.1);
|
||||
this.set("hunger.regen-exhaustion", 6.0);
|
||||
}
|
||||
|
||||
this.jumpWalkExhaustion = (float) this.getDouble( "hunger.jump-walk-exhaustion", 0.05 );
|
||||
this.jumpSprintExhaustion = (float) this.getDouble( "hunger.jump-sprint-exhaustion", 0.2 );
|
||||
this.combatExhaustion = (float) this.getDouble( "hunger.combat-exhaustion", 0.1 );
|
||||
this.regenExhaustion = (float) this.getDouble( "hunger.regen-exhaustion", 6.0 );
|
||||
this.swimMultiplier = (float) this.getDouble( "hunger.swim-multiplier", 0.01 );
|
||||
this.sprintMultiplier = (float) this.getDouble( "hunger.sprint-multiplier", 0.1 );
|
||||
this.otherMultiplier = (float) this.getDouble( "hunger.other-multiplier", 0.0 );
|
||||
this.jumpWalkExhaustion = (float) this.getDouble("hunger.jump-walk-exhaustion", 0.05);
|
||||
this.jumpSprintExhaustion = (float) this.getDouble("hunger.jump-sprint-exhaustion", 0.2);
|
||||
this.combatExhaustion = (float) this.getDouble("hunger.combat-exhaustion", 0.1);
|
||||
this.regenExhaustion = (float) this.getDouble("hunger.regen-exhaustion", 6.0);
|
||||
this.swimMultiplier = (float) this.getDouble("hunger.swim-multiplier", 0.01);
|
||||
this.sprintMultiplier = (float) this.getDouble("hunger.sprint-multiplier", 0.1);
|
||||
this.otherMultiplier = (float) this.getDouble("hunger.other-multiplier", 0.0);
|
||||
}
|
||||
|
||||
public int currentPrimedTnt = 0;
|
||||
public int maxTntTicksPerTick;
|
||||
private void maxTntPerTick() {
|
||||
if ( SpigotConfig.version < 7 )
|
||||
{
|
||||
this.set( "max-tnt-per-tick", 100 );
|
||||
if (SpigotConfig.version < 7) {
|
||||
this.set("max-tnt-per-tick", 100);
|
||||
}
|
||||
this.maxTntTicksPerTick = this.getInt( "max-tnt-per-tick", 100 );
|
||||
this.log( "Max TNT Explosions: " + this.maxTntTicksPerTick );
|
||||
this.maxTntTicksPerTick = this.getInt("max-tnt-per-tick", 100);
|
||||
this.log("Max TNT Explosions: " + this.maxTntTicksPerTick);
|
||||
}
|
||||
|
||||
public int hangingTickFrequency;
|
||||
private void hangingTickFrequency()
|
||||
{
|
||||
this.hangingTickFrequency = this.getInt( "hanging-tick-frequency", 100 );
|
||||
private void hangingTickFrequency() {
|
||||
this.hangingTickFrequency = this.getInt("hanging-tick-frequency", 100);
|
||||
}
|
||||
|
||||
public int tileMaxTickTime;
|
||||
public int entityMaxTickTime;
|
||||
private void maxTickTimes()
|
||||
{
|
||||
private void maxTickTimes() {
|
||||
this.tileMaxTickTime = this.getInt("max-tick-time.tile", 50);
|
||||
this.entityMaxTickTime = this.getInt("max-tick-time.entity", 50);
|
||||
this.log("Tile Max Tick Time: " + this.tileMaxTickTime + "ms Entity max Tick Time: " + this.entityMaxTickTime + "ms");
|
||||
}
|
||||
|
||||
public int thunderChance;
|
||||
private void thunderChance()
|
||||
{
|
||||
private void thunderChance() {
|
||||
this.thunderChance = this.getInt("thunder-chance", 100000);
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ public class TickLimiter {
|
||||
private final int maxTime;
|
||||
private long startTime;
|
||||
|
||||
public TickLimiter(int maxtime) {
|
||||
this.maxTime = maxtime;
|
||||
public TickLimiter(int maxTime) {
|
||||
this.maxTime = maxTime;
|
||||
}
|
||||
|
||||
public void initTick() {
|
||||
|
@ -1,51 +1,55 @@
|
||||
package org.spigotmc;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.ChatColor;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class TicksPerSecondCommand extends Command
|
||||
{
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public TicksPerSecondCommand(String name)
|
||||
{
|
||||
super( name );
|
||||
public class TicksPerSecondCommand extends Command {
|
||||
|
||||
private boolean hasShownMemoryWarning; // Paper
|
||||
|
||||
public TicksPerSecondCommand(String name) {
|
||||
super(name);
|
||||
this.description = "Gets the current ticks per second for the server";
|
||||
this.usageMessage = "/tps";
|
||||
this.setPermission( "bukkit.command.tps" );
|
||||
this.setPermission("bukkit.command.tps");
|
||||
}
|
||||
|
||||
// Paper start
|
||||
private static final net.kyori.adventure.text.Component WARN_MSG = net.kyori.adventure.text.Component.text()
|
||||
.append(net.kyori.adventure.text.Component.text("Warning: ", net.kyori.adventure.text.format.NamedTextColor.RED))
|
||||
.append(net.kyori.adventure.text.Component.text("Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention.", net.kyori.adventure.text.format.NamedTextColor.GOLD))
|
||||
private static final Component WARN_MSG = text()
|
||||
.append(text("Warning: ", NamedTextColor.RED))
|
||||
.append(text("Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention.", NamedTextColor.GOLD))
|
||||
.build();
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args)
|
||||
{
|
||||
if ( !this.testPermission( sender ) )
|
||||
{
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||
if (!this.testPermission(sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Paper start - Further improve tick handling
|
||||
double[] tps = org.bukkit.Bukkit.getTPS();
|
||||
net.kyori.adventure.text.Component[] tpsAvg = new net.kyori.adventure.text.Component[tps.length];
|
||||
Component[] tpsAvg = new Component[tps.length];
|
||||
|
||||
for ( int i = 0; i < tps.length; i++) {
|
||||
tpsAvg[i] = TicksPerSecondCommand.format( tps[i] );
|
||||
for (int i = 0; i < tps.length; i++) {
|
||||
tpsAvg[i] = TicksPerSecondCommand.format(tps[i]);
|
||||
}
|
||||
|
||||
net.kyori.adventure.text.TextComponent.Builder builder = net.kyori.adventure.text.Component.text();
|
||||
builder.append(net.kyori.adventure.text.Component.text("TPS from last 1m, 5m, 15m: ", net.kyori.adventure.text.format.NamedTextColor.GOLD));
|
||||
builder.append(net.kyori.adventure.text.Component.join(net.kyori.adventure.text.JoinConfiguration.commas(true), tpsAvg));
|
||||
TextComponent.Builder builder = text();
|
||||
builder.append(text("TPS from last 1m, 5m, 15m: ", NamedTextColor.GOLD));
|
||||
builder.append(Component.join(JoinConfiguration.commas(true), tpsAvg));
|
||||
sender.sendMessage(builder.asComponent());
|
||||
if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) {
|
||||
sender.sendMessage(net.kyori.adventure.text.Component.text()
|
||||
.append(net.kyori.adventure.text.Component.text("Current Memory Usage: ", net.kyori.adventure.text.format.NamedTextColor.GOLD))
|
||||
.append(net.kyori.adventure.text.Component.text(((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)", net.kyori.adventure.text.format.NamedTextColor.GREEN))
|
||||
sender.sendMessage(text()
|
||||
.append(text("Current Memory Usage: ", NamedTextColor.GOLD))
|
||||
.append(text(((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)", NamedTextColor.GREEN))
|
||||
);
|
||||
if (!this.hasShownMemoryWarning) {
|
||||
sender.sendMessage(WARN_MSG);
|
||||
@ -57,13 +61,11 @@ public class TicksPerSecondCommand extends Command
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasShownMemoryWarning; // Paper
|
||||
private static net.kyori.adventure.text.Component format(double tps) // Paper - Made static
|
||||
{
|
||||
// Paper
|
||||
net.kyori.adventure.text.format.TextColor color = ( ( tps > 18.0 ) ? net.kyori.adventure.text.format.NamedTextColor.GREEN : ( tps > 16.0 ) ? net.kyori.adventure.text.format.NamedTextColor.YELLOW : net.kyori.adventure.text.format.NamedTextColor.RED );
|
||||
String amount = Math.min(Math.round(tps * 100.0) / 100.0, 20.0) + (tps > 21.0 ? "*" : ""); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
|
||||
return net.kyori.adventure.text.Component.text(amount, color);
|
||||
private static Component format(double tps) { // Paper - Made static
|
||||
// Paper start
|
||||
TextColor color = ((tps > 18.0) ? NamedTextColor.GREEN : (tps > 16.0) ? NamedTextColor.YELLOW : NamedTextColor.RED);
|
||||
String amount = Math.min(Math.round(tps * 100.0) / 100.0, 20.0) + (tps > 21.0 ? "*" : ""); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
|
||||
return text(amount, color);
|
||||
// Paper end
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,7 @@ public final class TrackingRange {
|
||||
* Gets the range an entity should be 'tracked' by players and visible in
|
||||
* the client.
|
||||
*
|
||||
* @param entity
|
||||
* @param defaultRange Default range defined by Mojang
|
||||
* @return
|
||||
*/
|
||||
public static int getEntityTrackingRange(final Entity entity, final int defaultRange) {
|
||||
if (defaultRange == 0) {
|
||||
@ -51,7 +49,7 @@ public final class TrackingRange {
|
||||
} else {
|
||||
if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) {
|
||||
// Exempt ender dragon
|
||||
return ((ServerLevel) entity.getCommandSenderWorld()).getChunkSource().chunkMap.serverViewDistance;
|
||||
return ((ServerLevel) entity.level()).getChunkSource().chunkMap.serverViewDistance;
|
||||
}
|
||||
return config.otherTrackingRange;
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ import java.lang.management.MonitorInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import io.papermc.paper.configuration.GlobalConfiguration;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
|
||||
public class WatchdogThread extends Thread
|
||||
{
|
||||
public class WatchdogThread extends Thread {
|
||||
|
||||
private static WatchdogThread instance;
|
||||
private long timeoutTime;
|
||||
@ -21,160 +22,141 @@ public class WatchdogThread extends Thread
|
||||
private volatile long lastTick;
|
||||
private volatile boolean stopping;
|
||||
|
||||
private WatchdogThread(long timeoutTime, boolean restart)
|
||||
{
|
||||
super( "Paper Watchdog Thread" );
|
||||
private WatchdogThread(long timeoutTime, boolean restart) {
|
||||
super("Paper Watchdog Thread");
|
||||
this.timeoutTime = timeoutTime;
|
||||
this.restart = restart;
|
||||
earlyWarningEvery = Math.min(io.papermc.paper.configuration.GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); // Paper
|
||||
earlyWarningDelay = Math.min(io.papermc.paper.configuration.GlobalConfiguration.get().watchdog.earlyWarningDelay, timeoutTime); // Paper
|
||||
this.earlyWarningEvery = Math.min(GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); // Paper
|
||||
this.earlyWarningDelay = Math.min(GlobalConfiguration.get().watchdog.earlyWarningDelay, timeoutTime); // Paper
|
||||
}
|
||||
|
||||
private static long monotonicMillis()
|
||||
{
|
||||
private static long monotonicMillis() {
|
||||
return System.nanoTime() / 1000000L;
|
||||
}
|
||||
|
||||
public static void doStart(int timeoutTime, boolean restart)
|
||||
{
|
||||
if ( WatchdogThread.instance == null )
|
||||
{
|
||||
WatchdogThread.instance = new WatchdogThread( timeoutTime * 1000L, restart );
|
||||
public static void doStart(int timeoutTime, boolean restart) {
|
||||
if (WatchdogThread.instance == null) {
|
||||
WatchdogThread.instance = new WatchdogThread(timeoutTime * 1000L, restart);
|
||||
WatchdogThread.instance.start();
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
WatchdogThread.instance.timeoutTime = timeoutTime * 1000L;
|
||||
WatchdogThread.instance.restart = restart;
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick()
|
||||
{
|
||||
public static void tick() {
|
||||
WatchdogThread.instance.lastTick = WatchdogThread.monotonicMillis();
|
||||
}
|
||||
|
||||
public static void doStop()
|
||||
{
|
||||
if ( WatchdogThread.instance != null )
|
||||
{
|
||||
public static void doStop() {
|
||||
if (WatchdogThread.instance != null) {
|
||||
WatchdogThread.instance.stopping = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while ( !this.stopping )
|
||||
{
|
||||
//
|
||||
public void run() {
|
||||
while (!this.stopping) {
|
||||
// Paper start
|
||||
Logger log = Bukkit.getServer().getLogger();
|
||||
Logger logger = Bukkit.getServer().getLogger();
|
||||
long currentTime = WatchdogThread.monotonicMillis();
|
||||
if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable
|
||||
{
|
||||
boolean isLongTimeout = currentTime > lastTick + timeoutTime;
|
||||
if (this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) { // Paper - Add property to disable
|
||||
boolean isLongTimeout = currentTime > this.lastTick + this.timeoutTime;
|
||||
// Don't spam early warning dumps
|
||||
if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue;
|
||||
if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this...
|
||||
lastEarlyWarning = currentTime;
|
||||
if (!isLongTimeout && (this.earlyWarningEvery <= 0 ||
|
||||
!hasStarted || currentTime < this.lastEarlyWarning + this.earlyWarningEvery ||
|
||||
currentTime < this.lastTick + this.earlyWarningDelay))
|
||||
continue;
|
||||
if (!isLongTimeout && MinecraftServer.getServer().hasStopped())
|
||||
continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this...
|
||||
this.lastEarlyWarning = currentTime;
|
||||
if (isLongTimeout) {
|
||||
// Paper end
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
|
||||
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
|
||||
log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" );
|
||||
log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" );
|
||||
log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" );
|
||||
log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" );
|
||||
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
|
||||
log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() );
|
||||
//
|
||||
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
|
||||
{
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" );
|
||||
log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem );
|
||||
}
|
||||
//
|
||||
// Paper start - Warn in watchdog if an excessive velocity was ever set
|
||||
if (org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null) {
|
||||
log.log(Level.SEVERE, "------------------------------");
|
||||
log.log(Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity");
|
||||
log.log(Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated");
|
||||
log.log(Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage());
|
||||
for (StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace()) {
|
||||
log.log( Level.SEVERE, "\t\t" + stack );
|
||||
// Paper end
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug."); // Paper
|
||||
logger.log(Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author");
|
||||
logger.log(Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring");
|
||||
logger.log(Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once");
|
||||
logger.log(Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes");
|
||||
logger.log(Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues");
|
||||
logger.log(Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports");
|
||||
logger.log(Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion());
|
||||
|
||||
if (net.minecraft.world.level.Level.lastPhysicsProblem != null) {
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
logger.log(Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed");
|
||||
logger.log(Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem);
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
} else
|
||||
{
|
||||
log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---");
|
||||
log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump");
|
||||
|
||||
// Paper start - Warn in watchdog if an excessive velocity was ever set
|
||||
if (CraftServer.excessiveVelEx != null) {
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
logger.log(Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity");
|
||||
logger.log(Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated");
|
||||
logger.log(Level.SEVERE, CraftServer.excessiveVelEx.getMessage());
|
||||
for (StackTraceElement stack : CraftServer.excessiveVelEx.getStackTrace()) {
|
||||
logger.log(Level.SEVERE, "\t\t" + stack);
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---");
|
||||
logger.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump");
|
||||
}
|
||||
// Paper end - Different message for short timeout
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
|
||||
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
//
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper
|
||||
WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger);
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
|
||||
// Paper start - Only print full dump on long timeouts
|
||||
if ( isLongTimeout )
|
||||
{
|
||||
log.log( Level.SEVERE, "Entire Thread Dump:" );
|
||||
ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true );
|
||||
for ( ThreadInfo thread : threads )
|
||||
{
|
||||
WatchdogThread.dumpThread( thread, log );
|
||||
}
|
||||
if (isLongTimeout) {
|
||||
logger.log(Level.SEVERE, "Entire Thread Dump:");
|
||||
ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
|
||||
for (ThreadInfo thread : threads) {
|
||||
WatchdogThread.dumpThread(thread, logger);
|
||||
}
|
||||
} else {
|
||||
log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---");
|
||||
logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---");
|
||||
}
|
||||
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
logger.log(Level.SEVERE, "------------------------------");
|
||||
|
||||
if ( isLongTimeout )
|
||||
{
|
||||
if ( this.restart && !MinecraftServer.getServer().hasStopped() )
|
||||
{
|
||||
RestartCommand.restart();
|
||||
if (isLongTimeout) {
|
||||
if (this.restart && !MinecraftServer.getServer().hasStopped()) {
|
||||
RestartCommand.restart();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} // Paper end
|
||||
// Paper end
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
try {
|
||||
sleep(1000); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout
|
||||
} catch (InterruptedException ex) {
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpThread(ThreadInfo thread, Logger log)
|
||||
{
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
//
|
||||
log.log( Level.SEVERE, "Current Thread: " + thread.getThreadName() );
|
||||
log.log( Level.SEVERE, "\tPID: " + thread.getThreadId()
|
||||
+ " | Suspended: " + thread.isSuspended()
|
||||
+ " | Native: " + thread.isInNative()
|
||||
+ " | State: " + thread.getThreadState() );
|
||||
if ( thread.getLockedMonitors().length != 0 )
|
||||
{
|
||||
log.log( Level.SEVERE, "\tThread is waiting on monitor(s):" );
|
||||
for ( MonitorInfo monitor : thread.getLockedMonitors() )
|
||||
{
|
||||
log.log( Level.SEVERE, "\t\tLocked on:" + monitor.getLockedStackFrame() );
|
||||
private static void dumpThread(ThreadInfo thread, Logger log) {
|
||||
log.log(Level.SEVERE, "------------------------------");
|
||||
|
||||
log.log(Level.SEVERE, "Current Thread: " + thread.getThreadName());
|
||||
log.log(Level.SEVERE, "\tPID: " + thread.getThreadId()
|
||||
+ " | Suspended: " + thread.isSuspended()
|
||||
+ " | Native: " + thread.isInNative()
|
||||
+ " | State: " + thread.getThreadState());
|
||||
if (thread.getLockedMonitors().length != 0) {
|
||||
log.log(Level.SEVERE, "\tThread is waiting on monitor(s):");
|
||||
for (MonitorInfo monitor : thread.getLockedMonitors()) {
|
||||
log.log(Level.SEVERE, "\t\tLocked on:" + monitor.getLockedStackFrame());
|
||||
}
|
||||
}
|
||||
log.log( Level.SEVERE, "\tStack:" );
|
||||
//
|
||||
for ( StackTraceElement stack : io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateStacktrace(thread.getStackTrace()) ) // Paper
|
||||
{
|
||||
log.log( Level.SEVERE, "\t\t" + stack );
|
||||
log.log(Level.SEVERE, "\tStack:");
|
||||
|
||||
for (StackTraceElement stack : io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateStacktrace(thread.getStackTrace())) { // Paper
|
||||
log.log(Level.SEVERE, "\t\t" + stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren