This commit is contained in:
Sotr
2019-03-19 05:00:23 +08:00
parent 9ccbd91d78
commit dbfd5f4f2d
14 changed files with 346 additions and 20 deletions

View File

@@ -1,168 +0,0 @@
package io.akarin.server.core;
import com.google.common.base.Throwables;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
@SuppressWarnings({"UnusedIsStillUsed", "unused"})
public class AkarinGlobalConfig {
public final static Logger LOGGER = LogManager.getLogger("Akarin");
private static File CONFIG_FILE;
private static final String HEADER = "This is the global configuration file for Akarin.\n"
+ "Some options may impact gameplay, so use with caution,\n"
+ "and make sure you know what each option does before configuring.\n"
+ "\n"
+ "Akarin website: https://akarin.io/ \n";
/*========================================================================*/
public static YamlConfiguration config;
static int version;
/*========================================================================*/
public static void init(File configFile) {
CONFIG_FILE = configFile;
config = new YamlConfiguration();
try {
config.load(CONFIG_FILE);
} catch (IOException ex) {
} catch (InvalidConfigurationException ex) {
LOGGER.error("Could not load akarin.yml, please correct your syntax errors", ex);
throw Throwables.propagate(ex);
}
config.options().header(HEADER);
config.options().copyDefaults(true);
version = getInt("config-version", 2);
set("config-version", 2);
readConfig(AkarinGlobalConfig.class, null);
}
static void readConfig(Class<?> clazz, Object instance) {
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) {
LOGGER.error("Error invoking " + method, ex);
}
}
}
}
try {
config.save(CONFIG_FILE);
} catch (IOException ex) {
LOGGER.error("Could not save " + CONFIG_FILE, ex);
}
}
private static final Pattern SPACE = Pattern.compile(" ");
private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]");
public static int getSeconds(String str) {
str = SPACE.matcher(str).replaceAll("");
final char unit = str.charAt(str.length() - 1);
str = NOT_NUMERIC.matcher(str).replaceAll("");
double num;
try {
num = Double.parseDouble(str);
} catch (Exception e) {
num = 0D;
}
switch (unit) {
case 'd': num *= (double) 60*60*24; break;
case 'h': num *= (double) 60*60; break;
case 'm': num *= 60; break;
default: case 's': break;
}
return (int) num;
}
protected static String timeSummary(int seconds) {
String time = "";
if (seconds > 60 * 60 * 24) {
time += TimeUnit.SECONDS.toDays(seconds) + "d";
seconds %= 60 * 60 * 24;
}
if (seconds > 60 * 60) {
time += TimeUnit.SECONDS.toHours(seconds) + "h";
seconds %= 60 * 60;
}
if (seconds > 0) {
time += TimeUnit.SECONDS.toMinutes(seconds) + "m";
}
return time;
}
public static void set(String path, Object val) {
config.set(path, val);
}
private static boolean getBoolean(String path, boolean def) {
config.addDefault(path, def);
return config.getBoolean(path, config.getBoolean(path));
}
private static double getDouble(String path, double def) {
config.addDefault(path, def);
return config.getDouble(path, config.getDouble(path));
}
private static float getFloat(String path, float def) {
// TODO: Figure out why getFloat() always returns the default value.
return (float) getDouble(path, def);
}
private static int getInt(String path, int def) {
config.addDefault(path, def);
return config.getInt(path, config.getInt(path));
}
private static <T> List getList(String path, T def) {
config.addDefault(path, def);
return config.getList(path, config.getList(path));
}
private static String getString(String path, String def) {
config.addDefault(path, def);
return config.getString(path, config.getString(path));
}
/*========================================================================*/
public static boolean noResponseDoGC = true;
private static void noResponseDoGC() {
noResponseDoGC = getBoolean("alternative.gc-before-stuck-restart", noResponseDoGC);
}
public static String serverBrandName = "";
private static void serverBrandName() {
serverBrandName = getString("alternative.modified-server-brand-name", serverBrandName);
}
public static int fileIOThreads = 2;
private static void fileIOThreads() {
fileIOThreads = getInt("core.chunk-save-threads", fileIOThreads);
fileIOThreads = fileIOThreads < 1 ? 1 : fileIOThreads;
fileIOThreads = fileIOThreads > 8 ? 8 : fileIOThreads;
}
public static boolean fixPhysicsEventBehaviour = false;
private static void fixPhysicsEventBehavior() {
fixPhysicsEventBehaviour = getBoolean("alternative.fix-physics-event-behaviour", fixPhysicsEventBehaviour);
}
}

View File

@@ -1,6 +1,6 @@
package io.akarin.server.core;
public enum PacketType { // unused yet
public enum PacketType {
STATUS_OUT_SERVER_INFO,
STATUS_OUT_PONG,

View File

@@ -14,8 +14,8 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
}
public Chunk put(long i, Chunk chunk) {
org.spigotmc.AsyncCatcher.catchOp("Async Chunk put"); // Paper
chunk.world.timings.syncChunkLoadPostTimer.startTiming(); // Paper
//org.spigotmc.AsyncCatcher.catchOp("Async Chunk put"); // Paper // Akarin - comment
lastChunkByPos = chunk; // Paper
// Paper start
Chunk chunk1;
@@ -81,7 +81,7 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
public Chunk remove(long i) {
// Paper start
org.spigotmc.AsyncCatcher.catchOp("Async Chunk remove");
//org.spigotmc.AsyncCatcher.catchOp("Async Chunk remove"); // Akarin - comment
Chunk chunk;
synchronized (this) {
// synchronize so any async gets are safe

View File

@@ -5,6 +5,9 @@ import com.destroystokyo.paper.profile.CraftPlayerProfile;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.mojang.authlib.GameProfile;
import co.aikar.timings.ThreadAssertion;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
@@ -115,7 +118,7 @@ public final class MCUtil {
* @return
*/
public static void ensureMain(String reason, Runnable run) {
if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().primaryThread) {
if (AsyncCatcher.enabled && !ThreadAssertion.isMainThread() && Thread.currentThread() != MinecraftServer.getServer().primaryThread) { // Akarin
if (reason != null) {
new IllegalStateException("Asynchronous " + reason + "!").printStackTrace();
}
@@ -140,7 +143,7 @@ public final class MCUtil {
* @return
*/
public static <T> T ensureMain(String reason, Supplier<T> run) {
if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().primaryThread) {
if (AsyncCatcher.enabled && !ThreadAssertion.isMainThread() && Thread.currentThread() != MinecraftServer.getServer().primaryThread) { // Akarin
if (reason != null) {
new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace();
}

View File

@@ -16,6 +16,7 @@ import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.datafixers.DataFixer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
@@ -65,6 +66,7 @@ import org.bukkit.event.server.ServerLoadEvent;
// CraftBukkit end
import org.spigotmc.SlackActivityAccountant; // Spigot
import co.aikar.timings.MinecraftTimings; // Paper
import co.aikar.timings.ThreadAssertion;
public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStatistics, ICommandListener, Runnable {
@@ -1704,7 +1706,7 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati
}
public boolean isMainThread() {
return Thread.currentThread() == this.serverThread;
return ThreadAssertion.isMainThread() || Thread.currentThread() == this.serverThread; // Akarin
}
public int aw() {

View File

@@ -69,6 +69,7 @@ import com.destroystokyo.paper.event.player.IllegalPacketEvent; // Paper
import com.destroystokyo.paper.event.player.PlayerJumpEvent; // Paper
import co.aikar.timings.MinecraftTimings; // Paper
// CraftBukkit end
import co.aikar.timings.ThreadAssertion;
public class PlayerConnection implements PacketListenerPlayIn, ITickable {
@@ -1756,7 +1757,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable {
if (!async && s.startsWith("/")) {
// Paper Start
if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) {
if (!org.spigotmc.AsyncCatcher.shuttingDown && !ThreadAssertion.isMainThread() && !org.bukkit.Bukkit.isPrimaryThread()) {
final String fCommandLine = s;
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine);
MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable());

View File

@@ -139,6 +139,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import co.aikar.timings.ThreadAssertion;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
@@ -709,7 +710,7 @@ public final class CraftServer implements Server {
org.spigotmc.AsyncCatcher.catchOp( "command dispatch" ); // Spigot
// Paper Start
if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) {
if (!org.spigotmc.AsyncCatcher.shuttingDown && !ThreadAssertion.isMainThread() && !Bukkit.isPrimaryThread()) { // Akarin
final CommandSender fSender = sender;
final String fCommandLine = commandLine;
Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine);
@@ -1723,7 +1724,7 @@ public final class CraftServer implements Server {
@Override
public boolean isPrimaryThread() {
return Thread.currentThread().equals(console.primaryThread);
return ThreadAssertion.isMainThread() || Thread.currentThread().equals(console.primaryThread);
}
@Override

View File

@@ -40,7 +40,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
queuedChunk.provider.getChunkAt(queuedChunk.x, queuedChunk.z, true, true); // Paper - actually call original if it was already loaded
return;
}
try (Timing ignored = queuedChunk.provider.world.timings.chunkIOStage2.startTimingIfSync()) { // Paper
try (Timing ignored = queuedChunk.provider.world.timings.chunkIOStage2.startTimingIfSync(true)) { // Paper // Akarin
queuedChunk.loader.loadEntities(queuedChunk.compound.getCompound("Level"), chunk);
chunk.setLastSaved(queuedChunk.provider.world.getTime());

View File

@@ -1,5 +1,6 @@
package org.spigotmc;
import co.aikar.timings.ThreadAssertion;
import net.minecraft.server.MinecraftServer;
public class AsyncCatcher
@@ -10,7 +11,7 @@ public class AsyncCatcher
public static void catchOp(String reason)
{
if ( enabled && Thread.currentThread() != MinecraftServer.getServer().primaryThread )
if ( enabled && !ThreadAssertion.isMainThread() && Thread.currentThread() != MinecraftServer.getServer().primaryThread )
{
throw new IllegalStateException( "Asynchronous " + reason + "!" );
}