include pufferfish patches

This commit is contained in:
granny
2023-03-22 05:27:54 -07:00
parent 9cda2e740b
commit a0077699e6
362 changed files with 4983 additions and 751 deletions

View File

@@ -0,0 +1,527 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Raneri <kevin.raneri@gmail.com>
Date: Tue, 9 Nov 2021 14:01:56 -0500
Subject: [PATCH] Pufferfish API Changes
Pufferfish
Copyright (C) 2022 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();
}
}

View File

@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 4 Jan 2022 23:05:41 -0600
Subject: [PATCH] Fix pufferfish issues
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
index 2cb81e6d253d70388da15c9d07b630277d486c70..fa7229ae5e00e36b0dc8b4cf15d3c99892cc3291 100644
--- a/src/test/java/org/bukkit/AnnotationTest.java
+++ b/src/test/java/org/bukkit/AnnotationTest.java
@@ -47,6 +47,10 @@ public class AnnotationTest {
"org/bukkit/plugin/java/PluginClassLoader",
// Generic functional interface
"org/bukkit/util/Consumer",
+ // Purpur start
+ "gg/pufferfish/pufferfish/sentry/SentryContext",
+ "gg/pufferfish/pufferfish/sentry/SentryContext$State",
+ // Purpur end
// Paper start
"io/papermc/paper/util/TransformingRandomAccessList",
"io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator",

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Build System Changes
diff --git a/build.gradle.kts b/build.gradle.kts
index 097b62f538970013d8297f9f2972d1d2b8a088a3..1d1f5147827466bd3d032d6ea084e75b1b9fa7ad 100644
index b83e2c5a0a094002d12aee55ec0cf8d12bf33f3e..b5835fa536f90b7f88a5ee4df78733cf43e1cb23 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -97,6 +97,8 @@ tasks.jar {
@@ -105,6 +105,8 @@ tasks.jar {
}
tasks.withType<Javadoc> {

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Purpur client support
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 660f28e371176c62e38a84b187958aceb235c8e3..9306bd672a1c3aae9759e9d8cd434245be066749 100644
index b5fd857896b3afcfa69cce55cbc2696dd625f805..7ff5d4554be858e6bad5440b8847e3f21523f796 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3000,4 +3000,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Allow inventory resizing
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java
index 6957d5b88c549f08dd3afe272f018be122f3a4a6..c5824f7fb988ed68feb8758ce6db748218f10b9b 100644
index 35aac79a7c58d00e6b3c6c042b291093c9c7af71..7fa8909f07ce768654b9ea7c42c4913b7e2593b7 100644
--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java
+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java
@@ -155,7 +155,7 @@ public enum InventoryType {

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] AFK API
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 9306bd672a1c3aae9759e9d8cd434245be066749..8dcb8bd95cad85f80991b0f6ae0439ab070b202e 100644
index 7ff5d4554be858e6bad5440b8847e3f21523f796..04b31e42865469f9760db061607a803787fbadf3 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3008,5 +3008,24 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Player invulnerabilities
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 8dcb8bd95cad85f80991b0f6ae0439ab070b202e..6d44768ac23b80dc170e242f040c5bcaabd0510f 100644
index 04b31e42865469f9760db061607a803787fbadf3..819aa1f1e2c2c32510973e6fc9d8561366230851 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3027,5 +3027,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM

View File

@@ -50,7 +50,7 @@ index 3c5e90f039f0d2991be442168703526405e18e3d..df992c41d736ee4e89773c2621d261d6
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index 449d6e1995eedbfaeffdc5d1f1c2295378006aa8..11261c659e3a378f468f4a19e2c24c1bb1f95a2b 100644
index cd487177f6e391e114c394cd736796e20e0e8982..e5f129b7bbf4257e6be056af71c4e26a01ffd658 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -17,6 +17,18 @@ import org.bukkit.inventory.meta.ItemMeta;

View File

@@ -260,7 +260,7 @@ index bb249f7d54fd90d63f609eedf0bbb463f1aa96f1..a38863ebd363f54994753937a10e0410
/**
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 6d44768ac23b80dc170e242f040c5bcaabd0510f..c09c8e2c32b699301ae66b467582511e518bf3d3 100644
index 819aa1f1e2c2c32510973e6fc9d8561366230851..12b659d13ce336cca52dd704caa7c20366cfe6d9 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3048,5 +3048,75 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Add death screen API
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index c09c8e2c32b699301ae66b467582511e518bf3d3..134a573fd933dce1002d9e3b62dafce83b1d6aea 100644
index 12b659d13ce336cca52dd704caa7c20366cfe6d9..08b5f448e92add21f9f9797d9cea3ac60581dff5 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3118,5 +3118,21 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Add log suppression for LibraryLoader
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..f1e58639213be0c43cd2ff090b625e7d0a67e8be 100644
index 301e82369603f3dd6e6c1bd380da4bacacd7ef6c..0c6ca7588fb3d6b6497ddf032fe75e5c6c9719e5 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -55,6 +55,7 @@ public final class JavaPluginLoader implements PluginLoader {