diff --git a/sources/pom.xml b/sources/pom.xml
index ac7e7229a..6d4f83f17 100644
--- a/sources/pom.xml
+++ b/sources/pom.xml
@@ -133,6 +133,11 @@
mixin
0.7.8-SNAPSHOT
+
+ me.nallar.whocalled
+ WhoCalled
+ 1.1
+
@@ -148,6 +153,10 @@
spongepowered-repo
https://repo.spongepowered.org/maven/
+
+ nallar-repo
+ http://repo.nallar.me/
+
diff --git a/sources/src/main/java/co/aikar/timings/TimingHandler.java b/sources/src/main/java/co/aikar/timings/TimingHandler.java
index f51b4eeb2..38ea1a44f 100644
--- a/sources/src/main/java/co/aikar/timings/TimingHandler.java
+++ b/sources/src/main/java/co/aikar/timings/TimingHandler.java
@@ -24,6 +24,7 @@
package co.aikar.timings;
import co.aikar.util.LoadingIntMap;
+import io.akarin.api.Akari;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.bukkit.Bukkit;
diff --git a/sources/src/main/java/io/akarin/api/Akari.java b/sources/src/main/java/io/akarin/api/Akari.java
index b8c084fce..cc32887e4 100644
--- a/sources/src/main/java/io/akarin/api/Akari.java
+++ b/sources/src/main/java/io/akarin/api/Akari.java
@@ -8,12 +8,14 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.bukkit.entity.Minecart;
import com.google.common.collect.Queues;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import co.aikar.timings.Timing;
import co.aikar.timings.Timings;
+import net.minecraft.server.MinecraftServer;
public abstract class Akari {
/**
@@ -41,6 +43,12 @@ public abstract class Akari {
*/
public static final ExecutorCompletionService> STAGE_TICK = new ExecutorCompletionService<>(Executors.newSingleThreadExecutor(Akari.STAGE_FACTORY));
+ public static volatile boolean mayMock;
+
+ public static boolean isPrimaryThread() {
+ return Thread.currentThread().equals(MinecraftServer.getServer().primaryThread);
+ }
+
/*
* The unsafe
*/
diff --git a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java
index 27c03288b..95835cde8 100644
--- a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java
+++ b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java
@@ -189,6 +189,26 @@ public class AkarinGlobalConfig {
asyncLightingThreads = getInt("core.async-lighting.executor-threads", 2);
}
+ public static boolean enableMockPlugin;
+ private static void enableMockPlugin() {
+ enableMockPlugin = getBoolean("core.thread-safe.enable-mock-plugins", false);
+ }
+
+ public static List mockPackageList;
+ private static void mockPluginList() {
+ mockPackageList = getList("core.thread-safe.mock-package-name-contains", Lists.newArrayList());
+ }
+
+ public static boolean enableAsyncCatcher;
+ private static void enableAsyncCatcher() {
+ enableAsyncCatcher = getBoolean("core.thread-safe.async-catcher.enable", false);
+ }
+
+ public static boolean throwOnAsyncCaught;
+ private static void throwOnAsyncCaught() {
+ throwOnAsyncCaught = getBoolean("core.thread-safe.async-catcher.throw-on-caught", true);
+ }
+
public static boolean asyncLightingWorkStealing;
private static void asyncLightingWorkStealing() {
asyncLightingWorkStealing = getBoolean("core.async-lighting.use-work-stealing", false);
diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinCraftServer.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinCraftServer.java
index d2cca76b7..170d71da4 100644
--- a/sources/src/main/java/io/akarin/server/mixin/core/MixinCraftServer.java
+++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinCraftServer.java
@@ -7,9 +7,14 @@ import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
+import io.akarin.server.core.AkarinGlobalConfig;
+import me.nallar.whocalled.WhoCalled;
+import net.minecraft.server.MinecraftServer;
+
@Mixin(value = CraftServer.class, remap = false)
public class MixinCraftServer {
@Shadow @Final @Mutable private String serverName;
+ @Shadow @Final protected MinecraftServer console;
private boolean needApplyServerName = true;
@Overwrite
@@ -22,4 +27,18 @@ public class MixinCraftServer {
}
return serverName;
}
+
+ @Overwrite
+ public boolean isPrimaryThread() {
+ if (AkarinGlobalConfig.enableMockPlugin) {
+ // Mock forcely main thread plugins
+ String callerPackage = WhoCalled.$.getCallingClass().getPackage().getName();
+ if (callerPackage.startsWith("net.minecraft") || callerPackage.startsWith("org.bukkit") ||
+ callerPackage.startsWith("co.aikar") || callerPackage.startsWith("io.akarin")) return Thread.currentThread().equals(console.primaryThread);
+ for (String contains : AkarinGlobalConfig.mockPackageList) {
+ if (callerPackage.contains(contains)) return true;
+ }
+ }
+ return Thread.currentThread().equals(console.primaryThread);
+ }
}
diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java
index 5e293cdba..ad0653ad1 100644
--- a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java
+++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java
@@ -20,7 +20,7 @@ public class MixinTimingHandler {
@Overwrite
public void stopTimingIfSync() {
- if (Bukkit.isPrimaryThread()) {
+ if (Akari.isPrimaryThread()) { // Akarin
stopTiming(true); // Avoid twice thread check
}
}
@@ -38,7 +38,7 @@ public class MixinTimingHandler {
start = 0;
return;
} else {
- if (!sync && !Bukkit.isPrimaryThread()) {
+ if (!sync && !Akari.isPrimaryThread()) { // Akarin
if (AkarinGlobalConfig.silentAsyncTimings) {
Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name);
new Throwable().printStackTrace();
diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java
index 4ff00811a..3d9761279 100644
--- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java
+++ b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java
@@ -45,6 +45,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.google.common.collect.Lists;
+import io.akarin.api.Akari;
import io.akarin.api.mixin.IMixinChunk;
import io.akarin.api.mixin.IMixinWorldServer;
import net.minecraft.server.BlockPosition;
@@ -245,7 +246,7 @@ public abstract class MixinChunk implements IMixinChunk {
return;
}
- if (Bukkit.isPrimaryThread()) {
+ if (Akari.isPrimaryThread()) { // Akarin
try {
this.lightExecutorService.execute(() -> {
this.checkLightAsync(neighborChunks);
diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java
index 05439b423..008dfb7fa 100644
--- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java
+++ b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java
@@ -33,6 +33,7 @@ import org.bukkit.Bukkit;
import org.spongepowered.asm.mixin.Mixin;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.akarin.api.Akari;
import io.akarin.api.mixin.IMixinChunk;
import io.akarin.api.mixin.IMixinWorldServer;
import io.akarin.server.core.AkarinGlobalConfig;
@@ -240,7 +241,7 @@ public abstract class MixinWorldServer extends MixinWorld implements IMixinWorld
neighbor.setLightUpdateTime(chunk.getWorld().getTime());
}
- if (Bukkit.isPrimaryThread()) {
+ if (Akari.isPrimaryThread()) { // Akarin
this.lightExecutorService.execute(() -> {
this.checkLightAsync(lightType, pos, chunk, neighbors);
});
diff --git a/sources/src/main/java/net/minecraft/server/PlayerConnection.java b/sources/src/main/java/net/minecraft/server/PlayerConnection.java
index 42489ffe5..c3e505ee9 100644
--- a/sources/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/sources/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -3,6 +3,7 @@ package net.minecraft.server;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Floats;
+import io.akarin.api.Akari;
import io.akarin.server.core.AkarinGlobalConfig;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
@@ -1384,7 +1385,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 && !Akari.isPrimaryThread()) { // Akarin
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());