more patches
This commit is contained in:
parent
3a3831d6aa
commit
650edb93ca
62 changed files with 491 additions and 529 deletions
62
patches/api/0011-Add-PlayerLocaleChangeEvent.patch
Normal file
62
patches/api/0011-Add-PlayerLocaleChangeEvent.patch
Normal file
|
@ -0,0 +1,62 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Moore <rmsy@me.com>
|
||||
Date: Mon, 29 Feb 2016 18:02:25 -0600
|
||||
Subject: [PATCH] Add PlayerLocaleChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..29dd763a99ce7c6ecb176b9fb346a400369d48a0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
|
||||
@@ -0,0 +1,50 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+
|
||||
+/**
|
||||
+ * Called when the locale of the player is changed.
|
||||
+ *
|
||||
+ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream
|
||||
+ */
|
||||
+@Deprecated
|
||||
+public class PlayerLocaleChangeEvent extends PlayerEvent {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final String oldLocale;
|
||||
+ private final String newLocale;
|
||||
+
|
||||
+ public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) {
|
||||
+ super(player);
|
||||
+ this.oldLocale = oldLocale;
|
||||
+ this.newLocale = newLocale;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the locale the player switched from.
|
||||
+ *
|
||||
+ * @return player's old locale
|
||||
+ */
|
||||
+ public String getOldLocale() {
|
||||
+ return oldLocale;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the locale the player is changed to.
|
||||
+ *
|
||||
+ * @return player's new locale
|
||||
+ */
|
||||
+ public String getNewLocale() {
|
||||
+ return newLocale;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
39
patches/api/0012-Add-player-view-distance-API.patch
Normal file
39
patches/api/0012-Add-player-view-distance-API.patch
Normal file
|
@ -0,0 +1,39 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Mon, 29 Feb 2016 18:05:37 -0600
|
||||
Subject: [PATCH] Add player view distance API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 76ac0b20842002ce1b593e338bea98483e7080ac..f34601480a3b3069c30c52d258a35a2a79c981fb 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1394,6 +1394,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @param affects Whether the player can affect mob spawning
|
||||
*/
|
||||
public void setAffectsSpawning(boolean affects);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the view distance for this player
|
||||
+ *
|
||||
+ * @return the player's view distance
|
||||
+ * @deprecated This is unimplemented and <i>will</i> throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work.
|
||||
+ * @see org.bukkit.World#getViewDistance()
|
||||
+ * @see org.bukkit.World#getNoTickViewDistance()
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public int getViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the view distance for this player
|
||||
+ *
|
||||
+ * @param viewDistance the player's view distance
|
||||
+ * @deprecated This is unimplemented and <i>will</i> throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work.
|
||||
+ * @see org.bukkit.World#setViewDistance(int)
|
||||
+ * @see org.bukkit.World#setNoTickViewDistance(int)
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setViewDistance(int viewDistance);
|
||||
// Paper end
|
||||
|
||||
/**
|
98
patches/api/0013-Add-BeaconEffectEvent.patch
Normal file
98
patches/api/0013-Add-BeaconEffectEvent.patch
Normal file
|
@ -0,0 +1,98 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Mon, 29 Feb 2016 18:09:40 -0600
|
||||
Subject: [PATCH] Add BeaconEffectEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..978813b94a5eae0afccbd3b38b463091a46b56ac
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java
|
||||
@@ -0,0 +1,86 @@
|
||||
+package com.destroystokyo.paper.event.block;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.block.BlockEvent;
|
||||
+import org.bukkit.potion.PotionEffect;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a beacon effect is being applied to a player.
|
||||
+ */
|
||||
+public class BeaconEffectEvent extends BlockEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled;
|
||||
+ private PotionEffect effect;
|
||||
+ private Player player;
|
||||
+ private boolean primary;
|
||||
+
|
||||
+ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) {
|
||||
+ super(block);
|
||||
+ this.effect = effect;
|
||||
+ this.player = player;
|
||||
+ this.primary = primary;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancelled) {
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the potion effect being applied.
|
||||
+ *
|
||||
+ * @return Potion effect
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public PotionEffect getEffect() {
|
||||
+ return effect;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the potion effect that will be applied.
|
||||
+ *
|
||||
+ * @param effect Potion effect
|
||||
+ */
|
||||
+ public void setEffect(@NotNull PotionEffect effect) {
|
||||
+ this.effect = effect;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the player who the potion effect is being applied to.
|
||||
+ *
|
||||
+ * @return Affected player
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether the effect is a primary beacon effect.
|
||||
+ *
|
||||
+ * @return true if this event represents a primary effect
|
||||
+ */
|
||||
+ public boolean isPrimary() {
|
||||
+ return primary;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
29
patches/api/0014-Add-PlayerInitialSpawnEvent.patch
Normal file
29
patches/api/0014-Add-PlayerInitialSpawnEvent.patch
Normal file
|
@ -0,0 +1,29 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Anton <anxuiz.nx@gmail.com>
|
||||
Date: Mon, 29 Feb 2016 18:13:58 -0600
|
||||
Subject: [PATCH] Add PlayerInitialSpawnEvent
|
||||
|
||||
For modifying a player's initial spawn location as they join the server
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8b1fdb9d2869d4c1862d557c91bf8a1d8c537507
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
|
||||
@@ -0,0 +1,16 @@
|
||||
+package com.destroystokyo.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.spigotmc.event.player.PlayerSpawnLocationEvent;
|
||||
+
|
||||
+/**
|
||||
+ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API
|
||||
+ */
|
||||
+public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent {
|
||||
+
|
||||
+ public PlayerInitialSpawnEvent(@NotNull Player who, @NotNull Location spawnLocation) {
|
||||
+ super(who, spawnLocation);
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 29 Feb 2016 19:45:21 -0600
|
||||
Subject: [PATCH] Automatically disable plugins that fail to load
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
index cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b..2e306c7b984a02e12a74fac14589bf29ab6488bf 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
@@ -335,6 +335,10 @@ public final class JavaPluginLoader implements PluginLoader {
|
||||
jPlugin.setEnabled(true);
|
||||
} catch (Throwable ex) {
|
||||
server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ // Paper start - Disable plugins that fail to load
|
||||
+ disablePlugin(jPlugin);
|
||||
+ return;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
// Perhaps abort here, rather than continue going, but as it stands,
|
50
patches/api/0016-Expose-server-CommandMap.patch
Normal file
50
patches/api/0016-Expose-server-CommandMap.patch
Normal file
|
@ -0,0 +1,50 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Mon, 29 Feb 2016 19:48:59 -0600
|
||||
Subject: [PATCH] Expose server CommandMap
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 1014871a3d7bfcf2b749d20e6ef8096876f9b4d7..72f0268e70382a258aeac9a9d6d860e0284378ad 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -1717,6 +1717,19 @@ public final class Bukkit {
|
||||
return server.getUnsafe();
|
||||
}
|
||||
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the active {@link org.bukkit.command.CommandMap}
|
||||
+ *
|
||||
+ * @return the active command map
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static org.bukkit.command.CommandMap getCommandMap() {
|
||||
+ return server.getCommandMap();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@NotNull
|
||||
public static Server.Spigot spigot() {
|
||||
return server.spigot();
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 3f74dc04df61e7d038c99ad9c1c3bfff086a019a..8fc591b16da774d60e85e3f13e44e9b5be671a3b 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1311,6 +1311,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
public double[] getTPS();
|
||||
// Paper end
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the active {@link org.bukkit.command.CommandMap}
|
||||
+ *
|
||||
+ * @return the active command map
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ org.bukkit.command.CommandMap getCommandMap();
|
||||
+
|
||||
/**
|
||||
* Get the advancement specified by this key.
|
||||
*
|
|
@ -0,0 +1,124 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Mon, 29 Feb 2016 19:54:32 -0600
|
||||
Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses
|
||||
|
||||
Change Javadoc to be accurate
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 72f0268e70382a258aeac9a9d6d860e0284378ad..8646fc0987a8833996c5d977c36fe0d01bf72992 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -285,6 +285,30 @@ public final class Bukkit {
|
||||
return server.broadcastMessage(message);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to all online players.
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ server.broadcast(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to all online players.
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ server.broadcast(components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the name of the update folder. The update folder is used to safely
|
||||
* update plugins at the right moment on a plugin load.
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 8fc591b16da774d60e85e3f13e44e9b5be671a3b..599347ef656acad9a40be15fc5030e5d0f1630df 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -234,6 +234,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@Deprecated // Paper
|
||||
public int broadcastMessage(@NotNull String message);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to all online players.
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ spigot().broadcast(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to all online players.
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().broadcast(components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the name of the update folder. The update folder is used to safely
|
||||
* update plugins at the right moment on a plugin load.
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index f34601480a3b3069c30c52d258a35a2a79c981fb..4686212255e8de3e5a6f43d86f28fad595f687ed 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
public void sendMap(@NotNull MapView map);
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Sends the component to the player
|
||||
+ *
|
||||
+ * @param component the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Override
|
||||
+ @Deprecated
|
||||
+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ spigot().sendMessage(component);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the player
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
+ */
|
||||
+ @Override
|
||||
+ @Deprecated
|
||||
+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().sendMessage(components);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the specified screen position of this player
|
||||
+ *
|
||||
+ * @param position the screen position
|
||||
+ * @param components the components to send
|
||||
+ */
|
||||
+ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ spigot().sendMessage(position, components);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Forces an update of the player's entire inventory.
|
||||
*
|
604
patches/api/0018-Add-exception-reporting-event.patch
Normal file
604
patches/api/0018-Add-exception-reporting-event.patch
Normal file
|
@ -0,0 +1,604 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Mon, 29 Feb 2016 20:24:35 -0600
|
||||
Subject: [PATCH] Add exception reporting event
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2f573299a9a817a98372817a1de8bf641aaca956
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.apache.commons.lang.Validate;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import com.destroystokyo.paper.exception.ServerException;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called whenever an exception is thrown in a recoverable section of the server.
|
||||
+ */
|
||||
+public class ServerExceptionEvent extends Event {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ @NotNull private ServerException exception;
|
||||
+
|
||||
+ public ServerExceptionEvent(@NotNull ServerException exception) {
|
||||
+ super(!Bukkit.isPrimaryThread());
|
||||
+ this.exception = Preconditions.checkNotNull(exception, "exception");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the wrapped exception that was thrown.
|
||||
+ *
|
||||
+ * @return Exception thrown
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ServerException getException() {
|
||||
+ return exception;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a command throws an exception
|
||||
+ */
|
||||
+public class ServerCommandException extends ServerException {
|
||||
+
|
||||
+ private final Command command;
|
||||
+ private final CommandSender commandSender;
|
||||
+ private final String[] arguments;
|
||||
+
|
||||
+ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(cause);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
||||
+ this.arguments = checkNotNull(arguments, "arguments");
|
||||
+ this.command = checkNotNull(command, "command");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command which threw the exception
|
||||
+ *
|
||||
+ * @return exception throwing command
|
||||
+ */
|
||||
+ public Command getCommand() {
|
||||
+ return command;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command sender which executed the command request
|
||||
+ *
|
||||
+ * @return command sender of exception thrown command request
|
||||
+ */
|
||||
+ public CommandSender getCommandSender() {
|
||||
+ return commandSender;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the arguments which threw the exception for the command
|
||||
+ *
|
||||
+ * @return arguments of exception thrown command request
|
||||
+ */
|
||||
+ public String[] getArguments() {
|
||||
+ return arguments;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java
|
||||
@@ -0,0 +1,52 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.*;
|
||||
+
|
||||
+/**
|
||||
+ * Exception thrown when a server event listener throws an exception
|
||||
+ */
|
||||
+public class ServerEventException extends ServerPluginException {
|
||||
+
|
||||
+ private final Listener listener;
|
||||
+ private final Event event;
|
||||
+
|
||||
+ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ this.listener = checkNotNull(listener, "listener");
|
||||
+ this.event = checkNotNull(event, "event");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the listener which threw the exception
|
||||
+ *
|
||||
+ * @return event listener
|
||||
+ */
|
||||
+ public Listener getListener() {
|
||||
+ return listener;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the event which caused the exception
|
||||
+ *
|
||||
+ * @return event
|
||||
+ */
|
||||
+ public Event getEvent() {
|
||||
+ return event;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+/**
|
||||
+ * Wrapper exception for all exceptions that are thrown by the server.
|
||||
+ */
|
||||
+public class ServerException extends Exception {
|
||||
+
|
||||
+ public ServerException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+
|
||||
+ public ServerException(String message, Throwable cause) {
|
||||
+ super(message, cause);
|
||||
+ }
|
||||
+
|
||||
+ public ServerException(Throwable cause) {
|
||||
+ super(cause);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e762ed0dbad51625e65fef2e1898679108459a36
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java
|
||||
@@ -0,0 +1,35 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when the internal server throws a recoverable exception.
|
||||
+ */
|
||||
+public class ServerInternalException extends ServerException {
|
||||
+
|
||||
+ public ServerInternalException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+
|
||||
+ public ServerInternalException(String message, Throwable cause) {
|
||||
+ super(message, cause);
|
||||
+ }
|
||||
+
|
||||
+ public ServerInternalException(Throwable cause) {
|
||||
+ super(cause);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ }
|
||||
+
|
||||
+ public static void reportInternalException(Throwable cause) {
|
||||
+ try {
|
||||
+ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause)));
|
||||
+ ;
|
||||
+ } catch (Throwable t) {
|
||||
+ t.printStackTrace(); // Don't want to rethrow!
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java
|
||||
@@ -0,0 +1,20 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown whenever there is an exception with any enabling or disabling of plugins.
|
||||
+ */
|
||||
+public class ServerPluginEnableDisableException extends ServerPluginException {
|
||||
+ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6defac287d0214fdf99418d979144050cc1e53bc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java
|
||||
@@ -0,0 +1,38 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import org.apache.commons.lang.Validate;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.*;
|
||||
+
|
||||
+/**
|
||||
+ * Wrapper exception for all cases to which a plugin can be immediately blamed for
|
||||
+ */
|
||||
+public class ServerPluginException extends ServerException {
|
||||
+ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(message, cause);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) {
|
||||
+ super(cause);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace);
|
||||
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
||||
+ }
|
||||
+
|
||||
+ private final Plugin responsiblePlugin;
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the plugin which is directly responsible for the exception being thrown
|
||||
+ *
|
||||
+ * @return plugin which is responsible for the exception throw
|
||||
+ */
|
||||
+ public Plugin getResponsiblePlugin() {
|
||||
+ return responsiblePlugin;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..89e132525cfae0ce979e37b3e2793df781e47227
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java
|
||||
@@ -0,0 +1,64 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.plugin.Plugin;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.*;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when an incoming plugin message channel throws an exception
|
||||
+ */
|
||||
+public class ServerPluginMessageException extends ServerPluginException {
|
||||
+
|
||||
+ private final Player player;
|
||||
+ private final String channel;
|
||||
+ private final byte[] data;
|
||||
+
|
||||
+ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(message, cause, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(cause, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
||||
+ this.player = checkNotNull(player, "player");
|
||||
+ this.channel = checkNotNull(channel, "channel");
|
||||
+ this.data = checkNotNull(data, "data");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the channel to which the error occurred from recieving data from
|
||||
+ *
|
||||
+ * @return exception channel
|
||||
+ */
|
||||
+ public String getChannel() {
|
||||
+ return channel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the data to which the error occurred from
|
||||
+ *
|
||||
+ * @return exception data
|
||||
+ */
|
||||
+ public byte[] getData() {
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the player which the plugin message causing the exception originated from
|
||||
+ *
|
||||
+ * @return exception player
|
||||
+ */
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java
|
||||
@@ -0,0 +1,37 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.scheduler.BukkitTask;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Thrown when a plugin's scheduler fails with an exception
|
||||
+ */
|
||||
+public class ServerSchedulerException extends ServerPluginException {
|
||||
+
|
||||
+ private final BukkitTask task;
|
||||
+
|
||||
+ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) {
|
||||
+ super(message, cause, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ public ServerSchedulerException(Throwable cause, BukkitTask task) {
|
||||
+ super(cause, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, task.getOwner());
|
||||
+ this.task = checkNotNull(task, "task");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the task which threw the exception
|
||||
+ *
|
||||
+ * @return exception throwing task
|
||||
+ */
|
||||
+ public BukkitTask getTask() {
|
||||
+ return task;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java
|
||||
@@ -0,0 +1,22 @@
|
||||
+package com.destroystokyo.paper.exception;
|
||||
+
|
||||
+import org.bukkit.command.Command;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a tab-complete request throws an exception
|
||||
+ */
|
||||
+public class ServerTabCompleteException extends ServerCommandException {
|
||||
+
|
||||
+ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, command, commandSender, arguments);
|
||||
+ }
|
||||
+
|
||||
+ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(cause, command, commandSender, arguments);
|
||||
+ }
|
||||
+
|
||||
+ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
||||
+ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
index f020cb04eba27a2e70fc7cf799ebbfb434b9d974..adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52 100644
|
||||
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
|
||||
@@ -8,6 +8,10 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
||||
+import com.destroystokyo.paper.exception.ServerCommandException;
|
||||
+import com.destroystokyo.paper.exception.ServerTabCompleteException;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
@@ -155,11 +159,14 @@ public class SimpleCommandMap implements CommandMap {
|
||||
target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length));
|
||||
} // target.timings.stopTiming(); // Spigot // Paper
|
||||
} catch (CommandException ex) {
|
||||
+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper
|
||||
//target.timings.stopTiming(); // Spigot // Paper
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
//target.timings.stopTiming(); // Spigot // Paper
|
||||
- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex);
|
||||
+ String msg = "Unhandled exception executing '" + commandLine + "' in " + target;
|
||||
+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper
|
||||
+ throw new CommandException(msg, ex);
|
||||
}
|
||||
|
||||
// return true as command was handled
|
||||
@@ -238,7 +245,9 @@ public class SimpleCommandMap implements CommandMap {
|
||||
} catch (CommandException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex);
|
||||
+ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target;
|
||||
+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerTabCompleteException(msg, ex, target, sender, args))); // Paper
|
||||
+ throw new CommandException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
index 7548e40af8043c1b5716f2d7d0122833466854c4..c2c49ee9b5531bc4761d2da54cd707c57fc647bf 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -23,6 +23,10 @@ import java.util.WeakHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
||||
+import com.destroystokyo.paper.exception.ServerEventException;
|
||||
+import com.destroystokyo.paper.exception.ServerPluginEnableDisableException;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
@@ -478,7 +482,8 @@ public final class SimplePluginManager implements PluginManager {
|
||||
try {
|
||||
plugin.getPluginLoader().enablePlugin(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while enabling "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin);
|
||||
}
|
||||
|
||||
HandlerList.bakeAll();
|
||||
@@ -499,32 +504,37 @@ public final class SimplePluginManager implements PluginManager {
|
||||
try {
|
||||
plugin.getPluginLoader().disablePlugin(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while disabling "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getScheduler().cancelTasks(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getServicesManager().unregisterAll(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering services for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
HandlerList.unregisterAll(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering events for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
server.getMessenger().unregisterIncomingPluginChannel(plugin);
|
||||
server.getMessenger().unregisterOutgoingPluginChannel(plugin);
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||
+ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for "
|
||||
+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -537,6 +547,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
|
||||
+ server.getLogger().log(Level.SEVERE, msg, ex);
|
||||
+ callEvent(new ServerExceptionEvent(new ServerPluginEnableDisableException(msg, ex, plugin)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void clearPlugins() {
|
||||
synchronized (this) {
|
||||
@@ -600,7 +617,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex);
|
||||
+ // Paper start - error reporting
|
||||
+ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
|
||||
+ server.getLogger().log(Level.SEVERE, msg, ex);
|
||||
+ if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop
|
||||
+ callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event)));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
577
patches/api/0019-Player-Tab-List-and-Title-APIs.patch
Normal file
577
patches/api/0019-Player-Tab-List-and-Title-APIs.patch
Normal file
|
@ -0,0 +1,577 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Mon, 29 Feb 2016 20:02:40 -0600
|
||||
Subject: [PATCH] Player Tab List and Title APIs
|
||||
|
||||
Co-authored-by: Fruxz <cedricspitzer@outlook.de>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb902cb35d8c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/Title.java
|
||||
@@ -0,0 +1,420 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import net.md_5.bungee.api.chat.BaseComponent;
|
||||
+import net.md_5.bungee.api.chat.TextComponent;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Collection;
|
||||
+import java.util.List;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkArgument;
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+import static com.google.common.base.Preconditions.checkState;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a title to may be sent to a {@link Player}.
|
||||
+ *
|
||||
+ * <p>A title can be sent without subtitle text.</p>
|
||||
+ *
|
||||
+ * @deprecated use {@link net.kyori.adventure.title.Title}
|
||||
+ */
|
||||
+@Deprecated
|
||||
+public final class Title {
|
||||
+
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to fade in.
|
||||
+ */
|
||||
+ public static final int DEFAULT_FADE_IN = 20;
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to stay.
|
||||
+ */
|
||||
+ public static final int DEFAULT_STAY = 200;
|
||||
+ /**
|
||||
+ * The default number of ticks for the title to fade out.
|
||||
+ */
|
||||
+ public static final int DEFAULT_FADE_OUT = 20;
|
||||
+
|
||||
+ private final BaseComponent[] title;
|
||||
+ private final BaseComponent[] subtitle;
|
||||
+ private final int fadeIn;
|
||||
+ private final int stay;
|
||||
+ private final int fadeOut;
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent[] title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values and no subtitle.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ public Title(@NotNull String title) {
|
||||
+ this(title, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title with the default time values.
|
||||
+ *
|
||||
+ * <p>Times use default values.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ */
|
||||
+ public Title(@NotNull String title, @Nullable String subtitle) {
|
||||
+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ * @throws IllegalArgumentException if any of the times are negative
|
||||
+ */
|
||||
+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ this(
|
||||
+ new BaseComponent[]{checkNotNull(title, "title")},
|
||||
+ subtitle == null ? null : new BaseComponent[]{subtitle},
|
||||
+ fadeIn,
|
||||
+ stay,
|
||||
+ fadeOut
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ * @throws IllegalArgumentException if any of the times are negative
|
||||
+ */
|
||||
+ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
||||
+ checkArgument(stay >= 0, "Negative stay: %s", stay);
|
||||
+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
||||
+ this.title = checkNotNull(title, "title");
|
||||
+ this.subtitle = subtitle;
|
||||
+ this.fadeIn = fadeIn;
|
||||
+ this.stay = stay;
|
||||
+ this.fadeOut = fadeOut;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a new title.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} constrctors.</p>
|
||||
+ *
|
||||
+ * @param title the main text of the title
|
||||
+ * @param subtitle the secondary text of the title
|
||||
+ * @param fadeIn the number of ticks for the title to fade in
|
||||
+ * @param stay the number of ticks for the title to stay on screen
|
||||
+ * @param fadeOut the number of ticks for the title to fade out
|
||||
+ */
|
||||
+ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
+ this(
|
||||
+ TextComponent.fromLegacyText(checkNotNull(title, "title")),
|
||||
+ subtitle == null ? null : TextComponent.fromLegacyText(subtitle),
|
||||
+ fadeIn,
|
||||
+ stay,
|
||||
+ fadeOut
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the text of this title
|
||||
+ *
|
||||
+ * @return the text
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public BaseComponent[] getTitle() {
|
||||
+ return this.title;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the text of this title's subtitle
|
||||
+ *
|
||||
+ * @return the text
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public BaseComponent[] getSubtitle() {
|
||||
+ return this.subtitle;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to fade in.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to fade in
|
||||
+ */
|
||||
+ public int getFadeIn() {
|
||||
+ return this.fadeIn;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to stay.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to stay
|
||||
+ */
|
||||
+ public int getStay() {
|
||||
+ return this.stay;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the number of ticks to fade out.
|
||||
+ *
|
||||
+ * <p>The returned value is never negative.</p>
|
||||
+ *
|
||||
+ * @return the number of ticks to fade out
|
||||
+ */
|
||||
+ public int getFadeOut() {
|
||||
+ return this.fadeOut;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to an player
|
||||
+ *
|
||||
+ * @param player the receiver of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Player player) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to the defined players
|
||||
+ *
|
||||
+ * @param players the receivers of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Collection<? extends Player> players) {
|
||||
+ for (Player player : players) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to the defined players
|
||||
+ *
|
||||
+ * @param players the receivers of the title
|
||||
+ */
|
||||
+ public void send(@NotNull Player[] players) {
|
||||
+ for (Player player : players) {
|
||||
+ player.sendTitle(this);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the title directly to all online players
|
||||
+ */
|
||||
+ public void broadcast() {
|
||||
+ send(Bukkit.getOnlinePlayers());
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static Builder builder() {
|
||||
+ return new Builder();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * A builder for creating titles
|
||||
+ */
|
||||
+ public static final class Builder {
|
||||
+
|
||||
+ private BaseComponent[] title;
|
||||
+ private BaseComponent[] subtitle;
|
||||
+ private int fadeIn = DEFAULT_FADE_IN;
|
||||
+ private int stay = DEFAULT_STAY;
|
||||
+ private int fadeOut = DEFAULT_FADE_OUT;
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull BaseComponent title) {
|
||||
+ return this.title(new BaseComponent[]{checkNotNull(title, "title")});
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull BaseComponent[] title) {
|
||||
+ this.title = checkNotNull(title, "title");
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the title to the given text.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} methods.</p>
|
||||
+ *
|
||||
+ * @param title the title text
|
||||
+ * @return this builder instance
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder title(@NotNull String title) {
|
||||
+ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title")));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable BaseComponent subtitle) {
|
||||
+ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle});
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable BaseComponent[] subtitle) {
|
||||
+ this.subtitle = subtitle;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the subtitle to the given text.
|
||||
+ *
|
||||
+ * <p>It is recommended to the {@link BaseComponent} methods.</p>
|
||||
+ *
|
||||
+ * @param subtitle the title text
|
||||
+ * @return this builder instance
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder subtitle(@Nullable String subtitle) {
|
||||
+ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to fade in
|
||||
+ *
|
||||
+ * @param fadeIn the number of ticks to fade in
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder fadeIn(int fadeIn) {
|
||||
+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
|
||||
+ this.fadeIn = fadeIn;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to stay.
|
||||
+ *
|
||||
+ * @param stay the number of ticks to stay
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder stay(int stay) {
|
||||
+ checkArgument(stay >= 0, "Negative stay: %s", stay);
|
||||
+ this.stay = stay;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the number of ticks for the title to fade out.
|
||||
+ *
|
||||
+ * @param fadeOut the number of ticks to fade out
|
||||
+ * @return this builder instance
|
||||
+ * @throws IllegalArgumentException if it is negative
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Builder fadeOut(int fadeOut) {
|
||||
+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
|
||||
+ this.fadeOut = fadeOut;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a title based on the values in the builder.
|
||||
+ *
|
||||
+ * @return a title from the values in this builder
|
||||
+ * @throws IllegalStateException if title isn't specified
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Title build() {
|
||||
+ checkState(title != null, "Title not specified");
|
||||
+ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 4686212255e8de3e5a6f43d86f28fad595f687ed..769ad98fd7a6a866b320e1ccffd7962228d564cf 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2,6 +2,7 @@ package org.bukkit.entity;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
+import com.destroystokyo.paper.Title; // Paper
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.GameMode;
|
||||
@@ -648,6 +649,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
spigot().sendMessage(position, components);
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Set the text displayed in the player list header and footer for this player
|
||||
+ *
|
||||
+ * @param header content for the top of the player list
|
||||
+ * @param footer content for the bottom of the player list
|
||||
+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer);
|
||||
+
|
||||
+ /**
|
||||
+ * Set the text displayed in the player list header and footer for this player
|
||||
+ *
|
||||
+ * @param header content for the top of the player list
|
||||
+ * @param footer content for the bottom of the player list
|
||||
+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the times for titles displayed to the player
|
||||
+ *
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the subtitle of titles displayed to the player
|
||||
+ *
|
||||
+ * @param subtitle Subtitle to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle);
|
||||
+
|
||||
+ /**
|
||||
+ * Update the subtitle of titles displayed to the player
|
||||
+ *
|
||||
+ * @param subtitle Subtitle to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title to the player, along with the last subtitle set, using the last set times
|
||||
+ *
|
||||
+ * @param title Title to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title to the player, along with the last subtitle set, using the last set times
|
||||
+ *
|
||||
+ * @param title Title to set
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title and subtitle to the player using the given times
|
||||
+ *
|
||||
+ * @param title big text
|
||||
+ * @param subtitle little text under it
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the given title and subtitle to the player using the given times
|
||||
+ *
|
||||
+ * @param title big text
|
||||
+ * @param subtitle little text under it
|
||||
+ * @param fadeInTicks ticks to fade-in
|
||||
+ * @param stayTicks ticks to stay visible
|
||||
+ * @param fadeOutTicks ticks to fade-out
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the title to the player, overriding any previously displayed title.
|
||||
+ *
|
||||
+ * <p>This method overrides any previous title, use {@link #updateTitle(Title)} to change the existing one.</p>
|
||||
+ *
|
||||
+ * @param title the title to send
|
||||
+ * @throws NullPointerException if the title is null
|
||||
+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void sendTitle(@NotNull Title title);
|
||||
+
|
||||
+ /**
|
||||
+ * Show the title to the player, overriding any previously displayed title.
|
||||
+ *
|
||||
+ * <p>This method doesn't override previous titles, but changes their values.</p>
|
||||
+ *
|
||||
+ * @param title the title to send
|
||||
+ * @throws NullPointerException if title is null
|
||||
+ * @deprecated use {@link #showTitle(net.kyori.adventure.title.Title)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void updateTitle(@NotNull Title title);
|
||||
+
|
||||
+ /**
|
||||
+ * Hide any title that is currently visible to the player
|
||||
+ *
|
||||
+ * @deprecated use {@link #clearTitle()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void hideTitle();
|
||||
// Paper end
|
||||
|
||||
/**
|
|
@ -0,0 +1,27 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 29 Feb 2016 20:26:39 -0600
|
||||
Subject: [PATCH] Fix ServerListPingEvent flagging as Async
|
||||
|
||||
This event can sometimes fire Async, set the proper boolean
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/server/ServerEvent.java b/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
index 46b119017a1e3dfcd9ae5fb91b4fe8c20b0d6b86..05167fb34e4c42edc67af6e6700a2a3cc0f92769 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/ServerEvent.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.event.server;
|
||||
|
||||
+import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
/**
|
||||
@@ -8,7 +9,7 @@ import org.bukkit.event.Event;
|
||||
public abstract class ServerEvent extends Event {
|
||||
|
||||
public ServerEvent() {
|
||||
- super();
|
||||
+ super(!Bukkit.isPrimaryThread()); // Paper
|
||||
}
|
||||
|
||||
public ServerEvent(boolean isAsync) {
|
|
@ -0,0 +1,54 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Tue, 8 Mar 2016 13:05:59 -0800
|
||||
Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java
|
||||
index c88418c7aa19b4fecdfa9af3d18ff202a5dc5763..fb0e608fa92dae99b9eee8fc1cbdf4b91a33e620 100644
|
||||
--- a/src/main/java/org/bukkit/command/CommandSender.java
|
||||
+++ b/src/main/java/org/bukkit/command/CommandSender.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.bukkit.command;
|
||||
|
||||
import java.util.UUID;
|
||||
+import net.kyori.adventure.audience.MessageType;
|
||||
+import net.kyori.adventure.identity.Identity;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -117,5 +120,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe
|
||||
default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) {
|
||||
this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message));
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Sends the component to the sender
|
||||
+ *
|
||||
+ * <p>If this sender does not support sending full components then
|
||||
+ * the component will be sent as legacy text.</p>
|
||||
+ *
|
||||
+ * @param component the component to send
|
||||
+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
|
||||
+ this.sendMessage(component.toLegacyText());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sends an array of components as a single message to the sender
|
||||
+ *
|
||||
+ * <p>If this sender does not support sending full components then
|
||||
+ * the components will be sent as legacy text.</p>
|
||||
+ *
|
||||
+ * @param components the components to send
|
||||
+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
+ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText());
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mrapple <tony@oc.tc>
|
||||
Date: Sun, 25 Nov 2012 13:47:27 -0600
|
||||
Subject: [PATCH] Add methods for working with arrows stuck in living entities
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
index 24c858182f25496cc7254f7cf9e996b3bea1f9ec..45e9f585c3e522ecf94a6bc42cdc190e1a191a5c 100644
|
||||
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
@@ -605,4 +605,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
* @return Whether the entity is invisible
|
||||
*/
|
||||
public boolean isInvisible();
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Get the number of arrows stuck in this entity
|
||||
+ * @return Number of arrows stuck
|
||||
+ */
|
||||
+ int getArrowsStuck();
|
||||
+
|
||||
+ /**
|
||||
+ * Set the number of arrows stuck in this entity
|
||||
+ *
|
||||
+ * @param arrows Number of arrows to stick in this entity
|
||||
+ */
|
||||
+ void setArrowsStuck(int arrows);
|
||||
+ // Paper end
|
||||
}
|
118
patches/api/0023-Complete-resource-pack-API.patch
Normal file
118
patches/api/0023-Complete-resource-pack-API.patch
Normal file
|
@ -0,0 +1,118 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sat, 4 Apr 2015 22:59:54 -0400
|
||||
Subject: [PATCH] Complete resource pack API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a281530b82262 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1124,7 +1124,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @throws IllegalArgumentException Thrown if the URL is null.
|
||||
* @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
* length restriction is an implementation specific arbitrary value.
|
||||
+ * @deprecated use {@link #setResourcePack(String, String)}
|
||||
*/
|
||||
+ @Deprecated // Paper
|
||||
public void setResourcePack(@NotNull String url);
|
||||
|
||||
/**
|
||||
@@ -1601,6 +1603,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
|
||||
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName())));
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Request that the player's client download and switch resource packs.
|
||||
+ * <p>
|
||||
+ * The player's client will download the new resource pack asynchronously
|
||||
+ * in the background, and will automatically switch to it once the
|
||||
+ * download is complete. If the client has downloaded and cached the same
|
||||
+ * resource pack in the past, it will perform a quick timestamp check
|
||||
+ * over the network to determine if the resource pack has changed and
|
||||
+ * needs to be downloaded again. When this request is sent for the very
|
||||
+ * first time from a given server, the client will first display a
|
||||
+ * confirmation GUI to the player before proceeding with the download.
|
||||
+ * <p>
|
||||
+ * Notes:
|
||||
+ * <ul>
|
||||
+ * <li>Players can disable server resources on their client, in which
|
||||
+ * case this method will have no affect on them.
|
||||
+ * <li>There is no concept of resetting resource packs back to default
|
||||
+ * within Minecraft, so players will have to relog to do so.
|
||||
+ * </ul>
|
||||
+ *
|
||||
+ * @param url The URL from which the client will download the resource
|
||||
+ * pack. The string must contain only US-ASCII characters and should
|
||||
+ * be encoded as per RFC 1738.
|
||||
+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of
|
||||
+ * the resource pack file.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is null.
|
||||
+ * @throws IllegalArgumentException Thrown if the URL is too long. The
|
||||
+ * length restriction is an implementation specific arbitrary value.
|
||||
+ */
|
||||
+ void setResourcePack(@NotNull String url, @NotNull String hash);
|
||||
+
|
||||
+ /**
|
||||
+ * @return the most recent resource pack status received from the player,
|
||||
+ * or null if no status has ever been received from this player.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus();
|
||||
+
|
||||
+ /**
|
||||
+ * @return the most recent resource pack hash received from the player,
|
||||
+ * or null if no hash has ever been received from this player.
|
||||
+ *
|
||||
+ * @deprecated This is no longer sent from the client and will always be null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @Deprecated
|
||||
+ String getResourcePackHash();
|
||||
+
|
||||
+ /**
|
||||
+ * @return true if the last resource pack status received from this player
|
||||
+ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED}
|
||||
+ */
|
||||
+ boolean hasResourcePack();
|
||||
// Paper end
|
||||
|
||||
// Spigot start
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
index b98195650d49d78ec35970ca0376b6289b861e4b..4c2102a11c3d682d98f0db4ccafa35231e66bcdd 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java
|
||||
@@ -11,13 +11,32 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class PlayerResourcePackStatusEvent extends PlayerEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
+ @Deprecated
|
||||
+ private final String hash; // Paper
|
||||
private final Status status;
|
||||
|
||||
public PlayerResourcePackStatusEvent(@NotNull final Player who, @NotNull Status resourcePackStatus) {
|
||||
super(who);
|
||||
+ this.hash = null; // Paper
|
||||
this.status = resourcePackStatus;
|
||||
}
|
||||
|
||||
+ @Deprecated // Paper
|
||||
+ public PlayerResourcePackStatusEvent(final Player who, Status resourcePackStatus, String hash) {
|
||||
+ super(who);
|
||||
+ this.hash = hash; // Paper
|
||||
+ this.status = resourcePackStatus;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ /**
|
||||
+ * @deprecated Hash does not seem to ever be set
|
||||
+ */
|
||||
+ public String getHash() {
|
||||
+ return this.hash;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the status of this pack.
|
||||
*
|
398
patches/api/0024-Use-ASM-for-event-executors.patch
Normal file
398
patches/api/0024-Use-ASM-for-event-executors.patch
Normal file
|
@ -0,0 +1,398 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Thu, 3 Mar 2016 13:20:33 -0700
|
||||
Subject: [PATCH] Use ASM for event executors.
|
||||
|
||||
Uses method handles for private or static methods.
|
||||
|
||||
diff --git a/pom.xml b/pom.xml
|
||||
index cae43ce5c1287a4cd117fd069d34ebc1b64b7fdb..2c757ffb2253748c6a81f9b373290108209b6ff2 100644
|
||||
--- a/pom.xml
|
||||
+++ b/pom.xml
|
||||
@@ -163,6 +163,17 @@
|
||||
<version>9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
+ <!-- ASM -->
|
||||
+ <dependency>
|
||||
+ <groupId>org.ow2.asm</groupId>
|
||||
+ <artifactId>asm</artifactId>
|
||||
+ <version>9.0</version>
|
||||
+ </dependency>
|
||||
+ <dependency>
|
||||
+ <groupId>org.ow2.asm</groupId>
|
||||
+ <artifactId>asm-commons</artifactId>
|
||||
+ <version>9.0</version>
|
||||
+ </dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
|
||||
@@ -0,0 +1,42 @@
|
||||
+package com.destroystokyo.paper.event.executor;
|
||||
+
|
||||
+import java.lang.invoke.MethodHandle;
|
||||
+import java.lang.invoke.MethodHandles;
|
||||
+import java.lang.reflect.Method;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.SneakyThrow;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.EventException;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class MethodHandleEventExecutor implements EventExecutor {
|
||||
+ private final Class<? extends Event> eventClass;
|
||||
+ private final MethodHandle handle;
|
||||
+
|
||||
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
|
||||
+ this.eventClass = eventClass;
|
||||
+ this.handle = handle;
|
||||
+ }
|
||||
+
|
||||
+ public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
||||
+ this.eventClass = eventClass;
|
||||
+ try {
|
||||
+ m.setAccessible(true);
|
||||
+ this.handle = MethodHandles.lookup().unreflect(m);
|
||||
+ } catch (IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to set accessible", e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ try {
|
||||
+ handle.invoke(listener, event);
|
||||
+ } catch (Throwable t) {
|
||||
+ SneakyThrow.sneaky(t);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c83672427324bd068ed52916f700b68446a226f6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package com.destroystokyo.paper.event.executor;
|
||||
+
|
||||
+import java.lang.invoke.MethodHandle;
|
||||
+import java.lang.invoke.MethodHandles;
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.SneakyThrow;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.EventException;
|
||||
+import org.bukkit.event.Listener;
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public class StaticMethodHandleEventExecutor implements EventExecutor {
|
||||
+ private final Class<? extends Event> eventClass;
|
||||
+ private final MethodHandle handle;
|
||||
+
|
||||
+ public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
|
||||
+ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
|
||||
+ Preconditions.checkArgument(eventClass != null, "eventClass is null");
|
||||
+ this.eventClass = eventClass;
|
||||
+ try {
|
||||
+ m.setAccessible(true);
|
||||
+ this.handle = MethodHandles.lookup().unreflect(m);
|
||||
+ } catch (IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to set accessible", e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ try {
|
||||
+ handle.invoke(event);
|
||||
+ } catch (Throwable throwable) {
|
||||
+ SneakyThrow.sneaky(throwable);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b6e7d8ee8d903ebf975d60bec0e08603d9a49fdb
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java
|
||||
@@ -0,0 +1,47 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.util.concurrent.atomic.AtomicInteger;
|
||||
+
|
||||
+import org.bukkit.plugin.EventExecutor;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.objectweb.asm.ClassWriter;
|
||||
+import org.objectweb.asm.Type;
|
||||
+import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
+
|
||||
+import static org.objectweb.asm.Opcodes.*;
|
||||
+
|
||||
+public class ASMEventExecutorGenerator {
|
||||
+ @NotNull
|
||||
+ public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) {
|
||||
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
+ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)});
|
||||
+ // Generate constructor
|
||||
+ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null), ACC_PUBLIC, "<init>", "()V");
|
||||
+ methodGenerator.loadThis();
|
||||
+ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // Invoke the super class (Object) constructor
|
||||
+ methodGenerator.returnValue();
|
||||
+ methodGenerator.endMethod();
|
||||
+ // Generate the execute method
|
||||
+ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");;
|
||||
+ methodGenerator.loadArg(0);
|
||||
+ methodGenerator.checkCast(Type.getType(m.getDeclaringClass()));
|
||||
+ methodGenerator.loadArg(1);
|
||||
+ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0]));
|
||||
+ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface());
|
||||
+ if (m.getReturnType() != void.class) {
|
||||
+ methodGenerator.pop();
|
||||
+ }
|
||||
+ methodGenerator.returnValue();
|
||||
+ methodGenerator.endMethod();
|
||||
+ writer.visitEnd();
|
||||
+ return writer.toByteArray();
|
||||
+ }
|
||||
+
|
||||
+ public static AtomicInteger NEXT_ID = new AtomicInteger(1);
|
||||
+ @NotNull
|
||||
+ public static String generateName() {
|
||||
+ int id = NEXT_ID.getAndIncrement();
|
||||
+ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java
|
||||
@@ -0,0 +1,34 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public interface ClassDefiner {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if the defined classes can bypass access checks
|
||||
+ *
|
||||
+ * @return if classes bypass access checks
|
||||
+ */
|
||||
+ public default boolean isBypassAccessChecks() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Define a class
|
||||
+ *
|
||||
+ * @param parentLoader the parent classloader
|
||||
+ * @param name the name of the class
|
||||
+ * @param data the class data to load
|
||||
+ * @return the defined class
|
||||
+ * @throws ClassFormatError if the class data is invalid
|
||||
+ * @throws NullPointerException if any of the arguments are null
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data);
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static ClassDefiner getInstance() {
|
||||
+ return SafeClassDefiner.INSTANCE;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ac99477e9f2c08041aeff31abc1d1edee58d0a67
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java
|
||||
@@ -0,0 +1,66 @@
|
||||
+package com.destroystokyo.paper.event.executor.asm;
|
||||
+
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ConcurrentMap;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import com.google.common.collect.MapMaker;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.objectweb.asm.Type;
|
||||
+
|
||||
+public class SafeClassDefiner implements ClassDefiner {
|
||||
+ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
|
||||
+
|
||||
+ private SafeClassDefiner() {}
|
||||
+
|
||||
+ private final ConcurrentMap<ClassLoader, GeneratedClassLoader> loaders = new MapMaker().weakKeys().makeMap();
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) {
|
||||
+ GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
|
||||
+ synchronized (loader.getClassLoadingLock(name)) {
|
||||
+ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
|
||||
+ Class<?> c = loader.define(name, data);
|
||||
+ assert c.getName().equals(name);
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class GeneratedClassLoader extends ClassLoader {
|
||||
+ static {
|
||||
+ ClassLoader.registerAsParallelCapable();
|
||||
+ }
|
||||
+
|
||||
+ protected GeneratedClassLoader(@NotNull ClassLoader parent) {
|
||||
+ super(parent);
|
||||
+ }
|
||||
+
|
||||
+ private Class<?> define(@NotNull String name, byte[] data) {
|
||||
+ synchronized (getClassLoadingLock(name)) {
|
||||
+ assert !hasClass(name);
|
||||
+ Class<?> c = defineClass(name, data, 0, data.length);
|
||||
+ resolveClass(c);
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public Object getClassLoadingLock(@NotNull String name) {
|
||||
+ return super.getClassLoadingLock(name);
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasClass(@NotNull String name) {
|
||||
+ synchronized (getClassLoadingLock(name)) {
|
||||
+ try {
|
||||
+ Class.forName(name);
|
||||
+ return true;
|
||||
+ } catch (ClassNotFoundException e) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java
|
||||
@@ -5,9 +5,75 @@ import org.bukkit.event.EventException;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
+// Paper start
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ConcurrentMap;
|
||||
+import java.util.function.Function;
|
||||
+
|
||||
+import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor;
|
||||
+import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor;
|
||||
+import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator;
|
||||
+import com.destroystokyo.paper.event.executor.asm.ClassDefiner;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+// Paper end
|
||||
+
|
||||
/**
|
||||
* Interface which defines the class for event call backs to plugins
|
||||
*/
|
||||
public interface EventExecutor {
|
||||
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException;
|
||||
+
|
||||
+ // Paper start
|
||||
+ ConcurrentMap<Method, Class<? extends EventExecutor>> eventExecutorMap = new ConcurrentHashMap<Method, Class<? extends EventExecutor>>() {
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public Class<? extends EventExecutor> computeIfAbsent(@NotNull Method key, @NotNull Function<? super Method, ? extends Class<? extends EventExecutor>> mappingFunction) {
|
||||
+ Class<? extends EventExecutor> executorClass = get(key);
|
||||
+ if (executorClass != null)
|
||||
+ return executorClass;
|
||||
+
|
||||
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
+ synchronized (key) {
|
||||
+ executorClass = get(key);
|
||||
+ if (executorClass != null)
|
||||
+ return executorClass;
|
||||
+
|
||||
+ return super.computeIfAbsent(key, mappingFunction);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static EventExecutor create(@NotNull Method m, @NotNull Class<? extends Event> eventClass) {
|
||||
+ Preconditions.checkNotNull(m, "Null method");
|
||||
+ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount());
|
||||
+ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass);
|
||||
+ ClassDefiner definer = ClassDefiner.getInstance();
|
||||
+ if (Modifier.isStatic(m.getModifiers())) {
|
||||
+ return new StaticMethodHandleEventExecutor(eventClass, m);
|
||||
+ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) {
|
||||
+ // get the existing generated EventExecutor class for the Method or generate one
|
||||
+ Class<? extends EventExecutor> executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> {
|
||||
+ String name = ASMEventExecutorGenerator.generateName();
|
||||
+ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name);
|
||||
+ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class);
|
||||
+ });
|
||||
+
|
||||
+ try {
|
||||
+ EventExecutor asmExecutor = executorClass.newInstance();
|
||||
+ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception)
|
||||
+ return (listener, event) -> {
|
||||
+ if (!eventClass.isInstance(event)) return;
|
||||
+ asmExecutor.execute(listener, event);
|
||||
+ };
|
||||
+ } catch (InstantiationException | IllegalAccessException e) {
|
||||
+ throw new AssertionError("Unable to initialize generated event executor", e);
|
||||
+ }
|
||||
+ } else {
|
||||
+ return new MethodHandleEventExecutor(eventClass, m);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
index 2e306c7b984a02e12a74fac14589bf29ab6488bf..79ac529017aac059d13fe342f279e9c8faeba599 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
@@ -291,21 +291,7 @@ public final class JavaPluginLoader implements PluginLoader {
|
||||
}
|
||||
}
|
||||
|
||||
- EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper
|
||||
- @Override
|
||||
- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper
|
||||
- try {
|
||||
- if (!eventClass.isAssignableFrom(event.getClass())) {
|
||||
- return;
|
||||
- }
|
||||
- method.invoke(listener, event);
|
||||
- } catch (InvocationTargetException ex) {
|
||||
- throw new EventException(ex.getCause());
|
||||
- } catch (Throwable t) {
|
||||
- throw new EventException(t);
|
||||
- }
|
||||
- }
|
||||
- }, plugin, method, eventClass); // Paper
|
||||
+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); // Paper // Paper (Yes.) - Use factory method `EventExecutor.create()`
|
||||
if (false) { // Spigot - RL handles useTimings check now
|
||||
eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
|
||||
} else {
|
34
patches/api/0025-Add-a-call-helper-to-Event.patch
Normal file
34
patches/api/0025-Add-a-call-helper-to-Event.patch
Normal file
|
@ -0,0 +1,34 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 19 May 2013 20:36:58 -0400
|
||||
Subject: [PATCH] Add a call helper to Event
|
||||
|
||||
Reduces diff in Server patches
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java
|
||||
index 18d0636b749913bfdcea8eebc7d0840d192fb071..8ec56cd6b8e0f5c5dd8c7c88b4671e18dcf109d0 100644
|
||||
--- a/src/main/java/org/bukkit/event/Event.java
|
||||
+++ b/src/main/java/org/bukkit/event/Event.java
|
||||
@@ -35,6 +35,22 @@ public abstract class Event {
|
||||
this.async = isAsync;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Calls the event and tests if cancelled.
|
||||
+ *
|
||||
+ * @return false if event was cancelled, if cancellable. otherwise true.
|
||||
+ */
|
||||
+ public boolean callEvent() {
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(this);
|
||||
+ if (this instanceof Cancellable) {
|
||||
+ return !((Cancellable) this).isCancelled();
|
||||
+ } else {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Convenience method for providing a user-friendly identifier. By
|
||||
* default, it is the event's class's {@linkplain Class#getSimpleName()
|
|
@ -0,0 +1,43 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 22 Jul 2015 18:50:41 -0400
|
||||
Subject: [PATCH] Add sender name to commands.yml replacement
|
||||
|
||||
This allows you to use $sender in commands.yml definitions to make
|
||||
commands that auto target self.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
index a6ad94ef98a1df1d2842635d850bc990b0137849..9d4f553c04784cca63901a56a7aea62a5cae1d72 100644
|
||||
--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.bukkit.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
+import java.util.regex.Matcher; // Paper
|
||||
+import java.util.regex.Pattern; // Paper
|
||||
+
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -19,7 +22,7 @@ public class FormattedCommandAlias extends Command {
|
||||
ArrayList<String> commands = new ArrayList<String>();
|
||||
for (String formatString : formatStrings) {
|
||||
try {
|
||||
- commands.add(buildCommand(formatString, args));
|
||||
+ commands.add(buildCommand(sender, formatString, args)); // Paper
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof IllegalArgumentException) {
|
||||
sender.sendMessage(throwable.getMessage());
|
||||
@@ -37,7 +40,10 @@ public class FormattedCommandAlias extends Command {
|
||||
return result;
|
||||
}
|
||||
|
||||
- private String buildCommand(@NotNull String formatString, @NotNull String[] args) {
|
||||
+ private String buildCommand(@NotNull CommandSender sender, @NotNull String formatString, @NotNull String[] args) { // Paper
|
||||
+ if (formatString.contains("$sender")) { // Paper
|
||||
+ formatString = formatString.replaceAll(Pattern.quote("$sender"), Matcher.quoteReplacement(sender.getName())); // Paper
|
||||
+ } // Paper
|
||||
int index = formatString.indexOf('$');
|
||||
while (index != -1) {
|
||||
int start = index;
|
|
@ -0,0 +1,104 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William <admin@domnian.com>
|
||||
Date: Fri, 18 Mar 2016 03:28:07 -0400
|
||||
Subject: [PATCH] Add command to reload permissions.yml and require confirm to
|
||||
reload
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 8646fc0987a8833996c5d977c36fe0d01bf72992..72375883b07ede041a7ea5f7b6785f71aef702c0 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -1752,6 +1752,13 @@ public final class Bukkit {
|
||||
public static org.bukkit.command.CommandMap getCommandMap() {
|
||||
return server.getCommandMap();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Reload the Permissions in permissions.yml
|
||||
+ */
|
||||
+ public static void reloadPermissions() {
|
||||
+ server.reloadPermissions();
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@NotNull
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 599347ef656acad9a40be15fc5030e5d0f1630df..a2940eafa61814aae7f766262309495e991533d6 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1549,4 +1549,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@NotNull
|
||||
Spigot spigot();
|
||||
// Spigot end
|
||||
+
|
||||
+ void reloadPermissions(); // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..c62da4131b17e66892678e8b618fb9ba3de93b56 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java
|
||||
@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand {
|
||||
public ReloadCommand(@NotNull String name) {
|
||||
super(name);
|
||||
this.description = "Reloads the server configuration and plugins";
|
||||
- this.usageMessage = "/reload";
|
||||
+ this.usageMessage = "/reload [permissions]"; // Paper
|
||||
this.setPermission("bukkit.command.reload");
|
||||
this.setAliases(Arrays.asList("rl"));
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
|
||||
+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper
|
||||
if (!testPermission(sender)) return true;
|
||||
|
||||
+ // Paper start - Reload permissions.yml & require confirm
|
||||
+ boolean confirmed = System.getProperty("LetMeReload") != null;
|
||||
+ if (args.length == 1) {
|
||||
+ if (args[0].equalsIgnoreCase("permissions")) {
|
||||
+ Bukkit.getServer().reloadPermissions();
|
||||
+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded.");
|
||||
+ return true;
|
||||
+ } else if ("confirm".equalsIgnoreCase(args[0])) {
|
||||
+ confirmed = true;
|
||||
+ } else {
|
||||
+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Usage: " + usageMessage);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!confirmed) {
|
||||
+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type " + ChatColor.YELLOW + "/reload confirm");
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins.");
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server.");
|
||||
Bukkit.reload();
|
||||
@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException {
|
||||
- return Collections.emptyList();
|
||||
+ return java.util.Collections.singletonList("permissions"); // Paper
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
index c2c49ee9b5531bc4761d2da54cd707c57fc647bf..2d27dfb859c312d46a14d0356c7c3f227e965a67 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -895,4 +895,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
public void useTimings(boolean use) {
|
||||
co.aikar.timings.Timings.setTimingsEnabled(use); // Paper
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public void clearPermissions() {
|
||||
+ permissions.clear();
|
||||
+ defaultPerms.get(true).clear();
|
||||
+ defaultPerms.get(false).clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
}
|
48
patches/api/0028-Custom-replacement-for-eaten-items.patch
Normal file
48
patches/api/0028-Custom-replacement-for-eaten-items.patch
Normal file
|
@ -0,0 +1,48 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Sun, 21 Jun 2015 15:05:21 -0400
|
||||
Subject: [PATCH] Custom replacement for eaten items
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
index c2793f3ef01c1246c130971c17e1c2bf8f551435..373f4b5b5185aa81ff728da89c9cc4e0ccf87889 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java
|
||||
@@ -22,6 +22,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private boolean isCancelled = false;
|
||||
private ItemStack item;
|
||||
+ @Nullable private ItemStack replacement; // Paper
|
||||
|
||||
/**
|
||||
* @param player the player consuming
|
||||
@@ -58,6 +59,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Return the custom item stack that will replace the consumed item, or null if no
|
||||
+ * custom replacement has been set (which means the default replacement will be used).
|
||||
+ *
|
||||
+ * @return The custom item stack that will replace the consumed item or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public ItemStack getReplacement() {
|
||||
+ return this.replacement;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set a custom item stack to replace the consumed item. Pass null to clear any custom
|
||||
+ * stack that has been set and use the default replacement.
|
||||
+ *
|
||||
+ * @param replacement Replacement item to set, null to clear any custom stack and use default
|
||||
+ */
|
||||
+ public void setReplacement(@Nullable ItemStack replacement) {
|
||||
+ this.replacement = replacement;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.isCancelled;
|
79
patches/api/0029-Entity-AddTo-RemoveFrom-World-Events.patch
Normal file
79
patches/api/0029-Entity-AddTo-RemoveFrom-World-Events.patch
Normal file
|
@ -0,0 +1,79 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 20:26:34 -0400
|
||||
Subject: [PATCH] Entity AddTo/RemoveFrom World Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..07660202e41ee86f1b66bad3335cf6fe126e7f9c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java
|
||||
@@ -0,0 +1,32 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired any time an entity is being added to the world for any reason.
|
||||
+ *
|
||||
+ * Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent}
|
||||
+ * This will fire anytime a chunk is reloaded too.
|
||||
+ */
|
||||
+public class EntityAddToWorldEvent extends EntityEvent {
|
||||
+
|
||||
+ public EntityAddToWorldEvent(@NotNull Entity entity) {
|
||||
+ super(entity);
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e5dbbd660409bae0d3b96e83390511d3a423a52e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Fired any time an entity is being removed from a world for any reason
|
||||
+ */
|
||||
+public class EntityRemoveFromWorldEvent extends EntityEvent {
|
||||
+
|
||||
+ public EntityRemoveFromWorldEvent(@NotNull Entity entity) {
|
||||
+ super(entity);
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
95
patches/api/0030-EntityPathfindEvent.patch
Normal file
95
patches/api/0030-EntityPathfindEvent.patch
Normal file
|
@ -0,0 +1,95 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 21:15:34 -0400
|
||||
Subject: [PATCH] EntityPathfindEvent
|
||||
|
||||
Fires when an Entity decides to start moving to a location.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..63e46b2fb1b12b36fcb1e98b178cf29dd2e3d1b5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java
|
||||
@@ -0,0 +1,82 @@
|
||||
+package com.destroystokyo.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Fired when an Entity decides to start moving towards a location.
|
||||
+ *
|
||||
+ * This event does not fire for the entities actual movement. Only when it
|
||||
+ * is choosing to start moving to a location.
|
||||
+ */
|
||||
+public class EntityPathfindEvent extends EntityEvent implements Cancellable {
|
||||
+ @Nullable private final Entity targetEntity;
|
||||
+ @NotNull private final Location loc;
|
||||
+
|
||||
+ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) {
|
||||
+ super(entity);
|
||||
+ this.targetEntity = targetEntity;
|
||||
+ this.loc = loc;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The Entity that is pathfinding.
|
||||
+ * @return The Entity that is pathfinding.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Entity getEntity() {
|
||||
+ return entity;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * If the Entity is trying to pathfind to an entity, this is the entity in relation.
|
||||
+ *
|
||||
+ * Otherwise this will return null.
|
||||
+ *
|
||||
+ * @return The entity target or null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Entity getTargetEntity() {
|
||||
+ return targetEntity;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * The Location of where the entity is about to move to.
|
||||
+ *
|
||||
+ * Note that if the target happened to of been an entity
|
||||
+ * @return Location of where the entity is trying to pathfind to.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getLoc() {
|
||||
+ return loc;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,90 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: crast <contact@jamescrasta.com>
|
||||
Date: Sat, 1 Jun 2013 13:52:30 -0600
|
||||
Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase
|
||||
|
||||
Use ConcurrentHashMap to allow thread-safe access methods and very
|
||||
limited synchronized portions to allow much higher concurrency in
|
||||
MetadataStore as well as far less locking, especially on reads
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
index baf850226aed8545a5794deba6dff9603953b4b2..d363d517c05b3335101d829ce4ec22d049059c24 100644
|
||||
--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class MetadataStoreBase<T> {
|
||||
- private Map<String, Map<Plugin, MetadataValue>> metadataMap = new HashMap<String, Map<Plugin, MetadataValue>>();
|
||||
+ private Map<String, Map<Plugin, MetadataValue>> metadataMap = new java.util.concurrent.ConcurrentHashMap<String, Map<Plugin, MetadataValue>>(); // Paper
|
||||
|
||||
/**
|
||||
* Adds a metadata value to an object. Each metadata value is owned by a
|
||||
@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase<T> {
|
||||
entry = new WeakHashMap<Plugin, MetadataValue>(1);
|
||||
metadataMap.put(key, entry);
|
||||
}
|
||||
- entry.put(owningPlugin, newMetadataValue);
|
||||
+ synchronized (entry) {
|
||||
+ entry.put(owningPlugin, newMetadataValue);
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @see MetadataStore#getMetadata(Object, String)
|
||||
*/
|
||||
@NotNull
|
||||
- public synchronized List<MetadataValue> getMetadata(@NotNull T subject, @NotNull String metadataKey) {
|
||||
+ public List<MetadataValue> getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
- if (metadataMap.containsKey(key)) {
|
||||
- Collection<MetadataValue> values = metadataMap.get(key).values();
|
||||
+ Map<Plugin, MetadataValue> entry = metadataMap.get(key);
|
||||
+ if (entry != null) {
|
||||
+ Collection<MetadataValue> values = entry.values();
|
||||
return Collections.unmodifiableList(new ArrayList<MetadataValue>(values));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @param metadataKey the unique metadata key being queried.
|
||||
* @return the existence of the metadataKey within subject.
|
||||
*/
|
||||
- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) {
|
||||
+ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
return metadataMap.containsKey(key);
|
||||
}
|
||||
@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @see MetadataStore#removeMetadata(Object, String,
|
||||
* org.bukkit.plugin.Plugin)
|
||||
*/
|
||||
- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) {
|
||||
+ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper
|
||||
Validate.notNull(owningPlugin, "Plugin cannot be null");
|
||||
String key = disambiguate(subject, metadataKey);
|
||||
Map<Plugin, MetadataValue> entry = metadataMap.get(key);
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
-
|
||||
- entry.remove(owningPlugin);
|
||||
- if (entry.isEmpty()) {
|
||||
- metadataMap.remove(key);
|
||||
+ synchronized (entry) {
|
||||
+ entry.remove(owningPlugin);
|
||||
+ if (entry.isEmpty()) {
|
||||
+ metadataMap.remove(key);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase<T> {
|
||||
* @throws IllegalArgumentException If plugin is null
|
||||
* @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin)
|
||||
*/
|
||||
- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) {
|
||||
+ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper
|
||||
Validate.notNull(owningPlugin, "Plugin cannot be null");
|
||||
for (Map<Plugin, MetadataValue> values : metadataMap.values()) {
|
||||
if (values.containsKey(owningPlugin)) {
|
|
@ -0,0 +1,46 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 16 Jul 2013 21:26:50 -0400
|
||||
Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin)
|
||||
|
||||
So that on reload, metadata will be cleared
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
index d363d517c05b3335101d829ce4ec22d049059c24..abbe545af572687a0399c2387434863cd2b70f68 100644
|
||||
--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
+import java.util.Iterator; // Paper
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase<T> {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Removes all metadata in the metadata store that originates from the
|
||||
+ * given plugin.
|
||||
+ *
|
||||
+ * @param owningPlugin the plugin requesting the invalidation.
|
||||
+ * @throws IllegalArgumentException If plugin is null
|
||||
+ */
|
||||
+ public void removeAll(@NotNull Plugin owningPlugin) {
|
||||
+ Validate.notNull(owningPlugin, "Plugin cannot be null");
|
||||
+ for (Iterator<Map<Plugin, MetadataValue>> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) {
|
||||
+ Map<Plugin, MetadataValue> values = iterator.next();
|
||||
+ if (values.containsKey(owningPlugin)) {
|
||||
+ values.remove(owningPlugin);
|
||||
+ }
|
||||
+ if (values.isEmpty()) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Creates a unique name for the object receiving metadata by combining
|
||||
* unique data from the subject with a metadataKey.
|
Loading…
Add table
Add a link
Reference in a new issue