More more more more more work
This commit is contained in:
parent
d7cdc72bdf
commit
6f3591fd6d
90 changed files with 203 additions and 211 deletions
|
@ -3,6 +3,8 @@ From: Brokkonaut <hannos17@gmx.de>
|
|||
Date: Tue, 7 Feb 2017 16:55:35 -0600
|
||||
Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue
|
||||
|
||||
#NOTE: Vanilla now does incremental chunk saves
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index fb3b0693abb6f2f044d39508b727fb3a2ad16823..4a2739edb01c97c99524dc96decbdcb12e0b7d4f 100644
|
||||
|
|
|
@ -3,6 +3,7 @@ From: Zach Brown <zach.brown@destroystokyo.com>
|
|||
Date: Thu, 11 Jan 2018 16:47:28 -0600
|
||||
Subject: [PATCH] Make max squid spawn height configurable
|
||||
|
||||
#NOTE: Spigot removed the min option, Vanilla now has the same spawn rule for all ambient water animals
|
||||
I don't know why upstream made only the minimum height configurable but
|
||||
whatever
|
||||
|
||||
|
@ -21,16 +22,15 @@ index e2894138d3efb32161087ad2a1093b8c15c56a65..5892823425055efb92bf635b035d6298
|
|||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
index 3ffc1ee8a9ae63c8678c12736fab5d6ba0a21a5b..4da560f6e4da0750bda78b900b2d916d58adfccb 100644
|
||||
index 370513fbc39f178f903ce140ced1a97029dd39db..b195617c39c4b382a196a709c318904cd0598e0e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
@@ -211,7 +211,8 @@ public class Squid extends WaterAnimal {
|
||||
@@ -206,7 +206,7 @@ public class Squid extends WaterAnimal {
|
||||
public void travel(Vec3 movementInput) {
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
}
|
||||
|
||||
public static boolean checkSquidSpawnRules(EntityType<Squid> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) {
|
||||
- return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot
|
||||
+ final double maxHeight = world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper
|
||||
+ return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper
|
||||
}
|
||||
|
||||
-
|
||||
+// AAA
|
||||
@Override
|
||||
public void handleEntityEvent(byte status) {
|
||||
if (status == 19) {
|
|
@ -1,102 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,126 +0,0 @@
|
|||
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..d5632d352590dec6982a372b285a8d4a332fa589
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java
|
||||
@@ -0,0 +1,114 @@
|
||||
+package org.bukkit.event.command;
|
||||
+
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.Event;
|
||||
+
|
||||
+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;
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final String message) {
|
||||
+ this(sender, commandLine, message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(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 : Bukkit.getUnsafe().legacyComponentSerializer().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 : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets message that will be returned
|
||||
+ * <p>
|
||||
+ *
|
||||
+ * @return Unknown command message
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ 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;
|
||||
+ }
|
||||
+}
|
||||
+
|
|
@ -1,351 +0,0 @@
|
|||
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..2ef9a7bd55e2c9cf8cb20d5f77282676ae11181f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java
|
||||
@@ -0,0 +1,177 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.Set;
|
||||
+import java.util.UUID;
|
||||
+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 {
|
||||
+
|
||||
+ /**
|
||||
+ * @return The players name, if set
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ String getName();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets this profiles Name
|
||||
+ *
|
||||
+ * @param name The new Name
|
||||
+ * @return The previous Name
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ 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
|
||||
+ UUID setId(@Nullable UUID uuid);
|
||||
+
|
||||
+ /**
|
||||
+ * @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);
|
||||
+
|
||||
+ /**
|
||||
+ * Whether or not this Profile has textures associated to it
|
||||
+ * @return If 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 fa3cd5395ec29d7c51c792720acbb2394f238c45..6c7b1e172a9acc881ecade6543245e8a64e251f6 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -1918,6 +1918,40 @@ public final class Bukkit {
|
||||
public static boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
return server.suggestPlayerNamesWhenNullTabCompletions();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a PlayerProfile for the specified uuid, with name as null
|
||||
+ * @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
|
||||
+ * @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.
|
||||
+ *
|
||||
+ * @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);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index d1e5e679e0a7482a87a9a049ed0ce5c1b9891c90..8021598d78170ea1676cf21bac63858528398f53 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1685,5 +1685,33 @@ 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
|
||||
+ * @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
|
||||
+ * @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.
|
||||
+ *
|
||||
+ * @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);
|
||||
// Paper end
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
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
|
|
@ -1,37 +0,0 @@
|
|||
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 0ab94ddd3b88eee8040233a89823bd2fadc78d55..396092fd249928ca01133eeeeb61f0ad90b2e332 100644
|
||||
--- a/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/HumanEntity.java
|
||||
@@ -315,6 +315,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.
|
||||
*
|
|
@ -1,23 +0,0 @@
|
|||
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 7e0ec58ea1d23501f0273882ebae8e45513b02cf..d794ed97bd14c67584af9190bad7d0cd07001b05 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Entity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Entity.java
|
||||
@@ -673,5 +673,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
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+
|
||||
+}
|
|
@ -1,83 +0,0 @@
|
|||
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 {}
|
|
@ -1,52 +0,0 @@
|
|||
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 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..b1fbb931148a87f29e8b8796b13851d767cc1d68 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
@@ -160,5 +160,16 @@ public interface ItemFactory {
|
||||
*/
|
||||
@NotNull
|
||||
net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
|
||||
+
|
||||
+ /**
|
||||
+ * 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
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ String getI18NDisplayName(@Nullable ItemStack item);
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index a15abec467bac70116a6fc21a300d4930b909f15..de5bcdb7b84acdd5e22500e367df292f35a86e19 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -611,5 +611,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor
|
||||
public @NotNull net.kyori.adventure.text.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
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getI18NDisplayName() {
|
||||
+ return Bukkit.getServer().getItemFactory().getI18NDisplayName(this);
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
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 b1fbb931148a87f29e8b8796b13851d767cc1d68..71e5ee496a947fbd8e3ec579833b157c76b51833 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
|
||||
@@ -171,5 +171,17 @@ public interface ItemFactory {
|
||||
*/
|
||||
@Nullable
|
||||
String getI18NDisplayName(@Nullable ItemStack item);
|
||||
+
|
||||
+ /**
|
||||
+ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks.
|
||||
+ *
|
||||
+ * Use this method to 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
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
index de5bcdb7b84acdd5e22500e367df292f35a86e19..e8783b0116f4efd5447a5f6f260506000983ffd2 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
|
||||
@@ -536,7 +536,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor
|
||||
}
|
||||
}
|
||||
|
||||
- return result;
|
||||
+ return result.ensureServerConversions(); // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -612,6 +612,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor
|
||||
return Bukkit.getServer().getItemFactory().displayName(this);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks.
|
||||
+ *
|
||||
+ * Use this method to 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,
|
|
@ -1,56 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 02:08:55 -0500
|
||||
Subject: [PATCH] Make /plugins list alphabetical
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
index bcb576a4271b1ec7b1cfe6f83cf161b7d89ed2e5..4de959bbd1270d7d6ea8e5e69521bcca6abe2138 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
@@ -3,6 +3,9 @@ package org.bukkit.command.defaults;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.TreeMap;
|
||||
+
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -34,15 +37,22 @@ public class PluginsCommand extends BukkitCommand {
|
||||
|
||||
@NotNull
|
||||
private String getPluginList() {
|
||||
- StringBuilder pluginList = new StringBuilder();
|
||||
- Plugin[] plugins = Bukkit.getPluginManager().getPlugins();
|
||||
+ // Paper start
|
||||
+ TreeMap<String, Plugin> plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
+
|
||||
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
+ plugins.put(plugin.getDescription().getName(), plugin);
|
||||
+ }
|
||||
|
||||
- for (Plugin plugin : plugins) {
|
||||
+ StringBuilder pluginList = new StringBuilder();
|
||||
+ for (Map.Entry<String, Plugin> entry : plugins.entrySet()) {
|
||||
if (pluginList.length() > 0) {
|
||||
pluginList.append(ChatColor.WHITE);
|
||||
pluginList.append(", ");
|
||||
}
|
||||
|
||||
+ Plugin plugin = entry.getValue();
|
||||
+
|
||||
pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED);
|
||||
pluginList.append(plugin.getDescription().getName());
|
||||
|
||||
@@ -51,6 +61,8 @@ public class PluginsCommand extends BukkitCommand {
|
||||
}
|
||||
}
|
||||
|
||||
- return "(" + plugins.length + "): " + pluginList.toString();
|
||||
+ return "(" + plugins.size() + "): " + pluginList.toString();
|
||||
+ // Paper end
|
||||
}
|
||||
+
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
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 b41133f23d25f90fc0993499056c4eeaf003a701..bfc90a3569abc717f37c064e3068c55ef323edab 100644
|
||||
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
@@ -279,6 +279,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.
|
||||
*
|
|
@ -1,157 +0,0 @@
|
|||
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..8a259ab49ea79673b6da9e4e2aaecec67469994e
|
||||
--- /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 org.bukkit.Bukkit;
|
||||
+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 : Bukkit.getUnsafe().legacyComponentSerializer().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 : Bukkit.getUnsafe().legacyComponentSerializer().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 : Bukkit.getUnsafe().legacyComponentSerializer().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;
|
||||
+ }
|
||||
+}
|
|
@ -1,51 +0,0 @@
|
|||
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 533600dfb2e73736857cc2a10525db7dc2452433..02f80c9a34a23c2285a1e05b41f53b4bafc28c5a 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -37,6 +37,8 @@ dependencies {
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-gson")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-plain")
|
||||
+ api("org.apache.logging.log4j:log4j-api:2.14.1") // Paper
|
||||
+ api("org.slf4j:slf4j-api:1.7.30") // Paper
|
||||
|
||||
implementation("org.ow2.asm:asm:9.1")
|
||||
implementation("org.ow2.asm:asm-commons:9.1")
|
||||
diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
index 03ca87a1cbace2459174bb7bb8847bda766e80c5..c25fc646be750d3a3b2f4fb3f1c53daee5254107 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/Plugin.java
|
||||
@@ -179,6 +179,18 @@ public interface Plugin extends TabExecutor {
|
||||
@NotNull
|
||||
public Logger getLogger();
|
||||
|
||||
+ // Paper start - Add SLF4J/Log4J loggers
|
||||
+ @NotNull
|
||||
+ default org.slf4j.Logger getSLF4JLogger() {
|
||||
+ return org.slf4j.LoggerFactory.getLogger(getLogger().getName());
|
||||
+ }
|
||||
+
|
||||
+ @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>
|
|
@ -1,41 +0,0 @@
|
|||
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 50a479488917b4ce019fa71a496c41e843e9c5c4..f99d60ae4003f953b5680a997e9e43e63c035b0c 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
@@ -43,7 +43,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() {
|
||||
final ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
@@ -277,7 +277,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);
|
||||
+ // Paper - Handle plugin prefix in implementation
|
||||
+ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName());
|
||||
}
|
||||
|
||||
/**
|
|
@ -1,118 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,117 +0,0 @@
|
|||
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..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java
|
||||
@@ -0,0 +1,41 @@
|
||||
+package com.destroystokyo.paper.utils;
|
||||
+
|
||||
+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 {
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static Logger getLogger(@NotNull PluginDescriptionFile description) {
|
||||
+ Logger logger = new PaperPluginLogger(description);
|
||||
+ 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(description.getPrefix() != null ? description.getPrefix() : description.getName());
|
||||
+ }
|
||||
+
|
||||
+ return logger;
|
||||
+ }
|
||||
+
|
||||
+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) {
|
||||
+ super(description.getPrefix() != null ? description.getPrefix() : description.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 f99d60ae4003f953b5680a997e9e43e63c035b0c..c943bd801b54519ba6cf5d45aec593d7b7438f99 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
|
||||
@@ -43,7 +43,7 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
private boolean naggable = true;
|
||||
private FileConfiguration newConfig = null;
|
||||
private File configFile = null;
|
||||
- private Logger logger = null; // Paper - PluginLogger -> Logger
|
||||
+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private
|
||||
|
||||
public JavaPlugin() {
|
||||
final ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
@@ -277,8 +277,11 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
this.dataFolder = dataFolder;
|
||||
this.classLoader = classLoader;
|
||||
this.configFile = new File(dataFolder, "config.yml");
|
||||
- // Paper - Handle plugin prefix in implementation
|
||||
- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName());
|
||||
+ // Paper start
|
||||
+ if (this.logger == null) {
|
||||
+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
index 657243776c8a2abb5a57e5c407212a8387d649eb..4fa5f7140ea97e1b6a63808b59115bfb1a85cb32 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot
|
||||
private JavaPlugin pluginInit;
|
||||
private IllegalStateException pluginState;
|
||||
private final Set<String> seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
+ private java.util.logging.Logger logger; // Paper - add field
|
||||
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot
|
||||
this.url = file.toURI().toURL();
|
||||
this.libraryLoader = libraryLoader;
|
||||
|
||||
+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early
|
||||
+
|
||||
try {
|
||||
Class<?> jarClass;
|
||||
try {
|
||||
@@ -229,6 +232,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot
|
||||
pluginState = new IllegalStateException("Initial initialization");
|
||||
this.pluginInit = javaPlugin;
|
||||
|
||||
+ javaPlugin.logger = this.logger; // Paper - set logger
|
||||
javaPlugin.init(loader, loader.server, description, dataFolder, file, this);
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
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..e406ce639a2e88b78f82f25e71678a669d0a958b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java
|
||||
@@ -0,0 +1,137 @@
|
||||
+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.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;
|
||||
+ @Nullable private final ItemStack oldItem;
|
||||
+ @Nullable private final ItemStack newItem;
|
||||
+
|
||||
+ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable 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
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public ItemStack getOldItem() {
|
||||
+ return this.oldItem;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the new item that's replacing the old
|
||||
+ *
|
||||
+ * @return new item
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ 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),
|
||||
+ 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 or not this material can be equipped to a slot
|
||||
+ *
|
||||
+ * @param material material to check
|
||||
+ * @return whether or not this material can be equipped
|
||||
+ */
|
||||
+ public static boolean isEquipable(@NotNull Material material) {
|
||||
+ return getByMaterial(material) != null;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -1,31 +0,0 @@
|
|||
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 da0964b1b6555ad50cb2ee47f13a7b9dfb1ab6aa..3ca05a6e86a5329cf452041eac476e3636eec34a 100644
|
||||
--- a/src/main/java/org/bukkit/block/Block.java
|
||||
+++ b/src/main/java/org/bukkit/block/Block.java
|
||||
@@ -271,6 +271,16 @@ public interface Block extends Metadatable {
|
||||
@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
|
||||
*
|
|
@ -1,266 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
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.
|
||||
|
||||
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..619ed37169c126a8c75d02699a04728bac49d10d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java
|
||||
@@ -0,0 +1,177 @@
|
||||
+/*
|
||||
+ * 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.collect.ImmutableList;
|
||||
+import org.apache.commons.lang.Validate;
|
||||
+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 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;
|
||||
+ @NotNull private List<String> completions;
|
||||
+ private boolean cancelled;
|
||||
+ private boolean handled = false;
|
||||
+ private boolean fireSyncHandler = true;
|
||||
+
|
||||
+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List<String> completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) {
|
||||
+ super(true);
|
||||
+ this.sender = sender;
|
||||
+ this.completions = 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 completions;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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) {
|
||||
+ Validate.notNull(completions);
|
||||
+ this.completions = new ArrayList<>(completions);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
index d1a9956a1573dab54c5ff2e5d67ca86cfe1dc01a..f96c4ba53ab41ea66d4f9a4d54eeabb63f992b58 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.event.server;
|
||||
|
||||
+import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -8,6 +9,7 @@ import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Called when a {@link CommandSender} of any description (ie: player or
|
||||
@@ -29,6 +31,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, @Nullable org.bukkit.Location location) {
|
||||
+ this.isCommand = isCommand;
|
||||
+ this.loc = location;
|
||||
+ // Paper end
|
||||
Validate.notNull(sender, "sender");
|
||||
Validate.notNull(buffer, "buffer");
|
||||
Validate.notNull(completions, "completions");
|
||||
@@ -69,14 +78,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
|
||||
+ */
|
||||
+ @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) {
|
||||
Validate.notNull(completions);
|
||||
- this.completions = completions;
|
||||
+ this.completions = new ArrayList<>(completions); // Paper
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,71 +0,0 @@
|
|||
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 0dae92b41684e9c2ada74d8987f922db04a419ca..34445011ccd22753a345dfc1ff87e01d2432654c 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -36,7 +36,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 { // Paper
|
||||
+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper
|
||||
|
||||
// Paper start
|
||||
@Override
|
|
@ -1,35 +0,0 @@
|
|||
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 d74b3114f535e1e5e36ae007f1fe0522916a0362..d742c4058ba9aed4fbe1591fd755a06608b06e98 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
@@ -25,6 +25,7 @@ public class ShapedRecipe implements Recipe, Keyed {
|
||||
public ShapedRecipe(@NotNull ItemStack result) {
|
||||
Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result.");
|
||||
this.key = NamespacedKey.randomKey();
|
||||
+ 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();
|
||||
this.output = new ItemStack(result);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
index 68447fb8c12356e779b96ec98c54119045046751..84062dd719cb8a6142dc8c806777cb208c6b42b2 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
@@ -26,6 +26,7 @@ public class ShapelessRecipe implements Recipe, Keyed {
|
||||
public ShapelessRecipe(@NotNull ItemStack result) {
|
||||
Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result.");
|
||||
this.key = NamespacedKey.randomKey();
|
||||
+ 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();
|
||||
this.output = new ItemStack(result);
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,102 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,50 +0,0 @@
|
|||
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 b4c7f2d6de64d32804c8630f0ea1563a876b3510..96f1f1544d03d2928e95daa0dd02579ef3fdc87c 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -985,12 +985,33 @@ 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);
|
||||
+ }
|
||||
/**
|
||||
* 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
|
|
@ -1,127 +0,0 @@
|
|||
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..3ad231aa3206c8cfd5ec995249584cebab5d11f3
|
||||
--- /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").clone();
|
||||
+ 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 effecient 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;
|
||||
+ }
|
||||
+}
|
|
@ -1,80 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,78 +0,0 @@
|
|||
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 943d751fb3e48212fbe258845beba03c25fa22d9..a6914f01e01e9103702185f92b0209b3c84c152a 100644
|
||||
--- a/src/main/java/org/bukkit/block/Skull.java
|
||||
+++ b/src/main/java/org/bukkit/block/Skull.java
|
||||
@@ -7,6 +7,7 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile; // Paper
|
||||
|
||||
/**
|
||||
* Represents a captured state of a skull block.
|
||||
@@ -61,6 +62,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 PlayerProfile profile);
|
||||
+
|
||||
+ /**
|
||||
+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile}
|
||||
+ * @return The profile of the owner, if set
|
||||
+ */
|
||||
+ @Nullable PlayerProfile getPlayerProfile();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the rotation of the skull in the world (or facing direction if this
|
||||
* is a wall mounted skull).
|
||||
diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
index 496254f959345d74167a9b44d160ea1bb428c5a1..88d1c889c09adb91abb09a8e43a30c871b217da2 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.bukkit.inventory.meta;
|
||||
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
+
|
||||
/**
|
||||
* Represents a skull that can have an owner.
|
||||
*/
|
||||
@@ -36,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 PlayerProfile profile);
|
||||
+
|
||||
+ /**
|
||||
+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile}
|
||||
+ * @return The profile of the owner, if set
|
||||
+ */
|
||||
+ @Nullable PlayerProfile getPlayerProfile();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the owner of the skull.
|
||||
*
|
|
@ -1,176 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+}
|
|
@ -1,75 +0,0 @@
|
|||
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] PlayerAdvancementCriterionGrantEvent
|
||||
|
||||
|
||||
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..bb8d7c959cdea4b66455a49e74804ea4b126620d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java
|
||||
@@ -0,0 +1,63 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.advancement.Advancement;
|
||||
+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 a player is granted a criteria in an advancement.
|
||||
+ */
|
||||
+public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private final Advancement advancement;
|
||||
+ @NotNull private final String criterion;
|
||||
+ private boolean cancel = false;
|
||||
+
|
||||
+ public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) {
|
||||
+ super(who);
|
||||
+ this.advancement = advancement;
|
||||
+ this.criterion = criterion;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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;
|
||||
+ }
|
||||
+
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancel = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
|
@ -1,96 +0,0 @@
|
|||
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);
|
||||
+}
|
|
@ -1,39 +0,0 @@
|
|||
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
|
||||
|
||||
Adds data about what Item related methods were used in InventoryMoveItem event
|
||||
so that the server can improve the performance of this event.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
index a8c48f5a416326e96c431e5fa22edee04825530e..04d4a83bfc4f86341f9d72128458154d08c8ec43 100644
|
||||
--- a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java
|
||||
@@ -31,6 +31,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable {
|
||||
private final Inventory destinationInventory;
|
||||
private ItemStack itemStack;
|
||||
private final boolean didSourceInitiate;
|
||||
+ public boolean calledGetItem; // Paper
|
||||
+ public boolean calledSetItem; // Paper
|
||||
|
||||
public InventoryMoveItemEvent(@NotNull final Inventory sourceInventory, @NotNull final ItemStack itemStack, @NotNull final Inventory destinationInventory, final boolean didSourceInitiate) {
|
||||
Validate.notNull(itemStack, "ItemStack cannot be null");
|
||||
@@ -58,7 +60,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable {
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStack getItem() {
|
||||
- return itemStack.clone();
|
||||
+ calledGetItem = true; // Paper - record this method was used for auto detection of mode
|
||||
+ return itemStack; // Paper - Removed clone, handled better in Server
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +73,7 @@ public class InventoryMoveItemEvent extends Event implements Cancellable {
|
||||
*/
|
||||
public void setItem(@NotNull ItemStack itemStack) {
|
||||
Validate.notNull(itemStack, "ItemStack cannot be null. Cancel the event if you want nothing to be transferred.");
|
||||
+ calledSetItem = true; // Paper - record this method was used for auto detection of mode
|
||||
this.itemStack = itemStack.clone();
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
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
|
|
@ -1,91 +0,0 @@
|
|||
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 31f6f781a0403bf6388d668f0effaed5aae94468..25e0d571710403c334bd73ce1b97109dd65c3244 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
|
|
@ -1,381 +0,0 @@
|
|||
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..baac2e4f090a490372ef4aed92c8a5771955e921
|
||||
--- /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 612958a331575d1da2715531ebdf6b1168f2e860..bb4f7702ced0baf0670a7a21d48ad528b7249361 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
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
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/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 8d5ddb1451ea1d7a7a5c9eefb843a4adb885d20e..0dabd6f69e85b21f7ec6e6a2ac46d7fc58af24f6 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -4,6 +4,7 @@ import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
import com.destroystokyo.paper.Title; // Paper
|
||||
import net.kyori.adventure.text.Component;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile; // Paper
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.GameMode;
|
||||
@@ -1914,6 +1915,20 @@ 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
|
||||
+ 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
|
||||
+ * @param profile The new profile to use
|
||||
+ */
|
||||
+ void setPlayerProfile(@NotNull PlayerProfile profile);
|
||||
// Paper end
|
||||
|
||||
// Spigot start
|
|
@ -1,58 +0,0 @@
|
|||
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 befd34cfdd37451532f14feeba5e728d3f86751a..c85fc0cb1c4927fe637f20a4e2499bce7707d633 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -559,6 +559,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 89fc36a73b8ae26f19b06cb0f9376ec33724b939..1a80dad1fa0bf3f33f5669f846912092132f8d64 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -477,6 +477,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.
|
||||
*
|
|
@ -1,30 +0,0 @@
|
|||
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;
|
||||
+ }
|
||||
+
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 7 May 2017 06:26:09 -0500
|
||||
Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 9611388a6aeebb86b19d89c526f53dfed4d3ed27..d17af2ec8f72bf0cbe5928e7a83c06ba5ad4503d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -379,6 +379,7 @@ public class ItemEntity extends Entity {
|
||||
// CraftBukkit start - fire PlayerPickupItemEvent
|
||||
int canHold = player.getInventory().canHold(itemstack);
|
||||
int remaining = i - canHold;
|
||||
+ boolean flyAtPlayer = false; // Paper
|
||||
|
||||
if (this.pickupDelay <= 0 && canHold > 0) {
|
||||
itemstack.setCount(canHold);
|
||||
@@ -386,8 +387,14 @@ public class ItemEntity extends Entity {
|
||||
PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
|
||||
playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems());
|
||||
this.level.getCraftServer().getPluginManager().callEvent(playerEvent);
|
||||
+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper
|
||||
if (playerEvent.isCancelled()) {
|
||||
itemstack.setCount(i); // SPIGOT-5294 - restore count
|
||||
+ // Paper Start
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+ // Paper End
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -417,7 +424,11 @@ public class ItemEntity extends Entity {
|
||||
// CraftBukkit end
|
||||
|
||||
if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.getInventory().add(itemstack)) {
|
||||
- player.take(this, i);
|
||||
+ // Paper Start
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+ // Paper End
|
||||
if (itemstack.isEmpty()) {
|
||||
this.discard();
|
||||
itemstack.setCount(i);
|
|
@ -1,41 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 11 Jun 2017 16:30:30 -0500
|
||||
Subject: [PATCH] PlayerAttemptPickupItemEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index d17af2ec8f72bf0cbe5928e7a83c06ba5ad4503d..54025e401eb02fceb47afb182f0ede620ca23a8d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -37,6 +37,7 @@ import net.minecraft.stats.Stats;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
// CraftBukkit end
|
||||
+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper
|
||||
|
||||
public class ItemEntity extends Entity {
|
||||
|
||||
@@ -381,6 +382,22 @@ public class ItemEntity extends Entity {
|
||||
int remaining = i - canHold;
|
||||
boolean flyAtPlayer = false; // Paper
|
||||
|
||||
+ // Paper start
|
||||
+ if (this.pickupDelay <= 0) {
|
||||
+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent);
|
||||
+
|
||||
+ flyAtPlayer = attemptEvent.getFlyAtPlayer();
|
||||
+ if (attemptEvent.isCancelled()) {
|
||||
+ if (flyAtPlayer) {
|
||||
+ player.take(this, i);
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (this.pickupDelay <= 0 && canHold > 0) {
|
||||
itemstack.setCount(canHold);
|
||||
// Call legacy event
|
|
@ -1,25 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sweepyoface <github@sweepy.pw>
|
||||
Date: Sat, 17 Jun 2017 18:48:21 -0400
|
||||
Subject: [PATCH] Add UnknownCommandEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 696e2495ee8046c78ed53126db0e6c696c77c00d..e01f800130f183bf10a383e298b7da3d5f11e3a2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -817,7 +817,13 @@ public final class CraftServer implements Server {
|
||||
|
||||
// Spigot start
|
||||
if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) {
|
||||
- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage);
|
||||
+ // Paper start
|
||||
+ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage);
|
||||
+ Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ if (event.message() != null) {
|
||||
+ sender.sendMessage(event.message());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
// Spigot end
|
||||
|
|
@ -1,549 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 15 Jan 2018 22:11:48 -0500
|
||||
Subject: [PATCH] Basic PlayerProfile API
|
||||
|
||||
Establishes base extension of profile systems for future edits too
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..84551164b76bc8f064a3a0c030c3a1b47f567b6f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
|
||||
@@ -0,0 +1,302 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.destroystokyo.paper.PaperConfig;
|
||||
+import com.google.common.base.Charsets;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.authlib.properties.Property;
|
||||
+import com.mojang.authlib.properties.PropertyMap;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.players.GameProfileCache;
|
||||
+import org.apache.commons.lang3.Validate;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+import java.util.AbstractSet;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
+import java.util.Set;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public class CraftPlayerProfile implements PlayerProfile {
|
||||
+
|
||||
+ private GameProfile profile;
|
||||
+ private final PropertySet properties = new PropertySet();
|
||||
+
|
||||
+ public CraftPlayerProfile(CraftPlayer player) {
|
||||
+ this.profile = player.getHandle().getGameProfile();
|
||||
+ }
|
||||
+
|
||||
+ public CraftPlayerProfile(UUID id, String name) {
|
||||
+ this.profile = new GameProfile(id, name);
|
||||
+ }
|
||||
+
|
||||
+ public CraftPlayerProfile(GameProfile profile) {
|
||||
+ Validate.notNull(profile, "GameProfile cannot be null!");
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasProperty(String property) {
|
||||
+ return profile.getProperties().containsKey(property);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperty(ProfileProperty property) {
|
||||
+ String name = property.getName();
|
||||
+ PropertyMap properties = profile.getProperties();
|
||||
+ properties.removeAll(name);
|
||||
+ properties.put(name, new Property(name, property.getValue(), property.getSignature()));
|
||||
+ }
|
||||
+
|
||||
+ public GameProfile getGameProfile() {
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public UUID getId() {
|
||||
+ return profile.getId();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public UUID setId(@Nullable UUID uuid) {
|
||||
+ GameProfile prev = this.profile;
|
||||
+ this.profile = new GameProfile(uuid, prev.getName());
|
||||
+ copyProfileProperties(prev, this.profile);
|
||||
+ return prev.getId();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public String getName() {
|
||||
+ return profile.getName();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String setName(@Nullable String name) {
|
||||
+ GameProfile prev = this.profile;
|
||||
+ this.profile = new GameProfile(prev.getId(), name);
|
||||
+ copyProfileProperties(prev, this.profile);
|
||||
+ return prev.getName();
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public Set<ProfileProperty> getProperties() {
|
||||
+ return properties;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperties(Collection<ProfileProperty> properties) {
|
||||
+ properties.forEach(this::setProperty);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clearProperties() {
|
||||
+ profile.getProperties().clear();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeProperty(String property) {
|
||||
+ return !profile.getProperties().removeAll(property).isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ CraftPlayerProfile that = (CraftPlayerProfile) o;
|
||||
+ return Objects.equals(profile, that.profile);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return profile.hashCode();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return profile.toString();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CraftPlayerProfile clone() {
|
||||
+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName());
|
||||
+ clone.setProperties(getProperties());
|
||||
+ return clone;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isComplete() {
|
||||
+ return profile.isComplete();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean completeFromCache() {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ return completeFromCache(false, PaperConfig.isProxyOnlineMode());
|
||||
+ }
|
||||
+
|
||||
+ public boolean completeFromCache(boolean onlineMode) {
|
||||
+ return completeFromCache(false, onlineMode);
|
||||
+ }
|
||||
+
|
||||
+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ String name = profile.getName();
|
||||
+ GameProfileCache userCache = server.getProfileCache();
|
||||
+ if (profile.getId() == null) {
|
||||
+ final GameProfile profile;
|
||||
+ if (onlineMode) {
|
||||
+ profile = lookupUUID ? userCache.get(name).orElse(null) : userCache.getProfileIfCached(name);
|
||||
+ } else {
|
||||
+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile
|
||||
+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
|
||||
+ }
|
||||
+ if (profile != null) {
|
||||
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
|
||||
+ copyProfileProperties(this.profile, profile);
|
||||
+ this.profile = profile;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) {
|
||||
+ Optional<GameProfile> optProfile = userCache.get(this.profile.getId());
|
||||
+ if (optProfile.isPresent()) {
|
||||
+ GameProfile profile = optProfile.get();
|
||||
+ if (this.profile.getName() == null) {
|
||||
+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't
|
||||
+ copyProfileProperties(this.profile, profile);
|
||||
+ this.profile = profile;
|
||||
+ } else {
|
||||
+ copyProfileProperties(profile, this.profile);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return this.profile.isComplete();
|
||||
+ }
|
||||
+
|
||||
+ public boolean complete(boolean textures) {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ return complete(textures, PaperConfig.isProxyOnlineMode());
|
||||
+ }
|
||||
+ public boolean complete(boolean textures, boolean onlineMode) {
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+
|
||||
+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode);
|
||||
+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) {
|
||||
+ GameProfile result = server.getSessionService().fillProfileProperties(profile, true);
|
||||
+ if (result != null) {
|
||||
+ copyProfileProperties(result, this.profile, true);
|
||||
+ }
|
||||
+ if (this.profile.isComplete()) {
|
||||
+ server.getProfileCache().add(this.profile);
|
||||
+ }
|
||||
+ }
|
||||
+ return profile.isComplete() && (!onlineMode || !textures || hasTextures());
|
||||
+ }
|
||||
+
|
||||
+ private static void copyProfileProperties(GameProfile source, GameProfile target) {
|
||||
+ copyProfileProperties(source, target, false);
|
||||
+ }
|
||||
+
|
||||
+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) {
|
||||
+ PropertyMap sourceProperties = source.getProperties();
|
||||
+ PropertyMap targetProperties = target.getProperties();
|
||||
+ if (clearTarget) targetProperties.clear();
|
||||
+ if (sourceProperties.isEmpty()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (Property property : sourceProperties.values()) {
|
||||
+ targetProperties.removeAll(property.getName());
|
||||
+ targetProperties.put(property.getName(), property);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static ProfileProperty toBukkit(Property property) {
|
||||
+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature());
|
||||
+ }
|
||||
+
|
||||
+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) {
|
||||
+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName());
|
||||
+ copyProfileProperties(gameProfile, profile.profile);
|
||||
+ return profile;
|
||||
+ }
|
||||
+
|
||||
+ public static PlayerProfile asBukkitMirror(GameProfile profile) {
|
||||
+ return new CraftPlayerProfile(profile);
|
||||
+ }
|
||||
+
|
||||
+ public static Property asAuthlib(ProfileProperty property) {
|
||||
+ return new Property(property.getName(), property.getValue(), property.getSignature());
|
||||
+ }
|
||||
+
|
||||
+ public static GameProfile asAuthlibCopy(PlayerProfile profile) {
|
||||
+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile);
|
||||
+ return asAuthlib(craft.clone());
|
||||
+ }
|
||||
+
|
||||
+ public static GameProfile asAuthlib(PlayerProfile profile) {
|
||||
+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile);
|
||||
+ return craft.getGameProfile();
|
||||
+ }
|
||||
+
|
||||
+ private class PropertySet extends AbstractSet<ProfileProperty> {
|
||||
+
|
||||
+ @Override
|
||||
+ @Nonnull
|
||||
+ public Iterator<ProfileProperty> iterator() {
|
||||
+ return new ProfilePropertyIterator(profile.getProperties().values().iterator());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return profile.getProperties().size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean add(ProfileProperty property) {
|
||||
+ setProperty(property);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addAll(Collection<? extends ProfileProperty> c) {
|
||||
+ //noinspection unchecked
|
||||
+ setProperties((Collection<ProfileProperty>) c);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean contains(Object o) {
|
||||
+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName());
|
||||
+ }
|
||||
+
|
||||
+ private class ProfilePropertyIterator implements Iterator<ProfileProperty> {
|
||||
+ private final Iterator<Property> iterator;
|
||||
+
|
||||
+ ProfilePropertyIterator(Iterator<Property> iterator) {
|
||||
+ this.iterator = iterator;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return iterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ProfileProperty next() {
|
||||
+ return toBukkit(iterator.next());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.*;
|
||||
+import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment;
|
||||
+
|
||||
+import java.net.Proxy;
|
||||
+
|
||||
+public class PaperAuthenticationService extends YggdrasilAuthenticationService {
|
||||
+ private final Environment environment;
|
||||
+ public PaperAuthenticationService(Proxy proxy) {
|
||||
+ super(proxy);
|
||||
+ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public UserAuthentication createUserAuthentication(Agent agent) {
|
||||
+ return new PaperUserAuthentication(this, agent);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public MinecraftSessionService createMinecraftSessionService() {
|
||||
+ return new PaperMinecraftSessionService(this, this.environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public GameProfileRepository createProfileRepository() {
|
||||
+ return new PaperGameProfileRepository(this, this.environment);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
@@ -0,0 +1,18 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Agent;
|
||||
+import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.ProfileLookupCallback;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
|
||||
+
|
||||
+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
+ super(authenticationService, environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) {
|
||||
+ super.findProfilesByNames(names, agent, callback);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
@@ -0,0 +1,30 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
|
||||
+
|
||||
+import java.util.Map;
|
||||
+
|
||||
+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService {
|
||||
+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
+ super(authenticationService, environment);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.getTextures(profile, requireSecure);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.fillProfileProperties(profile, requireSecure);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) {
|
||||
+ return super.fillGameProfile(profile, requireSecure);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java
|
||||
@@ -0,0 +1,12 @@
|
||||
+package com.destroystokyo.paper.profile;
|
||||
+
|
||||
+import com.mojang.authlib.Agent;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public class PaperUserAuthentication extends YggdrasilUserAuthentication {
|
||||
+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) {
|
||||
+ super(authenticationService, UUID.randomUUID().toString(), agent);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index f0fed1d2c297d8d2a6903d2caa219b458c5e43c2..aa96017819712f42e16c7eac57222301600b66a5 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
|
||||
import java.lang.ref.Cleaner;
|
||||
@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
@@ -349,6 +352,10 @@ public final class MCUtil {
|
||||
return run.get();
|
||||
}
|
||||
|
||||
+ public static PlayerProfile toBukkit(GameProfile profile) {
|
||||
+ return CraftPlayerProfile.asBukkitMirror(profile);
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Calculates distance between 2 entities
|
||||
* @param e1
|
||||
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
|
||||
index c8385460701395cb5c65fba41335469ffb2d9b9a..fb0b3c5770f66cc3590f5ac4e690a33cb6179be3 100644
|
||||
--- a/src/main/java/net/minecraft/server/Main.java
|
||||
+++ b/src/main/java/net/minecraft/server/Main.java
|
||||
@@ -130,7 +130,7 @@ public class Main {
|
||||
}
|
||||
|
||||
File file = (File) optionset.valueOf("universe"); // CraftBukkit
|
||||
- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY);
|
||||
+ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper
|
||||
MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService();
|
||||
GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository();
|
||||
GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName()));
|
||||
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
index 6e1b7d5b20e9f6ed1b650eb9d6ac9f8c4867b4b7..61405c2b53e03a4b83e2c70c6e4d3739ca9676cb 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -135,6 +135,13 @@ public class GameProfileCache {
|
||||
return this.operationCount.incrementAndGet();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Nullable public GameProfile getProfileIfCached(String name) {
|
||||
+ GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
|
||||
+ return entry == null ? null : entry.getProfile();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public synchronized Optional<GameProfile> get(String name) { // Paper - synchronize
|
||||
String s1 = name.toLowerCase(Locale.ROOT);
|
||||
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index e01f800130f183bf10a383e298b7da3d5f11e3a2..a337967295f61f4892a2ae7dd65aeaba75a06172 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -246,6 +246,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
|
||||
|
||||
+import javax.annotation.Nullable; // Paper
|
||||
+import javax.annotation.Nonnull; // Paper
|
||||
+
|
||||
public final class CraftServer implements Server {
|
||||
private final String serverName = "Paper"; // Paper
|
||||
private final String serverVersion;
|
||||
@@ -2494,5 +2497,24 @@ public final class CraftServer implements Server {
|
||||
public boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||
return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) {
|
||||
+ return createProfile(uuid, null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) {
|
||||
+ return createProfile(null, name);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) {
|
||||
+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null);
|
||||
+ if (player != null) {
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player);
|
||||
+ }
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name);
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
index 9405812b8c308d70de1e26ba55500301b24ecc3c..490df0dcfd0e1e0ab05943410493522f86444ef8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
|
||||
}
|
||||
|
||||
private void setProfile(GameProfile profile) {
|
||||
+ // Paper start
|
||||
+ if (profile != null) {
|
||||
+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile);
|
||||
+ paperProfile.completeFromCache(false, true);
|
||||
+ profile = paperProfile.getGameProfile();
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.profile = profile;
|
||||
this.serializedProfile = (profile == null) ? null : NbtUtils.writeGameProfile(new CompoundTag(), profile);
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 15:18:30 -0400
|
||||
Subject: [PATCH] Shoulder Entities Release API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index a4eb5de429f6934cf6f2b771d62db51e328f8987..193d73c53c7c3cc31246dd19c6d7ff4cb39cac1b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1951,20 +1951,44 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public Entity releaseLeftShoulderEntity() {
|
||||
+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft());
|
||||
+ if (entity != null) {
|
||||
+ this.setShoulderEntityLeft(new CompoundTag());
|
||||
+ }
|
||||
+ return entity;
|
||||
+ }
|
||||
+
|
||||
+ public Entity releaseRightShoulderEntity() {
|
||||
+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight());
|
||||
+ if (entity != null) {
|
||||
+ this.setShoulderEntityRight(new CompoundTag());
|
||||
+ }
|
||||
+ return entity;
|
||||
+ }
|
||||
+ // Paper - maintain old signature
|
||||
private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean
|
||||
- if (!this.level.isClientSide && !nbttagcompound.isEmpty()) {
|
||||
+ return spawnEntityFromShoulder0(nbttagcompound) != null;
|
||||
+ }
|
||||
+
|
||||
+ // Paper - return entity
|
||||
+ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) {
|
||||
+ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) {
|
||||
return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit
|
||||
if (entity instanceof TamableAnimal) {
|
||||
((TamableAnimal) entity).setOwnerUUID(this.uuid);
|
||||
}
|
||||
|
||||
entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ());
|
||||
- return ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit
|
||||
- }).orElse(true); // CraftBukkit
|
||||
+ boolean addedToWorld = ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit
|
||||
+ return addedToWorld ? entity : null;
|
||||
+ }).orElse(null); // CraftBukkit // Paper - false -> null
|
||||
}
|
||||
|
||||
- return true; // CraftBukkit
|
||||
+ return null; // Paper - return null
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public abstract boolean isSpectator();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
index 841dbf4a86b19d7c8ea41930ecb1f88c660fa117..54947f02f29dd3dc546ee0d0f4600630242f003d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
||||
@@ -500,6 +500,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
this.getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() {
|
||||
+ if (!getHandle().getShoulderEntityLeft().isEmpty()) {
|
||||
+ Entity entity = getHandle().releaseLeftShoulderEntity();
|
||||
+ if (entity != null) {
|
||||
+ return entity.getBukkitEntity();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.entity.Entity releaseRightShoulderEntity() {
|
||||
+ if (!getHandle().getShoulderEntityRight().isEmpty()) {
|
||||
+ Entity entity = getHandle().releaseRightShoulderEntity();
|
||||
+ if (entity != null) {
|
||||
+ return entity.getBukkitEntity();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean discoverRecipe(NamespacedKey recipe) {
|
||||
return this.discoverRecipes(Arrays.asList(recipe)) != 0;
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 17 Jun 2017 17:00:32 -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/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.destroystokyo.paper.profile;
|
||||
|
||||
+import com.destroystokyo.paper.event.profile.LookupProfileEvent;
|
||||
+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent;
|
||||
+import com.google.common.collect.Sets;
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.Environment;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
|
||||
|
||||
+import java.util.Set;
|
||||
public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) {
|
||||
super(authenticationService, environment);
|
||||
@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository {
|
||||
|
||||
@Override
|
||||
public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) {
|
||||
- super.findProfilesByNames(names, agent, callback);
|
||||
+ Set<String> unfoundNames = Sets.newHashSet();
|
||||
+ for (String name : names) {
|
||||
+ PreLookupProfileEvent event = new PreLookupProfileEvent(name);
|
||||
+ event.callEvent();
|
||||
+ if (event.getUUID() != null) {
|
||||
+ // Plugin provided UUI, we can skip network call.
|
||||
+ GameProfile gameprofile = new GameProfile(event.getUUID(), name);
|
||||
+ // We might even have properties!
|
||||
+ Set<ProfileProperty> profileProperties = event.getProfileProperties();
|
||||
+ if (!profileProperties.isEmpty()) {
|
||||
+ for (ProfileProperty property : profileProperties) {
|
||||
+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property));
|
||||
+ }
|
||||
+ }
|
||||
+ callback.onProfileLookupSucceeded(gameprofile);
|
||||
+ } else {
|
||||
+ unfoundNames.add(name);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Some things were not found.... Proceed to look up.
|
||||
+ if (!unfoundNames.isEmpty()) {
|
||||
+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]);
|
||||
+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class PreProfileLookupCallback implements ProfileLookupCallback {
|
||||
+ private final ProfileLookupCallback callback;
|
||||
+
|
||||
+ PreProfileLookupCallback(ProfileLookupCallback callback) {
|
||||
+ this.callback = callback;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onProfileLookupSucceeded(GameProfile gameProfile) {
|
||||
+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile);
|
||||
+ new LookupProfileEvent(from).callEvent();
|
||||
+ callback.onProfileLookupSucceeded(gameProfile);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) {
|
||||
+ callback.onProfileLookupFailed(gameProfile, e);
|
||||
+ }
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sun, 2 Jul 2017 21:35:56 -0500
|
||||
Subject: [PATCH] Block player logins during server shutdown
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index a60b40d8cc802456374625af216c27998f8348b3..ab3409dd3a7671b46cba210cfa326311d10a7ef4 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -69,6 +69,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
+ // Paper start - Do not allow logins while the server is shutting down
|
||||
+ if (!MinecraftServer.getServer().isRunning()) {
|
||||
+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) {
|
||||
this.handleAcceptedLogin();
|
||||
} else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
|
|
@ -1,65 +0,0 @@
|
|||
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/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index bf52f5f9b13e8b4eb3c7ee19b0e57bb872d2af1d..3b2334e9ba44205a4e0ec12045eab4fad91bb15a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -322,6 +322,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this);
|
||||
public final boolean defaultActivationState;
|
||||
public long activatedTick = Integer.MIN_VALUE;
|
||||
+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
|
||||
protected int numCollisions = 0; // Paper
|
||||
public void inactiveTick() { }
|
||||
// Spigot end
|
||||
@@ -1868,6 +1869,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
}
|
||||
nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ()));
|
||||
}
|
||||
+ // Save entity's from mob spawner status
|
||||
+ if (spawnedViaMobSpawner) {
|
||||
+ nbt.putBoolean("Paper.FromMobSpawner", true);
|
||||
+ }
|
||||
// Paper end
|
||||
return nbt;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -2007,6 +2012,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
this.originWorld = originWorld;
|
||||
origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2));
|
||||
}
|
||||
+
|
||||
+ spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
|
||||
// Paper end
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index 65744b55f06c225745e3e145e5f5e60ebefd304c..e720c751518af3f38fba0c1b22e4c01a46561b00 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -167,6 +167,7 @@ public abstract class BaseSpawner {
|
||||
}
|
||||
// Spigot End
|
||||
}
|
||||
+ entity.spawnedViaMobSpawner = true; // Paper
|
||||
// Spigot Start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
|
||||
Entity vehicle = entity.getVehicle();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 78b3be2ea6351cb6375b77340218615aa75b87f5..a83d15178f71b1c4c6d8d49f7621eddd66577251 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1192,5 +1192,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
//noinspection ConstantConditions
|
||||
return originVector.toLocation(world);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean fromMobSpawner() {
|
||||
+ return getHandle().spawnedViaMobSpawner;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 10 Dec 2016 16:24:06 -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/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
index 6f473dbf949552afd288382b36223ea036eaa857..27a1ca43792644fc239af81dea5510f25d3328e9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
@@ -5,6 +5,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory;
|
||||
import org.bukkit.entity.AbstractHorse;
|
||||
import org.bukkit.entity.AnimalTamer;
|
||||
import org.bukkit.entity.Horse;
|
||||
@@ -98,6 +99,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac
|
||||
|
||||
@Override
|
||||
public AbstractHorseInventory getInventory() {
|
||||
- return new CraftInventoryAbstractHorse(this.getHandle().inventory);
|
||||
+ return new CraftSaddledInventory(getHandle().inventory);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
index 7013059856c2471dc34112a1a2068b96b809dd96..b72b4260fc1c0e9928d70f97589d8db00849b9e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java
|
||||
@@ -4,7 +4,7 @@ import net.minecraft.world.Container;
|
||||
import org.bukkit.inventory.HorseInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
-public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory {
|
||||
+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory {
|
||||
|
||||
public CraftInventoryHorse(Container inventory) {
|
||||
super(inventory);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3a617c07d445bacf5a13e0e3ff6481823cfc8477
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java
|
||||
@@ -0,0 +1,12 @@
|
||||
+package org.bukkit.craftbukkit.inventory;
|
||||
+
|
||||
+import net.minecraft.world.Container;
|
||||
+import org.bukkit.inventory.SaddledHorseInventory;
|
||||
+
|
||||
+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory {
|
||||
+
|
||||
+ public CraftSaddledInventory(Container inventory) {
|
||||
+ super(inventory);
|
||||
+ }
|
||||
+
|
||||
+}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 22:43:12 -0400
|
||||
Subject: [PATCH] Implement 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/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 69af359e0160480b77886ca35d8f8f3135f06455..73da393b26a7afd766b23716da454b0b68c26d5b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -356,5 +356,11 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) {
|
||||
return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName());
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public ItemStack ensureServerConversions(ItemStack item) {
|
||||
+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 May 2016 23:59:38 -0400
|
||||
Subject: [PATCH] Implement 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.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 73da393b26a7afd766b23716da454b0b68c26d5b..c50d3cee3dfebb62ad30f8d4efe23b5c7c9f2b57 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -362,5 +362,18 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
public ItemStack ensureServerConversions(ItemStack item) {
|
||||
return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public String getI18NDisplayName(ItemStack item) {
|
||||
+ net.minecraft.world.item.ItemStack nms = null;
|
||||
+ if (item instanceof CraftItemStack) {
|
||||
+ nms = ((CraftItemStack) item).handle;
|
||||
+ }
|
||||
+ if (nms == null) {
|
||||
+ nms = CraftItemStack.asNMSCopy(item);
|
||||
+ }
|
||||
+
|
||||
+ return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 3 Jul 2017 18:11:10 -0500
|
||||
Subject: [PATCH] ProfileWhitelistVerifyEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 0eea43c994e76b466fdda8ecd145d0b1c9273cea..17f56157d60d33695c4eac0e4fc94120a2101214 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -615,9 +615,9 @@ public abstract class PlayerList {
|
||||
|
||||
// return chatmessage;
|
||||
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
|
||||
- } else if (!this.isWhiteListed(gameprofile)) {
|
||||
- chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted");
|
||||
- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure
|
||||
+ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper
|
||||
+ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper
|
||||
+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted
|
||||
} else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) {
|
||||
IpBanListEntry ipbanentry = this.ipBans.get(socketaddress);
|
||||
|
||||
@@ -998,9 +998,25 @@ public abstract class PlayerList {
|
||||
this.server.getCommands().sendCommands(player);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
public boolean isWhiteListed(GameProfile profile) {
|
||||
- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile);
|
||||
+ return isWhitelisted(profile, null);
|
||||
}
|
||||
+ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) {
|
||||
+ boolean isOp = this.ops.contains(gameprofile);
|
||||
+ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile);
|
||||
+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage);
|
||||
+ event.callEvent();
|
||||
+ if (!event.isWhitelisted()) {
|
||||
+ if (loginEvent != null) {
|
||||
+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage()));
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public boolean isOp(GameProfile profile) {
|
||||
return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers;
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <kyle@denwav.dev>
|
||||
Date: Sun, 6 Aug 2017 17:17:53 -0500
|
||||
Subject: [PATCH] Fix this stupid bullshit
|
||||
|
||||
Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time.
|
||||
|
||||
modified in order to prevent merge conflicts when Spigot changes/disables the warning,
|
||||
and to provide some level of hint without being disruptive.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
index c7d5018cb6acef12e6da90626c75543ac279a101..64576ddd8363be55755fa50d1c16d95e4e02402d 100644
|
||||
--- a/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
+++ b/src/main/java/net/minecraft/server/Bootstrap.java
|
||||
@@ -42,7 +42,7 @@ public class Bootstrap {
|
||||
public static void bootStrap() {
|
||||
if (!Bootstrap.isBootstrapped) {
|
||||
// CraftBukkit start
|
||||
- String name = Bootstrap.class.getSimpleName();
|
||||
+ /*String name = Bootstrap.class.getSimpleName(); // Paper - actually, I don't think this class should ever have been called DispenserRegistry, that's a stupid name, bootstrap is waaay better
|
||||
switch (name) {
|
||||
case "DispenserRegistry":
|
||||
break;
|
||||
@@ -56,7 +56,7 @@ public class Bootstrap {
|
||||
System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***");
|
||||
System.err.println("**********************************************************************");
|
||||
break;
|
||||
- }
|
||||
+ }*/ // Paper
|
||||
// CraftBukkit end
|
||||
Bootstrap.isBootstrapped = true;
|
||||
if (Registry.REGISTRY.keySet().isEmpty()) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index bbf552bf586de94d8dfc5fb1c18e0af6f75aebe1..1da136f365664d4f8ace3d2d135b19eb97e55304 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -228,10 +228,12 @@ public class Main {
|
||||
Calendar deadline = Calendar.getInstance();
|
||||
deadline.add(Calendar.DAY_OF_YEAR, -28);
|
||||
if (buildDate.before(deadline.getTime())) {
|
||||
- System.err.println("*** Error, this build is outdated ***");
|
||||
+ // Paper start - This is some stupid bullshit
|
||||
+ System.err.println("*** Warning, you've not updated in a while! ***");
|
||||
System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper
|
||||
- System.err.println("*** Server will start in 20 seconds ***");
|
||||
- Thread.sleep(TimeUnit.SECONDS.toMillis(20));
|
||||
+ //System.err.println("*** Server will start in 20 seconds ***");
|
||||
+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20));
|
||||
+ // Paper End
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:49:48 -0500
|
||||
Subject: [PATCH] LivingEntity#setKiller
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index e955126fc82dfcdadb824c8d2d15e8b1f33bc67f..90b70935242757b5c302bac7777eb1428d69619e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -8,6 +8,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
@@ -344,6 +345,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
return this.getHandle().lastHurtByPlayer == null ? null : (Player) this.getHandle().lastHurtByPlayer.getBukkitEntity();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setKiller(Player killer) {
|
||||
+ ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle();
|
||||
+ getHandle().lastHurtByPlayer = entityPlayer;
|
||||
+ getHandle().lastHurtByMob = entityPlayer;
|
||||
+ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean addPotionEffect(PotionEffect effect) {
|
||||
return this.addPotionEffect(effect, false);
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:54:40 -0500
|
||||
Subject: [PATCH] Ocelot despawns should honor nametags and leash
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
index b223b54c80bdc2c9b620e5c9e44cab0c9abdd44c..49122e7baa5c0cd3691bcb48176fdefbdb79026b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -133,7 +133,7 @@ public class Ocelot extends Animal {
|
||||
|
||||
@Override
|
||||
public boolean removeWhenFarAway(double distanceSquared) {
|
||||
- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit
|
||||
+ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
|
@ -1,27 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 31 Jul 2017 01:45:19 -0500
|
||||
Subject: [PATCH] Reset spawner timer when spawner event is cancelled
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index e720c751518af3f38fba0c1b22e4c01a46561b00..14188ac6f158b36755abe23c0a967763cf7367d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -168,6 +168,7 @@ public abstract class BaseSpawner {
|
||||
// Spigot End
|
||||
}
|
||||
entity.spawnedViaMobSpawner = true; // Paper
|
||||
+ flag = true; // Paper
|
||||
// Spigot Start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
|
||||
Entity vehicle = entity.getVehicle();
|
||||
@@ -191,7 +192,7 @@ public abstract class BaseSpawner {
|
||||
((Mob) entity).spawnAnim();
|
||||
}
|
||||
|
||||
- flag = true;
|
||||
+ //flag = true; // Paper - moved up above cancellable event
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Thu, 17 Aug 2017 16:08:20 -0700
|
||||
Subject: [PATCH] Allow specifying a custom "authentication servers down" kick
|
||||
message
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index 7a69f9d9bb9c05474d8fbab22d626529a41a66a1..f4735cc330822183e098a67f2c0f00f21db9e137 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.destroystokyo.paper;
|
||||
|
||||
+import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
import java.io.File;
|
||||
@@ -285,4 +286,9 @@ public class PaperConfig {
|
||||
private static void suggestPlayersWhenNull() {
|
||||
suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions);
|
||||
}
|
||||
+
|
||||
+ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message
|
||||
+ private static void authenticationServersDownKickMessage() {
|
||||
+ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage));
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index ab3409dd3a7671b46cba210cfa326311d10a7ef4..82d0979e3239dddf3951df4a8b65ae7319d3d5b5 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -297,6 +297,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile);
|
||||
ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT;
|
||||
} else {
|
||||
+ // Paper start
|
||||
+ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) {
|
||||
+ ServerLoginPacketListenerImpl.this.disconnect(new TextComponent(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage));
|
||||
+ } else // Paper end
|
||||
ServerLoginPacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down"));
|
||||
ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable");
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Thu, 21 Sep 2017 16:14:55 +0200
|
||||
Subject: [PATCH] Handle plugin prefixes using Log4J configuration
|
||||
|
||||
Display logger name in the console for all loggers except the
|
||||
root logger, Bukkit's logger ("Minecraft") and Minecraft loggers.
|
||||
Since plugins now use the plugin name as logger name this will
|
||||
restore the plugin prefixes without having to prepend them manually
|
||||
to the log messages.
|
||||
|
||||
Logger prefixes are shown by default for all loggers except for
|
||||
the root logger, the Minecraft/Mojang loggers and the Bukkit loggers.
|
||||
This may cause additional prefixes to be disabled for plugins bypassing
|
||||
the plugin logger.
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 9b70376813531718c02082633e9f8105f4879a63..fc8ffeea3e808eb1381f85972adffc614937ef6d 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -25,7 +25,7 @@ dependencies {
|
||||
all its classes to check if they are plugins.
|
||||
Scanning takes about 1-2 seconds so adding this speeds up the server start.
|
||||
*/
|
||||
- runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1")
|
||||
+ implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
|
||||
// Paper end
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
|
||||
implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index f8a9d6a394f796634e4663ef4078a4c98447e13c..d73dfe72a54b621c0f944c90904df3e3bc709445 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -290,7 +290,7 @@ public class SpigotConfig
|
||||
private static void playerSample()
|
||||
{
|
||||
SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 );
|
||||
- System.out.println( "Server Ping Player Sample Count: " + SpigotConfig.playerSample );
|
||||
+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger
|
||||
}
|
||||
|
||||
public static int playerShuffle;
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -5,10 +5,22 @@
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
</Queue>
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
- <PatternLayout pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
</TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
+ pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<OnStartupTriggeringPolicy />
|
|
@ -1,47 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Sat, 23 Sep 2017 21:07:20 +0200
|
||||
Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers
|
||||
|
||||
Add full exceptions to log4j to not truncate stack traces
|
||||
|
||||
Disable logger prefix for various plugins bypassing the plugin logger
|
||||
|
||||
Some plugins bypass the plugin logger and add the plugin prefix
|
||||
manually to the log message. Since they use other logger names
|
||||
(e.g. qualified class names) these would now also appear in the
|
||||
log. Disable the logger prefix for these plugins so the messages
|
||||
show up correctly.
|
||||
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -6,19 +6,21 @@
|
||||
</Queue>
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
<PatternLayout>
|
||||
- <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx{full}}">
|
||||
<!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
- <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
- pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx{full}}" />
|
||||
</LoggerNamePatternSelector>
|
||||
</PatternLayout>
|
||||
</TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout>
|
||||
- <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n">
|
||||
+ <LoggerNamePatternSelector defaultPattern="[%d{HH:mm:ss}] [%t/%level]: [%logger] %minecraftFormatting{%msg}{strip}%n%xEx{full}">
|
||||
<!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
- <PatternMatch key=",net.minecraft.,Minecraft,com.mojang."
|
||||
- pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n" />
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="[%d{HH:mm:ss}] [%t/%level]: %minecraftFormatting{%msg}{strip}%n%xEx{full}" />
|
||||
</LoggerNamePatternSelector>
|
||||
</PatternLayout>
|
||||
<Policies>
|
|
@ -1,46 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Thu, 28 Sep 2017 17:21:44 -0400
|
||||
Subject: [PATCH] Add PlayerJumpEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 41f1b355a8a90216964e89432244a7d6929c9152..7759bf2afb9edeaca24726aace9358a8d5eafc64 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1174,7 +1174,34 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
boolean flag = d8 > 0.0D;
|
||||
|
||||
if (this.player.isOnGround() && !packet.isOnGround() && flag) {
|
||||
- this.player.jumpFromGround();
|
||||
+ // Paper start - Add player jump event
|
||||
+ Player player = this.getCraftPlayer();
|
||||
+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
|
||||
+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
|
||||
+
|
||||
+ // If the packet contains movement information then we update the To location with the correct XYZ.
|
||||
+ if (packet.hasPos) {
|
||||
+ to.setX(packet.x);
|
||||
+ to.setY(packet.y);
|
||||
+ to.setZ(packet.z);
|
||||
+ }
|
||||
+
|
||||
+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch.
|
||||
+ if (packet.hasRot) {
|
||||
+ to.setYaw(packet.yRot);
|
||||
+ to.setPitch(packet.xRot);
|
||||
+ }
|
||||
+
|
||||
+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to);
|
||||
+
|
||||
+ if (event.callEvent()) {
|
||||
+ this.player.jumpFromGround();
|
||||
+ } else {
|
||||
+ from = event.getFrom();
|
||||
+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet(), false);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9));
|
|
@ -1,40 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 5 Oct 2017 01:54:07 +0100
|
||||
Subject: [PATCH] handle PacketPlayInKeepAlive async
|
||||
|
||||
In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main
|
||||
thread, while entirely correct for the server, this causes issues with
|
||||
plugins which are expecting the PlayerQuitEvent on the main thread.
|
||||
|
||||
In order to counteract some bad behavior, we will post handling of the
|
||||
disconnection to the main thread, but leave the actual processing of the packet
|
||||
off the main thread.
|
||||
|
||||
also adding some additional logging in order to help work out what is causing
|
||||
random disconnections for clients.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 89588d6478ebd7d4892dceb03026dff89e1844db..7b6e6e646511bc47d2215c512b4d839b3f3a1c55 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2771,14 +2771,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // CraftBukkit
|
||||
+ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread
|
||||
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||
int i = (int) (Util.getMillis() - this.keepAliveTime);
|
||||
|
||||
this.player.latency = (this.player.latency * 3 + i) / 4;
|
||||
this.keepAlivePending = false;
|
||||
} else if (!this.isSingleplayerOwner()) {
|
||||
+ // Paper start - This needs to be handled on the main thread for plugins
|
||||
+ server.submit(() -> {
|
||||
this.disconnect(new TranslatableComponent("disconnect.timeout"));
|
||||
+ });
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Tue, 10 Oct 2017 18:45:20 +0200
|
||||
Subject: [PATCH] Expose client protocol version and virtual host
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a5a7624f1f372a26b982836cd31cff15e2589e9b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java
|
||||
@@ -0,0 +1,49 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import java.net.InetSocketAddress;
|
||||
+
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.network.Connection;
|
||||
+
|
||||
+public class PaperNetworkClient implements NetworkClient {
|
||||
+
|
||||
+ private final Connection networkManager;
|
||||
+
|
||||
+ PaperNetworkClient(Connection networkManager) {
|
||||
+ this.networkManager = networkManager;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InetSocketAddress getAddress() {
|
||||
+ return (InetSocketAddress) this.networkManager.getRemoteAddress();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getProtocolVersion() {
|
||||
+ return this.networkManager.protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public InetSocketAddress getVirtualHost() {
|
||||
+ return this.networkManager.virtualHost;
|
||||
+ }
|
||||
+
|
||||
+ public static InetSocketAddress prepareVirtualHost(String host, int port) {
|
||||
+ int len = host.length();
|
||||
+
|
||||
+ // FML appends a marker to the host to recognize FML clients (\0FML\0)
|
||||
+ int pos = host.indexOf('\0');
|
||||
+ if (pos >= 0) {
|
||||
+ len = pos;
|
||||
+ }
|
||||
+
|
||||
+ // When clients connect with a SRV record, their host contains a trailing '.'
|
||||
+ if (len > 0 && host.charAt(len - 1) == '.') {
|
||||
+ len--;
|
||||
+ }
|
||||
+
|
||||
+ return InetSocketAddress.createUnresolved(host.substring(0, len), port);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index b62e373445406ae84b37ec0570ebb1da02cff0b7..06e965996a5c50bce617847e594ae0dd83403484 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -83,6 +83,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
private float averageSentPackets;
|
||||
private int tickCount;
|
||||
private boolean handlingFault;
|
||||
+ // Paper start - NetworkClient implementation
|
||||
+ public int protocolVersion;
|
||||
+ public java.net.InetSocketAddress virtualHost;
|
||||
+ // Paper end
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
index c4ba069f5124ec151e05813beddf293fddc3b804..484221e5a9c246aa91e0eacef3911b0e9ecff401 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -150,6 +150,10 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
|
||||
throw new UnsupportedOperationException("Invalid intention " + packet.getIntention());
|
||||
}
|
||||
|
||||
+ // Paper start - NetworkClient implementation
|
||||
+ this.connection.protocolVersion = packet.getProtocolVersion();
|
||||
+ this.connection.virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(packet.hostName, packet.port);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 4233f5ffa673801c57e3f929cd9ae919d6c7169f..e5e12d1672588138e4f56007fcdd14a1bb8ec1ca 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -193,6 +193,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Implement NetworkClient
|
||||
+ @Override
|
||||
+ public int getProtocolVersion() {
|
||||
+ if (getHandle().connection == null) return -1;
|
||||
+ return getHandle().connection.connection.protocolVersion;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InetSocketAddress getVirtualHost() {
|
||||
+ if (getHandle().connection == null) return null;
|
||||
+ return getHandle().connection.connection.virtualHost;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public double getEyeHeight(boolean ignorePose) {
|
||||
if (ignorePose) {
|
|
@ -1,77 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 15 Oct 2017 00:29:07 +0100
|
||||
Subject: [PATCH] revert serverside behavior of keepalives
|
||||
|
||||
This patch intends to bump up the time that a client has to reply to the
|
||||
server back to 30 seconds as per pre 1.12.2, which allowed clients
|
||||
more than enough time to reply potentially allowing them to be less
|
||||
tempermental due to lag spikes on the network thread, e.g. that caused
|
||||
by plugins that are interacting with netty.
|
||||
|
||||
We also add a system property to allow people to tweak how long the server
|
||||
will wait for a reply. There is a compromise here between lower and higher
|
||||
values, lower values will mean that dead connections can be closed sooner,
|
||||
whereas higher values will make this less sensitive to issues such as spikes
|
||||
from networking or during connections flood of chunk packets on slower clients,
|
||||
at the cost of dead connections being kept open for longer.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 652703b1582e63148658a3a9d2604afa55674c23..cf42d59254f2786bfe8785249ad270d35996417a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -221,9 +221,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
private final MinecraftServer server;
|
||||
public ServerPlayer player;
|
||||
private int tickCount;
|
||||
- private long keepAliveTime; @Deprecated private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; @Deprecated private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER
|
||||
- private boolean keepAlivePending; @Deprecated private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; @Deprecated private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER
|
||||
- private long keepAliveChallenge; @Deprecated private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; @Deprecated private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER
|
||||
+ private long keepAliveTime = Util.getMillis();
|
||||
+ private boolean keepAlivePending;
|
||||
+ private long keepAliveChallenge;
|
||||
// CraftBukkit start - multithreaded fields
|
||||
private AtomicInteger chatSpamTickCount = new AtomicInteger();
|
||||
// CraftBukkit end
|
||||
@@ -252,6 +252,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
private int aboveGroundVehicleTickCount;
|
||||
private int receivedMovePacketCount;
|
||||
private int knownMovePacketCount;
|
||||
+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
|
||||
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
|
||||
this.server = server;
|
||||
@@ -334,18 +335,25 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
}
|
||||
|
||||
this.server.getProfiler().push("keepAlive");
|
||||
- long i = Util.getMillis();
|
||||
-
|
||||
- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit
|
||||
- if (this.keepAlivePending) {
|
||||
- this.disconnect(new TranslatableComponent("disconnect.timeout"));
|
||||
- } else {
|
||||
+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||
+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2
|
||||
+ long currentTime = Util.getMillis();
|
||||
+ long elapsedTime = currentTime - this.keepAliveTime;
|
||||
+
|
||||
+ if (this.keepAlivePending) {
|
||||
+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info
|
||||
+ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]));
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (elapsedTime >= 15000L) { // 15 seconds
|
||||
this.keepAlivePending = true;
|
||||
- this.keepAliveTime = i;
|
||||
- this.keepAliveChallenge = i;
|
||||
+ this.keepAliveTime = currentTime;
|
||||
+ this.keepAliveChallenge = currentTime;
|
||||
this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
this.server.getProfiler().pop();
|
||||
// CraftBukkit start
|
|
@ -1,80 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brokkonaut <hannos17@gmx.de>
|
||||
Date: Tue, 31 Oct 2017 03:26:18 +0100
|
||||
Subject: [PATCH] Send attack SoundEffects only to players who can see the
|
||||
attacker
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index 193d73c53c7c3cc31246dd19c6d7ff4cb39cac1b..8c20af91c9298cb36fdb2700d042b1e2fccf5f54 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
|
||||
+import net.minecraft.network.protocol.game.ClientboundSoundPacket;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
@@ -1181,7 +1182,7 @@ public abstract class Player extends LivingEntity {
|
||||
int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this);
|
||||
|
||||
if (this.isSprinting() && flag) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
++i;
|
||||
flag1 = true;
|
||||
}
|
||||
@@ -1256,7 +1257,7 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
this.sweepAttack();
|
||||
}
|
||||
|
||||
@@ -1284,15 +1285,15 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
|
||||
if (flag2) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
this.crit(target);
|
||||
}
|
||||
|
||||
if (!flag2 && !flag3) {
|
||||
if (flag) {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
} else {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1344,7 +1345,7 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value
|
||||
} else {
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F);
|
||||
+ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility
|
||||
if (flag4) {
|
||||
target.clearFire();
|
||||
}
|
||||
@@ -1791,6 +1792,14 @@ public abstract class Player extends LivingEntity {
|
||||
public int getXpNeededForNextLevel() {
|
||||
return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
|
||||
}
|
||||
+ // Paper start - send SoundEffect to everyone who can see fromEntity
|
||||
+ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) {
|
||||
+ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself
|
||||
+ if (fromEntity instanceof ServerPlayer) {
|
||||
+ ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public void causeFoodExhaustion(float exhaustion) {
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: pkt77 <parkerkt77@gmail.com>
|
||||
Date: Fri, 10 Nov 2017 23:46:34 -0500
|
||||
Subject: [PATCH] Add PlayerArmorChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 5f24963bd2681cab15d20221154a9a758be53b03..375959ed616596e604dc07d3b30d708b08d7ce57 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.minecraft.world.entity;
|
||||
|
||||
+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -2941,6 +2942,13 @@ public abstract class LivingEntity extends Entity {
|
||||
ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
|
||||
|
||||
if (!ItemStack.matches(itemstack1, itemstack)) {
|
||||
+ // Paper start - PlayerArmorChangeEvent
|
||||
+ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) {
|
||||
+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack);
|
||||
+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1);
|
||||
+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent();
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (map == null) {
|
||||
map = Maps.newEnumMap(EquipmentSlot.class);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: killme <killme-git@ibts.me>
|
||||
Date: Sun, 12 Nov 2017 19:40:01 +0100
|
||||
Subject: [PATCH] Prevent logins from being processed when the player has
|
||||
disconnected
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 82d0979e3239dddf3951df4a8b65ae7319d3d5b5..109d7f1bf37e442ff80f7f63d50e27e6e30e0b5e 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -76,7 +76,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
}
|
||||
// Paper end
|
||||
if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) {
|
||||
- this.handleAcceptedLogin();
|
||||
+ // Paper start - prevent logins to be processed even though disconnect was called
|
||||
+ if (connection.isConnected()) {
|
||||
+ this.handleAcceptedLogin();
|
||||
+ }
|
||||
+ // Paper end
|
||||
} else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
|
||||
ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId());
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mezz <tehgeek@gmail.com>
|
||||
Date: Wed, 9 Aug 2017 17:51:22 -0500
|
||||
Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index acfa844c87e5814c033cad4318813800f57885fd..b327e10a5708d523b9d4a6c77c1359521f2927d5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -730,6 +730,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// Spigot start
|
||||
// Iterator iterator = this.blockEntityTickers.iterator();
|
||||
int tilesThisCycle = 0;
|
||||
+ var toRemove = new it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet<TickingBlockEntity>(net.minecraft.Util.identityStrategy()); // Paper - use removeAll
|
||||
+ toRemove.add(null);
|
||||
for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
|
||||
this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
|
||||
TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(tileTickPosition);
|
||||
@@ -737,7 +739,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (tickingblockentity == null) {
|
||||
this.getCraftServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash");
|
||||
tilesThisCycle--;
|
||||
- this.blockEntityTickers.remove(this.tileTickPosition--);
|
||||
continue;
|
||||
}
|
||||
// Spigot end
|
||||
@@ -745,12 +746,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (tickingblockentity.isRemoved()) {
|
||||
// Spigot start
|
||||
tilesThisCycle--;
|
||||
- this.blockEntityTickers.remove(this.tileTickPosition--);
|
||||
+ toRemove.add(tickingblockentity); // Paper - use removeAll
|
||||
// Spigot end
|
||||
} else {
|
||||
tickingblockentity.tick();
|
||||
}
|
||||
}
|
||||
+ this.blockEntityTickers.removeAll(toRemove);
|
||||
|
||||
timings.tileEntityTick.stopTiming(); // Spigot
|
||||
this.tickingBlockEntities = false;
|
|
@ -1,60 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 16 Nov 2017 12:12:41 +0000
|
||||
Subject: [PATCH] use CB BlockState implementations for captured blocks
|
||||
|
||||
When modifying the world, CB will store a copy of the affected
|
||||
blocks in order to restore their state in the case that the event
|
||||
is cancelled. This change only modifies the collection of blocks
|
||||
in the world by normal means, e.g. not during tree population,
|
||||
as the potentially marginal overheads would serve no advantage.
|
||||
|
||||
CB was using a CraftBlockState for all blocks, which causes issues
|
||||
should any block that uses information beyond a data ID would suffer
|
||||
from missing information, e.g. Skulls.
|
||||
|
||||
By using CBs CraftBlock#getState(), we will maintain a proper copy of
|
||||
the blockstate that will be valid for restoration, as opposed to dropping
|
||||
information on restoration when the event is cancelled.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index b327e10a5708d523b9d4a6c77c1359521f2927d5..233a8fcfae4ac568ad1f73cc61d8ae5b66a01ac2 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -141,7 +141,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
|
||||
public boolean captureBlockStates = false;
|
||||
public boolean captureTreeGeneration = false;
|
||||
- public Map<BlockPos, CapturedBlockState> capturedBlockStates = new java.util.LinkedHashMap<>();
|
||||
+ public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
|
||||
public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>();
|
||||
public List<ItemEntity> captureDrops;
|
||||
public long ticksPerAnimalSpawns;
|
||||
@@ -361,7 +361,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
||||
// CraftBukkit start - tree generation
|
||||
if (this.captureTreeGeneration) {
|
||||
- CapturedBlockState blockstate = this.capturedBlockStates.get(pos);
|
||||
+ CraftBlockState blockstate = this.capturedBlockStates.get(pos);
|
||||
if (blockstate == null) {
|
||||
blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
|
||||
this.capturedBlockStates.put(pos.immutable(), blockstate);
|
||||
@@ -381,7 +381,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// CraftBukkit start - capture blockstates
|
||||
boolean captured = false;
|
||||
if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) {
|
||||
- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags);
|
||||
+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot
|
||||
+ blockstate.setFlag(flags); // Paper - set flag
|
||||
this.capturedBlockStates.put(pos.immutable(), blockstate);
|
||||
captured = true;
|
||||
}
|
||||
@@ -650,7 +651,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
// CraftBukkit start - tree generation
|
||||
if (this.captureTreeGeneration) {
|
||||
- CapturedBlockState previous = this.capturedBlockStates.get(pos);
|
||||
+ CraftBlockState previous = this.capturedBlockStates.get(pos); // Paper
|
||||
if (previous != null) {
|
||||
return previous.getHandle();
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 6 Nov 2017 21:08:22 -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
|
||||
|
||||
also Avoid NPE during CraftBlockEntityState load if could not get TE
|
||||
|
||||
If Tile Entity was null, correct Sign to return empty lines instead of null
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 27895fbe1cd7ee6ee025ed3e320671e3e971764d..1d1764766d2b4a0b7bf4078ce428bb1474f709df 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -42,6 +42,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
|
||||
this.type = type;
|
||||
this.worldPosition = pos.immutable();
|
||||
this.blockState = state;
|
||||
+ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -79,7 +80,7 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
|
||||
|
||||
// CraftBukkit start - read container
|
||||
public void load(CompoundTag nbt) {
|
||||
- this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY);
|
||||
+ this.persistentDataContainer.clear(); // Paper - clear instead of init
|
||||
|
||||
net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues");
|
||||
if (persistentDataTag instanceof CompoundTag) {
|
||||
@@ -222,10 +223,15 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
|
||||
|
||||
// CraftBukkit start - add method
|
||||
public InventoryHolder getOwner() {
|
||||
+ // Paper start
|
||||
+ return getOwner(true);
|
||||
+ }
|
||||
+ public InventoryHolder getOwner(boolean useSnapshot) {
|
||||
+ // Paper end
|
||||
if (this.level == null) return null;
|
||||
org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
if (block.getType() == org.bukkit.Material.AIR) return null;
|
||||
- org.bukkit.block.BlockState state = block.getState();
|
||||
+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
|
||||
if (state instanceof InventoryHolder) return (InventoryHolder) state;
|
||||
return null;
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index e6b8dd52cd503f45ca9bb868891ae4c8b29b3fcb..f1c4c3a3392c2d4d836fa10d7a38558d08084d9d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -314,7 +314,20 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public BlockState getState() {
|
||||
+ // Paper start
|
||||
+ return this.getState(true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public BlockState getState(boolean useSnapshot) {
|
||||
+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
|
||||
+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
|
||||
+ try {
|
||||
return CraftBlockStates.getBlockState(this);
|
||||
+ } finally {
|
||||
+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
index 2fb445e6edc43eb8e3e169cca3fc3b46ced94202..059a122ef7038f7c4e269b476eb6e013b3eb4531 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
@@ -10,15 +10,26 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
|
||||
|
||||
private final T tileEntity;
|
||||
private final T snapshot;
|
||||
+ public final boolean snapshotDisabled; // Paper
|
||||
+ public static boolean DISABLE_SNAPSHOT = false; // Paper
|
||||
|
||||
public CraftBlockEntityState(World world, T tileEntity) {
|
||||
super(world, tileEntity.getBlockPos(), tileEntity.getBlockState());
|
||||
|
||||
this.tileEntity = tileEntity;
|
||||
|
||||
+ // Paper start
|
||||
+ this.snapshotDisabled = DISABLE_SNAPSHOT;
|
||||
+ if (DISABLE_SNAPSHOT) {
|
||||
+ this.snapshot = this.tileEntity;
|
||||
+ } else {
|
||||
+ this.snapshot = this.createSnapshot(tileEntity);
|
||||
+ }
|
||||
// copy tile entity data:
|
||||
- this.snapshot = this.createSnapshot(tileEntity);
|
||||
- this.load(snapshot);
|
||||
+ if (this.snapshot != null) {
|
||||
+ this.load(this.snapshot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void refreshSnapshot() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
index ddd7b63f0452042baa3fca04bb9fbdb42fcecbfd..b638351581fa09c488425a2318b782a5812140ce 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
|
||||
@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
|
||||
public Map<String, Object> serialize() {
|
||||
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(this.toTagCompound());
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public void clear() {
|
||||
+ this.customDataTags.clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 26 Nov 2017 13:19:58 -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.
|
||||
|
||||
Also adds isCommand and getLocation to the sync TabCompleteEvent
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index cf42d59254f2786bfe8785249ad270d35996417a..8c2242d7e443bee26741608c65d314d8902f5765 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -702,10 +702,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
|
||||
@Override
|
||||
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
|
||||
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
|
||||
+ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async
|
||||
// CraftBukkit start
|
||||
if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
|
||||
- this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]));
|
||||
+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -715,12 +715,35 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
stringreader.skip();
|
||||
}
|
||||
|
||||
- ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
|
||||
+ // Paper start - async tab completion
|
||||
+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event;
|
||||
+ java.util.List<String> completions = new java.util.ArrayList<>();
|
||||
+ String buffer = packet.getCommand();
|
||||
+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions,
|
||||
+ buffer, true, null);
|
||||
+ event.callEvent();
|
||||
+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions();
|
||||
+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server
|
||||
+ if (!event.isHandled()) {
|
||||
+ if (!event.isCancelled()) {
|
||||
+
|
||||
+ this.server.scheduleOnMain(() -> { // Paper - This needs to be on main
|
||||
+ ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
|
||||
|
||||
- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
|
||||
- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
|
||||
- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions));
|
||||
- });
|
||||
+ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
|
||||
+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [<args>] from showing for plugins with nothing more to offer
|
||||
+ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions));
|
||||
+ });
|
||||
+ });
|
||||
+ }
|
||||
+ } else if (!completions.isEmpty()) {
|
||||
+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength());
|
||||
+
|
||||
+ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1);
|
||||
+ completions.forEach(builder::suggest);
|
||||
+ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join()));
|
||||
+ }
|
||||
+ // Paper end - async tab completion
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index a337967295f61f4892a2ae7dd65aeaba75a06172..435a68e6c99bffdc8d6ded9deda68d4e970a2d49 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2015,7 +2015,7 @@ public final class CraftServer implements Server {
|
||||
offers = this.tabCompleteChat(player, message);
|
||||
}
|
||||
|
||||
- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers);
|
||||
+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper
|
||||
this.getPluginManager().callEvent(tabEvent);
|
||||
|
||||
return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
index b996fde481cebbbcce80a6c267591136db7cc0bc..e5af155d75f717d33c23e22ff8b96bb3ff87844d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
|
||||
@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer {
|
||||
public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {
|
||||
final CraftServer server = this.server.server;
|
||||
final String buffer = line.line();
|
||||
+ // Async Tab Complete
|
||||
+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event;
|
||||
+ java.util.List<String> completions = new java.util.ArrayList<>();
|
||||
+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions,
|
||||
+ buffer, true, null);
|
||||
+ event.callEvent();
|
||||
+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions();
|
||||
+
|
||||
+ if (event.isCancelled() || event.isHandled()) {
|
||||
+ // Still fire sync event with the provided completions, if someone is listening
|
||||
+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ List<String> finalCompletions = completions;
|
||||
+ Waitable<List<String>> syncCompletions = new Waitable<List<String>>() {
|
||||
+ @Override
|
||||
+ protected List<String> evaluate() {
|
||||
+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions);
|
||||
+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of();
|
||||
+ }
|
||||
+ };
|
||||
+ server.getServer().processQueue.add(syncCompletions);
|
||||
+ try {
|
||||
+ completions = syncCompletions.get();
|
||||
+ } catch (InterruptedException | ExecutionException e1) {
|
||||
+ e1.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!completions.isEmpty()) {
|
||||
+ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList()));
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Paper end
|
||||
Waitable<List<String>> waitable = new Waitable<List<String>>() {
|
||||
@Override
|
|
@ -1,20 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 19 Dec 2017 22:02:53 -0500
|
||||
Subject: [PATCH] PlayerPickupExperienceEvent
|
||||
|
||||
Allows plugins to cancel a player picking up an experience orb
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
index 5220e3ee9fab4c4cbc95e0cf1928392316a35e34..1fdfeaa7758497e93fc13b44996e11d74a812546 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -300,7 +300,7 @@ public class ExperienceOrb extends Entity {
|
||||
@Override
|
||||
public void playerTouch(Player player) {
|
||||
if (!this.level.isClientSide) {
|
||||
- if (player.takeXpDelay == 0) {
|
||||
+ if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper
|
||||
player.takeXpDelay = 2;
|
||||
player.take(this, 1);
|
||||
int i = this.repairPlayerItems(player, this.value);
|
|
@ -1,87 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 20 Dec 2017 17:36:49 -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/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
index 6f25e9f41d93a225acaa6575954967438a6cabbf..d439e8ce87bf7da03683a336941c7673b8b166e4 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
@@ -270,8 +270,11 @@ public class EnchantmentHelper {
|
||||
return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0;
|
||||
}
|
||||
|
||||
- @Nullable
|
||||
- public static Entry<EquipmentSlot, ItemStack> getRandomItemWith(Enchantment enchantment, LivingEntity entity) {
|
||||
+ @Deprecated public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) {
|
||||
+ Entry<EquipmentSlot, ItemStack> entry = getRandomItemWith(enchantment, entityliving);
|
||||
+ return entry != null ? entry.getValue() : ItemStack.EMPTY;
|
||||
+ } // Paper - OBFHELPER
|
||||
+ @Nullable public static Entry<EquipmentSlot, ItemStack> getRandomItemWith(Enchantment enchantment, LivingEntity entity) {
|
||||
return getRandomItemWith(enchantment, entity, (stack) -> {
|
||||
return true;
|
||||
});
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 6b8ee829306ad22f52844ba29bf2a549558048bd..4c8617fbd2cd8e34c87634fe448d204ee7fb8a0f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -61,11 +61,14 @@ import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.server.players.UserWhiteListEntry;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
+import net.minecraft.world.entity.ExperienceOrb;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeMap;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
+import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
+import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||
@@ -1216,8 +1219,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
return GameMode.getByValue(this.getHandle().gameMode.getGameModeForPlayer().getId());
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public int applyMending(int amount) {
|
||||
+ ServerPlayer handle = getHandle();
|
||||
+ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties
|
||||
+ net.minecraft.world.item.ItemStack itemstack = EnchantmentHelper.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle);
|
||||
+ if (!itemstack.isEmpty() && itemstack.getItem().canBeDepleted()) {
|
||||
+
|
||||
+ ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level);
|
||||
+ orb.value = amount;
|
||||
+ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM;
|
||||
+ orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ());
|
||||
+
|
||||
+ int i = Math.min(orb.xpToDurability(amount), itemstack.getDamageValue());
|
||||
+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i);
|
||||
+ i = event.getRepairAmount();
|
||||
+ orb.discard();
|
||||
+ if (!event.isCancelled()) {
|
||||
+ amount -= orb.durabilityToXp(i);
|
||||
+ itemstack.setDamageValue(itemstack.getDamageValue() - i);
|
||||
+ }
|
||||
+ }
|
||||
+ return amount;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
- public void giveExp(int exp) {
|
||||
+ public void giveExp(int exp, boolean applyMending) {
|
||||
+ if (applyMending) {
|
||||
+ exp = this.applyMending(exp);
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.getHandle().giveExperiencePoints(exp);
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 14 Jan 2018 17:36:02 -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/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 4a2739edb01c97c99524dc96decbdcb12e0b7d4f..5e53ef4b71969737f900063ab631f4a1ce74cb90 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1024,11 +1024,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
chunkRange = (chunkRange > 8) ? 8 : chunkRange;
|
||||
|
||||
- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D;
|
||||
+ final int finalChunkRange = chunkRange; // Paper for lambda below
|
||||
+ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event
|
||||
// Spigot end
|
||||
long i = chunkcoordintpair.toLong();
|
||||
|
||||
return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> {
|
||||
+ // Paper start - add PlayerNaturallySpawnCreaturesEvent
|
||||
+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
|
||||
+ double blockRange = 16384.0D;
|
||||
+ if (reducedRange) {
|
||||
+ event = entityplayer.playerNaturallySpawnedEvent;
|
||||
+ if (event == null || event.isCancelled()) return false;
|
||||
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
|
||||
+ }
|
||||
+ // Paper end
|
||||
return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot
|
||||
});
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 3e2a5f83afcc3b9c9fe62748895d489135af03bf..1f3fe980e71c13b5e7852349cba1cb0e4aa42dcd 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -791,6 +791,15 @@ public class ServerChunkCache extends ChunkSource {
|
||||
List<ChunkHolder> list = Lists.newArrayList(this.chunkMap.getChunks());
|
||||
|
||||
Collections.shuffle(list);
|
||||
+ // Paper start - call player naturally spawn event
|
||||
+ int chunkRange = level.spigotConfig.mobSpawnRange;
|
||||
+ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
+ chunkRange = Math.min(chunkRange, 8);
|
||||
+ for (ServerPlayer entityPlayer : this.level.players()) {
|
||||
+ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
|
||||
+ entityPlayer.playerNaturallySpawnedEvent.callEvent();
|
||||
+ };
|
||||
+ // Paper end
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
list.forEach((playerchunk) -> {
|
||||
Optional<LevelChunk> optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index d4614faa22485dce226f3dc17ef984212ac8fcb9..66434418fae67ff63450bc246796c7f3d4d09ae6 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.minecraft.server.level;
|
||||
|
||||
+import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
@@ -233,6 +234,7 @@ public class ServerPlayer extends Player {
|
||||
public boolean sentListPacket = false;
|
||||
public Integer clientViewDistance;
|
||||
// CraftBukkit end
|
||||
+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
||||
|
||||
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 14 Jan 2018 17:01:31 -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/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
index 28f1a53a2b9ebe9948509dabbf1a4ae84d8e147c..345ecbc7fc080e8581d285b638db1ee6e684010a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
@@ -335,6 +335,20 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T> {
|
||||
|
||||
@Nullable
|
||||
public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper start - Call PreCreatureSpawnEvent
|
||||
+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath());
|
||||
+ if (type != null) {
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ net.minecraft.server.MCUtil.toLocation(worldserver, blockposition),
|
||||
+ type,
|
||||
+ spawnReason
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1);
|
||||
|
||||
if (t0 != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
index 3839bacbd5f4d06eb13d0e604651232d9fbd7b6a..206aee8bf14ffc4ddbb8a7001bc3baae6a2ea849 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -987,6 +987,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1);
|
||||
|
||||
if (blockposition1 != null) {
|
||||
+ // Paper start - Call PreCreatureSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ net.minecraft.server.MCUtil.toLocation(level, blockposition1),
|
||||
+ org.bukkit.entity.EntityType.IRON_GOLEM,
|
||||
+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one
|
||||
+ return null;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ // Paper end
|
||||
IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false);
|
||||
|
||||
if (entityirongolem != null) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
index 14188ac6f158b36755abe23c0a967763cf7367d8..572328fafb2347886900352983fd5b6490b0dd68 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -133,6 +133,27 @@ public abstract class BaseSpawner {
|
||||
double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D;
|
||||
|
||||
if (world.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) {
|
||||
+ // Paper start
|
||||
+ EntityType<?> entityType = optional.get();
|
||||
+ String key = EntityType.getKey(entityType).getPath();
|
||||
+
|
||||
+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key);
|
||||
+ if (type != null) {
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
|
||||
+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2),
|
||||
+ type,
|
||||
+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ flag = true;
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ break;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> {
|
||||
entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot());
|
||||
return entity1;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 0432ad7ab00c336e7c566f24c3ec92b399cb6e9d..ca0fcf46e67deb07a3fdb071b771a7603e0fc3d0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -236,7 +236,13 @@ public final class NaturalSpawner {
|
||||
j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount);
|
||||
}
|
||||
|
||||
- if (NaturalSpawner.isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
|
||||
+ // Paper start
|
||||
+ Boolean doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
||||
+ if (doSpawning == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
|
||||
+ // Paper end
|
||||
Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
|
||||
|
||||
if (entityinsentient == null) {
|
||||
@@ -283,9 +289,25 @@ public final class NaturalSpawner {
|
||||
return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos));
|
||||
}
|
||||
|
||||
- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
|
||||
+ private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper
|
||||
EntityType<?> entitytypes = spawnEntry.type;
|
||||
|
||||
+ // Paper start
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
|
||||
+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath());
|
||||
+ if (type != null) {
|
||||
+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ net.minecraft.server.MCUtil.toLocation(world, pos),
|
||||
+ type, SpawnReason.NATURAL
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (entitytypes.getCategory() == MobCategory.MISC) {
|
||||
return false;
|
||||
} else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) {
|
|
@ -1,90 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 19 Jan 2018 00:36:25 -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/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
|
||||
index d6a4638271644e31fbc38f5ae9150ded63a6d62f..e89eb5d631b4226d79caf49c89ebb44155e72a0f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.bukkit.craftbukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -100,6 +102,20 @@ public class CraftSkull extends CraftBlockEntityState<SkullBlockEntity> implemen
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setPlayerProfile(PlayerProfile profile) {
|
||||
+ Preconditions.checkNotNull(profile, "profile");
|
||||
+ this.profile = CraftPlayerProfile.asAuthlibCopy(profile);
|
||||
+ }
|
||||
+
|
||||
+ @javax.annotation.Nullable
|
||||
+ @Override
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public BlockFace getRotation() {
|
||||
BlockData blockData = getBlockData();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
index 490df0dcfd0e1e0ab05943410493522f86444ef8..7cacc61fed0c610845c67894d1cc68e44f5e46fe 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
|
||||
@@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
-import net.minecraft.nbt.CompoundTag;
|
||||
-import net.minecraft.nbt.NbtUtils;
|
||||
-import net.minecraft.nbt.Tag;
|
||||
-import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@@ -18,6 +16,11 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.NbtUtils;
|
||||
+import net.minecraft.nbt.Tag;
|
||||
+import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
@DelegateDeserialization(SerializableMeta.class)
|
||||
class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
|
||||
|
||||
@@ -151,6 +154,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
|
||||
return this.hasOwner() ? this.profile.getName() : null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setPlayerProfile(@Nullable PlayerProfile profile) {
|
||||
+ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile));
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PlayerProfile getPlayerProfile() {
|
||||
+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public OfflinePlayer getOwningPlayer() {
|
||||
if (this.hasOwner()) {
|
|
@ -1,42 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 2 Jan 2018 00:31:26 -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/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.destroystokyo.paper.profile;
|
||||
|
||||
import com.mojang.authlib.Environment;
|
||||
+import com.destroystokyo.paper.event.profile.FillProfileEvent;
|
||||
+import com.destroystokyo.paper.event.profile.PreFillProfileEvent;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi
|
||||
|
||||
@Override
|
||||
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
|
||||
- return super.fillProfileProperties(profile, requireSecure);
|
||||
+ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile);
|
||||
+ new PreFillProfileEvent(playerProfile).callEvent();
|
||||
+ profile = playerProfile.getGameProfile();
|
||||
+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) {
|
||||
+ return profile;
|
||||
+ }
|
||||
+ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure);
|
||||
+ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent();
|
||||
+ return gameProfile;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 19 Jan 2018 08:15:29 -0600
|
||||
Subject: [PATCH] PlayerAdvancementCriterionGrantEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
index f26bdd3d6eb0ae38c1d7b50f29942fcf2207e3a1..3d82f984648605d58fae3c57f145d0da8a2ae225 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -277,6 +277,12 @@ public class PlayerAdvancements {
|
||||
boolean flag1 = advancementprogress.isDone();
|
||||
|
||||
if (advancementprogress.grantProgress(criterionName)) {
|
||||
+ // Paper start
|
||||
+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) {
|
||||
+ advancementprogress.revokeProgress(criterionName);
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.unregisterListeners(advancement);
|
||||
this.progressChanged.add(advancement);
|
||||
flag = true;
|
|
@ -1,288 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 27 Jan 2018 17:04:14 -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.
|
||||
|
||||
Fixes GH-559
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
|
||||
index aee796567f11c8b93ac9ec0b8cb8f3a8412b23ce..39b98305632271e7375afe6c7001f241c17e103d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
|
||||
@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization;
|
||||
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey;
|
||||
|
||||
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
|
||||
-public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
+public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper
|
||||
|
||||
static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag");
|
||||
+ // Paper start
|
||||
+ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible");
|
||||
+ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate");
|
||||
+ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms");
|
||||
+ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small");
|
||||
+ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker");
|
||||
+
|
||||
+ private boolean invisible;
|
||||
+ private boolean noBasePlate;
|
||||
+ private boolean showArms;
|
||||
+ private boolean small;
|
||||
+ private boolean marker;
|
||||
+ // Paper end
|
||||
CompoundTag entityTag;
|
||||
|
||||
CraftMetaArmorStand(CraftMetaItem meta) {
|
||||
@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
}
|
||||
|
||||
CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta;
|
||||
+ // Paper start
|
||||
+ this.invisible = armorStand.invisible;
|
||||
+ this.noBasePlate = armorStand.noBasePlate;
|
||||
+ this.showArms = armorStand.showArms;
|
||||
+ this.small = armorStand.small;
|
||||
+ this.marker = armorStand.marker;
|
||||
+ // Paper end
|
||||
this.entityTag = armorStand.entityTag;
|
||||
}
|
||||
|
||||
@@ -30,11 +50,40 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
|
||||
if (tag.contains(ENTITY_TAG.NBT)) {
|
||||
this.entityTag = tag.getCompound(ENTITY_TAG.NBT);
|
||||
+
|
||||
+ // Paper start
|
||||
+ if (entityTag.contains(INVISIBLE.NBT)) {
|
||||
+ invisible = entityTag.getBoolean(INVISIBLE.NBT);
|
||||
+ }
|
||||
+
|
||||
+ if (entityTag.contains(NO_BASE_PLATE.NBT)) {
|
||||
+ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT);
|
||||
+ }
|
||||
+
|
||||
+ if (entityTag.contains(SHOW_ARMS.NBT)) {
|
||||
+ showArms = entityTag.getBoolean(SHOW_ARMS.NBT);
|
||||
+ }
|
||||
+
|
||||
+ if (entityTag.contains(SMALL.NBT)) {
|
||||
+ small = entityTag.getBoolean(SMALL.NBT);
|
||||
+ }
|
||||
+
|
||||
+ if (entityTag.contains(MARKER.NBT)) {
|
||||
+ marker = entityTag.getBoolean(MARKER.NBT);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
CraftMetaArmorStand(Map<String, Object> map) {
|
||||
super(map);
|
||||
+ // Paper start
|
||||
+ this.invisible = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT);
|
||||
+ this.noBasePlate = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT);
|
||||
+ this.showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT);
|
||||
+ this.small = SerializableMeta.getBoolean(map, SMALL.BUKKIT);
|
||||
+ this.marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,6 +106,31 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
void applyToItem(CompoundTag tag) {
|
||||
super.applyToItem(tag);
|
||||
|
||||
+ // Paper start
|
||||
+ if (!isArmorStandEmpty() && this.entityTag == null) {
|
||||
+ this.entityTag = new CompoundTag();
|
||||
+ }
|
||||
+
|
||||
+ if (isInvisible()) {
|
||||
+ this.entityTag.putBoolean(INVISIBLE.NBT, this.invisible);
|
||||
+ }
|
||||
+
|
||||
+ if (hasNoBasePlate()) {
|
||||
+ this.entityTag.putBoolean(NO_BASE_PLATE.NBT, this.noBasePlate);
|
||||
+ }
|
||||
+
|
||||
+ if (shouldShowArms()) {
|
||||
+ this.entityTag.putBoolean(SHOW_ARMS.NBT, this.showArms);
|
||||
+ }
|
||||
+
|
||||
+ if (isSmall()) {
|
||||
+ this.entityTag.putBoolean(SMALL.NBT, this.small);
|
||||
+ }
|
||||
+
|
||||
+ if (isMarker()) {
|
||||
+ this.entityTag.putBoolean(MARKER.NBT, this.marker);
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.entityTag != null) {
|
||||
tag.put(ENTITY_TAG.NBT, entityTag);
|
||||
}
|
||||
@@ -78,7 +152,7 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
}
|
||||
|
||||
boolean isArmorStandEmpty() {
|
||||
- return !(this.entityTag != null);
|
||||
+ return !(this.isInvisible() || this.hasNoBasePlate() || this.shouldShowArms() || this.isSmall() || this.isMarker() || this.entityTag != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,7 +163,13 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
if (meta instanceof CraftMetaArmorStand) {
|
||||
CraftMetaArmorStand that = (CraftMetaArmorStand) meta;
|
||||
|
||||
- return this.entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : this.entityTag == null;
|
||||
+ // Paper start
|
||||
+ return this.invisible == that.invisible &&
|
||||
+ this.noBasePlate == that.noBasePlate &&
|
||||
+ this.showArms == that.showArms &&
|
||||
+ this.small == that.small &&
|
||||
+ this.marker == that.marker;
|
||||
+ // Paper end
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -104,9 +184,14 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
final int original;
|
||||
int hash = original = super.applyHash();
|
||||
|
||||
- if (this.entityTag != null) {
|
||||
- hash = 73 * hash + this.entityTag.hashCode();
|
||||
- }
|
||||
+ // Paper start
|
||||
+ hash += this.entityTag != null ? 73 * hash + this.entityTag.hashCode() : 0;
|
||||
+ hash += this.isInvisible() ? 61 * hash + 1231 : 0;
|
||||
+ hash += this.hasNoBasePlate() ? 61 * hash + 1231 : 0;
|
||||
+ hash += this.shouldShowArms() ? 61 * hash + 1231 : 0;
|
||||
+ hash += this.isSmall() ? 61 * hash + 1231 : 0;
|
||||
+ hash += this.isMarker() ? 61 * hash + 1231 : 0;
|
||||
+ // Paper end
|
||||
|
||||
return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash;
|
||||
}
|
||||
@@ -115,6 +200,28 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
Builder<String, Object> serialize(Builder<String, Object> builder) {
|
||||
super.serialize(builder);
|
||||
|
||||
+ // Paper start
|
||||
+ if (this.isInvisible()) {
|
||||
+ builder.put(INVISIBLE.BUKKIT, invisible);
|
||||
+ }
|
||||
+
|
||||
+ if (this.hasNoBasePlate()) {
|
||||
+ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate);
|
||||
+ }
|
||||
+
|
||||
+ if (this.shouldShowArms()) {
|
||||
+ builder.put(SHOW_ARMS.BUKKIT, showArms);
|
||||
+ }
|
||||
+
|
||||
+ if (this.isSmall()) {
|
||||
+ builder.put(SMALL.BUKKIT, small);
|
||||
+ }
|
||||
+
|
||||
+ if (this.isMarker()) {
|
||||
+ builder.put(MARKER.BUKKIT, marker);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -128,4 +235,56 @@ public class CraftMetaArmorStand extends CraftMetaItem {
|
||||
|
||||
return clone;
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean isInvisible() {
|
||||
+ return invisible;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNoBasePlate() {
|
||||
+ return noBasePlate;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldShowArms() {
|
||||
+ return showArms;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isSmall() {
|
||||
+ return small;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isMarker() {
|
||||
+ return marker;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setInvisible(boolean invisible) {
|
||||
+ this.invisible = invisible;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setNoBasePlate(boolean noBasePlate) {
|
||||
+ this.noBasePlate = noBasePlate;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setShowArms(boolean showArms) {
|
||||
+ this.showArms = showArms;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSmall(boolean small) {
|
||||
+ this.small = small;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMarker(boolean marker) {
|
||||
+ this.marker = marker;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index 05d54f0eff89b721f01e90e79d2571baab297799..71320d9484842be3a694117de25159f3581bd2a3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -1444,6 +1444,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
CraftMetaCrossbow.CHARGED.NBT,
|
||||
CraftMetaCrossbow.CHARGED_PROJECTILES.NBT,
|
||||
CraftMetaSuspiciousStew.EFFECTS.NBT,
|
||||
+ // Paper start
|
||||
+ CraftMetaArmorStand.ENTITY_TAG.NBT,
|
||||
+ CraftMetaArmorStand.INVISIBLE.NBT,
|
||||
+ CraftMetaArmorStand.NO_BASE_PLATE.NBT,
|
||||
+ CraftMetaArmorStand.SHOW_ARMS.NBT,
|
||||
+ CraftMetaArmorStand.SMALL.NBT,
|
||||
+ CraftMetaArmorStand.MARKER.NBT,
|
||||
+ // Paper end
|
||||
CraftMetaCompass.LODESTONE_DIMENSION.NBT,
|
||||
CraftMetaCompass.LODESTONE_POS.NBT,
|
||||
CraftMetaCompass.LODESTONE_TRACKED.NBT,
|
||||
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
index a7505a08b952431d1dd7e4b332ede0c0d15eea64..f3a0578f53863dd0866b4c2cb957a30fa3bc6cc5 100644
|
||||
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
@@ -324,6 +324,7 @@ public class ItemMetaTest extends AbstractTestingBase {
|
||||
final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta();
|
||||
meta.entityTag = new CompoundTag();
|
||||
meta.entityTag.putBoolean("Small", true);
|
||||
+ meta.setInvisible(true); // Paper
|
||||
cleanStack.setItemMeta(meta);
|
||||
return cleanStack;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 11 Feb 2018 10:43:46 +0000
|
||||
Subject: [PATCH] Extend Player Interact cancellation
|
||||
|
||||
GUIs are opened on the client, meaning that the server cannot block them from opening,
|
||||
However, it is possible to close these GUIs from the server.
|
||||
|
||||
Flower pots are also not updated on the client when interaction is cancelled, this patch
|
||||
also resolves this.
|
||||
|
||||
Update adjacent blocks of doors, double plants, pistons and beds
|
||||
when cancelling interaction.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index ecfb88b4d9727ad20a2c33475cc6b1ec88821a19..315dad4789f5f2582ee9b4fc176affd1f57537ef 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -187,6 +187,11 @@ public class ServerPlayerGameMode {
|
||||
PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
if (event.isCancelled()) {
|
||||
// Let the client know the block still exists
|
||||
+ // Paper start - brute force neighbor blocks for any attached blocks
|
||||
+ for (Direction dir : Direction.values()) {
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
// Update any tile entity data for this block
|
||||
BlockEntity tileentity = this.level.getBlockEntity(pos);
|
||||
@@ -502,7 +507,13 @@ public class ServerPlayerGameMode {
|
||||
|
||||
// send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc)
|
||||
player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above()));
|
||||
+ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method
|
||||
+ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.StructureBlock) {
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId));
|
||||
+ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.CommandBlock) {
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId));
|
||||
}
|
||||
+ // Paper end - extend Player Interact cancellation
|
||||
player.getBukkitEntity().updateInventory(); // SPIGOT-2867
|
||||
enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS;
|
||||
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
|
@ -1,38 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 24 Feb 2018 01:14:55 -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/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
index 27a1ca43792644fc239af81dea5510f25d3328e9..69c95644b2531c1fe1c4a6cf7fee12e997dd67f4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java
|
||||
@@ -89,6 +89,10 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac
|
||||
}
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public UUID getOwnerUniqueId() {
|
||||
+ return getOwnerUUID();
|
||||
+ }
|
||||
public UUID getOwnerUUID() {
|
||||
return this.getHandle().getOwnerUUID();
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java
|
||||
index cc90c09c26b04689e4fffa890baf0e89c38665a3..0b152d8d20924fc1ce7f5bafb050216d250f6536 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java
|
||||
@@ -17,6 +17,10 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat
|
||||
return (TamableAnimal) super.getHandle();
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public UUID getOwnerUniqueId() {
|
||||
+ return getOwnerUUID();
|
||||
+ }
|
||||
public UUID getOwnerUUID() {
|
||||
try {
|
||||
return this.getHandle().getOwnerUUID();
|
|
@ -1,34 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MiniDigger <admin@minidigger.me>
|
||||
Date: Sat, 10 Mar 2018 00:50:24 +0100
|
||||
Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients.
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 5892823425055efb92bf635b035d62981942b966..0e08f6e566d1c93cc89a179583d0b0939127de8b 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -233,6 +233,11 @@ public class PaperWorldConfig {
|
||||
disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false);
|
||||
}
|
||||
|
||||
+ public boolean disablePlayerCrits;
|
||||
+ private void disablePlayerCrits() {
|
||||
+ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false);
|
||||
+ }
|
||||
+
|
||||
public boolean allChunksAreSlimeChunks;
|
||||
private void allChunksAreSlimeChunks() {
|
||||
allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index 8c20af91c9298cb36fdb2700d042b1e2fccf5f54..dbab4d28c49d22807dfc582fb83353232396555b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -1189,6 +1189,7 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
|
||||
|
||||
+ flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper
|
||||
flag2 = flag2 && !this.isSprinting();
|
||||
if (flag2) {
|
||||
f *= 1.5F;
|
|
@ -1,34 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 11 Mar 2018 14:13:33 -0400
|
||||
Subject: [PATCH] Disable Explicit Network Manager Flushing
|
||||
|
||||
This seems completely pointless, as packet dispatch uses .writeAndFlush.
|
||||
|
||||
Things seem to work fine without explicit flushing, but incase issues arise,
|
||||
provide a System property to re-enable it using improved logic of doing the
|
||||
flushing on the netty event loop, so it won't do the flush on the main thread.
|
||||
|
||||
Renable flushing by passing -Dpaper.explicit-flush=true
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 06e965996a5c50bce617847e594ae0dd83403484..636ac646bec67dbd933f00614693af03481b6173 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -86,6 +86,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
// Paper start - NetworkClient implementation
|
||||
public int protocolVersion;
|
||||
public java.net.InetSocketAddress virtualHost;
|
||||
+ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush");
|
||||
// Paper end
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
@@ -259,7 +260,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
if (this.channel != null) {
|
||||
- this.channel.flush();
|
||||
+ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version
|
||||
}
|
||||
|
||||
if (this.tickCount++ % 20 == 0) {
|
|
@ -1,250 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Minecrell <minecrell@minecrell.net>
|
||||
Date: Wed, 11 Oct 2017 15:56:26 +0200
|
||||
Subject: [PATCH] Implement extended PaperServerListPingEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4ecd0c5bbea55f68549c85aa27e80e2c7e6265d4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.util.CachedServerIcon;
|
||||
+
|
||||
+import javax.annotation.Nullable;
|
||||
+
|
||||
+class PaperServerListPingEventImpl extends PaperServerListPingEvent {
|
||||
+
|
||||
+ private final MinecraftServer server;
|
||||
+
|
||||
+ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) {
|
||||
+ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(),
|
||||
+ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon);
|
||||
+ this.server = server;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected final Object[] getOnlinePlayers() {
|
||||
+ return this.server.getPlayerList().players.toArray();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected final Player getBukkitPlayer(Object player) {
|
||||
+ return ((ServerPlayer) player).getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671602acdab
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java
|
||||
@@ -0,0 +1,11 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import net.minecraft.network.Connection;
|
||||
+
|
||||
+class PaperStatusClient extends PaperNetworkClient implements StatusClient {
|
||||
+
|
||||
+ PaperStatusClient(Connection networkManager) {
|
||||
+ super(networkManager);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab5193adc9
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
|
||||
@@ -0,0 +1,110 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.google.common.base.MoreObjects;
|
||||
+import com.google.common.base.Strings;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import io.papermc.paper.adventure.AdventureComponent;
|
||||
+import java.util.List;
|
||||
+import java.util.UUID;
|
||||
+import javax.annotation.Nonnull;
|
||||
+import net.minecraft.network.Connection;
|
||||
+import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
|
||||
+import net.minecraft.network.protocol.status.ServerStatus;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+
|
||||
+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl {
|
||||
+
|
||||
+ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0];
|
||||
+ private static final UUID FAKE_UUID = new UUID(0, 0);
|
||||
+
|
||||
+ private GameProfile[] originalSample;
|
||||
+
|
||||
+ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) {
|
||||
+ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon());
|
||||
+ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public List<PlayerProfile> getPlayerSample() {
|
||||
+ List<PlayerProfile> sample = super.getPlayerSample();
|
||||
+
|
||||
+ if (this.originalSample != null) {
|
||||
+ for (GameProfile profile : this.originalSample) {
|
||||
+ sample.add(CraftPlayerProfile.asBukkitCopy(profile));
|
||||
+ }
|
||||
+ this.originalSample = null;
|
||||
+ }
|
||||
+
|
||||
+ return sample;
|
||||
+ }
|
||||
+
|
||||
+ private GameProfile[] getPlayerSampleHandle() {
|
||||
+ if (this.originalSample != null) {
|
||||
+ return this.originalSample;
|
||||
+ }
|
||||
+
|
||||
+ List<PlayerProfile> entries = super.getPlayerSample();
|
||||
+ if (entries.isEmpty()) {
|
||||
+ return EMPTY_PROFILES;
|
||||
+ }
|
||||
+
|
||||
+ GameProfile[] profiles = new GameProfile[entries.size()];
|
||||
+ for (int i = 0; i < profiles.length; i++) {
|
||||
+ /*
|
||||
+ * Avoid null UUIDs/names since that will make the response invalid
|
||||
+ * on the client.
|
||||
+ * Instead, fall back to a fake/empty UUID and an empty string as name.
|
||||
+ * This can be used to create custom lines in the player list that do not
|
||||
+ * refer to a specific player.
|
||||
+ */
|
||||
+
|
||||
+ PlayerProfile profile = entries.get(i);
|
||||
+ if (profile.getId() != null && profile.getName() != null) {
|
||||
+ profiles[i] = CraftPlayerProfile.asAuthlib(profile);
|
||||
+ } else {
|
||||
+ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return profiles;
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("deprecation")
|
||||
+ public static void processRequest(MinecraftServer server, Connection networkManager) {
|
||||
+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus());
|
||||
+ server.server.getPluginManager().callEvent(event);
|
||||
+
|
||||
+ // Close connection immediately if event is cancelled
|
||||
+ if (event.isCancelled()) {
|
||||
+ networkManager.disconnect(null);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Setup response
|
||||
+ ServerStatus ping = new ServerStatus();
|
||||
+
|
||||
+ // Description
|
||||
+ ping.setDescription(new AdventureComponent(event.motd()));
|
||||
+
|
||||
+ // Players
|
||||
+ if (!event.shouldHidePlayers()) {
|
||||
+ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers()));
|
||||
+ ping.getPlayers().setSample(event.getPlayerSampleHandle());
|
||||
+ }
|
||||
+
|
||||
+ // Version
|
||||
+ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion()));
|
||||
+
|
||||
+ // Favicon
|
||||
+ if (event.getServerIcon() != null) {
|
||||
+ ping.setFavicon(event.getServerIcon().getData());
|
||||
+ }
|
||||
+
|
||||
+ // Send response
|
||||
+ networkManager.send(new ClientboundStatusResponsePacket(ping));
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
|
||||
index 67455a5ba75c9b816213e44d6872c5ddf8e27e98..23efad80934930beadf15e65781551d4ba7ff81b 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
|
||||
@@ -10,7 +10,9 @@ import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory;
|
||||
|
||||
public class ClientboundStatusResponsePacket implements Packet<ClientStatusPacketListener> {
|
||||
- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create();
|
||||
+ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory())
|
||||
+ .registerTypeAdapter(io.papermc.paper.adventure.AdventureComponent.class, new io.papermc.paper.adventure.AdventureComponent.Serializer())
|
||||
+ .create();
|
||||
private final ServerStatus status;
|
||||
|
||||
public ClientboundStatusResponsePacket(ServerStatus metadata) {
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 031bd2ed5c6fd2a859e8a69c48db3938cf71d61b..d9fab29a066367a5cf4a3486989fa7f35451801e 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2,6 +2,9 @@ package net.minecraft.server;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
+import co.aikar.timings.Timings;
|
||||
+import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
+import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -1331,7 +1334,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (i - this.lastServerStatus >= 5000000000L) {
|
||||
this.lastServerStatus = i;
|
||||
this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount()));
|
||||
- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)];
|
||||
+ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper
|
||||
int j = Mth.nextInt(this.random, 0, this.getPlayerCount() - agameprofile.length);
|
||||
|
||||
for (int k = 0; k < agameprofile.length; ++k) {
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
index 9baa56d6da9c24706f1dbc8851fd68ca752cab26..d65191a50349ec86fe35df4ac1070f94fbb77b4c 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
@@ -47,6 +47,8 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene
|
||||
this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON);
|
||||
} else {
|
||||
this.hasRequestedStatus = true;
|
||||
+ // Paper start - Replace everything
|
||||
+ /*
|
||||
// CraftBukkit start
|
||||
// this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing()));
|
||||
final Object[] players = this.server.getPlayerList().players.toArray();
|
||||
@@ -142,6 +144,9 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene
|
||||
ping.setVersion(new ServerStatus.Version(this.server.getServerModName() + " " + this.server.getServerVersion(), version));
|
||||
|
||||
this.connection.send(new ClientboundStatusResponsePacket(ping));
|
||||
+ */
|
||||
+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection);
|
||||
+ // Paper end
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index d73dfe72a54b621c0f944c90904df3e3bc709445..8e7630de11637a75a4a54a22283cbb2d0c7e6438 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -289,7 +289,7 @@ public class SpigotConfig
|
||||
public static int playerSample;
|
||||
private static void playerSample()
|
||||
{
|
||||
- SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 );
|
||||
+ SpigotConfig.playerSample = Math.max( SpigotConfig.getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts
|
||||
Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 18 Mar 2018 11:45:57 -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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 109d7f1bf37e442ff80f7f63d50e27e6e30e0b5e..261ebb134a5ff40406e74237f730aad1c78a8215 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.minecraft.server.network;
|
||||
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
|
||||
import java.math.BigInteger;
|
||||
@@ -37,6 +39,7 @@ import org.apache.commons.lang3.Validate;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import io.papermc.paper.adventure.PaperAdventure; // Paper
|
||||
+import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.util.Waitable;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||
@@ -336,8 +339,16 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId();
|
||||
final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
|
||||
|
||||
- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId);
|
||||
+ // Paper start
|
||||
+ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName);
|
||||
+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
|
||||
server.getPluginManager().callEvent(asyncEvent);
|
||||
+ profile = asyncEvent.getPlayerProfile();
|
||||
+ profile.complete();
|
||||
+ gameProfile = CraftPlayerProfile.asAuthlibCopy(profile);
|
||||
+ playerName = gameProfile.getName();
|
||||
+ uniqueId = gameProfile.getId();
|
||||
+ // Paper end
|
||||
|
||||
if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
|
||||
final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
|
|
@ -1,133 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 18 Mar 2018 12:29:48 -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/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 261ebb134a5ff40406e74237f730aad1c78a8215..39bdda56aaa5503efc15207261634127b462c3e7 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -340,12 +340,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
||||
final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
|
||||
|
||||
// Paper start
|
||||
- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName);
|
||||
+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
|
||||
AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
|
||||
server.getPluginManager().callEvent(asyncEvent);
|
||||
profile = asyncEvent.getPlayerProfile();
|
||||
- profile.complete();
|
||||
- gameProfile = CraftPlayerProfile.asAuthlibCopy(profile);
|
||||
+ profile.complete(true);
|
||||
+ ServerLoginPacketListenerImpl.this.gameProfile = CraftPlayerProfile.asAuthlib(profile);
|
||||
playerName = gameProfile.getName();
|
||||
uniqueId = gameProfile.getId();
|
||||
// Paper end
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index dbab4d28c49d22807dfc582fb83353232396555b..0ef9c95d40cd0cdff0d150121511e6f9efd65f4d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -173,7 +173,7 @@ public abstract class Player extends LivingEntity {
|
||||
protected int enchantmentSeed;
|
||||
protected final float defaultFlySpeed = 0.02F;
|
||||
private int lastLevelUpTime;
|
||||
- private final GameProfile gameProfile;
|
||||
+ public GameProfile gameProfile; // Paper - private->public
|
||||
private boolean reducedDebugInfo;
|
||||
private ItemStack lastItemInMainHand;
|
||||
private final ItemCooldowns cooldowns;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 4c8617fbd2cd8e34c87634fe448d204ee7fb8a0f..95a1d83fb7cb9947beb56b951b0081e4db2de6c9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -71,6 +71,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
+import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||
import net.minecraft.world.level.saveddata.maps.MapDecoration;
|
||||
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||
@@ -1347,8 +1348,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
this.hiddenPlayers.put(player.getUniqueId(), hidingPlugins);
|
||||
|
||||
// Remove this player from the hidden player's EntityTrackerEntry
|
||||
- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap;
|
||||
+ // Paper start
|
||||
ServerPlayer other = ((CraftPlayer) player).getHandle();
|
||||
+ unregisterPlayer(other);
|
||||
+ }
|
||||
+ private void unregisterPlayer(ServerPlayer other) {
|
||||
+ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap;
|
||||
+ // Paper end
|
||||
ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId());
|
||||
if (entry != null) {
|
||||
entry.removePlayer(this.getHandle());
|
||||
@@ -1389,8 +1395,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
}
|
||||
this.hiddenPlayers.remove(player.getUniqueId());
|
||||
|
||||
- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap;
|
||||
+ // Paper start
|
||||
ServerPlayer other = ((CraftPlayer) player).getHandle();
|
||||
+ registerPlayer(other);
|
||||
+ }
|
||||
+ private void registerPlayer(ServerPlayer other) {
|
||||
+ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap;
|
||||
+ // Paper end
|
||||
|
||||
this.getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other));
|
||||
|
||||
@@ -1399,6 +1410,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
entry.updatePlayer(this.getHandle());
|
||||
}
|
||||
}
|
||||
+ // Paper start
|
||||
+ private void reregisterPlayer(ServerPlayer player) {
|
||||
+ if (!hiddenPlayers.containsKey(player.getUUID())) {
|
||||
+ unregisterPlayer(player);
|
||||
+ registerPlayer(player);
|
||||
+ }
|
||||
+ }
|
||||
+ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) {
|
||||
+ ServerPlayer self = getHandle();
|
||||
+ self.gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile);
|
||||
+ if (!self.sentListPacket) {
|
||||
+ return;
|
||||
+ }
|
||||
+ List<ServerPlayer> players = server.getServer().getPlayerList().players;
|
||||
+ for (ServerPlayer player : players) {
|
||||
+ player.getBukkitEntity().reregisterPlayer(self);
|
||||
+ }
|
||||
+ refreshPlayer();
|
||||
+ }
|
||||
+ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() {
|
||||
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone();
|
||||
+ }
|
||||
+
|
||||
+ private void refreshPlayer() {
|
||||
+ ServerPlayer handle = getHandle();
|
||||
+
|
||||
+ Location loc = getLocation();
|
||||
+
|
||||
+ ServerGamePacketListenerImpl connection = handle.connection;
|
||||
+ reregisterPlayer(handle);
|
||||
+
|
||||
+ //Respawn the player then update their position and selected slot
|
||||
+ ServerLevel worldserver = handle.getLevel();
|
||||
+ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true));
|
||||
+ handle.onUpdateAbilities();
|
||||
+ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), java.util.Collections.emptySet(), 0, false));
|
||||
+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle);
|
||||
+
|
||||
+ if (this.isOp()) {
|
||||
+ this.setOp(false);
|
||||
+ this.setOp(true);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public void removeDisconnectingPlayer(Player player) {
|
||||
this.hiddenPlayers.remove(player.getUniqueId());
|
|
@ -1,40 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 22 Mar 2018 01:40:24 -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/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 435a68e6c99bffdc8d6ded9deda68d4e970a2d49..d10da7acb03a2e4a67cee41a6f6fc6357eb8efd6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1668,6 +1668,25 @@ public final class CraftServer implements Server {
|
||||
return recipients.size();
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Nullable
|
||||
+ public UUID getPlayerUniqueId(String name) {
|
||||
+ Player player = Bukkit.getPlayerExact(name);
|
||||
+ if (player != null) {
|
||||
+ return player.getUniqueId();
|
||||
+ }
|
||||
+ GameProfile profile;
|
||||
+ // Only fetch an online UUID in online mode
|
||||
+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) {
|
||||
+ profile = console.getProfileCache().get(name).orElse(null);
|
||||
+ } else {
|
||||
+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile
|
||||
+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
|
||||
+ }
|
||||
+ return profile != null ? profile.getId() : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
@Deprecated
|
||||
public OfflinePlayer getOfflinePlayer(String name) {
|
Loading…
Add table
Add a link
Reference in a new issue