Upstream has released updates that appear to apply and compile correctly Purpur Changes: PurpurMC/Purpur@bd5c4b6 Updated Upstream (Paper)
528 lines
21 KiB
Diff
528 lines
21 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: AlphaKR93 <dev@alpha93.kr>
|
|
Date: Fri, 31 Mar 2023 07:18:37 +0000
|
|
Subject: [PATCH] Pufferfish API Changes
|
|
|
|
Original: Kevin Raneri <kevin.raneri@gmail.com>
|
|
Copyright (C) 2023 Pufferfish Studios LLC
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index cad12a2632b9ebb569280441c42869685db1f31a..b83e2c5a0a094002d12aee55ec0cf8d12bf33f3e 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -42,6 +42,7 @@ dependencies {
|
|
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
|
|
api("org.apache.logging.log4j:log4j-api:2.17.1")
|
|
api("org.slf4j:slf4j-api:1.8.0-beta4")
|
|
+ api("io.sentry:sentry:5.4.0") // Pufferfish
|
|
|
|
implementation("org.ow2.asm:asm:9.4")
|
|
implementation("org.ow2.asm:asm-commons:9.4")
|
|
@@ -85,6 +86,13 @@ val generateApiVersioningFile by tasks.registering {
|
|
}
|
|
}
|
|
|
|
+// Pufferfish Start
|
|
+tasks.withType<JavaCompile> {
|
|
+ val compilerArgs = options.compilerArgs
|
|
+ compilerArgs.add("--add-modules=jdk.incubator.vector")
|
|
+}
|
|
+// Pufferfish End
|
|
+
|
|
tasks.jar {
|
|
from(generateApiVersioningFile.map { it.outputs.files.singleFile }) {
|
|
into("META-INF/maven/${project.group}/${project.name}")
|
|
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..6fbaf2a232745db0a41394b1c2cc0cc90cefc4ee
|
|
--- /dev/null
|
|
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
|
|
@@ -0,0 +1,161 @@
|
|
+package gg.pufferfish.pufferfish.sentry;
|
|
+
|
|
+import com.google.gson.Gson;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.util.Map;
|
|
+import java.util.TreeMap;
|
|
+import org.apache.logging.log4j.ThreadContext;
|
|
+import org.bukkit.command.Command;
|
|
+import org.bukkit.command.CommandSender;
|
|
+import org.bukkit.entity.Player;
|
|
+import org.bukkit.event.Event;
|
|
+import org.bukkit.event.player.PlayerEvent;
|
|
+import org.bukkit.plugin.Plugin;
|
|
+import org.bukkit.plugin.RegisteredListener;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+
|
|
+public class SentryContext {
|
|
+
|
|
+ private static final Gson GSON = new Gson();
|
|
+
|
|
+ public static void setPluginContext(@Nullable Plugin plugin) {
|
|
+ if (plugin != null) {
|
|
+ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName());
|
|
+ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getDescription().getVersion());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void removePluginContext() {
|
|
+ ThreadContext.remove("pufferfishsentry_pluginname");
|
|
+ ThreadContext.remove("pufferfishsentry_pluginversion");
|
|
+ }
|
|
+
|
|
+ public static void setSenderContext(@Nullable CommandSender sender) {
|
|
+ if (sender != null) {
|
|
+ ThreadContext.put("pufferfishsentry_playername", sender.getName());
|
|
+ if (sender instanceof Player player) {
|
|
+ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void removeSenderContext() {
|
|
+ ThreadContext.remove("pufferfishsentry_playername");
|
|
+ ThreadContext.remove("pufferfishsentry_playerid");
|
|
+ }
|
|
+
|
|
+ public static void setEventContext(Event event, RegisteredListener registration) {
|
|
+ setPluginContext(registration.getPlugin());
|
|
+
|
|
+ try {
|
|
+ // Find the player that was involved with this event
|
|
+ Player player = null;
|
|
+ if (event instanceof PlayerEvent) {
|
|
+ player = ((PlayerEvent) event).getPlayer();
|
|
+ } else {
|
|
+ Class<? extends Event> eventClass = event.getClass();
|
|
+
|
|
+ Field playerField = null;
|
|
+
|
|
+ for (Field field : eventClass.getDeclaredFields()) {
|
|
+ if (field.getType().equals(Player.class)) {
|
|
+ playerField = field;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (playerField != null) {
|
|
+ playerField.setAccessible(true);
|
|
+ player = (Player) playerField.get(event);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (player != null) {
|
|
+ setSenderContext(player);
|
|
+ }
|
|
+ } catch (Exception e) {} // We can't really safely log exceptions.
|
|
+
|
|
+ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event)));
|
|
+ }
|
|
+
|
|
+ public static void removeEventContext() {
|
|
+ removePluginContext();
|
|
+ removeSenderContext();
|
|
+ ThreadContext.remove("pufferfishsentry_eventdata");
|
|
+ }
|
|
+
|
|
+ private static Map<String, String> serializeFields(Object object) {
|
|
+ Map<String, String> fields = new TreeMap<>();
|
|
+ fields.put("_class", object.getClass().getName());
|
|
+ for (Field declaredField : object.getClass().getDeclaredFields()) {
|
|
+ try {
|
|
+ if (Modifier.isStatic(declaredField.getModifiers())) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ String fieldName = declaredField.getName();
|
|
+ if (fieldName.equals("handlers")) {
|
|
+ continue;
|
|
+ }
|
|
+ declaredField.setAccessible(true);
|
|
+ Object value = declaredField.get(object);
|
|
+ if (value != null) {
|
|
+ fields.put(fieldName, value.toString());
|
|
+ } else {
|
|
+ fields.put(fieldName, "<null>");
|
|
+ }
|
|
+ } catch (Exception e) {} // We can't really safely log exceptions.
|
|
+ }
|
|
+ return fields;
|
|
+ }
|
|
+
|
|
+ public static class State {
|
|
+
|
|
+ private Plugin plugin;
|
|
+ private Command command;
|
|
+ private String commandLine;
|
|
+ private Event event;
|
|
+ private RegisteredListener registeredListener;
|
|
+
|
|
+ public Plugin getPlugin() {
|
|
+ return plugin;
|
|
+ }
|
|
+
|
|
+ public void setPlugin(Plugin plugin) {
|
|
+ this.plugin = plugin;
|
|
+ }
|
|
+
|
|
+ public Command getCommand() {
|
|
+ return command;
|
|
+ }
|
|
+
|
|
+ public void setCommand(Command command) {
|
|
+ this.command = command;
|
|
+ }
|
|
+
|
|
+ public String getCommandLine() {
|
|
+ return commandLine;
|
|
+ }
|
|
+
|
|
+ public void setCommandLine(String commandLine) {
|
|
+ this.commandLine = commandLine;
|
|
+ }
|
|
+
|
|
+ public Event getEvent() {
|
|
+ return event;
|
|
+ }
|
|
+
|
|
+ public void setEvent(Event event) {
|
|
+ this.event = event;
|
|
+ }
|
|
+
|
|
+ public RegisteredListener getRegisteredListener() {
|
|
+ return registeredListener;
|
|
+ }
|
|
+
|
|
+ public void setRegisteredListener(RegisteredListener registeredListener) {
|
|
+ this.registeredListener = registeredListener;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..6d266ebf5e52745ad13e90e5754b524383fa9b29
|
|
--- /dev/null
|
|
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
|
|
@@ -0,0 +1,40 @@
|
|
+package gg.pufferfish.pufferfish.simd;
|
|
+
|
|
+import java.util.logging.Level;
|
|
+import java.util.logging.Logger;
|
|
+import jdk.incubator.vector.FloatVector;
|
|
+import jdk.incubator.vector.IntVector;
|
|
+import jdk.incubator.vector.VectorSpecies;
|
|
+
|
|
+/**
|
|
+ * Basically, java is annoying and we have to push this out to its own class.
|
|
+ */
|
|
+@Deprecated
|
|
+public class SIMDChecker {
|
|
+
|
|
+ @Deprecated
|
|
+ public static boolean canEnable(Logger logger) {
|
|
+ try {
|
|
+ if (SIMDDetection.getJavaVersion() != 17 && SIMDDetection.getJavaVersion() != 18 && SIMDDetection.getJavaVersion() != 19) {
|
|
+ return false;
|
|
+ } else {
|
|
+ SIMDDetection.testRun = true;
|
|
+
|
|
+ VectorSpecies<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
|
|
+ VectorSpecies<Float> FSPEC = FloatVector.SPECIES_PREFERRED;
|
|
+
|
|
+ logger.log(Level.INFO, "Max SIMD vector size on this system is " + ISPEC.vectorBitSize() + " bits (int)");
|
|
+ logger.log(Level.INFO, "Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)");
|
|
+
|
|
+ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) {
|
|
+ logger.log(Level.WARNING, "SIMD is not properly supported on this system!");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+ } catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it.
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..fd708554d6dab2ddcd24c3024330b8ebf9462111
|
|
--- /dev/null
|
|
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java
|
|
@@ -0,0 +1,35 @@
|
|
+package gg.pufferfish.pufferfish.simd;
|
|
+
|
|
+import java.util.logging.Logger;
|
|
+
|
|
+@Deprecated
|
|
+public class SIMDDetection {
|
|
+
|
|
+ public static boolean isEnabled = false;
|
|
+ public static boolean versionLimited = false;
|
|
+ public static boolean testRun = false;
|
|
+
|
|
+ @Deprecated
|
|
+ public static boolean canEnable(Logger logger) {
|
|
+ try {
|
|
+ return SIMDChecker.canEnable(logger);
|
|
+ } catch (NoClassDefFoundError | Exception ignored) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Deprecated
|
|
+ public static int getJavaVersion() {
|
|
+ // https://stackoverflow.com/a/2591122
|
|
+ String version = System.getProperty("java.version");
|
|
+ if(version.startsWith("1.")) {
|
|
+ version = version.substring(2, 3);
|
|
+ } else {
|
|
+ int dot = version.indexOf(".");
|
|
+ if(dot != -1) { version = version.substring(0, dot); }
|
|
+ }
|
|
+ version = version.split("-")[0]; // Azul is stupid
|
|
+ return Integer.parseInt(version);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..20ec3b29b0cb4061cc89d635b3929ffe71008e22
|
|
--- /dev/null
|
|
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java
|
|
@@ -0,0 +1,83 @@
|
|
+package gg.pufferfish.pufferfish.simd;
|
|
+
|
|
+import java.awt.Color;
|
|
+import jdk.incubator.vector.FloatVector;
|
|
+import jdk.incubator.vector.IntVector;
|
|
+import jdk.incubator.vector.VectorMask;
|
|
+import jdk.incubator.vector.VectorSpecies;
|
|
+import org.bukkit.map.MapPalette;
|
|
+
|
|
+@Deprecated
|
|
+public class VectorMapPalette {
|
|
+
|
|
+ private static final VectorSpecies<Integer> I_SPEC = IntVector.SPECIES_PREFERRED;
|
|
+ private static final VectorSpecies<Float> F_SPEC = FloatVector.SPECIES_PREFERRED;
|
|
+
|
|
+ @Deprecated
|
|
+ public static void matchColorVectorized(int[] in, byte[] out) {
|
|
+ int speciesLength = I_SPEC.length();
|
|
+ int i;
|
|
+ for (i = 0; i < in.length - speciesLength; i += speciesLength) {
|
|
+ float[] redsArr = new float[speciesLength];
|
|
+ float[] bluesArr = new float[speciesLength];
|
|
+ float[] greensArr = new float[speciesLength];
|
|
+ int[] alphasArr = new int[speciesLength];
|
|
+
|
|
+ for (int j = 0; j < speciesLength; j++) {
|
|
+ alphasArr[j] = (in[i + j] >> 24) & 0xFF;
|
|
+ redsArr[j] = (in[i + j] >> 16) & 0xFF;
|
|
+ greensArr[j] = (in[i + j] >> 8) & 0xFF;
|
|
+ bluesArr[j] = (in[i + j] >> 0) & 0xFF;
|
|
+ }
|
|
+
|
|
+ IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0);
|
|
+ FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0);
|
|
+ FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0);
|
|
+ FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0);
|
|
+ IntVector resultIndex = IntVector.zero(I_SPEC);
|
|
+ VectorMask<Integer> modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff);
|
|
+
|
|
+ modificationMask = modificationMask.and(alphas.lt(128).not());
|
|
+ FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE);
|
|
+
|
|
+ for (int c = 4; c < MapPalette.colors.length; c++) {
|
|
+ // We're using 32-bit floats here because it's 2x faster and nobody will know the difference.
|
|
+ // For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary.
|
|
+ FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed());
|
|
+ FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen());
|
|
+ FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue());
|
|
+
|
|
+ FloatVector rMean = reds.add(compReds).div(2.0f);
|
|
+ FloatVector rDiff = reds.sub(compReds);
|
|
+ FloatVector gDiff = greens.sub(compGreens);
|
|
+ FloatVector bDiff = blues.sub(compBlues);
|
|
+
|
|
+ FloatVector weightR = rMean.div(256.0f).add(2);
|
|
+ FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f);
|
|
+ FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f);
|
|
+
|
|
+ FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff));
|
|
+
|
|
+ // Now we compare to the best distance we've found.
|
|
+ // This mask contains a "1" if better, and a "0" otherwise.
|
|
+ VectorMask<Float> bestDistanceMask = distance.lt(bestDistances);
|
|
+ bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances
|
|
+
|
|
+ // Update the result array
|
|
+ // We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough.
|
|
+ resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results
|
|
+ }
|
|
+
|
|
+ for (int j = 0; j < speciesLength; j++) {
|
|
+ int index = resultIndex.lane(j);
|
|
+ out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // For the final ones, fall back to the regular method
|
|
+ for (; i < in.length; i++) {
|
|
+ out[i] = MapPalette.matchColor(new Color(in[i], true));
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
|
|
index 3a9aaca2e76411a9c27f9f5e0f22d060d5a66d06..9584e245144b561b4f6745b2f26a4f69a6f92891 100644
|
|
--- a/src/main/java/org/bukkit/map/MapPalette.java
|
|
+++ b/src/main/java/org/bukkit/map/MapPalette.java
|
|
@@ -1,6 +1,7 @@
|
|
package org.bukkit.map;
|
|
|
|
import com.google.common.base.Preconditions;
|
|
+import gg.pufferfish.pufferfish.simd.SIMDDetection; // Pufferfish
|
|
import java.awt.Color;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Image;
|
|
@@ -40,7 +41,7 @@ public final class MapPalette {
|
|
}
|
|
|
|
@NotNull
|
|
- static final Color[] colors = {
|
|
+ public static final Color[] colors = { // Pufferfish - public access
|
|
c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0),
|
|
c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29),
|
|
c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86),
|
|
@@ -211,9 +212,15 @@ public final class MapPalette {
|
|
temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth());
|
|
|
|
byte[] result = new byte[temp.getWidth() * temp.getHeight()];
|
|
+ // Pufferfish start
|
|
+ if (!SIMDDetection.isEnabled) {
|
|
for (int i = 0; i < pixels.length; i++) {
|
|
result[i] = matchColor(new Color(pixels[i], true));
|
|
}
|
|
+ } else {
|
|
+ gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result);
|
|
+ }
|
|
+ // Pufferfish end
|
|
return result;
|
|
}
|
|
|
|
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
|
index 2b8308989fce7f8a16907f8711b362e671fdbfb6..bd4d1a40f53784662174d426533ef4b5433a15b7 100644
|
|
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
|
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
|
@@ -584,7 +584,9 @@ public final class SimplePluginManager implements PluginManager {
|
|
|
|
// Paper start
|
|
private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
|
|
server.getLogger().log(Level.SEVERE, msg, ex);
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
|
|
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));
|
|
}
|
|
// Paper end
|
|
@@ -654,9 +656,11 @@ public final class SimplePluginManager implements PluginManager {
|
|
));
|
|
}
|
|
} catch (Throwable ex) {
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish
|
|
// Paper start - error reporting
|
|
String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
|
|
server.getLogger().log(Level.SEVERE, msg, ex);
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish
|
|
if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop
|
|
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event)));
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
|
index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..301e82369603f3dd6e6c1bd380da4bacacd7ef6c 100644
|
|
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
|
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
|
@@ -336,7 +336,13 @@ public final class JavaPluginLoader implements PluginLoader {
|
|
try {
|
|
jPlugin.setEnabled(true);
|
|
} catch (Throwable ex) {
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
|
|
server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
|
|
+ // Paper start - Disable plugins that fail to load
|
|
+ this.server.getPluginManager().disablePlugin(jPlugin);
|
|
+ return;
|
|
+ // Paper end
|
|
}
|
|
|
|
// Perhaps abort here, rather than continue going, but as it stands,
|
|
@@ -361,7 +367,9 @@ public final class JavaPluginLoader implements PluginLoader {
|
|
try {
|
|
jPlugin.setEnabled(false);
|
|
} catch (Throwable ex) {
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
|
|
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
|
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
|
|
}
|
|
|
|
if (cloader instanceof PluginClassLoader) {
|
|
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
|
index 1758e8a89c85eea8c2161ddcb5b0e745151a1f5e..fe21d31b463317eb90d58cbca5f098958ca93938 100644
|
|
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
|
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
|
@@ -48,6 +48,8 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|
private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper
|
|
public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper
|
|
|
|
+ private boolean closed = false; // Pufferfish
|
|
+
|
|
static {
|
|
ClassLoader.registerAsParallelCapable();
|
|
}
|
|
@@ -183,6 +185,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|
throw new ClassNotFoundException(name);
|
|
}
|
|
|
|
+ public boolean _airplane_hasClass(@NotNull String name) { return this.classes.containsKey(name); } // Pufferfish
|
|
@Override
|
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
|
if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
|
|
@@ -190,7 +193,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|
}
|
|
Class<?> result = classes.get(name);
|
|
|
|
- if (result == null) {
|
|
+ if (result == null && !this.closed) { // Pufferfish
|
|
String path = name.replace('.', '/').concat(".class");
|
|
JarEntry entry = jar.getJarEntry(path);
|
|
|
|
@@ -237,6 +240,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|
this.setClass(name, result); // Paper
|
|
}
|
|
|
|
+ if (result == null) throw new ClassNotFoundException(name); // Pufferfish
|
|
return result;
|
|
}
|
|
|
|
@@ -251,6 +255,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|
// Paper end
|
|
super.close();
|
|
} finally {
|
|
+ this.closed = true; // Pufferfish
|
|
jar.close();
|
|
}
|
|
}
|