more patches
This commit is contained in:
parent
f72886c9a6
commit
5dce4d9178
53 changed files with 654 additions and 952 deletions
120
patches/api/0240-Add-PlayerShearBlockEvent.patch
Normal file
120
patches/api/0240-Add-PlayerShearBlockEvent.patch
Normal file
|
@ -0,0 +1,120 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: JRoy <joshroy126@gmail.com>
|
||||
Date: Thu, 27 Aug 2020 12:32:35 -0400
|
||||
Subject: [PATCH] Add PlayerShearBlockEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..aa7d440b797eac9e62678d03cc87f42838758bfd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java
|
||||
@@ -0,0 +1,108 @@
|
||||
+package io.papermc.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.player.PlayerEvent;
|
||||
+import org.bukkit.inventory.EquipmentSlot;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a player uses sheers on a block.
|
||||
+ * <p>
|
||||
+ * This event is <b>not</b> called when breaking blocks with shears but instead only when a
|
||||
+ * player uses the sheer item on a block to garner drops from said block and/or change its state.
|
||||
+ * <p>
|
||||
+ * Examples include shearing a pumpkin to turn it into a carved pumpkin or shearing a beehive to get honeycomb.
|
||||
+ */
|
||||
+public class PlayerShearBlockEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled = false;
|
||||
+ private final Block block;
|
||||
+ private final ItemStack item;
|
||||
+ private final EquipmentSlot hand;
|
||||
+ private final List<ItemStack> drops;
|
||||
+
|
||||
+ public PlayerShearBlockEvent(@NotNull Player who, @NotNull Block block, @NotNull ItemStack item, @NotNull EquipmentSlot hand, @NotNull List<ItemStack> drops) {
|
||||
+ super(who);
|
||||
+ this.block = block;
|
||||
+ this.item = item;
|
||||
+ this.hand = hand;
|
||||
+ this.drops = drops;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block being sheared in this event.
|
||||
+ *
|
||||
+ * @return The {@link Block} which block is being sheared in this event.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Block getBlock() {
|
||||
+ return block;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the item used to shear the block.
|
||||
+ *
|
||||
+ * @return The {@link ItemStack} of the shears.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ItemStack getItem() {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the hand used to shear the block.
|
||||
+ *
|
||||
+ * @return Either {@link EquipmentSlot#HAND} OR {@link EquipmentSlot#OFF_HAND}.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public EquipmentSlot getHand() {
|
||||
+ return hand;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the resulting drops of this event.
|
||||
+ *
|
||||
+ * @return A {@link List list} of {@link ItemStack items} that will be dropped as result of this event.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public List<ItemStack> getDrops() {
|
||||
+ return drops;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether the shearing of the block should be cancelled or not.
|
||||
+ *
|
||||
+ * @return Whether the shearing of the block should be cancelled or not.
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether the shearing of the block should be cancelled or not.
|
||||
+ *
|
||||
+ * @param cancel whether the shearing of the block should be cancelled or not.
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
30
patches/api/0241-Enable-multi-release-plugin-jars.patch
Normal file
30
patches/api/0241-Enable-multi-release-plugin-jars.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <demonwav@gmail.com>
|
||||
Date: Fri, 4 Dec 2020 15:53:19 -0800
|
||||
Subject: [PATCH] Enable multi-release plugin jars
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
index 6b5d7c350c216b7a234d96ecacae1d39a1acd814..18cf36020bca7c174a775de75241f149ef4e45e7 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
@@ -58,7 +58,18 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot
|
||||
this.description = description;
|
||||
this.dataFolder = dataFolder;
|
||||
this.file = file;
|
||||
- this.jar = new JarFile(file);
|
||||
+ // Paper - enable multi-release jars for Java 9+
|
||||
+ JarFile jarFile;
|
||||
+ try {
|
||||
+ final java.lang.reflect.Method runtimeVersionMethod = JarFile.class.getMethod("runtimeVersion");
|
||||
+ final Object runtimeVersion = runtimeVersionMethod.invoke(null);
|
||||
+ @SuppressWarnings("JavaReflectionMemberAccess") final java.lang.reflect.Constructor<JarFile> constructor = JarFile.class.getConstructor(File.class, boolean.class, int.class, runtimeVersion.getClass());
|
||||
+ jarFile = constructor.newInstance(file, true, java.util.zip.ZipFile.OPEN_READ, runtimeVersion);
|
||||
+ } catch (Exception ignored) {
|
||||
+ jarFile = new JarFile(file);
|
||||
+ }
|
||||
+ this.jar = jarFile;
|
||||
+ // Paper end
|
||||
this.manifest = jar.getManifest();
|
||||
this.url = file.toURI().toURL();
|
||||
this.libraryLoader = libraryLoader;
|
100
patches/api/0242-Player-Chunk-Load-Unload-Events.patch
Normal file
100
patches/api/0242-Player-Chunk-Load-Unload-Events.patch
Normal file
|
@ -0,0 +1,100 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ysl3000 <yannicklamprecht@live.de>
|
||||
Date: Mon, 5 Oct 2020 21:24:45 +0200
|
||||
Subject: [PATCH] Player Chunk Load/Unload Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2c1cda1126e577a88f19071e958eddb5a38785af
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java
|
||||
@@ -0,0 +1,42 @@
|
||||
+package io.papermc.paper.event.packet;
|
||||
+
|
||||
+import org.bukkit.Chunk;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.world.ChunkEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Is called when a {@link org.bukkit.entity.Player} receives a {@link org.bukkit.Chunk}
|
||||
+ * <p>
|
||||
+ * Can for example be used for spawning a fake entity when the player receives a chunk.
|
||||
+ *
|
||||
+ * Should only be used for packet/clientside related stuff.
|
||||
+ * Not intended for modifying server side state.
|
||||
+ */
|
||||
+public class PlayerChunkLoadEvent extends ChunkEvent {
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final Player player;
|
||||
+
|
||||
+ public PlayerChunkLoadEvent(@NotNull Chunk chunk, @NotNull Player player) {
|
||||
+ super(chunk);
|
||||
+ this.player = player;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java
|
||||
@@ -0,0 +1,40 @@
|
||||
+package io.papermc.paper.event.packet;
|
||||
+
|
||||
+import org.bukkit.Chunk;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.world.ChunkEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Is called when a {@link Player} receives a chunk unload packet.
|
||||
+ *
|
||||
+ * Should only be used for packet/clientside related stuff.
|
||||
+ * Not intended for modifying server side.
|
||||
+ */
|
||||
+public class PlayerChunkUnloadEvent extends ChunkEvent {
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final Player player;
|
||||
+
|
||||
+ public PlayerChunkUnloadEvent(@NotNull Chunk chunk, @NotNull Player player) {
|
||||
+ super(chunk);
|
||||
+ this.player = player;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public Player getPlayer() {
|
||||
+ return player;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
30
patches/api/0243-Expose-LivingEntity-hurt-direction.patch
Normal file
30
patches/api/0243-Expose-LivingEntity-hurt-direction.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Sun, 13 Dec 2020 05:32:12 +0200
|
||||
Subject: [PATCH] Expose LivingEntity hurt direction
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
index b96b5f4f2fc754298e2223b2f449a0755469278c..b6de41e3e718fa5d1b82c6f68b153e60a81265e7 100644
|
||||
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
|
||||
@@ -845,5 +845,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
* @param quantity quantity of item
|
||||
*/
|
||||
void playPickupItemAnimation(@NotNull Item item, int quantity);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets player hurt direction
|
||||
+ *
|
||||
+ * @return hurt direction
|
||||
+ */
|
||||
+ float getHurtDirection();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets player hurt direction
|
||||
+ *
|
||||
+ * @param hurtDirection hurt direction
|
||||
+ */
|
||||
+ void setHurtDirection(float hurtDirection);
|
||||
// Paper end
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 24 Dec 2020 12:43:30 -0800
|
||||
Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java
|
||||
index c7d57e286c11eaa578ff6fd457b02a9ff829aa71..24b371b11347abf31fda4dadde8e0a7af60b181b 100644
|
||||
--- a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java
|
||||
@@ -37,6 +37,12 @@ public class PlayerBedEnterEvent extends PlayerEvent implements Cancellable {
|
||||
* Entering the bed is prevented due to the player being too far away.
|
||||
*/
|
||||
TOO_FAR_AWAY,
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Bed was obstructed.
|
||||
+ */
|
||||
+ OBSTRUCTED,
|
||||
+ // Paper end
|
||||
/**
|
||||
* Entering the bed is prevented due to there being monsters nearby.
|
||||
*/
|
166
patches/api/0245-Added-PlayerTradeEvent.patch
Normal file
166
patches/api/0245-Added-PlayerTradeEvent.patch
Normal file
|
@ -0,0 +1,166 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 2 Jul 2020 16:10:10 -0700
|
||||
Subject: [PATCH] Added PlayerTradeEvent
|
||||
|
||||
[Amendment: Alexander <protonull@protonmail.com>]
|
||||
PlayerTradeEvent is used for player purchases from villagers and wandering
|
||||
traders, but not custom merchants created via Bukkit.createMerchant(). During
|
||||
discussions in Discord it was decided that it'd be better to add a new event
|
||||
that PlayerTradeEvent inherits from than change getVillager()'s annotation to
|
||||
@Nullable, especially since that'd also infringe on the implication of the
|
||||
event being about villager trades.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c5648055c5e815474bf1e564a5c192ff5c0624fb
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java
|
||||
@@ -0,0 +1,112 @@
|
||||
+package io.papermc.paper.event.player;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.bukkit.inventory.MerchantRecipe;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a player trades with a standalone merchant GUI.
|
||||
+ */
|
||||
+public class PlayerPurchaseEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled;
|
||||
+
|
||||
+ private boolean increaseTradeUses;
|
||||
+ private boolean rewardExp;
|
||||
+ private MerchantRecipe trade;
|
||||
+
|
||||
+ public PlayerPurchaseEvent(@NotNull Player player,
|
||||
+ @NotNull MerchantRecipe trade,
|
||||
+ boolean rewardExp,
|
||||
+ boolean increaseTradeUses) {
|
||||
+ super(Objects.requireNonNull(player, "Player cannot be null!"));
|
||||
+ setTrade(trade);
|
||||
+ this.rewardExp = rewardExp;
|
||||
+ this.increaseTradeUses = increaseTradeUses;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the associated trade with this event
|
||||
+ * @return the trade
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public MerchantRecipe getTrade() {
|
||||
+ return this.trade;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the trade. This is then used to determine the next prices
|
||||
+ * @param trade the trade to use
|
||||
+ */
|
||||
+ public void setTrade(@NotNull MerchantRecipe trade) {
|
||||
+ this.trade = Objects.requireNonNull(trade, "Trade cannot be null!");
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return will trade try to reward exp
|
||||
+ */
|
||||
+ public boolean isRewardingExp() {
|
||||
+ return this.rewardExp;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether the trade will try to reward exp
|
||||
+ * @param rewardExp try to reward exp
|
||||
+ */
|
||||
+ public void setRewardExp(boolean rewardExp) {
|
||||
+ this.rewardExp = rewardExp;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return whether or not the trade will count as a use of the trade
|
||||
+ */
|
||||
+ public boolean willIncreaseTradeUses() {
|
||||
+ return this.increaseTradeUses;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether or not the trade will count as a use
|
||||
+ * @param increaseTradeUses true to count/false to not count
|
||||
+ */
|
||||
+ public void setIncreaseTradeUses(boolean increaseTradeUses) {
|
||||
+ this.increaseTradeUses = increaseTradeUses;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the cancellation state of this event. A cancelled event will not
|
||||
+ * be executed in the server, but will still pass to other plugins
|
||||
+ *
|
||||
+ * @return true if this event is cancelled
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return this.cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the cancellation state of this event. A cancelled event will not
|
||||
+ * be executed in the server, but will still pass to other plugins.
|
||||
+ *
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..a41fc186746b87f76347dfcc1f80d0969398322b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package io.papermc.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.entity.AbstractVillager;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.inventory.MerchantRecipe;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a player trades with a villager or wandering trader
|
||||
+ */
|
||||
+public class PlayerTradeEvent extends PlayerPurchaseEvent {
|
||||
+
|
||||
+ private final AbstractVillager villager;
|
||||
+
|
||||
+ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) {
|
||||
+ super(player, trade, rewardExp, increaseTradeUses);
|
||||
+ this.villager = villager;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the Villager or Wandering trader associated with this event
|
||||
+ * @return the villager or wandering trader
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public AbstractVillager getVillager() {
|
||||
+ return this.villager;
|
||||
+ }
|
||||
+
|
||||
+}
|
81
patches/api/0246-Add-TargetHitEvent-API.patch
Normal file
81
patches/api/0246-Add-TargetHitEvent-API.patch
Normal file
|
@ -0,0 +1,81 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: jmp <jasonpenilla2@me.com>
|
||||
Date: Wed, 25 Nov 2020 23:21:32 -0800
|
||||
Subject: [PATCH] Add TargetHitEvent API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..cc067ae118af9957b1b9f5c8d45f63f9154f4942
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java
|
||||
@@ -0,0 +1,69 @@
|
||||
+package io.papermc.paper.event.block;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.entity.Projectile;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a Target Block is hit by a projectile.
|
||||
+ * <p>
|
||||
+ * Cancelling this event will stop the Target from emitting a redstone signal,
|
||||
+ * and in the case that the shooter is a player, will stop them from receiving
|
||||
+ * advancement criteria.
|
||||
+ */
|
||||
+public class TargetHitEvent extends ProjectileHitEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private boolean cancelled;
|
||||
+ private int signalStrength;
|
||||
+
|
||||
+ public TargetHitEvent(@NotNull Projectile projectile, @NotNull Block block, @NotNull BlockFace blockFace, int signalStrength) {
|
||||
+ super(projectile, null, block, blockFace);
|
||||
+ this.signalStrength = signalStrength;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancelled) {
|
||||
+ this.cancelled = cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the strength of the redstone signal to be emitted by the Target block
|
||||
+ *
|
||||
+ * @return the strength of the redstone signal to be emitted
|
||||
+ */
|
||||
+ public int getSignalStrength() {
|
||||
+ return signalStrength;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the strength of the redstone signal to be emitted by the Target block
|
||||
+ *
|
||||
+ * @param signalStrength the strength of the redstone signal to be emitted
|
||||
+ */
|
||||
+ public void setSignalStrength(int signalStrength) {
|
||||
+ if (signalStrength < 0 || signalStrength > 15) {
|
||||
+ throw new IllegalArgumentException("Signal strength out of range (" + signalStrength + "), must be in range [0,15]");
|
||||
+ }
|
||||
+ this.signalStrength = signalStrength;
|
||||
+ }
|
||||
+}
|
57
patches/api/0247-Additional-Block-Material-API-s.patch
Normal file
57
patches/api/0247-Additional-Block-Material-API-s.patch
Normal file
|
@ -0,0 +1,57 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 30 Dec 2020 17:27:27 -0500
|
||||
Subject: [PATCH] Additional Block Material API's
|
||||
|
||||
Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower
|
||||
process to do this in the Bukkit API
|
||||
|
||||
Adds API for buildable, replaceable, burnable too.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
|
||||
index e759a03ccf7b341db36f455879e0004a6d6d4d07..b3c127a3d4c554c08e500497a54755e626342dd3 100644
|
||||
--- a/src/main/java/org/bukkit/block/Block.java
|
||||
+++ b/src/main/java/org/bukkit/block/Block.java
|
||||
@@ -428,6 +428,42 @@ public interface Block extends Metadatable {
|
||||
*/
|
||||
boolean isLiquid();
|
||||
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Check if this block is solid
|
||||
+ * <p>
|
||||
+ * Determined by Minecraft, typically a block a player can use to place a new block to build things.
|
||||
+ * An example of a non buildable block would be liquids, flowers, or fire
|
||||
+ *
|
||||
+ * @return true if block is buildable
|
||||
+ */
|
||||
+ boolean isBuildable();
|
||||
+ /**
|
||||
+ * Check if this block is burnable
|
||||
+ * <p>
|
||||
+ * Determined by Minecraft, typically a block that fire can destroy (Wool, Wood)
|
||||
+ *
|
||||
+ * @return true if block is burnable
|
||||
+ */
|
||||
+ boolean isBurnable();
|
||||
+ /**
|
||||
+ * Check if this block is replaceable
|
||||
+ * <p>
|
||||
+ * Determined by Minecraft, representing a block that is not AIR that you can still place a new block at, such as flowers.
|
||||
+ * @return true if block is replaceable
|
||||
+ */
|
||||
+ boolean isReplaceable();
|
||||
+ /**
|
||||
+ * Check if this block is solid
|
||||
+ * <p>
|
||||
+ * Determined by Minecraft, typically a block a player can stand on and can't be passed through.
|
||||
+ *
|
||||
+ * This API is faster than accessing Material#isSolid as it avoids a material lookup and switch statement.
|
||||
+ * @return true if block is solid
|
||||
+ */
|
||||
+ boolean isSolid();
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Gets the temperature of this block.
|
||||
* <p>
|
|
@ -0,0 +1,58 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Miller <mnmiller1@me.com>
|
||||
Date: Thu, 31 Dec 2020 12:48:38 +1000
|
||||
Subject: [PATCH] Add API to get Material from Boats and Minecarts
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Boat.java b/src/main/java/org/bukkit/entity/Boat.java
|
||||
index 24751b5c4e3bc24bdfa85af8f6fcba37413aa002..e0d0537606d4f9a3fe588ebf7d02f314c0359335 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Boat.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Boat.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
+import org.bukkit.Material;
|
||||
import org.bukkit.TreeSpecies;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -103,4 +104,14 @@ public interface Boat extends Vehicle {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setWorkOnLand(boolean workOnLand);
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the {@link Material} that represents this Boat type.
|
||||
+ *
|
||||
+ * @return the boat material.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Material getBoatMaterial();
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/entity/Minecart.java b/src/main/java/org/bukkit/entity/Minecart.java
|
||||
index 95c79c5fa0c4e30201f887da6467ce5f81c8a255..53b042f8ebbbf6ee77435b93d4e89371375cc515 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Minecart.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Minecart.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.bukkit.entity;
|
||||
|
||||
+import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -143,4 +144,14 @@ public interface Minecart extends Vehicle {
|
||||
* @return the current block offset for this minecart.
|
||||
*/
|
||||
public int getDisplayBlockOffset();
|
||||
+
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Gets the {@link Material} that represents this Minecart type.
|
||||
+ *
|
||||
+ * @return the minecart material.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Material getMinecartMaterial();
|
||||
+ // Paper end
|
||||
}
|
94
patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch
Normal file
94
patches/api/0249-Add-PlayerFlowerPotManipulateEvent.patch
Normal file
|
@ -0,0 +1,94 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MisterVector <whizkid3000@hotmail.com>
|
||||
Date: Tue, 13 Aug 2019 19:44:19 -0700
|
||||
Subject: [PATCH] Add PlayerFlowerPotManipulateEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4c141f3d8f668cdf9c75865a8e3ecbd012d9e521
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java
|
||||
@@ -0,0 +1,82 @@
|
||||
+package io.papermc.paper.event.player;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a player places an item in or takes an item out of a flowerpot.
|
||||
+ */
|
||||
+public class PlayerFlowerPotManipulateEvent extends PlayerEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull
|
||||
+ private final Block flowerpot;
|
||||
+ @NotNull
|
||||
+ private final ItemStack item;
|
||||
+ private final boolean placing;
|
||||
+
|
||||
+ private boolean cancel = false;
|
||||
+
|
||||
+ public PlayerFlowerPotManipulateEvent(@NotNull final Player player, @NotNull final Block flowerpot, @NotNull final ItemStack item, final boolean placing) {
|
||||
+ super(player);
|
||||
+ this.flowerpot = flowerpot;
|
||||
+ this.item = item;
|
||||
+ this.placing = placing;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancel;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancel = cancel;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the flowerpot that is involved in this event.
|
||||
+ *
|
||||
+ * @return the flowerpot that is involved with this event
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Block getFlowerpot() {
|
||||
+ return flowerpot;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the item being placed, or taken from, the flower pot.
|
||||
+ * Check if placing with {@link #isPlacing()}.
|
||||
+ *
|
||||
+ * @return the item placed, or taken from, the flowerpot
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public ItemStack getItem() {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets if the item is being placed into the flowerpot.
|
||||
+ *
|
||||
+ * @return if the item is being placed into the flowerpot
|
||||
+ */
|
||||
+ public boolean isPlacing() {
|
||||
+ return placing;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
30
patches/api/0250-Zombie-API-breaking-doors.patch
Normal file
30
patches/api/0250-Zombie-API-breaking-doors.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 18 Nov 2020 11:32:15 -0800
|
||||
Subject: [PATCH] Zombie API - breaking doors
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java
|
||||
index 1217576e6f08abf0175ab800cfca058d5deda116..a39fbc9fa0903be8ed8e89f3ef39f93c02dfc90b 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Zombie.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Zombie.java
|
||||
@@ -140,5 +140,19 @@ public interface Zombie extends Monster, Ageable {
|
||||
* @param shouldBurnInDay True to burn in sunlight
|
||||
*/
|
||||
void setShouldBurnInDay(boolean shouldBurnInDay);
|
||||
+
|
||||
+ /**
|
||||
+ * Check if this zombie can break doors
|
||||
+ *
|
||||
+ * @return True if zombie can break doors
|
||||
+ */
|
||||
+ boolean canBreakDoors();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets if this zombie can break doors
|
||||
+ *
|
||||
+ * @param canBreakDoors True if zombie can break doors
|
||||
+ */
|
||||
+ void setCanBreakDoors(boolean canBreakDoors);
|
||||
// Paper end
|
||||
}
|
113
patches/api/0251-Add-EntityLoadCrossbowEvent.patch
Normal file
113
patches/api/0251-Add-EntityLoadCrossbowEvent.patch
Normal file
|
@ -0,0 +1,113 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: JRoy <joshroy126@gmail.com>
|
||||
Date: Wed, 7 Oct 2020 12:04:17 -0400
|
||||
Subject: [PATCH] Add EntityLoadCrossbowEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..287f487b266d5c12fcf6f028452735e314d55636
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java
|
||||
@@ -0,0 +1,101 @@
|
||||
+package io.papermc.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.entity.LivingEntity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.bukkit.inventory.EquipmentSlot;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a LivingEntity loads a crossbow with a projectile.
|
||||
+ */
|
||||
+public class EntityLoadCrossbowEvent extends EntityEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final ItemStack crossbow;
|
||||
+ private final EquipmentSlot hand;
|
||||
+ private boolean cancelled;
|
||||
+ private boolean consumeItem = true;
|
||||
+
|
||||
+ public EntityLoadCrossbowEvent(@NotNull LivingEntity entity, @Nullable ItemStack crossbow, @NotNull EquipmentSlot hand) {
|
||||
+ super(entity);
|
||||
+ this.crossbow = crossbow;
|
||||
+ this.hand = hand;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public LivingEntity getEntity() {
|
||||
+ return (LivingEntity) entity;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the crossbow {@link ItemStack} being loaded.
|
||||
+ *
|
||||
+ * @return the crossbow involved in this event
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public ItemStack getCrossbow() {
|
||||
+ return crossbow;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the hand from which the crossbow was loaded.
|
||||
+ *
|
||||
+ * @return the hand
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public EquipmentSlot getHand() {
|
||||
+ return hand;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ *
|
||||
+ * @return should the itemstack be consumed
|
||||
+ */
|
||||
+ public boolean shouldConsumeItem() {
|
||||
+ return consumeItem;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ *
|
||||
+ * @param consume should the item be consumed
|
||||
+ */
|
||||
+ public void setConsumeItem(boolean consume) {
|
||||
+ this.consumeItem = consume;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Set whether or not to cancel the crossbow being loaded. If canceled, the
|
||||
+ * projectile that would be loaded into the crossbow will not be consumed.
|
||||
+ *
|
||||
+ * If set to false, and this event is pertaining to a player entity,
|
||||
+ * it's recommended that a call to {@link Player#updateInventory()} is made
|
||||
+ * as the client may think the server still loaded an item into the crossbow.
|
||||
+ *
|
||||
+ * @param cancel true if you wish to cancel this event
|
||||
+ */
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
103
patches/api/0252-Added-WorldGameRuleChangeEvent.patch
Normal file
103
patches/api/0252-Added-WorldGameRuleChangeEvent.patch
Normal file
|
@ -0,0 +1,103 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 20 Dec 2020 16:41:44 -0800
|
||||
Subject: [PATCH] Added WorldGameRuleChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..20c25a0f9d65188402e8bb3981348bc6462904bf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java
|
||||
@@ -0,0 +1,91 @@
|
||||
+package io.papermc.paper.event.world;
|
||||
+
|
||||
+import org.bukkit.GameRule;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.world.WorldEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a world's gamerule is changed, either by command or by api.
|
||||
+ */
|
||||
+public class WorldGameRuleChangeEvent extends WorldEvent implements Cancellable {
|
||||
+
|
||||
+ private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
+
|
||||
+ private final CommandSender commandSender;
|
||||
+ private final GameRule<?> gameRule;
|
||||
+ private String value;
|
||||
+ private boolean cancelled;
|
||||
+
|
||||
+ public WorldGameRuleChangeEvent(@NotNull World world, @Nullable CommandSender commandSender, @NotNull GameRule<?> gameRule, @NotNull String value) {
|
||||
+ super(world);
|
||||
+ this.commandSender = commandSender;
|
||||
+ this.gameRule = gameRule;
|
||||
+ this.value = value;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the command sender associated with this event.
|
||||
+ *
|
||||
+ * @return {@code null} if the gamerule was changed via api, otherwise the {@link CommandSender}.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public CommandSender getCommandSender() {
|
||||
+ return commandSender;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the game rule associated with this event.
|
||||
+ *
|
||||
+ * @return the gamerule being changed.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public GameRule<?> getGameRule() {
|
||||
+ return gameRule;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the new value of the gamerule.
|
||||
+ *
|
||||
+ * @return the new value of the gamerule.
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getValue() {
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the new value of this gamerule.
|
||||
+ *
|
||||
+ * @param value the new value of the gamerule.
|
||||
+ */
|
||||
+ public void setValue(@NotNull String value) {
|
||||
+ this.value = value;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+}
|
Loading…
Add table
Add a link
Reference in a new issue