Prepare for 1.20.3 dev
This commit is contained in:
parent
931781c220
commit
2a1ace0cf2
1514 changed files with 528 additions and 530 deletions
250
patches/unapplied/api/0003-Test-changes.patch
Normal file
250
patches/unapplied/api/0003-Test-changes.patch
Normal file
|
@ -0,0 +1,250 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 17 Mar 2019 23:04:30 +0000
|
||||
Subject: [PATCH] Test changes
|
||||
|
||||
- Allow use of TYPE_USE annotations
|
||||
- Ignore package-private methods for nullability annotations
|
||||
- Add excludes for classes which don't pass
|
||||
- Disable stupid BukkitMirrorTest
|
||||
|
||||
Co-authored-by: Riley Park <rileysebastianpark@gmail.com>
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index d86ee6acb78d249424c5df98a851178c0f62eec1..75bfb0ab8049ebbb52240abf661d469de5526767 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -106,6 +106,12 @@ tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
+// Paper start - compile tests with -parameters for better junit parameterized test names
|
||||
+tasks.compileTestJava {
|
||||
+ options.compilerArgs.add("-parameters")
|
||||
+}
|
||||
+// Paper end
|
||||
+
|
||||
// Paper start
|
||||
val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
|
||||
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
|
||||
diff --git a/src/test/java/io/papermc/paper/testing/EmptyTag.java b/src/test/java/io/papermc/paper/testing/EmptyTag.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..77154095cfb8b259bdb318e8ff40cb6f559ebc18
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/testing/EmptyTag.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package io.papermc.paper.testing;
|
||||
+
|
||||
+import java.util.Collections;
|
||||
+import java.util.Set;
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Tag;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public record EmptyTag(NamespacedKey key) implements Tag<Keyed> {
|
||||
+
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public EmptyTag() {
|
||||
+ this(NamespacedKey.randomKey());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull NamespacedKey getKey() {
|
||||
+ return this.key;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isTagged(@NotNull final Keyed item) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Set<Keyed> getValues() {
|
||||
+ return Collections.emptySet();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
index 64e7aef6220097edefdff3b98a771b988365930d..abadff47166722fdc756afdbc6ac7242b6bd4fb0 100644
|
||||
--- a/src/test/java/org/bukkit/AnnotationTest.java
|
||||
+++ b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
@@ -29,7 +29,13 @@ public class AnnotationTest {
|
||||
"Lorg/jetbrains/annotations/Nullable;",
|
||||
"Lorg/jetbrains/annotations/NotNull;",
|
||||
"Lorg/jetbrains/annotations/Contract;",
|
||||
- "Lorg/bukkit/UndefinedNullability;"
|
||||
+ "Lorg/bukkit/UndefinedNullability;",
|
||||
+ // Paper start
|
||||
+ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;",
|
||||
+ "Lorg/checkerframework/checker/nullness/qual/NonNull;",
|
||||
+ "Lorg/checkerframework/checker/nullness/qual/Nullable;",
|
||||
+ "Lorg/checkerframework/checker/nullness/qual/PolyNull;",
|
||||
+ // Paper end
|
||||
};
|
||||
|
||||
private static final String[] EXCLUDED_CLASSES = {
|
||||
@@ -40,7 +46,17 @@ public class AnnotationTest {
|
||||
"org/bukkit/util/io/Wrapper",
|
||||
"org/bukkit/plugin/java/PluginClassLoader",
|
||||
// Generic functional interface
|
||||
- "org/bukkit/util/Consumer"
|
||||
+ "org/bukkit/util/Consumer",
|
||||
+ // Paper start
|
||||
+ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull
|
||||
+ "co/aikar/timings/TimingHistory$2",
|
||||
+ "co/aikar/timings/TimingHistory$2$1",
|
||||
+ "co/aikar/timings/TimingHistory$2$1$1",
|
||||
+ "co/aikar/timings/TimingHistory$2$1$2",
|
||||
+ "co/aikar/timings/TimingHistory$3",
|
||||
+ "co/aikar/timings/TimingHistory$4",
|
||||
+ "co/aikar/timings/TimingHistoryEntry$1"
|
||||
+ // Paper end
|
||||
};
|
||||
|
||||
@Test
|
||||
@@ -67,14 +83,40 @@ public class AnnotationTest {
|
||||
}
|
||||
|
||||
if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) {
|
||||
+ // Paper start - Allow use of TYPE_USE annotations
|
||||
+ boolean warn = true;
|
||||
+ if (isWellAnnotated(method.visibleTypeAnnotations)) {
|
||||
+ warn = false;
|
||||
+ } else if (method.invisibleTypeAnnotations != null) {
|
||||
+ dance: for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) {
|
||||
+ final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef);
|
||||
+ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_RETURN && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) {
|
||||
+ warn = false;
|
||||
+ break dance; // cha cha real smooth
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (warn)
|
||||
+ // Paper end
|
||||
warn(errors, clazz, method, "return value");
|
||||
}
|
||||
|
||||
Type[] paramTypes = Type.getArgumentTypes(method.desc);
|
||||
List<ParameterNode> parameters = method.parameters;
|
||||
|
||||
+ dancing: // Paper
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
if (mustBeAnnotated(paramTypes[i]) ^ isWellAnnotated(method.invisibleParameterAnnotations == null ? null : method.invisibleParameterAnnotations[i])) {
|
||||
+ // Paper start
|
||||
+ if (method.invisibleTypeAnnotations != null) {
|
||||
+ for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) {
|
||||
+ final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef);
|
||||
+ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) {
|
||||
+ continue dancing;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Allow use of TYPE_USE annotations
|
||||
ParameterNode paramNode = parameters == null ? null : parameters.get(i);
|
||||
String paramName = paramNode == null ? null : paramNode.name;
|
||||
|
||||
@@ -91,13 +133,18 @@ public class AnnotationTest {
|
||||
|
||||
Collections.sort(errors);
|
||||
|
||||
- System.out.println(errors.size() + " missing annotation(s):");
|
||||
+ StringBuilder builder = new StringBuilder()
|
||||
+ .append("There ")
|
||||
+ .append(errors.size() != 1 ? "are " : "is ")
|
||||
+ .append(errors.size())
|
||||
+ .append(" missing annotation")
|
||||
+ .append(errors.size() != 1 ? "s:\n" : ":\n");
|
||||
+
|
||||
for (String message : errors) {
|
||||
- System.out.print("\t");
|
||||
- System.out.println(message);
|
||||
+ builder.append("\t").append(message).append("\n");
|
||||
}
|
||||
|
||||
- fail("There " + errors.size() + " are missing annotation(s)");
|
||||
+ fail(builder.toString());
|
||||
}
|
||||
|
||||
private static void collectClasses(@NotNull File from, @NotNull Map<String, ClassNode> to) throws IOException {
|
||||
@@ -140,6 +187,11 @@ public class AnnotationTest {
|
||||
// Exceptions are excluded
|
||||
return false;
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (isInternal(clazz.invisibleAnnotations)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
for (String excludedClass : EXCLUDED_CLASSES) {
|
||||
if (excludedClass.equals(clazz.name)) {
|
||||
@@ -152,7 +204,7 @@ public class AnnotationTest {
|
||||
|
||||
private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map<String, ClassNode> allClasses) {
|
||||
// Exclude private, synthetic and deprecated methods
|
||||
- if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0) {
|
||||
+ if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -170,11 +222,30 @@ public class AnnotationTest {
|
||||
if ("<init>".equals(method.name) && isAnonymous(clazz)) {
|
||||
return false;
|
||||
}
|
||||
+ // Paper start
|
||||
+ if (isInternal(method.invisibleAnnotations)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
return true;
|
||||
}
|
||||
+ // Paper start
|
||||
+ private static boolean isInternal(List<? extends AnnotationNode> annotations) {
|
||||
+ if (annotations == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ for (AnnotationNode node : annotations) {
|
||||
+ if (node.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;")) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- private static boolean isWellAnnotated(@Nullable List<AnnotationNode> annotations) {
|
||||
+ private static boolean isWellAnnotated(@Nullable List<? extends AnnotationNode> annotations) { // Paper
|
||||
if (annotations == null) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/BukkitMirrorTest.java b/src/test/java/org/bukkit/BukkitMirrorTest.java
|
||||
index 89ca06ebecdaadd5dfc7bc74473ca15ad36f6eff..5974ceea58940e1799f3589eac0e39b925a42c3b 100644
|
||||
--- a/src/test/java/org/bukkit/BukkitMirrorTest.java
|
||||
+++ b/src/test/java/org/bukkit/BukkitMirrorTest.java
|
||||
@@ -9,6 +9,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
+@org.junit.jupiter.api.Disabled // Paper
|
||||
public class BukkitMirrorTest {
|
||||
|
||||
public static Stream<Arguments> data() {
|
||||
diff --git a/src/test/java/org/bukkit/support/TestServer.java b/src/test/java/org/bukkit/support/TestServer.java
|
||||
index 79173d6ed844f1e640e3aa745a9b560ec5e6a2bc..73ec679ac0d1f398b417bd174b47f9af93351e27 100644
|
||||
--- a/src/test/java/org/bukkit/support/TestServer.java
|
||||
+++ b/src/test/java/org/bukkit/support/TestServer.java
|
||||
@@ -61,6 +61,11 @@ public final class TestServer {
|
||||
UnsafeValues unsafeValues = mock(withSettings().stubOnly());
|
||||
when(instance.getUnsafe()).thenReturn(unsafeValues);
|
||||
|
||||
+ // Paper start - testing changes
|
||||
+ when(instance.getTag(anyString(), any(NamespacedKey.class), any())).thenAnswer(ignored -> new io.papermc.paper.testing.EmptyTag());
|
||||
+ when(instance.getScoreboardCriteria(anyString())).thenReturn(null);
|
||||
+ // Paper end - testing changes
|
||||
+
|
||||
Bukkit.setServer(instance);
|
||||
}
|
||||
|
251
patches/unapplied/api/0004-Code-Generation.patch
Normal file
251
patches/unapplied/api/0004-Code-Generation.patch
Normal file
|
@ -0,0 +1,251 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 26 May 2023 18:14:44 -0700
|
||||
Subject: [PATCH] Code Generation
|
||||
|
||||
Currently includes generated key holder classes for types
|
||||
used in the Registry Modification API
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 75bfb0ab8049ebbb52240abf661d469de5526767..87e4ee95a8da287b02c13fac5f24f66902bc84c9 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
+ idea // Paper
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -46,6 +47,22 @@ dependencies {
|
||||
testImplementation("org.ow2.asm:asm-tree:9.5")
|
||||
}
|
||||
|
||||
+// Paper start
|
||||
+val generatedApiPath: java.nio.file.Path = rootProject.projectDir.toPath().resolve("paper-api-generator/generated")
|
||||
+idea {
|
||||
+ module {
|
||||
+ generatedSourceDirs.add(generatedApiPath.toFile())
|
||||
+ }
|
||||
+}
|
||||
+sourceSets {
|
||||
+ main {
|
||||
+ java {
|
||||
+ srcDir(generatedApiPath)
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+// Paper end
|
||||
+
|
||||
configure<PublishingExtension> {
|
||||
publications.create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
@@ -122,3 +139,14 @@ tasks.check {
|
||||
dependsOn(scanJar)
|
||||
}
|
||||
// Paper end
|
||||
+// Paper start
|
||||
+val scanJarForOldGeneratedCode = tasks.register("scanJarForOldGeneratedCode", io.papermc.paperweight.tasks.ScanJarForOldGeneratedCode::class) {
|
||||
+ mcVersion.set(providers.gradleProperty("mcVersion"))
|
||||
+ annotation.set("Lio/papermc/paper/generated/GeneratedFrom;")
|
||||
+ jarToScan.set(tasks.jar.flatMap { it.archiveFile })
|
||||
+ classpath.from(configurations.compileClasspath)
|
||||
+}
|
||||
+tasks.check {
|
||||
+ dependsOn(scanJarForOldGeneratedCode)
|
||||
+}
|
||||
+// Paper end
|
||||
diff --git a/src/main/java/io/papermc/paper/generated/GeneratedFrom.java b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2512dba27edfdccbc4430815b6cba048e3d93484
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java
|
||||
@@ -0,0 +1,21 @@
|
||||
+package io.papermc.paper.generated;
|
||||
+
|
||||
+import java.lang.annotation.Documented;
|
||||
+import java.lang.annotation.ElementType;
|
||||
+import java.lang.annotation.Retention;
|
||||
+import java.lang.annotation.RetentionPolicy;
|
||||
+import java.lang.annotation.Target;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+/**
|
||||
+ * Used to mark classes which are generated from
|
||||
+ * a specific version of minecraft.
|
||||
+ */
|
||||
+@ApiStatus.Internal
|
||||
+@Documented
|
||||
+@Retention(RetentionPolicy.RUNTIME)
|
||||
+@Target(ElementType.TYPE)
|
||||
+public @interface GeneratedFrom {
|
||||
+
|
||||
+ String value();
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5251f922d2d14da35f61098c11694371f591cd2a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
@@ -0,0 +1,61 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import net.kyori.adventure.key.Keyed;
|
||||
+import org.bukkit.GameEvent;
|
||||
+import org.bukkit.block.Biome;
|
||||
+import org.bukkit.generator.structure.StructureType;
|
||||
+import org.bukkit.inventory.meta.trim.TrimMaterial;
|
||||
+import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+import static io.papermc.paper.registry.RegistryKeyImpl.create;
|
||||
+
|
||||
+/**
|
||||
+ * Identifier for a specific registry. For use with
|
||||
+ * {@link TypedKey} and the registry modification API.
|
||||
+ * <p>
|
||||
+ * There are 2 types of registries, identified as "built-in"
|
||||
+ * or "data-driven". The former are not changeable by datapacks (which
|
||||
+ * doesn't necessarily mean they aren't changeable in the API) and
|
||||
+ * are loaded first. "Data-driven" registries are all created by
|
||||
+ * reading in data from the vanilla and other datapacks.
|
||||
+ *
|
||||
+ * @param <T> the value type
|
||||
+ */
|
||||
+@SuppressWarnings("unused")
|
||||
+@ApiStatus.Experimental
|
||||
+public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
|
||||
+
|
||||
+ /* ******************* *
|
||||
+ * Built-in Registries *
|
||||
+ * ******************* */
|
||||
+ /**
|
||||
+ * Built-in registry for game events
|
||||
+ * @see io.papermc.paper.registry.keys.GameEventKeys
|
||||
+ */
|
||||
+ RegistryKey<GameEvent> GAME_EVENT = create("game_event");
|
||||
+ /**
|
||||
+ * Built-in registry for structure types.
|
||||
+ * @see io.papermc.paper.registry.keys.StructureTypeKeys
|
||||
+ */
|
||||
+ RegistryKey<StructureType> STRUCTURE_TYPE = create("worldgen/structure_type");
|
||||
+
|
||||
+ /* ********************** *
|
||||
+ * Data-driven Registries *
|
||||
+ * ********************** */
|
||||
+ /**
|
||||
+ * Data-driven registry for structure types.
|
||||
+ * @see io.papermc.paper.registry.keys.BiomeKeys
|
||||
+ */
|
||||
+ RegistryKey<Biome> BIOME = create("worldgen/biome");
|
||||
+ /**
|
||||
+ * Data-driven registry for structure types.
|
||||
+ * @see io.papermc.paper.registry.keys.TrimMaterialKeys
|
||||
+ */
|
||||
+ RegistryKey<TrimMaterial> TRIM_MATERIAL = create("trim_material");
|
||||
+ /**
|
||||
+ * Data-driven registry for structure types.
|
||||
+ * @see io.papermc.paper.registry.keys.TrimPatternKeys
|
||||
+ */
|
||||
+ RegistryKey<TrimPattern> TRIM_PATTERN = create("trim_pattern");
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9ad300fa1668cb59bbd85ff8091591db69b8c9dc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java
|
||||
@@ -0,0 +1,19 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import com.google.common.collect.Sets;
|
||||
+import java.util.Set;
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import org.intellij.lang.annotations.Subst;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+record RegistryKeyImpl<T>(@NotNull Key key) implements RegistryKey<T> {
|
||||
+
|
||||
+ static final Set<RegistryKey<?>> REGISTRY_KEYS = Sets.newIdentityHashSet();
|
||||
+
|
||||
+ static <T> RegistryKey<T> create(@Subst("some_key") final String key) {
|
||||
+ final RegistryKey<T> registryKey = new RegistryKeyImpl<>(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||
+ REGISTRY_KEYS.add(registryKey);
|
||||
+ return registryKey;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..271454cd1b92ada4301025b57348ea77da9116a1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/TypedKey.java
|
||||
@@ -0,0 +1,44 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import net.kyori.adventure.key.Keyed;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a key for a value in a specific registry.
|
||||
+ *
|
||||
+ * @param <T> the value type for the registry
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+public sealed interface TypedKey<T> extends Keyed permits TypedKeyImpl {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the key for the value in the registry.
|
||||
+ *
|
||||
+ * @return the value's key
|
||||
+ */
|
||||
+ @Override
|
||||
+ @NotNull Key key();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the registry key for the value this key
|
||||
+ * represents.
|
||||
+ *
|
||||
+ * @return the registry key
|
||||
+ */
|
||||
+ @NotNull RegistryKey<T> registryKey();
|
||||
+
|
||||
+ /**
|
||||
+ * Create a typed key from a key and a registry key.
|
||||
+ *
|
||||
+ * @param registryKey the registry this key is for
|
||||
+ * @param key the key for the value in the registry
|
||||
+ * @param <T> value type
|
||||
+ * @return a new key for the value key and registry key
|
||||
+ */
|
||||
+ @ApiStatus.Experimental
|
||||
+ static <T extends Keyed> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
|
||||
+ return new TypedKeyImpl<>(key, registryKey);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3c3fd73f7742bb8602e2f9164dd4c1208a412255
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
|
||||
@@ -0,0 +1,8 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import net.kyori.adventure.key.Keyed;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+record TypedKeyImpl<T extends Keyed>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java
|
||||
index 2365a8c620be709b280fb08855752bb0995838fc..b63e24b3c4d2f1a08e39434caa527bb2e0edea22 100644
|
||||
--- a/src/main/java/org/bukkit/MinecraftExperimental.java
|
||||
+++ b/src/main/java/org/bukkit/MinecraftExperimental.java
|
||||
@@ -24,4 +24,5 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
})
|
||||
@ApiStatus.Internal
|
||||
public @interface MinecraftExperimental {
|
||||
+ String value() default ""; // Paper
|
||||
}
|
19
patches/unapplied/api/0005-Add-FastUtil-to-Bukkit.patch
Normal file
19
patches/unapplied/api/0005-Add-FastUtil-to-Bukkit.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 1 Apr 2016 00:02:47 -0400
|
||||
Subject: [PATCH] Add FastUtil to Bukkit
|
||||
|
||||
Doesn't expose to plugins, just allows Paper-API to use it for optimization
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 87e4ee95a8da287b02c13fac5f24f66902bc84c9..2b91ac7b5bc9fa7fb2ab64a80fd2707cb8d3f01d 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -23,6 +23,7 @@ dependencies {
|
||||
api("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
isTransitive = false // includes junit
|
||||
}
|
||||
+ api("it.unimi.dsi:fastutil:8.5.6")
|
||||
// Paper end
|
||||
|
||||
compileOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
5035
patches/unapplied/api/0006-Adventure.patch
Normal file
5035
patches/unapplied/api/0006-Adventure.patch
Normal file
File diff suppressed because it is too large
Load diff
28
patches/unapplied/api/0007-Paper-Utils.patch
Normal file
28
patches/unapplied/api/0007-Paper-Utils.patch
Normal file
|
@ -0,0 +1,28 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 23 Feb 2019 11:26:21 -0500
|
||||
Subject: [PATCH] Paper Utils
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9db0056ab94145819628b3ad8d8d26130d117fcf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java
|
||||
@@ -0,0 +1,16 @@
|
||||
+package com.destroystokyo.paper.util;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class SneakyThrow {
|
||||
+
|
||||
+ public static void sneaky(@NotNull Throwable exception) {
|
||||
+ SneakyThrow.<RuntimeException>throwSneaky(exception);
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ private static <T extends Throwable> void throwSneaky(@NotNull Throwable exception) throws T {
|
||||
+ throw (T) exception;
|
||||
+ }
|
||||
+
|
||||
+}
|
370
patches/unapplied/api/0008-Use-ASM-for-event-executors.patch
Normal file
370
patches/unapplied/api/0008-Use-ASM-for-event-executors.patch
Normal file
|
@ -0,0 +1,370 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Thu, 3 Mar 2016 13:20:33 -0700
|
||||
Subject: [PATCH] Use ASM for event executors.
|
||||
|
||||
Uses method handles for private or static methods.
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index acb27334da8245657a113a69faee6f6b19dd3110..3a4d5cc766095cbb83868ccb99423f10e3a07289 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -43,6 +43,9 @@ dependencies {
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-plain")
|
||||
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
|
||||
+
|
||||
+ implementation("org.ow2.asm:asm:9.4")
|
||||
+ implementation("org.ow2.asm:asm-commons:9.4")
|
||||
// Paper end
|
||||
|
||||
compileOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
|
||||
@@ -0,0 +1,42 @@
|
||||
+package com.destroystokyo.paper.event.executor;
|
||||
+
|
||||
+import java.lang.invoke.MethodHandle;
|
||||
+import java.lang.invoke.MethodHandles;
|
||||
+import java.lang.reflect.Method;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.SneakyThrow;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.EventException;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class MethodHandleEventExecutor implements EventExecutor {
|
||||
+ private final Class<? extends Event> eventClass;
|
||||
+ private final MethodHandle handle;
|
||||
+
|
||||
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
|
||||
+ this.eventClass = eventClass;
|
||||
+ this.handle = handle;
|
||||
+ }
|
||||
+
|
||||
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
||||
+ this.eventClass = eventClass;
|
||||
+ try {
|
||||
+ m.setAccessible(true);
|
||||
+ this.handle = MethodHandles.lookup().unreflect(m);
|
||||
+ } catch (IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to set accessible", e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ try {
|
||||
+ handle.invoke(listener, event);
|
||||
+ } catch (Throwable t) {
|
||||
+ SneakyThrow.sneaky(t);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c83672427324bd068ed52916f700b68446a226f6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package com.destroystokyo.paper.event.executor;
|
||||
+
|
||||
+import java.lang.invoke.MethodHandle;
|
||||
+import java.lang.invoke.MethodHandles;
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.SneakyThrow;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.EventException;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class StaticMethodHandleEventExecutor implements EventExecutor {
|
||||
+ private final Class<? extends Event> eventClass;
|
||||
+ private final MethodHandle handle;
|
||||
+
|
||||
+ public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
||||
+ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
|
||||
+ Preconditions.checkArgument(eventClass != null, "eventClass is null");
|
||||
+ this.eventClass = eventClass;
|
||||
+ try {
|
||||
+ m.setAccessible(true);
|
||||
+ this.handle = MethodHandles.lookup().unreflect(m);
|
||||
+ } catch (IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to set accessible", e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ try {
|
||||
+ handle.invoke(event);
|
||||
+ } catch (Throwable throwable) {
|
||||
+ SneakyThrow.sneaky(throwable);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..084c31af1a7ba32bb4c3dc8f16f67fd09ce0b6a4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
|
||||
@@ -0,0 +1,54 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.util.concurrent.atomic.AtomicInteger;
|
||||
+
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.objectweb.asm.ClassWriter;
|
||||
+import org.objectweb.asm.Type;
|
||||
+import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
+
|
||||
+import static org.objectweb.asm.Opcodes.*;
|
||||
+
|
||||
+public class ASMEventExecutorGenerator {
|
||||
+
|
||||
+ private static final String EXECUTE_DESCRIPTOR = "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V";
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) {
|
||||
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
+ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)});
|
||||
+ // Generate constructor
|
||||
+ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null), ACC_PUBLIC, "<init>", "()V");
|
||||
+ methodGenerator.loadThis();
|
||||
+ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // Invoke the super class (Object) constructor
|
||||
+ methodGenerator.returnValue();
|
||||
+ methodGenerator.endMethod();
|
||||
+ // Generate the execute method
|
||||
+ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR, null, null), ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR);
|
||||
+ methodGenerator.loadArg(0);
|
||||
+ methodGenerator.checkCast(Type.getType(m.getDeclaringClass()));
|
||||
+ methodGenerator.loadArg(1);
|
||||
+ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0]));
|
||||
+ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface());
|
||||
+ // The only purpose of this switch statement is to generate the correct pop instruction, should the event handler method return something other than void.
|
||||
+ // Non-void event handlers will be unsupported in a future release.
|
||||
+ switch (Type.getType(m.getReturnType()).getSize()) {
|
||||
+ // case 0 is omitted because the only type that has size 0 is void - no pop instruction needed.
|
||||
+ case 1 -> methodGenerator.pop(); // handles reference types and most primitives
|
||||
+ case 2 -> methodGenerator.pop2(); // handles long and double
|
||||
+ }
|
||||
+ methodGenerator.returnValue();
|
||||
+ methodGenerator.endMethod();
|
||||
+ writer.visitEnd();
|
||||
+ return writer.toByteArray();
|
||||
+ }
|
||||
+
|
||||
+ public static AtomicInteger NEXT_ID = new AtomicInteger(1);
|
||||
+ @NotNull
|
||||
+ public static String generateName() {
|
||||
+ int id = NEXT_ID.getAndIncrement();
|
||||
+ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
|
||||
@@ -0,0 +1,34 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public interface ClassDefiner {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if the defined classes can bypass access checks
|
||||
+ *
|
||||
+ * @return if classes bypass access checks
|
||||
+ */
|
||||
+ public default boolean isBypassAccessChecks() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Define a class
|
||||
+ *
|
||||
+ * @param parentLoader the parent classloader
|
||||
+ * @param name the name of the class
|
||||
+ * @param data the class data to load
|
||||
+ * @return the defined class
|
||||
+ * @throws ClassFormatError if the class data is invalid
|
||||
+ * @throws NullPointerException if any of the arguments are null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data);
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static ClassDefiner getInstance() {
|
||||
+ return SafeClassDefiner.INSTANCE;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ac99477e9f2c08041aeff31abc1d1edee58d0a67
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
|
||||
@@ -0,0 +1,66 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ConcurrentMap;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import com.google.common.collect.MapMaker;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.objectweb.asm.Type;
|
||||
+
|
||||
+public class SafeClassDefiner implements ClassDefiner {
|
||||
+ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
|
||||
+
|
||||
+ private SafeClassDefiner() {}
|
||||
+
|
||||
+ private final ConcurrentMap<ClassLoader, GeneratedClassLoader> loaders = new MapMaker().weakKeys().makeMap();
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) {
|
||||
+ GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
|
||||
+ synchronized (loader.getClassLoadingLock(name)) {
|
||||
+ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
|
||||
+ Class<?> c = loader.define(name, data);
|
||||
+ assert c.getName().equals(name);
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class GeneratedClassLoader extends ClassLoader {
|
||||
+ static {
|
||||
+ ClassLoader.registerAsParallelCapable();
|
||||
+ }
|
||||
+
|
||||
+ protected GeneratedClassLoader(@NotNull ClassLoader parent) {
|
||||
+ super(parent);
|
||||
+ }
|
||||
+
|
||||
+ private Class<?> define(@NotNull String name, byte[] data) {
|
||||
+ synchronized (getClassLoadingLock(name)) {
|
||||
+ assert !hasClass(name);
|
||||
+ Class<?> c = defineClass(name, data, 0, data.length);
|
||||
+ resolveClass(c);
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public Object getClassLoadingLock(@NotNull String name) {
|
||||
+ return super.getClassLoadingLock(name);
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasClass(@NotNull String name) {
|
||||
+ synchronized (getClassLoadingLock(name)) {
|
||||
+ try {
|
||||
+ Class.forName(name);
|
||||
+ return true;
|
||||
+ } catch (ClassNotFoundException e) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
@@ -5,9 +5,75 @@ import org.bukkit.event.EventException;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
+// Paper start
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ConcurrentMap;
|
||||
+import java.util.function.Function;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor;
|
||||
+import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor;
|
||||
+import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator;
|
||||
+import com.destroystokyo.paper.event.executor.asm.ClassDefiner;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+// Paper end
|
||||
+
|
||||
/**
|
||||
* Interface which defines the class for event call backs to plugins
|
||||
*/
|
||||
public interface EventExecutor {
|
||||
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException;
|
||||
+
|
||||
+ // Paper start
|
||||
+ ConcurrentMap<Method, Class<? extends EventExecutor>> eventExecutorMap = new ConcurrentHashMap<Method, Class<? extends EventExecutor>>() {
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Class<? extends EventExecutor> computeIfAbsent(@NotNull Method key, @NotNull Function<? super Method, ? extends Class<? extends EventExecutor>> mappingFunction) {
|
||||
+ Class<? extends EventExecutor> executorClass = get(key);
|
||||
+ if (executorClass != null)
|
||||
+ return executorClass;
|
||||
+
|
||||
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
+ synchronized (key) {
|
||||
+ executorClass = get(key);
|
||||
+ if (executorClass != null)
|
||||
+ return executorClass;
|
||||
+
|
||||
+ return super.computeIfAbsent(key, mappingFunction);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static EventExecutor create(@NotNull Method m, @NotNull Class<? extends Event> eventClass) {
|
||||
+ Preconditions.checkNotNull(m, "Null method");
|
||||
+ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount());
|
||||
+ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass);
|
||||
+ ClassDefiner definer = ClassDefiner.getInstance();
|
||||
+ if (Modifier.isStatic(m.getModifiers())) {
|
||||
+ return new StaticMethodHandleEventExecutor(eventClass, m);
|
||||
+ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) {
|
||||
+ // get the existing generated EventExecutor class for the Method or generate one
|
||||
+ Class<? extends EventExecutor> executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> {
|
||||
+ String name = ASMEventExecutorGenerator.generateName();
|
||||
+ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name);
|
||||
+ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class);
|
||||
+ });
|
||||
+
|
||||
+ try {
|
||||
+ EventExecutor asmExecutor = executorClass.newInstance();
|
||||
+ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception)
|
||||
+ return (listener, event) -> {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ asmExecutor.execute(listener, event);
|
||||
+ };
|
||||
+ } catch (InstantiationException | IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to initialize generated event executor", e);
|
||||
+ }
|
||||
+ } else {
|
||||
+ return new MethodHandleEventExecutor(eventClass, m);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
2555
patches/unapplied/api/0009-Paper-Plugins.patch
Normal file
2555
patches/unapplied/api/0009-Paper-Plugins.patch
Normal file
File diff suppressed because it is too large
Load diff
434
patches/unapplied/api/0010-Add-Position.patch
Normal file
434
patches/unapplied/api/0010-Add-Position.patch
Normal file
|
@ -0,0 +1,434 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 10:42:28 -0700
|
||||
Subject: [PATCH] Add Position
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/math/BlockPosition.java b/src/main/java/io/papermc/paper/math/BlockPosition.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f0fdabce4af640da2a406412e67020761ded3ac1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/math/BlockPosition.java
|
||||
@@ -0,0 +1,98 @@
|
||||
+package io.papermc.paper.math;
|
||||
+
|
||||
+import org.bukkit.Axis;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * A position represented with integers.
|
||||
+ * <p>
|
||||
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
|
||||
+ * @see FinePosition
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+public interface BlockPosition extends Position {
|
||||
+
|
||||
+ @Override
|
||||
+ default double x() {
|
||||
+ return this.blockX();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default double y() {
|
||||
+ return this.blockY();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default double z() {
|
||||
+ return this.blockZ();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isBlock() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isFine() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull BlockPosition toBlock() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull BlockPosition offset(int x, int y, int z) {
|
||||
+ return x == 0 && y == 0 && z == 0 ? this : new BlockPositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull FinePosition offset(double x, double y, double z) {
|
||||
+ return new FinePositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a block position offset by 1 in the direction specified.
|
||||
+ *
|
||||
+ * @param blockFace the block face to offset towards
|
||||
+ * @return the offset block position
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ default @NotNull BlockPosition offset(@NotNull BlockFace blockFace) {
|
||||
+ return this.offset(blockFace, 1);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a block position offset in the direction specified
|
||||
+ * multiplied by the amount.
|
||||
+ *
|
||||
+ * @param blockFace the block face to offset towards
|
||||
+ * @param amount the number of times to move in that direction
|
||||
+ * @return the offset block position
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ default @NotNull BlockPosition offset(@NotNull BlockFace blockFace, int amount) {
|
||||
+ return amount == 0 ? this : new BlockPositionImpl(this.blockX() + (blockFace.getModX() * amount), this.blockY() + (blockFace.getModY() * amount), this.blockZ() + (blockFace.getModZ() * amount));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a block position offset by the amount along
|
||||
+ * the specified axis.
|
||||
+ *
|
||||
+ * @param axis the axis to offset along
|
||||
+ * @param amount the amount to offset along that axis
|
||||
+ * @return the offset block position
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ default @NotNull BlockPosition offset(@NotNull Axis axis, int amount) {
|
||||
+ return amount == 0 ? this : switch (axis) {
|
||||
+ case X -> new BlockPositionImpl(this.blockX() + amount, this.blockY(), this.blockZ());
|
||||
+ case Y -> new BlockPositionImpl(this.blockX(), this.blockY() + amount, this.blockZ());
|
||||
+ case Z -> new BlockPositionImpl(this.blockX(), this.blockY(), this.blockZ() + amount);
|
||||
+ };
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/math/BlockPositionImpl.java b/src/main/java/io/papermc/paper/math/BlockPositionImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..eb5a3f26c7ba56c6715827f52c0013a860ec7d9a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/math/BlockPositionImpl.java
|
||||
@@ -0,0 +1,4 @@
|
||||
+package io.papermc.paper.math;
|
||||
+
|
||||
+record BlockPositionImpl(int blockX, int blockY, int blockZ) implements BlockPosition {
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/math/FinePosition.java b/src/main/java/io/papermc/paper/math/FinePosition.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d8df70d731573cf2446044925f218876d62fd7cf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/math/FinePosition.java
|
||||
@@ -0,0 +1,56 @@
|
||||
+package io.papermc.paper.math;
|
||||
+
|
||||
+import org.bukkit.util.NumberConversions;
|
||||
+import org.bukkit.util.Vector;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * A position represented with doubles.
|
||||
+ * <p>
|
||||
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
|
||||
+ * @see BlockPosition
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+public interface FinePosition extends Position {
|
||||
+
|
||||
+ @Override
|
||||
+ default int blockX() {
|
||||
+ return NumberConversions.floor(this.x());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default int blockY() {
|
||||
+ return NumberConversions.floor(this.y());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default int blockZ() {
|
||||
+ return NumberConversions.floor(this.z());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isBlock() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default boolean isFine() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull BlockPosition toBlock() {
|
||||
+ return new BlockPositionImpl(this.blockX(), this.blockY(), this.blockZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull FinePosition offset(int x, int y, int z) {
|
||||
+ return this.offset((double) x, y, z);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull FinePosition offset(double x, double y, double z) {
|
||||
+ return x == 0.0 && y == 0.0 && z == 0.0 ? this : new FinePositionImpl(this.x() + x, this.y() + y, this.z() + z);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/math/FinePositionImpl.java b/src/main/java/io/papermc/paper/math/FinePositionImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..93476aaf8d21efb5a30b6d2cc2eeda8100fb72d0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/math/FinePositionImpl.java
|
||||
@@ -0,0 +1,4 @@
|
||||
+package io.papermc.paper.math;
|
||||
+
|
||||
+record FinePositionImpl(double x, double y, double z) implements FinePosition {
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/math/Position.java b/src/main/java/io/papermc/paper/math/Position.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d9f242740
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/math/Position.java
|
||||
@@ -0,0 +1,191 @@
|
||||
+package io.papermc.paper.math;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.util.Vector;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Common interface for {@link FinePosition} and {@link BlockPosition}.
|
||||
+ * <p>
|
||||
+ * <b>May see breaking changes until Experimental annotation is removed.</b>
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+public interface Position {
|
||||
+
|
||||
+ FinePosition FINE_ZERO = new FinePositionImpl(0, 0, 0);
|
||||
+ BlockPosition BLOCK_ZERO = new BlockPositionImpl(0, 0, 0);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block x value for this position
|
||||
+ *
|
||||
+ * @return the block x value
|
||||
+ */
|
||||
+ int blockX();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block x value for this position
|
||||
+ *
|
||||
+ * @return the block x value
|
||||
+ */
|
||||
+ int blockY();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block x value for this position
|
||||
+ *
|
||||
+ * @return the block x value
|
||||
+ */
|
||||
+ int blockZ();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the x value for this position
|
||||
+ *
|
||||
+ * @return the x value
|
||||
+ */
|
||||
+ double x();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the y value for this position
|
||||
+ *
|
||||
+ * @return the y value
|
||||
+ */
|
||||
+ double y();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the z value for this position
|
||||
+ *
|
||||
+ * @return the z value
|
||||
+ */
|
||||
+ double z();
|
||||
+
|
||||
+ /**
|
||||
+ * Checks of this position represents a {@link BlockPosition}
|
||||
+ *
|
||||
+ * @return true if block
|
||||
+ */
|
||||
+ boolean isBlock();
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if this position represents a {@link FinePosition}
|
||||
+ *
|
||||
+ * @return true if fine
|
||||
+ */
|
||||
+ boolean isFine();
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if each component of this position is finite.
|
||||
+ */
|
||||
+ default boolean isFinite() {
|
||||
+ return Double.isFinite(this.x()) && Double.isFinite(this.y()) && Double.isFinite(this.z());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a position offset by the specified amounts.
|
||||
+ *
|
||||
+ * @param x x value to offset
|
||||
+ * @param y y value to offset
|
||||
+ * @param z z value to offset
|
||||
+ * @return the offset position
|
||||
+ */
|
||||
+ @NotNull Position offset(int x, int y, int z);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a position offset by the specified amounts.
|
||||
+ *
|
||||
+ * @param x x value to offset
|
||||
+ * @param y y value to offset
|
||||
+ * @param z z value to offset
|
||||
+ * @return the offset position
|
||||
+ */
|
||||
+ @NotNull FinePosition offset(double x, double y, double z);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a new position at the center of the block position this represents
|
||||
+ *
|
||||
+ * @return a new center position
|
||||
+ */
|
||||
+ @Contract(value = "-> new", pure = true)
|
||||
+ default @NotNull FinePosition toCenter() {
|
||||
+ return new FinePositionImpl(this.blockX() + 0.5, this.blockY() + 0.5, this.blockZ() + 0.5);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the block position of this position
|
||||
+ * or itself if it already is a block position
|
||||
+ *
|
||||
+ * @return the block position
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ @NotNull BlockPosition toBlock();
|
||||
+
|
||||
+ /**
|
||||
+ * Converts this position to a vector
|
||||
+ *
|
||||
+ * @return a new vector
|
||||
+ */
|
||||
+ @Contract(value = "-> new", pure = true)
|
||||
+ default @NotNull Vector toVector() {
|
||||
+ return new Vector(this.x(), this.y(), this.z());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new location object at this position with the specified world
|
||||
+ *
|
||||
+ * @param world the world for the location object
|
||||
+ * @return a new location
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ default @NotNull Location toLocation(@NotNull World world) {
|
||||
+ return new Location(world, this.x(), this.y(), this.z());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a position at the coordinates
|
||||
+ *
|
||||
+ * @param x x coord
|
||||
+ * @param y y coord
|
||||
+ * @param z z coord
|
||||
+ * @return a position with those coords
|
||||
+ */
|
||||
+ @Contract(value = "_, _, _ -> new", pure = true)
|
||||
+ static @NotNull BlockPosition block(int x, int y, int z) {
|
||||
+ return new BlockPositionImpl(x, y, z);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a position from the location.
|
||||
+ *
|
||||
+ * @param location the location to copy the position of
|
||||
+ * @return a new position at that location
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ static @NotNull BlockPosition block(@NotNull Location location) {
|
||||
+ return new BlockPositionImpl(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a position at the coordinates
|
||||
+ *
|
||||
+ * @param x x coord
|
||||
+ * @param y y coord
|
||||
+ * @param z z coord
|
||||
+ * @return a position with those coords
|
||||
+ */
|
||||
+ @Contract(value = "_, _, _ -> new", pure = true)
|
||||
+ static @NotNull FinePosition fine(double x, double y, double z) {
|
||||
+ return new FinePositionImpl(x, y, z);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a position from the location.
|
||||
+ *
|
||||
+ * @param location the location to copy the position of
|
||||
+ * @return a new position at that location
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ static @NotNull FinePosition fine(@NotNull Location location) {
|
||||
+ return new FinePositionImpl(location.getX(), location.getY(), location.getZ());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java
|
||||
index 7c4db051472fb6a6c6d24092dc6f75487356690a..85c342fc50f2fe0ce9a1b3980df9e088c3dea92d 100644
|
||||
--- a/src/main/java/org/bukkit/Location.java
|
||||
+++ b/src/main/java/org/bukkit/Location.java
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* magnitude than 360 are valid, but may be normalized to any other equivalent
|
||||
* representation by the implementation.
|
||||
*/
|
||||
-public class Location implements Cloneable, ConfigurationSerializable {
|
||||
+public class Location implements Cloneable, ConfigurationSerializable, io.papermc.paper.math.FinePosition { // Paper
|
||||
private Reference<World> world;
|
||||
private double x;
|
||||
private double y;
|
||||
@@ -706,4 +706,31 @@ public class Location implements Cloneable, ConfigurationSerializable {
|
||||
}
|
||||
return pitch;
|
||||
}
|
||||
+
|
||||
+ // Paper - add Position
|
||||
+ @Override
|
||||
+ public double x() {
|
||||
+ return this.getX();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double y() {
|
||||
+ return this.getY();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double z() {
|
||||
+ return this.getZ();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isFinite() {
|
||||
+ return io.papermc.paper.math.FinePosition.super.isFinite() && Float.isFinite(this.getYaw()) && Float.isFinite(this.getPitch());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Location toLocation(@NotNull World world) {
|
||||
+ return new Location(world, this.x(), this.y(), this.z(), this.getYaw(), this.getPitch());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
3801
patches/unapplied/api/0011-Timings-v2.patch
Normal file
3801
patches/unapplied/api/0011-Timings-v2.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,96 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 18 May 2021 14:42:26 -0700
|
||||
Subject: [PATCH] Add command line option to load extra plugin jars not in the
|
||||
plugins folder
|
||||
|
||||
ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 7300bba67cfd4d312c59b0f81f597ea0f8a54fcd..3a8b07a870d334296e3865598741dc3e6fcf9b62 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -79,6 +79,20 @@ public final class Bukkit {
|
||||
return server;
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded,
|
||||
+ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}.
|
||||
+ *
|
||||
+ * <p>Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this
|
||||
+ * directory manually when determining the location in which to store their data and configuration files.</p>
|
||||
+ *
|
||||
+ * @return plugins directory
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static File getPluginsFolder() {
|
||||
+ return server.getPluginsFolder();
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Attempts to set the {@link Server} singleton.
|
||||
* <p>
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 31227e818b624d641bb7562ac3de8a821815d33a..d3917c514f0e1d4343aed0738bea1625f63fcb92 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -64,6 +64,18 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper
|
||||
|
||||
+ /**
|
||||
+ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded,
|
||||
+ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}.
|
||||
+ *
|
||||
+ * <p>Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this
|
||||
+ * directory manually when determining the location in which to store their data and configuration files.</p>
|
||||
+ *
|
||||
+ * @return plugins directory
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ File getPluginsFolder();
|
||||
+
|
||||
/**
|
||||
* Used for all administrative messages, such as an operator using a
|
||||
* command.
|
||||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
index 63389474a2b3f0e283b42e7004aa6a94904a3d17..974ff7116b294473ec450757e8a9341540f43dcd 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -116,9 +116,22 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Plugin[] loadPlugins(@NotNull File directory) {
|
||||
+ // Paper start - extra jars
|
||||
+ return this.loadPlugins(directory, java.util.Collections.emptyList());
|
||||
+ }
|
||||
+ @NotNull
|
||||
+ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List<File> extraPluginJars) {
|
||||
+ // Paper end
|
||||
if (true) {
|
||||
List<Plugin> pluginList = new ArrayList<>();
|
||||
java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory));
|
||||
+ for (File file : extraPluginJars) {
|
||||
+ try {
|
||||
+ pluginList.add(this.paperPluginManager.loadPlugin(file));
|
||||
+ } catch (Exception e) {
|
||||
+ this.server.getLogger().log(Level.SEVERE, "Plugin loading error!", e);
|
||||
+ }
|
||||
+ }
|
||||
return pluginList.toArray(new Plugin[0]);
|
||||
}
|
||||
Preconditions.checkArgument(directory != null, "Directory cannot be null");
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
index de6b6188587fd254ab96cbc1f95fda2056d9cbe2..eaefbb00e9993d54906cc8cf35cf753c0d6c7707 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
@@ -93,7 +93,7 @@ public final class JavaPluginLoader implements PluginLoader {
|
||||
throw new InvalidPluginException(ex);
|
||||
}
|
||||
|
||||
- final File parentFile = file.getParentFile();
|
||||
+ final File parentFile = this.server.getPluginsFolder(); // Paper
|
||||
final File dataFolder = new File(parentFile, description.getName());
|
||||
@SuppressWarnings("deprecation")
|
||||
final File oldDataFolder = new File(parentFile, description.getRawName());
|
33
patches/unapplied/api/0013-Player-affects-spawning-API.patch
Normal file
33
patches/unapplied/api/0013-Player-affects-spawning-API.patch
Normal file
|
@ -0,0 +1,33 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Mon, 29 Feb 2016 17:22:34 -0600
|
||||
Subject: [PATCH] Player affects spawning API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index e237c2d34cdbd9968eab4628bb1c0155554586e7..081dbaebc0b209839d48ccbda85ae1a9ed0be439 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2259,6 +2259,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@Deprecated // Paper
|
||||
public String getLocale();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Get whether the player can affect mob spawning
|
||||
+ *
|
||||
+ * @return if the player can affect mob spawning
|
||||
+ */
|
||||
+ public boolean getAffectsSpawning();
|
||||
+
|
||||
+ /**
|
||||
+ * Set whether the player can affect mob spawning
|
||||
+ *
|
||||
+ * @param affects Whether the player can affect mob spawning
|
||||
+ */
|
||||
+ public void setAffectsSpawning(boolean affects);
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Update the list of commands sent to the client.
|
||||
* <br>
|
49
patches/unapplied/api/0014-Add-getTPS-method.patch
Normal file
49
patches/unapplied/api/0014-Add-getTPS-method.patch
Normal file
|
@ -0,0 +1,49 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 29 Feb 2016 17:24:57 -0600
|
||||
Subject: [PATCH] Add getTPS method
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 3a8b07a870d334296e3865598741dc3e6fcf9b62..43f4ec39a610119d6285884aa323d9f46e22f073 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2040,6 +2040,17 @@ public final class Bukkit {
|
||||
return server.getEntity(uuid);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the current server TPS
|
||||
+ * @return current server TPS (1m, 5m, 15m in Paper-Server)
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static double[] getTPS() {
|
||||
+ return server.getTPS();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Get the advancement specified by this key.
|
||||
*
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index d3917c514f0e1d4343aed0738bea1625f63fcb92..a8a932e308b4d7b1e9cacb53f78b1cdd0c6d4063 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1741,6 +1741,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@Nullable
|
||||
Entity getEntity(@NotNull UUID uuid);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the current server TPS
|
||||
+ *
|
||||
+ * @return current server TPS (1m, 5m, 15m in Paper-Server)
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public double[] getTPS();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Get the advancement specified by this key.
|
||||
*
|
200
patches/unapplied/api/0015-Version-Command-2.0.patch
Normal file
200
patches/unapplied/api/0015-Version-Command-2.0.patch
Normal file
|
@ -0,0 +1,200 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Mon, 27 May 2019 01:10:06 -0500
|
||||
Subject: [PATCH] Version Command 2.0
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
|
||||
@@ -0,0 +1,45 @@
|
||||
+package com.destroystokyo.paper.util;
|
||||
+
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public interface VersionFetcher {
|
||||
+ /**
|
||||
+ * Amount of time to cache results for in milliseconds
|
||||
+ * <p>
|
||||
+ * Negative values will never cache.
|
||||
+ *
|
||||
+ * @return cache time
|
||||
+ */
|
||||
+ long getCacheTime();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the version message to cache and show to command senders.
|
||||
+ *
|
||||
+ * <p>NOTE: This is run in a new thread separate from that of the command processing thread</p>
|
||||
+ *
|
||||
+ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()})
|
||||
+ * @return the message to show when requesting a version
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ Component getVersionMessage(@NotNull String serverVersion);
|
||||
+
|
||||
+ class DummyVersionFetcher implements VersionFetcher {
|
||||
+
|
||||
+ @Override
|
||||
+ public long getCacheTime() {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Component getVersionMessage(@NotNull String serverVersion) {
|
||||
+ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!");
|
||||
+ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()");
|
||||
+ new Throwable().printStackTrace();
|
||||
+ return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
index 659405d84b5a61618576e930805da5cd3a054b4c..4604392831d19a789e4906cf1a5f0197105fd6f2 100644
|
||||
--- a/src/main/java/org/bukkit/UnsafeValues.java
|
||||
+++ b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
@@ -127,5 +127,12 @@ public interface UnsafeValues {
|
||||
* @return name
|
||||
*/
|
||||
String getTimingsServerName();
|
||||
+
|
||||
+ /**
|
||||
+ * Called once by the version command on first use, then cached.
|
||||
+ */
|
||||
+ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
|
||||
+ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher();
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
|
||||
index 04b4fb6859df0221f8f9f92c5a7ac2dda1073355..b437cf212a63aa96a9492db8d01d5d37061aee23 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
|
||||
@@ -24,8 +24,25 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.util.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
+// Paper start - version command 2.0
|
||||
+import com.destroystokyo.paper.util.VersionFetcher;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import net.kyori.adventure.text.format.TextDecoration;
|
||||
+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
+// Paper end - version command 2.0
|
||||
|
||||
public class VersionCommand extends BukkitCommand {
|
||||
+ private VersionFetcher versionFetcher; // Paper - version command 2.0
|
||||
+ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration
|
||||
+ if (versionFetcher == null) {
|
||||
+ versionFetcher = Bukkit.getUnsafe().getVersionFetcher();
|
||||
+ }
|
||||
+
|
||||
+ return versionFetcher;
|
||||
+ }
|
||||
+
|
||||
public VersionCommand(@NotNull String name) {
|
||||
super(name);
|
||||
|
||||
@@ -40,7 +57,7 @@ public class VersionCommand extends BukkitCommand {
|
||||
if (!testPermission(sender)) return true;
|
||||
|
||||
if (args.length == 0) {
|
||||
- sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")");
|
||||
+ //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage
|
||||
sendVersion(sender);
|
||||
} else {
|
||||
StringBuilder name = new StringBuilder();
|
||||
@@ -79,8 +96,17 @@ public class VersionCommand extends BukkitCommand {
|
||||
|
||||
private void describeToSender(@NotNull Plugin plugin, @NotNull CommandSender sender) {
|
||||
PluginDescriptionFile desc = plugin.getDescription();
|
||||
- sender.sendMessage(ChatColor.GREEN + desc.getName() + ChatColor.WHITE + " version " + ChatColor.GREEN + desc.getVersion());
|
||||
-
|
||||
+ // Paper start - version command 2.0
|
||||
+ sender.sendMessage(
|
||||
+ Component.text()
|
||||
+ .append(Component.text(desc.getName(), NamedTextColor.GREEN))
|
||||
+ .append(Component.text(" version "))
|
||||
+ .append(Component.text(desc.getVersion(), NamedTextColor.GREEN)
|
||||
+ .hoverEvent(Component.text("Click to copy to clipboard", NamedTextColor.WHITE))
|
||||
+ .clickEvent(ClickEvent.copyToClipboard(desc.getVersion()))
|
||||
+ )
|
||||
+ );
|
||||
+ // Paper end - version command 2.0
|
||||
if (desc.getDescription() != null) {
|
||||
sender.sendMessage(desc.getDescription());
|
||||
}
|
||||
@@ -146,14 +172,14 @@ public class VersionCommand extends BukkitCommand {
|
||||
|
||||
private final ReentrantLock versionLock = new ReentrantLock();
|
||||
private boolean hasVersion = false;
|
||||
- private String versionMessage = null;
|
||||
+ private Component versionMessage = null; // Paper
|
||||
private final Set<CommandSender> versionWaiters = new HashSet<CommandSender>();
|
||||
private boolean versionTaskStarted = false;
|
||||
private long lastCheck = 0;
|
||||
|
||||
private void sendVersion(@NotNull CommandSender sender) {
|
||||
if (hasVersion) {
|
||||
- if (System.currentTimeMillis() - lastCheck > 21600000) {
|
||||
+ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier
|
||||
lastCheck = System.currentTimeMillis();
|
||||
hasVersion = false;
|
||||
} else {
|
||||
@@ -168,7 +194,7 @@ public class VersionCommand extends BukkitCommand {
|
||||
return;
|
||||
}
|
||||
versionWaiters.add(sender);
|
||||
- sender.sendMessage("Checking version, please wait...");
|
||||
+ sender.sendMessage(Component.text("Checking version, please wait...", NamedTextColor.WHITE, TextDecoration.ITALIC)); // Paper
|
||||
if (!versionTaskStarted) {
|
||||
versionTaskStarted = true;
|
||||
new Thread(new Runnable() {
|
||||
@@ -186,6 +212,13 @@ public class VersionCommand extends BukkitCommand {
|
||||
|
||||
private void obtainVersion() {
|
||||
String version = Bukkit.getVersion();
|
||||
+ // Paper start
|
||||
+ if (version.startsWith("null")) { // running from ide?
|
||||
+ setVersionMessage(Component.text("Unknown version, custom build?", NamedTextColor.YELLOW));
|
||||
+ return;
|
||||
+ }
|
||||
+ setVersionMessage(getVersionFetcher().getVersionMessage(version));
|
||||
+ /*
|
||||
if (version == null) version = "Custom";
|
||||
String[] parts = version.substring(0, version.indexOf(' ')).split("-");
|
||||
if (parts.length == 4) {
|
||||
@@ -215,11 +248,24 @@ public class VersionCommand extends BukkitCommand {
|
||||
} else {
|
||||
setVersionMessage("Unknown version, custom build?");
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
- private void setVersionMessage(@NotNull String msg) {
|
||||
+ // Paper start
|
||||
+ private void setVersionMessage(final @NotNull Component msg) {
|
||||
lastCheck = System.currentTimeMillis();
|
||||
- versionMessage = msg;
|
||||
+ final Component message = Component.textOfChildren(
|
||||
+ Component.text("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")", NamedTextColor.WHITE),
|
||||
+ Component.newline(),
|
||||
+ msg
|
||||
+ );
|
||||
+ this.versionMessage = Component.text()
|
||||
+ .append(message)
|
||||
+ .hoverEvent(Component.text("Click to copy to clipboard", NamedTextColor.WHITE))
|
||||
+ .clickEvent(ClickEvent.copyToClipboard(PlainTextComponentSerializer.plainText().serialize(message)))
|
||||
+ .build();
|
||||
+ // Paper end
|
||||
versionLock.lock();
|
||||
try {
|
||||
hasVersion = true;
|
66
patches/unapplied/api/0016-Entity-Origin-API.patch
Normal file
66
patches/unapplied/api/0016-Entity-Origin-API.patch
Normal file
|
@ -0,0 +1,66 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Mon, 29 Feb 2016 17:50:31 -0600
|
||||
Subject: [PATCH] Entity Origin API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
|
||||
index 121cd27185269339babae1757a604fbb5aabc869..63137429779d06fafb162f1bfb823d5149b3c58a 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Entity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Entity.java
|
||||
@@ -739,5 +739,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
|
||||
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
|
||||
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName())));
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the location where this entity originates from.
|
||||
+ * <p>
|
||||
+ * This value can be null if the entity hasn't yet been added to the world.
|
||||
+ *
|
||||
+ * @return Location where entity originates or null if not yet added
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ Location getOrigin();
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java
|
||||
index d96fd494b523491fcf1ac54d164351fd487f65d6..ae1ce2ee2deb82f3f4144ec54b3ba119b437c5e9 100644
|
||||
--- a/src/main/java/org/bukkit/entity/FallingBlock.java
|
||||
+++ b/src/main/java/org/bukkit/entity/FallingBlock.java
|
||||
@@ -126,4 +126,15 @@ public interface FallingBlock extends Entity {
|
||||
* @param damage the max damage to set. Must be >= 0
|
||||
*/
|
||||
void setMaxDamage(int damage);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the source block location of the FallingBlock
|
||||
+ *
|
||||
+ * @return the source block location the FallingBlock was spawned from
|
||||
+ * @deprecated replaced by {@link Entity#getOrigin()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default org.bukkit.Location getSourceLoc() {
|
||||
+ return this.getOrigin();
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/entity/TNTPrimed.java b/src/main/java/org/bukkit/entity/TNTPrimed.java
|
||||
index a23cfdf66877f0a61eae700de084c76e6ee7b431..0813bd913c8fdb2001963ce3e82c07c2af105418 100644
|
||||
--- a/src/main/java/org/bukkit/entity/TNTPrimed.java
|
||||
+++ b/src/main/java/org/bukkit/entity/TNTPrimed.java
|
||||
@@ -53,4 +53,15 @@ public interface TNTPrimed extends Explosive {
|
||||
* @param source the source of this primed TNT
|
||||
*/
|
||||
public void setSource(@Nullable Entity source);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the source block location of the TNTPrimed
|
||||
+ *
|
||||
+ * @return the source block location the TNTPrimed was spawned from
|
||||
+ * @deprecated replaced by {@link Entity#getOrigin()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default org.bukkit.Location getSourceLoc() {
|
||||
+ return this.getOrigin();
|
||||
+ }
|
||||
}
|
63
patches/unapplied/api/0017-Add-PlayerLocaleChangeEvent.patch
Normal file
63
patches/unapplied/api/0017-Add-PlayerLocaleChangeEvent.patch
Normal file
|
@ -0,0 +1,63 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Moore <rmsy@me.com>
|
||||
Date: Mon, 29 Feb 2016 18:02:25 -0600
|
||||
Subject: [PATCH] Add PlayerLocaleChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bb7baa91fd4ba763fd8ce216bc9043c5e2c4b7b7
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
|
||||
@@ -0,0 +1,51 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+/**
|
||||
+ * Called when the locale of the player is changed.
|
||||
+ *
|
||||
+ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream
|
||||
+ */
|
||||
+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
|
||||
+public class PlayerLocaleChangeEvent extends PlayerEvent {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final String oldLocale;
|
||||
+ private final String newLocale;
|
||||
+
|
||||
+ public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) {
|
||||
+ super(player);
|
||||
+ this.oldLocale = oldLocale;
|
||||
+ this.newLocale = newLocale;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the locale the player switched from.
|
||||
+ *
|
||||
+ * @return player's old locale
|
||||
+ */
|
||||
+ public String getOldLocale() {
|
||||
+ return oldLocale;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the locale the player is changed to.
|
||||
+ *
|
||||
+ * @return player's new locale
|
||||
+ */
|
||||
+ public String getNewLocale() {
|
||||
+ return newLocale;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
159
patches/unapplied/api/0018-Add-view-distance-API.patch
Normal file
159
patches/unapplied/api/0018-Add-view-distance-API.patch
Normal file
|
@ -0,0 +1,159 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Mon, 29 Feb 2016 18:05:37 -0600
|
||||
Subject: [PATCH] Add view distance API
|
||||
|
||||
Add per player no-tick, tick, and send view distances.
|
||||
|
||||
Also add send/no-tick view distance to World.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
|
||||
index 30dc2f85b60877930cab68230d3259ce92c08618..2867faf0acbbbb2e99c5b503f0c6bc83f3bfe80f 100644
|
||||
--- a/src/main/java/org/bukkit/World.java
|
||||
+++ b/src/main/java/org/bukkit/World.java
|
||||
@@ -2745,6 +2745,62 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
int getSimulationDistance();
|
||||
// Spigot end
|
||||
|
||||
+ // Paper start - view distance api
|
||||
+ /**
|
||||
+ * Sets the view distance for this world.
|
||||
+ * @param viewDistance view distance in [2, 32]
|
||||
+ */
|
||||
+ void setViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the simulation distance for this world.
|
||||
+ * @param simulationDistance simulation distance in [2, 32]
|
||||
+ */
|
||||
+ void setSimulationDistance(int simulationDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the no-tick view distance for this world.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @return The no-tick view distance for this world.
|
||||
+ * @deprecated Use {@link #getViewDistance()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ int getNoTickViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the no-tick view distance for this world.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32]
|
||||
+ * @deprecated Use {@link #setViewDistance(int)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void setNoTickViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the sending view distance for this world.
|
||||
+ * <p>
|
||||
+ * Sending view distance is the view distance where chunks will load in for players in this world.
|
||||
+ * </p>
|
||||
+ * @return The sending view distance for this world.
|
||||
+ */
|
||||
+ int getSendViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the sending view distance for this world.
|
||||
+ * <p>
|
||||
+ * Sending view distance is the view distance where chunks will load in for players in this world.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32] or -1
|
||||
+ */
|
||||
+ void setSendViewDistance(int viewDistance);
|
||||
+ // Paper end - view distance api
|
||||
+
|
||||
// Spigot start
|
||||
public class Spigot {
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 081dbaebc0b209839d48ccbda85ae1a9ed0be439..fa7637dd594821ffd20a53c6c7f5b3d9fa107564 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2273,6 +2273,78 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @param affects Whether the player can affect mob spawning
|
||||
*/
|
||||
public void setAffectsSpawning(boolean affects);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the view distance for this player
|
||||
+ *
|
||||
+ * @return the player's view distance
|
||||
+ * @see org.bukkit.World#getViewDistance()
|
||||
+ */
|
||||
+ public int getViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the view distance for this player
|
||||
+ *
|
||||
+ * @param viewDistance the player's view distance
|
||||
+ * @see org.bukkit.World#setViewDistance(int)
|
||||
+ */
|
||||
+ public void setViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the simulation distance for this player
|
||||
+ *
|
||||
+ * @return the player's simulation distance
|
||||
+ */
|
||||
+ public int getSimulationDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the simulation distance for this player
|
||||
+ *
|
||||
+ * @param simulationDistance the player's new simulation distance
|
||||
+ */
|
||||
+ public void setSimulationDistance(int simulationDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the no-ticking view distance for this player.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @return The no-tick view distance for this player.
|
||||
+ * @deprecated Use {@link #getViewDistance()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public int getNoTickViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the no-ticking view distance for this player.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32] or -1
|
||||
+ * @deprecated Use {@link #setViewDistance(int)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setNoTickViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the sending view distance for this player.
|
||||
+ * <p>
|
||||
+ * Sending view distance is the view distance where chunks will load in for players.
|
||||
+ * </p>
|
||||
+ * @return The sending view distance for this player.
|
||||
+ */
|
||||
+ public int getSendViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the sending view distance for this player.
|
||||
+ * <p>
|
||||
+ * Sending view distance is the view distance where chunks will load in for players.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32] or -1
|
||||
+ */
|
||||
+ public void setSendViewDistance(int viewDistance);
|
||||
// Paper end
|
||||
|
||||
/**
|
98
patches/unapplied/api/0019-Add-BeaconEffectEvent.patch
Normal file
98
patches/unapplied/api/0019-Add-BeaconEffectEvent.patch
Normal file
|
@ -0,0 +1,98 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Mon, 29 Feb 2016 18:09:40 -0600
|
||||
Subject: [PATCH] Add BeaconEffectEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..978813b94a5eae0afccbd3b38b463091a46b56ac
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
|
||||
@@ -0,0 +1,86 @@
|
||||
+package com.destroystokyo.paper.event.block;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.block.BlockEvent;
|
||||
+import org.bukkit.potion.PotionEffect;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a beacon effect is being applied to a player.
|
||||
+ */
|
||||
+public class BeaconEffectEvent extends BlockEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled;
|
||||
+ private PotionEffect effect;
|
||||
+ private Player player;
|
||||
+ private boolean primary;
|
||||
+
|
||||
+ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) {
|
||||
+ super(block);
|
||||
+ this.effect = effect;
|
||||
+ this.player = player;
|
||||
+ this.primary = primary;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancelled) {
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the potion effect being applied.
|
||||
+ *
|
||||
+ * @return Potion effect
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PotionEffect getEffect() {
|
||||
+ return effect;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the potion effect that will be applied.
|
||||
+ *
|
||||
+ * @param effect Potion effect
|
||||
+ */
|
||||
+ public void setEffect(@NotNull PotionEffect effect) {
|
||||
+ this.effect = effect;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the player who the potion effect is being applied to.
|
||||
+ *
|
||||
+ * @return Affected player
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether the effect is a primary beacon effect.
|
||||
+ *
|
||||
+ * @return true if this event represents a primary effect
|
||||
+ */
|
||||
+ public boolean isPrimary() {
|
||||
+ return primary;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
31
patches/unapplied/api/0020-Add-PlayerInitialSpawnEvent.patch
Normal file
31
patches/unapplied/api/0020-Add-PlayerInitialSpawnEvent.patch
Normal file
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Anton <anxuiz.nx@gmail.com>
|
||||
Date: Mon, 29 Feb 2016 18:13:58 -0600
|
||||
Subject: [PATCH] Add PlayerInitialSpawnEvent
|
||||
|
||||
For modifying a player's initial spawn location as they join the server
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..febd384b43560d7d55c96bda5b0701a27fc9e18e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
|
||||
@@ -0,0 +1,18 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.spigotmc.event.player.PlayerSpawnLocationEvent;
|
||||
+
|
||||
+/**
|
||||
+ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API
|
||||
+ */
|
||||
+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
|
||||
+public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent {
|
||||
+
|
||||
+ public PlayerInitialSpawnEvent(@NotNull Player who, @NotNull Location spawnLocation) {
|
||||
+ super(who, spawnLocation);
|
||||
+ }
|
||||
+}
|
50
patches/unapplied/api/0021-Expose-server-CommandMap.patch
Normal file
50
patches/unapplied/api/0021-Expose-server-CommandMap.patch
Normal file
|
@ -0,0 +1,50 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Mon, 29 Feb 2016 19:48:59 -0600
|
||||
Subject: [PATCH] Expose server CommandMap
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 43f4ec39a610119d6285884aa323d9f46e22f073..4c5671cf75143e741d945834a2a8b56cb52f20dd 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2241,6 +2241,19 @@ public final class Bukkit {
|
||||
return server.getUnsafe();
|
||||
}
|
||||
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the active {@link org.bukkit.command.CommandMap}
|
||||
+ *
|
||||
+ * @return the active command map
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static org.bukkit.command.CommandMap getCommandMap() {
|
||||
+ return server.getCommandMap();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@NotNull
|
||||
public static Server.Spigot spigot() {
|
||||
return server.spigot();
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index a8a932e308b4d7b1e9cacb53f78b1cdd0c6d4063..7ee7fdc8379078456492da00bb213a0738cc6f08 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1751,6 +1751,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
public double[] getTPS();
|
||||
// Paper end
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the active {@link org.bukkit.command.CommandMap}
|
||||
+ *
|
||||
+ * @return the active command map
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ org.bukkit.command.CommandMap getCommandMap();
|
||||
+
|
||||
/**
|
||||
* Get the advancement specified by this key.
|
||||
*
|
|
@ -0,0 +1,124 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Mon, 29 Feb 2016 19:54:32 -0600
|
||||
Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses
|
||||
|
||||
Change Javadoc to be accurate
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 4c5671cf75143e741d945834a2a8b56cb52f20dd..3118da2ad367b5bd547769214112ea5299c95866 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -411,6 +411,30 @@ public final class Bukkit {
|
||||
return server.broadcastMessage(message);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to all online players.
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ server.broadcast(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to all online players.
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ server.broadcast(components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the name of the update folder. The update folder is used to safely
|
||||
* update plugins at the right moment on a plugin load.
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 7ee7fdc8379078456492da00bb213a0738cc6f08..d94483d1481f233897faf378e6b34b6b97f02caf 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -346,6 +346,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@Deprecated // Paper
|
||||
public int broadcastMessage(@NotNull String message);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to all online players.
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ spigot().broadcast(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to all online players.
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().broadcast(components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the name of the update folder. The update folder is used to safely
|
||||
* update plugins at the right moment on a plugin load.
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index fa7637dd594821ffd20a53c6c7f5b3d9fa107564..944153f0d72c6ff5b7250e3d4b4591829deb16c2 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1102,6 +1102,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
public void sendMap(@NotNull MapView map);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to the player
|
||||
+ *
|
||||
+ * @param component the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Override
|
||||
+ @Deprecated
|
||||
+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ spigot().sendMessage(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the player
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Override
|
||||
+ @Deprecated
|
||||
+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().sendMessage(components);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the specified screen position of this player
|
||||
+ *
|
||||
+ * @param position the screen position
|
||||
+ * @param components the components to send
|
||||
+ */
|
||||
+ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().sendMessage(position, components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Send a hurt animation. This fakes incoming damage towards the player from
|
||||
* the given yaw relative to the player's direction.
|
580
patches/unapplied/api/0023-Add-exception-reporting-event.patch
Normal file
580
patches/unapplied/api/0023-Add-exception-reporting-event.patch
Normal file
|
@ -0,0 +1,580 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Mon, 29 Feb 2016 20:24:35 -0600
|
||||
Subject: [PATCH] Add exception reporting event
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..306dbd975e9380c22dae0dad526725cc47a36f16
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
|
||||
@@ -0,0 +1,42 @@
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import com.destroystokyo.paper.exception.ServerException;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called whenever an exception is thrown in a recoverable section of the server.
|
||||
+ */
|
||||
+public class ServerExceptionEvent extends Event {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private ServerException exception;
|
||||
+
|
||||
+ public ServerExceptionEvent(@NotNull ServerException exception) {
|
||||
+ super(!Bukkit.isPrimaryThread());
|
||||
+ this.exception = Preconditions.checkNotNull(exception, "exception");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the wrapped exception that was thrown.
|
||||
+ *
|
||||
+ * @return Exception thrown
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ServerException getException() {
|
||||
+ return exception;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a command throws an exception
|
||||
+ */
|
||||
+public class ServerCommandException extends ServerException {
|
||||
+
|
||||
+ private final Command command;
|
||||
+ private final CommandSender commandSender;
|
||||
+ private final String[] arguments;
|
||||
+
|
||||
+ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(cause);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command which threw the exception
|
||||
+ *
|
||||
+ * @return exception throwing command
|
||||
+ */
|
||||
+ public Command getCommand() {
|
||||
+ return command;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command sender which executed the command request
|
||||
+ *
|
||||
+ * @return command sender of exception thrown command request
|
||||
+ */
|
||||
+ public CommandSender getCommandSender() {
|
||||
+ return commandSender;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the arguments which threw the exception for the command
|
||||
+ *
|
||||
+ * @return arguments of exception thrown command request
|
||||
+ */
|
||||
+ public String[] getArguments() {
|
||||
+ return arguments;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java
|
||||
@@ -0,0 +1,52 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.*;
|
||||
+
|
||||
+/**
|
||||
+ * Exception thrown when a server event listener throws an exception
|
||||
+ */
|
||||
+public class ServerEventException extends ServerPluginException {
|
||||
+
|
||||
+ private final Listener listener;
|
||||
+ private final Event event;
|
||||
+
|
||||
+ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the listener which threw the exception
|
||||
+ *
|
||||
+ * @return event listener
|
||||
+ */
|
||||
+ public Listener getListener() {
|
||||
+ return listener;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the event which caused the exception
|
||||
+ *
|
||||
+ * @return event
|
||||
+ */
|
||||
+ public Event getEvent() {
|
||||
+ return event;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+/**
|
||||
+ * Wrapper exception for all exceptions that are thrown by the server.
|
||||
+ */
|
||||
+public class ServerException extends Exception {
|
||||
+
|
||||
+ public ServerException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+
|
||||
+ public ServerException(String message, Throwable cause) {
|
||||
+ super(message, cause);
|
||||
+ }
|
||||
+
|
||||
+ public ServerException(Throwable cause) {
|
||||
+ super(cause);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2c3effca7c9d6c904cbe248d312b74e2cd360acf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java
|
||||
@@ -0,0 +1,36 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import java.util.logging.Level;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when the internal server throws a recoverable exception.
|
||||
+ */
|
||||
+public class ServerInternalException extends ServerException {
|
||||
+
|
||||
+ public ServerInternalException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+
|
||||
+ public ServerInternalException(String message, Throwable cause) {
|
||||
+ super(message, cause);
|
||||
+ }
|
||||
+
|
||||
+ public ServerInternalException(Throwable cause) {
|
||||
+ super(cause);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ }
|
||||
+
|
||||
+ public static void reportInternalException(Throwable cause) {
|
||||
+ try {
|
||||
+ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause)));
|
||||
+ ;
|
||||
+ } catch (Throwable t) {
|
||||
+ Bukkit.getLogger().log(Level.WARNING, "Exception posting ServerExceptionEvent", t); // Don't want to rethrow!
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java
|
||||
@@ -0,0 +1,20 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown whenever there is an exception with any enabling or disabling of plugins.
|
||||
+ */
|
||||
+public class ServerPluginEnableDisableException extends ServerPluginException {
|
||||
+ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..be3f92e3c6bcefe8b78da701b75121275001882e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java
|
||||
@@ -0,0 +1,36 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Wrapper exception for all cases to which a plugin can be immediately blamed for
|
||||
+ */
|
||||
+public class ServerPluginException extends ServerException {
|
||||
+ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(message, cause);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(cause);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ private final Plugin responsiblePlugin;
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the plugin which is directly responsible for the exception being thrown
|
||||
+ *
|
||||
+ * @return plugin which is responsible for the exception throw
|
||||
+ */
|
||||
+ public Plugin getResponsiblePlugin() {
|
||||
+ return responsiblePlugin;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2faef4cb358ec65e32a6aba6426f0dd7ddf90d2a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.*;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when an incoming plugin message channel throws an exception
|
||||
+ */
|
||||
+public class ServerPluginMessageException extends ServerPluginException {
|
||||
+
|
||||
+ private final Player player;
|
||||
+ private final String channel;
|
||||
+ private final byte[] data;
|
||||
+
|
||||
+ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the channel to which the error occurred from receiving data from
|
||||
+ *
|
||||
+ * @return exception channel
|
||||
+ */
|
||||
+ public String getChannel() {
|
||||
+ return channel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the data to which the error occurred from
|
||||
+ *
|
||||
+ * @return exception data
|
||||
+ */
|
||||
+ public byte[] getData() {
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the player which the plugin message causing the exception originated from
|
||||
+ *
|
||||
+ * @return exception player
|
||||
+ */
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java
|
||||
@@ -0,0 +1,37 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.scheduler.BukkitTask;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a plugin's scheduler fails with an exception
|
||||
+ */
|
||||
+public class ServerSchedulerException extends ServerPluginException {
|
||||
+
|
||||
+ private final BukkitTask task;
|
||||
+
|
||||
+ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) {
|
||||
+ super(message, cause, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ public ServerSchedulerException(Throwable cause, BukkitTask task) {
|
||||
+ super(cause, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the task which threw the exception
|
||||
+ *
|
||||
+ * @return exception throwing task
|
||||
+ */
|
||||
+ public BukkitTask getTask() {
|
||||
+ return task;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java
|
||||
@@ -0,0 +1,22 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a tab-complete request throws an exception
|
||||
+ */
|
||||
+public class ServerTabCompleteException extends ServerCommandException {
|
||||
+
|
||||
+ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, command, commandSender, arguments);
|
||||
+ }
|
||||
+
|
||||
+ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(cause, command, commandSender, arguments);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
index 4205649948a9e2a72f64c3f007112245abac6d50..b3b32ce429edbf1ed040354dbe28ab86f0d24201 100644
|
||||
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
@@ -155,11 +155,14 @@ public class SimpleCommandMap implements CommandMap {
|
||||
target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length));
|
||||
} // target.timings.stopTiming(); // Spigot // Paper
|
||||
} catch (CommandException ex) {
|
||||
+ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper
|
||||
//target.timings.stopTiming(); // Spigot // Paper
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
//target.timings.stopTiming(); // Spigot // Paper
|
||||
- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex);
|
||||
+ String msg = "Unhandled exception executing '" + commandLine + "' in " + target;
|
||||
+ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper
|
||||
+ throw new CommandException(msg, ex);
|
||||
}
|
||||
|
||||
// return true as command was handled
|
||||
@@ -238,7 +241,9 @@ public class SimpleCommandMap implements CommandMap {
|
||||
} catch (CommandException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex);
|
||||
+ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target;
|
||||
+ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerTabCompleteException(msg, ex, target, sender, args))); // Paper
|
||||
+ throw new CommandException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
index 974ff7116b294473ec450757e8a9341540f43dcd..fc2dae69165776d08274e34a69962cc70445f411 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -515,7 +515,8 @@ public final class SimplePluginManager implements PluginManager {
|
||||
try {
|
||||
plugin.getPluginLoader().enablePlugin(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while enabling "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin);
|
||||
}
|
||||
|
||||
HandlerList.bakeAll();
|
||||
@@ -538,32 +539,37 @@ public final class SimplePluginManager implements PluginManager {
|
||||
try {
|
||||
plugin.getPluginLoader().disablePlugin(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while disabling "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getScheduler().cancelTasks(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getServicesManager().unregisterAll(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering services for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
HandlerList.unregisterAll(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering events for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getMessenger().unregisterIncomingPluginChannel(plugin);
|
||||
server.getMessenger().unregisterOutgoingPluginChannel(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -576,6 +582,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
|
||||
+ server.getLogger().log(Level.SEVERE, msg, ex);
|
||||
+ callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void clearPlugins() {
|
||||
if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper
|
||||
@@ -641,7 +654,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex);
|
||||
+ // Paper start - error reporting
|
||||
+ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
|
||||
+ server.getLogger().log(Level.SEVERE, msg, ex);
|
||||
+ 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)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Tue, 8 Mar 2016 13:05:59 -0800
|
||||
Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java
|
||||
index 70fec73328227725f519af845ecbdce8be2fa4e2..04e7cd0e4e2d0eb38fb2862ce6688a4470f30d6b 100644
|
||||
--- a/src/main/java/org/bukkit/command/CommandSender.java
|
||||
+++ b/src/main/java/org/bukkit/command/CommandSender.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.bukkit.command;
|
||||
|
||||
import java.util.UUID;
|
||||
+import net.kyori.adventure.audience.MessageType;
|
||||
+import net.kyori.adventure.identity.Identity;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -168,5 +171,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe
|
||||
default void sendPlainMessage(final @NotNull String message) {
|
||||
this.sendMessage(net.kyori.adventure.text.Component.text(message));
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the component to the sender
|
||||
+ *
|
||||
+ * <p>If this sender does not support sending full components then
|
||||
+ * the component will be sent as legacy text.</p>
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ this.sendMessage(component.toLegacyText());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the sender
|
||||
+ *
|
||||
+ * <p>If this sender does not support sending full components then
|
||||
+ * the components will be sent as legacy text.</p>
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText());
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 29 Feb 2016 20:26:39 -0600
|
||||
Subject: [PATCH] Fix ServerListPingEvent flagging as Async
|
||||
|
||||
This event can sometimes fire Async, set the proper boolean
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/server/ServerEvent.java b/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
index 46b119017a1e3dfcd9ae5fb91b4fe8c20b0d6b86..05167fb34e4c42edc67af6e6700a2a3cc0f92769 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.event.server;
|
||||
|
||||
+import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
/**
|
||||
@@ -8,7 +9,7 @@ import org.bukkit.event.Event;
|
||||
public abstract class ServerEvent extends Event {
|
||||
|
||||
public ServerEvent() {
|
||||
- super();
|
||||
+ super(!Bukkit.isPrimaryThread()); // Paper
|
||||
}
|
||||
|
||||
public ServerEvent(boolean isAsync) {
|
569
patches/unapplied/api/0026-Player-Tab-List-and-Title-APIs.patch
Normal file
569
patches/unapplied/api/0026-Player-Tab-List-and-Title-APIs.patch
Normal file
|
@ -0,0 +1,569 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Mon, 29 Feb 2016 20:02:40 -0600
|
||||
Subject: [PATCH] Player Tab List and Title APIs
|
||||
|
||||
Co-authored-by: Fruxz <cedricspitzer@outlook.de>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb902cb35d8c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/Title.java
|
||||
@@ -0,0 +1,420 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import net.md_5.bungee.api.chat.BaseComponent;
|
||||
+import net.md_5.bungee.api.chat.TextComponent;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collection;
|
||||
+import java.util.List;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkArgument;
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+import static com.google.common.base.Preconditions.checkState;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a title to may be sent to a {@link Player}.
|
||||
+ *
|
||||
+ * <p>A title can be sent without subtitle text.</p>
|
||||
+ *
|
||||
+ * @deprecated use {@link net.kyori.adventure.title.Title}
|
||||
+ */
|
||||
+@Deprecated
|
||||
+public final class Title {
|
||||
+
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to fade in.
|
||||
+ */
|
||||
+ public static final int DEFAULT_FADE_IN = 20;
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to stay.
|
||||
+ */
|
||||
+ public static final int DEFAULT_STAY = 200;
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to fade out.
|
||||
+ */
|
||||
+ public static final int DEFAULT_FADE_OUT = 20;
|
||||
+
|
||||
+ private final BaseComponent[] title;
|
||||
+ private final BaseComponent[] subtitle;
|
||||
+ private final int fadeIn;
|
||||
+ private final int stay;
|
||||
+ private final int fadeOut;
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent[] title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull String title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull String title, @Nullable String subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ * @throws IllegalArgumentException if any of the times are negative
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ this(
|
||||
+ new BaseComponent[]{checkNotNull(title, "title")},
|
||||
+ subtitle == null ? null : new BaseComponent[]{subtitle},
|
||||
+ fadeIn,
|
||||
+ stay,
|
||||
+ fadeOut
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ * @throws IllegalArgumentException if any of the times are negative
|
||||
+ */
|
||||
+ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
||||
+ checkArgument(stay >= 0, "Negative stay: %s", stay);
|
||||
+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
||||
+ this.title = checkNotNull(title, "title");
|
||||
+ this.subtitle = subtitle;
|
||||
+ this.fadeIn = fadeIn;
|
||||
+ this.stay = stay;
|
||||
+ this.fadeOut = fadeOut;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} constrctors.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ */
|
||||
+ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ this(
|
||||
+ TextComponent.fromLegacyText(checkNotNull(title, "title")),
|
||||
+ subtitle == null ? null : TextComponent.fromLegacyText(subtitle),
|
||||
+ fadeIn,
|
||||
+ stay,
|
||||
+ fadeOut
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the text of this title
|
||||
+ *
|
||||
+ * @return the text
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public BaseComponent[] getTitle() {
|
||||
+ return this.title;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the text of this title's subtitle
|
||||
+ *
|
||||
+ * @return the text
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public BaseComponent[] getSubtitle() {
|
||||
+ return this.subtitle;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to fade in.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to fade in
|
||||
+ */
|
||||
+ public int getFadeIn() {
|
||||
+ return this.fadeIn;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to stay.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to stay
|
||||
+ */
|
||||
+ public int getStay() {
|
||||
+ return this.stay;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to fade out.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to fade out
|
||||
+ */
|
||||
+ public int getFadeOut() {
|
||||
+ return this.fadeOut;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to an player
|
||||
+ *
|
||||
+ * @param player the receiver of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Player player) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to the defined players
|
||||
+ *
|
||||
+ * @param players the receivers of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Collection<? extends Player> players) {
|
||||
+ for (Player player : players) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to the defined players
|
||||
+ *
|
||||
+ * @param players the receivers of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Player[] players) {
|
||||
+ for (Player player : players) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to all online players
|
||||
+ */
|
||||
+ public void broadcast() {
|
||||
+ send(Bukkit.getOnlinePlayers());
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static Builder builder() {
|
||||
+ return new Builder();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * A builder for creating titles
|
||||
+ */
|
||||
+ public static final class Builder {
|
||||
+
|
||||
+ private BaseComponent[] title;
|
||||
+ private BaseComponent[] subtitle;
|
||||
+ private int fadeIn = DEFAULT_FADE_IN;
|
||||
+ private int stay = DEFAULT_STAY;
|
||||
+ private int fadeOut = DEFAULT_FADE_OUT;
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull BaseComponent title) {
|
||||
+ return this.title(new BaseComponent[]{checkNotNull(title, "title")});
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull BaseComponent[] title) {
|
||||
+ this.title = checkNotNull(title, "title");
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} methods.</p>
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull String title) {
|
||||
+ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title")));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable BaseComponent subtitle) {
|
||||
+ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle});
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable BaseComponent[] subtitle) {
|
||||
+ this.subtitle = subtitle;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} methods.</p>
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable String subtitle) {
|
||||
+ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to fade in
|
||||
+ *
|
||||
+ * @param fadeIn the number of ticks to fade in
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder fadeIn(int fadeIn) {
|
||||
+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
||||
+ this.fadeIn = fadeIn;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to stay.
|
||||
+ *
|
||||
+ * @param stay the number of ticks to stay
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder stay(int stay) {
|
||||
+ checkArgument(stay >= 0, "Negative stay: %s", stay);
|
||||
+ this.stay = stay;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to fade out.
|
||||
+ *
|
||||
+ * @param fadeOut the number of ticks to fade out
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder fadeOut(int fadeOut) {
|
||||
+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
||||
+ this.fadeOut = fadeOut;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title based on the values in the builder.
|
||||
+ *
|
||||
+ * @return a title from the values in this builder
|
||||
+ * @throws IllegalStateException if title isn't specified
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Title build() {
|
||||
+ checkState(title != null, "Title not specified");
|
||||
+ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 944153f0d72c6ff5b7250e3d4b4591829deb16c2..2025cad529cf317384f6968b7fb65a555b0668c2 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1136,6 +1136,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
spigot().sendMessage(position, components);
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Set the text displayed in the player list header and footer for this player
|
||||
+ *
|
||||
+ * @param header content for the top of the player list
|
||||
+ * @param footer content for the bottom of the player list
|
||||
+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer);
|
||||
+
|
||||
+ /**
|
||||
+ * Set the text displayed in the player list header and footer for this player
|
||||
+ *
|
||||
+ * @param header content for the top of the player list
|
||||
+ * @param footer content for the bottom of the player list
|
||||
+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the times for titles displayed to the player
|
||||
+ *
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the subtitle of titles displayed to the player
|
||||
+ *
|
||||
+ * @param subtitle Subtitle to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the subtitle of titles displayed to the player
|
||||
+ *
|
||||
+ * @param subtitle Subtitle to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title to the player, along with the last subtitle set, using the last set times
|
||||
+ *
|
||||
+ * @param title Title to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title to the player, along with the last subtitle set, using the last set times
|
||||
+ *
|
||||
+ * @param title Title to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title and subtitle to the player using the given times
|
||||
+ *
|
||||
+ * @param title big text
|
||||
+ * @param subtitle little text under it
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title and subtitle to the player using the given times
|
||||
+ *
|
||||
+ * @param title big text
|
||||
+ * @param subtitle little text under it
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the title to the player, overriding any previously displayed title.
|
||||
+ *
|
||||
+ * <p>This method overrides any previous title, use {@link #updateTitle(com.destroystokyo.paper.Title)} to change the existing one.</p>
|
||||
+ *
|
||||
+ * @param title the title to send
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void sendTitle(@NotNull com.destroystokyo.paper.Title title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the title to the player, overriding any previously displayed title.
|
||||
+ *
|
||||
+ * <p>This method doesn't override previous titles, but changes their values.</p>
|
||||
+ *
|
||||
+ * @param title the title to send
|
||||
+ * @throws NullPointerException if title is null
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void updateTitle(@NotNull com.destroystokyo.paper.Title title);
|
||||
+
|
||||
+ /**
|
||||
+ * Hide any title that is currently visible to the player
|
||||
+ *
|
||||
+ * @deprecated use {@link #clearTitle()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void hideTitle();
|
||||
// Paper end
|
||||
|
||||
/**
|
|
@ -0,0 +1,65 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mrapple <tony@oc.tc>
|
||||
Date: Sun, 25 Nov 2012 13:47:27 -0600
|
||||
Subject: [PATCH] Add methods for working with arrows stuck in living entities
|
||||
|
||||
Upstream added methods for this so the original methods
|
||||
are now deprecated
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
index 7c82644de3c438f45476ac02ce2c51c6fdbd543a..390bb294d09389877937ee2c6c3f346e65dfb178 100644
|
||||
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
@@ -215,12 +215,26 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
*/
|
||||
public int getArrowsInBody();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Set the amount of arrows in the entity's body.
|
||||
+ * <p>
|
||||
+ * Does not fire the {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent}.
|
||||
+ *
|
||||
+ * @param count amount of arrows in entity's body
|
||||
+ */
|
||||
+ default void setArrowsInBody(final int count) {
|
||||
+ this.setArrowsInBody(count, false);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Set the amount of arrows in the entity's body.
|
||||
*
|
||||
* @param count amount of arrows in entity's body
|
||||
+ * @param fireEvent whether to fire the {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent} event
|
||||
*/
|
||||
- public void setArrowsInBody(int count);
|
||||
+ void setArrowsInBody(int count, boolean fireEvent); // Paper
|
||||
|
||||
/**
|
||||
* Returns the living entity's current maximum no damage ticks.
|
||||
@@ -722,4 +736,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
* @return Whether the entity is invisible
|
||||
*/
|
||||
public boolean isInvisible();
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Get the number of arrows stuck in this entity
|
||||
+ * @return Number of arrows stuck
|
||||
+ * @deprecated use {@link #getArrowsInBody()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ int getArrowsStuck();
|
||||
+
|
||||
+ /**
|
||||
+ * Set the number of arrows stuck in this entity
|
||||
+ *
|
||||
+ * @param arrows Number of arrows to stick in this entity
|
||||
+ * @deprecated use {@link #setArrowsInBody(int, boolean)}. <b>This method previously fired {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent} so if
|
||||
+ * you want to retain exact functionality, pass {@code true} for {@code fireEvent}.</b>
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void setArrowsStuck(int arrows);
|
||||
+ // Paper end
|
||||
}
|
182
patches/unapplied/api/0028-Complete-resource-pack-API.patch
Normal file
182
patches/unapplied/api/0028-Complete-resource-pack-API.patch
Normal file
|
@ -0,0 +1,182 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sat, 4 Apr 2015 22:59:54 -0400
|
||||
Subject: [PATCH] Complete resource pack API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 2025cad529cf317384f6968b7fb65a555b0668c2..f2311a9842a4d7c45fc88b9f8ca485005a3b3352 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1716,7 +1716,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @throws IllegalArgumentException Thrown if the URL is null.
|
||||
* @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
* length restriction is an implementation specific arbitrary value.
|
||||
+ * @deprecated use {@link #setResourcePack(String, String)}
|
||||
*/
|
||||
+ @Deprecated // Paper
|
||||
public void setResourcePack(@NotNull String url);
|
||||
|
||||
/**
|
||||
@@ -2563,6 +2565,124 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
|
||||
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName())));
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Request that the player's client download and switch resource packs.
|
||||
+ * <p>
|
||||
+ * The player's client will download the new resource pack asynchronously
|
||||
+ * in the background, and will automatically switch to it once the
|
||||
+ * download is complete. If the client has downloaded and cached the same
|
||||
+ * resource pack in the past, it will perform a quick timestamp check
|
||||
+ * over the network to determine if the resource pack has changed and
|
||||
+ * needs to be downloaded again. When this request is sent for the very
|
||||
+ * first time from a given server, the client will first display a
|
||||
+ * confirmation GUI to the player before proceeding with the download.
|
||||
+ * <p>
|
||||
+ * Notes:
|
||||
+ * <ul>
|
||||
+ * <li>Players can disable server resources on their client, in which
|
||||
+ * case this method will have no affect on them.
|
||||
+ * <li>There is no concept of resetting resource packs back to default
|
||||
+ * within Minecraft, so players will have to relog to do so.
|
||||
+ * </ul>
|
||||
+ *
|
||||
+ * @param url The URL from which the client will download the resource
|
||||
+ * pack. The string must contain only US-ASCII characters and should
|
||||
+ * be encoded as per RFC 1738.
|
||||
+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of
|
||||
+ * the resource pack file.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is null.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
+ * length restriction is an implementation specific arbitrary value.
|
||||
+ */
|
||||
+ void setResourcePack(@NotNull String url, @NotNull String hash);
|
||||
+
|
||||
+ /**
|
||||
+ * Request that the player's client download and switch resource packs.
|
||||
+ * <p>
|
||||
+ * The player's client will download the new resource pack asynchronously
|
||||
+ * in the background, and will automatically switch to it once the
|
||||
+ * download is complete. If the client has downloaded and cached the same
|
||||
+ * resource pack in the past, it will perform a quick timestamp check
|
||||
+ * over the network to determine if the resource pack has changed and
|
||||
+ * needs to be downloaded again. When this request is sent for the very
|
||||
+ * first time from a given server, the client will first display a
|
||||
+ * confirmation GUI to the player before proceeding with the download.
|
||||
+ * <p>
|
||||
+ * Notes:
|
||||
+ * <ul>
|
||||
+ * <li>Players can disable server resources on their client, in which
|
||||
+ * case this method will have no affect on them.
|
||||
+ * <li>There is no concept of resetting resource packs back to default
|
||||
+ * within Minecraft, so players will have to relog to do so.
|
||||
+ * </ul>
|
||||
+ *
|
||||
+ * @param url The URL from which the client will download the resource
|
||||
+ * pack. The string must contain only US-ASCII characters and should
|
||||
+ * be encoded as per RFC 1738.
|
||||
+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of
|
||||
+ * the resource pack file.
|
||||
+ * @param required Marks if the resource pack should be required by the client
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is null.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
+ * length restriction is an implementation specific arbitrary value.
|
||||
+ */
|
||||
+ void setResourcePack(@NotNull String url, @NotNull String hash, boolean required);
|
||||
+
|
||||
+ /**
|
||||
+ * Request that the player's client download and switch resource packs.
|
||||
+ * <p>
|
||||
+ * The player's client will download the new resource pack asynchronously
|
||||
+ * in the background, and will automatically switch to it once the
|
||||
+ * download is complete. If the client has downloaded and cached the same
|
||||
+ * resource pack in the past, it will perform a quick timestamp check
|
||||
+ * over the network to determine if the resource pack has changed and
|
||||
+ * needs to be downloaded again. When this request is sent for the very
|
||||
+ * first time from a given server, the client will first display a
|
||||
+ * confirmation GUI to the player before proceeding with the download.
|
||||
+ * <p>
|
||||
+ * Notes:
|
||||
+ * <ul>
|
||||
+ * <li>Players can disable server resources on their client, in which
|
||||
+ * case this method will have no affect on them.
|
||||
+ * <li>There is no concept of resetting resource packs back to default
|
||||
+ * within Minecraft, so players will have to relog to do so.
|
||||
+ * </ul>
|
||||
+ *
|
||||
+ * @param url The URL from which the client will download the resource
|
||||
+ * pack. The string must contain only US-ASCII characters and should
|
||||
+ * be encoded as per RFC 1738.
|
||||
+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of
|
||||
+ * the resource pack file.
|
||||
+ * @param required Marks if the resource pack should be required by the client
|
||||
+ * @param resourcePackPrompt A Prompt to be displayed in the client request
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is null.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
+ * length restriction is an implementation specific arbitrary value.
|
||||
+ */
|
||||
+ void setResourcePack(@NotNull String url, @NotNull String hash, boolean required, @Nullable net.kyori.adventure.text.Component resourcePackPrompt);
|
||||
+ /**
|
||||
+ * @return the most recent resource pack status received from the player,
|
||||
+ * or null if no status has ever been received from this player.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus();
|
||||
+
|
||||
+ /**
|
||||
+ * @return the most recent resource pack hash received from the player,
|
||||
+ * or null if no hash has ever been received from this player.
|
||||
+ *
|
||||
+ * @deprecated This is no longer sent from the client and will always be null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated
|
||||
+ String getResourcePackHash();
|
||||
+
|
||||
+ /**
|
||||
+ * @return true if the last resource pack status received from this player
|
||||
+ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED}
|
||||
+ */
|
||||
+ boolean hasResourcePack();
|
||||
// Paper end
|
||||
|
||||
// Spigot start
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
index b98195650d49d78ec35970ca0376b6289b861e4b..4c2102a11c3d682d98f0db4ccafa35231e66bcdd 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
@@ -11,13 +11,32 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class PlayerResourcePackStatusEvent extends PlayerEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
+ @Deprecated
|
||||
+ private final String hash; // Paper
|
||||
private final Status status;
|
||||
|
||||
public PlayerResourcePackStatusEvent(@NotNull final Player who, @NotNull Status resourcePackStatus) {
|
||||
super(who);
|
||||
+ this.hash = null; // Paper
|
||||
this.status = resourcePackStatus;
|
||||
}
|
||||
|
||||
+ @Deprecated // Paper
|
||||
+ public PlayerResourcePackStatusEvent(final Player who, Status resourcePackStatus, String hash) {
|
||||
+ super(who);
|
||||
+ this.hash = hash; // Paper
|
||||
+ this.status = resourcePackStatus;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ /**
|
||||
+ * @deprecated Hash does not seem to ever be set
|
||||
+ */
|
||||
+ public String getHash() {
|
||||
+ return this.hash;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the status of this pack.
|
||||
*
|
34
patches/unapplied/api/0029-Add-a-call-helper-to-Event.patch
Normal file
34
patches/unapplied/api/0029-Add-a-call-helper-to-Event.patch
Normal file
|
@ -0,0 +1,34 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 19 May 2013 20:36:58 -0400
|
||||
Subject: [PATCH] Add a call helper to Event
|
||||
|
||||
Reduces diff in Server patches
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java
|
||||
index 18d0636b749913bfdcea8eebc7d0840d192fb071..8ec56cd6b8e0f5c5dd8c7c88b4671e18dcf109d0 100644
|
||||
--- a/src/main/java/org/bukkit/event/Event.java
|
||||
+++ b/src/main/java/org/bukkit/event/Event.java
|
||||
@@ -35,6 +35,22 @@ public abstract class Event {
|
||||
this.async = isAsync;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Calls the event and tests if cancelled.
|
||||
+ *
|
||||
+ * @return false if event was cancelled, if cancellable. otherwise true.
|
||||
+ */
|
||||
+ public boolean callEvent() {
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(this);
|
||||
+ if (this instanceof Cancellable) {
|
||||
+ return !((Cancellable) this).isCancelled();
|
||||
+ } else {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Convenience method for providing a user-friendly identifier. By
|
||||
* default, it is the event's class's {@linkplain Class#getSimpleName()
|
|
@ -0,0 +1,43 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 22 Jul 2015 18:50:41 -0400
|
||||
Subject: [PATCH] Add sender name to commands.yml replacement
|
||||
|
||||
This allows you to use $sender in commands.yml definitions to make
|
||||
commands that auto target self.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
index a6ad94ef98a1df1d2842635d850bc990b0137849..9d4f553c04784cca63901a56a7aea62a5cae1d72 100644
|
||||
--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.bukkit.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
+import java.util.regex.Matcher; // Paper
|
||||
+import java.util.regex.Pattern; // Paper
|
||||
+
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -19,7 +22,7 @@ public class FormattedCommandAlias extends Command {
|
||||
ArrayList<String> commands = new ArrayList<String>();
|
||||
for (String formatString : formatStrings) {
|
||||
try {
|
||||
- commands.add(buildCommand(formatString, args));
|
||||
+ commands.add(buildCommand(sender, formatString, args)); // Paper
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof IllegalArgumentException) {
|
||||
sender.sendMessage(throwable.getMessage());
|
||||
@@ -37,7 +40,10 @@ public class FormattedCommandAlias extends Command {
|
||||
return result;
|
||||
}
|
||||
|
||||
- private String buildCommand(@NotNull String formatString, @NotNull String[] args) {
|
||||
+ private String buildCommand(@NotNull CommandSender sender, @NotNull String formatString, @NotNull String[] args) { // Paper
|
||||
+ if (formatString.contains("$sender")) { // Paper
|
||||
+ formatString = formatString.replaceAll(Pattern.quote("$sender"), Matcher.quoteReplacement(sender.getName())); // Paper
|
||||
+ } // Paper
|
||||
int index = formatString.indexOf('$');
|
||||
while (index != -1) {
|
||||
int start = index;
|
|
@ -0,0 +1,86 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William <admin@domnian.com>
|
||||
Date: Fri, 18 Mar 2016 03:28:07 -0400
|
||||
Subject: [PATCH] Add command to reload permissions.yml and require confirm to
|
||||
reload
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 3118da2ad367b5bd547769214112ea5299c95866..7b467aedbcf3a6174bfb12ded3b27775a7eaf45c 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2276,6 +2276,13 @@ public final class Bukkit {
|
||||
public static org.bukkit.command.CommandMap getCommandMap() {
|
||||
return server.getCommandMap();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Reload the Permissions in permissions.yml
|
||||
+ */
|
||||
+ public static void reloadPermissions() {
|
||||
+ server.reloadPermissions();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index d94483d1481f233897faf378e6b34b6b97f02caf..c5591e82e14e299facfc767a20f2eed77354caac 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2012,4 +2012,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@NotNull
|
||||
Spigot spigot();
|
||||
// Spigot end
|
||||
+
|
||||
+ void reloadPermissions(); // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..5fa9d648bc780e874f658597f1a24715bccac5cb 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand {
|
||||
public ReloadCommand(@NotNull String name) {
|
||||
super(name);
|
||||
this.description = "Reloads the server configuration and plugins";
|
||||
- this.usageMessage = "/reload";
|
||||
+ this.usageMessage = "/reload [permissions]"; // Paper
|
||||
this.setPermission("bukkit.command.reload");
|
||||
this.setAliases(Arrays.asList("rl"));
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
|
||||
+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper
|
||||
if (!testPermission(sender)) return true;
|
||||
|
||||
+ // Paper start - Reload permissions.yml & require confirm
|
||||
+ boolean confirmed = System.getProperty("LetMeReload") != null;
|
||||
+ if (args.length == 1) {
|
||||
+ if (args[0].equalsIgnoreCase("permissions")) {
|
||||
+ Bukkit.getServer().reloadPermissions();
|
||||
+ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Permissions successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN));
|
||||
+ return true;
|
||||
+ } else if ("confirm".equalsIgnoreCase(args[0])) {
|
||||
+ confirmed = true;
|
||||
+ } else {
|
||||
+ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Usage: " + usageMessage, net.kyori.adventure.text.format.NamedTextColor.RED));
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!confirmed) {
|
||||
+ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type ", net.kyori.adventure.text.format.NamedTextColor.RED).append(net.kyori.adventure.text.Component.text("/reload confirm", net.kyori.adventure.text.format.NamedTextColor.YELLOW)));
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins.");
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server.");
|
||||
Bukkit.reload();
|
||||
@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException {
|
||||
- return Collections.emptyList();
|
||||
+ return java.util.Collections.singletonList("permissions"); // Paper
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sun, 21 Jun 2015 15:05:21 -0400
|
||||
Subject: [PATCH] Custom replacement for eaten items
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
index 5c054eb531e3caf17c179aff6a712fb8c33d8f77..6110d0417340710333b44312d82c7bd5165a8954 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
@@ -24,6 +24,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable {
|
||||
private boolean isCancelled = false;
|
||||
private ItemStack item;
|
||||
private final EquipmentSlot hand;
|
||||
+ @Nullable private ItemStack replacement; // Paper
|
||||
|
||||
/**
|
||||
* @param player the player consuming
|
||||
@@ -82,6 +83,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable {
|
||||
return hand;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Return the custom item stack that will replace the consumed item, or null if no
|
||||
+ * custom replacement has been set (which means the default replacement will be used).
|
||||
+ *
|
||||
+ * @return The custom item stack that will replace the consumed item or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public ItemStack getReplacement() {
|
||||
+ return this.replacement;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set a custom item stack to replace the consumed item. Pass null to clear any custom
|
||||
+ * stack that has been set and use the default replacement.
|
||||
+ *
|
||||
+ * @param replacement Replacement item to set, null to clear any custom stack and use default
|
||||
+ */
|
||||
+ public void setReplacement(@Nullable ItemStack replacement) {
|
||||
+ this.replacement = replacement;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.isCancelled;
|
|
@ -0,0 +1,79 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 20:26:34 -0400
|
||||
Subject: [PATCH] Entity AddTo/RemoveFrom World Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..07660202e41ee86f1b66bad3335cf6fe126e7f9c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
|
||||
@@ -0,0 +1,32 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired any time an entity is being added to the world for any reason.
|
||||
+ *
|
||||
+ * Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent}
|
||||
+ * This will fire anytime a chunk is reloaded too.
|
||||
+ */
|
||||
+public class EntityAddToWorldEvent extends EntityEvent {
|
||||
+
|
||||
+ public EntityAddToWorldEvent(@NotNull Entity entity) {
|
||||
+ super(entity);
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e5dbbd660409bae0d3b96e83390511d3a423a52e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired any time an entity is being removed from a world for any reason
|
||||
+ */
|
||||
+public class EntityRemoveFromWorldEvent extends EntityEvent {
|
||||
+
|
||||
+ public EntityRemoveFromWorldEvent(@NotNull Entity entity) {
|
||||
+ super(entity);
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
95
patches/unapplied/api/0034-EntityPathfindEvent.patch
Normal file
95
patches/unapplied/api/0034-EntityPathfindEvent.patch
Normal file
|
@ -0,0 +1,95 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 21:15:34 -0400
|
||||
Subject: [PATCH] EntityPathfindEvent
|
||||
|
||||
Fires when an Entity decides to start moving to a location.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..63e46b2fb1b12b36fcb1e98b178cf29dd2e3d1b5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
|
||||
@@ -0,0 +1,82 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when an Entity decides to start moving towards a location.
|
||||
+ *
|
||||
+ * This event does not fire for the entities actual movement. Only when it
|
||||
+ * is choosing to start moving to a location.
|
||||
+ */
|
||||
+public class EntityPathfindEvent extends EntityEvent implements Cancellable {
|
||||
+ @Nullable private final Entity targetEntity;
|
||||
+ @NotNull private final Location loc;
|
||||
+
|
||||
+ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) {
|
||||
+ super(entity);
|
||||
+ this.targetEntity = targetEntity;
|
||||
+ this.loc = loc;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The Entity that is pathfinding.
|
||||
+ * @return The Entity that is pathfinding.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Entity getEntity() {
|
||||
+ return entity;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If the Entity is trying to pathfind to an entity, this is the entity in relation.
|
||||
+ *
|
||||
+ * Otherwise this will return null.
|
||||
+ *
|
||||
+ * @return The entity target or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Entity getTargetEntity() {
|
||||
+ return targetEntity;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The Location of where the entity is about to move to.
|
||||
+ *
|
||||
+ * Note that if the target happened to of been an entity
|
||||
+ * @return Location of where the entity is trying to pathfind to.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getLoc() {
|
||||
+ return loc;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,90 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: crast <contact@jamescrasta.com>
|
||||
Date: Sat, 1 Jun 2013 13:52:30 -0600
|
||||
Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase
|
||||
|
||||
Use ConcurrentHashMap to allow thread-safe access methods and very
|
||||
limited synchronized portions to allow much higher concurrency in
|
||||
MetadataStore as well as far less locking, especially on reads
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
index 6886a7003fb76d07e0fa9c1c352c56480f08a0db..a0698522f01619c9d37474f4bd55a17de58fff89 100644
|
||||
--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class MetadataStoreBase<T> {
|
||||
- private Map<String, Map<Plugin, MetadataValue>> metadataMap = new HashMap<String, Map<Plugin, MetadataValue>>();
|
||||
+ private Map<String, Map<Plugin, MetadataValue>> metadataMap = new java.util.concurrent.ConcurrentHashMap<String, Map<Plugin, MetadataValue>>(); // Paper
|
||||
|
||||
/**
|
||||
* Adds a metadata value to an object. Each metadata value is owned by a
|
||||
@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase<T> {
|
||||
entry = new WeakHashMap<Plugin, MetadataValue>(1);
|
||||
metadataMap.put(key, entry);
|
||||
}
|
||||
- entry.put(owningPlugin, newMetadataValue);
|
||||
+ synchronized (entry) {
|
||||
+ entry.put(owningPlugin, newMetadataValue);
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @see MetadataStore#getMetadata(Object, String)
|
||||
*/
|
||||
@NotNull
|
||||
- public synchronized List<MetadataValue> getMetadata(@NotNull T subject, @NotNull String metadataKey) {
|
||||
+ public List<MetadataValue> getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
- if (metadataMap.containsKey(key)) {
|
||||
- Collection<MetadataValue> values = metadataMap.get(key).values();
|
||||
+ Map<Plugin, MetadataValue> entry = metadataMap.get(key);
|
||||
+ if (entry != null) {
|
||||
+ Collection<MetadataValue> values = entry.values();
|
||||
return Collections.unmodifiableList(new ArrayList<MetadataValue>(values));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @param metadataKey the unique metadata key being queried.
|
||||
* @return the existence of the metadataKey within subject.
|
||||
*/
|
||||
- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) {
|
||||
+ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
return metadataMap.containsKey(key);
|
||||
}
|
||||
@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @see MetadataStore#removeMetadata(Object, String,
|
||||
* org.bukkit.plugin.Plugin)
|
||||
*/
|
||||
- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) {
|
||||
+ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper
|
||||
Preconditions.checkArgument(owningPlugin != null, "Plugin cannot be null");
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
Map<Plugin, MetadataValue> entry = metadataMap.get(key);
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
-
|
||||
- entry.remove(owningPlugin);
|
||||
- if (entry.isEmpty()) {
|
||||
- metadataMap.remove(key);
|
||||
+ synchronized (entry) {
|
||||
+ entry.remove(owningPlugin);
|
||||
+ if (entry.isEmpty()) {
|
||||
+ metadataMap.remove(key);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @throws IllegalArgumentException If plugin is null
|
||||
* @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin)
|
||||
*/
|
||||
- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) {
|
||||
+ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper
|
||||
Preconditions.checkArgument(owningPlugin != null, "Plugin cannot be null");
|
||||
for (Map<Plugin, MetadataValue> values : metadataMap.values()) {
|
||||
if (values.containsKey(owningPlugin)) {
|
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 16 Jul 2013 21:26:50 -0400
|
||||
Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin)
|
||||
|
||||
So that on reload, metadata will be cleared
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
index a0698522f01619c9d37474f4bd55a17de58fff89..a298baaa7a126515bb2802dd311f8487f3e5533f 100644
|
||||
--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
@@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
+import java.util.Iterator; // Paper
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase<T> {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Removes all metadata in the metadata store that originates from the
|
||||
+ * given plugin.
|
||||
+ *
|
||||
+ * @param owningPlugin the plugin requesting the invalidation.
|
||||
+ * @throws IllegalArgumentException If plugin is null
|
||||
+ */
|
||||
+ public void removeAll(@NotNull Plugin owningPlugin) {
|
||||
+ Preconditions.checkNotNull(owningPlugin, "Plugin cannot be null");
|
||||
+ for (Iterator<Map<Plugin, MetadataValue>> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) {
|
||||
+ Map<Plugin, MetadataValue> values = iterator.next();
|
||||
+ if (values.containsKey(owningPlugin)) {
|
||||
+ values.remove(owningPlugin);
|
||||
+ }
|
||||
+ if (values.isEmpty()) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Creates a unique name for the object receiving metadata by combining
|
||||
* unique data from the subject with a metadataKey.
|
|
@ -0,0 +1,98 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sat, 2 Apr 2016 05:08:36 -0400
|
||||
Subject: [PATCH] Add PlayerUseUnknownEntityEvent
|
||||
|
||||
Adds the PlayerUseUnknownEntityEvent to be used by plugins dealing with
|
||||
virtual entities/entities that are not actually known to the server.
|
||||
|
||||
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a7228e248e3d8eb2e9f011dfe2c7dd9f3f48000f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java
|
||||
@@ -0,0 +1,82 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.bukkit.inventory.EquipmentSlot;
|
||||
+import org.bukkit.util.Vector;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents an event that is called when a player right-clicks an unknown entity.
|
||||
+ * Useful for plugins dealing with virtual entities (entities that don't actually spawned on the server).
|
||||
+ * <br>
|
||||
+ * This event may be called multiple times per interaction with different interaction hands
|
||||
+ * and with or without the clicked position.
|
||||
+ */
|
||||
+public class PlayerUseUnknownEntityEvent extends PlayerEvent {
|
||||
+
|
||||
+ private static final HandlerList HANDLERS = new HandlerList();
|
||||
+ private final int entityId;
|
||||
+ private final boolean attack;
|
||||
+ private final @NotNull EquipmentSlot hand;
|
||||
+ private final @Nullable Vector clickedPosition;
|
||||
+
|
||||
+ public PlayerUseUnknownEntityEvent(@NotNull Player who, int entityId, boolean attack, @NotNull EquipmentSlot hand, @Nullable Vector clickedPosition) {
|
||||
+ super(who);
|
||||
+ this.entityId = entityId;
|
||||
+ this.attack = attack;
|
||||
+ this.hand = hand;
|
||||
+ this.clickedPosition = clickedPosition;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the entity id of the unknown entity that was interacted with.
|
||||
+ *
|
||||
+ * @return the entity id of the entity that was interacted with
|
||||
+ */
|
||||
+ public int getEntityId() {
|
||||
+ return this.entityId;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether the interaction was an attack.
|
||||
+ *
|
||||
+ * @return true if the player is attacking the entity, false if the player is interacting with the entity
|
||||
+ */
|
||||
+ public boolean isAttack() {
|
||||
+ return this.attack;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the hand used to perform this interaction.
|
||||
+ *
|
||||
+ * @return the hand used to interact
|
||||
+ */
|
||||
+ public @NotNull EquipmentSlot getHand() {
|
||||
+ return this.hand;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the position relative to the entity that was clicked, or null if not available.
|
||||
+ * See {@link org.bukkit.event.player.PlayerInteractAtEntityEvent} for more details.
|
||||
+ *
|
||||
+ * @return the position relative to the entity that was clicked, or null if not available
|
||||
+ * @see org.bukkit.event.player.PlayerInteractAtEntityEvent
|
||||
+ */
|
||||
+ public @Nullable Vector getClickedRelativePosition() {
|
||||
+ return this.clickedPosition != null ? this.clickedPosition.clone() : null;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,290 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 13 Apr 2016 20:20:18 -0700
|
||||
Subject: [PATCH] Add handshake event to allow plugins to handle client
|
||||
handshaking logic themselves
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..59ae7bc3a0a2079fe4b3a92d777aca682a58e4e3
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java
|
||||
@@ -0,0 +1,277 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+/**
|
||||
+ * This event is fired during a player handshake.
|
||||
+ *
|
||||
+ * <p>If there are no listeners listening to this event, the logic default
|
||||
+ * to your server platform will be ran.</p>
|
||||
+ *
|
||||
+ * <p>WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS</p>
|
||||
+ */
|
||||
+public class PlayerHandshakeEvent extends Event implements Cancellable {
|
||||
+
|
||||
+ private static final HandlerList HANDLERS = new HandlerList();
|
||||
+ @NotNull private final String originalHandshake;
|
||||
+ @NotNull private final String originalSocketAddressHostname;
|
||||
+ private boolean cancelled;
|
||||
+ @Nullable private String serverHostname;
|
||||
+ @Nullable private String socketAddressHostname;
|
||||
+ @Nullable private UUID uniqueId;
|
||||
+ @Nullable private String propertiesJson;
|
||||
+ private boolean failed;
|
||||
+ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new {@link PlayerHandshakeEvent}.
|
||||
+ *
|
||||
+ * @param originalHandshake the original handshake string
|
||||
+ * @param cancelled if this event is enabled
|
||||
+ *
|
||||
+ * @deprecated in favour of {@link PlayerHandshakeEvent(String, String, boolean)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) {
|
||||
+ this(originalHandshake, "127.0.0.1", cancelled);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new {@link PlayerHandshakeEvent}.
|
||||
+ *
|
||||
+ * @param originalHandshake the original handshake string
|
||||
+ * @param originalSocketAddressHostname the original socket address hostname
|
||||
+ * @param cancelled if this event is enabled
|
||||
+ */
|
||||
+ public PlayerHandshakeEvent(@NotNull String originalHandshake, @NotNull String originalSocketAddressHostname, boolean cancelled) {
|
||||
+ super(true);
|
||||
+ this.originalHandshake = originalHandshake;
|
||||
+ this.originalSocketAddressHostname = originalSocketAddressHostname;
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Determines if this event is cancelled.
|
||||
+ *
|
||||
+ * <p>When this event is cancelled, custom handshake logic will not
|
||||
+ * be processed.</p>
|
||||
+ *
|
||||
+ * @return {@code true} if this event is cancelled, {@code false} otherwise
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return this.cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets if this event is cancelled.
|
||||
+ *
|
||||
+ * <p>When this event is cancelled, custom handshake logic will not
|
||||
+ * be processed.</p>
|
||||
+ *
|
||||
+ * @param cancelled {@code true} if this event is cancelled, {@code false} otherwise
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancelled) {
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the original handshake string.
|
||||
+ *
|
||||
+ * @return the original handshake string
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getOriginalHandshake() {
|
||||
+ return this.originalHandshake;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the original socket address hostname.
|
||||
+ *
|
||||
+ * <p>This does not include the port.</p>
|
||||
+ * <p>In cases where this event is manually fired and the plugin wasn't updated yet, the default is {@code "127.0.0.1"}.</p>
|
||||
+ *
|
||||
+ * @return the original socket address hostname
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getOriginalSocketAddressHostname() {
|
||||
+ return this.originalSocketAddressHostname;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the server hostname string.
|
||||
+ *
|
||||
+ * <p>This should not include the port.</p>
|
||||
+ *
|
||||
+ * @return the server hostname string
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getServerHostname() {
|
||||
+ return this.serverHostname;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the server hostname string.
|
||||
+ *
|
||||
+ * <p>This should not include the port.</p>
|
||||
+ *
|
||||
+ * @param serverHostname the server hostname string
|
||||
+ */
|
||||
+ public void setServerHostname(@NotNull String serverHostname) {
|
||||
+ this.serverHostname = serverHostname;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the socket address hostname string.
|
||||
+ *
|
||||
+ * <p>This should not include the port.</p>
|
||||
+ *
|
||||
+ * @return the socket address hostname string
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getSocketAddressHostname() {
|
||||
+ return this.socketAddressHostname;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the socket address hostname string.
|
||||
+ *
|
||||
+ * <p>This should not include the port.</p>
|
||||
+ *
|
||||
+ * @param socketAddressHostname the socket address hostname string
|
||||
+ */
|
||||
+ public void setSocketAddressHostname(@NotNull String socketAddressHostname) {
|
||||
+ this.socketAddressHostname = socketAddressHostname;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the unique id.
|
||||
+ *
|
||||
+ * @return the unique id
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public UUID getUniqueId() {
|
||||
+ return this.uniqueId;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the unique id.
|
||||
+ *
|
||||
+ * @param uniqueId the unique id
|
||||
+ */
|
||||
+ public void setUniqueId(@NotNull UUID uniqueId) {
|
||||
+ this.uniqueId = uniqueId;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the profile properties.
|
||||
+ *
|
||||
+ * <p>This should be a valid JSON string.</p>
|
||||
+ *
|
||||
+ * @return the profile properties, as JSON
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getPropertiesJson() {
|
||||
+ return this.propertiesJson;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Determines if authentication failed.
|
||||
+ *
|
||||
+ * <p>When {@code true}, the client connecting will be disconnected
|
||||
+ * with the {@link #getFailMessage() fail message}.</p>
|
||||
+ *
|
||||
+ * @return {@code true} if authentication failed, {@code false} otherwise
|
||||
+ */
|
||||
+ public boolean isFailed() {
|
||||
+ return this.failed;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets if authentication failed and the client should be disconnected.
|
||||
+ *
|
||||
+ * <p>When {@code true}, the client connecting will be disconnected
|
||||
+ * with the {@link #getFailMessage() fail message}.</p>
|
||||
+ *
|
||||
+ * @param failed {@code true} if authentication failed, {@code false} otherwise
|
||||
+ */
|
||||
+ public void setFailed(boolean failed) {
|
||||
+ this.failed = failed;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the profile properties.
|
||||
+ *
|
||||
+ * <p>This should be a valid JSON string.</p>
|
||||
+ *
|
||||
+ * @param propertiesJson the profile properties, as JSON
|
||||
+ */
|
||||
+ public void setPropertiesJson(@NotNull String propertiesJson) {
|
||||
+ this.propertiesJson = propertiesJson;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the message to display to the client when authentication fails.
|
||||
+ *
|
||||
+ * @return the message to display to the client
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Component failMessage() {
|
||||
+ return this.failMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the message to display to the client when authentication fails.
|
||||
+ *
|
||||
+ * @param failMessage the message to display to the client
|
||||
+ */
|
||||
+ public void failMessage(@NotNull Component failMessage) {
|
||||
+ this.failMessage = failMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the message to display to the client when authentication fails.
|
||||
+ *
|
||||
+ * @return the message to display to the client
|
||||
+ * @deprecated use {@link #failMessage()}
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Deprecated
|
||||
+ public String getFailMessage() {
|
||||
+ return LegacyComponentSerializer.legacySection().serialize(this.failMessage());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the message to display to the client when authentication fails.
|
||||
+ *
|
||||
+ * @param failMessage the message to display to the client
|
||||
+ * @deprecated use {@link #failMessage(Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setFailMessage(@NotNull String failMessage) {
|
||||
+ Preconditions.checkArgument(failMessage != null && !failMessage.isEmpty(), "fail message cannot be null or empty");
|
||||
+ this.failMessage(LegacyComponentSerializer.legacySection().deserialize(failMessage));
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+}
|
49
patches/unapplied/api/0039-Arrow-pickup-rule-API.patch
Normal file
49
patches/unapplied/api/0039-Arrow-pickup-rule-API.patch
Normal file
|
@ -0,0 +1,49 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Fri, 4 Mar 2016 03:13:18 -0500
|
||||
Subject: [PATCH] Arrow pickup rule API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java
|
||||
index 5b50a4e10e8ace8cc53ad3c8d7c3185f88d5c8db..e8e56e89e32d84af0639fe2e9b0eeabd747b6007 100644
|
||||
--- a/src/main/java/org/bukkit/entity/AbstractArrow.java
|
||||
+++ b/src/main/java/org/bukkit/entity/AbstractArrow.java
|
||||
@@ -141,4 +141,38 @@ public interface AbstractArrow extends Projectile {
|
||||
*/
|
||||
CREATIVE_ONLY
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the {@link PickupRule} for this arrow.
|
||||
+ *
|
||||
+ * <p>This is generally {@link PickupRule#ALLOWED} only if the arrow was
|
||||
+ * <b>not</b> fired from a bow with the infinity enchantment.</p>
|
||||
+ *
|
||||
+ * @return The pickup rule
|
||||
+ * @deprecated Use {@link Arrow#getPickupStatus()} as an upstream compatible replacement for this function
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default PickupRule getPickupRule() {
|
||||
+ return PickupRule.valueOf(this.getPickupStatus().name());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set the rule for which players can pickup this arrow as an item.
|
||||
+ *
|
||||
+ * @param rule The pickup rule
|
||||
+ * @deprecated Use {@link Arrow#setPickupStatus(PickupStatus)} with {@link PickupStatus} as an upstream compatible replacement for this function
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void setPickupRule(PickupRule rule) {
|
||||
+ this.setPickupStatus(PickupStatus.valueOf(rule.name()));
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ enum PickupRule {
|
||||
+ DISALLOWED,
|
||||
+ ALLOWED,
|
||||
+ CREATIVE_ONLY;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Fri, 22 Apr 2016 01:43:11 -0500
|
||||
Subject: [PATCH] EntityRegainHealthEvent isFastRegen API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java
|
||||
index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f2355ebfcb4a 100644
|
||||
--- a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java
|
||||
@@ -13,12 +13,31 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable
|
||||
private boolean cancelled;
|
||||
private double amount;
|
||||
private final RegainReason regainReason;
|
||||
+ private final boolean isFastRegen; // Paper
|
||||
|
||||
public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason) {
|
||||
+ // Paper start - Forward
|
||||
+ this(entity, amount, regainReason, false);
|
||||
+ }
|
||||
+
|
||||
+ public EntityRegainHealthEvent(@NotNull final Entity entity, final double amount, @NotNull final RegainReason regainReason, boolean isFastRegen) {
|
||||
+ // Paper end
|
||||
super(entity);
|
||||
this.amount = amount;
|
||||
this.regainReason = regainReason;
|
||||
+ this.isFastRegen = isFastRegen; // Paper
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - Add getter for isFastRegen
|
||||
+ /**
|
||||
+ * Is this event a result of the fast regeneration mechanic
|
||||
+ *
|
||||
+ * @return Whether the event is the result of a fast regeneration mechanic
|
||||
+ */
|
||||
+ public boolean isFastRegen() {
|
||||
+ return isFastRegen;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
/**
|
||||
* Gets the amount of regained health
|
432
patches/unapplied/api/0041-LootTable-API.patch
Normal file
432
patches/unapplied/api/0041-LootTable-API.patch
Normal file
|
@ -0,0 +1,432 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 1 May 2016 15:19:49 -0400
|
||||
Subject: [PATCH] LootTable API
|
||||
|
||||
Provides API to control what Loot Table an object uses.
|
||||
|
||||
Also provides an Event to control if a lootable inventory should
|
||||
auto replenish for a player.
|
||||
|
||||
Provides methods to determine players looted state for an object
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..92d7b853a2ccaae5afa8ac141bead840942944ef
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
|
||||
@@ -0,0 +1,17 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts
|
||||
+ */
|
||||
+public interface LootableBlockInventory extends LootableInventory {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block that is lootable
|
||||
+ * @return The Block
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ Block getBlock();
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b387894fe8001edb41ad2ad2b70ebabe065b682e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
|
||||
@@ -0,0 +1,17 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts
|
||||
+ */
|
||||
+public interface LootableEntityInventory extends LootableInventory {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the entity that is lootable
|
||||
+ * @return The Entity
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ Entity getEntity();
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2b01a50b6e18856f4c9e28340a7a111cae646a0a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
|
||||
@@ -0,0 +1,125 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.loot.Lootable;
|
||||
+
|
||||
+import java.util.UUID;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents an Inventory that contains a Loot Table associated to it that will
|
||||
+ * automatically fill on first open.
|
||||
+ *
|
||||
+ * A new feature and API is provided to support automatically refreshing the contents
|
||||
+ * of the inventory based on that Loot Table after a configurable amount of time has passed.
|
||||
+ *
|
||||
+ * The behavior of how the Inventory is filled based on the loot table may vary based
|
||||
+ * on Minecraft versions and the Loot Table feature.
|
||||
+ */
|
||||
+public interface LootableInventory extends Lootable {
|
||||
+
|
||||
+ /**
|
||||
+ * Server owners have to enable whether or not an object in a world should refill
|
||||
+ *
|
||||
+ * @return If the world this inventory is currently in has Replenishable Lootables enabled
|
||||
+ */
|
||||
+ boolean isRefillEnabled();
|
||||
+
|
||||
+ /**
|
||||
+ * Whether or not this object has ever been filled
|
||||
+ * @return Has ever been filled
|
||||
+ */
|
||||
+ boolean hasBeenFilled();
|
||||
+
|
||||
+ /**
|
||||
+ * Has this player ever looted this block
|
||||
+ * @param player The player to check
|
||||
+ * @return Whether or not this player has looted this block
|
||||
+ */
|
||||
+ default boolean hasPlayerLooted(@NotNull Player player) {
|
||||
+ return hasPlayerLooted(player.getUniqueId());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if this player can loot this block. Takes into account the "restrict player reloot" settings
|
||||
+ *
|
||||
+ * @param player the player to check
|
||||
+ *
|
||||
+ * @return Whether this player can loot this block
|
||||
+ */
|
||||
+ boolean canPlayerLoot(@NotNull UUID player);
|
||||
+
|
||||
+ /**
|
||||
+ * Has this player ever looted this block
|
||||
+ * @param player The player to check
|
||||
+ * @return Whether or not this player has looted this block
|
||||
+ */
|
||||
+ boolean hasPlayerLooted(@NotNull UUID player);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp, in milliseconds, of when the player last looted this object
|
||||
+ *
|
||||
+ * @param player The player to check
|
||||
+ * @return Timestamp last looted, or null if player has not looted this object
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ default Long getLastLooted(@NotNull Player player) {
|
||||
+ return getLastLooted(player.getUniqueId());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp, in milliseconds, of when the player last looted this object
|
||||
+ *
|
||||
+ * @param player The player to check
|
||||
+ * @return Timestamp last looted, or null if player has not looted this object
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ Long getLastLooted(@NotNull UUID player);
|
||||
+
|
||||
+ /**
|
||||
+ * Change the state of whether or not a player has looted this block
|
||||
+ * @param player The player to change state for
|
||||
+ * @param looted true to add player to looted list, false to remove
|
||||
+ * @return The previous state of whether the player had looted this or not
|
||||
+ */
|
||||
+ default boolean setHasPlayerLooted(@NotNull Player player, boolean looted) {
|
||||
+ return setHasPlayerLooted(player.getUniqueId(), looted);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Change the state of whether or not a player has looted this block
|
||||
+ * @param player The player to change state for
|
||||
+ * @param looted true to add player to looted list, false to remove
|
||||
+ * @return The previous state of whether the player had looted this or not
|
||||
+ */
|
||||
+ boolean setHasPlayerLooted(@NotNull UUID player, boolean looted);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns Whether or not this object has been filled and now has a pending refill
|
||||
+ * @return Has pending refill
|
||||
+ */
|
||||
+ boolean hasPendingRefill();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp in milliseconds that the Lootable object was last refilled
|
||||
+ *
|
||||
+ * @return -1 if it was never refilled, or timestamp in milliseconds
|
||||
+ */
|
||||
+ long getLastFilled();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp in milliseconds that the Lootable object will refill
|
||||
+ *
|
||||
+ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds
|
||||
+ */
|
||||
+ long getNextRefill();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the timestamp in milliseconds of the next refill for this object
|
||||
+ *
|
||||
+ * @param refillAt timestamp in milliseconds. -1 to clear next refill
|
||||
+ * @return The previous scheduled time to refill, or -1 if was not scheduled
|
||||
+ */
|
||||
+ long setNextRefill(long refillAt);
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fd184f13f5e8ee5cf829fff4f44696e1f760430b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
|
||||
@@ -0,0 +1,45 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable {
|
||||
+ @NotNull private final LootableInventory inventory;
|
||||
+
|
||||
+ public LootableInventoryReplenishEvent(@NotNull Player player, @NotNull LootableInventory inventory) {
|
||||
+ super(player);
|
||||
+ this.inventory = inventory;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public LootableInventory getInventory() {
|
||||
+ return inventory;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/block/Barrel.java b/src/main/java/org/bukkit/block/Barrel.java
|
||||
index aa1bb7a1a1c94b0b029bb60026efbc7f55584dd7..d3789b2b7dd71d7c1872a0d84698d35a1884101b 100644
|
||||
--- a/src/main/java/org/bukkit/block/Barrel.java
|
||||
+++ b/src/main/java/org/bukkit/block/Barrel.java
|
||||
@@ -5,4 +5,4 @@ import org.bukkit.loot.Lootable;
|
||||
/**
|
||||
* Represents a captured state of a Barrel.
|
||||
*/
|
||||
-public interface Barrel extends Container, Lootable, Lidded { }
|
||||
+public interface Barrel extends Container, com.destroystokyo.paper.loottable.LootableBlockInventory, Lidded { } // Paper
|
||||
diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java
|
||||
index b451191312e4fb19f2131c2d0a0c0337953f6c7c..db6affbc78106b2d93b41953b624a0bca0ca1d72 100644
|
||||
--- a/src/main/java/org/bukkit/block/Chest.java
|
||||
+++ b/src/main/java/org/bukkit/block/Chest.java
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableBlockInventory; // Paper
|
||||
+import org.bukkit.Nameable; // Paper
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.loot.Lootable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -7,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Represents a captured state of a chest.
|
||||
*/
|
||||
-public interface Chest extends Container, Lootable, Lidded {
|
||||
+public interface Chest extends Container, LootableBlockInventory, Lidded { // Paper
|
||||
|
||||
/**
|
||||
* Gets the inventory of the chest block represented by this block state.
|
||||
diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java
|
||||
index 74cd194c9a98245dc52e7e352d7d6c046e1e5cf3..07af1a3f011d4b96275f919d302ac367198e923e 100644
|
||||
--- a/src/main/java/org/bukkit/block/Dispenser.java
|
||||
+++ b/src/main/java/org/bukkit/block/Dispenser.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableBlockInventory;
|
||||
import org.bukkit.Nameable;
|
||||
import org.bukkit.loot.Lootable;
|
||||
import org.bukkit.projectiles.BlockProjectileSource;
|
||||
@@ -8,7 +9,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a captured state of a dispenser.
|
||||
*/
|
||||
-public interface Dispenser extends Container, Nameable, Lootable {
|
||||
+public interface Dispenser extends Container, Nameable, LootableBlockInventory { // Paper
|
||||
|
||||
/**
|
||||
* Gets the BlockProjectileSource object for the dispenser.
|
||||
diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java
|
||||
index 424392fb5ed4628199b0e73689522aa3c90740cb..c76202321e29ad67597ca3017eb8d9baf6787383 100644
|
||||
--- a/src/main/java/org/bukkit/block/Dropper.java
|
||||
+++ b/src/main/java/org/bukkit/block/Dropper.java
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableBlockInventory;
|
||||
import org.bukkit.loot.Lootable;
|
||||
|
||||
/**
|
||||
* Represents a captured state of a dropper.
|
||||
*/
|
||||
-public interface Dropper extends Container, Lootable {
|
||||
+public interface Dropper extends Container, LootableBlockInventory { // Paper
|
||||
|
||||
/**
|
||||
* Tries to drop a randomly selected item from the dropper's inventory,
|
||||
diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java
|
||||
index 58e493099810fb8d4705ecd49b4a5e1e1949b87b..7ade312f180b7e30871d3a3240c76325cc369c26 100644
|
||||
--- a/src/main/java/org/bukkit/block/Hopper.java
|
||||
+++ b/src/main/java/org/bukkit/block/Hopper.java
|
||||
@@ -1,8 +1,9 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableBlockInventory;
|
||||
import org.bukkit.loot.Lootable;
|
||||
|
||||
/**
|
||||
* Represents a captured state of a hopper.
|
||||
*/
|
||||
-public interface Hopper extends Container, Lootable { }
|
||||
+public interface Hopper extends Container, LootableBlockInventory { } // Paper
|
||||
diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java
|
||||
index 387b2892886e1ccb2bd928e5111fb9bd41d777ab..5dc5318b0a451937228a8a059dfec1cd9de389a6 100644
|
||||
--- a/src/main/java/org/bukkit/block/ShulkerBox.java
|
||||
+++ b/src/main/java/org/bukkit/block/ShulkerBox.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableBlockInventory;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.loot.Lootable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -7,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a captured state of a ShulkerBox.
|
||||
*/
|
||||
-public interface ShulkerBox extends Container, Lootable, Lidded {
|
||||
+public interface ShulkerBox extends Container, LootableBlockInventory, Lidded { // Paper
|
||||
|
||||
/**
|
||||
* Get the {@link DyeColor} corresponding to this ShulkerBox
|
||||
diff --git a/src/main/java/org/bukkit/entity/ChestBoat.java b/src/main/java/org/bukkit/entity/ChestBoat.java
|
||||
index 5b5c3be107fdaa6c55ceb1bca2c223ebc6ab7f43..4ebe1033c55dbd58d0794809435c935236fabcc2 100644
|
||||
--- a/src/main/java/org/bukkit/entity/ChestBoat.java
|
||||
+++ b/src/main/java/org/bukkit/entity/ChestBoat.java
|
||||
@@ -6,5 +6,5 @@ import org.bukkit.loot.Lootable;
|
||||
/**
|
||||
* A {@link Boat} with a chest.
|
||||
*/
|
||||
-public interface ChestBoat extends Boat, InventoryHolder, Lootable {
|
||||
+public interface ChestBoat extends Boat, InventoryHolder, com.destroystokyo.paper.loottable.LootableEntityInventory { // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
|
||||
index 937b99f8734d71b2ad33af142afbc251b81d9745..db69687a7ad4b18d17ab1677cae5d8dd4dcd3678 100644
|
||||
--- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
|
||||
+++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.entity.minecart;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableEntityInventory;
|
||||
import org.bukkit.entity.Minecart;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.loot.Lootable;
|
||||
@@ -7,7 +8,7 @@ import org.bukkit.loot.Lootable;
|
||||
/**
|
||||
* Represents a Minecart with a Hopper inside it
|
||||
*/
|
||||
-public interface HopperMinecart extends Minecart, InventoryHolder, Lootable {
|
||||
+public interface HopperMinecart extends Minecart, InventoryHolder, LootableEntityInventory {
|
||||
|
||||
/**
|
||||
* Checks whether or not this Minecart will pick up
|
||||
diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
|
||||
index 9ea403e6fd8e960d017660e0aec118abeda2c42b..238d118f7788b13cd86b7e9ea3a0fc38e2e09715 100644
|
||||
--- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
|
||||
+++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.entity.minecart;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableEntityInventory;
|
||||
import org.bukkit.entity.Minecart;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.loot.Lootable;
|
||||
@@ -9,5 +10,5 @@ import org.bukkit.loot.Lootable;
|
||||
* minecarts} have their own inventory that can be accessed using methods
|
||||
* from the {@link InventoryHolder} interface.
|
||||
*/
|
||||
-public interface StorageMinecart extends Minecart, InventoryHolder, Lootable {
|
||||
+public interface StorageMinecart extends Minecart, InventoryHolder, LootableEntityInventory { // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java
|
||||
index 24a3d989db3bc67e7afe8459a3d4bb132f448ea7..901db852498e0658c79a57582508dab29bf0a798 100644
|
||||
--- a/src/main/java/org/bukkit/loot/Lootable.java
|
||||
+++ b/src/main/java/org/bukkit/loot/Lootable.java
|
||||
@@ -36,6 +36,34 @@ public interface Lootable {
|
||||
@Nullable
|
||||
LootTable getLootTable();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Set the loot table and seed for a container or entity at the same time.
|
||||
+ *
|
||||
+ * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have.
|
||||
+ * @param seed the seed to used to generate loot. Default is 0.
|
||||
+ */
|
||||
+ default void setLootTable(@Nullable LootTable table, long seed) {
|
||||
+ setLootTable(table);
|
||||
+ setSeed(seed);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether or not this object has a Loot Table
|
||||
+ * @return Has a loot table
|
||||
+ */
|
||||
+ default boolean hasLootTable() {
|
||||
+ return getLootTable() != null;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Clears the associated Loot Table to this object
|
||||
+ */
|
||||
+ default void clearLootTable() {
|
||||
+ setLootTable(null);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Set the seed used when this Loot Table generates loot.
|
||||
*
|
122
patches/unapplied/api/0042-Add-EntityZapEvent.patch
Normal file
122
patches/unapplied/api/0042-Add-EntityZapEvent.patch
Normal file
|
@ -0,0 +1,122 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AlphaBlend <whizkid3000@hotmail.com>
|
||||
Date: Sun, 16 Oct 2016 23:19:34 -0700
|
||||
Subject: [PATCH] Add EntityZapEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1c5fa066c9e5e1b1a06df30842a4c7acc4742df8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.LightningStrike;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityTransformEvent;
|
||||
+
|
||||
+import java.util.Collections;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when lightning strikes an entity
|
||||
+ */
|
||||
+public class EntityZapEvent extends EntityTransformEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled;
|
||||
+ @NotNull private final LightningStrike bolt;
|
||||
+
|
||||
+ public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) {
|
||||
+ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING);
|
||||
+ Preconditions.checkNotNull(bolt);
|
||||
+ Preconditions.checkNotNull(replacementEntity);
|
||||
+ this.bolt = bolt;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the lightning bolt that is striking the entity.
|
||||
+ * @return The lightning bolt responsible for this event
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public LightningStrike getBolt() {
|
||||
+ return bolt;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the entity that will replace the struck entity.
|
||||
+ * @return The entity that will replace the struck entity
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Entity getReplacementEntity() {
|
||||
+ return getTransformedEntity();
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/event/entity/PigZapEvent.java b/src/main/java/org/bukkit/event/entity/PigZapEvent.java
|
||||
index 0e0ed93b568fd2c0d8f6e359c31dc29cb0fa71c2..d3949edfc736b3d67a627ef378748b374769e183 100644
|
||||
--- a/src/main/java/org/bukkit/event/entity/PigZapEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/entity/PigZapEvent.java
|
||||
@@ -2,6 +2,7 @@ package org.bukkit.event.entity;
|
||||
|
||||
import java.util.Collections;
|
||||
import org.bukkit.entity.Entity;
|
||||
+import com.destroystokyo.paper.event.entity.EntityZapEvent;
|
||||
import org.bukkit.entity.LightningStrike;
|
||||
import org.bukkit.entity.Pig;
|
||||
import org.bukkit.entity.PigZombie;
|
||||
@@ -12,14 +13,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Stores data for pigs being zapped
|
||||
*/
|
||||
-public class PigZapEvent extends EntityTransformEvent implements Cancellable {
|
||||
- private static final HandlerList handlers = new HandlerList();
|
||||
+public class PigZapEvent extends EntityZapEvent implements Cancellable {
|
||||
+ //private static final HandlerList handlers = new HandlerList();
|
||||
private boolean canceled;
|
||||
private final PigZombie pigzombie;
|
||||
private final LightningStrike bolt;
|
||||
|
||||
public PigZapEvent(@NotNull final Pig pig, @NotNull final LightningStrike bolt, @NotNull final PigZombie pigzombie) {
|
||||
- super(pig, Collections.singletonList((Entity) pigzombie), TransformReason.LIGHTNING);
|
||||
+ super(pig, bolt, pigzombie);
|
||||
this.bolt = bolt;
|
||||
this.pigzombie = pigzombie;
|
||||
}
|
||||
@@ -63,6 +64,8 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable {
|
||||
return pigzombie;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /*
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
@@ -73,4 +76,6 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable {
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
}
|
46
patches/unapplied/api/0043-Misc-Utils.patch
Normal file
46
patches/unapplied/api/0043-Misc-Utils.patch
Normal file
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: vemacs <d@nkmem.es>
|
||||
Date: Wed, 23 Nov 2016 12:53:43 -0500
|
||||
Subject: [PATCH] Misc Utils
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5bb677ce585b856b3d3e589e29786a29619c56a7
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java
|
||||
@@ -0,0 +1,34 @@
|
||||
+package com.destroystokyo.paper.utils;
|
||||
+
|
||||
+import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
+import java.util.concurrent.atomic.LongAdder;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public class CachedSizeConcurrentLinkedQueue<E> extends ConcurrentLinkedQueue<E> {
|
||||
+ private final LongAdder cachedSize = new LongAdder();
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean add(@NotNull E e) {
|
||||
+ boolean result = super.add(e);
|
||||
+ if (result) {
|
||||
+ cachedSize.increment();
|
||||
+ }
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public E poll() {
|
||||
+ E result = super.poll();
|
||||
+ if (result != null) {
|
||||
+ cachedSize.decrement();
|
||||
+ }
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return cachedSize.intValue();
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,108 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: willies952002 <admin@domnian.com>
|
||||
Date: Mon, 28 Nov 2016 10:16:39 -0500
|
||||
Subject: [PATCH] Allow Reloading of Command Aliases
|
||||
|
||||
Reload the aliases stored in commands.yml
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 7b467aedbcf3a6174bfb12ded3b27775a7eaf45c..27f076ed2bb30bc27564db61e165cff4172f9df0 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2283,6 +2283,15 @@ public final class Bukkit {
|
||||
public static void reloadPermissions() {
|
||||
server.reloadPermissions();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Reload the Command Aliases in commands.yml
|
||||
+ *
|
||||
+ * @return Whether the reload was successful
|
||||
+ */
|
||||
+ public static boolean reloadCommandAliases() {
|
||||
+ return server.reloadCommandAliases();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index c5591e82e14e299facfc767a20f2eed77354caac..d80f41e7f4466eae8101b5ee7136918e6de93324 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2014,4 +2014,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
// Spigot end
|
||||
|
||||
void reloadPermissions(); // Paper
|
||||
+
|
||||
+ boolean reloadCommandAliases(); // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/CommandMap.java b/src/main/java/org/bukkit/command/CommandMap.java
|
||||
index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a884d0731 100644
|
||||
--- a/src/main/java/org/bukkit/command/CommandMap.java
|
||||
+++ b/src/main/java/org/bukkit/command/CommandMap.java
|
||||
@@ -128,4 +128,14 @@ public interface CommandMap {
|
||||
*/
|
||||
@Nullable
|
||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) throws IllegalArgumentException;
|
||||
+
|
||||
+ // Paper start - Expose Known Commands
|
||||
+ /**
|
||||
+ * Return a Map of known commands
|
||||
+ *
|
||||
+ * @return known commands
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public java.util.Map<String, Command> getKnownCommands();
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
index b3b32ce429edbf1ed040354dbe28ab86f0d24201..1424060c0a162020d4a680e0a592224561067b16 100644
|
||||
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
@@ -293,4 +293,11 @@ public class SimpleCommandMap implements CommandMap {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start - Expose Known Commands
|
||||
+ @NotNull
|
||||
+ public Map<String, Command> getKnownCommands() {
|
||||
+ return knownCommands;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
index 5fa9d648bc780e874f658597f1a24715bccac5cb..3ec32b46264cfff857b50129b5e0fa5584943ec6 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
@@ -13,7 +13,7 @@ public class ReloadCommand extends BukkitCommand {
|
||||
public ReloadCommand(@NotNull String name) {
|
||||
super(name);
|
||||
this.description = "Reloads the server configuration and plugins";
|
||||
- this.usageMessage = "/reload [permissions]"; // Paper
|
||||
+ this.usageMessage = "/reload [permissions|commands|confirm]"; // Paper
|
||||
this.setPermission("bukkit.command.reload");
|
||||
this.setAliases(Arrays.asList("rl"));
|
||||
}
|
||||
@@ -29,6 +29,13 @@ public class ReloadCommand extends BukkitCommand {
|
||||
Bukkit.getServer().reloadPermissions();
|
||||
Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Permissions successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN));
|
||||
return true;
|
||||
+ } else if ("commands".equalsIgnoreCase(args[0])) {
|
||||
+ if (Bukkit.getServer().reloadCommandAliases()) {
|
||||
+ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Command aliases successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN));
|
||||
+ } else {
|
||||
+ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("An error occurred while trying to reload command aliases.", net.kyori.adventure.text.format.NamedTextColor.RED));
|
||||
+ }
|
||||
+ return true;
|
||||
} else if ("confirm".equalsIgnoreCase(args[0])) {
|
||||
confirmed = true;
|
||||
} else {
|
||||
@@ -53,6 +60,6 @@ public class ReloadCommand extends BukkitCommand {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException {
|
||||
- return java.util.Collections.singletonList("permissions"); // Paper
|
||||
+ return com.google.common.collect.Lists.newArrayList("permissions", "commands"); // Paper
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: AlphaBlend <whizkid3000@hotmail.com>
|
||||
Date: Thu, 8 Sep 2016 08:47:08 -0700
|
||||
Subject: [PATCH] Add source to PlayerExpChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java
|
||||
index c99c9281e98e4b510dddb711b8785bcd56b3b92f..7c340f539c31a431d7d9204a8135e0bfc31863a8 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerExpChangeEvent.java
|
||||
@@ -1,21 +1,43 @@
|
||||
package org.bukkit.event.player;
|
||||
|
||||
+import org.bukkit.entity.Entity; // Paper
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
+import org.jetbrains.annotations.Nullable; // Paper
|
||||
+
|
||||
/**
|
||||
* Called when a players experience changes naturally
|
||||
*/
|
||||
public class PlayerExpChangeEvent extends PlayerEvent {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
+ // Paper start
|
||||
+ @Nullable
|
||||
+ private final Entity source;
|
||||
private int exp;
|
||||
|
||||
public PlayerExpChangeEvent(@NotNull final Player player, final int expAmount) {
|
||||
+ this(player, null, expAmount);
|
||||
+ }
|
||||
+
|
||||
+ public PlayerExpChangeEvent(@NotNull final Player player, @Nullable final Entity sourceEntity, final int expAmount) {
|
||||
super(player);
|
||||
+ source = sourceEntity;
|
||||
exp = expAmount;
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Get the source that provided the experience.
|
||||
+ *
|
||||
+ * @return The source of the experience
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Entity getSource() {
|
||||
+ return source;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Get the amount of experience the player will receive
|
||||
*
|
82
patches/unapplied/api/0046-Add-ProjectileCollideEvent.patch
Normal file
82
patches/unapplied/api/0046-Add-ProjectileCollideEvent.patch
Normal file
|
@ -0,0 +1,82 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Fri, 16 Dec 2016 21:25:39 -0600
|
||||
Subject: [PATCH] Add ProjectileCollideEvent
|
||||
|
||||
Now deprecated and replaced with ProjectileHitEvent
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6ae2bc3d952d34f298220738856024e0b6594199
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java
|
||||
@@ -0,0 +1,69 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.Projectile;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a projectile collides with an entity
|
||||
+ * <p>
|
||||
+ * This event is called <b>before</b> {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying
|
||||
+ * @deprecated Deprecated, use {@link org.bukkit.event.entity.ProjectileHitEvent} and check if there is a hit entity
|
||||
+ */
|
||||
+@Deprecated
|
||||
+public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
|
||||
+ @NotNull private final Entity collidedWith;
|
||||
+
|
||||
+ /**
|
||||
+ * Get the entity the projectile collided with
|
||||
+ *
|
||||
+ * @return the entity collided with
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Entity getCollidedWith() {
|
||||
+ return collidedWith;
|
||||
+ }
|
||||
+
|
||||
+ public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) {
|
||||
+ super(what);
|
||||
+ this.collidedWith = collidedWith;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the projectile that collided
|
||||
+ *
|
||||
+ * @return the projectile that collided
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Projectile getEntity() {
|
||||
+ return (Projectile) super.getEntity();
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlerList = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlerList;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlerList;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,62 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 20 Dec 2016 15:55:55 -0500
|
||||
Subject: [PATCH] Add String based Action Bar API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index f2311a9842a4d7c45fc88b9f8ca485005a3b3352..05795d5e86c7427bb962144b66e43f68a9fa3ff3 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1103,6 +1103,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
public void sendMap(@NotNull MapView map);
|
||||
|
||||
// Paper start
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an Action Bar message to the client.
|
||||
+ *
|
||||
+ * Use Section symbols for legacy color codes to send formatting.
|
||||
+ *
|
||||
+ * @param message The message to send
|
||||
+ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void sendActionBar(@NotNull String message);
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an Action Bar message to the client.
|
||||
+ *
|
||||
+ * Use supplied alternative character to the section symbol to represent legacy color codes.
|
||||
+ *
|
||||
+ * @param alternateChar Alternate symbol such as '&'
|
||||
+ * @param message The message to send
|
||||
+ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void sendActionBar(char alternateChar, @NotNull String message);
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an Action Bar message to the client.
|
||||
+ *
|
||||
+ * @param message The components to send
|
||||
+ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void sendActionBar(@NotNull net.md_5.bungee.api.chat.BaseComponent... message);
|
||||
+
|
||||
/**
|
||||
* Sends the component to the player
|
||||
*
|
||||
@@ -1130,9 +1163,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Sends an array of components as a single message to the specified screen position of this player
|
||||
*
|
||||
+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client.
|
||||
* @param position the screen position
|
||||
* @param components the components to send
|
||||
*/
|
||||
+ @Deprecated
|
||||
public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
spigot().sendMessage(position, components);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 21 Dec 2016 11:47:25 -0600
|
||||
Subject: [PATCH] Add API methods to control if armour stands can move
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java
|
||||
index dc604d6ab9dcf67fa0791539d18c2f890a814ed8..91fc11dda99de506be83d40df8929bf7cd8e8d85 100644
|
||||
--- a/src/main/java/org/bukkit/entity/ArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/entity/ArmorStand.java
|
||||
@@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity {
|
||||
*/
|
||||
ADDING;
|
||||
}
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Tests if this armor stand can move.
|
||||
+ *
|
||||
+ * <p>The default value is {@code true}.</p>
|
||||
+ *
|
||||
+ * @return {@code true} if this armour stand can move, {@code false} otherwise
|
||||
+ */
|
||||
+ boolean canMove();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets if this armor stand can move.
|
||||
+ *
|
||||
+ * @param move {@code true} if this armour stand can move, {@code false} otherwise
|
||||
+ */
|
||||
+ void setCanMove(boolean move);
|
||||
+ // Paper end
|
||||
}
|
89
patches/unapplied/api/0049-IllegalPacketEvent.patch
Normal file
89
patches/unapplied/api/0049-IllegalPacketEvent.patch
Normal file
|
@ -0,0 +1,89 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 4 Dec 2016 01:19:14 -0500
|
||||
Subject: [PATCH] IllegalPacketEvent
|
||||
|
||||
Fire an event when an illegal packet is received to let plugins handle it
|
||||
|
||||
Lets plugins change the kick message and if it should kick or not.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8d8e9b16f2a6707d2af7567c7682dfc5db51a737
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * @deprecated Not used
|
||||
+ */
|
||||
+@Deprecated
|
||||
+public class IllegalPacketEvent extends PlayerEvent {
|
||||
+ @Nullable private final String type;
|
||||
+ @Nullable private final String ex;
|
||||
+ @Nullable private String kickMessage;
|
||||
+ private boolean shouldKick = true;
|
||||
+
|
||||
+ public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) {
|
||||
+ super(player);
|
||||
+ this.type = type;
|
||||
+ this.kickMessage = kickMessage;
|
||||
+ this.ex = e.getMessage();
|
||||
+ }
|
||||
+
|
||||
+ public boolean isShouldKick() {
|
||||
+ return shouldKick;
|
||||
+ }
|
||||
+
|
||||
+ public void setShouldKick(boolean shouldKick) {
|
||||
+ this.shouldKick = shouldKick;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public String getKickMessage() {
|
||||
+ return kickMessage;
|
||||
+ }
|
||||
+
|
||||
+ public void setKickMessage(@Nullable String kickMessage) {
|
||||
+ this.kickMessage = kickMessage;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public String getType() {
|
||||
+ return type;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public String getExceptionMessage() {
|
||||
+ return ex;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) {
|
||||
+ IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception);
|
||||
+ event.callEvent();
|
||||
+ if (event.shouldKick) {
|
||||
+ player.kickPlayer(kickMessage);
|
||||
+ }
|
||||
+ Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage());
|
||||
+ }
|
||||
+}
|
33
patches/unapplied/api/0050-Fireworks-API-s.patch
Normal file
33
patches/unapplied/api/0050-Fireworks-API-s.patch
Normal file
|
@ -0,0 +1,33 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 28 Dec 2016 01:18:55 -0500
|
||||
Subject: [PATCH] Fireworks API's
|
||||
|
||||
Get the Entity being boosted
|
||||
Get the firework launcher
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java
|
||||
index e750b34d7d067a5f2f5587853274b6f479cc4fd6..0d31aa0b22cf1e849572294e2cfe38b48c9210af 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Firework.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Firework.java
|
||||
@@ -111,4 +111,20 @@ public interface Firework extends Projectile {
|
||||
* @param shotAtAngle the new shotAtAngle
|
||||
*/
|
||||
void setShotAtAngle(boolean shotAtAngle);
|
||||
+
|
||||
+ // Paper start
|
||||
+ @org.jetbrains.annotations.Nullable
|
||||
+ public java.util.UUID getSpawningEntity();
|
||||
+ /**
|
||||
+ * If this firework is boosting an entity, return it
|
||||
+ * @deprecated use {@link #getAttachedTo()}
|
||||
+ * @see #setAttachedTo(LivingEntity)
|
||||
+ * @return The entity being boosted
|
||||
+ */
|
||||
+ @org.jetbrains.annotations.Nullable
|
||||
+ @Deprecated
|
||||
+ default LivingEntity getBoostedEntity() {
|
||||
+ return getAttachedTo();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 31 Dec 2016 20:29:33 -0500
|
||||
Subject: [PATCH] PlayerTeleportEndGatewayEvent
|
||||
|
||||
Allows you to access the Gateway being used in a teleport event
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b64ab6eecd8bc4ca9c109b9d83c82861d6260793
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.block.EndGateway;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when a teleport is triggered for an End Gateway
|
||||
+ */
|
||||
+public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent {
|
||||
+ @NotNull private final EndGateway gateway;
|
||||
+
|
||||
+ public PlayerTeleportEndGatewayEvent(@NotNull Player player, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) {
|
||||
+ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY);
|
||||
+ this.gateway = gateway;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The gateway triggering the teleport
|
||||
+ *
|
||||
+ * @return EndGateway used
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public EndGateway getGateway() {
|
||||
+ return gateway;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 7 Jan 2017 15:23:03 -0500
|
||||
Subject: [PATCH] Provide E/TE/Chunk count stat methods
|
||||
|
||||
Provides counts without the ineffeciency of using .getEntities().size()
|
||||
which creates copy of the collections.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
|
||||
index 2867faf0acbbbb2e99c5b503f0c6bc83f3bfe80f..f5a398aa5f7a7e6280167fd723f78f4d72e2b1dd 100644
|
||||
--- a/src/main/java/org/bukkit/World.java
|
||||
+++ b/src/main/java/org/bukkit/World.java
|
||||
@@ -47,6 +47,33 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed, net.kyori.adventure.audience.ForwardingAudience { // Paper
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * @return The amount of Entities in this world
|
||||
+ */
|
||||
+ int getEntityCount();
|
||||
+
|
||||
+ /**
|
||||
+ * @return The amount of Tile Entities in this world
|
||||
+ */
|
||||
+ int getTileEntityCount();
|
||||
+
|
||||
+ /**
|
||||
+ * @return The amount of Tickable Tile Entities in this world
|
||||
+ */
|
||||
+ int getTickableTileEntityCount();
|
||||
+
|
||||
+ /**
|
||||
+ * @return The amount of Chunks in this world
|
||||
+ */
|
||||
+ int getChunkCount();
|
||||
+
|
||||
+ /**
|
||||
+ * @return The amount of Players in this world
|
||||
+ */
|
||||
+ int getPlayerCount();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the {@link Block} at the given coordinates
|
||||
*
|
|
@ -0,0 +1,122 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 19 Dec 2017 16:28:32 -0500
|
||||
Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player
|
||||
|
||||
Adds lots of information about why this orb exists.
|
||||
|
||||
Replaces isFromBottle() with logic that persists entity reloads too.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/ExperienceOrb.java b/src/main/java/org/bukkit/entity/ExperienceOrb.java
|
||||
index c286edfd827e185a76e44c44faace19a80325d7a..dec70bbfaf73a9d525b2c45682b804c684e1645b 100644
|
||||
--- a/src/main/java/org/bukkit/entity/ExperienceOrb.java
|
||||
+++ b/src/main/java/org/bukkit/entity/ExperienceOrb.java
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable; // Paper
|
||||
+
|
||||
/**
|
||||
* Represents an Experience Orb.
|
||||
*/
|
||||
@@ -18,4 +21,99 @@ public interface ExperienceOrb extends Entity {
|
||||
* @param value Amount of experience
|
||||
*/
|
||||
public void setExperience(int value);
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Check if this orb was spawned from a {@link ThrownExpBottle}
|
||||
+ *
|
||||
+ * @return if orb was spawned from a bottle
|
||||
+ * @deprecated Use getSpawnReason() == EXP_BOTTLE
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default boolean isFromBottle() {
|
||||
+ return getSpawnReason() == SpawnReason.EXP_BOTTLE;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Reasons for why this Experience Orb was spawned
|
||||
+ */
|
||||
+ enum SpawnReason {
|
||||
+ /**
|
||||
+ * Spawned by a player dying
|
||||
+ */
|
||||
+ PLAYER_DEATH,
|
||||
+ /**
|
||||
+ * Spawned by an entity dying after being damaged by a player
|
||||
+ */
|
||||
+ ENTITY_DEATH,
|
||||
+ /**
|
||||
+ * Spawned by player using a furnace
|
||||
+ */
|
||||
+ FURNACE,
|
||||
+ /**
|
||||
+ * Spawned by player breeding animals
|
||||
+ */
|
||||
+ BREED,
|
||||
+ /**
|
||||
+ * Spawned by player trading with a villager
|
||||
+ */
|
||||
+ VILLAGER_TRADE,
|
||||
+ /**
|
||||
+ * Spawned by player fishing
|
||||
+ */
|
||||
+ FISHING,
|
||||
+ /**
|
||||
+ * Spawned by player breaking a block that gives experience points such as Diamond Ore
|
||||
+ */
|
||||
+ BLOCK_BREAK,
|
||||
+ /**
|
||||
+ * Spawned by Bukkit API
|
||||
+ */
|
||||
+ CUSTOM,
|
||||
+ /**
|
||||
+ * Spawned by a player throwing an experience points bottle
|
||||
+ */
|
||||
+ EXP_BOTTLE,
|
||||
+ /**
|
||||
+ * Spawned by a player using a grindstone
|
||||
+ */
|
||||
+ GRINDSTONE,
|
||||
+ /**
|
||||
+ * We do not know why it was spawned
|
||||
+ */
|
||||
+ UNKNOWN
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If this experience orb was triggered to be spawned by
|
||||
+ * an entity such as a player, due to events such as killing entity,
|
||||
+ * breaking blocks, smelting in a furnace, etc, this will return the UUID
|
||||
+ * of the entity that triggered this orb to drop.
|
||||
+ *
|
||||
+ * In the case of an entity being killed, this will be the killers UUID.
|
||||
+ *
|
||||
+ * @return UUID of the player that triggered this orb to drop, or null if unknown/no triggering entity
|
||||
+ */
|
||||
+ @Nullable java.util.UUID getTriggerEntityId();
|
||||
+
|
||||
+ /**
|
||||
+ * If this experience orb was spawned in relation to another
|
||||
+ * entity, such as a player or other living entity death, or breeding,
|
||||
+ * return the source entity UUID.
|
||||
+ *
|
||||
+ * In the case of breeding, this will be the new baby entities UUID.
|
||||
+ * In the case of an entity being killed, this will be the dead entities UUID.
|
||||
+ *
|
||||
+ * @return The UUID of the entity that sourced this experience orb
|
||||
+ */
|
||||
+ @Nullable java.util.UUID getSourceEntityId();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the reason that this experience orb was spawned. For any case that we
|
||||
+ * do not know, such as orbs spawned before this API was added, UNKNOWN is returned.
|
||||
+ * @return The reason for this orb being spawned.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ SpawnReason getSpawnReason();
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 21 Jan 2017 17:03:10 -0600
|
||||
Subject: [PATCH] Expose WorldBorder#isInBounds(Location) check
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/WorldBorder.java b/src/main/java/org/bukkit/WorldBorder.java
|
||||
index b1c08a7fc5856bcc29ee64d0a87b95a8ac940ddc..3ab5700b0b13fbfbf7c5b0b2c4a90bcc1e0a2d9c 100644
|
||||
--- a/src/main/java/org/bukkit/WorldBorder.java
|
||||
+++ b/src/main/java/org/bukkit/WorldBorder.java
|
||||
@@ -162,4 +162,18 @@ public interface WorldBorder {
|
||||
* @return The absolute maximum center coordinate of the WorldBorder
|
||||
*/
|
||||
public double getMaxCenterCoordinate();
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Checks if the location is within the boundaries of this border.
|
||||
+ *
|
||||
+ * @param location specific location to check
|
||||
+ * @return true if the location is within the bounds of this border, false otherwise.
|
||||
+ * @deprecated use {@link #isInside(Location)} for an upstream compatible replacement
|
||||
+ */
|
||||
+ @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
|
||||
+ public default boolean isInBounds(@NotNull Location location) {
|
||||
+ return this.isInside(location);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Fri, 9 Jun 2017 07:24:24 -0700
|
||||
Subject: [PATCH] Add configuration option to prevent player names from being
|
||||
suggested
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 27f076ed2bb30bc27564db61e165cff4172f9df0..0ec7937572a28964123322f0cd2c060d4d69e42e 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2292,6 +2292,16 @@ public final class Bukkit {
|
||||
public static boolean reloadCommandAliases() {
|
||||
return server.reloadCommandAliases();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if player names should be suggested when a command returns {@code null} as
|
||||
+ * their tab completion result.
|
||||
+ *
|
||||
+ * @return true if player names should be suggested
|
||||
+ */
|
||||
+ public static boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
+ return server.suggestPlayerNamesWhenNullTabCompletions();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index d80f41e7f4466eae8101b5ee7136918e6de93324..581955462495d63d07f2f461f45b1353e5b89c5b 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2016,4 +2016,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
void reloadPermissions(); // Paper
|
||||
|
||||
boolean reloadCommandAliases(); // Paper
|
||||
+
|
||||
+ // Paper start - allow preventing player name suggestions by default
|
||||
+ /**
|
||||
+ * Checks if player names should be suggested when a command returns {@code null} as
|
||||
+ * their tab completion result.
|
||||
+ *
|
||||
+ * @return true if player names should be suggested
|
||||
+ */
|
||||
+ boolean suggestPlayerNamesWhenNullTabCompletions();
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java
|
||||
index 5cfd88eec9bf02e83d77b6fce1a5c14b7687f48b..1c6205cc667bbec8f6aca479f13b3e9cfcd63ab2 100644
|
||||
--- a/src/main/java/org/bukkit/command/Command.java
|
||||
+++ b/src/main/java/org/bukkit/command/Command.java
|
||||
@@ -99,7 +99,7 @@ public abstract class Command {
|
||||
Preconditions.checkArgument(args != null, "Arguments cannot be null");
|
||||
Preconditions.checkArgument(alias != null, "Alias cannot be null");
|
||||
|
||||
- if (args.length == 0) {
|
||||
+ if (args.length == 0 || !sender.getServer().suggestPlayerNamesWhenNullTabCompletions()) { // Paper - allow preventing player name suggestions by default) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
1389
patches/unapplied/api/0056-Fix-upstream-javadocs.patch
Normal file
1389
patches/unapplied/api/0056-Fix-upstream-javadocs.patch
Normal file
File diff suppressed because it is too large
Load diff
31
patches/unapplied/api/0057-Item-canEntityPickup.patch
Normal file
31
patches/unapplied/api/0057-Item-canEntityPickup.patch
Normal file
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 5 May 2017 03:57:08 -0500
|
||||
Subject: [PATCH] Item#canEntityPickup
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java
|
||||
index 65dd4554c6cc0801fcbc0ef6809b794dcebd1124..ab06c640cef1309ab44b0fae8d95df48cdc869a7 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Item.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Item.java
|
||||
@@ -89,4 +89,20 @@ public interface Item extends Entity {
|
||||
*/
|
||||
@Nullable
|
||||
public UUID getThrower();
|
||||
+
|
||||
+ // Paper Start
|
||||
+ /**
|
||||
+ * Gets if non-player entities can pick this Item up
|
||||
+ *
|
||||
+ * @return True if non-player entities can pickup
|
||||
+ */
|
||||
+ public boolean canMobPickup();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets if non-player entities can pick this Item up
|
||||
+ *
|
||||
+ * @param canMobPickup True to allow non-player entity pickup
|
||||
+ */
|
||||
+ public void setCanMobPickup(boolean canMobPickup);
|
||||
+ // Paper end
|
||||
}
|
102
patches/unapplied/api/0058-PlayerAttemptPickupItemEvent.patch
Normal file
102
patches/unapplied/api/0058-PlayerAttemptPickupItemEvent.patch
Normal file
|
@ -0,0 +1,102 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 11 Jun 2017 16:30:37 -0500
|
||||
Subject: [PATCH] PlayerAttemptPickupItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0788153a9641e75da565d2e6eee37eeee1cbc61e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java
|
||||
@@ -0,0 +1,90 @@
|
||||
+package org.bukkit.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.Item;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a player attempts to pick an item up from the ground
|
||||
+ */
|
||||
+public class PlayerAttemptPickupItemEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private final Item item;
|
||||
+ private final int remaining;
|
||||
+ private boolean flyAtPlayer = true;
|
||||
+ private boolean isCancelled = false;
|
||||
+
|
||||
+ @Deprecated // Remove in 1.13 // Remove in 1.14?
|
||||
+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item) {
|
||||
+ this(player, item, 0);
|
||||
+ }
|
||||
+
|
||||
+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item, final int remaining) {
|
||||
+ super(player);
|
||||
+ this.item = item;
|
||||
+ this.remaining = remaining;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the Item attempted by the player.
|
||||
+ *
|
||||
+ * @return Item
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Item getItem() {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the amount that will remain on the ground, if any
|
||||
+ *
|
||||
+ * @return amount that will remain on the ground
|
||||
+ */
|
||||
+ public int getRemaining() {
|
||||
+ return remaining;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set if the item will fly at the player
|
||||
+ * <p>Cancelling the event will set this value to false.</p>
|
||||
+ *
|
||||
+ * @param flyAtPlayer True for item to fly at player
|
||||
+ */
|
||||
+ public void setFlyAtPlayer(boolean flyAtPlayer) {
|
||||
+ this.flyAtPlayer = flyAtPlayer;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets if the item will fly at the player
|
||||
+ *
|
||||
+ * @return True if the item will fly at the player
|
||||
+ */
|
||||
+ public boolean getFlyAtPlayer() {
|
||||
+ return this.flyAtPlayer;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return this.isCancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.isCancelled = cancel;
|
||||
+ this.flyAtPlayer = !cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
122
patches/unapplied/api/0059-Add-UnknownCommandEvent.patch
Normal file
122
patches/unapplied/api/0059-Add-UnknownCommandEvent.patch
Normal file
|
@ -0,0 +1,122 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sweepyoface <github@sweepy.pw>
|
||||
Date: Sat, 17 Jun 2017 18:48:06 -0400
|
||||
Subject: [PATCH] Add UnknownCommandEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e4f8a0d14ae66468bbb0a5d6bf9c1ee417dc866c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java
|
||||
@@ -0,0 +1,110 @@
|
||||
+package org.bukkit.event.command;
|
||||
+
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a player executes a command that is not defined
|
||||
+ */
|
||||
+public class UnknownCommandEvent extends Event {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private CommandSender sender;
|
||||
+ @NotNull private String commandLine;
|
||||
+ @Nullable private Component message;
|
||||
+
|
||||
+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final Component message) {
|
||||
+ super(false);
|
||||
+ this.sender = sender;
|
||||
+ this.commandLine = commandLine;
|
||||
+ this.message = message;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the CommandSender or ConsoleCommandSender
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @return Sender of the command
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public CommandSender getSender() {
|
||||
+ return sender;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command that was send
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @return Command sent
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getCommandLine() {
|
||||
+ return commandLine;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets message that will be returned
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @return Unknown command message
|
||||
+ * @deprecated use {@link #message()}
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated
|
||||
+ public String getMessage() {
|
||||
+ return this.message == null ? null : LegacyComponentSerializer.legacySection().serialize(this.message);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets message that will be returned
|
||||
+ * <p>
|
||||
+ * Set to null to avoid any message being sent
|
||||
+ *
|
||||
+ * @param message the message to be returned, or null
|
||||
+ * @deprecated use {@link #message(Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setMessage(@Nullable String message) {
|
||||
+ this.message(message == null ? null : LegacyComponentSerializer.legacySection().deserialize(message));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets message that will be returned
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @return Unknown command message
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Contract(pure = true)
|
||||
+ public Component message() {
|
||||
+ return this.message;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets message that will be returned
|
||||
+ * <p>
|
||||
+ * Set to null to avoid any message being sent
|
||||
+ *
|
||||
+ * @param message the message to be returned, or null
|
||||
+ */
|
||||
+ public void message(@Nullable Component message) {
|
||||
+ this.message = message;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
+
|
502
patches/unapplied/api/0060-Basic-PlayerProfile-API.patch
Normal file
502
patches/unapplied/api/0060-Basic-PlayerProfile-API.patch
Normal file
|
@ -0,0 +1,502 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 15 Jan 2018 21:46:46 -0500
|
||||
Subject: [PATCH] Basic PlayerProfile API
|
||||
|
||||
Provides basic elements of a PlayerProfile to be used by future API/events
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b76f13a0266806544bde13952476d4867caaf25b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java
|
||||
@@ -0,0 +1,231 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.Set;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import org.bukkit.profile.PlayerTextures;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a players profile for the game, such as UUID, Name, and textures.
|
||||
+ */
|
||||
+public interface PlayerProfile extends org.bukkit.profile.PlayerProfile {
|
||||
+
|
||||
+ /**
|
||||
+ * @return The players name, if set
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ String getName();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets this profiles Name
|
||||
+ *
|
||||
+ * @param name The new Name
|
||||
+ * @return The previous Name
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ String setName(@Nullable String name);
|
||||
+
|
||||
+ /**
|
||||
+ * @return The players unique identifier, if set
|
||||
+ */
|
||||
+ @Nullable UUID getId();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets this profiles UUID
|
||||
+ *
|
||||
+ * @param uuid The new UUID
|
||||
+ * @return The previous UUID
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ UUID setId(@Nullable UUID uuid);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the {@link PlayerTextures} of this profile.
|
||||
+ * This will build a snapshot of the current texture data once
|
||||
+ * requested inside PlayerTextures.
|
||||
+ *
|
||||
+ * @return the textures, not <code>null</code>
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ PlayerTextures getTextures();
|
||||
+
|
||||
+ /**
|
||||
+ * Copies the given textures.
|
||||
+ *
|
||||
+ * @param textures the textures to copy, or <code>null</code> to clear the
|
||||
+ * textures
|
||||
+ */
|
||||
+ void setTextures(@Nullable PlayerTextures textures);
|
||||
+
|
||||
+ /**
|
||||
+ * @return A Mutable set of this players properties, such as textures.
|
||||
+ * Values specified here are subject to implementation details.
|
||||
+ */
|
||||
+ @NotNull Set<ProfileProperty> getProperties();
|
||||
+
|
||||
+ /**
|
||||
+ * Check if the Profile has the specified property
|
||||
+ * @param property Property name to check
|
||||
+ * @return If the property is set
|
||||
+ */
|
||||
+ boolean hasProperty(@Nullable String property);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets a property. If the property already exists, the previous one will be replaced
|
||||
+ * @param property Property to set.
|
||||
+ */
|
||||
+ void setProperty(@NotNull ProfileProperty property);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets multiple properties. If any of the set properties already exist, it will be replaced
|
||||
+ * @param properties The properties to set
|
||||
+ */
|
||||
+ void setProperties(@NotNull Collection<ProfileProperty> properties);
|
||||
+
|
||||
+ /**
|
||||
+ * Removes a specific property from this profile
|
||||
+ * @param property The property to remove
|
||||
+ * @return If a property was removed
|
||||
+ */
|
||||
+ boolean removeProperty(@Nullable String property);
|
||||
+
|
||||
+ /**
|
||||
+ * Removes a specific property from this profile
|
||||
+ * @param property The property to remove
|
||||
+ * @return If a property was removed
|
||||
+ */
|
||||
+ default boolean removeProperty(@NotNull ProfileProperty property) {
|
||||
+ return removeProperty(property.getName());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Removes all properties in the collection
|
||||
+ * @param properties The properties to remove
|
||||
+ * @return If any property was removed
|
||||
+ */
|
||||
+ default boolean removeProperties(@NotNull Collection<ProfileProperty> properties) {
|
||||
+ boolean removed = false;
|
||||
+ for (ProfileProperty property : properties) {
|
||||
+ if (removeProperty(property)) {
|
||||
+ removed = true;
|
||||
+ }
|
||||
+ }
|
||||
+ return removed;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Clears all properties on this profile
|
||||
+ */
|
||||
+ void clearProperties();
|
||||
+
|
||||
+ /**
|
||||
+ * @return If the profile is now complete (has UUID and Name)
|
||||
+ */
|
||||
+ boolean isComplete();
|
||||
+
|
||||
+ /**
|
||||
+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls
|
||||
+ * Does not account for textures.
|
||||
+ *
|
||||
+ * @return If the profile is now complete (has UUID and Name)
|
||||
+ */
|
||||
+ boolean completeFromCache();
|
||||
+
|
||||
+ /**
|
||||
+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls
|
||||
+ * Does not account for textures.
|
||||
+ *
|
||||
+ * @param onlineMode Treat this as online mode or not
|
||||
+ * @return If the profile is now complete (has UUID and Name)
|
||||
+ */
|
||||
+ boolean completeFromCache(boolean onlineMode);
|
||||
+
|
||||
+ /**
|
||||
+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls
|
||||
+ * Does not account for textures.
|
||||
+ *
|
||||
+ * @param lookupUUID If only name is supplied, should we do a UUID lookup
|
||||
+ * @param onlineMode Treat this as online mode or not
|
||||
+ * @return If the profile is now complete (has UUID and Name)
|
||||
+ */
|
||||
+ boolean completeFromCache(boolean lookupUUID, boolean onlineMode);
|
||||
+
|
||||
+ /**
|
||||
+ * If this profile is not complete, then make the API call to complete it.
|
||||
+ * This is a blocking operation and should be done asynchronously.
|
||||
+ *
|
||||
+ * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}}
|
||||
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
|
||||
+ */
|
||||
+ default boolean complete() {
|
||||
+ return complete(true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If this profile is not complete, then make the API call to complete it.
|
||||
+ * This is a blocking operation and should be done asynchronously.
|
||||
+ *
|
||||
+ * Optionally will also fill textures.
|
||||
+ *
|
||||
+ * Online mode will be automatically determined
|
||||
+ * @param textures controls if we should fill the profile with texture properties
|
||||
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
|
||||
+ */
|
||||
+ boolean complete(boolean textures);
|
||||
+
|
||||
+ /**
|
||||
+ * If this profile is not complete, then make the API call to complete it.
|
||||
+ * This is a blocking operation and should be done asynchronously.
|
||||
+ *
|
||||
+ * Optionally will also fill textures.
|
||||
+ * @param textures controls if we should fill the profile with texture properties
|
||||
+ * @param onlineMode Treat this server as online mode or not
|
||||
+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
|
||||
+ */
|
||||
+ boolean complete(boolean textures, boolean onlineMode);
|
||||
+
|
||||
+ /**
|
||||
+ * Produces an updated player profile based on this profile.
|
||||
+ * <p>
|
||||
+ * This tries to produce a completed profile by filling in missing
|
||||
+ * properties (name, unique id, textures, etc.), and updates existing
|
||||
+ * properties (e.g. name, textures, etc.) to their official and up-to-date
|
||||
+ * values. This operation does not alter the current profile, but produces a
|
||||
+ * new updated {@link PlayerProfile}.
|
||||
+ * <p>
|
||||
+ * If no player exists for the unique id or name of this profile, this
|
||||
+ * operation yields a profile that is equal to the current profile, which
|
||||
+ * might not be complete.
|
||||
+ * <p>
|
||||
+ * This is an asynchronous operation: Updating the profile can result in an
|
||||
+ * outgoing connection in another thread in order to fetch the latest
|
||||
+ * profile properties. The returned {@link CompletableFuture} will be
|
||||
+ * completed once the updated profile is available. In order to not block
|
||||
+ * the server's main thread, you should not wait for the result of the
|
||||
+ * returned CompletableFuture on the server's main thread. Instead, if you
|
||||
+ * want to do something with the updated player profile on the server's main
|
||||
+ * thread once it is available, you could do something like this:
|
||||
+ * <pre>
|
||||
+ * profile.update().thenAcceptAsync(updatedProfile -> {
|
||||
+ * // Do something with the updated profile:
|
||||
+ * // ...
|
||||
+ * }, runnable -> Bukkit.getScheduler().runTask(plugin, runnable));
|
||||
+ * </pre>
|
||||
+ */
|
||||
+ @Override
|
||||
+ @NotNull CompletableFuture<PlayerProfile> update();
|
||||
+
|
||||
+ /**
|
||||
+ * Whether this Profile has textures associated to it
|
||||
+ * @return If it has a textures property
|
||||
+ */
|
||||
+ default boolean hasTextures() {
|
||||
+ return hasProperty("textures");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7b3b6ef533d32169fbeca389bd61cfc6b0e0faee
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java
|
||||
@@ -0,0 +1,72 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a property on a {@link PlayerProfile}
|
||||
+ */
|
||||
+public class ProfileProperty {
|
||||
+ private final String name;
|
||||
+ private final String value;
|
||||
+ private final String signature;
|
||||
+
|
||||
+ public ProfileProperty(@NotNull String name, @NotNull String value) {
|
||||
+ this(name, value, null);
|
||||
+ }
|
||||
+
|
||||
+ public ProfileProperty(@NotNull String name, @NotNull String value, @Nullable String signature) {
|
||||
+ this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null");
|
||||
+ this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null");
|
||||
+ this.signature = signature;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The property name, ie "textures"
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getName() {
|
||||
+ return name;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The property value, likely to be base64 encoded
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getValue() {
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return A signature from Mojang for signed properties
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getSignature() {
|
||||
+ return signature;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return If this property has a signature or not
|
||||
+ */
|
||||
+ public boolean isSigned() {
|
||||
+ return this.signature != null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ ProfileProperty that = (ProfileProperty) o;
|
||||
+ return Objects.equals(name, that.name) &&
|
||||
+ Objects.equals(value, that.value) &&
|
||||
+ Objects.equals(signature, that.signature);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return Objects.hash(name);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index a1c8cb4d89147311539a70901c74eae4020c022f..8f1f432c9d6c68ac142401626adaf1dc212181f2 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2304,6 +2304,83 @@ public final class Bukkit {
|
||||
public static boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
return server.suggestPlayerNamesWhenNullTabCompletions();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified uuid, with name as null.
|
||||
+ *
|
||||
+ * If a player with the passed uuid exists on the server at the time of creation, the returned player profile will
|
||||
+ * be populated with the properties of said player (including their uuid and name).
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid) {
|
||||
+ return server.createProfile(uuid);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified name, with UUID as null.
|
||||
+ *
|
||||
+ * If a player with the passed name exists on the server at the time of creation, the returned player profile will
|
||||
+ * be populated with the properties of said player (including their uuid and name).
|
||||
+ * <p>
|
||||
+ * E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile("JEB_")} will
|
||||
+ * yield a profile with the name 'jeb_', their uuid and their textures.
|
||||
+ * To bypass this pre-population on a case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name) {
|
||||
+ return server.createProfile(name);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified name/uuid
|
||||
+ *
|
||||
+ * Both UUID and Name can not be null at same time. One must be supplied.
|
||||
+ * If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||
+ * profile will be populated with the properties of said player (including their uuid and name).
|
||||
+ * <p>
|
||||
+ * E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile(null, "JEB_")} will
|
||||
+ * yield a profile with the name 'jeb_', their uuid and their textures.
|
||||
+ * To bypass this pre-population on an case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * The name comparison will compare the {@link String#toLowerCase()} version of both the passed name parameter and
|
||||
+ * a players name to honour the case-insensitive nature of a mojang profile lookup.
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) {
|
||||
+ return server.createProfile(uuid, name);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates an exact PlayerProfile for the specified name/uuid
|
||||
+ *
|
||||
+ * Both UUID and Name can not be null at same time. One must be supplied.
|
||||
+ * If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||
+ * profile will be populated with the properties of said player.
|
||||
+ * <p>
|
||||
+ * Compared to {@link #createProfile(UUID, String)}, this method will never mutate the passed uuid or name.
|
||||
+ * If a player with either the same uuid or a matching name (case-insensitive) is found on the server, their
|
||||
+ * properties, such as textures, will be pre-populated in the profile, however the passed uuid and name stay intact.
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name) {
|
||||
+ return server.createProfileExact(uuid, name);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 95d1e6c57c3331ce3badfb5269531dce490d4079..aad8b2fbdbb03fbf32f99b3a533716eca9d42219 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2024,5 +2024,74 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @return true if player names should be suggested
|
||||
*/
|
||||
boolean suggestPlayerNamesWhenNullTabCompletions();
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified uuid, with name as null.
|
||||
+ *
|
||||
+ * If a player with the passed uuid exists on the server at the time of creation, the returned player profile will
|
||||
+ * be populated with the properties of said player (including their uuid and name).
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified name, with UUID as null.
|
||||
+ *
|
||||
+ * If a player with the passed name exists on the server at the time of creation, the returned player profile will
|
||||
+ * be populated with the properties of said player (including their uuid and name).
|
||||
+ * <p>
|
||||
+ * E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile("JEB_")} will
|
||||
+ * yield a profile with the name 'jeb_', their uuid and their textures.
|
||||
+ * To bypass this pre-population on a case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified name/uuid
|
||||
+ *
|
||||
+ * Both UUID and Name can not be null at same time. One must be supplied.
|
||||
+ * If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||
+ * profile will be populated with the properties of said player (including their uuid and name).
|
||||
+ * <p>
|
||||
+ * E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile(null, "JEB_")} will
|
||||
+ * yield a profile with the name 'jeb_', their uuid and their textures.
|
||||
+ * To bypass this pre-population on an case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * The name comparison will compare the {@link String#toLowerCase()} version of both the passed name parameter and
|
||||
+ * a players name to honour the case-insensitive nature of a mojang profile lookup.
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates an exact PlayerProfile for the specified name/uuid
|
||||
+ *
|
||||
+ * Both UUID and Name can not be null at same time. One must be supplied.
|
||||
+ * If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||
+ * profile will be populated with the properties of said player.
|
||||
+ * <p>
|
||||
+ * Compared to {@link #createProfile(UUID, String)}, this method will never mutate the passed uuid or name.
|
||||
+ * If a player with either the same uuid or a matching name (case-insensitive) is found on the server, their
|
||||
+ * properties, such as textures, will be pre-populated in the profile, however the passed uuid and name stay intact.
|
||||
+ *
|
||||
+ * @param uuid UUID to create profile for
|
||||
+ * @param name Name to create profile for
|
||||
+ * @return A PlayerProfile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name);
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/profile/PlayerProfile.java b/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
index 16ae1282f3178e8873483a25a5d5cce16b2c21a9..fc46add38bf59dc1a04ea566fd230dcd8ae2708c 100644
|
||||
--- a/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
+++ b/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
@@ -93,7 +93,7 @@ public interface PlayerProfile extends Cloneable, ConfigurationSerializable {
|
||||
* PlayerProfile once it is available
|
||||
*/
|
||||
@NotNull
|
||||
- CompletableFuture<PlayerProfile> update();
|
||||
+ CompletableFuture<? extends PlayerProfile> update(); // Paper
|
||||
|
||||
@NotNull
|
||||
PlayerProfile clone();
|
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 May 2017 06:26:01 -0500
|
||||
Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java
|
||||
index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac018185cd38 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final Item item;
|
||||
+ private boolean flyAtPlayer = true; // Paper
|
||||
private boolean cancel = false;
|
||||
private final int remaining;
|
||||
|
||||
@@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable {
|
||||
return remaining;
|
||||
}
|
||||
|
||||
+ // Paper Start
|
||||
+ /**
|
||||
+ * Set if the item will fly at the player
|
||||
+ * <p>Cancelling the event will set this value to false.</p>
|
||||
+ *
|
||||
+ * @param flyAtPlayer True for item to fly at player
|
||||
+ */
|
||||
+ public void setFlyAtPlayer(boolean flyAtPlayer) {
|
||||
+ this.flyAtPlayer = flyAtPlayer;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets if the item will fly at the player
|
||||
+ *
|
||||
+ * @return True if the item will fly at the player
|
||||
+ */
|
||||
+ public boolean getFlyAtPlayer() {
|
||||
+ return flyAtPlayer;
|
||||
+ }
|
||||
+ // Paper End
|
||||
+
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
@@ -53,6 +75,7 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable {
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
+ this.flyAtPlayer = !cancel; // Paper
|
||||
}
|
||||
|
||||
@NotNull
|
|
@ -0,0 +1,37 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 15:04:51 -0400
|
||||
Subject: [PATCH] Shoulder Entities Release API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
index 3845a726adbd0e75d7bf2aeeb6da8cb571d51a8f..abdca9fe5acc90f167219eb769ece66c35682bb1 100644
|
||||
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
@@ -339,6 +339,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
|
||||
*/
|
||||
public int getExpToLevel();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned.
|
||||
+ * If no Entity is released, null will be returned.
|
||||
+ *
|
||||
+ * @return The released entity, or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Entity releaseLeftShoulderEntity();
|
||||
+
|
||||
+ /**
|
||||
+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned.
|
||||
+ * If no Entity is released, null will be returned.
|
||||
+ *
|
||||
+ * @return The released entity, or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Entity releaseRightShoulderEntity();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the current cooldown for a player's attack.
|
||||
*
|
23
patches/unapplied/api/0063-Entity-fromMobSpawner.patch
Normal file
23
patches/unapplied/api/0063-Entity-fromMobSpawner.patch
Normal file
|
@ -0,0 +1,23 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 18 Jun 2017 18:17:05 -0500
|
||||
Subject: [PATCH] Entity#fromMobSpawner()
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
|
||||
index 63137429779d06fafb162f1bfb823d5149b3c58a..4319dbac54b4cce95ad7479d5bd141a2b12ab7ae 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Entity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Entity.java
|
||||
@@ -749,5 +749,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
|
||||
*/
|
||||
@Nullable
|
||||
Location getOrigin();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether this entity was spawned from a mob spawner.
|
||||
+ *
|
||||
+ * @return True if entity spawned from a mob spawner
|
||||
+ */
|
||||
+ boolean fromMobSpawner();
|
||||
// Paper end
|
||||
}
|
174
patches/unapplied/api/0064-Profile-Lookup-Events.patch
Normal file
174
patches/unapplied/api/0064-Profile-Lookup-Events.patch
Normal file
|
@ -0,0 +1,174 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 16:30:44 -0400
|
||||
Subject: [PATCH] Profile Lookup Events
|
||||
|
||||
Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from
|
||||
profiles that had to be looked up.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8df37c07cd55ddf110d1dd68183d7b697f7a6756
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java
|
||||
@@ -0,0 +1,46 @@
|
||||
+package com.destroystokyo.paper.event.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Allows a plugin to be notified anytime AFTER a Profile has been looked up from the Mojang API
|
||||
+ * This is an opportunity to view the response and potentially cache things.
|
||||
+ *
|
||||
+ * No guarantees are made about thread execution context for this event. If you need to know, check
|
||||
+ * event.isAsync()
|
||||
+ */
|
||||
+public class LookupProfileEvent extends Event {
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull private final PlayerProfile profile;
|
||||
+
|
||||
+ public LookupProfileEvent(@NotNull PlayerProfile profile) {
|
||||
+ super(!Bukkit.isPrimaryThread());
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The profile that was recently looked up. This profile can be mutated
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4dcf6242c9acc62d030a94f67b78729ed29f8c85
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java
|
||||
@@ -0,0 +1,108 @@
|
||||
+package com.destroystokyo.paper.event.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
+import com.google.common.collect.ArrayListMultimap;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import java.util.UUID;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Allows a plugin to intercept a Profile Lookup for a Profile by name
|
||||
+ *
|
||||
+ * At the point of event fire, the UUID and properties are unset.
|
||||
+ *
|
||||
+ * If a plugin sets the UUID, and optionally the properties, the API call to look up the profile may be skipped.
|
||||
+ *
|
||||
+ * No guarantees are made about thread execution context for this event. If you need to know, check
|
||||
+ * event.isAsync()
|
||||
+ */
|
||||
+public class PreLookupProfileEvent extends Event {
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private final String name;
|
||||
+ private UUID uuid;
|
||||
+ @NotNull private Set<ProfileProperty> properties = new HashSet<>();
|
||||
+
|
||||
+ public PreLookupProfileEvent(@NotNull String name) {
|
||||
+ super(!Bukkit.isPrimaryThread());
|
||||
+ this.name = name;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Name of the profile
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getName() {
|
||||
+ return name;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If this value is left null by the completion of the event call, then the server will
|
||||
+ * trigger a call to the Mojang API to look up the UUID (Network Request), and subsequently, fire a
|
||||
+ * {@link LookupProfileEvent}
|
||||
+ *
|
||||
+ * @return The UUID of the profile if it has already been provided by a plugin
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public UUID getUUID() {
|
||||
+ return uuid;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the UUID for this player name. This will skip the initial API call to find the players UUID.
|
||||
+ *
|
||||
+ * However, if Profile Properties are needed by the server, you must also set them or else an API call might still be made.
|
||||
+ *
|
||||
+ * @param uuid the UUID to set for the profile or null to reset
|
||||
+ */
|
||||
+ public void setUUID(@Nullable UUID uuid) {
|
||||
+ this.uuid = uuid;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The currently pending prepopulated properties.
|
||||
+ * Any property in this Set will be automatically prefilled on this Profile
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Set<ProfileProperty> getProfileProperties() {
|
||||
+ return this.properties;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Clears any existing prepopulated properties and uses the supplied properties
|
||||
+ * Any property in this Set will be automatically prefilled on this Profile
|
||||
+ * @param properties The properties to add
|
||||
+ */
|
||||
+ public void setProfileProperties(@NotNull Set<ProfileProperty> properties) {
|
||||
+ this.properties = new HashSet<>();
|
||||
+ this.properties.addAll(properties);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Adds any properties currently missing to the prepopulated properties set, replacing any that already were set.
|
||||
+ * Any property in this Set will be automatically prefilled on this Profile
|
||||
+ * @param properties The properties to add
|
||||
+ */
|
||||
+ public void addProfileProperties(@NotNull Set<ProfileProperty> properties) {
|
||||
+ this.properties.addAll(properties);
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+}
|
|
@ -0,0 +1,83 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 10 Dec 2016 16:12:48 -0500
|
||||
Subject: [PATCH] Improve the Saddle API for Horses
|
||||
|
||||
Not all horses with Saddles have armor. This lets us break up the horses with saddles
|
||||
and access their saddle state separately from an interface shared with Armor.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb6a56950d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java
|
||||
@@ -0,0 +1,21 @@
|
||||
+package org.bukkit.inventory;
|
||||
+
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+public interface ArmoredHorseInventory extends AbstractHorseInventory {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the item in the horse's armor slot.
|
||||
+ *
|
||||
+ * @return the armor item
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ ItemStack getArmor();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the item in the horse's armor slot.
|
||||
+ *
|
||||
+ * @param stack the new item
|
||||
+ */
|
||||
+ void setArmor(@Nullable ItemStack stack);
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/HorseInventory.java b/src/main/java/org/bukkit/inventory/HorseInventory.java
|
||||
index 608e99c4207405bf9dd88d44ad8e82eefa19e45c..53498debe4cfb80592ef3025270bc8e5df4a5fec 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/HorseInventory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/HorseInventory.java
|
||||
@@ -5,20 +5,4 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* An interface to the inventory of a Horse.
|
||||
*/
|
||||
-public interface HorseInventory extends AbstractHorseInventory {
|
||||
-
|
||||
- /**
|
||||
- * Gets the item in the horse's armor slot.
|
||||
- *
|
||||
- * @return the armor item
|
||||
- */
|
||||
- @Nullable
|
||||
- ItemStack getArmor();
|
||||
-
|
||||
- /**
|
||||
- * Sets the item in the horse's armor slot.
|
||||
- *
|
||||
- * @param stack the new item
|
||||
- */
|
||||
- void setArmor(@Nullable ItemStack stack);
|
||||
-}
|
||||
+public interface HorseInventory extends AbstractHorseInventory, ArmoredHorseInventory {}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/LlamaInventory.java b/src/main/java/org/bukkit/inventory/LlamaInventory.java
|
||||
index 2fa2c9d07ecbafaf2396d913af90f1f4d432b238..5ac1afb8a213fa0fe344db4730ecbc5de6eed445 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/LlamaInventory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/LlamaInventory.java
|
||||
@@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* An interface to the inventory of a {@link Llama}.
|
||||
*/
|
||||
-public interface LlamaInventory extends AbstractHorseInventory {
|
||||
+public interface LlamaInventory extends SaddledHorseInventory {
|
||||
|
||||
/**
|
||||
* Gets the item in the llama's decor slot.
|
||||
diff --git a/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7944f26a3e2a92601c3be0e55c00c39cc16cf177
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java
|
||||
@@ -0,0 +1,3 @@
|
||||
+package org.bukkit.inventory;
|
||||
+
|
||||
+public interface SaddledHorseInventory extends AbstractHorseInventory {}
|
59
patches/unapplied/api/0066-Add-getI18NDisplayName-API.patch
Normal file
59
patches/unapplied/api/0066-Add-getI18NDisplayName-API.patch
Normal file
|
@ -0,0 +1,59 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 23:55:48 -0400
|
||||
Subject: [PATCH] Add getI18NDisplayName API
|
||||
|
||||
Gets the Display name as seen in the Client.
|
||||
Currently the server only supports the English language. To override this,
|
||||
You must replace the language file embedded in the server jar.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
index 6b1c55249b39a45c33ac49bacef4e9d80ba8cc3a..cccf5d3dfd368c434dcafb0e9319f09a668c7ec2 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
@@ -237,4 +237,20 @@ public interface ItemFactory {
|
||||
@NotNull
|
||||
net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
|
||||
// Paper end - Adventure
|
||||
+
|
||||
+ // Paper start - add getI18NDisplayName
|
||||
+ /**
|
||||
+ * Gets the Display name as seen in the Client.
|
||||
+ * Currently, the server only supports the English language. To override this,
|
||||
+ * You must replace the language file embedded in the server jar.
|
||||
+ *
|
||||
+ * @param item Item to return Display name of
|
||||
+ * @return Display name of Item
|
||||
+ * @deprecated {@link ItemStack} implements {@link net.kyori.adventure.translation.Translatable}; use that and
|
||||
+ * {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)} instead.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated
|
||||
+ String getI18NDisplayName(@Nullable ItemStack item);
|
||||
+ // Paper end - add getI18NDisplayName
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index 9d327f0832c40d4a8d212346284274f6cf78834f..09a36df6edce2a283df80c67d5ef62da7ff73555 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -618,5 +618,20 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
public net.kyori.adventure.text.@NotNull Component displayName() {
|
||||
return Bukkit.getServer().getItemFactory().displayName(this);
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the Display name as seen in the Client.
|
||||
+ * Currently the server only supports the English language. To override this,
|
||||
+ * You must replace the language file embedded in the server jar.
|
||||
+ *
|
||||
+ * @return Display name of Item
|
||||
+ * @deprecated {@link ItemStack} implements {@link net.kyori.adventure.translation.Translatable}; use that and
|
||||
+ * {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)} instead.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated
|
||||
+ public String getI18NDisplayName() {
|
||||
+ return Bukkit.getServer().getItemFactory().getI18NDisplayName(this);
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
64
patches/unapplied/api/0067-ensureServerConversions-API.patch
Normal file
64
patches/unapplied/api/0067-ensureServerConversions-API.patch
Normal file
|
@ -0,0 +1,64 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 23:55:48 -0400
|
||||
Subject: [PATCH] ensureServerConversions API
|
||||
|
||||
This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it,
|
||||
to ensure it meets latest minecraft expectations.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
index cccf5d3dfd368c434dcafb0e9319f09a668c7ec2..246b58f52e914c45f357240b155c826b1d40b202 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
@@ -253,4 +253,18 @@ public interface ItemFactory {
|
||||
@Deprecated
|
||||
String getI18NDisplayName(@Nullable ItemStack item);
|
||||
// Paper end - add getI18NDisplayName
|
||||
+
|
||||
+ // Paper start - ensure server conversions API
|
||||
+ /**
|
||||
+ * Minecraft's updates are converting simple item stacks into more complex NBT oriented Item Stacks.
|
||||
+ *
|
||||
+ * Use this method to ensure any desired data conversions are processed.
|
||||
+ * The input itemstack will not be the same as the returned itemstack.
|
||||
+ *
|
||||
+ * @param item The item to process conversions on
|
||||
+ * @return A potentially Data-Converted-ItemStack
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ ItemStack ensureServerConversions(@NotNull ItemStack item);
|
||||
+ // Paper end - ensure server conversions API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index 09a36df6edce2a283df80c67d5ef62da7ff73555..a8faa4c1881bae4d47d901388a78b991d138b518 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -537,7 +537,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
}
|
||||
}
|
||||
|
||||
- return result;
|
||||
+ return result.ensureServerConversions(); // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -619,6 +619,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
||||
return Bukkit.getServer().getItemFactory().displayName(this);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks.
|
||||
+ *
|
||||
+ * Use this method to ensure any desired data conversions are processed.
|
||||
+ * The input itemstack will not be the same as the returned itemstack.
|
||||
+ *
|
||||
+ * @return A potentially Data Converted ItemStack
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ItemStack ensureServerConversions() {
|
||||
+ return Bukkit.getServer().getItemFactory().ensureServerConversions(this);
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Gets the Display name as seen in the Client.
|
||||
* Currently the server only supports the English language. To override this,
|
26
patches/unapplied/api/0068-LivingEntity-setKiller.patch
Normal file
26
patches/unapplied/api/0068-LivingEntity-setKiller.patch
Normal file
|
@ -0,0 +1,26 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:49:43 -0500
|
||||
Subject: [PATCH] LivingEntity#setKiller
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
index 390bb294d09389877937ee2c6c3f346e65dfb178..6a9df4ec0eee205bcd37de9c4d04a6c67eb21644 100644
|
||||
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
@@ -319,6 +319,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
@Nullable
|
||||
public Player getKiller();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sets the player identified as the killer of the living entity.
|
||||
+ *
|
||||
+ * @param killer player
|
||||
+ */
|
||||
+ public void setKiller(@Nullable Player killer);
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Adds the given {@link PotionEffect} to the living entity.
|
||||
*
|
157
patches/unapplied/api/0069-ProfileWhitelistVerifyEvent.patch
Normal file
157
patches/unapplied/api/0069-ProfileWhitelistVerifyEvent.patch
Normal file
|
@ -0,0 +1,157 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 3 Jul 2017 18:11:34 -0500
|
||||
Subject: [PATCH] ProfileWhitelistVerifyEvent
|
||||
|
||||
Fires when the server is validating if a player is whitelisted.
|
||||
|
||||
Allows you to do dynamic whitelisting and change of kick message
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c6f5e2b5459368ad1e4db9929ca14568a25793fa
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java
|
||||
@@ -0,0 +1,142 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 - Daniel Ennis (Aikar) - MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Fires when the server needs to verify if a player is whitelisted.
|
||||
+ *
|
||||
+ * Plugins may override/control the servers whitelist with this event,
|
||||
+ * and dynamically change the kick message.
|
||||
+ */
|
||||
+public class ProfileWhitelistVerifyEvent extends Event {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private final PlayerProfile profile;
|
||||
+ private final boolean whitelistEnabled;
|
||||
+ private boolean whitelisted;
|
||||
+ private final boolean isOp;
|
||||
+ @Nullable private Component kickMessage;
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable String kickMessage) {
|
||||
+ this(profile, whitelistEnabled, whitelisted, isOp, kickMessage == null ? null : LegacyComponentSerializer.legacySection().deserialize(kickMessage));
|
||||
+ }
|
||||
+
|
||||
+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable Component kickMessage) {
|
||||
+ this.profile = profile;
|
||||
+ this.whitelistEnabled = whitelistEnabled;
|
||||
+ this.whitelisted = whitelisted;
|
||||
+ this.isOp = isOp;
|
||||
+ this.kickMessage = kickMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return the currently planned message to send to the user if they are not whitelisted
|
||||
+ * @deprecated use {@link #kickMessage()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ @Nullable
|
||||
+ public String getKickMessage() {
|
||||
+ return this.kickMessage == null ? null : LegacyComponentSerializer.legacySection().serialize(kickMessage);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default
|
||||
+ * @deprecated Use {@link #kickMessage(Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setKickMessage(@Nullable String kickMessage) {
|
||||
+ this.kickMessage(kickMessage == null ? null : LegacyComponentSerializer.legacySection().deserialize(kickMessage));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return the currently planned message to send to the user if they are not whitelisted
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Component kickMessage() {
|
||||
+ return this.kickMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default
|
||||
+ */
|
||||
+ public void kickMessage(@Nullable Component kickMessage) {
|
||||
+ this.kickMessage = kickMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The profile of the player trying to connect
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why its true)
|
||||
+ */
|
||||
+ public boolean isWhitelisted() {
|
||||
+ return whitelisted;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Changes the players whitelisted state. false will deny the login
|
||||
+ * @param whitelisted The new whitelisted state
|
||||
+ */
|
||||
+ public void setWhitelisted(boolean whitelisted) {
|
||||
+ this.whitelisted = whitelisted;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return if the player obtained whitelist status by having op
|
||||
+ */
|
||||
+ public boolean isOp() {
|
||||
+ return isOp;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return if the server even has whitelist on
|
||||
+ */
|
||||
+ public boolean isWhitelistEnabled() {
|
||||
+ return whitelistEnabled;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,73 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Thu, 21 Sep 2017 16:33:12 +0200
|
||||
Subject: [PATCH] Allow plugins to use SLF4J for logging
|
||||
|
||||
SLF4J is a commonly used abstraction for various logging frameworks
|
||||
such as java.util.logging (JUL) or Log4j. Currently, plugins are
|
||||
required to do all their logging using the provided JUL logger.
|
||||
This is annoying for plugins that target multiple platforms or when
|
||||
using libraries that log messages using SLF4J.
|
||||
|
||||
Expose SLF4J as optional logging API for plugins, so they can use
|
||||
it without having to shade it in the plugin and going through
|
||||
several layers of logging abstraction.
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 37d894eaffbf31045b1ed349d70af6408348a1a6..e827ee211e3c65dc68ac5867fd8476639df63645 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -12,6 +12,8 @@ java {
|
||||
val annotationsVersion = "24.0.1"
|
||||
val bungeeCordChatVersion = "1.20-R0.1"
|
||||
val adventureVersion = "4.14.0"
|
||||
+val slf4jVersion = "1.8.0-beta4"
|
||||
+val log4jVersion = "2.17.1"
|
||||
val apiAndDocs: Configuration by configurations.creating {
|
||||
attributes {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
|
||||
@@ -43,6 +45,8 @@ dependencies {
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-plain")
|
||||
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
|
||||
+ api("org.apache.logging.log4j:log4j-api:$log4jVersion")
|
||||
+ api("org.slf4j:slf4j-api:$slf4jVersion")
|
||||
|
||||
implementation("org.ow2.asm:asm:9.4")
|
||||
implementation("org.ow2.asm:asm-commons:9.4")
|
||||
@@ -134,6 +138,8 @@ tasks.withType<Javadoc> {
|
||||
"https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
|
||||
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
|
||||
+ "https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/",
|
||||
+ "https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/$log4jVersion/",
|
||||
// Paper end
|
||||
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper
|
||||
)
|
||||
diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
index 8c76716249e44ed8bf6be94c1f5c7b6d9bb35be2..4eb639fbb46a0848be207149ea433455550fae1c 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
@@ -198,6 +198,22 @@ public interface Plugin extends TabExecutor {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - Add SLF4J/Log4J loggers
|
||||
+ @NotNull
|
||||
+ default org.slf4j.Logger getSLF4JLogger() {
|
||||
+ return org.slf4j.LoggerFactory.getLogger(getLogger().getName());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @deprecated use {@link #getSLF4JLogger()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ @NotNull
|
||||
+ default org.apache.logging.log4j.Logger getLog4JLogger() {
|
||||
+ return org.apache.logging.log4j.LogManager.getLogger(getLogger().getName());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Returns the name of the plugin.
|
||||
* <p>
|
|
@ -0,0 +1,41 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Thu, 21 Sep 2017 16:14:13 +0200
|
||||
Subject: [PATCH] Handle plugin prefixes in implementation logging
|
||||
configuration
|
||||
|
||||
Currently, plugin prefixes are prepended to the log message in
|
||||
the PluginLogger before passing the message to the underlying
|
||||
logging framework. This is bad design because they need to be
|
||||
stripped manually when using custom appenders to log messages
|
||||
in a different format.
|
||||
|
||||
Additionally, it makes integration of alternative logging APIs hard
|
||||
because all logging must go through the PluginLogger. Avoid using
|
||||
PluginLogger and create a regular logger using the plugin name.
|
||||
The implementation should handle plugin prefixes by displaying
|
||||
logger names when appropriate.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
index f594913e6b94f77b26a4a758c447a42d8a25b6ff..7cd9f98c042dc2bb80876af35c755f81bef34651 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
@@ -46,7 +46,7 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
private boolean naggable = true;
|
||||
private FileConfiguration newConfig = null;
|
||||
private File configFile = null;
|
||||
- private PluginLogger logger = null;
|
||||
+ private Logger logger = null; // Paper - PluginLogger -> Logger
|
||||
|
||||
public JavaPlugin() {
|
||||
// Paper start
|
||||
@@ -303,8 +303,8 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
this.dataFolder = dataFolder;
|
||||
this.classLoader = classLoader;
|
||||
this.configFile = new File(dataFolder, "config.yml");
|
||||
- this.logger = new PluginLogger(this);
|
||||
this.pluginMeta = configuration; // Paper
|
||||
+ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); // Paper - Handle plugin prefix in implementation
|
||||
}
|
||||
|
||||
/**
|
118
patches/unapplied/api/0072-Add-PlayerJumpEvent.patch
Normal file
118
patches/unapplied/api/0072-Add-PlayerJumpEvent.patch
Normal file
|
@ -0,0 +1,118 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Thu, 28 Sep 2017 17:21:32 -0400
|
||||
Subject: [PATCH] Add PlayerJumpEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..289a0d784a3c74caf8a7231b4dd166096b1849a1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java
|
||||
@@ -0,0 +1,106 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when the server detects the player is jumping.
|
||||
+ * <p>
|
||||
+ * Added to avoid the overhead and special case logic that many plugins use
|
||||
+ * when checking for jumps via PlayerMoveEvent, this event is fired whenever
|
||||
+ * the server detects that the player is jumping.
|
||||
+ */
|
||||
+public class PlayerJumpEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancel = false;
|
||||
+ @NotNull private Location from;
|
||||
+ @NotNull private Location to;
|
||||
+
|
||||
+ public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) {
|
||||
+ super(player);
|
||||
+ this.from = from;
|
||||
+ this.to = to;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the cancellation state of this event. A cancelled event will not
|
||||
+ * be executed in the server, but will still pass to other plugins
|
||||
+ * <p>
|
||||
+ * If a jump event is cancelled, the player will be moved or
|
||||
+ * teleported back to the Location as defined by getFrom(). This will not
|
||||
+ * fire an event
|
||||
+ *
|
||||
+ * @return true if this event is cancelled
|
||||
+ */
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the cancellation state of this event. A cancelled event will not
|
||||
+ * be executed in the server, but will still pass to other plugins
|
||||
+ * <p>
|
||||
+ * If a jump event is cancelled, the player will be moved or
|
||||
+ * teleported back to the Location as defined by getFrom(). This will not
|
||||
+ * fire an event
|
||||
+ *
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancel = cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the location this player jumped from
|
||||
+ *
|
||||
+ * @return Location the player jumped from
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getFrom() {
|
||||
+ return from;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the location to mark as where the player jumped from
|
||||
+ *
|
||||
+ * @param from New location to mark as the players previous location
|
||||
+ */
|
||||
+ public void setFrom(@NotNull Location from) {
|
||||
+ validateLocation(from);
|
||||
+ this.from = from;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the location this player jumped to
|
||||
+ *
|
||||
+ * This information is based on what the client sends, it typically
|
||||
+ * has little relation to the arc of the jump at any given point.
|
||||
+ *
|
||||
+ * @return Location the player jumped to
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getTo() {
|
||||
+ return to;
|
||||
+ }
|
||||
+
|
||||
+ private void validateLocation(Location loc) {
|
||||
+ Preconditions.checkArgument(loc != null, "Cannot use null location!");
|
||||
+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!");
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,115 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Thu, 21 Sep 2017 19:41:20 +0200
|
||||
Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin
|
||||
logger
|
||||
|
||||
Essentials uses a custom logger name ("Essentials") instead of the
|
||||
plugin logger. Log messages are redirected to the plugin logger by
|
||||
setting the parent of the "Essentials" logger to the plugin logger.
|
||||
|
||||
With our changes, the plugin logger is now also called "Essentials",
|
||||
resulting in an infinite loop. Make sure plugins can't change the
|
||||
parent of the plugin logger to avoid this.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d90a18f9f8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java
|
||||
@@ -0,0 +1,48 @@
|
||||
+package com.destroystokyo.paper.utils;
|
||||
+
|
||||
+import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||
+import org.bukkit.plugin.PluginDescriptionFile;
|
||||
+
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.logging.LogManager;
|
||||
+import java.util.logging.Logger;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger.
|
||||
+ */
|
||||
+public class PaperPluginLogger extends Logger {
|
||||
+
|
||||
+ @Deprecated(forRemoval = true)
|
||||
+ @NotNull
|
||||
+ public static Logger getLogger(@NotNull PluginDescriptionFile description) {
|
||||
+ return getLogger((PluginMeta) description);
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static Logger getLogger(@NotNull PluginMeta meta) {
|
||||
+ Logger logger = new PaperPluginLogger(meta);
|
||||
+ if (!LogManager.getLogManager().addLogger(logger)) {
|
||||
+ // Disable this if it's going to happen across reloads anyways...
|
||||
+ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName()));
|
||||
+ logger = LogManager.getLogManager().getLogger(meta.getLoggerPrefix() != null ? meta.getLoggerPrefix() : meta.getName());
|
||||
+ }
|
||||
+
|
||||
+ return logger;
|
||||
+ }
|
||||
+
|
||||
+ private PaperPluginLogger(@NotNull PluginMeta meta) {
|
||||
+ super(meta.getLoggerPrefix() != null ? meta.getLoggerPrefix() : meta.getName(), null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setParent(@NotNull Logger parent) {
|
||||
+ if (getParent() != null) {
|
||||
+ warning("Ignoring attempt to change parent of plugin logger");
|
||||
+ } else {
|
||||
+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent);
|
||||
+ super.setParent(parent);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
index 7cd9f98c042dc2bb80876af35c755f81bef34651..5cd236965de12392d8c7aa81307c0ff1cc8673b1 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
@@ -291,10 +291,10 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
.orElseThrow();
|
||||
}
|
||||
public final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) {
|
||||
- init(server, description, dataFolder, file, classLoader, description);
|
||||
+ init(server, description, dataFolder, file, classLoader, description, com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description));
|
||||
this.pluginMeta = description;
|
||||
}
|
||||
- public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration) {
|
||||
+ public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration, @NotNull Logger logger) {
|
||||
// Paper end
|
||||
this.loader = DummyPluginLoaderImplHolder.INSTANCE; // Paper
|
||||
this.server = server;
|
||||
@@ -304,7 +304,7 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
this.classLoader = classLoader;
|
||||
this.configFile = new File(dataFolder, "config.yml");
|
||||
this.pluginMeta = configuration; // Paper
|
||||
- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); // Paper - Handle plugin prefix in implementation
|
||||
+ this.logger = logger; // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
index 74b6581a97a092c44a0876e7981ff8a8e6153100..d6d3e1332e51adc5611543b2a6689efa5921a9f2 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
@@ -67,6 +67,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
||||
this.url = file.toURI().toURL();
|
||||
this.libraryLoader = libraryLoader;
|
||||
|
||||
+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early
|
||||
// Paper start
|
||||
this.dependencyContext = dependencyContext;
|
||||
this.classLoaderGroup = io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage.instance().registerSpigotGroup(this);
|
||||
@@ -262,7 +263,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
||||
pluginState = new IllegalStateException("Initial initialization");
|
||||
this.pluginInit = javaPlugin;
|
||||
|
||||
- javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper
|
||||
+ javaPlugin.init(org.bukkit.Bukkit.getServer(), description, dataFolder, file, this, description, this.logger); // Paper
|
||||
}
|
||||
|
||||
// Paper start
|
151
patches/unapplied/api/0074-Add-PlayerArmorChangeEvent.patch
Normal file
151
patches/unapplied/api/0074-Add-PlayerArmorChangeEvent.patch
Normal file
|
@ -0,0 +1,151 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: pkt77 <parkerkt77@gmail.com>
|
||||
Date: Fri, 10 Nov 2017 23:45:59 -0500
|
||||
Subject: [PATCH] Add PlayerArmorChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..57521010ff0574f1bbc96727948a6185fd37e9ee
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java
|
||||
@@ -0,0 +1,139 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import static org.bukkit.Material.*;
|
||||
+
|
||||
+/**
|
||||
+ * Called when the player themselves change their armor items
|
||||
+ * <p>
|
||||
+ * Not currently called for environmental factors though it <strong>MAY BE IN THE FUTURE</strong>
|
||||
+ */
|
||||
+public class PlayerArmorChangeEvent extends PlayerEvent {
|
||||
+ private static final HandlerList HANDLERS = new HandlerList();
|
||||
+
|
||||
+ @NotNull private final SlotType slotType;
|
||||
+ @NotNull private final ItemStack oldItem;
|
||||
+ @NotNull private final ItemStack newItem;
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @NotNull ItemStack oldItem, @NotNull ItemStack newItem) {
|
||||
+ super(player);
|
||||
+ this.slotType = slotType;
|
||||
+ this.oldItem = oldItem;
|
||||
+ this.newItem = newItem;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the type of slot being altered.
|
||||
+ *
|
||||
+ * @return type of slot being altered
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public SlotType getSlotType() {
|
||||
+ return this.slotType;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the existing item that's being replaced
|
||||
+ *
|
||||
+ * @return old item
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ItemStack getOldItem() {
|
||||
+ return this.oldItem;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the new item that's replacing the old
|
||||
+ *
|
||||
+ * @return new item
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ItemStack getNewItem() {
|
||||
+ return this.newItem;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}';
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return HANDLERS;
|
||||
+ }
|
||||
+
|
||||
+ public enum SlotType {
|
||||
+ HEAD(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, CARVED_PUMPKIN, PLAYER_HEAD, SKELETON_SKULL, ZOMBIE_HEAD, CREEPER_HEAD, WITHER_SKELETON_SKULL, TURTLE_HELMET, DRAGON_HEAD, PIGLIN_HEAD),
|
||||
+ CHEST(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA),
|
||||
+ LEGS(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS),
|
||||
+ FEET(NETHERITE_BOOTS, DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS);
|
||||
+
|
||||
+ private final Set<Material> mutableTypes = new HashSet<>();
|
||||
+ private Set<Material> immutableTypes;
|
||||
+
|
||||
+ SlotType(Material... types) {
|
||||
+ this.mutableTypes.addAll(Arrays.asList(types));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets an immutable set of all allowed material types that can be placed in an
|
||||
+ * armor slot.
|
||||
+ *
|
||||
+ * @return immutable set of material types
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Set<Material> getTypes() {
|
||||
+ if (immutableTypes == null) {
|
||||
+ immutableTypes = Collections.unmodifiableSet(mutableTypes);
|
||||
+ }
|
||||
+
|
||||
+ return immutableTypes;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the type of slot via the specified material
|
||||
+ *
|
||||
+ * @param material material to get slot by
|
||||
+ * @return slot type the material will go in, or null if it won't
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public static SlotType getByMaterial(@NotNull Material material) {
|
||||
+ for (SlotType slotType : values()) {
|
||||
+ if (slotType.getTypes().contains(material)) {
|
||||
+ return slotType;
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether this material can be equipped to a slot
|
||||
+ *
|
||||
+ * @param material material to check
|
||||
+ * @return whether this material can be equipped
|
||||
+ */
|
||||
+ public static boolean isEquipable(@NotNull Material material) {
|
||||
+ return getByMaterial(material) != null;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 6 Nov 2017 21:10:01 -0500
|
||||
Subject: [PATCH] API to get a BlockState without a snapshot
|
||||
|
||||
This allows you to get a BlockState without creating a snapshot, operating
|
||||
on the real tile entity.
|
||||
|
||||
This is useful for where performance is needed
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
|
||||
index 870ad6cd930653e6248abcc0fce94ffafbe9ebde..9f4d383ea3d6b26d16b8b77ca4c29d2d839ad6dd 100644
|
||||
--- a/src/main/java/org/bukkit/block/Block.java
|
||||
+++ b/src/main/java/org/bukkit/block/Block.java
|
||||
@@ -272,6 +272,16 @@ public interface Block extends Metadatable, Translatable {
|
||||
@NotNull
|
||||
BlockState getState();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * @see #getState() optionally disables use of snapshot, to operate on real block data
|
||||
+ * @param useSnapshot if this block is a TE, should we create a fully copy of the TileEntity
|
||||
+ * @return BlockState with the current state of this block
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ BlockState getState(boolean useSnapshot);
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Returns the biome that this block resides in
|
||||
*
|
||||
diff --git a/src/main/java/org/bukkit/block/TileState.java b/src/main/java/org/bukkit/block/TileState.java
|
||||
index 3b10fcc13893403b29f0260b8605144679e89b82..5c8517c5bcae10161952c104b6a4ff7c713bcdbd 100644
|
||||
--- a/src/main/java/org/bukkit/block/TileState.java
|
||||
+++ b/src/main/java/org/bukkit/block/TileState.java
|
||||
@@ -36,4 +36,18 @@ public interface TileState extends BlockState, PersistentDataHolder {
|
||||
@NotNull
|
||||
@Override
|
||||
PersistentDataContainer getPersistentDataContainer();
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Checks if this TileState is a snapshot or a live
|
||||
+ * representation of the underlying tile entity.
|
||||
+ * <p>
|
||||
+ * NOTE: You may still have to call {@link BlockState#update()} on
|
||||
+ * live representations to update any visuals on the block.
|
||||
+ *
|
||||
+ * @return true if this is a snapshot
|
||||
+ * @see Block#getState(boolean)
|
||||
+ */
|
||||
+ boolean isSnapshot();
|
||||
+ // Paper end
|
||||
}
|
592
patches/unapplied/api/0076-AsyncTabCompleteEvent.patch
Normal file
592
patches/unapplied/api/0076-AsyncTabCompleteEvent.patch
Normal file
|
@ -0,0 +1,592 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Sun, 26 Nov 2017 13:17:09 -0500
|
||||
Subject: [PATCH] AsyncTabCompleteEvent
|
||||
|
||||
Let plugins be able to control tab completion of commands and chat async.
|
||||
|
||||
This will be useful for frameworks like ACF so we can define async safe completion handlers,
|
||||
and avoid going to main for tab completions.
|
||||
|
||||
Especially useful if you need to query a database in order to obtain the results for tab
|
||||
completion, such as offline players.
|
||||
|
||||
Co-authored-by: Aikar <aikar@aikar.co>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9be64a95c2345433b6142d611077dedadcef9f5d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java
|
||||
@@ -0,0 +1,328 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import io.papermc.paper.util.TransformingRandomAccessList;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.examination.Examinable;
|
||||
+import net.kyori.examination.ExaminableProperty;
|
||||
+import net.kyori.examination.string.StringExaminer;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.stream.Stream;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Allows plugins to compute tab completion results asynchronously. If this event provides completions, then the standard synchronous process will not be fired to populate the results. However, the synchronous TabCompleteEvent will fire with the Async results.
|
||||
+ *
|
||||
+ * Only 1 process will be allowed to provide completions, the Async Event, or the standard process.
|
||||
+ */
|
||||
+public class AsyncTabCompleteEvent extends Event implements Cancellable {
|
||||
+ @NotNull private final CommandSender sender;
|
||||
+ @NotNull private final String buffer;
|
||||
+ private final boolean isCommand;
|
||||
+ @Nullable
|
||||
+ private final Location loc;
|
||||
+ private final List<Completion> completions = new ArrayList<>();
|
||||
+ private final List<String> stringCompletions = new TransformingRandomAccessList<>(
|
||||
+ this.completions,
|
||||
+ Completion::suggestion,
|
||||
+ Completion::completion
|
||||
+ );
|
||||
+ private boolean cancelled;
|
||||
+ private boolean handled = false;
|
||||
+ private boolean fireSyncHandler = true;
|
||||
+
|
||||
+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, boolean isCommand, @Nullable Location loc) {
|
||||
+ super(true);
|
||||
+ this.sender = sender;
|
||||
+ this.buffer = buffer;
|
||||
+ this.isCommand = isCommand;
|
||||
+ this.loc = loc;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List<String> completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) {
|
||||
+ super(true);
|
||||
+ this.sender = sender;
|
||||
+ this.completions.addAll(fromStrings(completions));
|
||||
+ this.buffer = buffer;
|
||||
+ this.isCommand = isCommand;
|
||||
+ this.loc = loc;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the sender completing this command.
|
||||
+ *
|
||||
+ * @return the {@link CommandSender} instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public CommandSender getSender() {
|
||||
+ return sender;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The list of completions which will be offered to the sender, in order.
|
||||
+ * This list is mutable and reflects what will be offered.
|
||||
+ *
|
||||
+ * If this collection is not empty after the event is fired, then
|
||||
+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ *
|
||||
+ * @return a list of offered completions
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public List<String> getCompletions() {
|
||||
+ return this.stringCompletions;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set the completions offered, overriding any already set.
|
||||
+ * If this collection is not empty after the event is fired, then
|
||||
+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ *
|
||||
+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here
|
||||
+ *
|
||||
+ * @param completions the new completions
|
||||
+ */
|
||||
+ public void setCompletions(@NotNull List<String> completions) {
|
||||
+ if (completions == this.stringCompletions) {
|
||||
+ return;
|
||||
+ }
|
||||
+ Preconditions.checkNotNull(completions);
|
||||
+ this.completions.clear();
|
||||
+ this.completions.addAll(fromStrings(completions));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The list of {@link Completion completions} which will be offered to the sender, in order.
|
||||
+ * This list is mutable and reflects what will be offered.
|
||||
+ * <p>
|
||||
+ * If this collection is not empty after the event is fired, then
|
||||
+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ *
|
||||
+ * @return a list of offered completions
|
||||
+ */
|
||||
+ public @NotNull List<Completion> completions() {
|
||||
+ return this.completions;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set the {@link Completion completions} offered, overriding any already set.
|
||||
+ * If this collection is not empty after the event is fired, then
|
||||
+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ * <p>
|
||||
+ * The passed collection will be cloned to a new List. You must call {{@link #completions()}} to mutate from here
|
||||
+ *
|
||||
+ * @param newCompletions the new completions
|
||||
+ */
|
||||
+ public void completions(final @NotNull List<Completion> newCompletions) {
|
||||
+ Preconditions.checkNotNull(newCompletions, "new completions");
|
||||
+ this.completions.clear();
|
||||
+ this.completions.addAll(newCompletions);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Return the entire buffer which formed the basis of this completion.
|
||||
+ *
|
||||
+ * @return command buffer, as entered
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getBuffer() {
|
||||
+ return buffer;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return True if it is a command being tab completed, false if it is a chat message.
|
||||
+ */
|
||||
+ public boolean isCommand() {
|
||||
+ return isCommand;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The position looked at by the sender, or null if none
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Location getLocation() {
|
||||
+ return loc;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ *
|
||||
+ * @return Is completions considered handled. Always true if completions is not empty.
|
||||
+ */
|
||||
+ public boolean isHandled() {
|
||||
+ return !completions.isEmpty() || handled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether or not to consider the completion request handled.
|
||||
+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
|
||||
+ * or current player names will not be called.
|
||||
+ *
|
||||
+ * @param handled if this completion should be marked as being handled
|
||||
+ */
|
||||
+ public void setHandled(boolean handled) {
|
||||
+ this.handled = handled;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Will provide no completions, and will not fire the synchronous process
|
||||
+ * @param cancelled true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancelled) {
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private static @NotNull List<Completion> fromStrings(final @NotNull List<String> strings) {
|
||||
+ final List<Completion> list = new ArrayList<>();
|
||||
+ for (final String it : strings) {
|
||||
+ list.add(new CompletionImpl(it, null));
|
||||
+ }
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * A rich tab completion, consisting of a string suggestion, and a nullable {@link Component} tooltip.
|
||||
+ */
|
||||
+ public interface Completion extends Examinable {
|
||||
+ /**
|
||||
+ * Get the suggestion string for this {@link Completion}.
|
||||
+ *
|
||||
+ * @return suggestion string
|
||||
+ */
|
||||
+ @NotNull String suggestion();
|
||||
+
|
||||
+ /**
|
||||
+ * Get the suggestion tooltip for this {@link Completion}.
|
||||
+ *
|
||||
+ * @return tooltip component
|
||||
+ */
|
||||
+ @Nullable Component tooltip();
|
||||
+
|
||||
+ @Override
|
||||
+ default @NotNull Stream<? extends ExaminableProperty> examinableProperties() {
|
||||
+ return Stream.of(ExaminableProperty.of("suggestion", this.suggestion()), ExaminableProperty.of("tooltip", this.tooltip()));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a new {@link Completion} from a suggestion string.
|
||||
+ *
|
||||
+ * @param suggestion suggestion string
|
||||
+ * @return new completion instance
|
||||
+ */
|
||||
+ static @NotNull Completion completion(final @NotNull String suggestion) {
|
||||
+ return new CompletionImpl(suggestion, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a new {@link Completion} from a suggestion string and a tooltip {@link Component}.
|
||||
+ *
|
||||
+ * <p>If the provided component is null, the suggestion will not have a tooltip.</p>
|
||||
+ *
|
||||
+ * @param suggestion suggestion string
|
||||
+ * @param tooltip tooltip component, or null
|
||||
+ * @return new completion instance
|
||||
+ */
|
||||
+ static @NotNull Completion completion(final @NotNull String suggestion, final @Nullable Component tooltip) {
|
||||
+ return new CompletionImpl(suggestion, tooltip);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ static final class CompletionImpl implements Completion {
|
||||
+ private final String suggestion;
|
||||
+ private final Component tooltip;
|
||||
+
|
||||
+ CompletionImpl(final @NotNull String suggestion, final @Nullable Component tooltip) {
|
||||
+ this.suggestion = suggestion;
|
||||
+ this.tooltip = tooltip;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull String suggestion() {
|
||||
+ return this.suggestion;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable Component tooltip() {
|
||||
+ return this.tooltip;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final @Nullable Object o) {
|
||||
+ if (this == o) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (o == null || this.getClass() != o.getClass()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ final CompletionImpl that = (CompletionImpl) o;
|
||||
+ return this.suggestion.equals(that.suggestion)
|
||||
+ && java.util.Objects.equals(this.tooltip, that.tooltip);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return java.util.Objects.hash(this.suggestion, this.tooltip);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull String toString() {
|
||||
+ return StringExaminer.simpleEscaping().examine(this);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276118c1c7b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java
|
||||
@@ -0,0 +1,169 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.AbstractList;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.List;
|
||||
+import java.util.ListIterator;
|
||||
+import java.util.RandomAccess;
|
||||
+import java.util.function.Function;
|
||||
+import java.util.function.Predicate;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Modified version of the Guava class with the same name to support add operations.
|
||||
+ *
|
||||
+ * @param <F> backing list element type
|
||||
+ * @param <T> transformed list element type
|
||||
+ */
|
||||
+public final class TransformingRandomAccessList<F, T> extends AbstractList<T> implements RandomAccess {
|
||||
+ final List<F> fromList;
|
||||
+ final Function<? super F, ? extends T> toFunction;
|
||||
+ final Function<? super T, ? extends F> fromFunction;
|
||||
+
|
||||
+ /**
|
||||
+ * Create a new {@link TransformingRandomAccessList}.
|
||||
+ *
|
||||
+ * @param fromList backing list
|
||||
+ * @param toFunction function mapping backing list element type to transformed list element type
|
||||
+ * @param fromFunction function mapping transformed list element type to backing list element type
|
||||
+ */
|
||||
+ public TransformingRandomAccessList(
|
||||
+ final @NonNull List<F> fromList,
|
||||
+ final @NonNull Function<? super F, ? extends T> toFunction,
|
||||
+ final @NonNull Function<? super T, ? extends F> fromFunction
|
||||
+ ) {
|
||||
+ this.fromList = checkNotNull(fromList);
|
||||
+ this.toFunction = checkNotNull(toFunction);
|
||||
+ this.fromFunction = checkNotNull(fromFunction);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clear() {
|
||||
+ this.fromList.clear();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T get(int index) {
|
||||
+ return this.toFunction.apply(this.fromList.get(index));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Iterator<T> iterator() {
|
||||
+ return this.listIterator();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ListIterator<T> listIterator(int index) {
|
||||
+ return new TransformedListIterator<F, T>(this.fromList.listIterator(index)) {
|
||||
+ @Override
|
||||
+ T transform(F from) {
|
||||
+ return TransformingRandomAccessList.this.toFunction.apply(from);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ F transformBack(T from) {
|
||||
+ return TransformingRandomAccessList.this.fromFunction.apply(from);
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEmpty() {
|
||||
+ return this.fromList.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeIf(Predicate<? super T> filter) {
|
||||
+ checkNotNull(filter);
|
||||
+ return this.fromList.removeIf(element -> filter.test(this.toFunction.apply(element)));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T remove(int index) {
|
||||
+ return this.toFunction.apply(this.fromList.remove(index));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return this.fromList.size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T set(int i, T t) {
|
||||
+ return this.toFunction.apply(this.fromList.set(i, this.fromFunction.apply(t)));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void add(int i, T t) {
|
||||
+ this.fromList.add(i, this.fromFunction.apply(t));
|
||||
+ }
|
||||
+
|
||||
+ static abstract class TransformedListIterator<F, T> implements ListIterator<T>, Iterator<T> {
|
||||
+ final Iterator<F> backingIterator;
|
||||
+
|
||||
+ TransformedListIterator(ListIterator<F> backingIterator) {
|
||||
+ this.backingIterator = checkNotNull((Iterator<F>) backingIterator);
|
||||
+ }
|
||||
+
|
||||
+ private ListIterator<F> backingIterator() {
|
||||
+ return cast(this.backingIterator);
|
||||
+ }
|
||||
+
|
||||
+ static <A> ListIterator<A> cast(Iterator<A> iterator) {
|
||||
+ return (ListIterator<A>) iterator;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final boolean hasPrevious() {
|
||||
+ return this.backingIterator().hasPrevious();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final T previous() {
|
||||
+ return this.transform(this.backingIterator().previous());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final int nextIndex() {
|
||||
+ return this.backingIterator().nextIndex();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final int previousIndex() {
|
||||
+ return this.backingIterator().previousIndex();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void set(T element) {
|
||||
+ this.backingIterator().set(this.transformBack(element));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void add(T element) {
|
||||
+ this.backingIterator().add(this.transformBack(element));
|
||||
+ }
|
||||
+
|
||||
+ abstract T transform(F from);
|
||||
+
|
||||
+ abstract F transformBack(T to);
|
||||
+
|
||||
+ @Override
|
||||
+ public final boolean hasNext() {
|
||||
+ return this.backingIterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final T next() {
|
||||
+ return this.transform(this.backingIterator.next());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public final void remove() {
|
||||
+ this.backingIterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
index 270e6d8ad4358baa256cee5f16cff281f063ce3b..4a3451af454295ac3e1b688e6665cad9fc594c82 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
@@ -29,6 +29,13 @@ public class TabCompleteEvent extends Event implements Cancellable {
|
||||
private boolean cancelled;
|
||||
|
||||
public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List<String> completions) {
|
||||
+ // Paper start
|
||||
+ this(sender, buffer, completions, sender instanceof org.bukkit.command.ConsoleCommandSender || buffer.startsWith("/"), null);
|
||||
+ }
|
||||
+ public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List<String> completions, boolean isCommand, @org.jetbrains.annotations.Nullable org.bukkit.Location location) {
|
||||
+ this.isCommand = isCommand;
|
||||
+ this.loc = location;
|
||||
+ // Paper end
|
||||
Preconditions.checkArgument(sender != null, "sender");
|
||||
Preconditions.checkArgument(buffer != null, "buffer");
|
||||
Preconditions.checkArgument(completions != null, "completions");
|
||||
@@ -69,14 +76,35 @@ public class TabCompleteEvent extends Event implements Cancellable {
|
||||
return completions;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private final boolean isCommand;
|
||||
+ private final org.bukkit.Location loc;
|
||||
+ /**
|
||||
+ * @return True if it is a command being tab completed, false if it is a chat message.
|
||||
+ */
|
||||
+ public boolean isCommand() {
|
||||
+ return isCommand;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The position looked at by the sender, or null if none
|
||||
+ */
|
||||
+ @org.jetbrains.annotations.Nullable
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ return loc;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Set the completions offered, overriding any already set.
|
||||
*
|
||||
+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here
|
||||
+ *
|
||||
* @param completions the new completions
|
||||
*/
|
||||
public void setCompletions(@NotNull List<String> completions) {
|
||||
Preconditions.checkArgument(completions != null);
|
||||
- this.completions = completions;
|
||||
+ this.completions = new java.util.ArrayList<>(completions); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
index abadff47166722fdc756afdbc6ac7242b6bd4fb0..88f1ca89fa640a686231b8eec87e70419b2d73ef 100644
|
||||
--- a/src/test/java/org/bukkit/AnnotationTest.java
|
||||
+++ b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
@@ -48,6 +48,8 @@ public class AnnotationTest {
|
||||
// Generic functional interface
|
||||
"org/bukkit/util/Consumer",
|
||||
// Paper start
|
||||
+ "io/papermc/paper/util/TransformingRandomAccessList",
|
||||
+ "io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator",
|
||||
// Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull
|
||||
"co/aikar/timings/TimingHistory$2",
|
||||
"co/aikar/timings/TimingHistory$2$1",
|
|
@ -0,0 +1,71 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Tue, 10 Oct 2017 18:44:42 +0200
|
||||
Subject: [PATCH] Expose client protocol version and virtual host
|
||||
|
||||
Add a NetworkClient interface that provides access to:
|
||||
- The socket address
|
||||
- The protocol version
|
||||
- The virtual host (the hostname/port the client used to connect
|
||||
to the server)
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/NetworkClient.java b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b851aa04f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java
|
||||
@@ -0,0 +1,41 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import java.net.InetSocketAddress;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a client connected to the server.
|
||||
+ */
|
||||
+public interface NetworkClient {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the socket address of the client.
|
||||
+ *
|
||||
+ * @return The client's socket address
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ InetSocketAddress getAddress();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the protocol version of the client.
|
||||
+ *
|
||||
+ * @return The client's protocol version, or {@code -1} if unknown
|
||||
+ * @see <a href="http://wiki.vg/Protocol_version_numbers">List of protocol
|
||||
+ * version numbers</a>
|
||||
+ */
|
||||
+ int getProtocolVersion();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the virtual host the client is connected to.
|
||||
+ *
|
||||
+ * <p>The virtual host refers to the hostname/port the client used to
|
||||
+ * connect to the server.</p>
|
||||
+ *
|
||||
+ * @return The client's virtual host, or {@code null} if unknown
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ InetSocketAddress getVirtualHost();
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 74823885b0836db404737199b21c09c1ebcbad3c..0da374b18e0f602e9836cfaefe07c5219a7d9bd1 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -51,7 +51,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a player, connected or not
|
||||
*/
|
||||
-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer { // Paper
|
||||
+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer, com.destroystokyo.paper.network.NetworkClient { // Paper
|
||||
|
||||
// Paper start
|
||||
@Override
|
|
@ -0,0 +1,35 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 9 Dec 2017 12:40:25 -0500
|
||||
Subject: [PATCH] Display warning on deprecated recipe API
|
||||
|
||||
Any plugin still using this API will result in the server saving an inconsistent UUID to player data files,
|
||||
which then triggers warnings such as "Tried to load unrecognized recipe: bukkit:9e5b92f5-e549-4f47-b0a8-9f89390ed77b removed now."
|
||||
on the players login.
|
||||
|
||||
Plugin authors need to define a key to keep it consistent between server restarts.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
index 9f9c67e935940833bbfe58e6bfa398e6c86980d5..71e494177473c62449aafda1699b26a0c4c81a68 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
@@ -31,6 +31,7 @@ public class ShapedRecipe extends CraftingRecipe {
|
||||
@Deprecated
|
||||
public ShapedRecipe(@NotNull ItemStack result) {
|
||||
super(NamespacedKey.randomKey(), result);
|
||||
+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
index 03839302c94adc3175d0a88065cd230257ffd20d..d6e38c7ccfe3b6e85eafb611da20b1a29fb74d97 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
@@ -20,6 +20,7 @@ public class ShapelessRecipe extends CraftingRecipe {
|
||||
@Deprecated
|
||||
public ShapelessRecipe(@NotNull ItemStack result) {
|
||||
super(NamespacedKey.randomKey(), result);
|
||||
+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
|
||||
}
|
||||
|
||||
/**
|
93
patches/unapplied/api/0079-PlayerPickupExperienceEvent.patch
Normal file
93
patches/unapplied/api/0079-PlayerPickupExperienceEvent.patch
Normal file
|
@ -0,0 +1,93 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 19 Dec 2017 22:00:41 -0500
|
||||
Subject: [PATCH] PlayerPickupExperienceEvent
|
||||
|
||||
Allows plugins to cancel a player picking up an experience orb
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f7beb22d5105157940b39efe594ace9d4cb153f5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java
|
||||
@@ -0,0 +1,80 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.ExperienceOrb;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when a player is attempting to pick up an experience orb
|
||||
+ */
|
||||
+public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable {
|
||||
+ @NotNull private final ExperienceOrb experienceOrb;
|
||||
+
|
||||
+ public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) {
|
||||
+ super(player);
|
||||
+ this.experienceOrb = experienceOrb;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Returns the Orb that the player is picking up
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ExperienceOrb getExperienceOrb() {
|
||||
+ return experienceOrb;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If true, Cancels picking up the experience orb, leaving it in the world
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
102
patches/unapplied/api/0080-ExperienceOrbMergeEvent.patch
Normal file
102
patches/unapplied/api/0080-ExperienceOrbMergeEvent.patch
Normal file
|
@ -0,0 +1,102 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 19 Dec 2017 22:56:24 -0500
|
||||
Subject: [PATCH] ExperienceOrbMergeEvent
|
||||
|
||||
Fired when the server is about to merge 2 experience orbs
|
||||
Plugins can cancel this if they want to ensure experience orbs do not lose important
|
||||
metadata such as spawn reason, or conditionally move data from source to target.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0ce3e397716c28c30ed05e153babd0bfb9dd354a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
|
||||
@@ -0,0 +1,87 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.ExperienceOrb;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired anytime the server is about to merge 2 experience orbs into one
|
||||
+ */
|
||||
+public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable {
|
||||
+ @NotNull private final ExperienceOrb mergeTarget;
|
||||
+ @NotNull private final ExperienceOrb mergeSource;
|
||||
+
|
||||
+ public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) {
|
||||
+ super(mergeTarget);
|
||||
+ this.mergeTarget = mergeTarget;
|
||||
+ this.mergeSource = mergeSource;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The orb that will absorb the other experience orb
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ExperienceOrb getMergeTarget() {
|
||||
+ return mergeTarget;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The orb that is subject to being removed and merged into the target orb
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ExperienceOrb getMergeSource() {
|
||||
+ return mergeSource;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param cancel true if you wish to cancel this event, and prevent the orbs from merging
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,53 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 20 Dec 2017 17:38:07 -0500
|
||||
Subject: [PATCH] Ability to apply mending to XP API
|
||||
|
||||
This allows plugins that give players the ability to apply the experience
|
||||
points to the Item Mending formula, which will repair an item instead
|
||||
of giving the player experience points.
|
||||
|
||||
Both an API To standalone mend, and apply mending logic to .giveExp has been added.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 0da374b18e0f602e9836cfaefe07c5219a7d9bd1..e6b4347fc7e14971b8c975f19ff389fdafa16723 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1429,6 +1429,15 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
public void resetPlayerWeather();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gives the player the amount of experience specified.
|
||||
+ *
|
||||
+ * @param amount Exp amount to give
|
||||
+ */
|
||||
+ public default void giveExp(int amount) {
|
||||
+ giveExp(amount, false);
|
||||
+ }
|
||||
/**
|
||||
* Gets the player's cooldown between picking up experience orbs.
|
||||
*
|
||||
@@ -1454,8 +1463,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* Gives the player the amount of experience specified.
|
||||
*
|
||||
* @param amount Exp amount to give
|
||||
+ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)}
|
||||
*/
|
||||
- public void giveExp(int amount);
|
||||
+ public void giveExp(int amount, boolean applyMending);
|
||||
+
|
||||
+ /**
|
||||
+ * Applies the mending effect to any items just as picking up an orb would.
|
||||
+ *
|
||||
+ * Can also be called with {@link #giveExp(int, boolean)} by passing true to applyMending
|
||||
+ *
|
||||
+ * @param amount Exp to apply
|
||||
+ * @return the remaining experience
|
||||
+ */
|
||||
+ public int applyMending(int amount);
|
||||
+ // Paper end
|
||||
|
||||
/**
|
||||
* Gives the player the amount of experience levels specified. Levels can
|
127
patches/unapplied/api/0082-PreCreatureSpawnEvent.patch
Normal file
127
patches/unapplied/api/0082-PreCreatureSpawnEvent.patch
Normal file
|
@ -0,0 +1,127 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 14 Jan 2018 16:59:43 -0500
|
||||
Subject: [PATCH] PreCreatureSpawnEvent
|
||||
|
||||
Adds an event to fire before an Entity is created, so that plugins that need to cancel
|
||||
CreatureSpawnEvent can do so from this event instead.
|
||||
|
||||
Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste
|
||||
as it's done after the Entity object has been fully created.
|
||||
|
||||
Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event
|
||||
instead and save a lot of server resources.
|
||||
|
||||
See: https://github.com/PaperMC/Paper/issues/917
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8b48759bf6f4fcef0847d9a2461993e3f2fdc9aa
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java
|
||||
@@ -0,0 +1,105 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.EntityType;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does.
|
||||
+ *
|
||||
+ * You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement".
|
||||
+ * The intent of this event is to improve server performance, so it fires even if the spawning might fail later, for
|
||||
+ * example when the entity would be unable to spawn due to limited space or lighting.
|
||||
+ *
|
||||
+ * Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions.
|
||||
+ * Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event.
|
||||
+ */
|
||||
+public class PreCreatureSpawnEvent extends Event implements Cancellable {
|
||||
+ @NotNull private final Location location;
|
||||
+ @NotNull private final EntityType type;
|
||||
+ @NotNull private final CreatureSpawnEvent.SpawnReason reason;
|
||||
+ private boolean shouldAbortSpawn;
|
||||
+
|
||||
+ public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ this.location = Preconditions.checkNotNull(location, "Location may not be null");
|
||||
+ this.type = Preconditions.checkNotNull(type, "Type may not be null");
|
||||
+ this.reason = Preconditions.checkNotNull(reason, "Reason may not be null");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The location this creature is being spawned at
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getSpawnLocation() {
|
||||
+ return location;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The type of creature being spawned
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public EntityType getType() {
|
||||
+ return type;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Reason this creature is spawning (ie, NATURAL vs SPAWNER)
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public CreatureSpawnEvent.SpawnReason getReason() {
|
||||
+ return reason;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return If the spawn process should be aborted vs trying more attempts
|
||||
+ */
|
||||
+ public boolean shouldAbortSpawn() {
|
||||
+ return shouldAbortSpawn;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from
|
||||
+ * trying more attempts after this cancellation.
|
||||
+ *
|
||||
+ * @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts
|
||||
+ */
|
||||
+ public void setShouldAbortSpawn(boolean shouldAbortSpawn) {
|
||||
+ this.shouldAbortSpawn = shouldAbortSpawn;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ /**
|
||||
+ * @return If the spawn of this creature is cancelled or not
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Cancelling this event is more efficient than cancelling CreatureSpawnEvent
|
||||
+ * @param cancel true if you wish to cancel this event, and abort the spawn of this creature
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,80 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 14 Jan 2018 17:31:37 -0500
|
||||
Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent
|
||||
|
||||
This event can be used for when you want to exclude a certain player
|
||||
from triggering monster spawns on a server.
|
||||
|
||||
Also a highly more effecient way to blanket block spawns in a world
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..112a0dbf522b8e74ce882678434923814e6b187f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event
|
||||
+ */
|
||||
+public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable {
|
||||
+ private byte radius;
|
||||
+
|
||||
+ public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) {
|
||||
+ super(player);
|
||||
+ this.radius = radius;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The radius of chunks around this player to be included in natural spawn selection
|
||||
+ */
|
||||
+ public byte getSpawnRadius() {
|
||||
+ return radius;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param radius The radius of chunks around this player to be included in natural spawn selection
|
||||
+ */
|
||||
+ public void setSpawnRadius(byte radius) {
|
||||
+ this.radius = radius;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ /**
|
||||
+ * @return If this players chunks will be excluded from natural spawns
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,90 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 19 Jan 2018 00:29:28 -0500
|
||||
Subject: [PATCH] Add setPlayerProfile API for Skulls
|
||||
|
||||
This allows you to create already filled textures on Skulls to avoid texture lookups
|
||||
which commonly cause rate limit issues with Mojang API
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/block/Skull.java b/src/main/java/org/bukkit/block/Skull.java
|
||||
index b39128bb0ca2d4fe7a254193236c60fb5bfaa7da..5135b8e6028e6926e2711e2dd6ce68b76f468fd7 100644
|
||||
--- a/src/main/java/org/bukkit/block/Skull.java
|
||||
+++ b/src/main/java/org/bukkit/block/Skull.java
|
||||
@@ -63,6 +63,20 @@ public interface Skull extends TileState {
|
||||
*/
|
||||
public void setOwningPlayer(@NotNull OfflinePlayer player);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled.
|
||||
+ * @param profile The profile to set this Skull to use, may not be null
|
||||
+ */
|
||||
+ void setPlayerProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile);
|
||||
+
|
||||
+ /**
|
||||
+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link com.destroystokyo.paper.profile.PlayerProfile}
|
||||
+ * @return The profile of the owner, if set
|
||||
+ */
|
||||
+ @Nullable com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the profile of the player who owns the skull. This player profile
|
||||
* may appear as the texture depending on skull type.
|
||||
@@ -70,6 +84,7 @@ public interface Skull extends TileState {
|
||||
* @return the profile of the owning player
|
||||
*/
|
||||
@Nullable
|
||||
+ @Deprecated // Paper
|
||||
PlayerProfile getOwnerProfile();
|
||||
|
||||
/**
|
||||
@@ -84,6 +99,7 @@ public interface Skull extends TileState {
|
||||
* @throws IllegalArgumentException if the profile does not contain the
|
||||
* necessary information
|
||||
*/
|
||||
+ @Deprecated // Paper
|
||||
void setOwnerProfile(@Nullable PlayerProfile profile);
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
index 5a18a66a0b7877ec0c1859f78cce659db4b8541a..862640b4611458dfbcd3be797eacd120fc8d1f9f 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
@@ -38,6 +38,20 @@ public interface SkullMeta extends ItemMeta {
|
||||
@Deprecated
|
||||
boolean setOwner(@Nullable String owner);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled.
|
||||
+ * @param profile The profile to set this Skull to use, or null to clear owner
|
||||
+ */
|
||||
+ void setPlayerProfile(@Nullable com.destroystokyo.paper.profile.PlayerProfile profile);
|
||||
+
|
||||
+ /**
|
||||
+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link com.destroystokyo.paper.profile.PlayerProfile}
|
||||
+ * @return The profile of the owner, if set
|
||||
+ */
|
||||
+ @Nullable com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the owner of the skull.
|
||||
*
|
||||
@@ -64,6 +78,7 @@ public interface SkullMeta extends ItemMeta {
|
||||
* @return the profile of the owning player
|
||||
*/
|
||||
@Nullable
|
||||
+ @Deprecated // Paper
|
||||
PlayerProfile getOwnerProfile();
|
||||
|
||||
/**
|
||||
@@ -78,6 +93,7 @@ public interface SkullMeta extends ItemMeta {
|
||||
* @throws IllegalArgumentException if the profile does not contain the
|
||||
* necessary information
|
||||
*/
|
||||
+ @Deprecated // Paper
|
||||
void setOwnerProfile(@Nullable PlayerProfile profile);
|
||||
|
||||
/**
|
|
@ -0,0 +1,91 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 19 Jan 2018 08:15:14 -0600
|
||||
Subject: [PATCH] Add PlayerAdvancementCriterionGrantEvent
|
||||
|
||||
Co-authored-by: The456gamer <the456gamer@the456gamer.dev>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..99dac77befbf7c0c067f50150e62fe6d6ddaec7c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java
|
||||
@@ -0,0 +1,78 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.advancement.Advancement;
|
||||
+import org.bukkit.advancement.AdvancementProgress;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called after a player is granted a criteria in an advancement.
|
||||
+ * If cancelled the criteria will be revoked.
|
||||
+ */
|
||||
+public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private final Advancement advancement;
|
||||
+ @NotNull private final String criterion;
|
||||
+ @NotNull private final AdvancementProgress advancementProgress;
|
||||
+ private boolean cancel = false;
|
||||
+
|
||||
+ public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) {
|
||||
+ super(who);
|
||||
+ this.advancement = advancement;
|
||||
+ this.criterion = criterion;
|
||||
+ this.advancementProgress = who.getAdvancementProgress(advancement);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the advancement which has been affected.
|
||||
+ *
|
||||
+ * @return affected advancement
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Advancement getAdvancement() {
|
||||
+ return advancement;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the criterion which has been granted.
|
||||
+ *
|
||||
+ * @return granted criterion
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getCriterion() {
|
||||
+ return criterion;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the current AdvancementProgress.
|
||||
+ * See {@link PlayerAdvancementCriterionGrantEvent}
|
||||
+ *
|
||||
+ * @return advancement progress
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public AdvancementProgress getAdvancementProgress() {
|
||||
+ return advancementProgress;
|
||||
+ }
|
||||
+
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancel = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
176
patches/unapplied/api/0086-Fill-Profile-Property-Events.patch
Normal file
176
patches/unapplied/api/0086-Fill-Profile-Property-Events.patch
Normal file
|
@ -0,0 +1,176 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 2 Jan 2018 00:31:08 -0500
|
||||
Subject: [PATCH] Fill Profile Property Events
|
||||
|
||||
Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API
|
||||
to fill in textures for example.
|
||||
|
||||
If Mojang API does need to be hit, event fire so you can get the results.
|
||||
|
||||
This is useful for implementing a ProfileCache for Player Skulls
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..71f36e9cae209ec6861835a5e76e018de959040a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java
|
||||
@@ -0,0 +1,75 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+
|
||||
+import java.util.Set;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired once a profiles additional properties (such as textures) has been filled
|
||||
+ */
|
||||
+public class FillProfileEvent extends Event {
|
||||
+ @NotNull private final PlayerProfile profile;
|
||||
+
|
||||
+ public FillProfileEvent(@NotNull PlayerProfile profile) {
|
||||
+ super(!org.bukkit.Bukkit.isPrimaryThread());
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The Profile that had properties filled
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Same as .getPlayerProfile().getProperties()
|
||||
+ *
|
||||
+ * @see PlayerProfile#getProperties()
|
||||
+ * @return The new properties on the profile.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Set<ProfileProperty> getProperties() {
|
||||
+ return profile.getProperties();
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..021bc86310a06f84b39459e0eb8927802726399c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java
|
||||
@@ -0,0 +1,77 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when the server is requesting to fill in properties of an incomplete profile, such as textures.
|
||||
+ *
|
||||
+ * Allows plugins to pre populate cached properties and avoid a call to the Mojang API
|
||||
+ */
|
||||
+public class PreFillProfileEvent extends Event {
|
||||
+ @NotNull private final PlayerProfile profile;
|
||||
+
|
||||
+ public PreFillProfileEvent(@NotNull PlayerProfile profile) {
|
||||
+ super(!org.bukkit.Bukkit.isPrimaryThread());
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The profile that needs its properties filled
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the properties on the profile, avoiding the call to the Mojang API
|
||||
+ * Same as .getPlayerProfile().setProperties(properties);
|
||||
+ *
|
||||
+ * @see PlayerProfile#setProperties(Collection)
|
||||
+ * @param properties The properties to set/append
|
||||
+ */
|
||||
+ public void setProperties(@NotNull Collection<ProfileProperty> properties) {
|
||||
+ profile.setProperties(properties);
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
96
patches/unapplied/api/0087-Add-ArmorStand-Item-Meta.patch
Normal file
96
patches/unapplied/api/0087-Add-ArmorStand-Item-Meta.patch
Normal file
|
@ -0,0 +1,96 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 27 Jan 2018 17:06:24 -0500
|
||||
Subject: [PATCH] Add ArmorStand Item Meta
|
||||
|
||||
This is adds basic item meta for armor stands. It does not add all
|
||||
possible metadata however.
|
||||
|
||||
There are armor, hand, and equipment types, as well as position data
|
||||
that can also be added here. This initial addition should serve a
|
||||
starting point for future additions in this area.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7e4acfff16db80a75e1ff2fee1972b16955b0918
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java
|
||||
@@ -0,0 +1,78 @@
|
||||
+package com.destroystokyo.paper.inventory.meta;
|
||||
+
|
||||
+import org.bukkit.inventory.meta.ItemMeta;
|
||||
+
|
||||
+public interface ArmorStandMeta extends ItemMeta {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether the ArmorStand should be invisible when spawned
|
||||
+ *
|
||||
+ * @return true if this should be invisible
|
||||
+ */
|
||||
+ boolean isInvisible();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether this ArmorStand should have no base plate when spawned
|
||||
+ *
|
||||
+ * @return true if it will not have a base plate
|
||||
+ */
|
||||
+ boolean hasNoBasePlate();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether this ArmorStand should show arms when spawned
|
||||
+ *
|
||||
+ * @return true if it will show arms
|
||||
+ */
|
||||
+ boolean shouldShowArms();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether this ArmorStand will be small when spawned
|
||||
+ *
|
||||
+ * @return true if it will be small
|
||||
+ */
|
||||
+ boolean isSmall();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether this ArmorStand will be a marker when spawned
|
||||
+ * The exact details of this flag are an implementation detail
|
||||
+ *
|
||||
+ * @return true if it will be a marker
|
||||
+ */
|
||||
+ boolean isMarker();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets that this ArmorStand should be invisible when spawned
|
||||
+ *
|
||||
+ * @param invisible true if set invisible
|
||||
+ */
|
||||
+ void setInvisible(boolean invisible);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets that this ArmorStand should have no base plate when spawned
|
||||
+ *
|
||||
+ * @param noBasePlate true if no base plate
|
||||
+ */
|
||||
+ void setNoBasePlate(boolean noBasePlate);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets that this ArmorStand should show arms when spawned
|
||||
+ *
|
||||
+ * @param showArms true if show arms
|
||||
+ */
|
||||
+ void setShowArms(boolean showArms);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets that this ArmorStand should be small when spawned
|
||||
+ *
|
||||
+ * @param small true if small
|
||||
+ */
|
||||
+ void setSmall(boolean small);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets that this ArmorStand should be a marker when spawned
|
||||
+ * The exact details of this flag are an implementation detail
|
||||
+ *
|
||||
+ * @param marker true if a marker
|
||||
+ */
|
||||
+ void setMarker(boolean marker);
|
||||
+}
|
19
patches/unapplied/api/0088-Optimize-Hoppers.patch
Normal file
19
patches/unapplied/api/0088-Optimize-Hoppers.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 18 Jan 2018 01:00:27 -0500
|
||||
Subject: [PATCH] Optimize Hoppers
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
index 919cc993e3cb1c14e2a3aebf90e6cc0fa6fbc17f..0161b8a94c7e8774fec3ed9c36d9c37221525928 100644
|
||||
--- a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
@@ -58,7 +58,7 @@ public class InventoryMoveItemEvent extends Event implements Cancellable {
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStack getItem() {
|
||||
- return itemStack.clone();
|
||||
+ return itemStack; // Paper - Removed clone, handled better in Server
|
||||
}
|
||||
|
||||
/**
|
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 24 Feb 2018 00:55:52 -0500
|
||||
Subject: [PATCH] Tameable#getOwnerUniqueId API
|
||||
|
||||
This is faster if all you need is the UUID, as .getOwner() will cause
|
||||
an OfflinePlayer to be loaded from disk.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Tameable.java b/src/main/java/org/bukkit/entity/Tameable.java
|
||||
index 26c996cd41acc88490ac0135a9239cffc03e8efb..65e68da98ab66ed781bce2f0dbe0913be48d2990 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Tameable.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Tameable.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Tameable extends Animals {
|
||||
@@ -25,9 +26,22 @@ public interface Tameable extends Animals {
|
||||
*/
|
||||
public void setTamed(boolean tame);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the owners UUID
|
||||
+ *
|
||||
+ * @return the owners UUID, or null if not owned
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public java.util.UUID getOwnerUniqueId();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the current owning AnimalTamer
|
||||
*
|
||||
+ * @see #getOwnerUniqueId() Recommended to use UUID version instead of this for performance.
|
||||
+ * This method will cause OfflinePlayer to be loaded from disk if the owner is not online.
|
||||
+ *
|
||||
* @return the owning AnimalTamer, or null if not owned
|
||||
*/
|
||||
@Nullable
|
|
@ -0,0 +1,91 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 18 Mar 2018 11:43:30 -0400
|
||||
Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent
|
||||
|
||||
This will allow you to change the players name or skin on login.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java
|
||||
index c7c45e2de8cca1bf8b8e12752e08db62403efa6a..c30b44ff26f8f253902754452a0816f07c7fd035 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java
|
||||
@@ -2,6 +2,9 @@ package org.bukkit.event.player;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -15,9 +18,9 @@ public class AsyncPlayerPreLoginEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Result result;
|
||||
private net.kyori.adventure.text.Component message; // Paper
|
||||
- private final String name;
|
||||
+ //private String name; // Paper - Not used anymore
|
||||
private final InetAddress ipAddress;
|
||||
- private final UUID uniqueId;
|
||||
+ //private UUID uniqueId; // Paper - Not used anymore
|
||||
|
||||
@Deprecated
|
||||
public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress) {
|
||||
@@ -25,12 +28,37 @@ public class AsyncPlayerPreLoginEvent extends Event {
|
||||
}
|
||||
|
||||
public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) {
|
||||
+ // Paper start
|
||||
+ this(name, ipAddress, uniqueId, Bukkit.createProfile(uniqueId, name));
|
||||
+ }
|
||||
+ private PlayerProfile profile;
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the PlayerProfile of the player logging in
|
||||
+ * @return The Profile
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Changes the PlayerProfile the player will login as
|
||||
+ * @param profile The profile to use
|
||||
+ */
|
||||
+ public void setPlayerProfile(@NotNull PlayerProfile profile) {
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) {
|
||||
super(true);
|
||||
+ this.profile = profile;
|
||||
+ // Paper end
|
||||
this.result = Result.ALLOWED;
|
||||
this.message = net.kyori.adventure.text.Component.empty(); // Paper
|
||||
- this.name = name;
|
||||
+ //this.name = name; // Paper - Not used anymore
|
||||
this.ipAddress = ipAddress;
|
||||
- this.uniqueId = uniqueId;
|
||||
+ //this.uniqueId = uniqueId; // Paper - Not used anymore
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +221,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
|
||||
*/
|
||||
@NotNull
|
||||
public String getName() {
|
||||
- return name;
|
||||
+ return profile.getName(); // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +241,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
|
||||
*/
|
||||
@NotNull
|
||||
public UUID getUniqueId() {
|
||||
- return uniqueId;
|
||||
+ return profile.getId(); // Paper
|
||||
}
|
||||
|
||||
@NotNull
|
|
@ -0,0 +1,381 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Wed, 11 Oct 2017 15:55:38 +0200
|
||||
Subject: [PATCH] Add extended PaperServerListPingEvent
|
||||
|
||||
Add a new event that extends the original ServerListPingEvent
|
||||
and allows full control of the response sent to the client.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e886ac04c0c14ae5dfb87212e262b96ec5b3b9dc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java
|
||||
@@ -0,0 +1,334 @@
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import static java.util.Objects.requireNonNull;
|
||||
+
|
||||
+import com.destroystokyo.paper.network.StatusClient;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.server.ServerListPingEvent;
|
||||
+import org.bukkit.util.CachedServerIcon;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.List;
|
||||
+import java.util.NoSuchElementException;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Extended version of {@link ServerListPingEvent} that allows full control
|
||||
+ * of the response sent to the client.
|
||||
+ */
|
||||
+public class PaperServerListPingEvent extends ServerListPingEvent implements Cancellable {
|
||||
+
|
||||
+ @NotNull private final StatusClient client;
|
||||
+
|
||||
+ private int numPlayers;
|
||||
+ private boolean hidePlayers;
|
||||
+ @NotNull private final List<PlayerProfile> playerSample = new ArrayList<>();
|
||||
+
|
||||
+ @NotNull private String version;
|
||||
+ private int protocolVersion;
|
||||
+
|
||||
+ @Nullable private CachedServerIcon favicon;
|
||||
+
|
||||
+ private boolean cancelled;
|
||||
+
|
||||
+ private boolean originalPlayerCount = true;
|
||||
+ private Object[] players;
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers,
|
||||
+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) {
|
||||
+ super("", client.getAddress().getAddress(), motd, numPlayers, maxPlayers);
|
||||
+ this.client = client;
|
||||
+ this.numPlayers = numPlayers;
|
||||
+ this.version = version;
|
||||
+ this.protocolVersion = protocolVersion;
|
||||
+ setServerIcon(favicon);
|
||||
+ }
|
||||
+
|
||||
+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull net.kyori.adventure.text.Component motd, int numPlayers, int maxPlayers,
|
||||
+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) {
|
||||
+ super("", client.getAddress().getAddress(), motd, numPlayers, maxPlayers);
|
||||
+ this.client = client;
|
||||
+ this.numPlayers = numPlayers;
|
||||
+ this.version = version;
|
||||
+ this.protocolVersion = protocolVersion;
|
||||
+ setServerIcon(favicon);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the {@link StatusClient} pinging the server.
|
||||
+ *
|
||||
+ * @return The client
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public StatusClient getClient() {
|
||||
+ return this.client;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@inheritDoc}
|
||||
+ *
|
||||
+ * <p>Returns {@code -1} if players are hidden using
|
||||
+ * {@link #shouldHidePlayers()}.</p>
|
||||
+ */
|
||||
+ @Override
|
||||
+ public int getNumPlayers() {
|
||||
+ if (this.hidePlayers) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return this.numPlayers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of players displayed in the server list.
|
||||
+ *
|
||||
+ * <p>Note that this won't have any effect if {@link #shouldHidePlayers()}
|
||||
+ * is enabled.</p>
|
||||
+ *
|
||||
+ * @param numPlayers The number of online players
|
||||
+ */
|
||||
+ public void setNumPlayers(int numPlayers) {
|
||||
+ if (this.numPlayers != numPlayers) {
|
||||
+ this.numPlayers = numPlayers;
|
||||
+ this.originalPlayerCount = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@inheritDoc}
|
||||
+ *
|
||||
+ * <p>Returns {@code -1} if players are hidden using
|
||||
+ * {@link #shouldHidePlayers()}.</p>
|
||||
+ */
|
||||
+ @Override
|
||||
+ public int getMaxPlayers() {
|
||||
+ if (this.hidePlayers) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return super.getMaxPlayers();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether all player related information is hidden in the server
|
||||
+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()}
|
||||
+ * and {@link #getPlayerSample()} to be skipped in the response.
|
||||
+ *
|
||||
+ * <p>The Vanilla Minecraft client will display the player count as {@code ???}
|
||||
+ * when this option is enabled.</p>
|
||||
+ *
|
||||
+ * @return {@code true} if the player count is hidden
|
||||
+ */
|
||||
+ public boolean shouldHidePlayers() {
|
||||
+ return hidePlayers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether all player related information is hidden in the server
|
||||
+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()}
|
||||
+ * and {@link #getPlayerSample()} to be skipped in the response.
|
||||
+ *
|
||||
+ * <p>The Vanilla Minecraft client will display the player count as {@code ???}
|
||||
+ * when this option is enabled.</p>
|
||||
+ *
|
||||
+ * @param hidePlayers {@code true} if the player count should be hidden
|
||||
+ */
|
||||
+ public void setHidePlayers(boolean hidePlayers) {
|
||||
+ this.hidePlayers = hidePlayers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a mutable list of {@link PlayerProfile} that will be displayed
|
||||
+ * as online players on the client.
|
||||
+ *
|
||||
+ * <p>The Vanilla Minecraft client will display them when hovering the
|
||||
+ * player count with the mouse.</p>
|
||||
+ *
|
||||
+ * @return The mutable player sample list
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public List<PlayerProfile> getPlayerSample() {
|
||||
+ return this.playerSample;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the version that will be sent as server version on the client.
|
||||
+ *
|
||||
+ * @return The server version
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getVersion() {
|
||||
+ return version;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the version that will be sent as server version to the client.
|
||||
+ *
|
||||
+ * @param version The server version
|
||||
+ */
|
||||
+ public void setVersion(@NotNull String version) {
|
||||
+ this.version = requireNonNull(version, "version");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the protocol version that will be sent as the protocol version
|
||||
+ * of the server to the client.
|
||||
+ *
|
||||
+ * @return The protocol version of the server, or {@code -1} if the server
|
||||
+ * has not finished initialization yet
|
||||
+ */
|
||||
+ public int getProtocolVersion() {
|
||||
+ return protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the protocol version that will be sent as the protocol version
|
||||
+ * of the server to the client.
|
||||
+ *
|
||||
+ * @param protocolVersion The protocol version of the server
|
||||
+ */
|
||||
+ public void setProtocolVersion(int protocolVersion) {
|
||||
+ this.protocolVersion = protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the server icon sent to the client.
|
||||
+ *
|
||||
+ * @return The icon to send to the client, or {@code null} for none
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public CachedServerIcon getServerIcon() {
|
||||
+ return this.favicon;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the server icon sent to the client.
|
||||
+ *
|
||||
+ * @param icon The icon to send to the client, or {@code null} for none
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setServerIcon(@Nullable CachedServerIcon icon) {
|
||||
+ if (icon != null && icon.isEmpty()) {
|
||||
+ // Represent empty icons as null
|
||||
+ icon = null;
|
||||
+ }
|
||||
+
|
||||
+ this.favicon = icon;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@inheritDoc}
|
||||
+ *
|
||||
+ * <p>Cancelling this event will cause the connection to be closed immediately,
|
||||
+ * without sending a response to the client.</p>
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return this.cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@inheritDoc}
|
||||
+ *
|
||||
+ * <p>Cancelling this event will cause the connection to be closed immediately,
|
||||
+ * without sending a response to the client.</p>
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@inheritDoc}
|
||||
+ *
|
||||
+ * <p><b>Note:</b> For compatibility reasons, this method will return all
|
||||
+ * online players, not just the ones referenced in {@link #getPlayerSample()}.
|
||||
+ * Removing a player will:</p>
|
||||
+ *
|
||||
+ * <ul>
|
||||
+ * <li>Decrement the online player count (if and only if) the player
|
||||
+ * count wasn't changed by another plugin before.</li>
|
||||
+ * <li>Remove all entries from {@link #getPlayerSample()} that refer to
|
||||
+ * the removed player (based on their {@link UUID}).</li>
|
||||
+ * </ul>
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Iterator<Player> iterator() {
|
||||
+ if (this.players == null) {
|
||||
+ this.players = getOnlinePlayers();
|
||||
+ }
|
||||
+
|
||||
+ return new PlayerIterator();
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ protected Object[] getOnlinePlayers() {
|
||||
+ return Bukkit.getOnlinePlayers().toArray();
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ protected Player getBukkitPlayer(@NotNull Object player) {
|
||||
+ return (Player) player;
|
||||
+ }
|
||||
+
|
||||
+ private final class PlayerIterator implements Iterator<Player> {
|
||||
+
|
||||
+ private int next;
|
||||
+ private int current;
|
||||
+ @Nullable private Player player;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ for (; this.next < players.length; this.next++) {
|
||||
+ if (players[this.next] != null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Player next() {
|
||||
+ if (!hasNext()) {
|
||||
+ this.player = null;
|
||||
+ throw new NoSuchElementException();
|
||||
+ }
|
||||
+
|
||||
+ this.current = this.next++;
|
||||
+ return this.player = getBukkitPlayer(players[this.current]);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ if (this.player == null) {
|
||||
+ throw new IllegalStateException();
|
||||
+ }
|
||||
+
|
||||
+ UUID uniqueId = this.player.getUniqueId();
|
||||
+ this.player = null;
|
||||
+
|
||||
+ // Remove player from iterator
|
||||
+ players[this.current] = null;
|
||||
+
|
||||
+ // Remove player from sample
|
||||
+ getPlayerSample().removeIf(p -> uniqueId.equals(p.getId()));
|
||||
+
|
||||
+ // Decrement player count
|
||||
+ if (originalPlayerCount) {
|
||||
+ numPlayers--;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..517d15238ed117f38bbd39f570874014cecf7bb5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
@@ -0,0 +1,13 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a client requesting the current status from the server (e.g. from
|
||||
+ * the server list).
|
||||
+ *
|
||||
+ * @see PaperServerListPingEvent
|
||||
+ */
|
||||
+public interface StatusClient extends NetworkClient {
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java
|
||||
index 9a7768d41270714d4a1c89b4dcb436cc66f57545..b74b21a1ac7798e847b6d34ff45026e1c9cfed14 100644
|
||||
--- a/src/main/java/org/bukkit/util/CachedServerIcon.java
|
||||
+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java
|
||||
@@ -18,4 +18,9 @@ public interface CachedServerIcon {
|
||||
@Nullable
|
||||
public String getData(); // Paper
|
||||
|
||||
+ // Paper start
|
||||
+ default boolean isEmpty() {
|
||||
+ return getData() == null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
145
patches/unapplied/api/0092-Player.setPlayerProfile-API.patch
Normal file
145
patches/unapplied/api/0092-Player.setPlayerProfile-API.patch
Normal file
|
@ -0,0 +1,145 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 18 Mar 2018 12:28:55 -0400
|
||||
Subject: [PATCH] Player.setPlayerProfile API
|
||||
|
||||
This can be useful for changing name or skins after a player has logged in.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 8f1f432c9d6c68ac142401626adaf1dc212181f2..8c430623204d419a93ccc67a0214942952f4a33c 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -1306,8 +1306,10 @@ public final class Bukkit {
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if both the unique id is
|
||||
* <code>null</code> and the name is <code>null</code> or blank
|
||||
+ * @deprecated use {@link #createProfile(UUID, String)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated // Paper
|
||||
public static PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name) {
|
||||
return server.createPlayerProfile(uniqueId, name);
|
||||
}
|
||||
@@ -1318,8 +1320,10 @@ public final class Bukkit {
|
||||
* @param uniqueId the unique id
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if the unique id is <code>null</code>
|
||||
+ * @deprecated use {@link #createProfile(UUID)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated // Paper
|
||||
public static PlayerProfile createPlayerProfile(@NotNull UUID uniqueId) {
|
||||
return server.createPlayerProfile(uniqueId);
|
||||
}
|
||||
@@ -1331,8 +1335,10 @@ public final class Bukkit {
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if the name is <code>null</code> or
|
||||
* blank
|
||||
+ * @deprecated use {@link #createProfile(String)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated // Paper
|
||||
public static PlayerProfile createPlayerProfile(@NotNull String name) {
|
||||
return server.createPlayerProfile(name);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
index bec480aff819e09220b52175cab0cb6d68ae68c6..12349910297a75c00e64f6ccc7981aeeeb43ecd3 100644
|
||||
--- a/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
@@ -59,7 +59,7 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
|
||||
* @return the player's profile
|
||||
*/
|
||||
@NotNull
|
||||
- PlayerProfile getPlayerProfile();
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile(); // Paper
|
||||
|
||||
/**
|
||||
* Checks if this player has had their profile banned.
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index aad8b2fbdbb03fbf32f99b3a533716eca9d42219..405b6a388c3593a83985f766e79b92951006563e 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1119,8 +1119,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if both the unique id is
|
||||
* <code>null</code> and the name is <code>null</code> or blank
|
||||
+ * @deprecated use {@link #createProfile(UUID, String)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated // Paper
|
||||
PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name);
|
||||
|
||||
/**
|
||||
@@ -1129,8 +1131,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @param uniqueId the unique id
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if the unique id is <code>null</code>
|
||||
+ * @deprecated use {@link #createProfile(UUID)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated // Paper
|
||||
PlayerProfile createPlayerProfile(@NotNull UUID uniqueId);
|
||||
|
||||
/**
|
||||
@@ -1140,8 +1144,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @return the new PlayerProfile
|
||||
* @throws IllegalArgumentException if the name is <code>null</code> or
|
||||
* blank
|
||||
+ * @deprecated use {@link #createProfile(String)}
|
||||
*/
|
||||
@NotNull
|
||||
+ @Deprecated
|
||||
PlayerProfile createPlayerProfile(@NotNull String name);
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index e6b4347fc7e14971b8c975f19ff389fdafa16723..43ba9fbec2060786fe1cb24025adc697a88b8678 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2739,6 +2739,24 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED}
|
||||
*/
|
||||
boolean hasResourcePack();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets a copy of this players profile
|
||||
+ * @return The players profile object
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile();
|
||||
+
|
||||
+ /**
|
||||
+ * Changes the PlayerProfile for this player. This will cause this player
|
||||
+ * to be reregistered to all clients that can currently see this player.
|
||||
+ *
|
||||
+ * After executing this method, the player {@link java.util.UUID} won't
|
||||
+ * be swapped, only their name and gameprofile properties.
|
||||
+ *
|
||||
+ * @param profile The new profile to use
|
||||
+ */
|
||||
+ void setPlayerProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile);
|
||||
// Paper end
|
||||
|
||||
// Spigot start
|
||||
diff --git a/src/main/java/org/bukkit/profile/PlayerProfile.java b/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
index fc46add38bf59dc1a04ea566fd230dcd8ae2708c..d36b3e3c7e53840132011add365ca2a26d799064 100644
|
||||
--- a/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
+++ b/src/main/java/org/bukkit/profile/PlayerProfile.java
|
||||
@@ -16,7 +16,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
* <p>
|
||||
* New profiles can be created via
|
||||
* {@link Server#createPlayerProfile(UUID, String)}.
|
||||
+ * @deprecated see {@link com.destroystokyo.paper.profile.PlayerProfile}
|
||||
*/
|
||||
+@Deprecated // Paper
|
||||
public interface PlayerProfile extends Cloneable, ConfigurationSerializable {
|
||||
|
||||
/**
|
||||
@@ -25,6 +27,7 @@ public interface PlayerProfile extends Cloneable, ConfigurationSerializable {
|
||||
* @return the player's unique id, or <code>null</code> if not available
|
||||
*/
|
||||
@Nullable
|
||||
+ @Deprecated // Paper
|
||||
UUID getUniqueId();
|
||||
|
||||
/**
|
58
patches/unapplied/api/0093-getPlayerUniqueId-API.patch
Normal file
58
patches/unapplied/api/0093-getPlayerUniqueId-API.patch
Normal file
|
@ -0,0 +1,58 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 22 Mar 2018 01:39:28 -0400
|
||||
Subject: [PATCH] getPlayerUniqueId API
|
||||
|
||||
Gets the unique ID of the player currently known as the specified player name
|
||||
In Offline Mode, will return an Offline UUID
|
||||
|
||||
This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 8c430623204d419a93ccc67a0214942952f4a33c..9f52c092d906622e2eade3bc9d8baac6816f9f3a 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -689,6 +689,20 @@ public final class Bukkit {
|
||||
return server.getPlayer(id);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the unique ID of the player currently known as the specified player name
|
||||
+ * In Offline Mode, will return an Offline UUID
|
||||
+ *
|
||||
+ * @param playerName the player name to look up the unique ID for
|
||||
+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public static UUID getPlayerUniqueId(@NotNull String playerName) {
|
||||
+ return server.getPlayerUniqueId(playerName);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the plugin manager for interfacing with plugins.
|
||||
*
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 405b6a388c3593a83985f766e79b92951006563e..aace34252f65dd54868b521288f68c641b7ed71e 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -593,6 +593,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@Nullable
|
||||
public Player getPlayer(@NotNull UUID id);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the unique ID of the player currently known as the specified player name
|
||||
+ * In Offline Mode, will return an Offline UUID
|
||||
+ *
|
||||
+ * @param playerName the player name to look up the unique ID for
|
||||
+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public UUID getPlayerUniqueId(@NotNull String playerName);
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the plugin manager for interfacing with plugins.
|
||||
*
|
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Wed, 11 Oct 2017 19:30:20 +0200
|
||||
Subject: [PATCH] Add legacy ping support to PaperServerListPingEvent
|
||||
|
||||
Add a new method to StatusClient check if the client is a legacy
|
||||
client that does not support all of the features provided in the
|
||||
event.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9dcca2802 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
@@ -10,4 +10,16 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
*/
|
||||
public interface StatusClient extends NetworkClient {
|
||||
|
||||
+ /**
|
||||
+ * Returns whether the client is using an older version that doesn't
|
||||
+ * support all of the features in {@link PaperServerListPingEvent}.
|
||||
+ *
|
||||
+ * <p>For Vanilla, this returns {@code true} for all clients older than 1.7.</p>
|
||||
+ *
|
||||
+ * @return {@code true} if the client is using legacy ping
|
||||
+ */
|
||||
+ default boolean isLegacy() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Sun, 1 Apr 2018 02:28:43 +0300
|
||||
Subject: [PATCH] Add openSign method to HumanEntity
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
index abdca9fe5acc90f167219eb769ece66c35682bb1..b3aa3dc6aa5afbc36cc86741b4cba56f463c2234 100644
|
||||
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
@@ -500,6 +500,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
|
||||
*/
|
||||
@Deprecated
|
||||
public void setShoulderEntityRight(@Nullable Entity entity);
|
||||
+ // Paper start - Add method to open already placed sign
|
||||
+ /**
|
||||
+ * Opens an editor window for the specified sign
|
||||
+ *
|
||||
+ * @param sign The sign to open
|
||||
+ * @deprecated use {@link #openSign(org.bukkit.block.Sign, org.bukkit.block.sign.Side)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void openSign(@NotNull org.bukkit.block.Sign sign) {
|
||||
+ this.openSign(sign, org.bukkit.block.sign.Side.FRONT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Opens an editor window for the specified sign
|
||||
+ *
|
||||
+ * @param sign The sign to open
|
||||
+ * @param side The side of the sign to open
|
||||
+ */
|
||||
+ void openSign(org.bukkit.block.@NotNull Sign sign, org.bukkit.block.sign.@NotNull Side side);
|
||||
+ // Paper end
|
||||
|
||||
/**
|
||||
* Make the entity drop the item in their hand.
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 43ba9fbec2060786fe1cb24025adc697a88b8678..67d253239b86a120162e7fcc56a345b5ebb88ba9 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2584,10 +2584,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Open a Sign for editing by the Player.
|
||||
*
|
||||
- * The Sign must be placed in the same world as the player.
|
||||
+ * The Sign must be in the same world as the player.
|
||||
*
|
||||
* @param sign The sign to edit
|
||||
+ * @deprecated use {@link #openSign(Sign, Side)}
|
||||
*/
|
||||
+ @Deprecated
|
||||
public void openSign(@NotNull Sign sign);
|
||||
|
||||
/**
|
|
@ -0,0 +1,242 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 28 Apr 2018 10:28:50 -0400
|
||||
Subject: [PATCH] Add Ban Methods to Player Objects
|
||||
|
||||
Allows a more logical API for banning players.
|
||||
|
||||
player.banPlayer("Breaking the rules");
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
index 12349910297a75c00e64f6ccc7981aeeeb43ecd3..8f2f3e0ac5266f571b62a754921422bb07d61984 100644
|
||||
--- a/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/OfflinePlayer.java
|
||||
@@ -67,6 +67,61 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
|
||||
* @return true if banned, otherwise false
|
||||
*/
|
||||
public boolean isBanned();
|
||||
+ // Paper start
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans this player from the server
|
||||
+ *
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public default BanEntry banPlayer(@Nullable String reason) {
|
||||
+ return banPlayer(reason, null, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans this player from the server
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param source Source of the ban, or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public default BanEntry banPlayer(@Nullable String reason, @Nullable String source) {
|
||||
+ return banPlayer(reason, null, source);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans this player from the server
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires) {
|
||||
+ return banPlayer(reason, expires, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans this player from the server
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @param source Source of the ban or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) {
|
||||
+ return banPlayer(reason, expires, source, true);
|
||||
+ }
|
||||
+ @NotNull
|
||||
+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source, boolean kickIfOnline) {
|
||||
+ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.NAME).addBan(getName(), reason, expires, source);
|
||||
+ if (kickIfOnline && isOnline()) {
|
||||
+ getPlayer().kickPlayer(reason);
|
||||
+ }
|
||||
+ return banEntry;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
/**
|
||||
* Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 67d253239b86a120162e7fcc56a345b5ebb88ba9..e13d09c5d4c62d47f6f4e057a23caea3ed18496a 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1103,6 +1103,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
public void sendMap(@NotNull MapView map);
|
||||
|
||||
// Paper start
|
||||
+ /**
|
||||
+ * Permanently Bans the Profile and IP address currently used by the player.
|
||||
+ *
|
||||
+ * @param reason Reason for ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ // For reference, Bukkit defines this as nullable, while they impl isn't, we'll follow API.
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerFull(@Nullable String reason) {
|
||||
+ return banPlayerFull(reason, null, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans the Profile and IP address currently used by the player.
|
||||
+ *
|
||||
+ * @param reason Reason for ban
|
||||
+ * @param source Source of ban, or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerFull(@Nullable String reason, @Nullable String source) {
|
||||
+ return banPlayerFull(reason, null, source);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the Profile and IP address currently used by the player.
|
||||
+ *
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerFull(@Nullable String reason, @Nullable java.util.Date expires) {
|
||||
+ return banPlayerFull(reason, expires, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the Profile and IP address currently used by the player.
|
||||
+ *
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @param source Source of the ban, or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerFull(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) {
|
||||
+ banPlayer(reason, expires, source);
|
||||
+ return banPlayerIP(reason, expires, source, true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ *
|
||||
+ * @param reason Reason for ban
|
||||
+ * @param kickPlayer Whether or not to kick the player afterwards
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, boolean kickPlayer) {
|
||||
+ return banPlayerIP(reason, null, null, kickPlayer);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for ban
|
||||
+ * @param source Source of ban, or null for default
|
||||
+ * @param kickPlayer Whether or not to kick the player afterwards
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable String source, boolean kickPlayer) {
|
||||
+ return banPlayerIP(reason, null, source, kickPlayer);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @param kickPlayer Whether or not to kick the player afterwards
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable java.util.Date expires, boolean kickPlayer) {
|
||||
+ return banPlayerIP(reason, expires, null, kickPlayer);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ *
|
||||
+ * @param reason Reason for ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason) {
|
||||
+ return banPlayerIP(reason, null, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Permanently Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for ban
|
||||
+ * @param source Source of ban, or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable String source) {
|
||||
+ return banPlayerIP(reason, null, source);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable java.util.Date expires) {
|
||||
+ return banPlayerIP(reason, expires, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @param source Source of the ban or null for default
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) {
|
||||
+ return banPlayerIP(reason, expires, source, true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Bans the IP address currently used by the player.
|
||||
+ * Does not ban the Profile, use {@link #banPlayerFull(String, java.util.Date, String)}
|
||||
+ * @param reason Reason for Ban
|
||||
+ * @param expires When to expire the ban
|
||||
+ * @param source Source of the ban or null for default
|
||||
+ * @param kickPlayer if the targeted player should be kicked
|
||||
+ * @return Ban Entry
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public default org.bukkit.BanEntry banPlayerIP(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source, boolean kickPlayer) {
|
||||
+ org.bukkit.BanEntry banEntry = org.bukkit.Bukkit.getServer().getBanList(org.bukkit.BanList.Type.IP).addBan(getAddress().getAddress().getHostAddress(), reason, expires, source);
|
||||
+ if (kickPlayer && isOnline()) {
|
||||
+ getPlayer().kickPlayer(reason);
|
||||
+ }
|
||||
+
|
||||
+ return banEntry;
|
||||
+ }
|
||||
|
||||
/**
|
||||
* Sends an Action Bar message to the client.
|
102
patches/unapplied/api/0097-EndermanEscapeEvent.patch
Normal file
102
patches/unapplied/api/0097-EndermanEscapeEvent.patch
Normal file
|
@ -0,0 +1,102 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 30 Apr 2018 13:14:30 -0400
|
||||
Subject: [PATCH] EndermanEscapeEvent
|
||||
|
||||
Fires an event anytime an enderman intends to teleport away from the player
|
||||
|
||||
You may cancel this, enabling ranged attacks to damage the enderman for example.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..806112a8b5a7ce31166675f5b074ceaf42e364b6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java
|
||||
@@ -0,0 +1,87 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Enderman;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
|
||||
+ @NotNull private final Reason reason;
|
||||
+
|
||||
+ public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) {
|
||||
+ super(entity);
|
||||
+ this.reason = reason;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Enderman getEntity() {
|
||||
+ return (Enderman) super.getEntity();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The reason the enderman is trying to escape
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Reason getReason() {
|
||||
+ return reason;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Cancels the escape.
|
||||
+ *
|
||||
+ * If this escape normally would of resulted in damage avoidance such as indirect,
|
||||
+ * the enderman will now take damage.
|
||||
+ *
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ public enum Reason {
|
||||
+ /**
|
||||
+ * The enderman has stopped attacking and ran away
|
||||
+ */
|
||||
+ RUNAWAY,
|
||||
+ /**
|
||||
+ * The enderman has teleported away due to indirect damage (ranged)
|
||||
+ */
|
||||
+ INDIRECT,
|
||||
+ /**
|
||||
+ * The enderman has teleported away due to a critical hit
|
||||
+ */
|
||||
+ CRITICAL_HIT,
|
||||
+ /**
|
||||
+ * The enderman has teleported away due to the player staring at it during combat
|
||||
+ */
|
||||
+ STARE,
|
||||
+ /**
|
||||
+ * Specific case for CRITICAL_HIT where the enderman is taking rain damage
|
||||
+ */
|
||||
+ DROWN
|
||||
+ }
|
||||
+}
|
29
patches/unapplied/api/0098-Enderman.teleportRandomly.patch
Normal file
29
patches/unapplied/api/0098-Enderman.teleportRandomly.patch
Normal file
|
@ -0,0 +1,29 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 30 Apr 2018 13:29:15 -0400
|
||||
Subject: [PATCH] Enderman.teleportRandomly()
|
||||
|
||||
Ability to trigger the vanilla "teleport randomly" mechanic of an enderman.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Enderman.java b/src/main/java/org/bukkit/entity/Enderman.java
|
||||
index 0a03dc437973888ba57ba00fec47193fee38b5a9..605af1a9fc48602643aec57dd14e8c4ab657a0bc 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Enderman.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Enderman.java
|
||||
@@ -11,6 +11,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public interface Enderman extends Monster {
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Try to teleport the enderman to a random nearby location.
|
||||
+ *
|
||||
+ * May conditionally fail if the random location was not valid
|
||||
+ * @return If the enderman teleported successfully or not
|
||||
+ */
|
||||
+
|
||||
+ public boolean teleportRandomly();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the id and data of the block that the Enderman is carrying.
|
||||
*
|
|
@ -0,0 +1,260 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 30 Apr 2018 17:55:28 -0400
|
||||
Subject: [PATCH] Additional world.getNearbyEntities API's
|
||||
|
||||
Provides more methods to get nearby entities, and filter by types and predicates
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
|
||||
index faedd3857023513340b6e9fc67b78c79e3989cbe..58a15d8fd57d55848b37bfc8fffa101692efce87 100644
|
||||
--- a/src/main/java/org/bukkit/World.java
|
||||
+++ b/src/main/java/org/bukkit/World.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
+import org.bukkit.generator.ChunkGenerator;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -625,6 +628,238 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
@NotNull
|
||||
public Collection<Entity> getEntitiesByClasses(@NotNull Class<?>... classes);
|
||||
|
||||
+ // Paper start - additional getNearbyEntities API
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param radius Radius
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double radius) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, radius, radius, radius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double xzRadius, final double yRadius) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, xzRadius, yRadius, xzRadius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z radius
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, xRadius, yRadius, zRadius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param radius X Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of living entities near location. This will always be a non-null collection
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double radius, final @Nullable Predicate<? super LivingEntity> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, radius, radius, radius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of living entities near location. This will always be a non-null collection
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double xzRadius, final double yRadius, final @Nullable Predicate<? super LivingEntity> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, xzRadius, yRadius, xzRadius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby LivingEntities within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of living entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<LivingEntity> getNearbyLivingEntities(final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius, final @Nullable Predicate<? super LivingEntity> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(LivingEntity.class, loc, xRadius, yRadius, zRadius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param radius X/Y/Z Radius
|
||||
+ * @return the collection of living entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double radius) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, radius, radius, radius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @return the collection of living entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double xzRadius, final double yRadius) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, xzRadius, yRadius, xzRadius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z Radius
|
||||
+ * @return the collection of players near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, xRadius, yRadius, zRadius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param radius X/Y/Z Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of players near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double radius, final @Nullable Predicate<? super Player> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, radius, radius, radius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of players near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double xzRadius, final double yRadius, final @Nullable Predicate<? super Player> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, xzRadius, yRadius, xzRadius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets nearby players within the specified radius (bounding box)
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @return the collection of players near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull Collection<Player> getNearbyPlayers(final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius, final @Nullable Predicate<? super Player> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(Player.class, loc, xRadius, yRadius, zRadius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param radius X/Y/Z radius to search within
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull <T extends Entity> Collection<T> getNearbyEntitiesByType(final @Nullable Class<? extends T> clazz, final @NotNull Location loc, final double radius) {
|
||||
+ return this.getNearbyEntitiesByType(clazz, loc, radius, radius, radius, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z radius to search within
|
||||
+ * @param yRadius Y radius to search within
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull <T extends Entity> Collection<T> getNearbyEntitiesByType(final @Nullable Class<? extends T> clazz, final @NotNull Location loc, final double xzRadius, final double yRadius) {
|
||||
+ return this.getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z Radius
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull <T extends Entity> Collection<T> getNearbyEntitiesByType(final @Nullable Class<? extends T> clazz, final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius) {
|
||||
+ return this.getNearbyEntitiesByType(clazz, loc, xRadius, yRadius, zRadius, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param radius X/Y/Z radius to search within
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull <T extends Entity> Collection<T> getNearbyEntitiesByType(final @Nullable Class<? extends T> clazz, final @NotNull Location loc, final double radius, final @Nullable Predicate<? super T> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(clazz, loc, radius, radius, radius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param xzRadius X/Z radius to search within
|
||||
+ * @param yRadius Y radius to search within
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default @NotNull <T extends Entity> Collection<T> getNearbyEntitiesByType(final @Nullable Class<? extends T> clazz, final @NotNull Location loc, final double xzRadius, final double yRadius, final @Nullable Predicate<? super T> predicate) {
|
||||
+ return this.getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, predicate);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all nearby entities of the specified type, within the specified radius (bounding box)
|
||||
+ * @param clazz Type to filter by
|
||||
+ * @param loc Center location
|
||||
+ * @param xRadius X Radius
|
||||
+ * @param yRadius Y Radius
|
||||
+ * @param zRadius Z Radius
|
||||
+ * @param predicate a predicate used to filter results
|
||||
+ * @param <T> the entity type
|
||||
+ * @return the collection of entities near location. This will always be a non-null collection.
|
||||
+ */
|
||||
+ default <T extends Entity> @NotNull Collection<T> getNearbyEntitiesByType(@Nullable Class<? extends Entity> clazz, final @NotNull Location loc, final double xRadius, final double yRadius, final double zRadius, final @Nullable Predicate<? super T> predicate) {
|
||||
+ if (clazz == null) {
|
||||
+ clazz = Entity.class;
|
||||
+ }
|
||||
+ final List<T> nearby = new ArrayList<>();
|
||||
+ for (final Entity bukkitEntity : this.getNearbyEntities(loc, xRadius, yRadius, zRadius)) {
|
||||
+ //noinspection unchecked
|
||||
+ if (clazz.isAssignableFrom(bukkitEntity.getClass()) && (predicate == null || predicate.test((T) bukkitEntity))) {
|
||||
+ //noinspection unchecked
|
||||
+ nearby.add((T) bukkitEntity);
|
||||
+ }
|
||||
+ }
|
||||
+ return nearby;
|
||||
+ }
|
||||
+ // Paper end - additional getNearbyEntities API
|
||||
+
|
||||
/**
|
||||
* Get a list of all players in this World
|
||||
*
|
18
patches/unapplied/api/0100-Location.isChunkLoaded-API.patch
Normal file
18
patches/unapplied/api/0100-Location.isChunkLoaded-API.patch
Normal file
|
@ -0,0 +1,18 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 30 Apr 2018 19:27:31 -0400
|
||||
Subject: [PATCH] Location.isChunkLoaded() API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java
|
||||
index 85c342fc50f2fe0ce9a1b3980df9e088c3dea92d..251d26e6870490abd3e915c5e7c06ce1075a24ab 100644
|
||||
--- a/src/main/java/org/bukkit/Location.java
|
||||
+++ b/src/main/java/org/bukkit/Location.java
|
||||
@@ -533,6 +533,7 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
|
||||
return this;
|
||||
}
|
||||
|
||||
+ public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
|
@ -0,0 +1,587 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 29 Aug 2017 23:58:48 -0400
|
||||
Subject: [PATCH] Expand World.spawnParticle API and add Builder
|
||||
|
||||
Adds ability to control who receives it and who is the source/sender (vanish API)
|
||||
the standard API is to send the packet to everyone in the world, which is ineffecient.
|
||||
|
||||
This adds a new Builder API which is much friendlier to use.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/ParticleBuilder.java b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f45b8cfd1611345e8d81ecb8297a586f05eb5dc6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java
|
||||
@@ -0,0 +1,485 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import com.google.common.collect.Lists;
|
||||
+import org.bukkit.Color;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.Particle;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.util.NumberConversions;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.List;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Helps prepare a particle to be sent to players.
|
||||
+ *
|
||||
+ * Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API
|
||||
+ */
|
||||
+public class ParticleBuilder {
|
||||
+
|
||||
+ private Particle particle;
|
||||
+ private List<Player> receivers;
|
||||
+ private Player source;
|
||||
+ private Location location;
|
||||
+ private int count = 1;
|
||||
+ private double offsetX = 0, offsetY = 0, offsetZ = 0;
|
||||
+ private double extra = 1;
|
||||
+ private Object data;
|
||||
+ private boolean force = true;
|
||||
+
|
||||
+ public ParticleBuilder(@NotNull Particle particle) {
|
||||
+ this.particle = particle;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the particle to all receiving players (or all). This method is safe to use
|
||||
+ * Asynchronously
|
||||
+ *
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder spawn() {
|
||||
+ if (this.location == null) {
|
||||
+ throw new IllegalStateException("Please specify location for this particle");
|
||||
+ }
|
||||
+ location.getWorld().spawnParticle(particle, receivers, source,
|
||||
+ location.getX(), location.getY(), location.getZ(),
|
||||
+ count, offsetX, offsetY, offsetZ, extra, data, force
|
||||
+ );
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The particle going to be sent
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Particle particle() {
|
||||
+ return particle;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Changes what particle will be sent
|
||||
+ *
|
||||
+ * @param particle The particle
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder particle(@NotNull Particle particle) {
|
||||
+ this.particle = particle;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return List of players who will receive the particle, or null for all in world
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public List<Player> receivers() {
|
||||
+ return receivers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Example use:
|
||||
+ *
|
||||
+ * builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); }
|
||||
+ *
|
||||
+ * @return If this particle is going to be sent to someone
|
||||
+ */
|
||||
+ public boolean hasReceivers() {
|
||||
+ return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || (
|
||||
+ receivers != null && !receivers.isEmpty());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends this particle to all players in the world. This is rather silly and you should likely not
|
||||
+ * be doing this.
|
||||
+ *
|
||||
+ * Just be a logical person and use receivers by radius or collection.
|
||||
+ *
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder allPlayers() {
|
||||
+ this.receivers = null;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param receivers List of players to receive this particle, or null for all players in the
|
||||
+ * world
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(@Nullable List<Player> receivers) {
|
||||
+ // Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars
|
||||
+ // TODO: deprecate?
|
||||
+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param receivers List of players to receive this particle, or null for all players in the
|
||||
+ * world
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(@Nullable Collection<Player> receivers) {
|
||||
+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @param receivers List of players to be receive this particle, or null for all players in the
|
||||
+ * world
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(@Nullable Player... receivers) {
|
||||
+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Selects all players within a cuboid selection around the particle location, within the
|
||||
+ * specified bounding box. If you want a more spherical check, see {@link #receivers(int,
|
||||
+ * boolean)}
|
||||
+ *
|
||||
+ * @param radius amount to add on all axis
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(int radius) {
|
||||
+ return receivers(radius, radius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Selects all players within the specified radius around the particle location. If byDistance is
|
||||
+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
|
||||
+ * true, radius is tested by distance in a spherical shape
|
||||
+ *
|
||||
+ * @param radius amount to add on each axis
|
||||
+ * @param byDistance true to use a spherical radius, false to use a cuboid
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(int radius, boolean byDistance) {
|
||||
+ if (!byDistance) {
|
||||
+ return receivers(radius, radius, radius);
|
||||
+ } else {
|
||||
+ this.receivers = Lists.newArrayList();
|
||||
+ for (Player nearbyPlayer : location.getWorld()
|
||||
+ .getNearbyPlayers(location, radius, radius, radius)) {
|
||||
+ Location loc = nearbyPlayer.getLocation();
|
||||
+ double x = NumberConversions.square(location.getX() - loc.getX());
|
||||
+ double y = NumberConversions.square(location.getY() - loc.getY());
|
||||
+ double z = NumberConversions.square(location.getZ() - loc.getZ());
|
||||
+ if (Math.sqrt(x + y + z) > radius) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ this.receivers.add(nearbyPlayer);
|
||||
+ }
|
||||
+ return this;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Selects all players within a cuboid selection around the particle location, within the
|
||||
+ * specified bounding box. Allows specifying a different Y size than X and Z If you want a more
|
||||
+ * cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check,
|
||||
+ * see {@link #receivers(int, boolean)}
|
||||
+ *
|
||||
+ * @param xzRadius amount to add on the x/z axis
|
||||
+ * @param yRadius amount to add on the y axis
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(int xzRadius, int yRadius) {
|
||||
+ return receivers(xzRadius, yRadius, xzRadius);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Selects all players within the specified radius around the particle location. If byDistance is
|
||||
+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
|
||||
+ * true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape.
|
||||
+ *
|
||||
+ * @param xzRadius amount to add on the x/z axis
|
||||
+ * @param yRadius amount to add on the y axis
|
||||
+ * @param byDistance true to use a cylinder shape, false to use cuboid
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) {
|
||||
+ if (!byDistance) {
|
||||
+ return receivers(xzRadius, yRadius, xzRadius);
|
||||
+ } else {
|
||||
+ this.receivers = Lists.newArrayList();
|
||||
+ for (Player nearbyPlayer : location.getWorld()
|
||||
+ .getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) {
|
||||
+ Location loc = nearbyPlayer.getLocation();
|
||||
+ if (Math.abs(loc.getY() - this.location.getY()) > yRadius) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ double x = NumberConversions.square(location.getX() - loc.getX());
|
||||
+ double z = NumberConversions.square(location.getZ() - loc.getZ());
|
||||
+ if (x + z > NumberConversions.square(xzRadius)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ this.receivers.add(nearbyPlayer);
|
||||
+ }
|
||||
+ return this;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Selects all players within a cuboid selection around the particle location, within the
|
||||
+ * specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int,
|
||||
+ * boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)}
|
||||
+ *
|
||||
+ * @param xRadius amount to add on the x axis
|
||||
+ * @param yRadius amount to add on the y axis
|
||||
+ * @param zRadius amount to add on the z axis
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) {
|
||||
+ if (location == null) {
|
||||
+ throw new IllegalStateException("Please set location first");
|
||||
+ }
|
||||
+ return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The player considered the source of this particle (for Visibility concerns), or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Player source() {
|
||||
+ return source;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the source of this particle for visibility concerns (Vanish API)
|
||||
+ *
|
||||
+ * @param source The player who is considered the source
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder source(@Nullable Player source) {
|
||||
+ this.source = source;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Location of where the particle will spawn
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Location location() {
|
||||
+ return location;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the location of where to spawn the particle
|
||||
+ *
|
||||
+ * @param location The location of the particle
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder location(@NotNull Location location) {
|
||||
+ this.location = location.clone();
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the location of where to spawn the particle
|
||||
+ *
|
||||
+ * @param world World to spawn particle in
|
||||
+ * @param x X location
|
||||
+ * @param y Y location
|
||||
+ * @param z Z location
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder location(@NotNull World world, double x, double y, double z) {
|
||||
+ this.location = new Location(world, x, y, z);
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return Number of particles to spawn
|
||||
+ */
|
||||
+ public int count() {
|
||||
+ return count;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of particles to spawn
|
||||
+ *
|
||||
+ * @param count Number of particles
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder count(int count) {
|
||||
+ this.count = count;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Particle offset X. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @return Particle offset X.
|
||||
+ */
|
||||
+ public double offsetX() {
|
||||
+ return offsetX;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Particle offset Y. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @return Particle offset Y.
|
||||
+ */
|
||||
+ public double offsetY() {
|
||||
+ return offsetY;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Particle offset Z. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @return Particle offset Z.
|
||||
+ */
|
||||
+ public double offsetZ() {
|
||||
+ return offsetZ;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle offset. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @param offsetX Particle offset X
|
||||
+ * @param offsetY Particle offset Y
|
||||
+ * @param offsetZ Particle offset Z
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) {
|
||||
+ this.offsetX = offsetX;
|
||||
+ this.offsetY = offsetY;
|
||||
+ this.offsetZ = offsetZ;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the Particle extra data. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @return the extra particle data
|
||||
+ */
|
||||
+ public double extra() {
|
||||
+ return extra;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle extra data. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @param extra the extra particle data
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder extra(double extra) {
|
||||
+ this.extra = extra;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the particle custom data. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @param <T> The Particle data type
|
||||
+ * @return the ParticleData for this particle
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public <T> T data() {
|
||||
+ //noinspection unchecked
|
||||
+ return (T) data;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle custom data. Varies by particle on how this is used
|
||||
+ *
|
||||
+ * @param data The new particle data
|
||||
+ * @param <T> The Particle data type
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public <T> ParticleBuilder data(@Nullable T data) {
|
||||
+ this.data = data;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return whether the particle is forcefully shown to players.
|
||||
+ */
|
||||
+ public boolean force() {
|
||||
+ return force;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether the particle is forcefully shown to the player. If forced, the particle will show
|
||||
+ * faraway, as far as the player's view distance allows. If false, the particle will show
|
||||
+ * according to the client's particle settings.
|
||||
+ *
|
||||
+ * @param force true to force, false for normal
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder force(boolean force) {
|
||||
+ this.force = force;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle Color. Only valid for REDSTONE.
|
||||
+ *
|
||||
+ * @param color the new particle color
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder color(@Nullable Color color) {
|
||||
+ return color(color, 1);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle Color and size. Only valid for REDSTONE.
|
||||
+ *
|
||||
+ * @param color the new particle color
|
||||
+ * @param size the size of the particle
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder color(@Nullable Color color, float size) {
|
||||
+ if (particle != Particle.REDSTONE && color != null) {
|
||||
+ throw new IllegalStateException("Color may only be set on REDSTONE");
|
||||
+ }
|
||||
+
|
||||
+ // We don't officially support reusing these objects, but here we go
|
||||
+ if (color == null) {
|
||||
+ if (data instanceof Particle.DustOptions) {
|
||||
+ return data(null);
|
||||
+ } else {
|
||||
+ return this;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return data(new Particle.DustOptions(color, size));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the particle Color.
|
||||
+ * Only valid for REDSTONE.
|
||||
+ * @param r red color component
|
||||
+ * @param g green color component
|
||||
+ * @param b blue color component
|
||||
+ * @return a reference to this object.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ParticleBuilder color(int r, int g, int b) {
|
||||
+ return color(Color.fromRGB(r, g, b));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java
|
||||
index e2adb9901cc92ede9d44ca9939c6a54d4762eb4b..81bd12c8addcee754c71e5e030c729c7e096fb4c 100644
|
||||
--- a/src/main/java/org/bukkit/Particle.java
|
||||
+++ b/src/main/java/org/bukkit/Particle.java
|
||||
@@ -194,6 +194,18 @@ public enum Particle implements Keyed {
|
||||
return key;
|
||||
}
|
||||
|
||||
+ // Paper start - Particle API expansion
|
||||
+ /**
|
||||
+ * Creates a {@link com.destroystokyo.paper.ParticleBuilder}
|
||||
+ *
|
||||
+ * @return a {@link com.destroystokyo.paper.ParticleBuilder} for the particle
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public com.destroystokyo.paper.ParticleBuilder builder() {
|
||||
+ return new com.destroystokyo.paper.ParticleBuilder(this);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Options which can be applied to redstone dust particles - a particle
|
||||
* color and size.
|
||||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
|
||||
index 58a15d8fd57d55848b37bfc8fffa101692efce87..93c46d40efd73293d84c7eaadf4e360cc3706e2a 100644
|
||||
--- a/src/main/java/org/bukkit/World.java
|
||||
+++ b/src/main/java/org/bukkit/World.java
|
||||
@@ -2841,7 +2841,57 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
* @param data the data to use for the particle or null,
|
||||
* the type of this depends on {@link Particle#getDataType()}
|
||||
*/
|
||||
- public <T> void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data);
|
||||
+ public default <T> void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); }// Paper start - Expand Particle API
|
||||
+ /**
|
||||
+ * Spawns the particle (the number of times specified by count)
|
||||
+ * at the target location. The position of each particle will be
|
||||
+ * randomized positively and negatively by the offset parameters
|
||||
+ * on each axis.
|
||||
+ *
|
||||
+ * @param particle the particle to spawn
|
||||
+ * @param receivers List of players to receive the particles, or null for all in world
|
||||
+ * @param source Source of the particles to be used in visibility checks, or null if no player source
|
||||
+ * @param x the position on the x axis to spawn at
|
||||
+ * @param y the position on the y axis to spawn at
|
||||
+ * @param z the position on the z axis to spawn at
|
||||
+ * @param count the number of particles
|
||||
+ * @param offsetX the maximum random offset on the X axis
|
||||
+ * @param offsetY the maximum random offset on the Y axis
|
||||
+ * @param offsetZ the maximum random offset on the Z axis
|
||||
+ * @param extra the extra data for this particle, depends on the
|
||||
+ * particle used (normally speed)
|
||||
+ * @param data the data to use for the particle or null,
|
||||
+ * the type of this depends on {@link Particle#getDataType()}
|
||||
+ * @param <T> Type
|
||||
+ */
|
||||
+ public default <T> void spawnParticle(@NotNull Particle particle, @Nullable List<Player> receivers, @NotNull Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, receivers, source, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); }
|
||||
+ /**
|
||||
+ * Spawns the particle (the number of times specified by count)
|
||||
+ * at the target location. The position of each particle will be
|
||||
+ * randomized positively and negatively by the offset parameters
|
||||
+ * on each axis.
|
||||
+ *
|
||||
+ * @param particle the particle to spawn
|
||||
+ * @param receivers List of players to receive the particles, or null for all in world
|
||||
+ * @param source Source of the particles to be used in visibility checks, or null if no player source
|
||||
+ * @param x the position on the x axis to spawn at
|
||||
+ * @param y the position on the y axis to spawn at
|
||||
+ * @param z the position on the z axis to spawn at
|
||||
+ * @param count the number of particles
|
||||
+ * @param offsetX the maximum random offset on the X axis
|
||||
+ * @param offsetY the maximum random offset on the Y axis
|
||||
+ * @param offsetZ the maximum random offset on the Z axis
|
||||
+ * @param extra the extra data for this particle, depends on the
|
||||
+ * particle used (normally speed)
|
||||
+ * @param data the data to use for the particle or null,
|
||||
+ * the type of this depends on {@link Particle#getDataType()}
|
||||
+ * @param <T> Type
|
||||
+ * @param force allows the particle to be seen further away from the player
|
||||
+ * and shows to players using any vanilla client particle settings
|
||||
+ */
|
||||
+ public <T> void spawnParticle(@NotNull Particle particle, @Nullable List<Player> receivers, @Nullable Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data, boolean force);
|
||||
+ // Paper end
|
||||
+
|
||||
|
||||
/**
|
||||
* Spawns the particle (the number of times specified by count)
|
116
patches/unapplied/api/0102-EndermanAttackPlayerEvent.patch
Normal file
116
patches/unapplied/api/0102-EndermanAttackPlayerEvent.patch
Normal file
|
@ -0,0 +1,116 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 1 May 2018 20:17:44 -0400
|
||||
Subject: [PATCH] EndermanAttackPlayerEvent
|
||||
|
||||
Allow control over whether or not an enderman aggros a player.
|
||||
|
||||
This allows you to override/extend the pumpkin/stare logic.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f530a3d9314e17d1da896cac633f6a422258d9a9
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java
|
||||
@@ -0,0 +1,101 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining
|
||||
+ * a copy of this software and associated documentation files (the
|
||||
+ * "Software"), to deal in the Software without restriction, including
|
||||
+ * without limitation the rights to use, copy, modify, merge, publish,
|
||||
+ * distribute, sublicense, and/or sell copies of the Software, and to
|
||||
+ * permit persons to whom the Software is furnished to do so, subject to
|
||||
+ * the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Enderman;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when an Enderman determines if it should attack a player or not.
|
||||
+ * Starts off cancelled if the player is wearing a pumpkin head or is not looking
|
||||
+ * at the Enderman, according to Vanilla rules.
|
||||
+ *
|
||||
+ */
|
||||
+public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable {
|
||||
+ @NotNull private final Player player;
|
||||
+
|
||||
+ public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) {
|
||||
+ super(entity);
|
||||
+ this.player = player;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The enderman considering attacking
|
||||
+ *
|
||||
+ * @return The enderman considering attacking
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Enderman getEntity() {
|
||||
+ return (Enderman) super.getEntity();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The player the Enderman is considering attacking
|
||||
+ *
|
||||
+ * @return The player the Enderman is considering attacking
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ /**
|
||||
+ *
|
||||
+ * @return If cancelled, the enderman will not attack
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Cancels if the Enderman will attack this player
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue