diff --git a/build-data/mcdev-imports.txt b/build-data/mcdev-imports.txt new file mode 100644 index 0000000..6837ce8 --- /dev/null +++ b/build-data/mcdev-imports.txt @@ -0,0 +1,6 @@ +# You can use this file to import files from vanilla into the project +# both fully qualified and a file based syntax are accepted here: +# net.minecraft.world.level.entity.LevelEntityGetterAdapter +# net/minecraft/world/level/entity/LevelEntityGetter.java +net.minecraft.world.damagesource.BadRespawnPointDamage +net.minecraft.world.level.block.RespawnAnchorBlock \ No newline at end of file diff --git a/build-data/parchment.at b/build-data/parchment.at new file mode 100644 index 0000000..a5ca7a7 --- /dev/null +++ b/build-data/parchment.at @@ -0,0 +1,2 @@ +# Add UnsafeValues#canPlaceItemOn +public net.minecraft.world.item.BlockItem canPlace(Lnet/minecraft/world/item/context/BlockPlaceContext;Lnet/minecraft/world/level/block/state/BlockState;)Z diff --git a/patches/api/0001-Build-changes.patch b/patches/api/0001-Build-changes.patch new file mode 100644 index 0000000..54b0ebb --- /dev/null +++ b/patches/api/0001-Build-changes.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Thu, 17 Jun 2021 14:38:59 -0400 +Subject: [PATCH] Build changes + + +diff --git a/build.gradle.kts b/build.gradle.kts +index 6d04816e22f44a33c001d2b7e080402fba6af86c..8dea8af5898cfe89e6aa4a8d278eba32fc4214cf 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -27,6 +27,7 @@ dependencies { + api("org.ow2.asm:asm:9.0") + api("org.ow2.asm:asm-commons:9.0") + api("org.apache.logging.log4j:log4j-api:2.14.1") // Paper ++ api(project(":Parchment-Common")) // Parchment + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/patches/api/0002-Add-Getter-interfaces.patch b/patches/api/0002-Add-Getter-interfaces.patch new file mode 100644 index 0000000..bee764b --- /dev/null +++ b/patches/api/0002-Add-Getter-interfaces.patch @@ -0,0 +1,1157 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Fri, 18 Jun 2021 14:12:56 -0400 +Subject: [PATCH] Add Getter interfaces + +Creates new interfaces for objects that have a reference to a player, offlineplayer, location, etc. + +Also creates interfaces for objects that are like players in that they use all other interfaces and can receive Adventure messages. + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +index 978813b94a5eae0afccbd3b38b463091a46b56ac..14d057791db091e49b5be7cf9700435e8811edbc 100644 +--- a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Called when a beacon effect is being applied to a player. + */ +-public class BeaconEffectEvent extends BlockEvent implements Cancellable { ++public class BeaconEffectEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private PotionEffect effect; +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java +index f530a3d9314e17d1da896cac633f6a422258d9a9..af6e9a654940ed0a9a434501d20dfe225155f4f2 100644 +--- a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java +@@ -38,7 +38,7 @@ import org.jetbrains.annotations.NotNull; + * at the Enderman, according to Vanilla rules. + * + */ +-public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable { ++public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + @NotNull private final Player player; + + public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) { +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java +index a315c5185cd465dcf63c0ababef195da76dfc786..ea39b1dd25e00d9e8a8db86a05105297eb46d9bc 100644 +--- a/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java +@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Fired when a Turtle lays eggs + */ +-public class TurtleLayEggEvent extends EntityEvent implements Cancellable { ++public class TurtleLayEggEvent extends EntityEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled = false; + @NotNull +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java +index abeb24fccda2acfdb0dfdadacb8fe688bd97cf78..03f8ddd864eac5d87aba29f791022a6719cd054f 100644 +--- a/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java +@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Fired when a Turtle starts digging to lay eggs + */ +-public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable { ++public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled = false; + @NotNull private final Location location; +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +index a077962fa786a3291849abfa823c7f0ec4664fce..7895fe36f6f6f2e47d506a1704494d6cb71f3db7 100644 +--- a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; + * + *

WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

+ */ +-public class PlayerHandshakeEvent extends Event implements Cancellable { ++public class PlayerHandshakeEvent extends Event implements Cancellable, me.lexikiq.OptionalUniqueId { // Parchment + + private static final HandlerList HANDLERS = new HandlerList(); + @NotNull private final String originalHandshake; +diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java +index 4dcf6242c9acc62d030a94f67b78729ed29f8c85..18fd6889457f1a9d7663c7631ce83b847eb458e2 100644 +--- a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java +@@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; + * No guarantees are made about thread execution context for this event. If you need to know, check + * event.isAsync() + */ +-public class PreLookupProfileEvent extends Event { ++public class PreLookupProfileEvent extends Event implements me.lexikiq.OptionalUniqueId { // Parchment + + private static final HandlerList handlers = new HandlerList(); + @NotNull private final String name; +@@ -49,11 +49,27 @@ public class PreLookupProfileEvent extends Event { + * {@link LookupProfileEvent} + * + * @return The UUID of the profile if it has already been provided by a plugin ++ * @deprecated alias of {@link #getUniqueId()} + */ + @Nullable +- public UUID getUUID() { ++ // Parchment start ++ @Deprecated ++ public final UUID getUUID() { ++ return getUniqueId(); ++ } ++ ++ /** ++ * If this value is left null by the completion of the event call, then the server will ++ * trigger a call to the Mojang API to look up the UUID (Network Request), and subsequently, fire a ++ * {@link LookupProfileEvent} ++ * ++ * @return The UUID of the profile if it has already been provided by a plugin ++ */ ++ @Override ++ public @Nullable UUID getUniqueId() { + return uuid; + } ++ // Parchment end + + /** + * Sets the UUID for this player name. This will skip the initial API call to find the players UUID. +diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +index 4cd97cb102e1ec53b3fe1a451b65b4b640fde099..2de2df06dcb7099e42a097ec2c74d45529cceb21 100644 +--- a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java ++++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +@@ -48,7 +48,7 @@ import org.jetbrains.annotations.Nullable; + * + * Only 1 process will be allowed to provide completions, the Async Event, or the standard process. + */ +-public class AsyncTabCompleteEvent extends Event implements Cancellable { ++public class AsyncTabCompleteEvent extends Event implements Cancellable, me.lexikiq.OptionalLocation { // Parchment + @NotNull private final CommandSender sender; + @NotNull private final String buffer; + private final boolean isCommand; +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +index 89e132525cfae0ce979e37b3e2793df781e47227..c06d406f0644aa7380581f81442878b95f555843 100644 +--- a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +@@ -8,7 +8,7 @@ import static com.google.common.base.Preconditions.*; + /** + * Thrown when an incoming plugin message channel throws an exception + */ +-public class ServerPluginMessageException extends ServerPluginException { ++public class ServerPluginMessageException extends ServerPluginException implements me.lexikiq.HasPlayer { // Parchment + + private final Player player; + private final String channel; +diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java +index 2c1cda1126e577a88f19071e958eddb5a38785af..a0994a7613a2b34a6b9ec850a8a0fc9254c89751 100644 +--- a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java ++++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; + * Should only be used for packet/clientside related stuff. + * Not intended for modifying server side state. + */ +-public class PlayerChunkLoadEvent extends ChunkEvent { ++public class PlayerChunkLoadEvent extends ChunkEvent implements me.lexikiq.HasPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private final Player player; +diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java +index 12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b..80e7db5cbc82e0ed69ea1a0f659fd3259ef0beb2 100644 +--- a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java ++++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; + * Should only be used for packet/clientside related stuff. + * Not intended for modifying server side. + */ +-public class PlayerChunkUnloadEvent extends ChunkEvent { ++public class PlayerChunkUnloadEvent extends ChunkEvent implements me.lexikiq.HasPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private final Player player; +diff --git a/src/main/java/me/lexikiq/HasHumanEntity.java b/src/main/java/me/lexikiq/HasHumanEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..46efc8787afe2eda000fc71a6a1f3c0f0d7da320 +--- /dev/null ++++ b/src/main/java/me/lexikiq/HasHumanEntity.java +@@ -0,0 +1,19 @@ ++package me.lexikiq; ++ ++import org.bukkit.entity.HumanEntity; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an object that has a {@link HumanEntity} ++ * @see me.lexikiq.OptionalHumanEntity ++ */ ++@FunctionalInterface ++public interface HasHumanEntity extends OptionalHumanEntity { ++ /** ++ * Gets a {@link HumanEntity} object that this represents ++ * ++ * @return human entity ++ */ ++ @Override ++ @NotNull HumanEntity getPlayer(); ++} +diff --git a/src/main/java/me/lexikiq/HasLocation.java b/src/main/java/me/lexikiq/HasLocation.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ac380c3f767f2d7a86ca2f9a3f7dbfcfc172e2be +--- /dev/null ++++ b/src/main/java/me/lexikiq/HasLocation.java +@@ -0,0 +1,18 @@ ++package me.lexikiq; ++ ++import org.bukkit.Location; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an object that has a {@link Location} ++ * @see OptionalLocation ++ */ ++public interface HasLocation extends OptionalLocation { ++ /** ++ * Gets a {@link Location} attached to this object ++ * ++ * @return attached location ++ */ ++ @Override ++ @NotNull Location getLocation(); ++} +diff --git a/src/main/java/me/lexikiq/HasOfflinePlayer.java b/src/main/java/me/lexikiq/HasOfflinePlayer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..33b04ae2dee02e53ffa070de6631f71e2ddaf998 +--- /dev/null ++++ b/src/main/java/me/lexikiq/HasOfflinePlayer.java +@@ -0,0 +1,17 @@ ++package me.lexikiq; ++ ++import org.bukkit.OfflinePlayer; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an object that has a {@link OfflinePlayer} ++ */ ++@FunctionalInterface ++public interface HasOfflinePlayer { ++ /** ++ * Gets an {@link OfflinePlayer} object that this represents ++ * ++ * @return offline player ++ */ ++ @NotNull OfflinePlayer getOfflinePlayer(); ++} +diff --git a/src/main/java/me/lexikiq/HasPlayer.java b/src/main/java/me/lexikiq/HasPlayer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..117e3994ffec1830f471b8810746f6e4088db298 +--- /dev/null ++++ b/src/main/java/me/lexikiq/HasPlayer.java +@@ -0,0 +1,19 @@ ++package me.lexikiq; ++ ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents an object that has a {@link Player} ++ * @see me.lexikiq.OptionalPlayer ++ */ ++@FunctionalInterface ++public interface HasPlayer extends OptionalPlayer, HasHumanEntity { ++ /** ++ * Gets a {@link Player} object that this represents ++ * ++ * @return player ++ */ ++ @Override ++ @NotNull Player getPlayer(); ++} +diff --git a/src/main/java/me/lexikiq/OptionalHumanEntity.java b/src/main/java/me/lexikiq/OptionalHumanEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..139887822a853876508b937f5288bfd117d15da6 +--- /dev/null ++++ b/src/main/java/me/lexikiq/OptionalHumanEntity.java +@@ -0,0 +1,18 @@ ++package me.lexikiq; ++ ++import org.bukkit.entity.HumanEntity; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents an object that may have a {@link HumanEntity} ++ * @see HasHumanEntity ++ */ ++@FunctionalInterface ++public interface OptionalHumanEntity { ++ /** ++ * Gets a {@link HumanEntity} object that this represents, if there is one ++ * ++ * @return human entity or null ++ */ ++ @Nullable HumanEntity getPlayer(); ++} +diff --git a/src/main/java/me/lexikiq/OptionalLocation.java b/src/main/java/me/lexikiq/OptionalLocation.java +new file mode 100644 +index 0000000000000000000000000000000000000000..10d06b9af2a9cfb2e80991d9916ca9953a25e42c +--- /dev/null ++++ b/src/main/java/me/lexikiq/OptionalLocation.java +@@ -0,0 +1,18 @@ ++package me.lexikiq; ++ ++import org.bukkit.Location; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents an object that may have a {@link Location} ++ * @see HasLocation ++ */ ++@FunctionalInterface ++public interface OptionalLocation { ++ /** ++ * Gets a {@link Location} attached to this object if present ++ * ++ * @return attached location ++ */ ++ @Nullable Location getLocation(); ++} +diff --git a/src/main/java/me/lexikiq/OptionalPlayer.java b/src/main/java/me/lexikiq/OptionalPlayer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6de254b174966ff9cc9e0ec091639885cd925b56 +--- /dev/null ++++ b/src/main/java/me/lexikiq/OptionalPlayer.java +@@ -0,0 +1,19 @@ ++package me.lexikiq; ++ ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents an object that may have a {@link Player} ++ * @see HasPlayer ++ */ ++@FunctionalInterface ++public interface OptionalPlayer extends OptionalHumanEntity { ++ /** ++ * Gets a {@link Player} object that this represents, if there is one. This may be null if the ++ * player is online or the player object being optional. ++ * ++ * @return player or null ++ */ ++ @Nullable Player getPlayer(); ++} +diff --git a/src/main/java/me/lexikiq/OptionalPlayerLike.java b/src/main/java/me/lexikiq/OptionalPlayerLike.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9ea2385c1f4de8bfd59bae284fb47e5a15026b55 +--- /dev/null ++++ b/src/main/java/me/lexikiq/OptionalPlayerLike.java +@@ -0,0 +1,189 @@ ++package me.lexikiq; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.bossbar.BossBar; ++import net.kyori.adventure.identity.Identified; ++import net.kyori.adventure.identity.Identity; ++import net.kyori.adventure.inventory.Book; ++import net.kyori.adventure.sound.Sound; ++import net.kyori.adventure.sound.SoundStop; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.title.Title; ++import org.apache.commons.lang3.Validate; ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.function.Consumer; ++ ++/** ++ * Class that may be like a {@link org.bukkit.entity.Player} in that it has a {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, {@link Identity}, and a nullable Player. ++ * @see me.lexikiq.PlayerLike ++ */ ++public interface OptionalPlayerLike extends OptionalPlayer, HasUniqueId, HasOfflinePlayer, OptionalLocation, Identified, Audience { ++ /** ++ * Gets the identity associated with this object ++ * ++ * @return associated identity ++ */ ++ @Override ++ default @NotNull Identity identity() { ++ return Identity.identity(getUniqueId()); ++ } ++ ++ /** ++ * Returns if the {@link Player} associated with this object is online. ++ * ++ * @return if the player is online ++ */ ++ default boolean isOnline() { ++ return getPlayer() != null; ++ } ++ ++ /** ++ * Run a consumer with the {@link Player} associated with this object if the player is online. ++ *

++ * Allows easily running a code on the player only if they are connected. ++ * ++ * @param consumer function that accepts a Player ++ */ ++ default void consumeIfOnline(final @NotNull Consumer<@NotNull Player> consumer) { ++ Validate.notNull(consumer, "Consumer should not be null"); ++ ++ final Player player = getPlayer(); ++ if (player != null) ++ consumer.accept(player); ++ } ++ ++ /** ++ * Sends a chat message. ++ * ++ * @param source the identity of the source of the message ++ * @param message a message ++ * @param type the type ++ */ ++ @Override ++ default void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { ++ consumeIfOnline(player -> player.sendMessage(source, message, type)); ++ } ++ ++ /** ++ * Sends a message on the action bar. ++ * ++ * @param message a message ++ */ ++ @Override ++ default void sendActionBar(final @NotNull Component message) { ++ consumeIfOnline(player -> player.sendActionBar(message)); ++ } ++ ++ /** ++ * Sends the player list header and footer. ++ * ++ * @param header the header ++ * @param footer the footer ++ */ ++ @Override ++ default void sendPlayerListHeaderAndFooter(final @NotNull Component header, final @NotNull Component footer) { ++ consumeIfOnline(player -> player.sendPlayerListHeaderAndFooter(header, footer)); ++ } ++ ++ /** ++ * Shows a title. ++ * ++ * @param title a title ++ */ ++ @Override ++ default void showTitle(final @NotNull Title title) { ++ consumeIfOnline(player -> player.showTitle(title)); ++ } ++ ++ /** ++ * Clears the title, if one is being displayed. ++ */ ++ @Override ++ default void clearTitle() { ++ consumeIfOnline(Audience::clearTitle); ++ } ++ ++ /** ++ * Resets the title and timings back to their default. ++ */ ++ @Override ++ default void resetTitle() { ++ consumeIfOnline(Audience::resetTitle); ++ } ++ ++ /** ++ * Shows a boss bar. ++ * ++ * @param bar a boss bar ++ */ ++ @Override ++ default void showBossBar(final @NotNull BossBar bar) { ++ consumeIfOnline(player -> player.showBossBar(bar)); ++ } ++ ++ /** ++ * Hides a boss bar. ++ * ++ * @param bar a boss bar ++ */ ++ @Override ++ default void hideBossBar(final @NotNull BossBar bar) { ++ consumeIfOnline(player -> player.hideBossBar(bar)); ++ } ++ ++ /** ++ * Plays a sound. ++ * ++ * @param sound a sound ++ */ ++ @Override ++ default void playSound(final @NotNull Sound sound) { ++ consumeIfOnline(player -> player.playSound(sound)); ++ } ++ ++ /** ++ * Plays a sound at a location. ++ * ++ * @param sound a sound ++ * @param x x coordinate ++ * @param y y coordinate ++ * @param z z coordinate ++ */ ++ @Override ++ default void playSound(final @NotNull Sound sound, final double x, final double y, final double z) { ++ consumeIfOnline(player -> player.playSound(sound, x, y, z)); ++ } ++ ++ /** ++ * Stops a sound, or many sounds. ++ * ++ * @param stop a sound stop ++ */ ++ @Override ++ default void stopSound(final @NotNull SoundStop stop) { ++ consumeIfOnline(player -> player.stopSound(stop)); ++ } ++ ++ /** ++ * Opens a book. ++ * ++ *

When possible, no item should persist after closing the book.

++ * ++ * @param book a book ++ */ ++ @Override ++ default void openBook(final @NotNull Book book) { ++ consumeIfOnline(player -> player.openBook(book)); ++ } ++ ++ @Override ++ default @Nullable Location getLocation() { ++ final Player player = getPlayer(); ++ return player == null ? null : player.getLocation(); ++ } ++} +diff --git a/src/main/java/me/lexikiq/PlayerLike.java b/src/main/java/me/lexikiq/PlayerLike.java +new file mode 100644 +index 0000000000000000000000000000000000000000..314bf6e8cacfe8891f1354952c5ccfe7d2e21939 +--- /dev/null ++++ b/src/main/java/me/lexikiq/PlayerLike.java +@@ -0,0 +1,28 @@ ++package me.lexikiq; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.function.Consumer; ++ ++/** ++ * Class that is like a {@link org.bukkit.entity.Player} in that it has a Player, {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, and an {@link net.kyori.adventure.identity.Identity}. ++ * @see me.lexikiq.OptionalPlayerLike ++ */ ++public interface PlayerLike extends HasPlayer, HasLocation, OptionalPlayerLike { ++ @Override ++ default void consumeIfOnline(final @NotNull Consumer<@NotNull Player> consumer) { ++ consumer.accept(getPlayer()); ++ } ++ ++ @Override ++ default boolean isOnline() { ++ return true; ++ } ++ ++ @Override ++ default @NotNull Location getLocation() { ++ return getPlayer().getLocation(); ++ } ++} +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 432d5711b7ec34eafeb27df82d367612dfe1fe54..7be8b69aa1b617273b5c3c17022fec2386d22bf7 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -30,7 +30,7 @@ import org.bukkit.entity.Player; + * magnitude than 360 are valid, but may be normalized to any other equivalent + * representation by the implementation. + */ +-public class Location implements Cloneable, ConfigurationSerializable { ++public class Location implements Cloneable, ConfigurationSerializable, me.lexikiq.HasLocation { // Parchment + private Reference world; + private double x; + private double y; +@@ -72,6 +72,13 @@ public class Location implements Cloneable, ConfigurationSerializable { + this.yaw = yaw; + } + ++ // Parchment start ++ @Override ++ public @NotNull Location getLocation() { ++ return this; ++ } ++ // Parchment end ++ + /** + * Sets the world that this location resides in + * +diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java +index 3afd5f5c0208a4ee93b5dbfc2aab2b9d2e8a7544..5898a13f0f90547ff6ecabee18969c7891d0beee 100644 +--- a/src/main/java/org/bukkit/OfflinePlayer.java ++++ b/src/main/java/org/bukkit/OfflinePlayer.java +@@ -9,7 +9,7 @@ import org.bukkit.permissions.ServerOperator; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable { ++public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, me.lexikiq.HasOfflinePlayer, me.lexikiq.OptionalPlayer { // Parchment + + /** + * Checks if this player is currently online +@@ -126,6 +126,13 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + @Nullable + public Player getPlayer(); + ++ // Parchment start ++ @Override ++ default @org.jetbrains.annotations.NotNull OfflinePlayer getOfflinePlayer() { ++ return this; ++ } ++ // Parchment end ++ + /** + * Gets the first date and time that this player was witnessed on this + * server. +diff --git a/src/main/java/org/bukkit/Raid.java b/src/main/java/org/bukkit/Raid.java +index 983a8c20a06d2b509602b27f49c090598b8ecc42..bc6b6739ad46a076f3ac8f92814a027f9d2840a7 100644 +--- a/src/main/java/org/bukkit/Raid.java ++++ b/src/main/java/org/bukkit/Raid.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a raid event. + */ +-public interface Raid { ++public interface Raid extends me.lexikiq.HasLocation { // Parchment + + /** + * Get whether this raid started. +diff --git a/src/main/java/org/bukkit/Vibration.java b/src/main/java/org/bukkit/Vibration.java +index 8d568d21fcbf706f55cda087bd7222ac60889c0a..51b214313e7ee6b5eb1f0fa6f1e1fe383c6d04e1 100644 +--- a/src/main/java/org/bukkit/Vibration.java ++++ b/src/main/java/org/bukkit/Vibration.java +@@ -64,7 +64,7 @@ public class Vibration { + } + } + +- public static class BlockDestination implements Destination { ++ public static class BlockDestination implements Destination, me.lexikiq.HasLocation { // Parchment + + private final Location block; + +diff --git a/src/main/java/org/bukkit/attribute/AttributeModifier.java b/src/main/java/org/bukkit/attribute/AttributeModifier.java +index ff8f1231f3e2e71740fd24fa8d4dac5d0e550ae7..4a1e40e0c7cff6ef8898771adf3bc600c715ee8d 100644 +--- a/src/main/java/org/bukkit/attribute/AttributeModifier.java ++++ b/src/main/java/org/bukkit/attribute/AttributeModifier.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Concrete implementation of an attribute modifier. + */ +-public class AttributeModifier implements ConfigurationSerializable { ++public class AttributeModifier implements ConfigurationSerializable, me.lexikiq.HasUniqueId { // Parchment + + private final UUID uuid; + private final String name; +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index ca488173a20bcf3427906f0a6548f06a97c9dc36..6ebf6f2bf02550ad69fad45cb79b6d92549df980 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable; + * (i.e. lighting and power) may not be able to be safely accessed during world + * generation when used in cases like BlockPhysicsEvent!!!! + */ +-public interface Block extends Metadatable { ++public interface Block extends Metadatable, me.lexikiq.HasLocation { // Parchment + + /** + * Gets the metadata for this block +diff --git a/src/main/java/org/bukkit/block/BlockState.java b/src/main/java/org/bukkit/block/BlockState.java +index 631cbf2be51040eee00aa39a39c5ec4003f91843..71ce90d8eb69cc2071f0b78534ded55a857998c4 100644 +--- a/src/main/java/org/bukkit/block/BlockState.java ++++ b/src/main/java/org/bukkit/block/BlockState.java +@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; + * change the state of the block and you will not know, or they may change the + * block to another type entirely, causing your BlockState to become invalid. + */ +-public interface BlockState extends Metadatable { ++public interface BlockState extends Metadatable, me.lexikiq.HasLocation { // Parchment + + /** + * Gets the block represented by this block state. +diff --git a/src/main/java/org/bukkit/block/DoubleChest.java b/src/main/java/org/bukkit/block/DoubleChest.java +index a39d2f1acbbd84ae0e2cf29f85594e09e55e9355..19b54fc9f05a88849538a1ed28d8440306b8c81e 100644 +--- a/src/main/java/org/bukkit/block/DoubleChest.java ++++ b/src/main/java/org/bukkit/block/DoubleChest.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a double chest. + */ +-public class DoubleChest implements InventoryHolder { ++public class DoubleChest implements InventoryHolder, me.lexikiq.HasLocation { // Parchment + private DoubleChestInventory inventory; + + public DoubleChest(@NotNull DoubleChestInventory chest) { +diff --git a/src/main/java/org/bukkit/entity/AnimalTamer.java b/src/main/java/org/bukkit/entity/AnimalTamer.java +index 2e17b2d4f759531fbe9ee8e9b00c839186af09ca..3f87365f96b220cf58b5ab9405ec77b70d24039b 100644 +--- a/src/main/java/org/bukkit/entity/AnimalTamer.java ++++ b/src/main/java/org/bukkit/entity/AnimalTamer.java +@@ -4,7 +4,7 @@ import java.util.UUID; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-public interface AnimalTamer { ++public interface AnimalTamer extends me.lexikiq.HasUniqueId { // Parchment + + /** + * This is the name of the specified AnimalTamer. +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index a9e455c5b3bbe4edbdb71f86f5c6eebc2f605547..a1a82de1631bf70534a5f29f4c3becc4dd91eb95 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a base entity in the world + */ +-public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper ++public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource, me.lexikiq.HasUniqueId, me.lexikiq.HasLocation { // Paper // Parchment + + /** + * Gets the entity's current position +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index da83b4cbed0be6f693c7cbb1cc032356f12d7883..081d372190a176b62999c4e28636370d5a9129e4 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -42,7 +42,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a player, connected or not + */ +-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper ++public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, me.lexikiq.HasPlayer { // Paper // Parchment + + // Paper start + @Override +diff --git a/src/main/java/org/bukkit/event/block/BlockBreakEvent.java b/src/main/java/org/bukkit/event/block/BlockBreakEvent.java +index c05cd9cadcff827a2eb236cf955bc898fa5e8b52..cc3c009be9756a5fcc8e579c1854721edc4a650f 100644 +--- a/src/main/java/org/bukkit/event/block/BlockBreakEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockBreakEvent.java +@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull; + * If a Block Break event is cancelled, the block will not break and + * experience will not drop. + */ +-public class BlockBreakEvent extends BlockExpEvent implements Cancellable { ++public class BlockBreakEvent extends BlockExpEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private final Player player; + private boolean dropItems; + private boolean cancel; +diff --git a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +index a1350c0f74d445dca09eea6e10abac050bb06990..7d9573f88ab4333db2da42379344580087f7f561 100644 +--- a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; + * #getMaterial()} instead. + * + */ +-public class BlockCanBuildEvent extends BlockEvent { ++public class BlockCanBuildEvent extends BlockEvent implements me.lexikiq.OptionalPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + protected boolean buildable; + +diff --git a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java +index f70871e1ae7b1a1d77405d942d82666f03bf0498..fc40801a3d314b20b4334cffff7e6beeceba80cf 100644 +--- a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; + *

+ * If a Block Damage event is cancelled, the block will not be damaged. + */ +-public class BlockDamageEvent extends BlockEvent implements Cancellable { ++public class BlockDamageEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private final Player player; + private boolean instaBreak; +diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +index 3dd4bd38e72c04e74e5787fb38ca9abd10bad06b..440792fcdd618b75d9387e8104562b86bfe33c13 100644 +--- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; + * AIR in most cases. Use #getBlockState() for more Information about the broken + * block. + */ +-public class BlockDropItemEvent extends BlockEvent implements Cancellable { ++public class BlockDropItemEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private final Player player; +diff --git a/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java b/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java +index 695309b4b7ef269ba2496408a5f874f61cd6c445..535e94fb4c2a021a89111ec98c7dbfef1534ac53 100644 +--- a/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java +@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable; + * block with bonemeal. Will be called after the applicable + * {@link StructureGrowEvent}. + */ +-public class BlockFertilizeEvent extends BlockEvent implements Cancellable { ++public class BlockFertilizeEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; +diff --git a/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java +index 6dcd9f828c6c40e48593b0bad5a44a656eb01645..542cfd60a1f4775544fb040a7d8c05daaf7a5c67 100644 +--- a/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + *

+ * If a Block Ignite event is cancelled, the block will not be ignited. + */ +-public class BlockIgniteEvent extends BlockEvent implements Cancellable { ++public class BlockIgniteEvent extends BlockEvent implements Cancellable, me.lexikiq.OptionalPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private final IgniteCause cause; + private final Entity ignitingEntity; +diff --git a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java +index be0a2d1f234d8265d98e54e518a994957b1f3ab7..ef5471f00a6c308368dd92f40fd1f3abe60e3e2b 100644 +--- a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; + *

+ * If a Block Place event is cancelled, the block will not be placed. + */ +-public class BlockPlaceEvent extends BlockEvent implements Cancellable { ++public class BlockPlaceEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + protected boolean cancel; + protected boolean canBuild; +diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +index 1f79f704abf339150df08900b8ea7da4cefef258..d08d9a87c89effcc4882aeda67019f7278aa099c 100644 +--- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java ++++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; + *

+ * If a Sign Change event is cancelled, the sign will not be changed. + */ +-public class SignChangeEvent extends BlockEvent implements Cancellable { ++public class SignChangeEvent extends BlockEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; + private final Player player; +diff --git a/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java b/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java +index 59aab10c2d27247eb77bd71d75b5f9126aa0fb12..6794fe6835ad8a5b1a3194288631f7178fa94b72 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java +@@ -13,7 +13,7 @@ import org.jetbrains.annotations.Nullable; + * This can be cancelled but the item will still be consumed that was used to + * make the entity enter into love mode. + */ +-public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable { ++public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable, me.lexikiq.OptionalHumanEntity { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private boolean cancel; +@@ -42,11 +42,27 @@ public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable + * + * @return The Human entity that caused the animal to enter love mode, or + * null if there wasn't one. ++ * @deprecated alias of {@link #getPlayer()} + */ + @Nullable +- public HumanEntity getHumanEntity() { ++ // Parchment start ++ @Deprecated ++ public final HumanEntity getHumanEntity() { ++ return getPlayer(); ++ } ++ ++ /** ++ * Gets the Human Entity that caused the animal to enter love mode. ++ * ++ * @return The Human entity that caused the animal to enter love mode, or ++ * null if there wasn't one. ++ */ ++ @Override ++ @Nullable ++ public HumanEntity getPlayer() { + return humanEntity; + } ++ // Parchment end + + /** + * Gets the amount of ticks that the animal will fall in love for. +diff --git a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +index 10d0e18dfd423b108fe381e8142867eb10399359..9877ca9ee25f4f10b130085b70e02eedf7b5b469 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Called when an entity explodes + */ +-public class EntityExplodeEvent extends EntityEvent implements Cancellable { ++public class EntityExplodeEvent extends EntityEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancel; + private final Location location; +diff --git a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java +index ea8f9ed43d8e4158e6c9c345252a94a5000c5561..d9000c142b4097ba17f7333864f0fa197f259300 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java +@@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; + * Note that this event is currently only fired for four specific placements: + * armor stands, boats, minecarts, and end crystals. + */ +-public class EntityPlaceEvent extends EntityEvent implements Cancellable { ++public class EntityPlaceEvent extends EntityEvent implements Cancellable, me.lexikiq.OptionalPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; +diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +index 6818e9f0ba32ca1a1e612703f7526b29f5a6438f..9bcc13260ed26a75a1325fe6598bfed51f63496c 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Called when an entity comes into contact with a portal + */ +-public class EntityPortalEnterEvent extends EntityEvent { ++public class EntityPortalEnterEvent extends EntityEvent implements me.lexikiq.HasLocation { // Parchment + private static final HandlerList handlers = new HandlerList(); + private final Location location; + +diff --git a/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java +index 961ee511342cd3a12ff2ff74d7b4683c6753123d..35aaa2479ef2ede010162230a1b683de5811c4bb 100644 +--- a/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + *

+ * If an Entity Spawn event is cancelled, the entity will not spawn. + */ +-public class EntitySpawnEvent extends EntityEvent implements Cancellable { ++public class EntitySpawnEvent extends EntityEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private boolean canceled; +diff --git a/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java b/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java +index 6fc66197eb2c5d59c70d8d028b7963748371edbe..f4c02474f16a009fccd480f6a59bb937c96bbfb7 100644 +--- a/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java +@@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; + * Cancelling the event results in the item being allowed to exist for 5 more + * minutes. This behavior is not guaranteed and may change in future versions. + */ +-public class ItemDespawnEvent extends EntityEvent implements Cancellable { ++public class ItemDespawnEvent extends EntityEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean canceled; + private final Location location; +diff --git a/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java b/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java +index 5eb3fb72a13881b8bf0e40037b0002cb0a6eb883..6ab6bb4237418479156bd24d77bc1f24db637969 100644 +--- a/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java +@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Called immediately prior to a creature being leashed by a player. + */ +-public class PlayerLeashEntityEvent extends Event implements Cancellable { ++public class PlayerLeashEntityEvent extends Event implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private final Entity leashHolder; + private final Entity entity; +diff --git a/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java b/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java +index 959b9f3fb41f8de6c8fb9a3b2df13212e29cf0e7..a92dbe0a21a4b8571813dbc9ff504694239d025b 100644 +--- a/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Triggered when a hanging entity is created in the world + */ +-public class HangingPlaceEvent extends HangingEvent implements Cancellable { ++public class HangingPlaceEvent extends HangingEvent implements Cancellable, me.lexikiq.OptionalPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final Player player; +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java +index 020739697a0b535cad0b15b574f77cdabbdfa3eb..db95a2096f12c42d84b44bada6048184074a20b4 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * This event is called when a player takes items out of the furnace + */ +-public class FurnaceExtractEvent extends BlockExpEvent { ++public class FurnaceExtractEvent extends BlockExpEvent implements me.lexikiq.HasPlayer { // Parchment + private final Player player; + private final Material itemType; + private final int itemAmount; +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +index 21ad8888c0e403bfc63518502577d651c02dda05..4dd6182476a4a9b961089f34d5376780e1774fc4 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a player related inventory event + */ +-public class InventoryCloseEvent extends InventoryEvent { ++public class InventoryCloseEvent extends InventoryEvent implements me.lexikiq.HasHumanEntity { // Parchment + private static final HandlerList handlers = new HandlerList(); + // Paper start + private final Reason reason; +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java +index 9013d043503d175004ad276799e5935b7fa59dc4..2af2c43ba34de3ff6f6a82f5abb4f94f2fa5d19e 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a player related inventory event + */ +-public class InventoryOpenEvent extends InventoryEvent implements Cancellable { ++public class InventoryOpenEvent extends InventoryEvent implements Cancellable, me.lexikiq.HasHumanEntity { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index 77aefda5aac4602bf5bf71c29600e7450defdd4e..0a7c4936bc97da1d7defe3c370d95376455baae2 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; + *

+ * This event is asynchronous, and not run using main thread. + */ +-public class AsyncPlayerPreLoginEvent extends Event { ++public class AsyncPlayerPreLoginEvent extends Event implements me.lexikiq.HasUniqueId { // Parchment + private static final HandlerList handlers = new HandlerList(); + private Result result; + private net.kyori.adventure.text.Component message; // Paper +diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java +index f6d3b817de3001f04ea4554c7c39a1290af3fd6d..309d4526816853dfc2d5c3061bd772238776ab74 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java +@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a player related event + */ +-public abstract class PlayerEvent extends Event { ++public abstract class PlayerEvent extends Event implements me.lexikiq.HasPlayer { // Parchment + protected Player player; + + public PlayerEvent(@NotNull final Player who) { +diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +index 123979ed64939d615b061f91c19c630e1e1db8c7..0220c4f087fd6b5769a0fa4f03bfd096a1462359 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +@@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull; + */ + @Deprecated + @Warning(reason = "This event causes a login thread to synchronize with the main thread") +-public class PlayerPreLoginEvent extends Event { ++public class PlayerPreLoginEvent extends Event implements me.lexikiq.HasUniqueId { // Parchment + private static final HandlerList handlers = new HandlerList(); + private Result result; + private net.kyori.adventure.text.Component message; // Paper +diff --git a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java +index 68eab1563caba1ee4f52b308f390e4e172667fc5..7ebf60f80ac29f3969d2d70fa0cf668f2933b647 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Called prior to an entity being unleashed due to a player's action. + */ +-public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Cancellable { ++public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + private final Player player; + private boolean cancelled = false; + +diff --git a/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java b/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java +index 128e43cf12205f82f2b119a773208502cdccfdd4..f0a5fc39fa35ec71cf9cadb7d0cff379f5d8c6cb 100644 +--- a/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java ++++ b/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + * Called when a {@link Raid} is triggered (e.g: a player with Bad Omen effect + * enters a village). + */ +-public class RaidTriggerEvent extends RaidEvent implements Cancellable { ++public class RaidTriggerEvent extends RaidEvent implements Cancellable, me.lexikiq.HasPlayer { // Parchment + + private static final HandlerList handlers = new HandlerList(); + // +diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java +index f96c4ba53ab41ea66d4f9a4d54eeabb63f992b58..39fa65a2b130c00b2ba5d90e2fa673a6d9c85f4b 100644 +--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java ++++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java +@@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable; + * advised to ensure the client does not have permission for the relevant + * commands, or use {@link PlayerCommandSendEvent}. + */ +-public class TabCompleteEvent extends Event implements Cancellable { ++public class TabCompleteEvent extends Event implements Cancellable, me.lexikiq.OptionalLocation { // Parchment + + private static final HandlerList handlers = new HandlerList(); + // +diff --git a/src/main/java/org/bukkit/event/world/GenericGameEvent.java b/src/main/java/org/bukkit/event/world/GenericGameEvent.java +index fed29b2cb2a2c2997a7a3f42e9be84a8cb1c6425..629fd7abf0bea441cf8f2578c894a5426a9c877a 100644 +--- a/src/main/java/org/bukkit/event/world/GenericGameEvent.java ++++ b/src/main/java/org/bukkit/event/world/GenericGameEvent.java +@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable; + * Specific Bukkit events should be used where possible, this event is mainly + * used internally by Sculk sensors. + */ +-public class GenericGameEvent extends WorldEvent implements Cancellable { ++public class GenericGameEvent extends WorldEvent implements Cancellable, me.lexikiq.HasLocation { // Parchment + + private static final HandlerList handlers = new HandlerList(); + private final GameEvent event; +diff --git a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java +index 7af8d6e51c824cf0592b722b834f1d4986e3cc08..8baaa32094bacb181848904f18184fe6f90289df 100644 +--- a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java ++++ b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + * Event that is called when an organic structure attempts to grow (Sapling {@literal ->} + * Tree), (Mushroom {@literal ->} Huge Mushroom), naturally or using bonemeal. + */ +-public class StructureGrowEvent extends WorldEvent implements Cancellable { ++public class StructureGrowEvent extends WorldEvent implements Cancellable, me.lexikiq.OptionalPlayer { // Parchment + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled = false; + private final Location location; +diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java +index 8f00cb2e3bc9963e9657c1b2493e8b015a6664d0..7029f3e6fe4a5167265a70eb3113f25836c6e121 100644 +--- a/src/main/java/org/bukkit/inventory/Inventory.java ++++ b/src/main/java/org/bukkit/inventory/Inventory.java +@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; + * @see #getContents() + * @see #getStorageContents() + */ +-public interface Inventory extends Iterable { ++public interface Inventory extends Iterable, me.lexikiq.OptionalLocation { // Parchment + + /** + * Returns the size of the inventory +diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java +index b06995aa57aa9cba0bb59f1d26d81015619a08e6..d599b72c2441a023dff8ee4bdaf587b21471f11f 100644 +--- a/src/main/java/org/bukkit/inventory/InventoryView.java ++++ b/src/main/java/org/bukkit/inventory/InventoryView.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + * contracts of certain methods, there's no guarantee that the game will work + * as it should. + */ +-public abstract class InventoryView { ++public abstract class InventoryView implements me.lexikiq.HasHumanEntity { // Parchment + public static final int OUTSIDE = -999; + /** + * Represents various extra properties of certain inventory windows. +diff --git a/src/main/java/org/bukkit/loot/LootContext.java b/src/main/java/org/bukkit/loot/LootContext.java +index e307f9fc45a4e5d742b78c4cda9a41d7f259a515..ab532552e4a10e03125b64e0884650a841275cca 100644 +--- a/src/main/java/org/bukkit/loot/LootContext.java ++++ b/src/main/java/org/bukkit/loot/LootContext.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; + * Represents additional information a {@link LootTable} can use to modify it's + * generated loot. + */ +-public final class LootContext { ++public final class LootContext implements me.lexikiq.HasLocation { // Parchment + + public static final int DEFAULT_LOOT_MODIFIER = -1; + diff --git a/patches/reverted/api/0008-Add-SoundEvent.patch b/patches/api/0003-Add-SoundEvent.patch similarity index 65% rename from patches/reverted/api/0008-Add-SoundEvent.patch rename to patches/api/0003-Add-SoundEvent.patch index 80fd89f..a8e3ee5 100644 --- a/patches/reverted/api/0008-Add-SoundEvent.patch +++ b/patches/api/0003-Add-SoundEvent.patch @@ -1,20 +1,21 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: lexikiq -Date: Tue, 1 Jun 2021 16:22:54 -0400 +Date: Sat, 19 Jun 2021 16:17:40 -0400 Subject: [PATCH] Add SoundEvent diff --git a/src/main/java/me/lexikiq/event/sound/EntitySoundEvent.java b/src/main/java/me/lexikiq/event/sound/EntitySoundEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..bf7cd3b9183925cdeef2969cad045bf766a54742 +index 0000000000000000000000000000000000000000..de8606c42022589ed8b3841e531e001aaa716bcf --- /dev/null +++ b/src/main/java/me/lexikiq/event/sound/EntitySoundEvent.java -@@ -0,0 +1,44 @@ +@@ -0,0 +1,49 @@ +package me.lexikiq.event.sound; + +import org.apache.commons.lang.Validate; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; ++import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.HumanEntity; +import org.jetbrains.annotations.NotNull; @@ -53,15 +54,20 @@ index 0000000000000000000000000000000000000000..bf7cd3b9183925cdeef2969cad045bf7 + this.origin = origin; + } + ++ @Override ++ public World getWorld() { ++ return origin.getWorld(); ++ } +} diff --git a/src/main/java/me/lexikiq/event/sound/LocationCustomSoundEvent.java b/src/main/java/me/lexikiq/event/sound/LocationCustomSoundEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..8ce556953dd175336ef887c508ad8e027b9df4a6 +index 0000000000000000000000000000000000000000..f007bc326bea341735e7313789f5d110af5ac4ca --- /dev/null +++ b/src/main/java/me/lexikiq/event/sound/LocationCustomSoundEvent.java -@@ -0,0 +1,73 @@ +@@ -0,0 +1,121 @@ +package me.lexikiq.event.sound; + ++import me.lexikiq.HasLocation; +import org.apache.commons.lang.Validate; +import org.bukkit.Keyed; +import org.bukkit.Location; @@ -73,10 +79,12 @@ index 0000000000000000000000000000000000000000..8ce556953dd175336ef887c508ad8e02 +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + ++import static com.google.common.base.Preconditions.checkNotNull; ++ +/** + * Called when a sound not available in {@link org.bukkit.Sound} is sent to a player from a {@link Location}. Cancelling this event will prevent the packet from sending. + */ -+public class LocationCustomSoundEvent extends SoundEvent implements Keyed { ++public class LocationCustomSoundEvent extends SoundEvent implements Keyed, HasLocation { + private @NotNull Vector vector; + private @NotNull NamespacedKey key; + private @NotNull final World world; @@ -91,6 +99,18 @@ index 0000000000000000000000000000000000000000..8ce556953dd175336ef887c508ad8e02 + this.key = key; + } + ++ public LocationCustomSoundEvent(@Nullable HumanEntity receiver, @NotNull Location location, @NotNull NamespacedKey key, @NotNull SoundCategory category, float volume, float pitch) { ++ this(receiver, checkNotNull(location, "location").getWorld(), location.toVector(), key, category, volume, pitch); ++ } ++ ++ public LocationCustomSoundEvent(@NotNull HumanEntity receiver, @NotNull Vector vector, @NotNull NamespacedKey key, @NotNull SoundCategory category, float volume, float pitch) { ++ this(checkNotNull(receiver, "receiver"), receiver.getWorld(), vector, key, category, volume, pitch); ++ } ++ ++ public LocationCustomSoundEvent(@NotNull HumanEntity receiver, @NotNull NamespacedKey key, @NotNull SoundCategory category, float volume, float pitch) { ++ this(checkNotNull(receiver, "receiver"), receiver.getLocation().toVector(), key, category, volume, pitch); ++ } ++ + /** + * Gets the position in the world of the sound + * @return position in the world @@ -107,14 +127,21 @@ index 0000000000000000000000000000000000000000..8ce556953dd175336ef887c508ad8e02 + return key; + } + -+ /** -+ * Gets the world in which the sound is being played -+ * @return sound's world -+ */ ++ @Override + public @NotNull World getWorld() { + return world; + } + ++ /** ++ * Gets the location of the sound being played ++ * @return copy of sound location ++ * @see #getVector() ++ * @see #setVector(Vector) ++ */ ++ public @NotNull Location getLocation() { ++ return new Location(world, vector.getX(), vector.getY(), vector.getZ()); ++ } ++ + /** + * Sets the position in the world of the sound + * @param vector position in the world @@ -132,15 +159,42 @@ index 0000000000000000000000000000000000000000..8ce556953dd175336ef887c508ad8e02 + Validate.notNull(key, "key cannot be null"); + this.key = key; + } ++ ++ // boilerplate ++ ++ private boolean cancelled; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ private static final org.bukkit.event.HandlerList handlers = new org.bukkit.event.HandlerList(); ++ ++ @Override ++ public @NotNull org.bukkit.event.HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static org.bukkit.event.HandlerList getHandlerList() { ++ return handlers; ++ } +} diff --git a/src/main/java/me/lexikiq/event/sound/LocationNamedSoundEvent.java b/src/main/java/me/lexikiq/event/sound/LocationNamedSoundEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..242a7f3d4d6ab6ff7000e544605a69eac35f03a8 +index 0000000000000000000000000000000000000000..81ba14fea8d04347a0fd3931b27188028c5ac859 --- /dev/null +++ b/src/main/java/me/lexikiq/event/sound/LocationNamedSoundEvent.java -@@ -0,0 +1,52 @@ +@@ -0,0 +1,72 @@ +package me.lexikiq.event.sound; + ++import me.lexikiq.HasLocation; +import org.apache.commons.lang.Validate; +import org.bukkit.Location; +import org.bukkit.Sound; @@ -151,21 +205,33 @@ index 0000000000000000000000000000000000000000..242a7f3d4d6ab6ff7000e544605a69ea +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + ++import static com.google.common.base.Preconditions.checkNotNull; ++ +/** + * Called when a sound available in {@link Sound} is sent to a player from a {@link Location}. Cancelling this event will prevent the packet from sending. + */ -+public class LocationNamedSoundEvent extends NamedSoundEvent { ++public class LocationNamedSoundEvent extends NamedSoundEvent implements HasLocation { + private @NotNull Vector vector; + private @NotNull final World world; + + public LocationNamedSoundEvent(@Nullable HumanEntity receiver, @NotNull World world, @NotNull Vector vector, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) { + super(receiver, sound, category, volume, pitch); -+ Validate.notNull(world, "world cannot be null"); -+ Validate.notNull(vector, "vector cannot be null"); -+ this.world = world; -+ this.vector = vector; ++ this.world = checkNotNull(world, "world"); ++ this.vector = checkNotNull(vector, "vector"); + } + ++ public LocationNamedSoundEvent(@Nullable HumanEntity receiver, @NotNull Location location, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) { ++ this(receiver, checkNotNull(location, "location").getWorld(), location.toVector(), sound, category, volume, pitch); ++ } ++ ++ public LocationNamedSoundEvent(@NotNull HumanEntity receiver, @NotNull Vector vector, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) { ++ this(checkNotNull(receiver, "receiver"), receiver.getWorld(), vector, sound, category, volume, pitch); ++ } ++ ++ public LocationNamedSoundEvent(@NotNull HumanEntity receiver, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) { ++ this(checkNotNull(receiver, "receiver"), receiver.getLocation().toVector(), sound, category, volume, pitch); ++ } ++ + /** + * Gets the position in the world of the sound + * @return position in the world @@ -174,14 +240,21 @@ index 0000000000000000000000000000000000000000..242a7f3d4d6ab6ff7000e544605a69ea + return vector; + } + -+ /** -+ * Gets the world in which the sound is being played -+ * @return sound's world -+ */ ++ @Override + public @NotNull World getWorld() { + return world; + } + ++ /** ++ * Gets the location of the sound being played ++ * @return copy of sound location ++ * @see #getVector() ++ * @see #setVector(Vector) ++ */ ++ public @NotNull Location getLocation() { ++ return new Location(world, vector.getX(), vector.getY(), vector.getZ()); ++ } ++ + /** + * Sets the position in the world of the sound + * @param vector position in the world @@ -193,10 +266,10 @@ index 0000000000000000000000000000000000000000..242a7f3d4d6ab6ff7000e544605a69ea +} diff --git a/src/main/java/me/lexikiq/event/sound/NamedSoundEvent.java b/src/main/java/me/lexikiq/event/sound/NamedSoundEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..516352ffb64fd025be018f5389a7c80e62743c9a +index 0000000000000000000000000000000000000000..8623e03aa5ca094629bf6a20669ea8c5086d938c --- /dev/null +++ b/src/main/java/me/lexikiq/event/sound/NamedSoundEvent.java -@@ -0,0 +1,40 @@ +@@ -0,0 +1,64 @@ +package me.lexikiq.event.sound; + +import org.apache.commons.lang.Validate; @@ -208,10 +281,8 @@ index 0000000000000000000000000000000000000000..516352ffb64fd025be018f5389a7c80e + +/** + * Called when a sound available in {@link Sound} is sent to a player. Cancelling this event will prevent the packet from sending. -+ *

-+ * Note: this does not directly correspond to any given sound packet. It is provided for listening convenience. + */ -+public class NamedSoundEvent extends SoundEvent { ++public abstract class NamedSoundEvent extends SoundEvent { + private @NotNull Sound sound; + + public NamedSoundEvent(@Nullable HumanEntity receiver, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) { @@ -236,36 +307,59 @@ index 0000000000000000000000000000000000000000..516352ffb64fd025be018f5389a7c80e + Validate.notNull(sound, "sound cannot be null"); + this.sound = sound; + } ++ ++ // boilerplate ++ ++ private boolean cancelled; ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancelled) { ++ this.cancelled = cancelled; ++ } ++ ++ private static final org.bukkit.event.HandlerList handlers = new org.bukkit.event.HandlerList(); ++ ++ @Override ++ public @NotNull org.bukkit.event.HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static org.bukkit.event.HandlerList getHandlerList() { ++ return handlers; ++ } +} diff --git a/src/main/java/me/lexikiq/event/sound/SoundEvent.java b/src/main/java/me/lexikiq/event/sound/SoundEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..05cd0148bec4770ce78fceda1fe57cf625b0bacf +index 0000000000000000000000000000000000000000..77b17b76a5137b30d5f8f040c0bcfa5f143223cb --- /dev/null +++ b/src/main/java/me/lexikiq/event/sound/SoundEvent.java -@@ -0,0 +1,115 @@ +@@ -0,0 +1,96 @@ +package me.lexikiq.event.sound; + +import me.lexikiq.OptionalHumanEntity; +import org.apache.commons.lang.Validate; +import org.bukkit.SoundCategory; ++import org.bukkit.World; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Called when a sound is sent to a player. Cancelling this event will prevent the packet from sending. -+ *

-+ * Note: this does not directly correspond to any given sound packet. It is provided for listening convenience. + */ -+public class SoundEvent extends Event implements Cancellable, OptionalHumanEntity { ++public abstract class SoundEvent extends Event implements Cancellable, OptionalHumanEntity { + private @Nullable final HumanEntity receiver; + private @NotNull SoundCategory category; + private float volume; + private float pitch; -+ private boolean cancelled; + + public SoundEvent(@Nullable HumanEntity receiver, @NotNull SoundCategory category, float volume, float pitch) { + super(true); @@ -336,25 +430,9 @@ index 0000000000000000000000000000000000000000..05cd0148bec4770ce78fceda1fe57cf6 + this.pitch = pitch; + } + -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } ++ /** ++ * Gets the world in which the sound is being played ++ * @return sound's world ++ */ ++ public abstract World getWorld(); +} diff --git a/patches/reverted/api/0006-Create-PlayerUseRespawnAnchorEvent.patch b/patches/api/0004-Add-PlayerUseRespawnAnchorEvent.patch similarity index 80% rename from patches/reverted/api/0006-Create-PlayerUseRespawnAnchorEvent.patch rename to patches/api/0004-Add-PlayerUseRespawnAnchorEvent.patch index c6e8b5a..c4c485f 100644 --- a/patches/reverted/api/0006-Create-PlayerUseRespawnAnchorEvent.patch +++ b/patches/api/0004-Add-PlayerUseRespawnAnchorEvent.patch @@ -1,17 +1,18 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: lexikiq Date: Thu, 13 May 2021 23:55:02 -0400 -Subject: [PATCH] Create PlayerUseRespawnAnchorEvent +Subject: [PATCH] Add PlayerUseRespawnAnchorEvent diff --git a/src/main/java/me/lexikiq/event/player/PlayerUseRespawnAnchorEvent.java b/src/main/java/me/lexikiq/event/player/PlayerUseRespawnAnchorEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..96b552fe0bd6e6507c1c4f9380cab32e725cb129 +index 0000000000000000000000000000000000000000..fcf552bb84a10794dda178b337768efe4781facd --- /dev/null +++ b/src/main/java/me/lexikiq/event/player/PlayerUseRespawnAnchorEvent.java -@@ -0,0 +1,102 @@ +@@ -0,0 +1,117 @@ +package me.lexikiq.event.player; + ++import com.google.common.base.Preconditions; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; @@ -20,7 +21,8 @@ index 0000000000000000000000000000000000000000..96b552fe0bd6e6507c1c4f9380cab32e +import org.jetbrains.annotations.NotNull; + +/** -+ * This event is fired immediately before the result of using a respawn anchor is executed ++ * This event is fired after determining what action should result from a player interacting with ++ * a respawn anchor. + */ +public class PlayerUseRespawnAnchorEvent extends PlayerEvent implements Cancellable { + @@ -39,12 +41,16 @@ index 0000000000000000000000000000000000000000..96b552fe0bd6e6507c1c4f9380cab32e + /** + * The player will charge the respawn anchor + */ -+ CHARGE ++ CHARGE, ++ /** ++ * The respawn anchor will do nothing ++ */ ++ NOTHING + } + + private static final HandlerList handlers = new HandlerList(); + private final Block respawnAnchor; -+ private final RespawnAnchorResult respawnAnchorResult; ++ private RespawnAnchorResult respawnAnchorResult; + private boolean cancelled = false; + + public PlayerUseRespawnAnchorEvent(@NotNull Player who, @NotNull Block respawnAnchor, @NotNull RespawnAnchorResult respawnAnchorResult) { @@ -69,11 +75,20 @@ index 0000000000000000000000000000000000000000..96b552fe0bd6e6507c1c4f9380cab32e + * @return the respawn anchor result for the outcome of the event + */ + @NotNull -+ public RespawnAnchorResult getRespawnAnchorResult() { ++ public RespawnAnchorResult getResult() { + return this.respawnAnchorResult; + } + + /** ++ * Sets the outcome of the event. ++ * ++ * @param result event to set ++ */ ++ public void setResult(@NotNull RespawnAnchorResult result) { ++ this.respawnAnchorResult = Preconditions.checkNotNull(result, "result"); ++ } ++ ++ /** + * Gets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins. + *

diff --git a/patches/reverted/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch b/patches/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch similarity index 84% rename from patches/reverted/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch rename to patches/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch index a745a31..e9a7635 100644 --- a/patches/reverted/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch +++ b/patches/api/0005-Add-origin-location-to-EntityDamageByBlockEvent.patch @@ -1,14 +1,14 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: lexikiq -Date: Mon, 10 May 2021 22:10:23 -0400 +Date: Fri, 18 Jun 2021 14:06:43 -0400 Subject: [PATCH] Add origin location to EntityDamageByBlockEvent diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java -index 461727dc7f06efb3550fc370e0db5bd04ba89711..cd3ad8ce0f3f22f1292ae81e3a974d0d464a388c 100644 +index 461727dc7f06efb3550fc370e0db5bd04ba89711..f20ac2ba1921616f346c11ef60c53aba0080728b 100644 --- a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java -@@ -12,17 +12,38 @@ import org.jetbrains.annotations.Nullable; +@@ -12,17 +12,43 @@ import org.jetbrains.annotations.Nullable; */ public class EntityDamageByBlockEvent extends EntityDamageEvent { private final Block damager; @@ -30,7 +30,12 @@ index 461727dc7f06efb3550fc370e0db5bd04ba89711..cd3ad8ce0f3f22f1292ae81e3a974d0d + public EntityDamageByBlockEvent(@Nullable final Block damager, @NotNull final Entity damagee, @NotNull final DamageCause cause, @Nullable final org.bukkit.Location damageLocation, @NotNull final Map modifiers, @NotNull final Map> modifierFunctions) { + super(damagee, cause, modifiers, modifierFunctions); + this.damager = damager; -+ this.location = damageLocation; ++ if (damageLocation != null) ++ this.location = damageLocation; ++ else if (damager != null) ++ this.location = damager.getLocation(); ++ else ++ this.location = null; + } + + /** diff --git a/patches/api/0006-Adventure-fixes.patch b/patches/api/0006-Adventure-fixes.patch new file mode 100644 index 0000000..b8d6ef1 --- /dev/null +++ b/patches/api/0006-Adventure-fixes.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Fri, 18 Jun 2021 01:47:40 -0400 +Subject: [PATCH] Adventure fixes + + +diff --git a/src/main/java/org/bukkit/Keyed.java b/src/main/java/org/bukkit/Keyed.java +index 32c92621c2c15eec14c50965f5ecda00c46e6c80..3876a03ab9df9a0aef7a5c05a38b39b07a6dd285 100644 +--- a/src/main/java/org/bukkit/Keyed.java ++++ b/src/main/java/org/bukkit/Keyed.java +@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents an object which has a {@link NamespacedKey} attached to it. + */ +-public interface Keyed { ++public interface Keyed extends net.kyori.adventure.key.Keyed { // Parchment + + /** + * Return the namespaced identifier for this object. +@@ -14,4 +14,11 @@ public interface Keyed { + */ + @NotNull + NamespacedKey getKey(); ++ ++ // Parchment start ++ @Override ++ default net.kyori.adventure.key.@org.checkerframework.checker.nullness.qual.NonNull Key key() { ++ return getKey(); ++ } ++ // Parchment end + } diff --git a/patches/api/0007-Add-UnsafeValues-canPlaceItemOn.patch b/patches/api/0007-Add-UnsafeValues-canPlaceItemOn.patch new file mode 100644 index 0000000..5fff70c --- /dev/null +++ b/patches/api/0007-Add-UnsafeValues-canPlaceItemOn.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Fri, 18 Jun 2021 03:18:47 -0400 +Subject: [PATCH] Add UnsafeValues#canPlaceItemOn + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 379acee1b5f2d06e6a96f3444783f4a29ca24095..c4f81d9a642005e52eb3d88daf6da6caa48a3f0d 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -184,4 +184,17 @@ public interface UnsafeValues { + */ + int getProtocolVersion(); + // Paper end ++ ++ // Parchment start ++ /** ++ * Determines if this item can be placed on a block. Must be run synchronously. ++ * Factors in player location, blocking events, hitboxes, and more. ++ * @param item item to test ++ * @param player optional player placing the block ++ * @param block block that is being placed against ++ * @param face cardinal direction ++ * @return if the item can be placed ++ */ ++ java.util.concurrent.CompletableFuture canPlaceItemOn(@org.jetbrains.annotations.NotNull ItemStack item, @org.jetbrains.annotations.Nullable me.lexikiq.OptionalHumanEntity player, @org.jetbrains.annotations.NotNull org.bukkit.block.Block block, @org.jetbrains.annotations.NotNull org.bukkit.block.BlockFace face); ++ // Parchment end + } diff --git a/patches/reverted/api/0001-Parchment-POM-Changes.patch b/patches/reverted/api/0001-Parchment-POM-Changes.patch deleted file mode 100644 index a3e3e39..0000000 --- a/patches/reverted/api/0001-Parchment-POM-Changes.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sat, 1 May 2021 14:27:26 -0400 -Subject: [PATCH] Parchment POM Changes - - -diff --git a/pom.xml b/pom.xml -index 73fbd5d5a591871a3a386fb5c455cd96a3992e7a..1e182b441771c7159dd4323c2c72364efb971407 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -3,18 +3,18 @@ - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - 4.0.0 - -- com.destroystokyo.paper -- paper-parent -+ me.lexikiq -+ parchment-parent - dev-SNAPSHOT -+ ../pom.xml - - -- com.destroystokyo.paper -- paper-api -+ parchment-api - 1.16.5-R0.1-SNAPSHOT - jar - -- Paper-API -- https://github.com/PaperMC/Paper -+ Parchment-API -+ https://github.com/lexikiq/Parchment - An enhanced plugin API for Minecraft servers. - - diff --git a/patches/reverted/api/0002-Create-interfaces-for-getting-UUIDs-and-Players.patch b/patches/reverted/api/0002-Create-interfaces-for-getting-UUIDs-and-Players.patch deleted file mode 100644 index 7e8ee2e..0000000 --- a/patches/reverted/api/0002-Create-interfaces-for-getting-UUIDs-and-Players.patch +++ /dev/null @@ -1,1101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sun, 2 May 2021 14:16:41 -0400 -Subject: [PATCH] Create interfaces for getting UUIDs and Players - -Creates new interfaces for getting UUIDs, Human Entities, Offline Players, and Players. Features matching NotNull and Nullable interfaces. Lessens the required overloads for plugin developers when working with varying player objects. - -diff --git a/pom.xml b/pom.xml -index 1e182b441771c7159dd4323c2c72364efb971407..6857042b3475925f426cbe9f4858438a02bebd23 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -47,6 +47,14 @@ - - - -+ -+ -+ me.lexikiq -+ parchment-common -+ dev-SNAPSHOT -+ compile -+ -+ - - - net.kyori -diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -index 978813b94a5eae0afccbd3b38b463091a46b56ac..18716a020c0c7c1a06b5ab3935abc33a42d89748 100644 ---- a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper.event.block; - -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Called when a beacon effect is being applied to a player. - */ --public class BeaconEffectEvent extends BlockEvent implements Cancellable { -+public class BeaconEffectEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private PotionEffect effect; -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -index f530a3d9314e17d1da896cac633f6a422258d9a9..e2c3612d4544e99c1023cafb4e3b5bf28f2decd2 100644 ---- a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -@@ -23,6 +23,7 @@ - - package com.destroystokyo.paper.event.entity; - -+import me.lexikiq.HasPlayer; - import org.bukkit.entity.Enderman; - import org.bukkit.entity.Entity; - import org.bukkit.entity.Player; -@@ -38,7 +39,7 @@ import org.jetbrains.annotations.NotNull; - * at the Enderman, according to Vanilla rules. - * - */ --public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable { -+public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable, HasPlayer { // Parchment - @NotNull private final Player player; - - public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) { -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -index 12c1c6fe9dc8dc5f5faf6dcf99f6857219ef22b8..81dc840856825c6ee58a46cfda04936a529ca9af 100644 ---- a/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper.event.player; - -+import me.lexikiq.HasUniqueId; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - -@@ -43,7 +44,7 @@ import org.jetbrains.annotations.NotNull; - * {@link Event#isAsynchronous()} and handle accordingly. - *

- */ --public class PlayerConnectionCloseEvent extends Event { -+public class PlayerConnectionCloseEvent extends Event implements HasUniqueId { - - private static final HandlerList HANDLERS = new HandlerList(); - -@@ -60,11 +61,19 @@ public class PlayerConnectionCloseEvent extends Event { - - /** - * Returns the {@code UUID} of the player disconnecting. -+ * @deprecated alias of {@link #getUniqueId()} - */ -- @NotNull -+ @NotNull @Deprecated // Parchment -- method is named inconsistently compared to other player events - public UUID getPlayerUniqueId() { -+ return getUniqueId(); // Parchment -+ } -+ -+ // Parchment start -+ @Override @NotNull -+ public UUID getUniqueId() { - return this.playerUniqueId; - } -+ // Parchment end - - /** - * Returns the name of the player disconnecting. -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -index a077962fa786a3291849abfa823c7f0ec4664fce..d9fe6d298cdbd4355775fc35f32eb5be6253a6fb 100644 ---- a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper.event.player; - -+import me.lexikiq.OptionalUniqueId; - import net.kyori.adventure.text.Component; - import net.kyori.adventure.text.format.NamedTextColor; - import org.apache.commons.lang.Validate; -@@ -20,7 +21,7 @@ import org.jetbrains.annotations.Nullable; - * - *

WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

- */ --public class PlayerHandshakeEvent extends Event implements Cancellable { -+public class PlayerHandshakeEvent extends Event implements Cancellable, OptionalUniqueId { - - private static final HandlerList HANDLERS = new HandlerList(); - @NotNull private final String originalHandshake; -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -index 4dcf6242c9acc62d030a94f67b78729ed29f8c85..5218d184b9ea12a6cac3643d897dad1eafea2cb9 100644 ---- a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -@@ -3,6 +3,7 @@ package com.destroystokyo.paper.event.profile; - import com.destroystokyo.paper.profile.PlayerProfile; - import com.destroystokyo.paper.profile.ProfileProperty; - import com.google.common.collect.ArrayListMultimap; -+import me.lexikiq.OptionalUniqueId; - import org.bukkit.Bukkit; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; -@@ -23,7 +24,7 @@ import org.jetbrains.annotations.Nullable; - * No guarantees are made about thread execution context for this event. If you need to know, check - * event.isAsync() - */ --public class PreLookupProfileEvent extends Event { -+public class PreLookupProfileEvent extends Event implements OptionalUniqueId { // Parchment - - private static final HandlerList handlers = new HandlerList(); - @NotNull private final String name; -@@ -49,12 +50,21 @@ public class PreLookupProfileEvent extends Event { - * {@link LookupProfileEvent} - * - * @return The UUID of the profile if it has already been provided by a plugin -+ * @deprecated alias of {@link #getUniqueId()} (Parchment) - */ - @Nullable -+ @Deprecated // Parchment - public UUID getUUID() { - return uuid; - } - -+ // Parchment start -+ @Override -+ public @Nullable UUID getUniqueId() { -+ return uuid; -+ } -+ // Parchment end -+ - /** - * Sets the UUID for this player name. This will skip the initial API call to find the players UUID. - * -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -index 89e132525cfae0ce979e37b3e2793df781e47227..8b8b529fc3ee8dc370937e7125a665905fd45806 100644 ---- a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -@@ -1,14 +1,16 @@ - package com.destroystokyo.paper.exception; - -+import me.lexikiq.HasPlayer; - import org.bukkit.entity.Player; - import org.bukkit.plugin.Plugin; -+import org.jetbrains.annotations.NotNull; - - import static com.google.common.base.Preconditions.*; - - /** - * Thrown when an incoming plugin message channel throws an exception - */ --public class ServerPluginMessageException extends ServerPluginException { -+public class ServerPluginMessageException extends ServerPluginException implements HasPlayer { // Parchment - - private final Player player; - private final String channel; -@@ -40,7 +42,7 @@ public class ServerPluginMessageException extends ServerPluginException { - * - * @return exception channel - */ -- public String getChannel() { -+ public @NotNull String getChannel() { // Parchment - return channel; - } - -@@ -58,7 +60,7 @@ public class ServerPluginMessageException extends ServerPluginException { - * - * @return exception player - */ -- public Player getPlayer() { -+ public @NotNull Player getPlayer() { // Parchment - return player; - } - } -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -index 2c1cda1126e577a88f19071e958eddb5a38785af..56976277476d3ebb6627269d35a92800fed1169d 100644 ---- a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -@@ -1,5 +1,6 @@ - package io.papermc.paper.event.packet; - -+import me.lexikiq.HasPlayer; - import org.bukkit.Chunk; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -@@ -14,7 +15,7 @@ import org.jetbrains.annotations.NotNull; - * Should only be used for packet/clientside related stuff. - * Not intended for modifying server side state. - */ --public class PlayerChunkLoadEvent extends ChunkEvent { -+public class PlayerChunkLoadEvent extends ChunkEvent implements HasPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private final Player player; -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -index 12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b..139ce51c98d68d2a1a493ae92825d9375d7b1950 100644 ---- a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -@@ -1,5 +1,6 @@ - package io.papermc.paper.event.packet; - -+import me.lexikiq.HasPlayer; - import org.bukkit.Chunk; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -@@ -12,7 +13,7 @@ import org.jetbrains.annotations.NotNull; - * Should only be used for packet/clientside related stuff. - * Not intended for modifying server side. - */ --public class PlayerChunkUnloadEvent extends ChunkEvent { -+public class PlayerChunkUnloadEvent extends ChunkEvent implements HasPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private final Player player; -diff --git a/src/main/java/me/lexikiq/HasHumanEntity.java b/src/main/java/me/lexikiq/HasHumanEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d2fbd2a415584e71f5c88ad7e42a13bebabe16d7 ---- /dev/null -+++ b/src/main/java/me/lexikiq/HasHumanEntity.java -@@ -0,0 +1,17 @@ -+package me.lexikiq; -+ -+import org.bukkit.entity.HumanEntity; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an object that has a {@link HumanEntity} -+ */ -+public interface HasHumanEntity extends OptionalHumanEntity { -+ /** -+ * Gets a {@link HumanEntity} object that this represents -+ * -+ * @return human entity -+ */ -+ @Override -+ @NotNull HumanEntity getPlayer(); -+} -diff --git a/src/main/java/me/lexikiq/HasOfflinePlayer.java b/src/main/java/me/lexikiq/HasOfflinePlayer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..184055b7468911550bf86b4a6ad95a9399e5e669 ---- /dev/null -+++ b/src/main/java/me/lexikiq/HasOfflinePlayer.java -@@ -0,0 +1,17 @@ -+package me.lexikiq; -+ -+import org.bukkit.OfflinePlayer; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an object that has a {@link OfflinePlayer} -+ */ -+public interface HasOfflinePlayer extends OptionalOfflinePlayer { -+ /** -+ * Gets an {@link OfflinePlayer} object that this represents -+ * -+ * @return offline player -+ */ -+ @Override -+ @NotNull OfflinePlayer getOfflinePlayer(); -+} -diff --git a/src/main/java/me/lexikiq/HasPlayer.java b/src/main/java/me/lexikiq/HasPlayer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..df10bd66eb531f51b519815a67566195a9432f96 ---- /dev/null -+++ b/src/main/java/me/lexikiq/HasPlayer.java -@@ -0,0 +1,17 @@ -+package me.lexikiq; -+ -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an object that has a {@link Player} -+ */ -+public interface HasPlayer extends OptionalPlayer, HasHumanEntity { -+ /** -+ * Gets a {@link Player} object that this represents -+ * -+ * @return player -+ */ -+ @Override -+ @NotNull Player getPlayer(); -+} -diff --git a/src/main/java/me/lexikiq/OptionalHumanEntity.java b/src/main/java/me/lexikiq/OptionalHumanEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fc5a565e9b654eaa3604f9be5f0fa86bbaab6f2f ---- /dev/null -+++ b/src/main/java/me/lexikiq/OptionalHumanEntity.java -@@ -0,0 +1,16 @@ -+package me.lexikiq; -+ -+import org.bukkit.entity.HumanEntity; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents an object that may have a {@link HumanEntity} -+ */ -+public interface OptionalHumanEntity { -+ /** -+ * Gets a {@link HumanEntity} object that this represents, if there is one -+ * -+ * @return human entity or null -+ */ -+ @Nullable HumanEntity getPlayer(); -+} -diff --git a/src/main/java/me/lexikiq/OptionalOfflinePlayer.java b/src/main/java/me/lexikiq/OptionalOfflinePlayer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1622ec23d985337c61da4b977c98a9b8cbd051f8 ---- /dev/null -+++ b/src/main/java/me/lexikiq/OptionalOfflinePlayer.java -@@ -0,0 +1,16 @@ -+package me.lexikiq; -+ -+import org.bukkit.OfflinePlayer; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents an object that may have an {@link OfflinePlayer} -+ */ -+public interface OptionalOfflinePlayer { -+ /** -+ * Gets an {@link OfflinePlayer} object that this represents, if there is one -+ * -+ * @return offline player or null -+ */ -+ @Nullable OfflinePlayer getOfflinePlayer(); -+} -diff --git a/src/main/java/me/lexikiq/OptionalPlayer.java b/src/main/java/me/lexikiq/OptionalPlayer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..70fcce84e8b42f3a2c3543b8365b25cc90addc8d ---- /dev/null -+++ b/src/main/java/me/lexikiq/OptionalPlayer.java -@@ -0,0 +1,16 @@ -+package me.lexikiq; -+ -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents an object that may have a {@link Player} -+ */ -+public interface OptionalPlayer extends OptionalHumanEntity { -+ /** -+ * Gets a {@link Player} object that this represents, if there is one -+ * -+ * @return player or null -+ */ -+ @Nullable Player getPlayer(); -+} -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 3afd5f5c0208a4ee93b5dbfc2aab2b9d2e8a7544..e2b4f86fc3825a77a5a0c1c29b428308eee54b16 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -1,6 +1,10 @@ - package org.bukkit; - - import java.util.UUID; -+ -+import me.lexikiq.HasOfflinePlayer; -+import me.lexikiq.HasUniqueId; -+import me.lexikiq.OptionalPlayer; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.EntityType; -@@ -9,7 +13,13 @@ import org.bukkit.permissions.ServerOperator; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - --public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable { -+public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, OptionalPlayer, HasUniqueId, HasOfflinePlayer { // Parchment -+ // Parchment start -+ @Override -+ @NotNull default OfflinePlayer getOfflinePlayer() { -+ return this; -+ } -+ // Parchment end - - /** - * Checks if this player is currently online -diff --git a/src/main/java/org/bukkit/attribute/AttributeModifier.java b/src/main/java/org/bukkit/attribute/AttributeModifier.java -index ff8f1231f3e2e71740fd24fa8d4dac5d0e550ae7..b2f6e641125fb4c3389cbda8a62d6198bbcacc0f 100644 ---- a/src/main/java/org/bukkit/attribute/AttributeModifier.java -+++ b/src/main/java/org/bukkit/attribute/AttributeModifier.java -@@ -4,6 +4,8 @@ import java.util.HashMap; - import java.util.Map; - import java.util.Objects; - import java.util.UUID; -+ -+import me.lexikiq.HasUniqueId; - import org.apache.commons.lang.Validate; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.inventory.EquipmentSlot; -@@ -14,7 +16,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Concrete implementation of an attribute modifier. - */ --public class AttributeModifier implements ConfigurationSerializable { -+public class AttributeModifier implements ConfigurationSerializable, HasUniqueId { // Parchment - - private final UUID uuid; - private final String name; -diff --git a/src/main/java/org/bukkit/entity/AnimalTamer.java b/src/main/java/org/bukkit/entity/AnimalTamer.java -index 2e17b2d4f759531fbe9ee8e9b00c839186af09ca..b412cca0cdcb7ffa295a77cb96546d3c51c683d1 100644 ---- a/src/main/java/org/bukkit/entity/AnimalTamer.java -+++ b/src/main/java/org/bukkit/entity/AnimalTamer.java -@@ -1,10 +1,9 @@ - package org.bukkit.entity; - --import java.util.UUID; --import org.jetbrains.annotations.NotNull; -+import me.lexikiq.HasUniqueId; - import org.jetbrains.annotations.Nullable; - --public interface AnimalTamer { -+public interface AnimalTamer extends HasUniqueId { // Parchment - - /** - * This is the name of the specified AnimalTamer. -@@ -14,11 +13,5 @@ public interface AnimalTamer { - @Nullable - public String getName(); - -- /** -- * This is the UUID of the specified AnimalTamer. -- * -- * @return The UUID to reference on tamed animals -- */ -- @NotNull -- public UUID getUniqueId(); -+ // Parchment: now inherits getUniqueId from interface HasUniqueId - } -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 46985eaea3d3b00d1dd88c2dd5a2bc53d518c64f..b33b9bb12e16f1e491912a3fdae6db552a4f8bfa 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -2,7 +2,8 @@ package org.bukkit.entity; - - import java.util.List; - import java.util.Set; --import java.util.UUID; -+ -+import me.lexikiq.HasUniqueId; - import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; -@@ -26,7 +27,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a base entity in the world - */ --public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper -+public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource, HasUniqueId { // Paper // Parchment - - /* - * Gets the entity's current position -@@ -383,13 +384,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - @Nullable - public EntityDamageEvent getLastDamageCause(); - -- /** -- * Returns a unique and persistent id for this entity -- * -- * @return unique id -- */ -- @NotNull -- public UUID getUniqueId(); -+ // Parchment: now inherits getUniqueId from interface HasUniqueID - - /** - * Gets the amount of ticks this entity has lived for. -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 2ce774c81a93260a1464183d435b4c418ed61648..aaf08f8e2cce8c7f7f0520fbe3904d260aafbeb9 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -2,6 +2,8 @@ package org.bukkit.entity; - - import java.util.Collection; - import java.util.Set; -+ -+import me.lexikiq.HasHumanEntity; - import org.bukkit.GameMode; - import org.bukkit.Location; - import org.bukkit.Material; -@@ -19,7 +21,18 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a human entity, such as an NPC or a player - */ --public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder { -+public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder, HasHumanEntity { // Parchment -+ -+ // Parchment start -+ /** -+ * Returns this human entity -+ * @return this human entity -+ */ -+ @Override -+ @NotNull default HumanEntity getPlayer() { -+ return this; -+ }; -+ // Parchment end - - /** - * Returns the name of this player -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index a4b236d75e77176a163094edd31f81725bbf4eca..54138dae452714e73549ad1c1512b68267cad443 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -5,6 +5,7 @@ import java.util.Set; // Paper - import java.util.UUID; - import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper -+import me.lexikiq.HasPlayer; - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper - import java.util.Date; // Paper -@@ -39,7 +40,18 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, HasPlayer { // Paper // Parchment -+ -+ // Parchment start -+ /** -+ * Returns this player -+ * @return this player -+ */ -+ @Override -+ @NotNull default Player getPlayer() { -+ return this; -+ }; -+ // Parchment end - - // Paper start - @Override -diff --git a/src/main/java/org/bukkit/event/block/BlockBreakEvent.java b/src/main/java/org/bukkit/event/block/BlockBreakEvent.java -index c05cd9cadcff827a2eb236cf955bc898fa5e8b52..47127320d4ee35ccae959dad4cc4483911546a9e 100644 ---- a/src/main/java/org/bukkit/event/block/BlockBreakEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockBreakEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull; - * If a Block Break event is cancelled, the block will not break and - * experience will not drop. - */ --public class BlockBreakEvent extends BlockExpEvent implements Cancellable { -+public class BlockBreakEvent extends BlockExpEvent implements Cancellable, HasPlayer { // Parchment - private final Player player; - private boolean dropItems; - private boolean cancel; -diff --git a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java -index a1350c0f74d445dca09eea6e10abac050bb06990..c08aef3b7c7705127e215f29d480080da0b8519b 100644 ---- a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.OptionalPlayer; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.data.BlockData; -@@ -19,7 +20,7 @@ import org.jetbrains.annotations.Nullable; - * #getMaterial()} instead. - * - */ --public class BlockCanBuildEvent extends BlockEvent { -+public class BlockCanBuildEvent extends BlockEvent implements OptionalPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - protected boolean buildable; - -diff --git a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java -index f70871e1ae7b1a1d77405d942d82666f03bf0498..8757ed7671bce68dc1dcb8983ee6d9cd28cc62c5 100644 ---- a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -12,7 +13,7 @@ import org.jetbrains.annotations.NotNull; - *

- * If a Block Damage event is cancelled, the block will not be damaged. - */ --public class BlockDamageEvent extends BlockEvent implements Cancellable { -+public class BlockDamageEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private final Player player; - private boolean instaBreak; -diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -index 3dd4bd38e72c04e74e5787fb38ca9abd10bad06b..bfb0672f25581db817a4fed1bec3489af98ec809 100644 ---- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -@@ -1,6 +1,8 @@ - package org.bukkit.event.block; - - import java.util.List; -+ -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.block.BlockState; - import org.bukkit.entity.Item; -@@ -24,7 +26,7 @@ import org.jetbrains.annotations.NotNull; - * AIR in most cases. Use #getBlockState() for more Information about the broken - * block. - */ --public class BlockDropItemEvent extends BlockEvent implements Cancellable { -+public class BlockDropItemEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private final Player player; -diff --git a/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java b/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java -index 695309b4b7ef269ba2496408a5f874f61cd6c445..0351d70dc5faefb80a373317e2145a958d0e485e 100644 ---- a/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockFertilizeEvent.java -@@ -1,6 +1,8 @@ - package org.bukkit.event.block; - - import java.util.List; -+ -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.block.BlockState; - import org.bukkit.entity.Player; -@@ -15,7 +17,7 @@ import org.jetbrains.annotations.Nullable; - * block with bonemeal. Will be called after the applicable - * {@link StructureGrowEvent}. - */ --public class BlockFertilizeEvent extends BlockEvent implements Cancellable { -+public class BlockFertilizeEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; -diff --git a/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java -index 6dcd9f828c6c40e48593b0bad5a44a656eb01645..42b5ddf3e89842fc0e2eb5319e5318d976638761 100644 ---- a/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.OptionalPlayer; - import org.bukkit.block.Block; - import org.bukkit.entity.Entity; - import org.bukkit.entity.Player; -@@ -14,7 +15,7 @@ import org.jetbrains.annotations.Nullable; - *

- * If a Block Ignite event is cancelled, the block will not be ignited. - */ --public class BlockIgniteEvent extends BlockEvent implements Cancellable { -+public class BlockIgniteEvent extends BlockEvent implements Cancellable, OptionalPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private final IgniteCause cause; - private final Entity ignitingEntity; -diff --git a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java -index be0a2d1f234d8265d98e54e518a994957b1f3ab7..8999f8ce6b82d7a8ad7c977037d7939b0a43f609 100644 ---- a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.block.BlockState; - import org.bukkit.entity.Player; -@@ -14,7 +15,7 @@ import org.jetbrains.annotations.NotNull; - *

- * If a Block Place event is cancelled, the block will not be placed. - */ --public class BlockPlaceEvent extends BlockEvent implements Cancellable { -+public class BlockPlaceEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - protected boolean cancel; - protected boolean canBuild; -diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -index 1f79f704abf339150df08900b8ea7da4cefef258..08c8f7578b0c9a48b25fe161b506cc4772ff96f5 100644 ---- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java -+++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.block; - -+import me.lexikiq.HasPlayer; - import org.bukkit.block.Block; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -12,7 +13,7 @@ import org.jetbrains.annotations.Nullable; - *

- * If a Sign Change event is cancelled, the sign will not be changed. - */ --public class SignChangeEvent extends BlockEvent implements Cancellable { -+public class SignChangeEvent extends BlockEvent implements Cancellable, HasPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; - private final Player player; -diff --git a/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java b/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java -index 59aab10c2d27247eb77bd71d75b5f9126aa0fb12..1d4abde60166d63cbd0344419052b1f946e483a8 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityEnterLoveModeEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.entity; - -+import me.lexikiq.OptionalHumanEntity; - import org.bukkit.entity.Animals; - import org.bukkit.entity.HumanEntity; - import org.bukkit.event.Cancellable; -@@ -7,13 +8,15 @@ import org.bukkit.event.HandlerList; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -+import java.util.UUID; -+ - /** - * Called when an entity enters love mode. - *
- * This can be cancelled but the item will still be consumed that was used to - * make the entity enter into love mode. - */ --public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable { -+public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable, OptionalHumanEntity { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private boolean cancel; -@@ -42,12 +45,27 @@ public class EntityEnterLoveModeEvent extends EntityEvent implements Cancellable - * - * @return The Human entity that caused the animal to enter love mode, or - * null if there wasn't one. -+ * @deprecated alias of {@link #getPlayer()} - */ - @Nullable -+ @Deprecated // Parchment - inconsistent naming, other events use getPlayer even when returned type is HumanEntity - public HumanEntity getHumanEntity() { - return humanEntity; - } - -+ // Parchment start -+ /** -+ * Gets the Human Entity that caused the animal to enter love mode. -+ * -+ * @return The Human entity that caused the animal to enter love mode, or -+ * null if there wasn't one. -+ */ -+ @Nullable -+ public HumanEntity getPlayer() { -+ return humanEntity; -+ } -+ // Parchment end -+ - /** - * Gets the amount of ticks that the animal will fall in love for. - * -diff --git a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java -index ea8f9ed43d8e4158e6c9c345252a94a5000c5561..a56d5f0518bcbf5c07646e449659055bd08a0ff3 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.entity; - -+import me.lexikiq.OptionalPlayer; - import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Entity; -@@ -16,7 +17,7 @@ import org.jetbrains.annotations.Nullable; - * Note that this event is currently only fired for four specific placements: - * armor stands, boats, minecarts, and end crystals. - */ --public class EntityPlaceEvent extends EntityEvent implements Cancellable { -+public class EntityPlaceEvent extends EntityEvent implements Cancellable, OptionalPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; -diff --git a/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java b/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java -index 5eb3fb72a13881b8bf0e40037b0002cb0a6eb883..0f1d9a271ceb3a62026211301771b38176dab077 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.entity; - -+import me.lexikiq.HasPlayer; - import org.bukkit.entity.Entity; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -10,7 +11,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Called immediately prior to a creature being leashed by a player. - */ --public class PlayerLeashEntityEvent extends Event implements Cancellable { -+public class PlayerLeashEntityEvent extends Event implements Cancellable, HasPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private final Entity leashHolder; - private final Entity entity; -diff --git a/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java b/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java -index 959b9f3fb41f8de6c8fb9a3b2df13212e29cf0e7..6a77a4dedcd15e0a1549be330774c22b213fff4e 100644 ---- a/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java -+++ b/src/main/java/org/bukkit/event/hanging/HangingPlaceEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.hanging; - -+import me.lexikiq.OptionalPlayer; - import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Hanging; -@@ -12,7 +13,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Triggered when a hanging entity is created in the world - */ --public class HangingPlaceEvent extends HangingEvent implements Cancellable { -+public class HangingPlaceEvent extends HangingEvent implements Cancellable, OptionalPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final Player player; -diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java -index 020739697a0b535cad0b15b574f77cdabbdfa3eb..8d83f406a07fa20fee0a63237e31f141919199fb 100644 ---- a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import me.lexikiq.HasPlayer; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.entity.Player; -@@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - /** - * This event is called when a player takes items out of the furnace - */ --public class FurnaceExtractEvent extends BlockExpEvent { -+public class FurnaceExtractEvent extends BlockExpEvent implements HasPlayer { // Parchment - private final Player player; - private final Material itemType; - private final int itemAmount; -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -index 21ad8888c0e403bfc63518502577d651c02dda05..fcf0424fa7dbbca8c8358069971304dfc8153e49 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java -@@ -1,6 +1,7 @@ - - package org.bukkit.event.inventory; - -+import me.lexikiq.HasHumanEntity; - import org.bukkit.entity.HumanEntity; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.InventoryView; -@@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a player related inventory event - */ --public class InventoryCloseEvent extends InventoryEvent { -+public class InventoryCloseEvent extends InventoryEvent implements HasHumanEntity { // Parchment - private static final HandlerList handlers = new HandlerList(); - // Paper start - private final Reason reason; -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java -index 9013d043503d175004ad276799e5935b7fa59dc4..9a6e1ebd46d580addf532786842ea64f6559ba37 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import me.lexikiq.HasHumanEntity; - import org.bukkit.entity.HumanEntity; - import org.bukkit.event.Cancellable; - import org.bukkit.event.HandlerList; -@@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a player related inventory event - */ --public class InventoryOpenEvent extends InventoryEvent implements Cancellable { -+public class InventoryOpenEvent extends InventoryEvent implements Cancellable, HasHumanEntity { // Parchment - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index 77aefda5aac4602bf5bf71c29600e7450defdd4e..e1275a902986ea82187f491503032d60b8c2c784 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -4,6 +4,7 @@ import java.net.InetAddress; - import java.util.UUID; - - import com.destroystokyo.paper.profile.PlayerProfile; -+import me.lexikiq.HasUniqueId; - import org.bukkit.Bukkit; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; -@@ -14,7 +15,7 @@ import org.jetbrains.annotations.NotNull; - *

- * This event is asynchronous, and not run using main thread. - */ --public class AsyncPlayerPreLoginEvent extends Event { -+public class AsyncPlayerPreLoginEvent extends Event implements HasUniqueId { // Parchment - private static final HandlerList handlers = new HandlerList(); - private Result result; - private net.kyori.adventure.text.Component message; // Paper -diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java -index f6d3b817de3001f04ea4554c7c39a1290af3fd6d..85a7a49d59902cd292f5a0d14af472c458f9b674 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.player; - -+import me.lexikiq.HasPlayer; - import org.bukkit.entity.Player; - import org.bukkit.event.Event; - import org.jetbrains.annotations.NotNull; -@@ -7,7 +8,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a player related event - */ --public abstract class PlayerEvent extends Event { -+public abstract class PlayerEvent extends Event implements HasPlayer { // Parchment - protected Player player; - - public PlayerEvent(@NotNull final Player who) { -diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -index 123979ed64939d615b061f91c19c630e1e1db8c7..90cbfe9c3bd1c6fb8da85e0fb6b24d3ad23282ce 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -@@ -2,6 +2,8 @@ package org.bukkit.event.player; - - import java.net.InetAddress; - import java.util.UUID; -+ -+import me.lexikiq.HasUniqueId; - import org.bukkit.Warning; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; -@@ -16,7 +18,7 @@ import org.jetbrains.annotations.NotNull; - */ - @Deprecated - @Warning(reason = "This event causes a login thread to synchronize with the main thread") --public class PlayerPreLoginEvent extends Event { -+public class PlayerPreLoginEvent extends Event implements HasUniqueId { // Parchment - private static final HandlerList handlers = new HandlerList(); - private Result result; - private net.kyori.adventure.text.Component message; // Paper -diff --git a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -index 68eab1563caba1ee4f52b308f390e4e172667fc5..9e4ed3642e60a49a29c0bbfa3c46043d645bde4d 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.player; - -+import me.lexikiq.HasPlayer; - import org.bukkit.entity.Entity; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -@@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Called prior to an entity being unleashed due to a player's action. - */ --public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Cancellable { -+public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Cancellable, HasPlayer { // Parchment - private final Player player; - private boolean cancelled = false; - -diff --git a/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java b/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java -index 128e43cf12205f82f2b119a773208502cdccfdd4..d18daf2d8625e27bfd02c8191b57d8eae96b8d2c 100644 ---- a/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java -+++ b/src/main/java/org/bukkit/event/raid/RaidTriggerEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.raid; - -+import me.lexikiq.HasPlayer; - import org.bukkit.Raid; - import org.bukkit.World; - import org.bukkit.entity.Player; -@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull; - * Called when a {@link Raid} is triggered (e.g: a player with Bad Omen effect - * enters a village). - */ --public class RaidTriggerEvent extends RaidEvent implements Cancellable { -+public class RaidTriggerEvent extends RaidEvent implements Cancellable, HasPlayer { // Parchment - - private static final HandlerList handlers = new HandlerList(); - // -diff --git a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java -index 7af8d6e51c824cf0592b722b834f1d4986e3cc08..5e869c53255d3fa5876c7a6bb0e7104a24b33388 100644 ---- a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java -+++ b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java -@@ -1,6 +1,8 @@ - package org.bukkit.event.world; - - import java.util.List; -+ -+import me.lexikiq.OptionalPlayer; - import org.bukkit.Location; - import org.bukkit.TreeType; - import org.bukkit.block.BlockState; -@@ -14,7 +16,7 @@ import org.jetbrains.annotations.Nullable; - * Event that is called when an organic structure attempts to grow (Sapling {@literal ->} - * Tree), (Mushroom {@literal ->} Huge Mushroom), naturally or using bonemeal. - */ --public class StructureGrowEvent extends WorldEvent implements Cancellable { -+public class StructureGrowEvent extends WorldEvent implements Cancellable, OptionalPlayer { // Parchment - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled = false; - private final Location location; -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index b06995aa57aa9cba0bb59f1d26d81015619a08e6..c16b7174139d9e437ce6c16f48e40e8b639f9ec7 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -1,6 +1,7 @@ - package org.bukkit.inventory; - - import com.google.common.base.Preconditions; -+import me.lexikiq.HasHumanEntity; - import org.bukkit.entity.HumanEntity; - import org.bukkit.event.inventory.InventoryType; - import org.jetbrains.annotations.NotNull; -@@ -14,7 +15,7 @@ import org.jetbrains.annotations.Nullable; - * contracts of certain methods, there's no guarantee that the game will work - * as it should. - */ --public abstract class InventoryView { -+public abstract class InventoryView implements HasHumanEntity { // Parchment - public static final int OUTSIDE = -999; - /** - * Represents various extra properties of certain inventory windows. -diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java -index f4e626f92857f2d091b1c2370aa0ce928b088c9e..d4de2902c5ba6e03a68fea4b2c4c6828f767f920 100644 ---- a/src/main/java/org/bukkit/scoreboard/Score.java -+++ b/src/main/java/org/bukkit/scoreboard/Score.java -@@ -1,5 +1,6 @@ - package org.bukkit.scoreboard; - -+import me.lexikiq.HasOfflinePlayer; - import org.bukkit.OfflinePlayer; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -@@ -9,7 +10,7 @@ import org.jetbrains.annotations.Nullable; - * #getObjective() objective}. Changing this will not affect any other - * objective or scoreboard. - */ --public interface Score { -+public interface Score extends HasOfflinePlayer { // Parchment - - /** - * Gets the OfflinePlayer being tracked by this Score -@@ -22,6 +23,22 @@ public interface Score { - @NotNull - OfflinePlayer getPlayer(); - -+ // Parchment start -+ /** -+ * Gets the OfflinePlayer being tracked by this Score -+ *

-+ * Alias for {@link #getPlayer()} -+ * -+ * @return this Score's tracked player -+ * @deprecated Scoreboards can contain entries that aren't players -+ * @see #getEntry() -+ */ -+ @Override -+ @NotNull default OfflinePlayer getOfflinePlayer() { -+ return getPlayer(); -+ } -+ // Parchment end -+ - /** - * Gets the entry being tracked by this Score - * diff --git a/patches/reverted/api/0003-Add-Optional-PlayerLike-interfaces.patch b/patches/reverted/api/0003-Add-Optional-PlayerLike-interfaces.patch deleted file mode 100644 index 49256fc..0000000 --- a/patches/reverted/api/0003-Add-Optional-PlayerLike-interfaces.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Mon, 3 May 2021 21:48:40 -0400 -Subject: [PATCH] Add [Optional]PlayerLike interfaces - - -diff --git a/src/main/java/me/lexikiq/OptionalPlayerLike.java b/src/main/java/me/lexikiq/OptionalPlayerLike.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aaa1879f9560ef6ff415e98a5fdf2403f0480a0b ---- /dev/null -+++ b/src/main/java/me/lexikiq/OptionalPlayerLike.java -@@ -0,0 +1,16 @@ -+package me.lexikiq; -+ -+import net.kyori.adventure.identity.Identified; -+import net.kyori.adventure.identity.Identity; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Class that may be like a {@link org.bukkit.entity.Player} in that it has a {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, {@link Identity}, and a nullable Player. -+ * @see me.lexikiq.PlayerLike -+ */ -+public interface OptionalPlayerLike extends OptionalPlayer, HasUniqueId, HasOfflinePlayer, Identified { -+ @Override -+ default @NonNull Identity identity() { -+ return Identity.identity(getUniqueId()); -+ } -+} -diff --git a/src/main/java/me/lexikiq/PlayerLike.java b/src/main/java/me/lexikiq/PlayerLike.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3184f585f9c6e59ce9297d6613749453ce5e6ab5 ---- /dev/null -+++ b/src/main/java/me/lexikiq/PlayerLike.java -@@ -0,0 +1,7 @@ -+package me.lexikiq; -+ -+/** -+ * Class that is like a {@link org.bukkit.entity.Player} in that it has a Player, {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, and an {@link net.kyori.adventure.identity.Identity}. -+ * @see me.lexikiq.OptionalPlayerLike -+ */ -+public interface PlayerLike extends HasPlayer, OptionalPlayerLike {} -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index e2b4f86fc3825a77a5a0c1c29b428308eee54b16..95220ef8ad0602fae9f88c0231762ff50358d98f 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -5,6 +5,7 @@ import java.util.UUID; - import me.lexikiq.HasOfflinePlayer; - import me.lexikiq.HasUniqueId; - import me.lexikiq.OptionalPlayer; -+import me.lexikiq.OptionalPlayerLike; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.EntityType; -@@ -13,7 +14,7 @@ import org.bukkit.permissions.ServerOperator; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - --public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, OptionalPlayer, HasUniqueId, HasOfflinePlayer { // Parchment -+public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, OptionalPlayerLike { // Parchment - // Parchment start - @Override - @NotNull default OfflinePlayer getOfflinePlayer() { -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 54138dae452714e73549ad1c1512b68267cad443..2c9aa0cbce1450695b285a9e654b0e9f10e28c37 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -6,6 +6,7 @@ import java.util.UUID; - import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper - import me.lexikiq.HasPlayer; -+import me.lexikiq.PlayerLike; - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper - import java.util.Date; // Paper -@@ -40,7 +41,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, HasPlayer { // Paper // Parchment -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, PlayerLike { // Paper // Parchment - - // Parchment start - /** diff --git a/patches/reverted/api/0004-Update-to-Java-15.patch b/patches/reverted/api/0004-Update-to-Java-15.patch deleted file mode 100644 index a7ac28b..0000000 --- a/patches/reverted/api/0004-Update-to-Java-15.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sun, 9 May 2021 17:03:09 -0400 -Subject: [PATCH] Update to Java 15 - - -diff --git a/pom.xml b/pom.xml -index 6857042b3475925f426cbe9f4858438a02bebd23..a295e88e8c05306c0e5876608797d64df6dc1699 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -19,8 +19,10 @@ - - - -- 1.8 -- 1.8 -+ -+ 15 -+ 15 -+ - UTF-8 - 4.7.0 - -@@ -148,7 +150,7 @@ - - - org.jetbrains -- annotations-java5 -+ annotations - 20.1.0 - provided - -@@ -278,15 +280,38 @@ - - - -+ -+ -+ org.apache.maven.plugins -+ maven-source-plugin -+ 3.2.0 -+ -+ -+ attach-sources -+ -+ jar -+ -+ -+ -+ - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 -+ -+ -+ attach-javadocs -+ -+ jar -+ -+ -+ - -+ ${java.home}/bin/javadoc - - https://guava.dev/releases/21.0/api/docs/ - https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ -- https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ -+ https://javadoc.io/doc/org.jetbrains/annotations/20.1.0/ - https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ - - https://jd.adventure.kyori.net/api/${adventure.version}/ -@@ -297,6 +322,7 @@ - - - -+ - - - diff --git a/patches/reverted/api/0007-Make-OptionalPlayerLike-extend-Audience.patch b/patches/reverted/api/0007-Make-OptionalPlayerLike-extend-Audience.patch deleted file mode 100644 index ee0b9e2..0000000 --- a/patches/reverted/api/0007-Make-OptionalPlayerLike-extend-Audience.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Fri, 14 May 2021 21:05:49 -0400 -Subject: [PATCH] Make OptionalPlayerLike extend Audience - - -diff --git a/src/main/java/me/lexikiq/OptionalPlayer.java b/src/main/java/me/lexikiq/OptionalPlayer.java -index 70fcce84e8b42f3a2c3543b8365b25cc90addc8d..428e25fa82e276c473f3d96e56ac1539431a6674 100644 ---- a/src/main/java/me/lexikiq/OptionalPlayer.java -+++ b/src/main/java/me/lexikiq/OptionalPlayer.java -@@ -13,4 +13,13 @@ public interface OptionalPlayer extends OptionalHumanEntity { - * @return player or null - */ - @Nullable Player getPlayer(); -+ -+ /** -+ * Tests if the {@link Player} represented by this object is online. -+ * -+ * @return true if online -+ */ -+ default boolean isOnline() { -+ return getPlayer() != null; -+ } - } -diff --git a/src/main/java/me/lexikiq/OptionalPlayerLike.java b/src/main/java/me/lexikiq/OptionalPlayerLike.java -index aaa1879f9560ef6ff415e98a5fdf2403f0480a0b..d56c4612ac601fb43a277ee3102726e6547cfee8 100644 ---- a/src/main/java/me/lexikiq/OptionalPlayerLike.java -+++ b/src/main/java/me/lexikiq/OptionalPlayerLike.java -@@ -1,16 +1,200 @@ - package me.lexikiq; - -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.bossbar.BossBar; - import net.kyori.adventure.identity.Identified; - import net.kyori.adventure.identity.Identity; --import org.checkerframework.checker.nullness.qual.NonNull; -+import net.kyori.adventure.inventory.Book; -+import net.kyori.adventure.sound.Sound; -+import net.kyori.adventure.sound.SoundStop; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.title.Title; -+import org.apache.commons.lang.Validate; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.function.Consumer; - - /** - * Class that may be like a {@link org.bukkit.entity.Player} in that it has a {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, {@link Identity}, and a nullable Player. -+ *

-+ * This class extends the {@link Audience} interface and will silently fail if the player is not online. - * @see me.lexikiq.PlayerLike - */ --public interface OptionalPlayerLike extends OptionalPlayer, HasUniqueId, HasOfflinePlayer, Identified { -+public interface OptionalPlayerLike extends OptionalPlayer, HasUniqueId, HasOfflinePlayer, Identified, Audience { -+ /** -+ * Gets the identity corresponding with this object. -+ * -+ * @return the identity -+ * @since 4.0.0 -+ */ - @Override -- default @NonNull Identity identity() { -+ default @NotNull Identity identity() { - return Identity.identity(getUniqueId()); - } -+ -+ /** -+ * Run a consumer with the {@link Player} associated with this object if the player is online. -+ *

-+ * Allows easily running a code on the player only if they are connected. -+ * -+ * @param consumer function that accepts a Player -+ */ -+ default void consumeIfOnline(final @NotNull Consumer<@NotNull Player> consumer) { -+ Validate.notNull(consumer, "Consumer should not be null"); -+ -+ final Player player = getPlayer(); -+ if (player != null) -+ consumer.accept(player); -+ } -+ -+ /** -+ * Sends a chat message. -+ * -+ * @param source the identity of the source of the message -+ * @param message a message -+ * @param type the type -+ * @see Component -+ * @since 4.0.0 -+ */ -+ @Override -+ default void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { -+ consumeIfOnline(player -> player.sendMessage(source, message, type)); -+ } -+ -+ /** -+ * Sends a message on the action bar. -+ * -+ * @param message a message -+ * @see Component -+ * @since 4.0.0 -+ */ -+ @Override -+ default void sendActionBar(final @NotNull Component message) { -+ consumeIfOnline(player -> player.sendActionBar(message)); -+ } -+ -+ /** -+ * Sends the player list header and footer. -+ * -+ * @param header the header -+ * @param footer the footer -+ * @since 4.3.0 -+ */ -+ @Override -+ default void sendPlayerListHeaderAndFooter(final @NotNull Component header, final @NotNull Component footer) { -+ consumeIfOnline(player -> player.sendPlayerListHeaderAndFooter(header, footer)); -+ } -+ -+ /** -+ * Shows a title. -+ * -+ * @param title a title -+ * @see Title -+ * @since 4.0.0 -+ */ -+ @Override -+ default void showTitle(final @NotNull Title title) { -+ consumeIfOnline(player -> player.showTitle(title)); -+ } -+ -+ /** -+ * Clears the title, if one is being displayed. -+ * -+ * @see Title -+ * @since 4.0.0 -+ */ -+ @Override -+ default void clearTitle() { -+ consumeIfOnline(Audience::clearTitle); -+ } -+ -+ /** -+ * Resets the title and timings back to their default. -+ * -+ * @see Title -+ * @since 4.0.0 -+ */ -+ @Override -+ default void resetTitle() { -+ consumeIfOnline(Audience::resetTitle); -+ } -+ -+ /** -+ * Shows a boss bar. -+ * -+ * @param bar a boss bar -+ * @see BossBar -+ * @since 4.0.0 -+ */ -+ @Override -+ default void showBossBar(final @NotNull BossBar bar) { -+ consumeIfOnline(player -> player.showBossBar(bar)); -+ } -+ -+ /** -+ * Hides a boss bar. -+ * -+ * @param bar a boss bar -+ * @see BossBar -+ * @since 4.0.0 -+ */ -+ @Override -+ default void hideBossBar(final @NotNull BossBar bar) { -+ consumeIfOnline(player -> player.hideBossBar(bar)); -+ } -+ -+ /** -+ * Plays a sound. -+ * -+ * @param sound a sound -+ * @see Sound -+ * @since 4.0.0 -+ */ -+ @Override -+ default void playSound(final @NotNull Sound sound) { -+ consumeIfOnline(player -> player.playSound(sound)); -+ } -+ -+ /** -+ * Plays a sound at a location. -+ * -+ * @param sound a sound -+ * @param x x coordinate -+ * @param y y coordinate -+ * @param z z coordinate -+ * @see Sound -+ * @since 4.0.0 -+ */ -+ @Override -+ default void playSound(final @NotNull Sound sound, final double x, final double y, final double z) { -+ consumeIfOnline(player -> player.playSound(sound, x, y, z)); -+ } -+ -+ /** -+ * Stops a sound, or many sounds. -+ * -+ * @param stop a sound stop -+ * @see SoundStop -+ * @since 4.0.0 -+ */ -+ @Override -+ default void stopSound(final @NotNull SoundStop stop) { -+ consumeIfOnline(player -> player.stopSound(stop)); -+ } -+ -+ /** -+ * Opens a book. -+ * -+ *

When possible, no item should persist after closing the book.

-+ * -+ * @param book a book -+ * @see Book -+ * @since 4.0.0 -+ */ -+ @Override -+ default void openBook(final @NotNull Book book) { -+ consumeIfOnline(player -> player.openBook(book)); -+ } - } -diff --git a/src/main/java/me/lexikiq/PlayerLike.java b/src/main/java/me/lexikiq/PlayerLike.java -index 3184f585f9c6e59ce9297d6613749453ce5e6ab5..d00a256c3a489d918c4d9bef1023e621d0faece3 100644 ---- a/src/main/java/me/lexikiq/PlayerLike.java -+++ b/src/main/java/me/lexikiq/PlayerLike.java -@@ -1,7 +1,24 @@ - package me.lexikiq; - -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.function.Consumer; -+ - /** - * Class that is like a {@link org.bukkit.entity.Player} in that it has a Player, {@link java.util.UUID}, {@link org.bukkit.OfflinePlayer}, and an {@link net.kyori.adventure.identity.Identity}. - * @see me.lexikiq.OptionalPlayerLike - */ --public interface PlayerLike extends HasPlayer, OptionalPlayerLike {} -+public interface PlayerLike extends HasPlayer, OptionalPlayerLike { -+ -+ /** -+ * Run a consumer with the {@link Player} associated with this object. -+ * Unlike the parent class {@link OptionalPlayerLike}, this will always run. -+ * -+ * @param consumer function that accepts a Player -+ */ -+ @Override -+ default void consumeIfOnline(@NotNull Consumer<@NotNull Player> consumer) { -+ consumer.accept(getPlayer()); -+ } -+} -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 95220ef8ad0602fae9f88c0231762ff50358d98f..27e837a0dbcf37fff9927deb1c34a3ca96a7a49f 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -3,9 +3,7 @@ package org.bukkit; - import java.util.UUID; - - import me.lexikiq.HasOfflinePlayer; --import me.lexikiq.HasUniqueId; - import me.lexikiq.OptionalPlayer; --import me.lexikiq.OptionalPlayerLike; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.EntityType; -@@ -14,7 +12,7 @@ import org.bukkit.permissions.ServerOperator; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - --public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, OptionalPlayerLike { // Parchment -+public interface OfflinePlayer extends ServerOperator, AnimalTamer, ConfigurationSerializable, HasOfflinePlayer, OptionalPlayer { // Parchment - // Parchment start - @Override - @NotNull default OfflinePlayer getOfflinePlayer() { -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2c9aa0cbce1450695b285a9e654b0e9f10e28c37..b7ce4b50a7f8f9488cb30a40f0e8acaf2b8d33e7 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -5,8 +5,8 @@ import java.util.Set; // Paper - import java.util.UUID; - import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper -+import me.lexikiq.HasOfflinePlayer; - import me.lexikiq.HasPlayer; --import me.lexikiq.PlayerLike; - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper - import java.util.Date; // Paper -@@ -41,7 +41,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, PlayerLike { // Paper // Parchment -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient, HasOfflinePlayer, HasPlayer { // Paper // Parchment - - // Parchment start - /** diff --git a/patches/reverted/server/0001-Parchment-POM-Changes.patch b/patches/reverted/server/0001-Parchment-POM-Changes.patch deleted file mode 100644 index a41a7ed..0000000 --- a/patches/reverted/server/0001-Parchment-POM-Changes.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sat, 1 May 2021 14:36:37 -0400 -Subject: [PATCH] Parchment POM Changes - - -diff --git a/pom.xml b/pom.xml -index 1a9204c869dd36e80932b1366352db15ebd70723..e8c91265e5694676b6fb6a4b3ee022b88d1e5cf0 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,11 +1,11 @@ - - 4.0.0 -- paper -+ parchment - jar - 1.16.5-R0.1-SNAPSHOT -- Paper -- https://papermc.io -+ Parchment-Server -+ https://github.com/lexikiq/Parchment - - - -@@ -19,8 +19,8 @@ - - - -- com.destroystokyo.paper -- paper-parent -+ me.lexikiq -+ parchment-parent - dev-SNAPSHOT - ../pom.xml - -@@ -39,8 +39,8 @@ - - - -- com.destroystokyo.paper -- paper-api -+ me.lexikiq -+ parchment-api - ${project.version} - compile - -@@ -187,7 +187,7 @@ - - - -- paper-${minecraft.version} -+ parchment-${minecraft.version} - clean install - - -@@ -195,7 +195,7 @@ - gitdescribe-maven-plugin - 1.3 - -- git-Paper- -+ git-Parchment- - .. - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 674096cab190d62622f9947853b056f57d43a2a5..fbba763d909c4636174e79c680745b83c41409bb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.lexikiq/parchment-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/patches/reverted/server/0002-Disable-Metrics.patch b/patches/reverted/server/0002-Disable-Metrics.patch deleted file mode 100644 index 2fbc2a7..0000000 --- a/patches/reverted/server/0002-Disable-Metrics.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sat, 1 May 2021 14:44:37 -0400 -Subject: [PATCH] Disable Metrics - - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index dee00aac05f1acf050f05d4db557a08dd0f301c8..df2aefc163d9f932664e2ff0c8a8f9a5b09047e5 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -73,7 +73,7 @@ public class Metrics { - Metrics.logger = logger; - - // Start submitting the data -- startSubmitting(); -+ // startSubmitting(); - } - - /** diff --git a/patches/reverted/server/0003-Parchment-brand-changes.patch b/patches/reverted/server/0003-Parchment-brand-changes.patch deleted file mode 100644 index ef58a5e..0000000 --- a/patches/reverted/server/0003-Parchment-brand-changes.patch +++ /dev/null @@ -1,683 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Sat, 1 May 2021 15:08:28 -0400 -Subject: [PATCH] Parchment brand changes - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bf80e870e6a2a6fe1d4ae1bea355bcd7a0735d3b..2b5c226789e807574af798f49d09ebc55db4b71d 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1583,7 +1583,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Parchment"; //Parchment - Parchment > //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index cebecee640ed5a7fc2b978e00ff7eb012228267d..825a49819a4ff3302f1067d80654e698518506ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -230,7 +230,7 @@ import javax.annotation.Nullable; // Paper - import javax.annotation.Nonnull; // Paper - - public final class CraftServer implements Server { -- private final String serverName = "Paper"; // Paper -+ private final String serverName = "Parchment"; // Paper // Parchment - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 409fbeeb66fb8f58a72d94686bc9515299927b75..312225f15a864dc42df47f9911ba376ffb7b2c99 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -265,7 +265,7 @@ public class Main { - if (buildDate.before(deadline.getTime())) { - // Paper start - This is some stupid bullshit - System.err.println("*** Warning, you've not updated in a while! ***"); -- System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper -+ System.err.println("*** Please compile a new build ***"); // Paper - //System.err.println("*** Server will start in 20 seconds ***"); - //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); - // Paper End -diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -index a7d785f60c884ee4ee487cc364402d66c3dc2ecc..0aea373d9f0b09a19a0ed781938bba9cda1a4a30 100644 -GIT binary patch -literal 18477 -zcmV)9K*hg_P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T -zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p -z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i -z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW -zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X -zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 -zfg=2N-7=cNnjjOr{yriy6mMFgG#l -znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U -zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? -z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y -zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB -zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt -z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C -z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB -zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe -zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 -z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ -z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 -z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu -zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu -z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E -ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw -zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX -z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& -z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 -z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R -z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw -zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD -zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| -zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy -zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z -zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} -z002E$Nkl)=_nw*GA8U3yB?&1Ig#A3{Id9$X -z-m})M^3t`hu -zAc`1w*G(*XE?cJiJMfq-`Q>r{S|Q`Sv=dvuEY<*LyvsfDM9qIxzn>RXb9Iobu4#Y{e7ZHGxhuyJAS+?ZyfP0 -z`P@ODQms?tt?D~JJ=?#c05A39 -zo(Dg|k;hiTfAVPVyzFG6L}PQf=x19<1UVjQvaC+8(RuJ`w1?YCb1CfH;&TMhtFWd6LzW&Ym;t~E81$ZeP -zKl^nx>mNIcdoQ1Y)-AFWvJ9MsC=w-5fQcbWL=j9Idd4Wy%ro`8noBt9gnvsV`1b&T -zi~3gMoL|o8oL@F$;m3~Ro|{f3PeI4v9ViVZ0-M3uHVh0vPg|72d%%OW9&5o`n0j8D -z9Y4{L6CQI?r3Bknd1`y~GJfMIq_1yZi7Q20++x&qC9{D^x^7-=l;NYLwVf+1FaRDpu@OkR| -z&-Z+{zvu&>YzTkPoj1f!JDT0MQl;<#1_vN+i-|YE0_^n3N|2`?`wqGf9$7wr&Hw9S -zEp$7cI2Mawb5Vvn&KBi(_fCrA|I={x(Mj{_=03YG*IwrrJ(mSL!p^T)faMhUXm9NH -z>h-zh;scv6T1#K2`4wXT7X+zbkAu?2`!`;7HDCP1tMQK=g?iPLQVH%nJK%*>+(i_L -zR;E84nk`T -zbO#`cBi85*Gq4@WR0ZN#z?`ee;=_9=Vgu)2??nmtEB43Nmha~o#4Rvdl*s1LQ)7%b -zSX&9GRB{I@10wql>k3n_zTD3A5S>> -z+>{URp}6QKQG)$N6bh}t -z=AI~$3FBOtJ6?oT9H0K$<-G5mTaa}<$_GKzu|Wji_*}y5XFZT{(M_I<|6W~4yI0W} -z@I;Bir6SY|uBuE(mU)5CUP*+3$9cIv6DypP-!lrFg3h2PX^A2jqv&+umY*g>u~?Vg -zzRW35`$qis)~XmIiXFLA -z!T}_T+s|sT%V)a0=WC-EY}|fU3!FzQp^B9mL6w!5eQm_W -ztRtAgInQpNPe*n;XSHz7lXV3Isxa2hdv+b+JGY&c;B)c)-V2?al66s4EG!ei6JjpuD1;z;>VPF4_M)b`(cOs~X;BQw)l -z5m;ozUwaEWlIv)<0~?q#q5=#(E}Igw+8B{bt1b7Ir{XH`!X@ZPTuWpm7vZdk(dAOX -z<}8><6gAJ~TC`I9=sX#yzuxD0X2FsbVQJ+WEvLB$;G_F(%LPB$XZR<2R^uOk`VL;n -z;5!G}L!>Evdb>w_b)I@$pe8#5V%ALp?OwR>3dXi5WeUe}R4cqN9t#KXiIjXYP -z?F6pgOvc%t|yA+u}ekhc?K#8#FLTFC=F>BbSCrcO9w_I3OHY)k%2D!-#hJ(0b5w`xtDM< -z0Q}N?NAO=~S}woMap}byu<0a&512$7O_rwMa=g#ku45%U~f!0KE8%@q@ -z_Lx4hJJJz1{pn30+@*_1q6ihvTQF}rN-z;n_Y`9i -zUbXY-JpRja*ajs54m+8V(GEt6x)A%_-w!7nspc$2qBnvSf69O -z6Xq@N&}y|Y?Qtkf)RSEMXyC?3CO -z6LJqK+{pg3zDSzq!tgl<&f~46o8@HAk!Lx^M6BK$lUqm2Xj-j=sr!6uI79lwh(uQr -zMV5(We9Pf7Ij%n~Dr*+vP`vWf-`b%Of_kA`KvMyd9{zsm2}H5NdtU;cT|XyE@bjZ0 -zUbB^A=T8s!UGLp*JO>}NIvR(!9Vyc?;Bt#Xw8j{Z@;TZh=p-gGk%V1FGA~9cOwt<) -zI&zXov(;;-vFk2vF8IZ|I19>XTs8nWBJJ=VoK1ymP!URNl+vIhv{oq7!Z~>4v5a@T -zcLq<~I|f~W#^0!kX_B}dhVLxm#QE|@K4a!5O1FcrDdJ+8oYR9a({smV6gOFaO0^E4%$+X*I -z%JKkkTn1jlwRbqaaprIYfBBy`K^Gv-i%GS42dx~j0iUPh4~u**mblf6j=<;$A0h^& -z99kPps|T&X+gyy0(s-?jlnA>}0HZf_}rqj!fUwaz26=- -zMmL@o(G4YRMdVUY;CU{9`n)Ubaw)*FU;q*R6JIZ{s6EDD(|}YhbW@4z(+uAFYF#?! -z*S@BQ?|pY2JWfKRfV9z?D42RLAv4-&aRoS(&rnKZB866}1b(8EnkZ5wbLViFNDFw1 -zM7g{Ntu@+cRPf)SbOaqK6bcnsJ!^%yiNf_6T_uuEUGR3U8Q8i?K4^qIp!lGmL#Gr; -zl92lhiz8AI9jj=^AzkQ1I7+l1JnZ=UW67+e`_NN7`pt7BLdamCAI7g1uFKc1DXtXa -zBYP@-b>p((fMw?a>g2c+faJrVOYEyK&P#k9j^mG8N07S@fGT9`w372F1;%I*tdsGL -z4ES7>q%~$O^3FVr)`3WIMBzM<37W4EAsf(2H-;pNz4WX`_vi@lgt|G##50Ya2D;^kk_As+rP6cmUBO -zg|~A4ZVIggqL#UP+^T`IgWlBF|Y -z_D2Ss%f*M+CPosOpd>!<2s*qT1~(*v1e8nCUnv==II5H@3g$hEr0&0PAI^mZA;yaiiIE!kVa9llfx0 -z4iR=KeEC2Abz293CR~KGUdSpBiI!T&ydyYZvkjL|e#@i)Ypv0)X=y~(l{9UZ$pxE` -zK}!cI!@W~Zo`})a;75Vg(m@FlBQsDdnYG1A9kC9HbzA>nRr#T^u;zTK94&N6uYwj#nvzc30gA7Ji1 -zhYd+Q2+!W`3Hk6~LR&qx9}1JE0Di>;&}#T+3d>*&w33J@iHRey>AVVS=~`Jp;aZTH -z--^KmHv>)-&s6X0kcW>9L`I>NX5Fpl0kGZV$!s@yGMl~XRpn!V``&g$DX(g_R_V+r -zfDolMItu)>7TP#>H7Bif^?e;;ssc-*hxv0A5@cg~1UA@EqShI#=@9TAdz1q?ZDlIJ -zYEly8niO&cot#vupO37oRacpZN{epy-#Ys)nxT!qE^%5z2yf)14>npSkSA>6B)qzOm!@?}t@z2Ktu=g>R -zEcLWo9&%6C^%(6*Q%^VbWg+Z~q5x486U9~ -zCQ6HFg83JMt|ER6Y_j7l=FP9PfAvkCV%;sLm*ePs&D{o&RE%|D3AC=#vhB72+j;Yw -ziKB&!7L|{;-fFAic{dHQDQ17oq!kv=TITi*mj1tE!y2_>wrhzuiv=dGsC3P3J&B2R -zkmfQ;I;s4RqmVItu@oTBWVTyd17%if0J{CYVcB%ad3Zta#l3sV%$hc}d{W&)cuy3N -zdJ@5;?PoOrTOF*ez2z+W2YrKMDC+y`vQr9LIM#Y+Z-sCdEEpO2hS#H@Ewj$P3{y8B -z-iwJ>ib!iB9hgY1q-Fq*3Ywi4Goqf&Qk9={#R}Ehk)=|zU~^#y2Se?Iw?&rqMN$A4 -z7F^g2qLy5YR{{b}+ysEs1g&bto+kJ(rG%A>bQQx3X%oO+Yc(PR-#cZ|sDQ0_ZQ~uE -z!KeyL=z>cKv)&kZ#*Sx;$G$`Q$c&}B*LlxX)!NUTb9rU1OI|<`=>Y1yU^rKU0Vj2$C21UTp$Tz(?w`Fvjiti47R+r@Dx)J!}!^JKX% -zKR9+wxcHW;K%Egmgb0Zws>mEYB%PsjRrsk5V5GL-%yat}dy$0_tp2KLW!PB{F|~q2 -zW`B&mW*%0~%6bB&NTL*vi|2aCXG=n-(B$$p@$p_)alQ)g`EU;Jg)PjzC&vd;P~oi; -z3or!NjcrMoXhIph!IO48k@i^s!hyim0lxCt*HvaO3TCMjvSvZh-oXx^6x(#;UpJvJ -zYQBblieyWDGL*znksl~ss=|bLex%u-Tg!9v=kwhB`FQWk_s4BKO~@h>IC=%UJoQcf -z-q~bWOFT`vZ6Ys7N7bO9fy2_t$^U7ZdjkF0tgJ* -z!d7hxkFSjLtAM*#v;~+WC|MBg-PipBAHY@8qD%;RnlyJ*J)I@)E4(@LShFcH>PxzT30nds7$ESSD?Jy>4bIHEzkSh{H3e)d+oGum0+_G -zrx9w@pGPoVxC%X{ja@WQ`8Hik16wC+8bcb_7)^}AXoYifLq;2N=ZKUpYvr_-Olrgb -z6?n@)e@DvATQT%?pf{1R9_YfK@AP#xaQ4bj04pXp=fEQ_#b|}Caok&Nq&VjrhHj_A -zL?zO%rFe_VmO7DEWai3bjV$^_xhf~1oG8G$>#n=h)h-)sumLk>%%J}t|6=SeTh~a5 -z%D-&*>+djq|6}mpFO?f8KI5~zGT#X6Pe#JJ$AbCR;LS}Jhl1W<`WxKFf3--{qoiWlvie*FH6F1xqJ${f6=r1!2@nXGGj^Pjx}NzTt@y(8aM7eiSFs -zHH|W=Qd?6~ilTmA5+^ltWbM+WuGd*>xY@5w5EmX#f9m;lFn67-Jfkba8AVG+Jo3J8 -zmP#^t^5inyeB@nU<z^p!(`raMxE}B8ktuSmt9x<8!1@0einwJqVmPuW_EC -zaBb@DUtA(n*?;fjf%2uYNM4nU>D2ce4Z!}p!6~0o^rz4_5GY_^Ox!HVWI2|LFE5kW -zs#^icc2NSsEE8)`9Piox>5}>`c>c1=)eiw0z8OI+?~3>t-#xeN6yxee9oFJQ;$_B+ -z8H=F+DpqjlwG2gEC0SHpfO+$HcHTU?-EOG__rCor)K}7Y@3GGD&wamHe((LeLH~e& -z#8%`+lFF57%jSwdwI -z3a+3q*@fG<^V&67?qevxwhpBfn_Yi;Ah0rd6v^X$BNY`e`iLwIjV9oIR5^A44985b6gI$+U&j6;9Q3OiOrqe#`T0)e4Y -zS{OkSRjXM5w%KJyQ)P?LFKSd<*J}4FX>B@5GE5IV@W80F?NA=S@%~W1Tle1qh&=o3 -zv!kAOQ5ks%Qg?-K(jyOJUHJ8*;4l99-fvYDDDc4EV*1~(ZD=o}VSc}qfn{lxB|hlq -zuwv}uO6nBaGiHnkHWZ6=yRzJ=&J7gfURqUO0AMHe`nqDriu^(GSvN$uqY8X!po@}- -z+8&ZnW;gzX_D-7*6Fk5+H~mC1cp($0ybq;;l_IRM#u_Ex -zvACnRx3}p9;J-%Nto$K!=gd409h_|xJd-JJyM=x%~j30LB1+(L|C+K2lrN#yT{m)~@ -z2+LOoZ1tmfeVd!kz~O6uwIjD9M)a>o -zcv>|hgTEgf6jz`S05~>jBz!Ji6%}A2!1}wLAzbkeyU9Y3r~-klUO4mv@{@Ds+A0sA -zHA+V)Wy)e%6Ou(cJ^n4$GK2l8Nhe%KeHr&ax36ZYgwk{5wd9aCyo-gt7;&joN-k> -z-j+A~nC2(_MUUu>DDtx7J{zUee2QUs`~dDkKO3FU`g@Ekgyd*$Y1`N@C6fA -z3*;EW^=CPZ?UC`h@j=DP*tBTnVSuDZ%EX-14cc6|mIVvtHs&v|O{}HBI*rHC6TvQz -z92M%hL*-Dtw!0ut%EC;K8|<>}&1aBVhtdig%47UUWNocr!Q&UhsMmZ{*`wH(Frh4L -zDAI8^ozB!f4k3ynvMd{h{Od|Ed-m+0PmVmVfN);hr@)6snyqBzq4kxf0G)vabURG} -zJEVNP7D+Y6`bTFj;H1-vn!c|$&Nuez|0Xd*h9P86d?^TB4yu$I)jB*hT8h_veJJdB -z?#w^3;G%2r))B9_7Tf;n*szLa$ZRhfLl}*%g@Upzi7#^sOH;V=njPcD82A8;(^RT& -zjFxQ=%u3wYXQe5?tfw9f4H`q{Psvk1DEb<$ -zsbI(JPh;vE4`uf3*{mDN*M{-{bLPwe;F9y#8Rkt26q1By6-L8A`Vv%tNAA0scCVp- -z5yXjyNTF&iW9lJ|Hn7p;X~TqHJh#^J&j%mm!M7gHwtqXV>34%E5enIdXss5f#)tq(Ywo%CUI6aj^N>;zisDXRlz9({6eb<}pG-UU9A?j+%{uF>(=h#o -z@TWhpK6&0OpYy;#C(ynYQVU~RlqvOf8&@k&H-&K_ -zQTE2&+ao6DnigI$XYO2{n?Iik6J(2>2g0nSAap{diFbZv3^!zir+xlp9^C!lQt$c;Z0;!eiDVF$Lm?$lD?^*?|)j|Aa|mCYM%Ak|J| -z;?REHL0%&&3s$sN_aCo{3NRhu`$xSAkhZHmJpy6|`Y0oUgMTD8`RAvuU0US*W*jo& -zOq?ACte8E866kTg6{lZxXz~?cE6c8nsqdWh66$R;c>fcP-&$?;)rbA&GqYzm{?DE> -zhgr`&!#eA%!`f@F4ZxkdA5667xKjAKhD`+zSZ3Wfp1J=VODnX2fAXO{nSS3y20L|Y -z1Xo-l_w|!2E2xrY(2Ah1TeV}@W6RRoq^qI=G^So>Q2ts;W%7-IdmnF-Kku9QMV>zU -zvSFv0Gk5N&KXKn{KHCVvB2`;xXhGVKJ)11gmzul*N+kf8TEi1K&vlbdDM`jURPouf4J=x?KRYBxl0>p+mNC%D -zR_?|@D@Or>9Fn+N#_Tg`ZcrTWpLuXK5=$}rhvxeqc*|kK$-H7&(hvr3`q$4~tnima -z+>B-w)?RyU#)j&jsc-xec*k{Y&&#a7hR_f=5= -z#P!XRdbU6O?@8oV3PF^U0c-UNyERlx{3uM^QWbd=0I+@zH=M!iyZOG6lNYmR4?F*8 -z3qwbvciZiDSpzWjO#HU;&?WqBtXQ`fe*^R5}q4y2FV!R|+2AL(fL*2F20CeC=Y{ -z#?vmYLcp?M(3N?Dsev=tX6voX@8s4laSh;TwT4Tw3Tv(@MLH9#A#3p -zUnapE!&qbqp^el77!zEDlGi2=cLRQvvjENt-CLNrp0N@IeE0;p*46ghz7ka70>Z#f -z4XoSJ9`moby-MfQg|nD?ytzXF=4g5QrLhVlDMsOH*4y^!aBGg-g7Z4mA3AAzTHBk5 -zz)tV=4p~-x%|0?85wxfWcMG0(gKMe)CZPF1zr@C=Gr6qTO*MVOak{SQsj= -zHauegrm#k!0!JFyk!Iq=!}o76a8-=uNN3C$=KJfWe@Q-nq}ji;)}WOnwQx_DU1N($ -zQRt`jGXUt&Ygb5?g%Av>VZ+&%809~~!3v}E+KYHA#GuAn`%)(ug -zMNmqy#THut@T#5r1OQsuO~mN1`U*H%<4JD1mPQ8iY6dul@vFzao9n+U)+eg(a8XoVXldnc98?y#|( -z@Z)b>ek-7tNBBUgl9!+V0|p0#{pH!L-zL+0c^eNU*~kOCep -zK~pUa_ah>I6%gmRapP79(jQ6CqjeJ-=$DG9H3K)W)$4`$w-!7G>ubWdC3`K&pCQ+A -z)CEQO7%)R8cB@I%SzUsM3y!I>~P6{H8N-3dz=lO -z5(<0hJd;C<)B>y(CcF46R_AVe<&;vHr0mF*l<>oEIii`RnmKc^$bPiH;y3Hcx479q -znv%J&?$IQxNeNuu-2aCfwc|Y8cEhBS7S6-snz+_E%^28h!mx;7naH7K*)(d@FKn?s -z?6WIOTwSroIQU$c{ja{_cx=D4x6DH;)ZBZFk*=CrX>5V!l_GbJhu-(?QLkm&zf38s -zfQ**CUh;77If_T#byNcY&KP0+z>;G7p9UrEzKZbA -z`#>D!LHTsT*s+=&UMrc)&DN9s0_G1&pP(g)>iOK$G6xprmT}`+ymz1D_`koy!!zNB -zzaOq6wy#rh^ucXw(LQwH{8W?R+Vpqd#-$lge)NRuV%J@rEzbEGzNnY>9v?b{`>J|$ -zSnR(tg+5Z<|IlO0-E;1_0ZbgWwo|f~aUpo|WESsr**bT@f@(59`gD_I+iHF39grBf -zf4cnkD7%ZVJO!v@fRDdT@tJpp-NH=8UVZTUzCqbG>|wzNIT=8sR9JIYMFu*F*z~vG -zra#Rv#?WrZwXiR=77L)VtqdJsZOU7)e_HDimx?Vf0IZ*DX;?+?0n>RR++y -zqJ`Y>?;f*%)tT0*DtfRhfE`>RVPGp3vZCFV_9byVLg%%5M+|Qp@w+dmTwmu%ef638 -z`ptST9T%*JtB}>a^R8^Ng(Kwnmxgm#5)(L@peNNLkGks=h@(o>UtYSaZaKHruIBaA -z=T>k)E2%oCWce@<_~I!*+La4m)GuoQ(p;#_x9%wK&phWZ!^M-b=M&p1VpB -zTv0%zN?}_E@B5&1EBSwK3DK>SOkrLvmX^+;FMY>0SZIVlNbpB3x8jqPM#5y=8LP%f4-)F -zY1qQi4(o-qE+Sax9M(CU50QpajV`P6o|6x5w5G6tQQ*4b&~Y`1Bw+;5Uv&um@e82< -z+W?H6{NLpZuY2=;WL7k?=%1)fbIX{5^VP+VIxkHXkr^+`uYH-_D?NyH=-?VAj2#=+ -z9!j^Lau=?}@c%2q=Z{874>SK8HMi?|;>jlgxcRcE$^h1u5%`)1(>ju6VXoFPHt2Nj -zrA8pP(kuc6#>2zU$jScnkMdd$ebJIZ-UZ=@4UTLEk@8$}v|Qvp2ON(sTBO^sa3jRp -zAiHkkJubI+>rvK)Qg2C~C=VtqrPfaV#F6F&s#@;k*l6U=(tK~I@B#Yz`Y3c%mVJu_ -z$gQiFEC`L^E3ELww@LVS?1!W^Y-Gd=jA@I4bh@(fgkAv^0V^!Oq>WVn;EOb-$J_8) -z$pk8TBf~&$(Jr(C4R$a09&H`D_n~2u4l8h=$7s5_N0&mb7uppqMOkd!)M%|>m(@Mg -zKey>7n+)p+Qm~n~TppEyk1uHO8tYeB0_6*vR-GraGW%@?sjkZGicaCHLN>6*L#|2D -z=qk@c8MqRYHAyO|x${FO$R^Igzw5BxPUBJDm(3cru9jjuD@(tev!uDLmd}=T098u4 -zHG+WiJYOOUI9e#TG|8fkCrxSy|H*07D&b$z#?}yhXW^{UBFOgjRghDh@$K)H&-};k -zl1+_G)g-kQNwhVPtr!5fJPHs2?D~OUmM);=wu6EGKnVB8A-Y@T@u5(5}T6G;%GgI8qF~Nv&t!l0e(@jRH2FG>IsR -zxc`9%xbOb^x$pk_%T8jqT)jqBo8lm|nykA}SZ`a=9a+$03$$C+4Q#ui%=m6t9}tI3 -zU@MX556l=w0I3&J0W836ch4L$fQsI>?995dKj@-F0+2uPbL=+B>x3$F~&a=g(-&i}=n>S4CB$Bl%=HSbG5O?S -zU*p14e;}UBN&3=S@mKY=fDarvg>BCNs`z9dh@qm}j;|3wffu!bA&Hgr<4>(44h#vjEoH^^8U+5E)t2s8t1G -zdfH;bE~o`5^RBo(2&KB2+_@$)DyNA&R$-R=de|2}ms{Id>;F`(`}eZ6l&cH>?wi-= -zj+@r!uAA29&YLH(?u2UDxRk&7(rD#1^Ip{a*KfrKr0*;I%RcX)Q~uU>4hR&77e8-| -z;Hh#vT}1}f%>T|Wh5~#RVAhU6Vg&Myi -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 -z4w5m_p({=d`@C&JBdg72{2>JJdT~kJ8 -zX6E47-wglpc1v;gPYhbYhd-SUdw*;jj@-BA%L82-2Rb_og7mc_5M!wA1S%zQtzw;I -zP!0t=JWGwVnsWdBJMNOjU(k0CX!7($(MPe{xdCiggQD{b4~XqaPl7|Ejy+a -z6wHVf>4w}yJF0kyD3XYTkiRJV0Eec|nX5pd4mcq;@Y5@yui4e(x4;1_eIQqMhme(Y -zGW4kgj)FX-te9c -z7Dk8tdm^N}iw|}D9uaaD+>X%|D4o3kF1(>}Z#gS)r;inNtZE7{q9Po1fjs%~f5O6U -z0D!@qds{7>7#s38)`?Jh5?M_%CJ_Z1+pf@jF+nmf&8D4~?-Z-^bZ{MME|#D$?VVJF -z9!J5o1b)A$Z@%L(xcZ(K#?SvdE5L|~@TGI)$yfJ*)yLJATPq10eT|tZ1lpSfU>0Vo -z*1|Tnqsq_gP?Tb=B>Qp)Q6Qkwz)luyWNZXi6f-`^pP&2%<}7^a2>zv_03#~GNtZTb -zbRYI4^tGz;qQRnd^56O9{(FUoEXXCT#6TMaLlkxUNhnz9rh#wJVSOs1Am9DnVy~B1 -z6ksJP0>Cl9mj6HasLXI5z+ZvtU30VWvf^eiE5K64QV0WASO^L5m3?LN2zf{A(6=4K8O3kTQ;g}I -zGwNr4e8O6MbU(%M-%>A^VTpLT9mjojUDjR`X3T=)PQ9N~elVG7PeYV8+nBse4z;3N -grN45#w2uEj0IsQg7c6bg&Hw-a07*qoM6N<$f)YdpWdHyG - -literal 14310 -zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c -zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 -z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez -za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ -zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc -zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 -z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C -z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj -z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO -zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq -zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP -zJxwXvt5fFTCOVgB)Zq -z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( -z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 -zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP -zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN -zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| -z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK -z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf -zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l -z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP -zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 -z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! -zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! -zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX -z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A -z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# -zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x -zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 -zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk -z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B -zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| -zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx -z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE -zllqxy -z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t -z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W -z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); -zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} -z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX -z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx -z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% -zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v -zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< -zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A -zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h -zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- -zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< -zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS -z4&$M&7(|(9nWY%QShCnuN0 -z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm -zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ -z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 -zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; -z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; -z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC -z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> -zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg -zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> -zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k -zL^tBOHF^=)k&U-Tw{gfijqQ&^ -z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 -z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X -z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 -zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( -zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY -zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU -zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ -z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ -z1IGS^Z5t=0Zj86J2MfJc -zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 -z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 -z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf -zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) -z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd -z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= -z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 -z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 -zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA -zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH -zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ -z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< -zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ -zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf -zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- -zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= -zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G -z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp -zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x -zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 -z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN -zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl -z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh -zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; -z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ -zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK -zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! -zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ -z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X -zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* -zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 -zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH -z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw -z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G -z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv -zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L -z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H -zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% -zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz -z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| -zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP -zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 -zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty -zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n -z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 -zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo -zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF -zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V -zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% -zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W -z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 -zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy -zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 -z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 -zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd -zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m -z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I -z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe -zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA -zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` -zh~ggr^knneWU!Nn}AQt=0Id6Hk; -z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# -zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 -z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< -zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r -z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN -zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D -z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk -zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq -z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ -z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ -zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl -zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH -z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif -z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) -zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf -zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m -zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< -zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I -z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 -zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} -zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` - diff --git a/patches/reverted/server/0005-Bump-to-Java-15.patch b/patches/reverted/server/0005-Bump-to-Java-15.patch deleted file mode 100644 index ea0ab4b..0000000 --- a/patches/reverted/server/0005-Bump-to-Java-15.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Tue, 4 May 2021 13:02:02 -0400 -Subject: [PATCH] Bump to Java 15 - - -diff --git a/pom.xml b/pom.xml -index afa475f33bad218e77e5a6f373615409b3eb5d60..e5c61b389ac022e59c3abb3aac1afeb45d384913 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -14,8 +14,8 @@ - git - 1.16.5 - 1_16_R3 -- 1.8 -- 1.8 -+ 15 -+ 15 - - - diff --git a/patches/reverted/server/0006-Add-CraftItemStack-canPlaceOn.patch b/patches/reverted/server/0006-Add-CraftItemStack-canPlaceOn.patch deleted file mode 100644 index af0a7f9..0000000 --- a/patches/reverted/server/0006-Add-CraftItemStack-canPlaceOn.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Mon, 10 May 2021 02:50:34 -0400 -Subject: [PATCH] Add CraftItemStack#canPlaceOn - - -diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java -index 59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7..25326f1124773ca4956a72a9b2998513748f7b85 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBlock.java -+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java -@@ -173,6 +173,7 @@ public class ItemBlock extends Item { - }).orElse(iblockdata); - } - -+ public boolean canPlaceOn(BlockActionContext blockActionContext, IBlockData iBlockData) {return b(blockActionContext, iBlockData);} // Parchment - OBFHELPER - protected boolean b(BlockActionContext blockactioncontext, IBlockData iblockdata) { - EntityHuman entityhuman = blockactioncontext.getEntity(); - VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a((Entity) entityhuman); -diff --git a/src/main/java/net/minecraft/world/item/context/BlockActionContext.java b/src/main/java/net/minecraft/world/item/context/BlockActionContext.java -index 2cb451db6ca23290f700dc428a7622f64fb90b97..1763ada73e4ef422f95eb5c3f42f19d7600261a6 100644 ---- a/src/main/java/net/minecraft/world/item/context/BlockActionContext.java -+++ b/src/main/java/net/minecraft/world/item/context/BlockActionContext.java -@@ -24,7 +24,7 @@ public class BlockActionContext extends ItemActionContext { - this(itemactioncontext.getWorld(), itemactioncontext.getEntity(), itemactioncontext.getHand(), itemactioncontext.getItemStack(), itemactioncontext.i()); - } - -- protected BlockActionContext(World world, @Nullable EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack, MovingObjectPositionBlock movingobjectpositionblock) { -+ public BlockActionContext(World world, @Nullable EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack, MovingObjectPositionBlock movingobjectpositionblock) { // Parchment - super(world, entityhuman, enumhand, itemstack, movingobjectpositionblock); - this.a = true; - this.b = movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 09d7a86b5f6cffdf6664ad657dd4f8dd8eabdd70..e709c910e3e9a09c26b44225a0d6c809502e4b67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -3,21 +3,41 @@ package org.bukkit.craftbukkit.inventory; - import static org.bukkit.craftbukkit.inventory.CraftMetaItem.*; - import com.google.common.collect.ImmutableMap; - import java.util.Map; -+import me.lexikiq.HasHumanEntity; -+import me.lexikiq.OptionalHumanEntity; -+import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.world.EnumHand; -+import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.Item; -+import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentManager; -+import net.minecraft.world.item.ItemBlock; -+import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.Vec3D; - import org.apache.commons.lang.Validate; -+import org.bukkit.Location; - import org.bukkit.Material; -+import org.bukkit.World; -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockFace; - import org.bukkit.configuration.serialization.DelegateDeserialization; -+import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.bukkit.craftbukkit.block.CraftBlock; -+import org.bukkit.craftbukkit.entity.CraftEntity; - import org.bukkit.craftbukkit.util.CraftLegacy; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.enchantments.Enchantment; -+import org.bukkit.entity.HumanEntity; - import org.bukkit.inventory.ItemStack; - import org.bukkit.inventory.meta.ItemMeta; - import org.bukkit.material.MaterialData; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - - @DelegateDeserialization(ItemStack.class) - public final class CraftItemStack extends ItemStack { -@@ -105,6 +125,57 @@ public final class CraftItemStack extends ItemStack { - setItemMeta(itemMeta); - } - -+ // Parchment start -+ /** -+ * Determines if this item can be placed on a block. Must be run synchronously. Factors in player location, -+ * nearby entities, and more. -+ * @param world world in which the block is being placed -+ * @param _player optional player placing the block -+ * @param block block to check against -+ * @param face cardinal direction -+ * @return if the item can be placed -+ */ -+ public boolean canPlaceOn(World world, @Nullable OptionalHumanEntity _player, Block block, BlockFace face) { -+ Validate.notNull(world, "'world' must not be null"); -+ Validate.notNull(block, "'block' must not be null"); -+ Validate.notNull(face, "'face' must not be null"); -+ -+ if (block.getType().isEmpty() || block.isLiquid()) return false; -+ HumanEntity player = _player != null ? _player.getPlayer() : null; -+ if (!(world instanceof CraftWorld)) return false; -+ if (!face.isCartesian()) throw new IllegalArgumentException("Face must be cartesian"); -+ if (!(block instanceof CraftBlock)) return false; -+ if (player != null && !(player instanceof CraftEntity)) return false; -+ EntityHuman human = player != null ? (EntityHuman) ((CraftEntity) player).getHandle() : null; -+ CraftBlock craftBlock = (CraftBlock) block; -+ CraftBlock relativeBlock = (CraftBlock) block.getRelative(face); -+ if (!relativeBlock.isReplaceable()) -+ return false; -+ Location playerLoc = player != null ? player.getLocation() : relativeBlock.getLocation(); -+ EnumDirection direction = EnumDirection.valueOf(face.name()); -+ -+ Item item = handle != null ? handle.getItem() : Items.AIR; -+ if (!(item instanceof ItemBlock)) return false; -+ ItemBlock itemBlock = (ItemBlock) item; -+ -+ BlockActionContext context = new BlockActionContext(((CraftWorld) world).getHandle(), human, EnumHand.MAIN_HAND, asNMSCopy(this), new MovingObjectPositionBlock(new Vec3D(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ()), direction, craftBlock.getPosition(), false)); -+ return itemBlock.canPlaceOn(context, itemBlock.getBlock().getPlacedState(context)); -+ } -+ -+ /** -+ * Determines if this item can be placed on a block. Must be run synchronously. Factors in player location, -+ * nearby entities, and more. -+ * @param player player placing the block -+ * @param block block to check against -+ * @param face cardinal direction -+ * @return if the item can be placed -+ */ -+ public boolean canPlaceOn(@NotNull HasHumanEntity player, Block block, BlockFace face) { -+ Validate.notNull(player, "'player' must not be null"); -+ return canPlaceOn(player.getPlayer().getWorld(), player, block, face); -+ } -+ // Parchment end -+ - @Override - public MaterialData getData() { - return handle != null ? CraftMagicNumbers.getMaterialData(handle.getItem()) : super.getData(); diff --git a/patches/reverted/server/0007-Add-origin-location-to-EntityDamageByBlockEvent.patch b/patches/reverted/server/0007-Add-origin-location-to-EntityDamageByBlockEvent.patch deleted file mode 100644 index ce074d5..0000000 --- a/patches/reverted/server/0007-Add-origin-location-to-EntityDamageByBlockEvent.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Mon, 10 May 2021 22:10:23 -0400 -Subject: [PATCH] Add origin location to EntityDamageByBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index e6bf78f46acc37d9515d58cec3587e236ac0733c..1cea7c5bf99e0c99e8160658df0eab065cca2841 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -46,6 +46,16 @@ public class DamageSource { - private boolean D; - private boolean E; - public final String translationIndex; -+ // Parchment start -+ private @Nullable org.bukkit.Location location; -+ public @Nullable org.bukkit.Location getLocation() { -+ return location; -+ } -+ public DamageSource location(@Nullable org.bukkit.Location location) { -+ this.location = location; -+ return this; -+ } -+ // Parchment end - // CraftBukkit start - private boolean sweep; - -@@ -109,11 +119,11 @@ public class DamageSource { - } - - public static DamageSource explosion(@Nullable Explosion explosion) { -- return d(explosion != null ? explosion.getSource() : null); -+ return d(explosion != null ? explosion.getSource() : null).location(explosion != null ? explosion.getBukkitLocation() : null); // Parchment - } - - public static DamageSource d(@Nullable EntityLiving entityliving) { -- return entityliving != null ? (new EntityDamageSource("explosion.player", entityliving)).r().setExplosion() : (new DamageSource("explosion")).r().setExplosion(); -+ return (entityliving != null ? (new EntityDamageSource("explosion.player", entityliving)) : (new DamageSource("explosion"))).r().setExplosion(); // Parchment - } - - public static DamageSource a() { -@@ -234,8 +244,9 @@ public class DamageSource { - return entity instanceof EntityHuman && ((EntityHuman) entity).abilities.canInstantlyBuild; - } - -+ public Vec3D getPosition() {return w();} // Parchment - OBFHELPER - @Nullable - public Vec3D w() { -- return null; -+ return location == null ? null : new Vec3D(location.getX(), location.getY(), location.getZ()); // Parchment - } - } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 79008bda42558ea7d28ccf51b66405a3bdb52da7..8fd81f4238416fd6a5d09e3307aebe785f8e28e1 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -85,6 +85,13 @@ public class Explosion { - this.l = explosiondamagecalculator == null ? this.a(entity) : explosiondamagecalculator; - } - -+ // Parchment start -+ public @Nullable org.bukkit.Location getBukkitLocation() { -+ if (this.world == null) return null; -+ return new org.bukkit.Location(world.getWorld(), posX, posY, posZ); -+ } -+ // Parchment end -+ - private ExplosionDamageCalculator a(@Nullable Entity entity) { - return (ExplosionDamageCalculator) (entity == null ? Explosion.a : new ExplosionDamageCalculatorEntity(entity)); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java -index 00a01a157deec004bcf2f8587723a0ecd0bfef85..ece4648bf133621b644291390f5743f9c48c750d 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java -@@ -89,7 +89,12 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - world.a(blockposition1, false); - } - -- world.createExplosion((Entity) null, DamageSource.a(), (ExplosionDamageCalculator) null, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment start -+ double posX = blockposition.getX() + 0.5D; -+ double posY = blockposition.getY() + 0.5D; -+ double posZ = blockposition.getZ() + 0.5D; -+ world.createExplosion((Entity) null, DamageSource.a().location(new org.bukkit.Location(world.getWorld(), posX, posY, posZ)), (ExplosionDamageCalculator) null, posX, posY, posZ, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment end - return EnumInteractionResult.SUCCESS; - } else if ((Boolean) iblockdata.get(BlockBed.OCCUPIED)) { - if (!this.a(world, blockposition)) { -@@ -138,7 +143,12 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - world.a(blockposition1, false); - } - -- world.createExplosion((Entity) null, DamageSource.a(), (ExplosionDamageCalculator) null, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment start -+ double posX = blockposition.getX() + 0.5D; -+ double posY = blockposition.getY() + 0.5D; -+ double posZ = blockposition.getZ() + 0.5D; -+ world.createExplosion((Entity) null, DamageSource.a().location(new org.bukkit.Location(world.getWorld(), posX, posY, posZ)), (ExplosionDamageCalculator) null, posX, posY, posZ, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment end - return EnumInteractionResult.SUCCESS; - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a678277416cd71e01cd6980bcfaf9a9803e7ea17..0df40bc18dcd66a367b82e435316851eb99d077c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -941,7 +941,7 @@ public class CraftEventFactory { - entityDamage = null; - EntityDamageEvent event; - if (damager == null) { -- event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions); -+ event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, source.getLocation(), modifiers, modifierFunctions); // Parchment - } else if (entity instanceof EntityEnderDragon && /*PAIL FIXME ((EntityEnderDragon) entity).target == damager*/ false) { - event = new EntityDamageEvent(entity.getBukkitEntity(), DamageCause.ENTITY_EXPLOSION, modifiers, modifierFunctions); - } else { -@@ -977,7 +977,7 @@ public class CraftEventFactory { - - return callEntityDamageEvent(damager, entity, cause, modifiers, modifierFunctions, cancelled); - } else if (source == DamageSource.OUT_OF_WORLD) { -- EntityDamageEvent event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.VOID, modifiers, modifierFunctions); -+ EntityDamageEvent event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.VOID, entity.getBukkitEntity().getLocation(), modifiers, modifierFunctions); // Parchment - event.setCancelled(cancelled); - callEvent(event); - if (!event.isCancelled()) { diff --git a/patches/reverted/server/0008-Create-PlayerUseRespawnAnchorEvent.patch b/patches/reverted/server/0008-Create-PlayerUseRespawnAnchorEvent.patch deleted file mode 100644 index d82bf0a..0000000 --- a/patches/reverted/server/0008-Create-PlayerUseRespawnAnchorEvent.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Thu, 13 May 2021 23:52:14 -0400 -Subject: [PATCH] Create PlayerUseRespawnAnchorEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -index 028e98decf8b0496b4ebcd1aad3aa474e5c4e7c1..1a3c66464947e16cc085a20ee1172cc51a3fc2f5 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList.Builder; - import com.google.common.collect.UnmodifiableIterator; - import java.util.Optional; - import java.util.stream.Stream; -+import me.lexikiq.event.player.PlayerUseRespawnAnchorEvent; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -@@ -37,6 +38,8 @@ import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.pathfinder.PathMode; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; -+import org.bukkit.craftbukkit.block.CraftBlock; // Parchment -+import org.bukkit.entity.Player; // Parchment - - public class BlockRespawnAnchor extends Block { - -@@ -53,6 +56,11 @@ public class BlockRespawnAnchor extends Block { - public EnumInteractionResult interact(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { - ItemStack itemstack = entityhuman.b(enumhand); - -+ // Parchment start -- PlayerUseRespawnAnchorEvent -+ Player player = entityhuman.getBukkitEntity() instanceof Player ? (Player) entityhuman.getBukkitEntity() : null; -+ org.bukkit.block.Block block = CraftBlock.at(world, blockposition); -+ // Parchment end -+ - if (enumhand == EnumHand.MAIN_HAND && !a(itemstack) && a(entityhuman.b(EnumHand.OFF_HAND))) { - return EnumInteractionResult.PASS; - } else if (a(itemstack) && h(iblockdata)) { -@@ -61,16 +69,31 @@ public class BlockRespawnAnchor extends Block { - itemstack.subtract(1); - } - -+ // Parchment start -+ if (player != null && !(new PlayerUseRespawnAnchorEvent(player, block, PlayerUseRespawnAnchorEvent.RespawnAnchorResult.CHARGE).callEvent())) -+ return EnumInteractionResult.PASS; -+ // Parchment end -+ - return EnumInteractionResult.a(world.isClientSide); - } else if ((Integer) iblockdata.get(BlockRespawnAnchor.a) == 0) { - return EnumInteractionResult.PASS; - } else if (!a(world)) { -+ // Parchment start -+ if (player != null && !(new PlayerUseRespawnAnchorEvent(player, block, PlayerUseRespawnAnchorEvent.RespawnAnchorResult.EXPLODE).callEvent())) -+ return EnumInteractionResult.PASS; -+ // Parchment end -+ - if (!world.isClientSide) { - this.d(iblockdata, world, blockposition); - } - - return EnumInteractionResult.a(world.isClientSide); - } else { -+ // Parchment start -+ if (player != null && !(new PlayerUseRespawnAnchorEvent(player, block, PlayerUseRespawnAnchorEvent.RespawnAnchorResult.SET_SPAWN).callEvent())) -+ return EnumInteractionResult.PASS; -+ // Parchment end -+ - if (!world.isClientSide) { - EntityPlayer entityplayer = (EntityPlayer) entityhuman; - -@@ -115,7 +138,7 @@ public class BlockRespawnAnchor extends Block { - - private void d(IBlockData iblockdata, World world, final BlockPosition blockposition) { - world.a(blockposition, false); -- Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.a(); -+ Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.a(); // Parchment - Fix deobfuscation error - - blockposition.getClass(); - boolean flag = stream.map(blockposition::shift).anyMatch((blockposition1) -> { diff --git a/patches/reverted/server/0009-Add-respawn-anchor-damage-location.patch b/patches/reverted/server/0009-Add-respawn-anchor-damage-location.patch deleted file mode 100644 index 559495c..0000000 --- a/patches/reverted/server/0009-Add-respawn-anchor-damage-location.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Fri, 14 May 2021 23:41:14 -0400 -Subject: [PATCH] Add respawn anchor damage location - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -index 1a3c66464947e16cc085a20ee1172cc51a3fc2f5..2f921f08de6a349f4582e8471f0f1ff3670f92ed 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRespawnAnchor.java -@@ -38,6 +38,7 @@ import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.pathfinder.PathMode; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; -+import org.bukkit.Location; - import org.bukkit.craftbukkit.block.CraftBlock; // Parchment - import org.bukkit.entity.Player; // Parchment - -@@ -152,7 +153,12 @@ public class BlockRespawnAnchor extends Block { - } - }; - -- world.createExplosion((Entity) null, DamageSource.a(), explosiondamagecalculator, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment start -+ double posX = blockposition.getX() + 0.5D; -+ double posY = blockposition.getY() + 0.5D; -+ double posZ = blockposition.getZ() + 0.5D; -+ world.createExplosion((Entity) null, DamageSource.a().location(new Location(world.getWorld(), posX, posY, posZ)), explosiondamagecalculator, posX, posY, posZ, 5.0F, true, Explosion.Effect.DESTROY); -+ // Parchment end - } - - public static boolean a(World world) { diff --git a/patches/reverted/server/0010-Add-SoundEvent.patch b/patches/reverted/server/0010-Add-SoundEvent.patch deleted file mode 100644 index 5be5afb..0000000 --- a/patches/reverted/server/0010-Add-SoundEvent.patch +++ /dev/null @@ -1,429 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lexikiq -Date: Wed, 9 Jun 2021 18:39:18 -0400 -Subject: [PATCH] Add SoundEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandPlaySound.java b/src/main/java/net/minecraft/server/commands/CommandPlaySound.java -index f896dd7447d8a8fbc6e3c1abad0c3da5448273c1..2ee039d18ddd98298586f1ace2e6b980cb3061e0 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandPlaySound.java -+++ b/src/main/java/net/minecraft/server/commands/CommandPlaySound.java -@@ -15,7 +15,6 @@ import net.minecraft.commands.arguments.ArgumentMinecraftKeyRegistered; - import net.minecraft.commands.arguments.coordinates.ArgumentVec3; - import net.minecraft.commands.synchronization.CompletionProviders; - import net.minecraft.network.chat.ChatMessage; --import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; -@@ -81,7 +80,7 @@ public class CommandPlaySound { - f3 = f2; - } - -- entityplayer.playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(minecraftkey, soundcategory, vec3d1, f3, f1)); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationCustomSoundEvent(entityplayer.getBukkitEntity(), entityplayer.getWorldServer().getWorld(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(vec3d1), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(minecraftkey), org.bukkit.SoundCategory.valueOf(soundcategory.name()), f3, f1), entityplayer); // Parchment - sound event - ++i; - } - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 75bcfb3a2b4a104aeebb2fe3298714b2e5b569d2..703ae4aab9b47415a31245c2be641b6fa41502b7 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -53,7 +53,6 @@ import net.minecraft.network.protocol.game.PacketPlayOutExperience; - import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; - import net.minecraft.network.protocol.game.PacketPlayOutLookAt; - import net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutOpenBook; - import net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor; - import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow; -@@ -2158,7 +2157,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void a(SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1) { -- this.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundeffect, soundcategory, this.locX(), this.locY(), this.locZ(), f, f1)); -+ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(this.getBukkitEntity(), this.getWorld().getWorld(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(this.getPositionVector()), org.bukkit.craftbukkit.CraftSound.getBukkit(soundeffect), org.bukkit.SoundCategory.valueOf(soundcategory.name()), f, f1), this); // Parchment - sound event - } - - @Override -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index f68a252378a94c8fcab622d2d89d738aceab45a4..7a290adb13ed083db50f197fc2acf0007f6dd2d2 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -58,11 +58,9 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.network.protocol.game.PacketPlayOutBlockAction; - import net.minecraft.network.protocol.game.PacketPlayOutBlockBreakAnimation; --import net.minecraft.network.protocol.game.PacketPlayOutEntitySound; - import net.minecraft.network.protocol.game.PacketPlayOutEntityStatus; - import net.minecraft.network.protocol.game.PacketPlayOutExplosion; - import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnPosition; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; -@@ -168,6 +166,10 @@ import org.bukkit.event.server.MapInitializeEvent; - import org.bukkit.event.weather.LightningStrikeEvent; - import org.bukkit.event.world.TimeSkipEvent; - // CraftBukkit end -+// Parchment start -+import org.bukkit.craftbukkit.CraftSound; -+import org.bukkit.util.Vector; -+// Parchment end - - public class WorldServer extends World implements GeneratorAccessSeed { - -@@ -1663,12 +1665,20 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - @Override - public void playSound(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1) { -- this.server.getPlayerList().sendPacketNearby(entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this.getDimensionKey(), new PacketPlayOutNamedSoundEffect(soundeffect, soundcategory, d0, d1, d2, f, f1)); -+ // Parchment start -+ CraftEventFactory.playSoundEvent( -+ new me.lexikiq.event.sound.LocationNamedSoundEvent(entityhuman == null ? null : entityhuman.getBukkitEntity(), getWorld(), new org.bukkit.util.Vector(d0, d1, d2), org.bukkit.craftbukkit.CraftSound.getBukkit(soundeffect), org.bukkit.SoundCategory.valueOf(soundcategory.name()), f, f1), -+ this.server, entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this); -+ // Parchment end - } - - @Override - public void playSound(@Nullable EntityHuman entityhuman, Entity entity, SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1) { -- this.server.getPlayerList().sendPacketNearby(entityhuman, entity.locX(), entity.locY(), entity.locZ(), f > 1.0F ? (double) (16.0F * f) : 16.0D, this.getDimensionKey(), new PacketPlayOutEntitySound(soundeffect, soundcategory, entity, f, f1)); -+ // Parchment start -+ CraftEventFactory.playSoundEvent( -+ new me.lexikiq.event.sound.EntitySoundEvent(entityhuman == null ? null : entityhuman.getBukkitEntity(), entity.getBukkitEntity(), org.bukkit.craftbukkit.CraftSound.getBukkit(soundeffect), org.bukkit.SoundCategory.valueOf(soundcategory.name()), f, f1), -+ this.server, entityhuman, entity.locX(), entity.locY(), entity.locZ(), f > 1.0F ? (double) (16.0F * f) : 16.0D, this); -+ // Parchment end - } - - @Override -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 90776231b1faffb11e4394f555f336ca248e3004..319226264b341fa04ab264087e243c8b87d8c012 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -43,7 +43,6 @@ import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; - import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot; - import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.network.protocol.game.PacketPlayOutLogin; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; - import net.minecraft.network.protocol.game.PacketPlayOutRecipeUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutRespawn; -@@ -67,8 +66,6 @@ import net.minecraft.server.level.PlayerInteractManager; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; --import net.minecraft.sounds.SoundCategory; --import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.ServerStatisticManager; - import net.minecraft.stats.StatisticList; - import net.minecraft.tags.Tag; -@@ -981,7 +978,7 @@ public abstract class PlayerList { - if (flag2 && !isLocAltered) { - IBlockData data = worldserver1.getType(blockposition); - worldserver1.setTypeAndData(blockposition, data.set(BlockRespawnAnchor.a, data.get(BlockRespawnAnchor.a) - 1), 3); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(entityplayer1.getBukkitEntity(), entityplayer1.getWorld().getWorld(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(entityplayer1.getPositionVector()), org.bukkit.Sound.BLOCK_RESPAWN_ANCHOR_DEPLETE, org.bukkit.SoundCategory.BLOCKS, 1.0F, 1.0F), entityplayer1); // Parchment - sound event - // Paper end - } - // Added from changeDimension -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 85f571a791bce63989890f277857bc7bdeec0cb5..fb7feb22c964cc6f2cfafa84ef3068d35d56cb04 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -12,9 +12,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; --import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumDifficulty; --import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.World; -@@ -23,9 +21,13 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.AxisAlignedBB; - - // CraftBukkit start --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end -+// Parchment start -+import org.bukkit.Sound; -+import org.bukkit.util.Vector; -+import me.lexikiq.event.sound.LocationNamedSoundEvent; -+// Parchment end - - public class EntityLightning extends Entity { - -@@ -88,8 +90,7 @@ public class EntityLightning extends Entity { - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; - // Paper start - Limit lightning strike effect distance - if (distanceSquared <= this.world.paperConfig.sqrMaxLightningImpactSoundDistance) { -- player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, -- SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); -+ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(player.getBukkitEntity(), world.getWorld(), new org.bukkit.util.Vector(this.locX(), this.locY(), this.locZ()), org.bukkit.Sound.ENTITY_LIGHTNING_BOLT_IMPACT, org.bukkit.SoundCategory.WEATHER, 2f, 0.5F + this.random.nextFloat() * 0.2F), player); // Parchment - sound event - } - - if (world.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= world.paperConfig.sqrMaxThunderDistance) { -@@ -97,14 +98,14 @@ public class EntityLightning extends Entity { - } - - // Paper end -+ double relativeX = this.locX(); // Parchment - sound event -+ double relativeZ = this.locZ(); // Parchment - sound event - if (distanceSquared > viewDistance * viewDistance) { - double deltaLength = Math.sqrt(distanceSquared); -- double relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; -- double relativeZ = player.locZ() + (deltaZ / deltaLength) * viewDistance; -- player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, relativeX, this.locY(), relativeZ, 10000.0F, pitch)); -- } else { -- player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 10000.0F, pitch)); -+ relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; // Parchment - sound event -+ relativeZ = player.locZ() + (deltaZ / deltaLength) * viewDistance; // Parchment - sound event - } -+ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(player.getBukkitEntity(), world.getWorld(), new org.bukkit.util.Vector(relativeX, this.locY(), relativeZ), org.bukkit.Sound.ENTITY_LIGHTNING_BOLT_THUNDER, org.bukkit.SoundCategory.WEATHER, 10000.0F, pitch), player); // Parchment - sound event - } - // CraftBukkit end - // this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index c39c50e53549e9cb9d3520bc7e8b7e89cfa20163..9c344b510bca742f31911fddeeb7c947c335e2e8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -28,7 +28,6 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -@@ -1755,7 +1754,7 @@ public abstract class EntityHuman extends EntityLiving { - private static void sendSoundEffect(EntityHuman fromEntity, double x, double y, double z, SoundEffect soundEffect, SoundCategory soundCategory, float volume, float pitch) { - fromEntity.world.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself - if (fromEntity instanceof EntityPlayer) { -- ((EntityPlayer) fromEntity).playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundEffect, soundCategory, x, y, z, volume, pitch)); -+ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(((EntityPlayer) fromEntity).getBukkitEntity(), fromEntity.getWorld().getWorld(), new org.bukkit.util.Vector(x, y, z), org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect), org.bukkit.SoundCategory.valueOf(soundCategory.name()), volume, pitch), ((EntityPlayer) fromEntity)); // Parchment - sound event - } - } - // Paper end -diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java -index 457cbdab3fa96fdf7fad1b0206bec9c0aa7847d8..44d7231bb9901b84a1363e8bbbdf993d74f1744a 100644 ---- a/src/main/java/net/minecraft/world/entity/raid/Raid.java -+++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java -@@ -26,12 +26,9 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.server.level.BossBattleServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; --import net.minecraft.sounds.SoundCategory; --import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; - import net.minecraft.util.MathHelper; - import net.minecraft.world.BossBattle; -@@ -495,7 +492,7 @@ public class Raid { - double d1 = vec3d.z + (double) (13.0F / f1) * (vec3d1.z - vec3d.z); - - if (f1 <= 64.0F || collection.contains(entityplayer)) { -- entityplayer.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.EVENT_RAID_HORN, SoundCategory.NEUTRAL, d0, entityplayer.locY(), d1, 64.0F, 1.0F)); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(entityplayer.getBukkitEntity(), world.getWorld(), new org.bukkit.util.Vector(d0, entityplayer.locY(), d1), org.bukkit.Sound.EVENT_RAID_HORN, org.bukkit.SoundCategory.NEUTRAL, 64.0F, 1.0F), entityplayer); // Parchment - sound event - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index c0b49a0eaeda06b89a4fb425eec3d5bfa9717379..21891dad5b799ef4dbebbd47487ddf7b366ed937 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -26,10 +26,8 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IRegistry; - import net.minecraft.data.worldgen.BiomeDecoratorGroups; --import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; --import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; -@@ -2326,8 +2324,11 @@ public class CraftWorld implements World { - double y = loc.getY(); - double z = loc.getZ(); - -- PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(new MinecraftKey(sound), SoundCategory.valueOf(category.name()), new Vec3D(x, y, z), volume, pitch); -- world.getMinecraftServer().getPlayerList().sendPacketNearby(null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, this.world.getDimensionKey(), packet); -+ // Parchment start -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent( -+ new me.lexikiq.event.sound.LocationCustomSoundEvent(null, this, new Vector(x, y, z), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromString(sound), category, volume, pitch), -+ world.getMinecraftServer(), null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, world); -+ // Parchment end - } - - private static Map> gamerules; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index cfe6898dc373fe55a08acf5c90e200061aa7d0fc..e43fe61c298acdb346beac81003b8591d11eddc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -41,10 +41,8 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockBreakAnimation; - import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutChat; - import net.minecraft.network.protocol.game.PacketPlayOutCustomPayload; --import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutExperience; - import net.minecraft.network.protocol.game.PacketPlayOutMap; --import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnPosition; -@@ -582,7 +580,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - float f = (float) Math.pow(2.0D, (note - 12.0D) / 12.0D); -- getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note_block." + instrumentName), net.minecraft.sounds.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(this, getWorld(), new org.bukkit.util.Vector(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Sound.valueOf("BLOCK_NOTE_BLOCK_" + instrumentName.toUpperCase()), org.bukkit.SoundCategory.RECORDS, 3f, f), this); // Parchment - sound event - } - - @Override -@@ -644,7 +642,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - break; - } - float f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D); -- getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note_block." + instrumentName), net.minecraft.sounds.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(this, getWorld(), new org.bukkit.util.Vector(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Sound.valueOf("BLOCK_NOTE_BLOCK_" + instrumentName.toUpperCase()), org.bukkit.SoundCategory.RECORDS, 3f, f), this); // Parchment - sound event - } - - @Override -@@ -660,17 +658,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - @Override - public void playSound(Location loc, Sound sound, org.bukkit.SoundCategory category, float volume, float pitch) { - if (loc == null || sound == null || category == null || getHandle().playerConnection == null) return; -- -- PacketPlayOutNamedSoundEffect packet = new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect(sound), net.minecraft.sounds.SoundCategory.valueOf(category.name()), loc.getX(), loc.getY(), loc.getZ(), volume, pitch); -- getHandle().playerConnection.sendPacket(packet); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(this, getWorld(), loc.toVector(), sound, category, volume, pitch), this); // Parchment - sound event - } - - @Override - public void playSound(Location loc, String sound, org.bukkit.SoundCategory category, float volume, float pitch) { - if (loc == null || sound == null || category == null || getHandle().playerConnection == null) return; -- -- PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(new MinecraftKey(sound), net.minecraft.sounds.SoundCategory.valueOf(category.name()), new Vec3D(loc.getX(), loc.getY(), loc.getZ()), volume, pitch); -- getHandle().playerConnection.sendPacket(packet); -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationCustomSoundEvent(this, getWorld(), loc.toVector(), CraftNamespacedKey.fromString(sound), category, volume, pitch), this); // Parchment - sound event - } - - @Override -@@ -2216,11 +2210,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { - final MinecraftKey name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); - final java.util.Optional event = net.minecraft.core.IRegistry.SOUND_EVENT.getOptional(name); -+ // Parchment start -+ me.lexikiq.event.sound.SoundEvent soundEvent; -+ org.bukkit.util.Vector pos = new org.bukkit.util.Vector(x, y, z); -+ org.bukkit.SoundCategory category = org.bukkit.SoundCategory.valueOf(io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()).name()); - if (event.isPresent()) { -- this.getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); -+ soundEvent = new me.lexikiq.event.sound.LocationNamedSoundEvent(this, getWorld(), pos, CraftSound.getBukkit(event.get()), category, sound.volume(), sound.pitch()); - } else { -- this.getHandle().playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3D(x, y, z), sound.volume(), sound.pitch())); -+ soundEvent = new me.lexikiq.event.sound.LocationCustomSoundEvent(this, getWorld(), pos, CraftNamespacedKey.fromMinecraft(name), category, sound.volume(), sound.pitch()); - } -+ org.bukkit.craftbukkit.event.CraftEventFactory.playSoundEvent(soundEvent, this); -+ // Parchment end - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0df40bc18dcd66a367b82e435316851eb99d077c..375a51ce14fe0bd4ed0dac6f65167e9124307af1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -231,6 +231,18 @@ import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.potion.PotionEffect; - - import org.bukkit.event.entity.SpawnerSpawnEvent; // Spigot -+// Parchment start -+import org.bukkit.util.Vector; -+import org.bukkit.craftbukkit.util.CraftVector; -+import org.bukkit.craftbukkit.CraftSound; -+import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; -+import net.minecraft.network.protocol.game.PacketPlayOutEntitySound; -+import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; -+import me.lexikiq.event.sound.EntitySoundEvent; -+import me.lexikiq.event.sound.LocationCustomSoundEvent; -+import me.lexikiq.event.sound.LocationNamedSoundEvent; -+import me.lexikiq.event.sound.SoundEvent; -+// Parchment end - - public class CraftEventFactory { - public static final DamageSource MELTING = CraftDamageSource.copyOf(DamageSource.BURN); -@@ -1841,4 +1853,69 @@ public class CraftEventFactory { - return event.callEvent(); - } - // Paper end -+ -+ // Parchment start -+ private static net.minecraft.network.protocol.Packet handleSoundEvent(SoundEvent _event) { -+ if (!_event.callEvent()) -+ return null; -+ else { -+ float volume = _event.getVolume(); -+ float pitch = _event.getPitch(); -+ if (_event instanceof LocationNamedSoundEvent) { -+ LocationNamedSoundEvent event = (LocationNamedSoundEvent) _event; -+ Vector pos = event.getVector(); -+ return new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect(event.getSound()), SoundCategory.valueOf(event.getCategory().name()), pos.getX(), pos.getY(), pos.getZ(), volume, pitch); -+ } else if (_event instanceof LocationCustomSoundEvent) { -+ LocationCustomSoundEvent event = (LocationCustomSoundEvent) _event; -+ Vector pos = event.getVector(); -+ return new PacketPlayOutCustomSoundEffect(CraftNamespacedKey.toMinecraft(event.getKey()), SoundCategory.valueOf(event.getCategory().name()), CraftVector.toNMS(pos), volume, pitch); -+ } else { // EntitySoundEvent -+ EntitySoundEvent event = (EntitySoundEvent) _event; -+ return new PacketPlayOutEntitySound(CraftSound.getSoundEffect(event.getSound()), SoundCategory.valueOf(event.getCategory().name()), ((CraftEntity) event.getOrigin()).getHandle(), volume, pitch); -+ } -+ } -+ } -+ -+ public static void playSoundEvent(SoundEvent event, java.util.function.Consumer> soundPlayer) { -+ org.apache.commons.lang.Validate.notNull(event, "Sound event cannot be null"); -+ org.apache.commons.lang.Validate.notNull(soundPlayer, "Sound packet consumer cannot be null"); -+ -+ if (!(event instanceof LocationNamedSoundEvent || event instanceof LocationCustomSoundEvent || event instanceof EntitySoundEvent)) -+ throw new IllegalArgumentException("Unknown sound event: " + event.getClass().getName()); -+ -+ java.util.concurrent.ThreadPoolExecutor executor = net.minecraft.server.MCUtil.asyncExecutor; -+ java.util.concurrent.CompletableFuture.supplyAsync(() -> handleSoundEvent(event), executor).thenAcceptAsync(packet -> { -+ if (packet != null) -+ soundPlayer.accept(packet); -+ }, executor); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, CraftPlayer sendTo) { -+ playSoundEvent(event, sendTo.getHandle()); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.level.EntityPlayer sendTo) { -+ playSoundEvent(event, sendTo.playerConnection); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.network.PlayerConnection sendTo) { -+ playSoundEvent(event, sendTo::sendPacket); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.MinecraftServer server, @Nullable EntityHuman human, double x, double y, double z, double radius, World world) { -+ playSoundEvent(event, server, human, x, y, z, radius, world.getDimensionKey()); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.MinecraftServer server, @Nullable EntityHuman human, double x, double y, double z, double radius, net.minecraft.resources.ResourceKey world) { -+ playSoundEvent(event, server.getPlayerList(), human, x, y, z, radius, world); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.players.PlayerList playerList, @Nullable EntityHuman human, double x, double y, double z, double radius, World world) { -+ playSoundEvent(event, playerList, human, x, y, z, radius, world.getDimensionKey()); -+ } -+ -+ public static void playSoundEvent(SoundEvent event, net.minecraft.server.players.PlayerList playerList, @Nullable EntityHuman human, double x, double y, double z, double radius, net.minecraft.resources.ResourceKey world) { -+ playSoundEvent(event, packet -> playerList.sendPacketNearby(human, x, y, z, radius, world, packet)); -+ } -+ // Parchment end - } diff --git a/patches/server/0001-Build-changes.patch b/patches/server/0001-Build-changes.patch index c569fea..f2f00b1 100644 --- a/patches/server/0001-Build-changes.patch +++ b/patches/server/0001-Build-changes.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 12 Jun 2021 16:40:34 +0200 +From: lexikiq +Date: Fri, 18 Jun 2021 02:01:12 -0400 Subject: [PATCH] Build changes diff --git a/build.gradle.kts b/build.gradle.kts -index f111042223f0d7974785c37245bb60b75388163e..043e5f4a0914fab856f98d39262a7c28c327460f 100644 +index f111042223f0d7974785c37245bb60b75388163e..a7beb454b194f3e93cc1c5dc6d8ea783eafdf11b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,8 +19,8 @@ repositories { @@ -28,8 +28,21 @@ index f111042223f0d7974785c37245bb60b75388163e..043e5f4a0914fab856f98d39262a7c28 standardInput = System.`in` workingDir = rootProject.layout.projectDirectory.dir( providers.gradleProperty("runWorkDir").forUseAtConfigurationTime().orElse("run") +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 218f5bafeed8551b55b91c7fccaf6935c8b631ca..52126870f1fc15a9ddce4452673b236ea692860f 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -73,7 +73,7 @@ public class Metrics { + Metrics.logger = logger; + + // Start submitting the data +- startSubmitting(); ++ // startSubmitting(); + } + + /** diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c6747f49ae8ddc9fc1bad82ab480f85d0883da5d..804eb17da12b816438a4d4c39fc330c4869cea1d 100644 +index c6747f49ae8ddc9fc1bad82ab480f85d0883da5d..648f062c5d0e5a73d12e1174ea35dfb5b2eb0228 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1649,7 +1649,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopZzga +ztPXMm+B@2rT3DL^ojvSLfF|x1rT~EZVp-Zp$8EVUCa+bIdXU!sD8p3<6s +zUM5neks5AV?tJpJWaj|RnUdQB!@2v_*TdGA^EkiYB%_v#_qzM}%TI}3Ck|)Q&3-RL +ztNr%7r<=E{56?AcbEgJ=zUcRw8%_`RW{mCnuaA%G<1oG=C~clE`w}+K51mhkXr3=F +z&o}i*y_u?mf)|I+hZ4_oA?i=};&(0q=a<@U`(-belp~jy_j9MOOi+HTqFXm}OD~Cj +zTAFsEEodd4>T4mWRcyoHJ +zY2I><+QI?Lf_oR^e!uRwG49tg@o0HLzI;5c<6!WvaE)h~U-W{3hpMIhc<&zf?l!ai +zb+?Vi_3S>O@!WqiLo_i-_0B|h@!bQDzM8!7OxwDlS0U7C)nN2w=ndy_B=v#6}DzR9In6ET3I!ybqGLo +z^WLdDwC`)ilaQ*%!F0w;^cMvdRr-9~PP<sc&3|m){G771(mJ%cn#WqZ +zyPC4HYrSQ6pYHq)*DmbdiO)I4b?I%I>{7R|tDQ7HbokL^W~O{*Zr-5~Mdhga(6;&1 +zp{w(oipV&9VTS7i0c*ic0dM=b?#e@5ef#EkdB~xe?(6orpWj^9>8GewmHVy-v$?w& +z9X|sKc-lCxzSv&k`SSx*!-+}ZX59gPecN;|*V}L{q0i0U%V{Lb?5=E?=$X7v3(c>K +zjqOKE-!EV1+Im+7-5On9vHm)Pc3)gpUq;Jqaz~q{uaDzx_i|PcZZ}~HW9CD}kK3Q` +zBb}~pNm=c0OL>L7wjUDAFbBum9+&#*`A2A1?LID#7|C{F$;SH3hzxyX(l6GdyH0RA +z28pr@mm0~(>?IlPU|Q|m)K&K{oBa+61G7G4nAPxbmoBX0?3S}O-_$+CHrE}Q%wO!L +zotFYcF4QYOBee)Q5DQxKu!U8hUy$_gZOhvoa|+oNA1@x3J+_1#ZxLCL&Uf>FO%2W8 +z@;s?NzuIjb=WNXVG9|1V@nqu@NDQj?++mqBULF74_^iH2XA}2JQsfprwcAO*qU!W6 +za3abIwXA*(i#BoUHloyC#K(X(Qi(CqC)>kRruP>|wBdj&m4%BPsps8!Bj;CgB)}CYQSz1`L(N2&X9F}X# +zdpUX<7-Up-`|u<**lpM?QCHbN*&GpzokK_4k8s1j$o(uss%I;&Wpip>)jml1uo>ZU +zF2ZT$Fdyg^&tpe&p8d2TZF48W_rbmLO8Ktb&ZH`HWfnA=_Yc9lbtMDxhtUs`W>9P(1v +z<>YbqfE8+hSh>$=d4jCw=<~qDoilA(l0)jzeFjOwhU%|Y5~^UXVy)bt<>FaBa@9p` +z`=rb}phg{ku>Xbg7Kir^!H?igFbtl&;_r$^x`IfPZ;jUMxk`&*k1sM~4wYO||dohTfP{zI-cfEH`O +zdRfD)P@onxC3N#9drhwZkDjR6iBBfbBYHN5%b*w1?1YhnDmUmW;f +zcYR>BYY{L)=Els9>M!ZCgv(>H?a6)HArg*7TGD2Gs^-UX&#k}rnw3B#^mg~(8Tpoo +z1T`ZbZ@+vjcn5$q5>1f2O3tD|g7E*@{ZP6~p3yFi-3xGK#?aHtGTWuTGY9|BG21Sf +zI9pL|T1;cpc0Fow7zaS#+$B^Cy4r@v@P-Z++j{D*>caqNMdh{?`j3-Xphqc +z0U~a=itrSIei}F?gwI3;tk2Fftd@sbw*Xltf(keK5ccLp8M2NwRL0MJ?)cANglhvD +z8VjP4!qQa&V8tOD&=X?ByD998{6nz3E%k0yaQuw6Hz|tS#HJO0dR_ua(fXLYU2u19}YuT!ff(jI8h~-7A!Z`1_Mo!u_;0l(tjQ +zL`(VRAOp`ao{E)&`aLa;x3wsnD0Q>}8DMB5<0HUj_fQ7vlMxG=rb7q{9HeSA1E0ZD +z1WV+W-*dDBwO=nm@_eLL|Iqjsv0d!>s4VNAc(U0pbY~h +z4ElxrCawBRHR&P +z8w+xG{6*bnEap!GWJ9OpBdG??%LF38 +zl7*AOP|_DED8=WCG_LY`8=B101jxxC%HbH}8m2!}6d~5CDb6p;37!Q7P@bhWuc2lk +z5l6YdO*6+W{SE9AmHmZB&4nM%LQA5n6ex9xVH{LB80Tzwbav+8;754~CC#Fg`|!E|HNC@RbtSA{*xa#d +z+&3Q3t0iBN*(!_RR<2zqaLbE*vgcvE=gV;$xg7Lf0^zz!WEUpVVWC1-0x6bRaO(|o +zvGxWL7S5hw#Mn59^FyebTiNZ?fn`XZ^7CDWRkmt~oRCxDQSddlp&JO1YME2|9s&0- +zi49HHhBNwBs3)GWNZSsq;X=(Q-`tMq=Mbr|`XTl3fp{EZ<-`yHPzmjWz +z476wPwNs*f(8ahd*P}gGlRG!40s4ag=iF|64`SRexA<^=9S-ftcsm285Z2>Pn=b%d +zRDQ|P-_3A&XBysk)?b}4K;wEuCrs}<8nzLE^zYa=L~gr7JoPJ)J{c6!t~kC@1jLJE +zecNt634-1#i$`B>3^W0&^Wq1-+VWWI2^liipkvpkWUs$#u?xBebL)nLS>(CNO1Z-1 +zKn5~D+=aI)p9SEKc4!(9u?}c!Nn8!tvWrsD>h~Ozd270U$Sd$bY(GNE#_1qcmlQK= +zjk-qVeP_Hf9tEVuwguaFY@@*SGEuC*3Ux^N@AyZlp*j!3NXC0$ +zL+-zKf$_a1@2Pe?O@YlgP2r=n?`2eGl%R)aFWm3@05*eSIT0fI+`g>67;>CxucTEN +zDrB3)DmH)4Z-@}i{>8?eB_I|*$OJRk-QR<}%x~oZg6eZ`7FC0e$itX0rY@(*Zku-x +znKYqxi)2SA{Tf824c!N1ygeVM=~TZep8mD`_~K>S*%w?X5}8FvBkRmq@hXb+0jSb- +z5lqH3{xpvd83Y+~N>c&$5#5@J)x4AL@_l-bXOR3p*_pR-pj!yu%#dEq!J^3;JXA{l4$J@Oh}E?fEhdA1e| +z&&m#jo6jzaDI7P*??J=2p?-t!vN_zO;h?;YI(tRqTpw+>(P%tHza}A2hIvN|=Mn)z +zG!|$w0zWh~iVh%htwUpxD|~TrSb)4fe6p;tx5@DT6vpWqZV@&!kYh#-T}xCugri)Y +z1ZA8Zw+_f^H~0x}+xI=|eUFnhE&|54!il5{#>gM1{#d3#NS(Qm0jb5=NII21GzdgZmPMRkI1N7JN=ev4h(18t_is;UFls**_FK0pUxVN(N$ZTN^ej +zb99=spS%5y7KunRRF;$#M3@$cd^ohnnwJ?m?OP;(C^#{^u_-uSCPH-GDfBsFm8YHQ +zT5?_{7YhnQp|ZAGWzc>v(zOj1fS3dcoVT7m_NU)lK#rTjyX^jmlp6U}B@4Nnl2_2` +zwJrB>~UThL{-(eg<2 +zEf_4qMAqy`$Ta9Kd_iT>8dM6%;RD}gxZjQ1ngsxMw-uh9KC~F4!-M#my$91+?j!F6 +zJ6v+r6m{MCtAom#$3jcH7IZQZ;I|1)wQo?yLpl{Z8OgU*XwaLA6Ktk18Z+1ffH2nz +z&yDdWcf9^-GsH)>?DcH%3c<6wIkr5ATKzOCG9I~F@1T}s=_bdX}knky8Y53|-wxXH8D;ot)j6+5#(e`LkwYSar; +zMn_JGxPQ!5?SbfdFR=n(eH?=JaQS|YRR`}B0LMr$0naCx!qf +z8UAewc@MqZgB)H>>2h$YX(GGcE~uP^oIKc^!p$9TXDs5q>G0RZ6QOOYK#NnFWL$`9 +zUc=E+RIO-tLLPM{$tp~E#R--f5z=ym9-JpXN%~53Mie!Q={tzvXsyK-q??zP<{H)_ +zeJ)%_hE?|8@wIIJYzc0#4h;p94kks%MRvytQi+sNWvUwl347+J@YfwN6^a%Z;wT(x_?$L> +z>uXl)DNq-{G%3yFOju3SjgC3L^f%tzBva7^Gv>=(8_SACgXjM+~p*4$y2k=qR%gqs-t +z5YnGr2*DVSW9h}Zsr8ENm$CwwvXcX5MXaY +ztGzEo?hYE6t#+wpQT#j?wj?$9E`Ir_qn8xwXZ$#VgUpGTk`C`~2%M0KiuMSDrZR&u +za=-tTRQJ=Th(_9lFXvQ-M~)xax1Nb+Zb#fzdBBaCFneTkKJ1d>i;eg1-BuE%Ybz#EM +z+s;6}!J7R}!DEWDF_{oichA`GpG_0;RhsG$mLMKKN!82;2dX7Cr{bgD@sU{5#YrP} +z=|=QBozQ~RZoceobiL2ctA%g_8~!^$D;&=TXiS}5siry0a>x->G@#xZxt&yK$CTTX +zb#bLy(WhpGg#0gwV(}E%vAREkLd4Mivabd*PQ{E_bC`>D?U)-;R^HEQrClo?1Ha1u!50l +z%+7QMgiHWLjq_^jk4crO5v`QcwrAAiP`*$AP)s_E)5!ez6-FhvS@oJ|@dC9Yo~@V$vjUv*5$ +z=#137Q+{kHe+}%z6rDuWbWRNcl`W`zGmr$Va{=)mN)Dgp_vgo^Ap?&@Zg5e!f+E18 +zIeBHjE@9(C5rSxLN}lJ9pCa7E9Cv&{YxW>pKxlLlM7T@?QAM)-3DJ4NFyh(KQY8N* +ztF_VEUG_Iak%e!ffEhc-YUtMl?+lI+N=Hc3yEq +zzl1oRdvD`YKDX3+QsX6m*c-PTgRmm-XfQ|uGYN9FG2%HmCuWX{;37D^Z1foOJy22t +z?udlnPWrJn2VNO{29-2P$(@F^R-OJk0HGQ2OVEu(<(Y9>I$0LpB<*pDP@rWdZU@3g +zFE+N6v6h%D94komDW7C+Mcmy=V9x?|Rn= +zzftF-S3sHrs}Xw!QXa0-l_OyfkK#h2YK|c`7w!<)p*jNkRM{-CC7wE7;q>;JIwKiS +zmqH+0qU-FwYBB1PL57wbIQ&N850}V1ihvHZnyE^(fF3?@(GP~a34(t`501o!R~E!B +z#V0HJzR*s!O|QO79AWtc&3ctTT1L$1g68?WN@d$%9Y9POOS|!d>oBGRhy1G;$Q6ZJ>{}+=UU2?mwlTw=l%@o1|7Dp4 +zOAj<6G0(|i)SdV`i4~V4S&>E1K+BYr8vCjn_b$c4!Mr3ry~0D{&Bgl)sgJFAB?!eI +zm=fh)&+aMt<$MgIKOm2zK$4`28DS +zKF{f@G=$ak+tb7g(|$-sM>~fNO(J}iY1oZC0_VvIAZNH7h1N|)(-sq~h+Bo!1G86Y +zT~C=cwHy?LE*l`MR&qDCJ4KrHG8;wPc?l5>tiTWbaW37!oepnXSvh0Ml@LUCOX1-m +z9M20u3~129e=uscY5*-3P`G{Ev*I3nbcCuam)>JTf_qy7eH*dOIr$ue-*AuLU?^?^ +z7FEkk)|4S{DTH3jG~i#RI}5>RH+UDsP23|G=q3f9L`uYpp-z7b>x#`I!N>kNF^>mY +zi!eDM_vaErY^@NF(8vgn +z=n)9c5@7*OBfa-Uk|?TlHcNkjEUnJpo_2j#&1IxQ_i)TyayySMaD+~bwli?aByr8r +zUUP2V!gJE +zsJ@?Jgzvzy#?Wv2X;!tip^`!PTSZRtk(k(ogqE@)Ir<2hIAe{Xz|6gNZ8|(s6CmAq +z$!_~AN`RwigPpX#ZeaJC~dbRNKXYm!AI +zOkuxg1K`-@U%zg4g_WoY*_gOPVt($em#?%;n`NIDIDt?fNkAWP^ZraxAaZ7F4;g9I +zDV}@Za!#`6YtFzc7TqIj_m~m;f$&!-*F&H4ITx>gIz@f^k(LRl|U+O5I +zQ}Sm>aM|P3Y?k(Y!o#xA1L_tI*?}-jb?CO~OhQ_yy-Y0;Xp}pHM+lXHQbP3Zcrcl@ +z$%!Q`v(sZirPcZYnMp}T5o%b6)ljpjUy7xwG9hevz97^&hto>Y2T}|P>-6Kt-;hn2 +zUd&iS?8FI33F)!DBm&wIWS)8>)ka&r7tRY)33ghuXL^w3c`jgikqkufT8N;yP++!o +zgcg~2A_8*uk|gk}$pKvtAMPJjP1zY|yNLbPat9JMGmjabX({)11 +z7|gD}vi5LvozXdjPPQf_rAVkCJ5jKZ5lp4=aEBL?&lycPYM+m!9zx*Ur=0XL*DP|( +zk?YI9HO~gx=zr&cyl#E$<_k3lR +zNg>co7x%wh2!UlSh8F}xOkA|j?u)m~ +z)mP%kPVUf=T1W2D=aHKS?R4L*Al7eu7wkHtyzNyNW^0I_^ykC97|&xMe@`|fXPwWB +zZ}GbPo`rOJ8P7^q443nGSz0J(7v9HpHa#6QfnMWk3m^&g5n+L+A$S*bZ1Vk6H)r>H +zY7YJ?(%He%4!7>aQTNZIrdhTHN3=RamrGZ&H0rXgL4%4;lew|EU=x^TUjl-jfG7(B +zs3l&60H%A21IOgZ58V1vwPAfd!@-^7!Yvj +zGrAo-Yw5j@^;HcICWbE~!)4X3%@TGq3d6z{xapK-IqEbTmWECmek=NtDA}s6Zlm+i +zLunl?%Pc`Y*)9j)6O?kP;I^^Wdw5bUM~?~cgCScj8rRFZBTWBoD>@;KaM=OV(P +z;oPTMUybzI2iTLN4;@46Ve**KqnH!#WWkH7kaJ{rqsZZxD(Hc3;>ZOw*i~#_A;URc +zbGuuu?ImcHdI(i+!^H) +zoQ6j%Bg8W>1{vkVQTOARLH}2RjX*g35hl72qU8 +zUCDXUWC+s2#*zmmc7f!3M6TJKa@Hkcw3ne?gQI~-v3^{ma2|}u*{lJ$h$NH^>@p+H +zzBymQ^YC;u=Scx7c05)>e9_XNUf7>!{XqjlnNjGe2u{O17(h~;2bYW-@6bkaoQ?i? +z4+^D2)$N0a=U%bWMZ>s_ihdu%F!mWh5#|bER(Ebt9F4kC=EA9YE0c~Yx#uUV?&pQ9 +zFtN$m@+wSl*yg +zcC~jE<)RA^#|4;o;uw+^L@OJv*4eFjis(JvRJIOG7)^sTrD!M>xU*lW{Ugvq?4_~$ +zAMJ3P5FulkQeG)|Ms4sKM%jUM-q*3gDW{6m3@Z64vN_Q$N-@=tb;z0ZCc`-Q9iYn| +z!S>*kPfc=L70H-c^YObdgnWMQtH15K2uy0iuL2rl(dJL0xYMJ-ol2|gydn~9X{4B= +zm`6k`ZQ(0Ns^T7a=*HiX!!ITdAy +zWxsFAZj?Ne)&1zawxA>13?Yu+Y@p4@MevCdvqC75u4bf{YFD9yu<;!O0`e}DYH%z@ +zan9)H{T7_{+H}h=>d0R)P}=y%T+%$%{ZdTWhHc3zzEJyZG92mp19}8m1tE?T>P*n) +zf}z?s$E1*%ZagNfZdfG;#Yb6BdntkhV4$la%um3BWST~+>0b%=Y;%ZH@V>DH!uEeN +zZQ@83Kn|N729={4d1GN5h5sIhrBFgm?4qcW*kXAEv^!9-O2qhMcOA4boZ5=+f!!j6 +z^==RYrR^Nb}y5%l#&qmIfVKcfJ$Miq&OgA&iH-5hx1XF4s6>E +z?K}oG66?Wa)pSB>9!CEXzgFyr{Mi=^FJ>g)Cdk((p;b8HzgrbQ!P=7d;o7sFAm9ceAhpX&M*)(V9M +zpd?{RN21Pgiu9Otl?OH*)rVy|FdNqUbW(IfO@15Xf{V3kxXA~`eHR;?xZGZkOvF`J +zL*m;s%T+743~!@w`5=~1s`Pu<7=xdUnpZM%?Gv1cSfPkfc^Bj%E)za(~p{CRUboPD|Jth#2!4G +zC!zO)VdlDG;cX}j!>?#~LcpRZL^EsgsO2lbsH>B3p|4 +z`HnD8X&D>}%&iR&QC9zc06ms?I&;+1vgS@dy;d3_p@T%y@WWIqnG@^cFIt7M2O7d^ +zk}|`az?fu#Q=WMlsmx6U=spuDzS}K#mF_y&XqZ>p9nsl~1fTS?(iNq6^67HJ2#%)P +zodPAVyndZ9LRe;iY|SXzD725lO}-QNGurIf=mpJSH~Cnb(u#xpiXogNsczx`{KbD&hjoVjpSc1rQX^TKUJb}Arj;H=rZ8OqSRVyK)^Mr^TQw8pBfK<2U5Gu +zH3Zu`FHC~gxx1{<7YW0f$%e=0)&?}uaF55m^7LLP*#l4)u}-7t@F7fL +zk~>7^kd`=m+K@Y)cLF~qQP89UExee1NSm;M41FOp@$F0k5lGNX#TCaqsJS`5m(HH5Nc0sq= +zEasaf_z3f6-UC$rN(zka9{Q>Q6u=Ia>ADk)g3cSTUzoLbui01Ze{yNkRO28Xci(HYN#V|~NsjfW)3Ui>9q +zC<$mDMxWpO?S_Qx(PAz&?Q~oczbib`XFkGd97U6)BqhT#r-V72@s>cWFA(5#C6Qyb;-K$`Y*peY#9EJ;BL5`*qj2 +z>>a`^AhJK%U#&QsKP@i+P9~3toM@qycFRdGJa`Fp_VlA`ZH$(P?tyX|TxXS-nO6FB +z?IWxp1Pjnnk^SqWjGc1RS&0ADx?gXpu;o)>5x4ax+4nl}K^6GD{$621x6pZ!KaUC% +zU-h~PJ{r+OE{q}I;`uA0X8{+;jmxcbtWCegV7;?ZxuM3;)*p6Oqi1_5-z0>kkr4Ss +z%+vq&^r*%ivs6XWK0Zl+8CdYkU+-w?b1vL?1e(f}N#yfJ0w`m;&(R+%Dj=vc2W^T* +zf&xH%i#<*BhukcSL^@hnLo`VzLKKzruh$yd +zi{Ad%x%soS<0R)l)pvfHnozer+23KduGgtTu^h1oBs6^o^pW`rwe{%h +zP-gl&d80*gfZ5P-$zkhUvJT7dlyrHndad6*@rd4{%)m4kv;rU4(b$N#n@hd;zVwch +z5dp=2e7Ds_hOINouH3E&bObPCcOPQ^fa7P1<3Bq~Kw3yaI(N7+R6Tl5A=!b&pxb{Z +zmAs&^+Ds&CS7IP0w|YCr)348K!>AYcJe^=^;y_~=cm&fbe#Eb`9({#%JtC~>7ZYC+ +z8j1SN2v;;}yDHF~&X^J>apWR=e>; +zC>p7yr?t{g)=~Ynwg>*dtDsU_TSm0%Suy6bK0})t8P8QY*7XvN)&%mIaj#c(_R?zx +zVlaFzyo$zHGaLyybIM~Ho=W|SFt$NRbu{Jp(#w(b@r1M8C)zXPnny~2D@|@W0R}g$ +z#hMp(t79+V3OTmOSc1_OsJfdofo~pJBRZOQcsOwtz$CFQZXNtV%tLSb`F$O6x&qG5 +z0*;C(u5Ru`7rJg7_Ll{Tm~4)k%13-1ah|1^`}6MM=_b-Td>jqro*jpJN;lL>3(a6d +zib8Kh49EqhZUR3iJ2sr(JsCD|Nujm+xy!UtlUk!WOyjKc=vuhuh&WXMJF8Wjn%5Yu +zBUR;UB+bax$1a)+&m5>%=o38iMPXmI^O)zZd>;3q#NQrJm1dY0@f?PZs-F8lWlFHr`*G`_sF!SO}O1vV`X>Ev+zjVW^x`3>G-$ +zu(;0rHlCpeC*ujL#~G?9(DcYoa|xGF*w`e)<`C>@(vG +z%W*2+*=;i1DR=86(Yv-Y|b^FXISUmo;`(yYU8wR3`bbn&(OW1_7*gQ7)D8ETHB5#|fFOe_vvM)voupvNIf{9z~ +zMqICv^3)$dDZ$bScJd(!$ON!gh_naEW^4`2&8eA*7L+OWN&;rDE8|x^WHQpu()V&W +zf%IDNbVw4~K;!AoIM9GCeX)d%5r>)>ZNXb;t*&CQnr +z;dLb@f+<7V)E{|aXHroHDwJ5UAnWT?CKv^_=i92xxt-mo4~NA18WM9E$5{)HQSZ># +z76Gbej_E%-N!@Q4VULJI<{ypChTVh^=2zeB +zxIc~IrZlgtD<_8=fm%bBOHf{n# +z7q(tgU#*TB4Y5&GpgY`wn%u9UhkP_klti +zv$Hb7^-xj$%glywjAeaJUH9zV4u`a*Z6iIC^O^{a(=inJhIvBL9z>aP{N?>k|PinZc?$Jgx +zoLVESiw`5svPjM86w9i>A_L)Vj0}5x|iMY}fSlzz`y^E4v@H&DuQ_X`x>2<+kw# +z7DipQAuQ0(6=Rb0?sMD670Z+dA=ix+Cm`upr)K|NOct?%M&VEKNs;g=^W*8l#1oyh +zCGI;1NE$uI6FxnC8(@>VMckN+(0Zb%Y2HuKqWC;6l6)_AaJ`TMBo&Ks4H7S9*;$PAlcIFF5u +zpLEGW)4ZC4mUo^AHl`9mv~}a;o;3jIi#WKA%1Lq>QanjzC>}>%iGCTggb9|V1m$9P +z&GpXiOo=ogrq7SE!toarUc#AD1=oFJPf_`=S+?B){nl6uA&a^_A0kLKo>8+rc^8IU +zwUH&iB#T@n^`DAWp3i?k6ldPIT1UmSAO0#gsXK#=Bzwx2e&KGc^iv1R<~VRW5j|b^ +zg04mvGc7$rpU>cDH@A-YvCtxXsC&k9DhxHLYRRjqQO +zMpWwO+pruqW!Z{R0yJ8ZV**vWBZEA*H8($S`|Y^-ib4B1XNFn!sIV>C+QW!y|6&Ul +z{G&hB9vjI94J4^*6|4~paG8JIdV=f@{ji5)Io#s%h1~wqo^Ywg>3pIdxyENhtLmzS +zK+NA90^WTsSW;a|uHQA1Q>z65*akhg5lxr^Lpa?&CU+T#A3QkUTPBbgP?ot|&h0Be +z)|M=Tf2}lOgw`FPyXM@0TyG$}Y`B!2E+jVVI(15w?d6xWpG}wOfm7t-*zoNz>^Ajk +zqC$8S8vM324rU@NEJYZo3kX6}?1s8&jrXY~u?#Li7HSR)qbNJEt9+264Yt#se5}3i +z#nHz(<*}M)p8gi{D|P}z@xq@-uv%f@3~^{L98Za7ar+5k8uyrjs&C%ePM!h;j?2U2 +znLf~J2}^3v=rea=^z#1&mM-~4C?wHSl^B<&4OnjFH_^}0fl#TMEb1MzgvJ8(K-H`; +z%A&<}Z&$%aPg4$y92ZX2@((?b0Gf9_%w7rA+P^laRwGcmFCykW1XP-h!-oO|Nd>8m +z)ocpSGQ2#-LJR^7dga=Mo{Lk+Z43}QJV#X6ze9g+x9$1@=cJpDvM;zUm5m(X=guqp +z>-(@Mvx@f5_(p50RTN3~s^Ah6rQK>hyzC$k5z>93u+6KL{ydG#?d1sk~Zx+ZrQ{9(^Xyx9NBqR +zPyfyMy3Eqy`a0s%Hvj@xyJ$b%eAvN)cvY=>+k0&01QoPSL02N(iF^0W3#yj;MMYCV +z*q>|$>xsGb6*kLQd!eNtFsztg=Icj|sH21$&fI9?CJA*1&ge$Ym`^BEVZ;7Umo +z*CI+6p<9M%k|?n}qo;6D(X+$`T6K2D^%e(3)s&-_2LkUPHgCHgAWt|iDN%12(KJ(p>Q4sfUy(=0k1&BXzkE3(F}Q_4yJqRDc^ZG_ +zZ<PDWX(WlK={E0I5*n^?@?ZbxC#=Ea9a!&&;y_>vaFo`f31nkp4_&4CI +zw9P^JAs;7yh0{jl78ks4i$B-iZt4BV_(6L!<0)i4t*xcUB}G!s5F#obC?O6*MAs=3 +zt(lIEM86pKcn9~XU5X_{kH~N;~L&J`^xb +z_#ru$dA4%jI6MIIew1vX*xSQLW7Bz!?*2|MYkl@Am|R7Bo^f>Fx~e*O+eS!e@wQ!1 +zTUki}Y-hs)GPW}^VR5&yf7?z700@b?+k?PXCeA=36Eh22VT#k{b_$?{u`q=ew=$cu +zy`+h`g`B6O$$L)~4X~#bnBSN}R0L7TUEmGC#>5!}bhoj#brNtFruYk2;H~{f%t`_L +zOU2nrm_l1w4Jc{nXaeM7;bLK9mUg#r<)9Ej1PVDCn+m8)$^0GS?Mj%!+}YV)fR)wF +z&5gy4lf}-_jFp|ApP!YDgO!7W`Avh_$-~wevoHn4TR-q0@!8lbEB_PT*6Hsoyz#;64zg!uXJKQtv0?pp3nyo3*Ef*A2lRin +zaMF0&b;+u3;$-LI2sV*+HL-Q3{C5ar@IUSCT^z0dO2-(?YGQ3-^QP+b=9T?FT*}HT +ztNqjB4+UlxHuis6y^;MNn$8xc|03%@V*AtcS33V5$eZ~;asNa6AG!af{HCR>EFfhE +zcKH*Yyp%A-AO8Zzc3=x*fxnvE#vEW?FgG7Fp9vc;GncV3Co_nh&y*R=Z)ytSW8*Ug +zaq;{cl)SBzGsqTf@(1b-oWWLeW#*;R51n^1>7xENuUhs9A%YP2UWJDU>X1 +zUEKfGp})I?Tz~ca85V)J +zWZsAc{i)M8fWPE#xd=!)nt+_`95w9htc5B5garI!`B!-Zh5j}uau!Z+8XkWt{_i#a +z-o)W=SAV+&tS$cP0s{XkTLBRGZ%&**t|rERIeN4ETNl_IWNT*fc7Ol9p#CAZ_`eJm +zh}Q@V;xy%BHU@!Bn7R1a-v-Obgol}*?Tu_sHg516&Hst+WM}H^268kJH+#$UEt|Ij +z`YRhC-CtDF|EIQ_xyc`%*f`jk*?5@Q`83!#1lZUFxVf3xxZWBRtbb3K_0L`XkBo&_ +z|391v{iX14)4-eE-(+vo%iCiVf^|$nOv2P%E5{2PO|G#T4D0*T~ABQLh)DBZMBh8ARMQ19uc)Iy(F}1{Qck+ZcM?L_weBp?9?*gwUSg;ssjr +z!eF+JG5uemDp4Cc{LY`;;};ND{U(3@RGUGe7pl6+rO@D;E3aY +zfoy{pf*Ij&X?ZiYyHA3DLbyXvLu2z(q4sM5@z42On$uh|7`sulwAy*8g6T@oB@`2= +z4V7wo6IoO*T2-|>y#grx&HNS7ST8{k_qswN@TKCpYTCHouSAL-YjLL=-@pe19{21T +z*+ldRJU)F+Dc>kM%7P~XzbbX`4`T}5{f4GxMsCYRyu&&B1axp8L_-=_?V5ysg1F;X +zgFD;z%NQJ1%^VhO@k7ON3~u8_3lv0$52fy?BL@+gmrn&!MZGq14C0)| +z0NXR6PcF)St#7W8gw>993MWAD0yZJW^cIG8EA+aidYR!N7RFc}W<{er$U#;mUlam1 +z&Bf)YujOU9;jM>*$~Da8nX)&(9Vm3-;L#*=cW#4M9nM!A8P53Z1u75Ea`~*qQS)sH>ZGpf9Wu?K@bGLM(i!%Fkl>TGov-S8S%I}>T#MT +zL1P2O*5X4XnMx*2FU^p@8DT78=iZOFDw +z_kd(!Ee97+@2vNr|53K;(In4|B<~ly6i2qG(;OCyLBni*ncXVhc`_1AVtPhaxk9k& +zNDW1#+FG!`1ct5O@;awzyx)FX=)~C>R)*kB1Fc+GTsP!JNi-V_oj_v0$hCK9;b^LcuYc6$gvDv9 +z>l#VbjUwGLmO+{3!MoP;5C6KJY!PbG@VhT3m^r~q7JBFOV-o-WLcp3$l6U>P1_Q3W +z(q_dHn;q?vSGG&;e^znJW9l!h%OLQeCoGS7?%DrYm+b!%%xeQnJeO&i=Q6eK>&>a8 +z;GZv_&WXp3VfM^=CQYm%nFuir<+_Zk%?H14+|Ag +z2f+6~WAl#rHkNR3hC6Vx9SrY&iS+0NyyxOYOrKoCKVS6}&u@Z%`i8?VznElvi_kHR +z3ZY;Bdj!xs7@ohOhLLoN%4y>)rjE5Z`#8AfLy9fCC95|nZhu_z{H78_?i}w2AnUng +zj~hRIhXv&Aam@8B!^yx&c!|4m$D;XFyysn0STw(hsZ(m1IIfziszl(vC`0KgsTkSY +zMtb1Y;I${7-pl3hpN#_SOl82U3e1&&p%KN`{x_3Q +z&w#dW#g2B##+`~sS4-}HA##Zoo>Do{`&|O7fd{;wM}gtPF4o`1QH`dPztf8&ChY5t +zmt8cG6W*b%!^H8`w6;`W+oEJs`-hYu3k9-W-Hfzt#U0v-WeGm^tpc|{sYoOQU7Iha +zq9Vc2j$I6Hd0eAb#<`wa=W_9XXaV_;PfsG-)5(8bKLWtTD+HguC_!_*h&+_$#ix_1 +ztL3JjKgnhPz6F5WzLH?UR4X{Ik7oJ&tsmT6+T`fxrcn;76i%&x)n=i32uK<;W&!+&McEB +z)?lU65sTxWd)?OX#dFS^%fxz@apPX*<6qgyjSnjBSykj4AG2A$#K!iJsiB?QX=+%+ +zic@ERCm_$gDp@q$iqcTRz0Q_B`nCC!peiFGLSB@i#ZiDzn!@5!Thb|LsTZ`=3+7F+ +zIO7=j)J3qjN3vtDV&g8wL(fYd3&kMit^3Kq*MV)o?Z9oo!(e1a4-3efc8mhfN7Kho +zpiIK^%$2QNc-~Z&E^cAUq*{_mE3#?#c_?tR!{mFq8E)H2VQ^O{G+r!$3i(r$M~545 +z$F3nJPpm;ClY#Z{ktKi~?S|_!riSYJG?#y@k#S?!aM{1Cr!Na1{-(=E-!1vbISHyO +z1^J#$pcc~9TFcTI@a#rdvq_&vD#N|( +zQR!KU%e=V4j=$mDv&L}2c~d#^h!!SKtj6-7Ba_b*7ZT+;@r8jQvYlNNySGE39U;JV +zqE^79eMpb`F>zEVAe*-6Ks}L82F|NO=Rk^%et+oODwI;#sU&Bfzl3|o)bh_)u4468 +z_~C7ejXNE_^pPs2%$tKkpe&1AL4UTbTWOccik{Q9^u`_W+^2C~Ft0ol;|KP_bRWI- +zkV;1v{(bru#n13NZYWrm1r0TVqh{M2HQVO>XDYVtQ9S#K8$bA3+;pXsQaFQyWIH<< +z-n$J|=t3z??VyZ%WS+UtEd(m +zyP}$k(W6$ +z3CI<~i?6BF*YCRFdieJv2{ZBnouiR1I7Y0JN@yabBaQFz%(W?Om1)7k>4F8*EG{`! +zv0GhHy-6|OfElV@-QSWC1@C)F2V9#Lzd40k5`+$E07RUd%^oSZh{J}XKcl2nc +zO{pyjuFb;|VF0U?BHyotqR_bo;q*}Sn6&=pDcN*Z6vgskRonZ2ZIxj8LU?EmTz|t3 +zzVlUwOez6FAe6$g^k-ZJvnPeu`Q&43IqTR2N0zJWHlDWq!xbkx+bHu`RTyf1yY}sDm;=jL-igYMkOXt`D +zZ3QDiCog{MR){v*N_DjBc%rSPavZ3jeJr4h}K0dpARyo@Zp&8nV56aGh)bcP0~|f9*r1 +zzIL?j=%!L0(xYUksTHA%F)*yS(eIyc|#j&+UPuq&e*DBik +zpuP&0%(8-A<>dRx?%hG6s+l=QP37#9Tj<@hn+KmMu(wkOL|0v6aq<#7uzY?j;&0g1 +znqP751K_a35?Qc4N;|1Sm1gEYG!l0fz +zQU}BS@$##EoP6Rq>`XQ8AQX#Q7^T$zzw`{7n;w*GX@{@=Mv_T7TyS!NWWp10nWO*Z +z2Pq6J!AUk#tZWY4^mojGi%z!57h^dZ1=7*y?=-elQ?2LT$uQGyLfJlQ!TV3ryp%|@)Da(J0%aVk^JmW$`{aTbcN){yrBNS +z&~%soGl@bQxDZ`GvDEy-2QHb!r5DX$>EafuDie_yqMZAq6u8+e*{&{f?b~oi_5{U5 +z{=>Jd@WEMDsVin1u9lQqa00&_gTfKBRHoapVTa`O&pMt38O6=NI*q=~TN&E^bf8%S +zm(GT#*1Np>b74k(**v)9RGV?lI{5A%Qarg<@&kj+IBz2S_h%A}Z?VEyp^QuU)n66) +z>D~HsFa9h^b%luJOM*Z3ijoAjtQH#BsE{wrZ`*k&j+()`BEBYDJ0{O78>p{WF +zgpLDYQz$pIX2DO)S{EF6WxM2_XC$|-ima;ye&cx@+uv>iat!eQd9elnvu9NBub(=C +zmCMJ|+LDQ0QJKJ779CCVXx~k-cN3sWtcuTa^${LlpiGz+qV?Ur09l4WN);8Np{!y@ +zyJG7e$=a=oJD*VO?%DUvzVyU7OlVMaz4)g%ckYGMdzPzaC`4-xtaP7iS$UIDVmE${4}8W{bvJQ9_wF*Th^mQ)vYPMl|Ud +z3D`ZoA1Wyoz{uqUL&X3Rg#snm)g^g&wdC5nBM4aDgNMHXZ2DUlkSXX|?Q{L_I(kVh +z|N5yTSiWp5)gIj=PVorV*mcSE^pWdmBiFS7C5t6Vzmhn?(5S9a!3R-G666D9Xvh7{ +zoG-%8cFC(dB&*gbZg^0Y-E=1$V{!V)Y39#KGdLu~=^+Xm?=wF1UJQiV5D*y?64S~E5t=CFT}aP> +z;)!*VAKjrC2no~j`0+g>p48g2j~Z30gy{9xKAC#Fmr;%_!cW@BoWc@hGjs#b}C%N1Sn8OGKO}=BuoHOssLqctQDMf +zjLq@$6c4YF{P!OfMM=VARa}DZ3vm12nt+^V3J1W~zVjl(BSn@k8_TR2^&}F)d&r8y +z&@j1<4o3EF2B#;YvHX0454XCKvUGBP1G&-=npl8uZmP~c#rmz1KR+k=&7aFZ?#4Q} +z?BWzhEzU4~N{aeA%j-lUwCkX~0h$_ZPCmin&yPyhzuF55Y9>x4KhS}42P0ZGk%$Jd +z{`L5l&WE7=TadE6wvKPw?*8z)weUhsjm7*qX%@^)bJ2MewFLFQDgd#e$rGE>_}GA6vi`|2U5iexQqc?%u>#zQ38heQ@{v9o&6? +z2jd#yvwvrC@{u;RRl;A(FcBxgvZJExBSKPY?d^XC8AWt_41aHrV)aJJ?T<_Ddb+$& +zoP2`CnJX(;Fekg3HAj|H(MYe7qWZ}F<>|}zvN#m)T +zG@kt65ZUftvYl<@`?jGx=+hVUWHO|PIIdwG%D6S*Ug8F(3N@56wu(Z{7 +zsp0<2g=}Bk#H1sS#Qoq|)NI?yrnNiix$yzipe9jei}0h{72uMxT|Rh*VCig&8T$|x +zRSs-X(SSx7?sPn7;{U$>RhK&-SKRq(^!$rQ!Krg#W-C0uGZ2szn%Vv1zZDB|J@9^j +z$NzK&OBc5Qkn8DX`;&iS)jG+4|K8;#1Mi+a9{%-Gn-h-+YavXIl;4Ta5@BM>ks(FG +zjlqR`do&Dt=M$3Ko>2RYCr&;g!_4U^Mz4O%g)E%c#K2II!J#4p0|iF14*9%`<4SUU1MJz_M$dpo$?^rr=3&DgXspsi!^#ZQ +zRSBBwp`k|i?ro^iN@O?-j#S>-24KwXYs*rR7NPZ^6p2(y2kBCR +zay{W78l)q18>HJFm;Ca<=m}1m49jQ2Ks6eEu&h&qM#7I~=8Kz>@ +zcfPRry{o?dyUm2q7Yx9RbRf +zHek?LLqGO7CR!M$&Z>dnsoGLi~oHUCU +zrkOf9MRk>kK)j}vQb5AvS=pB7;sx=Bpy;RoDz;*rB>#GzeIdsOKR)of7A~EFR7#LZ +zLtPCtHwkL0A(<4U(*nm)6bj(F$_wfR^|gZLCX4zyi;9e(s?uWlvI=Udt-yl#g52%Q +z=9@#OvtDJ4RJLJS;=zt6O-~g%`xx1{i@vAVGkC|Ul6x3a4;P)HW0omnERu;b0^*r8 +z<#_-deTwVvmE7@c`23d5hI5V(jIRPWr}kOw_QV$WQFs}j^Qb9@w1E81^9OnSPiF+Z +zX_f2Hv+5QcM@FjF{J?wFI+v?|;B^mQg3akCrGhBPjNb5?t|1UY*R&@Rg5Ew!Wn~!G2vORj*9^4v-u7H0R|T-J +z|Ney6-C?h@g#UN&BzCD}X;#$qzf>$?qrxD*H#3QH;iff~6 +zkdqd`JCCuLH`$`LLMxm{*0_A(`p|Ru)H#Bci@o4ql~Rpd7kYNOaP?L5`23Yig0&smwvC}}Pif|>;KnO +zTh!KAC7sseoG`};K^YNO#45_~^4&1AG&WA*h!ZIL2NapK2!zZ0j49|50f{9P&Fg-p +za0*`@UQ8i=L#QY-(fbl5B_dK4WeQ73Z1bU66RZ;6Lse2z*xSSK=H2u>@*>%X*F@+n +zmn;`pz^}YOe8w2K>LQzIt>Q2D4e+{#vw&1DUyZHLZtU#JYU{*vBU@0j}f^%WT5< +zgXl{LKKaYw4Sxd8I8^f>!G+D4RUam?T!)dK9i_=2RcgI`g|>XLRrut4WXg{*zIt^f +z?>w!FbSh+}3QGi(1m9a&`*M-h>t0{wX5RqZ^hXD?Dq>8l;KK7#95Fw|v?(c?8|_l} +zFt%CaWWTspFPA$ImX0MXp#$)QC`~BFV~>5UCqnSR$oc#*KgkfX7_-q!I0zB@qBv#O +z>^?yV&jv|L<(=Csj8{?rG}Ty3@~FAg9X*%g`%b6->GkaW&hItUexgM~McDa1juV8< +zBUEr7=_)}*ogmw#6OSc +z7F4Vn%@RVHO%9Gfrh-&bgbOCX_AB6Aea@;%!IdAcC!6i%j{97!Dw~C$Jf3uY1)bYF +z$PHytQlVUlausggLFQeY;R1#JJcZpu$nIzq*w&%=?vL|m5-FVb&ID(ioMFM-G);|m +zgg_`=O(QY2xfyeqJ*-RuV1Sl+2~pPtl2P}|Ctmtqk>4#o78Zb&;g3V_<=4eAkxd?G +zeBlwfpv0XD6QClr7QTOI#R^5rNxNBHWqz+`I)x=j)>YAP`~up4@<-Hgfz_KN^C#I@ +zCa6X{Nva}TJrvZoSmXv=eJKu{I2C@c%c|1oE}C~Aj7@zoOK#5x-Uaa4PtIq-+^{iv +zwtX*7|L#b+YARXkkDGqHBS~C+okM#coOz1P`R7!Hpo$UL`!o$7RZ1lVOBSVBvo^<` +zU6PT3VMZ^VNZt4bT*t+gE_OPBU6CMJog!7AA=6St)r4AV=QdNbpoz*Eb)+U#VbvyZ +z`t!Qghj+ZPQF6z<1%CSLEX87x>MB7)y{%It2+jZiAOJ~3K~#}0qXI8ZMUN|RvqaTY +zzy&YYl1hbvdL)_V(`$^+`s`R&)N$kR1>96N;2YxSc`ZE +z$}orGFM?9a4!KMXkv};7VJ0V)^n?T5R>rc36xsL;-0gcMYxML0PFRCzFc0!Oy)KK8;z^QzdoJ%A5jg#*f}FlP4zm)|d5l +zbU(419S>|kAZVR3icD3-{@<7-NY!Vkncm2lGo~^6?`Bee@>r~vFkSrEQ<8uBmq9N7 +zWET%TK0>jmB38rPgRbiX3el2NrAo_Hr7CTLP#Tj6hTO?~d+Mk%B1yoyHJ6_Z8>|6aXGR~t$Dmuy-LaY3YZ?w_&tJyH1YRfxmZ)trI38!;z^u;?$n?pw9r35u68I4r7)=*Jf$xzQ= +zghjgF3zoJ?H&swGtBLfaYFu04dNkAaPPp^F0_$GMF=3odYjYwnu8dfQh#TZ1S_W(z&4GBE-wT|= +z>sQ)^GSDyO@q|PfRKm)n7~Ii@v!jFFL3r0YtZ;95N>kXORf)J=W|A~180pgrX`}#a +z+k;a)25dZ3EJ#2SJ8{{Vh~g;@^aT%7%COi;2uLTr#9Yh`+1e&q?J;UDyD$~_MqfOG$|a2v +zi*m__`}yV%dTDES%cE9hnk87CTLGo6my7{(Qo`>160Yt$jSVv8Ww$9Ag%IR7O1?-$ +z-7t(Ani!8>nZBN3)`TaFK_y@ezYp9vVeary$m))s3&7S+Xz%sQa+Sx`3Y&zxMensT +ziZGFcRHc67#OOS*;}0bl%cwPvS~jPzJ?JOpYfnprbNXyMiYN*Jn|6gOv2b2GqA}x% +zyCC2-HibzKZ>Y2Qw@+zTOAa_}yZ04Pipu&bs$U}>+212sm!|2cv5dZW2AO%GGyIDi +zioECj-8}f%NRTKrxmu+O>HiKQa(LIpER%w~;szVucR{FLw%zv%N-C1+B(=?T9PA@As*2HPO{Zqr +zsE9TBD<|TX=D*jEY47I6XU-w{eU^TNzH_V +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 +z!=@#S=1lyIyj_(cFKQWa;S4 +z(zSPhTp@~gi&)FdSPefzUi+4Lvjnx(R*Ao9E`nKg7ugdgEy-Z1T4mh2s!C&Mr3agc +z5@ze0jA&J)NH%5yE7E!EqbScmjc9tqPgUjI8ewEkV>EUZc>t7_FA8BiCnIiAvFSbW +zGEjr58&o4w=0Q`&CGyOF^%0uZ*WOp^Mh8fh$Ac8MXE|haF9gaa)O81>^$s*D-3yGn +z{Nt<2{;{DFj-4l%J4GpivX*aUHJy4=ik%cG$PqqCys +zb(tflqNtboe9fi^evlqfly8NXWeHMs6%;0ADZZM;-LjXFEqkb*GudF8h!TfeMFN3+ +z2)HovBF2IWzo)j8T +zFr|}sI8=^gb(&;Dnxe>pg8t`UrF#BUggMJYNkl@|qWgWRf?a2sialE39&w$}(6L{$ +z;lD{KvrN=6?FHAmAR1*B`vmY?BMaIyIHeEm8|2& +zJ@D<{ha-qDSrKklfAEXn3{!|mGs?)O4=1ULXv2orumDOyO;zZ|$)a1^uigyF)(S~z;eOTwg!2s0*#owx+vEt6mITree~ +zKCqGsfg3>#f|6a+tQi^6L|w>Jf9NI2^P3fqys{s$n+@~E!_0AlJDyeyhx%?1uN~D} +zB_IXhY~X)@zn2moeWr)+ef@aGk3ACQy7ad9vFVA&=;$7ytxK}KUGd0^if4_EMK>7p +z=sx%5AtsDVFmHAm%`FldiBd7^L0D*ICyeQ~vMh>N(&98>+_^6xs$46>H~FyB350Et +zXiVeo&^5^;Tid9aKP9?>BaMFJMcYKn@=7L;5>ywKFaXVt(WYN242aouLoHF7uQCNn +zSO`1TvC-_&<+*0=aE{J9pA0_xojXgPLwyETEP$zF1f%K&^;J+?0o4`Sd${{KX$r?K +z;N8IUZ>4~M?&|y@bU)P3-}68Rmwf1cetq3aCXKJAacmO{S1zahxd&M^UDsm&Qm-q48pEfXSMl$H|5g9K)`8u4kec;N`RDfjCfO$Ou +zaf|LD;$~$~j--$gsGMTxkmbAPPPd09xAL+_g$@hb=5ZFkHAWp +zO_ZfV7F^tcVG<3sVJp+f1A={;X9Wm_%of>k-5(jg_qh<8O~5;k6wICoqw56CHF}__ +zAKEAx2JNnb8y}Wj|4?xLb?8Y0yAD`k9mMDQXAc!Ssja=hvoEx9`Y98rsY#N|WJpvs +zG2Fg2KpQhjL1V38%2 +zW0R$PH&99#9#;JN_d0&7o7qg=)FzyQ!$4R6TP`5daVZYvkw|2(OTMj>=64>4unq0+ +zm%hd<{qG6cuBmLf6^p-g1&J+L6wF>@pZhaK1ck-gvjJ+&t-B2irt2Hk#c +z#%xL_;z7PZ69XZ!i=7oTKkNH^fE8r4G0q@`ib!t$omdR9J_fVq<` +z{_`UV5|$o2@P)7R(LW#~9z=XPlgZ(WcUCkpop?8lw82Ys@_Jm6Q+WNsx^fjA4{T@P +z<*oydLoynuuxq`#mCiv5U44e%PFS(054+m9{V^D8|x9{QmKUs_P=6N?vn?kZ?e01)) +z6$K`zjr?B=x^@-;{VuBK8*h3f1byd*o7s5=sWxxLAP(?|8 +z^C10?wNvQM9++A8sNZ%)BDksCu8wG}wx6HyiHs^rLGd{@zU2^QMi#^^a;*Kk;iD4N +zEGWliV9h2rUws{ecZAcTihYCLN22xX(Oica{KLQt8|b?3E&$G63}+r`1u{%*Adx~N +zm3A_`?w5BdzV*l8qDO#pJXfDXSwM>DQP7Zozmd7d>^1JC78_efwiTDOLx!;&&u4czW6%7kinG!y;bXF>| +zJNB~e2RF0xi$BBN))Bep+@7vTt4QUzW$E-jBcRaP%dT(U0Knu%xO7E0GMZRFEQCKD +zSLqJ$3fkHv-?=41;r(Y|&B5NxZxs2c4fv@4%fDUo6n*`=#vxr-OR{+$MJH@#Ee-1} +zJzB~oD-+D|%CWAzdYIj9PINX11|7ldtSD7U<*A^wb!kOL1V~n{`@jVRpmLg~tmj`D +zAlET`KZB8yI-jfDtD0+`(xOVWq3bk;{eTQSj%GQ>t7CNB02u;<46 +z*z$?*G4kgZLrXUv#%*D-ktjw{06yhal_e{pK7 +z1fMuxYtKRvuD@Y0(r_*^N`cqztY|{`e&4K_)AR|lJ9W{Nb%0!~bZc1a+4uZj-3{b* +zyIIM=G6Bf`5uDz^Fm^CdEZ@fuyY+;$Wf34(F>6!SbcrxeVF_feK=+@YyVN}Na +z!rpet<~@qrUJmooz$f0QP5egFSO3M!mGJ3*e};}O?VBenE2(Im6BP~_j!O2A#WQT) +zv&?g~ep_VCx_q#3L1#sKKRYXWOlvb9bPt4e7&1n6FN0i#!Mrjm3N54Kp+NyLlXy}wxOx*CzIZKd-~1hTWKOFg +zLDN|i8MSf>>E_C4ET40<`$kwO6$F}o!U};qoMX=~?$qmL!#PKbp!*E*8Z2X`ijpwY +zE6MgL9*8CnzXY`ZtqRB{;O7AOg5usk?+VtmX8eRmXH2)uU|P$93s!_${b#=!3IhIk +zZ#1);yCp;{nDr8hMjIf@7EBx;W%LRm4#l0v+$HSf&o$Ybq9$?s}R+#X275+q&8Qqg&YiZ`b0i-|3k%LDM@YG3LCPR8FXk +zDiRq*w|q23*miU*f@jkEo?3_8sePkQoUNh$;GQf>==$dDm%&cSu0D7;49B*4NoxL9 +z1q9&hzHa!|f3Id_#6bZS4Rs_kO{L9*VDo4btjBw>J^Krnbr^y))2ij@$|67(=6Q$zGFB? +z$MqVuYN~*D%(7xZB_&9mZ$*ZCCCY_ow@1GI8@`9~w=5uA(4ZX1p?fB1`?6=S&*S4OEQEluHhoovwy)DJKYX^PH2?0dfbb;Tk+ +z@+545@OWeSz1`7tg`WqBG)#zE5+OvS5q6LyG~BA8^;_Ba#h=jr{ab?XPtB}m;y*25 +z)QZWtc_&aHf$;nEoPt+~A*;j +zVlW4{t`C-l+vpafFPg!Wi|3PS$dKz8j+O%i3Pme!HKPBPoINq* +zWtHjdCW{W8w>=iD{nD9HGp~&J(DJ5BDNnw#Lz*75Ihy|aUtsv{A|Uqw-2mVG?^oy_ +z(2JX{twD;{o;WLnrpNooQ_pHG^m;lgn($#mT__BNK~F#u2S!g5mY{M@bXZ>hOC5i8 +zjY*_MrzarAZF?jAu}bnE=4^6GI|P~T&cF*B*?8sm>HFQo!E3cAjArT;OQ@gQLUFi2 +zz9(B|xDLpI8xH0f)B=*3JUZ4~!sy@#WVi3d*{~acOHUBgSBVf;h&9`gUYW13^>t_a +z^moMEtKYmC8~4o;kRouG|I3C=eZeNEXqvoVCzvzIqQWZ`x$zG<3SK?3(R*OuofTyW +z1W4n@j6t%U!$C6hK#$DmXb*m8dzO69UzuGuEP|Ex(6)gr%5lTKSJI%H#7kaFf(4%< +zGQ#fv{S!OB@Ka=)eh!IoX(s%`JjR|nl|)5?Y}YWwp?$mdu1C$0h0wC3TN=Wdab||k +z(^7+LHV5xLW|kH2}{YKx=1fjWIJ +zv?CpPz(G1_4wc_?*FQ#{@4?OewPeV6;{#~X1=>)~WJh|?X{i4V?BLz=b!~03KG#Joqw1Z>5tsB*^E$CTC +z32ejT3n(R$2>Uv4Jv_s^t1og1_rF=2_RSQKy}(w0Ki=II#vwKPKXzc!Xd@1JE+2GO +z)O$q*JS%B*Ry2oY`kfWc9Lh0Ey&k}hqA-{{V7f_Q@utMuF)7Hl{k6e*X-$Q4!#WQQ +z>DoczQ_%6yc)vTGW!KN|V(+(qAB{CWu!zd>wJ52`b&pUO$nW13Nk!2U5O**XkYsaR +zq%UmHIK#HdZf^@+~@2ALs+^=T)eZQS&0~%XQ_SSF-E8N_Q8YJ8!J(p +z!fJ>jV$SY7g}&T=3Wp)hGTynum`A>kj)&Q;ZEU{gI`U6%@LZ}ClRvhIx;ZTfA#k!q +zvYq82-2HN|a&ABksb9Xhw8fB8%(V;rTgBb%xL*?-XOAX8uMnX{k1GZL@2)4egZYSF +zS@&jc*f(21f=cu*Q$XtWe^&XVQQ=1D=yJl&iZL`Z=&rbr&Wer;2#Z~H?+nh@ySWoP +znFvcq4+QQNg34J9C9m%8+KO2bF(n0@92O$!sGLxVOM3ib?{<- +zmYPR$frgs9pV*BoIAkgh&YY0UsH##l>%}e|N4%DRnAvyZ-&QhFz7WYnc?Z{SVcS(d +zLV0de?eU|SaLz0e)hSSld`~vmVKUVf2jynV!M$o&lHZSt!$>Qlq9GuuWaLK8 +zMBdQaE$sOGPXd>$VdXf+tek?Cvb}p72_V|nbNFMkWkDi)^z~(y%_G@V8(h+viC+Gx +z_GU7o4I!YnFT9V&DxnLW3`=1}Yr7&A#eeTeG$pg=?JOVxSl8E|kGLcIdzi|-r%#4i +za=$*^in`;LF(DTLSv8uU3|z?V#m2yQshSp!kQms}d(b9LS!tWp^inG_vTN|QgJH8i +z-m@U~lu?LO!sz`U#w#P6cd`BR*9G^~bml}_mrX?27P2UHyiqu?t^kTab-yh|Z$5=H +z5boH4?LU7J)C@G9F@fe|#vv?$ +zn|H}|4eys*_ge67VL)3xr#)0|)wA>v*$<`n@ZOpmu^5ij-t_f{-&<2@bS1I%JP*s( +zKXyWBYKe&QEdhq3F4o}NSwQlB%$YN?uzDl!-=!pMsPjCR4VyJ;74PsJQ0I+IbB{ZR +zZw{Wti*APKIAcMgu8OKt^{npx7dt5o<`0^im1-*EW);+HQcrv`Ab=XsH!5n|v#UORDaqzKK31`V +zGpc`wEu6rWRZ=Ui-o8*kQb|$bPQ{w6#Jwzik5Spqy`2Rlc(kVPY$Yu0i +z4`|zyutO*}URNR&v^h(-rvEfvktw6`nE}8ns6TdI=w@y2p{lOxpxkV-HeGgO{w0R5 +zEVw$~fbN#!!>Os}x(LTf6&!Z`@@|~~Vpp8!<&K1H7(2%Z(#20>`?m8-3N-fI7CZ2J9I}1n0&U7R=e1$Z{#Hs+H8mV&zvqcKW7`o?~0LmS`Vlu+EDD>wj^yl`Wn*RDD+c|`ET$H15 +zwrc@tn$gVH7Iv^Cc^8hWa2$m((=*a%ARZ6;^&UY>FGqJP@na4pJr^t)1zC(e^tKg{ +z3SU5)n=(-W5&NH@D-=WX?6{>J7JcotuCS6X3?0P)R#-G-8gLbM7)&-ULu=;IDaM^S9V=;* +z@5%l}ChlK*Xg5t;yJBxHux6jVc!W7skH?1GsK`*OqN7R}y8*;YXf>>az)Bbay5)7Z +z@pfk_x-}}_&H@rl`x(_z5ew4y-$Cy2a&0wLLc3R1batUquqyjbzC64D*XS%547v1p +z@hXNbHk`01_^s{P9S7~EQw^E2&UL=4G!Du4Wg}zE-0l#TO*Pg60%u@^o!`GXIN$j9 +z&cUuolIuP&7`JpID~9*<1rWHiOT!Ft%cV* +zIB>gMH*~)e-iV6I=MiV4^yF!onEbGqSV41S!gOg|UfpB+5g9 +zDoJu3n8*DG`(6oBXigifwmfM^KS#Ss%zXfiXKX}y+r-6w8fX)*GTQ$~ +zYfBW}kl3viQuv)xcQX7XNF-Bn^hjhZ<-H~v^*Dju+n-^@{74)d8KDLFL>5XJN +zMn&of0Q8_% +zE809D4pw)VN) +zF*Fjs&u8N1`@en8t&*;Kv*a#! +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 +z?y +z9rg7Ml$Tezo?rURm$oe^D>eAb4<-4^w=&%Fv}DCxFl9hCu6q$-dNOkg*N{B^;kNW9hgtuqu>5{jb_x9QR__|^4 +zdcb1+T9db)pJerlB%MbsOf$+Ur>NX)#|}lGTU})ai8pE;tb0=lv1o=}M`7Cmhb2=r +zGCAS3naEI1;&~M_s(!w*MUZ%0lC^y=@*s-T`t@NTPuyKqa^0`ex83!iodWpIKQCv- +z^pw9F4R>^77e+&2|76DENcjC@Ztn51i-|Q>hw}%4{!Q?k0?Zo5M5^nE&q`ZX6l?$m{u>kpjw_v5mv4%&nM#hy_h?ry!bkg(ld)yT$d=Dbx +z0-2N8>2YYR#!ipZdHvn0IJl-BkrckFlhqltyOhtbo!~XHeHn&#^pM{Z6cQ`T;cq^Z +zNtLPa&9W!lzRA$C#kA5lsKjv770%W&16T6 +zd4KDEo3qY3i|>8!d*t(Z?!W(jKJ>v4kj@H=%VgnS?@)_j>L)KJ +zQeLWR&MKrbLb}|xT7*JtQ1o|vpNY^6=0T*Et9XmwmoyWhm|SREth61s^Vdrt98Epe +zt>Q;aR|QIh(J_P2IBlY~6x%9bjps4SBG?qLMwQp;`T1QcL^-XQ!f4J97wy5I?qNg? +z`d{oMdvFA2APh5?uV2b{E*oOyl5yfOq17#9$TL{BBw`9biPnw8>#K^G0d>#nl~KO_ +zy~o+JXAcV&Ea1{hFJ;DKk8}Cumyt@9asBnzbM3X)0`TZl`e?63BA(^;U)M5yszF1Y +z$=`o2$ydLf;rd4;a~lN}Nf9Ek)<<;&Zq39|xrk{9Vus}77a6?tGsh#8ycXEvhFd2r +zinZqVcjUj~%|G4n(>JkXakYQ%3)w8aySE0-P+m)c4R%3c;f_1lfB$nfn-4(6JI++d +zl|qmV1jYo2mcUrTVy+YU^>yYSA;RtPe!IIUs?58sDWbST*pU;CFDE4Yn!#yoB}UXB +zQKM=OhMR|2>2Zc%+y$0H>P-zqE8^sb$JOULN?*h;`0Y+JzG(nwz{03aQTfhwO#O%V +zv*d;^@XLRg&l$@zBokV}PTPHLw?G#{QN7~aB%79Zjc1=xN@cm^>Z`BjzyY;&pK{76 +zTzc8txc9!>`OMXyrn0h<>#nB8BsQFHY5iB8)TFbZ8vsW+K7vY+RbYv)2k*)_32?G%^h?d0>5yP*5kGFO( +zzNHnBGAW-|jXhrQA!8?NAzeAL`cGcsZW;z=GLD&ufniW39KKxk9MfYPbw?Q#{ECWy +z9s|BC8uXKswUD3)7=HS#3O@1qhgq>=1>g9_H)v{V;+Mbt319iTd4z9&`#T5$b6aBmajPl}zHoIZ*L-=D`?f=KmE^pWbr2({!b=&DTMME3 +zwG{E3WJQbM>I>jU4@kx{Q~-Aarve=(nt{x5dt?;E`};%u=9YF=E-R;HRyoZL2{MP< +zC`~95<3tQ%rXXrcHGL-30M6hj{O}KIAvJyRN(JjW@)gBi!f?4R1R}NkLk9VTt>-+_ +z_h$b0dYr$cB;9Lk +zKl!9MxBQ}tTkag=um0+4>g(&sWF%|O6xg=p+OPban{N6~a=9F%=@D#4a^X29AG)%V +z*)yUcBV4;W$+_z?JoJRkbx%PeDp@gGC@x;1kgtNRxOsC0Nj48T3oO)p`&b^vvXb^N +zZ9qM6E^y;K7BDdY03ZNKL_t)EW+17FP`u>%O~X9DY531RSmhOGQGLeA$H4d}hAbfj +zN?+sznqFc;#8nic6{A}|WryP*Pa5H1T?nD-FER+zBt@+N?y7TKBr2*AIK-<<$@GmP +zN(|(fgGd^bOjGSR1&`KT;wRr_=Pf5zR~di^2<94j{yOz2mBuc`Q>BVZfiZYE177YC +zoO^L^m4E4aPZ~0`AH?H=gY6cXjLqQS5GBb9{^Q?<86JYSzvJDcQYn7&lb^6=rQq*B +zSH+Y@6H~iyUMd)i2|oJ%6c0V2An_kR3OxF%s5{r3h#}S#@0;s>csf!_4z{P+-!{O@ +zFLtq~L?4?k&h(@i&V!37u4 +z+S_AiSYd5I{H}u?2DwZz@L8~|ugR3AXDC)6tpMbP%#@jkbG}jVIm4@d+iiIbOD(j-S +zPC{TzYG2g>f^eQAT?R)qq|9+ih0T)iZI4%%Vw4OZN({`1LIXKL7d8^R9Qj +z3n2va=g()xjF}7%k07Na7K`!8PkxfGeeG-9cF!2APECYvlb!;arr?})Np8DGO_jdm +zRF}vhqJEZ$Ls=B!F%_1}5lLxGF`bmggWBtOc%&$PA{vOlL^4?`)EF2qO%jhn)D%>e +zsD~c-I?uzh`E$LOxZK)t+!mwkQ$4m2Y6PhA}(9IfB#k*oH_DC{HysnI7 +zV}+lv>l|73uzLCxm#o1oQ?-u^qQhKOb_Y@VgOtioz{Q08!Es#OAKmYST0a&$a72p2$w^^}b1@q?3W5Wx3eWC`TrFy~b +zlI-5ALdl94T((ju^vx_{fp@Q?|FE32`Kn+Yv+M1IfqDH?Os5N>l^RLJR11`*N9Wi< +z&p%E8`>tQ={zBgJXR(Di)>N#V#5lBtX*=}Z@|c1}pWDND>ygRLIutU=NoPqzBfFBK +zLZcS13o(hVh5Cbn%ep-oNnUwN4P~=}S$*51B-QlD%THAz@t4N>`9SLT#Et&&Lf0~H +zUn$m^7)E)lA^zVw;Z!W}&KmsfF7k#tlX)$IYp%J5`Sa&<^2sN2&t1Ra+g~kZ`BH;) +zI?X3O@d;L}Sizn>d-&jcVt)QJ8P+l~D*3k?RVaDRNsvtFu(+GA7{MIRv0g>A#LkK6 +zL44)~U4IZD>WXw4Zb%+_C`E15Elt5q7Z#x`Ljl +zfhRXpws5AFOK97tw!p((b7%>1Q4X(d)4~uT$XK|4C$+X%d+^xg6h;w4v*SK-I~VAY +zC#N;={zMlSmiz&OyatrHpW}L1N852HAX9n*?tPY&s<XWBBmpAf3*P9=-rhWj_qDM~u*w~Z8TjoZ +z6b8~0m!`*SWoi&iNdLp#g-614Lc_N`O}>A)$ZJf3j%hKwNBZD>j?bS}oY=e963}r9 +z%}~@q9nV0HV^p``$}KxC*>rTtEIu`5kPDMHBV^vs*}}C>Z7Ndp7>*NMvZv$dEk2)> +zop7sa +z1B4+akSL%ThR%2x!XsojdDqKE9(9;^9RG6M1Y7@{x>}Q!rx-{H2M*?gD!zcN+jCs~ +zw|$&`K`+0#WdsQvY%g%{L+bi2I0 +zovYb_c(zMcu%|=uLQS?c$|9Im=um86 +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 +z8d-!R!_O6}n#vhC +zkPfcXaqJ)WI-aw)Gxnq=XRiR@(B46iwAzRk!ajx<|)lCa%&JVRL&y= +zL}L*u8dFqFDW~PsX3n^5Dd~YR`j3uqU|T28-WC*LKe|rPQm@U_IABE7=HXSzr7p+j +z*RbTIk!{B?bZ0~1)!?hWkj>Y~K#l;{0HUWi&ATt38w#^xB{7a}-~Hz|vIwXu6HKp# +zr`-EKvaOZMHA~c_otT7wR|w2x9HXw1(Py@k8P8HTy^50Z1a&j2IJm8oolhL1@8D1f +zv3k=x7xU)#FXyzkokZj88WLr3RnU~df(wf862tA{lM)P6vMhw6)wHC<&f9eF@27j; +zAQl#*d;1xB{3xT_`WfFnM7C{&+@Vnlof(`VOR=}-f=c@E(J{LB4bZWzheIzNW#7~7 +z?0jTDTkqS;uBY0_3}?xW<&loWjGLGd)n#D2p2HLZ(=b9jSK1tuTYm^T0QPM>NLfvi +zni=K1c*hdZ9<(L?i(ZF2(G6r6I18B7*_GqM +zbDNpcP~ztlX2fK4&?Y<77iuz`fNB*p>A02F>2)er-PR6rXpGUWJ}Or(#E3`363|+6 +zV{*n63YJC3{aZ=ZCK>7-<&N(@#dv>E6s(?6#@Qb@mGeHlirLGiQd*e|SLwA~*4B1q +zL*vx)e&4cehPu7jvX89pQy&0;^!N=b3|y4UJPXrGn>g-$AlG&YM55k}VIl +zGB!HS>{F-m@D0zi`-yf2x`&x{auXtA_>3j`VAjiz?B%iFYyn_aHC%m>L8>IU9y0=w +zsBpDIf+H1>)&XvT^LYG+lGsw<_WGD%5UoMv@sg +z&mZFcpTFRL)@Lsk)Rb$?j+!?xBSF4qm@+`LTpO{DvE=vlKrT4WZSJPb>&ZZFMN!k& +ze*a(h@E2DtqrhFvlSA3fioXV_s!C#3J$$l;O% +z(>`)BMm!dp&qjbOSoGYtf$s0$?jLW?X;WBv;Ub#n)?u0kw(AZ2+M`r-n8ECXbYt(J +z7fU7Pkj)l&@|Q2N>xqe-)=f)lXj<4n<&+fVHKmkPB#4#8h(;qg-Z9-B-gITGEyuwS +z22wccTw(?#@q|x6ZA%5=+ETLOilt;na*XwjF?eK{u6=#9zubkLb?9#!;pw)`2q9Sa +zu~TU|eFk<28JA>-vpoB&ElTTSYcD-+YivVHEjim^;hI@&x^ovBZdD#(<=Yn1)z;63 +z-|yh0wX;dpl={bO+tSJH-+9`<_J6!gFuPGqfby+EFa#wX)yh5@VRj)iG5K(0C^-lC +z`D?X^UrPhY0@ne5D}e_eJX?6a3#NojI!7T> +zAeU8Q8&&mXYJ62nB5r*oA`E&D3?d!L>F+z4jlbQ-ru)?DYhF-K)DXl|aaO(kB%Z!u +zGr|zmHdW9#tA@?@?4#%K5Xq_}5yPN;XBW4A{c(Q*{PkM|r?!X*lL=lcz9S`u6j=Gd +zbC?ljG-edC>B(zOhx%c2kb7(ao_ehovB_)u+68J +za?#bNv-TZJsjN@Au{r)i_bcWyO!#a|shwBwv^{jnmXc^JLd&XY%sp*7Q|8uE(U>Bc +zN?=Az3bsPHB8EZEb^^m95CC#qL-EKB^m>ZtxlExDG0)f{ZqgkwCepr`5rb$VLP>do +zSb3aORgy?Fg6Se{xDc=qf`gkn7)xhZ_x|Pd9U0{CrXE&Zv6xw>Hv8lgkywPCkM3vD +zIkT9%W(LW!IE74}R6`k64JkTycXRXCf;!z_o+CJSnaj;(iqPD@rSXRO9a`k$8mhv}C-$H`Mdv$Dr;k +zveydj#ju9Z3`#&{nZb&AuyLnkEDxEj`^k=sl3FyAj$b`M`mPPkUDM3vpIgV&d3Amg +zD2hMOMZXFf%r5xDY$?exZ8Nj(`2`)HAaV-mtOv5W`+Af2?KPw**{(Igm +zh?Sc>|2RAVzj!g!TJlj|MVg<s=Aai)9IY`gPb-z%7r +zpg8DQfe{#nPz%8h3()$*e1_mqm&4co)A6UvjJgy~Z<?5uSm@^%GYlL@ +zvg64%9{Kl|0?)BtaQ-rv_)TaABET+4-w>oDF-(COb@>SpC2NF=?|WuHfJ58zAc)J +z6JaSq%1Z>xXA5?X;Td2jU3@TXgru!L6I8(J`#Lb90 +zri+%@GN3+{Zk@$nz#=dXTS^>9`k|N%EqZmHHjpTbk*G}iVW3y^^ZC{vQ;**I~DLuRQX_I(GIf)TwxF{kK3BnBr%94VW +zErRX=iK|@3&PVssFtdWXrpoXG6Gg`1Edq}=$VI4pyVaTkJ!msu6oPr7PSjM3du(8w +zd%yn#y?Yc287+yh^sNh27(_s9Q4)S +z0316>L_t)-1L4z +zKi)rFCRp7fLeC9%Q}MMvJjzi=U`CXeQ642c>yb-OEDYKLez^gT1`X7ob=MVd1OrLC +zh}qcy>Cp`5oju)8k`rZd(t{S`gS|d&zlv2A2{Ufo8k#P1!ik%0gOyh|I}wFbXRG;v +zU7hL|c0SXN#AeFuTB1?YU!0ClD;hjdsWFlmlN1UIu9pdtd_wg8p220u3p{e&M*8=T +zu>4&M>DfC#X?=o|*3b3nbtDQIGdzPqc`*;d^}43Kh3kb;j(cvNN3dN;+75+k5Oo>w +zJwx)0&O4UW>N%drGKJO&pwX>5QqsAnm%G3B1U-9HmOP~lzIKIR@l;LC%Dq{J>G5^B +z&(aE_18_w-?QmVhv7nHdWQXm5I|FC6$qldM8^u5Xo(J9yRPWe5!jgp*%%2l*(Uw%D +zIJ#qRFaxc-WQkULa9y;oP9@xN%wT3fN{B^Z$xOkN3fSm!&$aLDrG0M~Q)bsvQl9V| +z{Q@~b;cMx53&e69-?QL{Gag*47P87Gq#xpVi)qV)d)W6_JM+$(&dKM`XY0LtscWgC +zW%YC-E^I8NbVE0_P(7A*!~40PDS1i13az4sf#s+j-}82U!Ob;l6(*_Ah!`qgDLA$( +zXApQAuUM##Yx)3#9wz4V7F!?Q%OgK|p2C>g?$^wQ&t52Kt_sMeh0DF=^LM!t5`JQC +z5F&>y$=BZAz>#J;P69DMVSe$`w8@8nga_Bl}u#B!7Ms{rxv;~iXn@k}Z!6mM@V +z8N;#@q>py`M8%<5^`g0TT_IOGZacIL(c@wWm{}({Z4R_`DDI?@-VB@mxQ|qAlA7iU +zBBtr*6%j+I+`pP>k0lL0kEXh-+XDIyHFIa2sJ +zR?IZXJGSdN6uj$&N=8u|i|}(ILb--SGSE4~)4zO)9S;VxNFP2^aOGNqR4kC*_K>L% +zsf!Fat-Sjq43}oeLjg_ozLf*3X!PE8;O0%x*6+V{J@B*tsYUxgX&?Y?z;s|)z98xA +zALZP2Q;9~^gDG#QVDLzq{Mc|vOD{xxHVNrBjtqk6w9=hqjxKNDZmVXA9i@ttU9NrIX6$a*`DZKU~}M%t1P~ +z^>Eh5R#H2wip*%9oquejwxyEhlN)J!?l6!1U?bU~JoDGiAW<4~*#iybm3(j@$UP!P +z03%Dc4&u`k3&T(1z3Z?Xg~&x*T0}3LGerP46nFfZ!XRo0zrk|PGY5I#+s`oEsoG{{ +zR>2o95uCA55OqT+GvLpq15Y2IjxK8H@_kvk$qR$ew!t5^hniq7do6md +zP80(HcpSI_sM@tRO;tsNm8aCXa$p8kQ|sv7a~Nd7PZIsPWX+p|kS&L>ykJq~-LWBN +z!bwvFC(nR`M`17ngPo(i{KtL7$|BS@R}hIs6k_A`UAf2c!zZ^mDBOh@i<(q6rFikS +z-Ryew0IB*CYNu6FC|Er5uNx_ADB<*XF2#%(IF`e<`}a{bqnt!4!NcDRMyD5_KZpG< +zcd+Nl{nRh0!!hvN$%Wg6>n&=_t+Evh_;}}JXvl*Qp0T+AgL{uGCm^}@iiHusja~h2 +z-=RSsyWx3u+#hhTUAac^$qNmpR0!2*=z0pr&HwZbOc*Nck~(tb_Y(;}M{#WB{j(zy +zS%gO&=!fq<8A>(Z$*WB3b0Qi@4%i5M05BhWx|^koDw*3-fdC@$C?&OZ^zLo*7kDTq +zDK4urxku621f|x&+E6JtV}YO|4x8O5_Tc6&+O`~~0fH8N>AF#k$_m4UZe8zDa8$j* +zc0G!t?S!e?QU<$+89bck;7dm_5(bH~INR=NW%=ccXqa8&0|Hy_-9tPTrE^ygV|^KB +zt)9YA$0&<0n9HU+wsZKU9!hJI)Xu0NCpCm=z0LS2;lbn+BtV!6H^*X)Es$v +z5+dac9X=dlALkf)Imd!Bba>d$OAN(MI)94bjCqjH!+}1?4CUGR}?B3RhJ-yAR09}+Sbd_ZT*b( +zW?262MWkxW=-l2*^U`{@-_?pR1w9A)S+u@I@ofcaaIRs78zrHr>)9oA@M;)dO-9A? +z($7PphC;F;hH6zeRXLyin~reb_nx9-v+8V!8Strd1XsSvpuR%*G6WuUtJB9yJ1|Nw +z5to|UZZX-UFa)Lx^Ja=#N-_nwVFT<5#-E-9KKNQz%uh4}0X3G}1S|)5@Xsdvjt10LfG@!wUA(7)eT$nHraHJGp<<1-j@zx=Ol|Snu{4TiJ7KiDU6!5J=@NlwbPh= +z+H}T;vh3f`!Ei^K^`BZzb#n!~9^TK?r43Xxq*Pv^6)n{)c~HRg>J?GL^y?q0Q^4`% +z2qLZyf<7%MT`0Nl&>%0|x|NN;+0JOM3a8$(7_L5FuzH?BTo(ZKG=y9Y6whOT2&DC7 +znA=KC3kn~l3K@q1V*^fzkh);Q?JvV00~+RG;2d6MDxcSrfjGdOz7>=a(zyL4av7HS!Ze_4t(e#|N06wu^wThG{f{jHXYud!1Es>50 +zRJUCfP){+;UszEQlA|`M}SiR +znj541?&ojjq=nUhAl;Yd>A> +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 +z*9z#EU)l=6SlBzN0UKu6PoF$RkiM<4O +zp_3Hj(qs&ij8*mb0uwn|51$qcydbnUx~vJdD&(07d6MKHMhY}^-_xid!9&#A)x%BJ +z)pa%M!o;|6>O35H1NOA~gfZ99{h2G_&KS%z1M%4BK6e3+pu_&PH!r~xy+E(9Wv#IO +zHp4A9s>rgRn*bqeNC;0PS9Wa0CLLk}wKk_1==e*`h6L^4kdQYWt;EJgn{|sn)4{Dg +ziyi*aOGN{+#GGYH5*4W*#GC`0D&VVCHyuUYKaV(8fk~+Tm6|CiSvDqw$#LP`cZ9)n +z&^rKqLoMe#f@8Lqol +zlFoX1QDY9$Y-%1+t!clcG2xQ-{4y)lMM;p&Mp9x<-ukJEhc}S1dQ8Io+_$yGP1HeK +zs%nZ{GaLUcpKr*N?^3pa_ne^^;hraJ2xo?cqbG!Cj>3g{%efwKM$ygxQG%y5kSm8F +z;KwMn;fv@#yUjr5@M$=FTChfVaD!p(ZHDEGTj&37BRmKqk# +zqaa4tn2^AX)g?Y|_QP?Enhi~k^QMF`Q|}F?GKteS`REutv@2)X0(gA84V9}f<>&Ge +z$%>1Hrv9A|qkKQaR$Ud&`pR3}eS!$}It*PDj-7!g_Y3b9*P7?R^T2O`Ke{A*R-rnJ +z4P+SATKYM#3U~l*KCU=^4vz0p_psrkuyK{)V@s6p6lWcr1gU$Q*V?s99;qC$jC?s! +z34fX6%(kmyHDkhEpmrqQAys%WNwP0VsAkY)+jsAcxb+Nh7sbPT@n%bZ0Yf}P*AVdU3SMcz-z#do%?HEzbE*qiZ1gFJ_ki^A(8N^v=S +zs^!`Hou~Lc@J4wRN)K{5h)e8`xSZvFQ~`1wV0s3iXFzZ2rcU8gx2tElz9Iz))Sw)g +zM+R)5m8ZEy9`l!}iYvAfy@8$59cN01+*X{Y$Xv4RLcBbKk+;#jqF*@Fs)s%aJc|lK +z@8t?FqbUt!W?>X1MeYPvxbSN$uo|Fe5PAmnwtjvkZ0J;m?fkh~*41%ZPpvnhVikH4 +zQY8I(3VztpXk){$IT0rr4M~?jkBPaKko6aw9~B192)+Ll`cAeyR}TEmg;0N(spZ)+ +z#QNZHhx063Nrt!psusSy2G(^NKGI +zrvGd)kMVzgXIu%7`(6?D4P4eU9&}ZxZl)n=ur!eAiFK|Dc0bTju%g9q-<^il%T(et +zMW{6S(rqS8G~t0ALg$U}(`}ZvIVSX0!ius)mBn+&hA#?zC*bK9h0)fI#H*+P#_!6! +zq71P<2pn{uN6`6{hk*NlO8+qQ?-drb!N$FgQ>fZ`;+Vs1uAxc$o +zn_<({(0LC38qpAHPwR&8w_W)3YqX&!<$qJ@L9Qm;=0d!%zBQ;kC2Eb4P`qftC>J1>je})6BwtMQI?@4;ED=|E}{Y +z7F2O``@M$GbQ$K&i4`iz;o%)QOK*TjAGA8VQFZ0xOviQqbV%4Y*y1gI1MEN<%_aWF +zsFX)=#UQ}zF8<%`3}mH1+mVyddrVk#9o%$-p{-5dQ!ftchTe@UP1q1S^cL*ipYw~q +z!pT@~IsyF1d8%iCH_PKL4P-jwEwtaT6L=3;RnNHQ@2|m$Az^uk4tBkCQsqZK-DPOx +z@Ryf_A3i0#8VTeFfbTi4bP(-hlqfOdFc%#YKIJ@(e1Ef%uYLl#w-ed*Z7XYUDQsli +z3w*Xbwi2@q?amvV2c&9|o3BR}vLF;);w$B`lqgZeCg3~3 +eobo8H4*VC(Unzh*$|>Fe0000O + +literal 14310 +zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c +zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 +z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez +za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ +zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc +zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 +z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C +z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj +z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO +zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq +zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP +zJxwXvt5fFTCOVgB)Zq +z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( +z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 +zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP +zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN +zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| +z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK +z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf +zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l +z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP +zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 +z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! +zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! +zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX +z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A +z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# +zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x +zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 +zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk +z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B +zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| +zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx +z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE +zllqxy +z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t +z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W +z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); +zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} +z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX +z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx +z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% +zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v +zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< +zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A +zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h +zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- +zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< +zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS +z4&$M&7(|(9nWY%QShCnuN0 +z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm +zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ +z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 +zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; +z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; +z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC +z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> +zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg +zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> +zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k +zL^tBOHF^=)k&U-Tw{gfijqQ&^ +z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 +z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X +z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 +zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( +zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY +zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU +zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ +z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ +z1IGS^Z5t=0Zj86J2MfJc +zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 +z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 +z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf +zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) +z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd +z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= +z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 +z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 +zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA +zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH +zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ +z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< +zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ +zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf +zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- +zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= +zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G +z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp +zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x +zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 +z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN +zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl +z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh +zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; +z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ +zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK +zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! +zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ +z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X +zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* +zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 +zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH +z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw +z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G +z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv +zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L +z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H +zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% +zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz +z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| +zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP +zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 +zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty +zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n +z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 +zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo +zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF +zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V +zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% +zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W +z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 +zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy +zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 +z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 +zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd +zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m +z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I +z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe +zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA +zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` +zh~ggr^knneWU!Nn}AQt=0Id6Hk; +z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# +zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 +z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< +zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r +z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN +zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D +z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk +zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq +z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ +z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ +zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl +zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH +z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif +z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) +zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf +zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m +zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< +zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I +z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 +zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} +zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` + diff --git a/patches/server/0002-Add-SoundEvent.patch b/patches/server/0002-Add-SoundEvent.patch new file mode 100644 index 0000000..454eb5a --- /dev/null +++ b/patches/server/0002-Add-SoundEvent.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 19 Jun 2021 16:30:39 -0400 +Subject: [PATCH] Add SoundEvent + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index f893d8ab74293feec6ef69c5a4ddec57b11ca751..d6dbd903316ec16088ce7022b173285cd2fe80cd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -55,8 +55,8 @@ import net.minecraft.network.protocol.game.ClientboundExplodePacket; + import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; + import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; +-import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; +-import net.minecraft.network.protocol.game.ClientboundSoundPacket; ++//import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; // Parchment ++//import net.minecraft.network.protocol.game.ClientboundSoundPacket; // Parchment + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.MCUtil; +@@ -1335,12 +1335,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + @Override + public void playSound(@Nullable Player player, double x, double y, double z, SoundEvent sound, SoundSource category, float volume, float pitch) { +- this.server.getPlayerList().broadcast(player, x, y, z, volume > 1.0F ? (double) (16.0F * volume) : 16.0D, this.dimension(), new ClientboundSoundPacket(sound, category, x, y, z, volume, pitch)); ++ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(player == null ? null : player.getBukkitEntity(), getWorld(), new org.bukkit.util.Vector(x, y, z), org.bukkit.craftbukkit.CraftSound.getBukkit(sound), org.bukkit.SoundCategory.valueOf(category.name()), volume, pitch), this.server, volume > 1.0F ? (double) (16.0F * volume) : 16.0D); // Parchment + } + + @Override + public void playSound(@Nullable Player player, Entity entity, SoundEvent sound, SoundSource category, float volume, float pitch) { +- this.server.getPlayerList().broadcast(player, entity.getX(), entity.getY(), entity.getZ(), volume > 1.0F ? (double) (16.0F * volume) : 16.0D, this.dimension(), new ClientboundSoundEntityPacket(sound, category, entity, volume, pitch)); ++ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.EntitySoundEvent(player == null ? null : player.getBukkitEntity(), entity.getBukkitEntity(), org.bukkit.craftbukkit.CraftSound.getBukkit(sound), org.bukkit.SoundCategory.valueOf(category.name()), volume, pitch), this.server, volume > 1.0F ? (double) (16.0F * volume) : 16.0D); // Parchment + } + + @Override +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 53f6a45a505725c81ab15bd2daa1c61b024f1d68..bbe27b5334578e547eefd8eaca3d2ce23d3ff854 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -67,7 +67,7 @@ import net.minecraft.network.protocol.game.ClientboundRespawnPacket; + import net.minecraft.network.protocol.game.ClientboundSetCameraPacket; + import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; + import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; +-import net.minecraft.network.protocol.game.ClientboundSoundPacket; ++//import net.minecraft.network.protocol.game.ClientboundSoundPacket; // Parchment + import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; + import net.minecraft.resources.ResourceKey; +@@ -2134,7 +2134,7 @@ public class ServerPlayer extends Player { + + @Override + public void playNotifySound(SoundEvent event, SoundSource category, float volume, float pitch) { +- this.connection.send(new ClientboundSoundPacket(event, category, this.getX(), this.getY(), this.getZ(), volume, pitch)); ++ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(getBukkitEntity(), org.bukkit.craftbukkit.CraftSound.getBukkit(event), org.bukkit.SoundCategory.valueOf(category.name()), volume, pitch), this); // Parchment + } + + @Override +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index bc3fe18dd32da2d381b9546aae675a475c073696..fae458c2ec53e8663536c183d2487a2a6041d24e 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -58,7 +58,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; + import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; + import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +-import net.minecraft.network.protocol.game.ClientboundSoundPacket; ++//import net.minecraft.network.protocol.game.ClientboundSoundPacket; // Parchment + import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; +@@ -951,7 +951,7 @@ public abstract class PlayerList { + if (flag2 && !isLocAltered) { + BlockState data = worldserver1.getBlockState(blockposition); + worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); +- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); ++ entityplayer1.playNotifySound(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, 1.0F, 1.0F); // Parchment + // Paper end + } + // Added from changeDimension +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index d286d88a3c3f93dbfa92de9421e320c92cd96350..eea377ccf09afd2c175041bdd8226e1009fe6914 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -30,7 +30,7 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; +-import net.minecraft.network.protocol.game.ClientboundSoundPacket; ++//import net.minecraft.network.protocol.game.ClientboundSoundPacket; // Parchment + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +@@ -1824,7 +1824,7 @@ public abstract class Player extends LivingEntity { + private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { + fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself + if (fromEntity instanceof ServerPlayer) { +- ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch)); ++ CraftEventFactory.playSoundEvent(new me.lexikiq.event.sound.LocationNamedSoundEvent(fromEntity.getBukkitEntity(), new org.bukkit.util.Vector(x, y, z), org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect), org.bukkit.SoundCategory.valueOf(soundCategory.name()), volume, pitch), (ServerPlayer) fromEntity); // Parchment + } + } + // Paper end +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java +index a79ba23ecf887ecbb6e095140f019ebb6fd0a6f7..5112edc5e68a386e9bb16ac0ec9d998e7df06f3c 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raid.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java +@@ -27,7 +27,7 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; +-import net.minecraft.network.protocol.game.ClientboundSoundPacket; ++//import net.minecraft.network.protocol.game.ClientboundSoundPacket; // Parchment + import net.minecraft.server.level.ServerBossEvent; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -537,7 +537,7 @@ public class Raid { + double d2 = vec3d.z + 13.0D / d0 * (vec3d1.z - vec3d.z); + + if (d0 <= 64.0D || collection.contains(entityplayer)) { +- entityplayer.connection.send(new ClientboundSoundPacket(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, d1, entityplayer.getY(), d2, 64.0F, 1.0F)); ++ entityplayer.playNotifySound(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, 64.0F, 1.0F); // Parchment + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 71571868090062f02579d50ae483d9f367de5016..e94fc60cd34678d7ce052e70728040f9999a9d00 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -1835,4 +1835,77 @@ public class CraftEventFactory { + return event.callEvent(); + } + // Paper end ++ ++ // Parchment start ++ private static net.minecraft.network.protocol.Packet handleSoundEvent(me.lexikiq.event.sound.SoundEvent _event) { ++ if (!_event.callEvent()) { ++ return null; ++ } else { ++ float volume = _event.getVolume(); ++ float pitch = _event.getPitch(); ++ net.minecraft.sounds.SoundSource source = net.minecraft.sounds.SoundSource.valueOf(_event.getCategory().name()); ++ ++ if (_event instanceof me.lexikiq.event.sound.NamedSoundEvent namedSoundEvent) { ++ net.minecraft.sounds.SoundEvent sound = org.bukkit.craftbukkit.CraftSound.getSoundEffect(namedSoundEvent.getSound()); ++ ++ if (_event instanceof me.lexikiq.event.sound.LocationNamedSoundEvent event) { ++ org.bukkit.util.Vector pos = event.getVector(); ++ return new net.minecraft.network.protocol.game.ClientboundSoundPacket(sound, source, pos.getX(), pos.getY(), pos.getZ(), volume, pitch); ++ } else { ++ me.lexikiq.event.sound.EntitySoundEvent event = (me.lexikiq.event.sound.EntitySoundEvent) _event; ++ return new net.minecraft.network.protocol.game.ClientboundSoundEntityPacket(sound, source, ((CraftEntity) event.getOrigin()).getHandle(), volume, pitch); ++ } ++ } else { ++ me.lexikiq.event.sound.LocationCustomSoundEvent event = (me.lexikiq.event.sound.LocationCustomSoundEvent) _event; ++ org.bukkit.util.Vector pos = event.getVector(); ++ return new net.minecraft.network.protocol.game.ClientboundCustomSoundPacket(CraftNamespacedKey.toMinecraft(event.getKey()), source, org.bukkit.craftbukkit.util.CraftVector.toNMS(pos), volume, pitch); ++ } ++ } ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, java.util.function.Consumer> soundPlayer) { ++ org.apache.commons.lang3.Validate.notNull(event, "event"); ++ org.apache.commons.lang3.Validate.notNull(soundPlayer, "soundPlayer"); ++ if (!(event instanceof me.lexikiq.event.sound.LocationNamedSoundEvent || event instanceof me.lexikiq.event.sound.LocationCustomSoundEvent || event instanceof me.lexikiq.event.sound.EntitySoundEvent)) { ++ throw new IllegalArgumentException("Unknown sound event: " + event.getClass().getName()); ++ } ++ java.util.concurrent.CompletableFuture.supplyAsync(() -> handleSoundEvent(event), net.minecraft.server.MCUtil.asyncExecutor).thenAcceptAsync(packet -> { ++ if (packet != null) ++ soundPlayer.accept(packet); ++ }, net.minecraft.server.MCUtil.asyncExecutor); ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, CraftPlayer sendTo) { ++ playSoundEvent(event, sendTo.getHandle()); ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, ServerPlayer sendTo) { ++ playSoundEvent(event, sendTo.connection); ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, net.minecraft.server.network.ServerPlayerConnection sendTo) { ++ playSoundEvent(event, sendTo::send); ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, net.minecraft.server.MinecraftServer server, double radius) { ++ playSoundEvent(event, server.getPlayerList(), radius); ++ } ++ ++ public static void playSoundEvent(me.lexikiq.event.sound.SoundEvent event, net.minecraft.server.players.PlayerList playerList, double radius) { ++ final net.minecraft.world.entity.player.Player player = event.getPlayer() == null ? null : ((org.bukkit.craftbukkit.entity.CraftHumanEntity) event.getPlayer()).getHandle(); ++ final net.minecraft.resources.ResourceKey world = ((CraftWorld) event.getWorld()).getHandle().dimension(); ++ final org.bukkit.util.Vector pos; ++ if (event instanceof me.lexikiq.HasLocation hasLoc) { ++ pos = hasLoc.getLocation().toVector(); ++ } else if (event instanceof me.lexikiq.event.sound.EntitySoundEvent entityEvent) { ++ pos = entityEvent.getOrigin().getLocation().toVector(); ++ } else { ++ throw new IllegalArgumentException("Could not determine location of sound event"); ++ } ++ final double posX = pos.getX(); ++ final double posY = pos.getY(); ++ final double posZ = pos.getZ(); ++ playSoundEvent(event, packet -> playerList.broadcast(player, posX, posY, posZ, radius, world, packet)); ++ } ++ // Parchment end + } diff --git a/patches/server/0003-Add-PlayerUseRespawnAnchorEvent.patch b/patches/server/0003-Add-PlayerUseRespawnAnchorEvent.patch new file mode 100644 index 0000000..55e0109 --- /dev/null +++ b/patches/server/0003-Add-PlayerUseRespawnAnchorEvent.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Sat, 19 Jun 2021 01:14:13 -0400 +Subject: [PATCH] Add PlayerUseRespawnAnchorEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java +index af4eb4a8814491afef449a2874521636957d7557..93fae52a7531e1697e4fa63c82aef6ef24d0fb25 100644 +--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableList.Builder; + import java.util.Optional; + import java.util.Random; ++import me.lexikiq.event.player.PlayerUseRespawnAnchorEvent; // Parchment + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; +@@ -52,33 +53,51 @@ public class RespawnAnchorBlock extends Block { + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + ItemStack itemStack = player.getItemInHand(hand); ++ ++ // Parchment start -- PlayerUseRespawnAnchorEvent ++ org.bukkit.entity.Player bukkitPlayer = player.getBukkitEntity() instanceof org.bukkit.entity.Player ? (org.bukkit.entity.Player) player.getBukkitEntity() : null; ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); ++ PlayerUseRespawnAnchorEvent.RespawnAnchorResult result; + if (hand == InteractionHand.MAIN_HAND && !isRespawnFuel(itemStack) && isRespawnFuel(player.getItemInHand(InteractionHand.OFF_HAND))) { + return InteractionResult.PASS; + } else if (isRespawnFuel(itemStack) && canBeCharged(state)) { ++ result = PlayerUseRespawnAnchorEvent.RespawnAnchorResult.CHARGE; ++ } else if (state.getValue(CHARGE) == 0) { ++ result = PlayerUseRespawnAnchorEvent.RespawnAnchorResult.NOTHING; ++ } else if (!canSetSpawn(world) && !world.isClientSide) { ++ result = PlayerUseRespawnAnchorEvent.RespawnAnchorResult.EXPLODE; ++ } else if (!world.isClientSide) { ++ result = PlayerUseRespawnAnchorEvent.RespawnAnchorResult.SET_SPAWN; ++ } else { ++ return InteractionResult.SUCCESS; ++ } ++ ++ if (bukkitPlayer != null) { ++ PlayerUseRespawnAnchorEvent event = new PlayerUseRespawnAnchorEvent(bukkitPlayer, block, result); ++ event.callEvent(); ++ result = event.getResult(); ++ } ++ ++ if (result == PlayerUseRespawnAnchorEvent.RespawnAnchorResult.NOTHING) { ++ return InteractionResult.PASS; ++ } else if (result == PlayerUseRespawnAnchorEvent.RespawnAnchorResult.CHARGE) { + charge(world, pos, state); + if (!player.getAbilities().instabuild) { + itemStack.shrink(1); + } + + return InteractionResult.sidedSuccess(world.isClientSide); +- } else if (state.getValue(CHARGE) == 0) { +- return InteractionResult.PASS; +- } else if (!canSetSpawn(world)) { +- if (!world.isClientSide) { +- this.explode(state, world, pos); +- } +- +- return InteractionResult.sidedSuccess(world.isClientSide); ++ } else if (result == PlayerUseRespawnAnchorEvent.RespawnAnchorResult.EXPLODE) { ++ this.explode(state, world, pos); ++ return InteractionResult.CONSUME; + } else { +- if (!world.isClientSide) { +- ServerPlayer serverPlayer = (ServerPlayer)player; +- if (serverPlayer.getRespawnDimension() != world.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) { +- serverPlayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true); +- world.playSound((Player)null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); +- return InteractionResult.SUCCESS; +- } ++ ServerPlayer serverPlayer = (ServerPlayer)player; ++ if (serverPlayer.getRespawnDimension() != world.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) { ++ serverPlayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true); ++ world.playSound((Player)null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); ++ return InteractionResult.SUCCESS; + } +- ++ // Parchment end + return InteractionResult.CONSUME; + } + } diff --git a/patches/server/0004-Add-origin-location-to-EntityDamageByBlockEvent.patch b/patches/server/0004-Add-origin-location-to-EntityDamageByBlockEvent.patch new file mode 100644 index 0000000..66353d6 --- /dev/null +++ b/patches/server/0004-Add-origin-location-to-EntityDamageByBlockEvent.patch @@ -0,0 +1,178 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Fri, 18 Jun 2021 14:04:39 -0400 +Subject: [PATCH] Add origin location to EntityDamageByBlockEvent + + +diff --git a/src/main/java/net/minecraft/world/damagesource/BadRespawnPointDamage.java b/src/main/java/net/minecraft/world/damagesource/BadRespawnPointDamage.java +index f5a18fb39eb69b2a9842d3f96aa1cd6a8dff6d9b..456d93305f524da6142bad320edb817b27c6c1e6 100644 +--- a/src/main/java/net/minecraft/world/damagesource/BadRespawnPointDamage.java ++++ b/src/main/java/net/minecraft/world/damagesource/BadRespawnPointDamage.java +@@ -9,12 +9,20 @@ import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.world.entity.LivingEntity; + + public class BadRespawnPointDamage extends DamageSource { ++ @Deprecated // Parchment + protected BadRespawnPointDamage() { + super("badRespawnPoint"); + this.setScalesWithDifficulty(); + this.setExplosion(); + } + ++ // Parchment start ++ protected BadRespawnPointDamage(org.bukkit.Location location) { ++ this(); ++ location(location); ++ } ++ // Parchment end ++ + @Override + public Component getLocalizedDeathMessage(LivingEntity entity) { + Component component = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("death.attack.badRespawnPoint.link")).withStyle((style) -> { +diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +index 80d19af2ad423bd3de0e039c5bb8f97af536aaa9..2cafb9edf4020c0b8d747dbb4ff91d7759bcd8c3 100644 +--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java ++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java +@@ -64,6 +64,18 @@ public class DamageSource { + return this; + } + // CraftBukkit end ++ // Parchment start ++ private @Nullable org.bukkit.Location location; ++ ++ public @Nullable org.bukkit.Location getLocation() { ++ return location; ++ } ++ ++ public DamageSource location(@Nullable org.bukkit.Location location) { ++ this.location = location; ++ return this; ++ } ++ // Parchment end + + public static DamageSource sting(LivingEntity attacker) { + return new EntityDamageSource("sting", attacker); +@@ -114,17 +126,24 @@ public class DamageSource { + } + + public static DamageSource explosion(@Nullable Explosion explosion) { +- return DamageSource.explosion(explosion != null ? explosion.getSourceMob() : null); ++ return DamageSource.explosion(explosion != null ? explosion.getSourceMob() : null).location(explosion != null ? explosion.getBukkitLocation() : null); // Parchment + } + + public static DamageSource explosion(@Nullable LivingEntity attacker) { + return attacker != null ? (new EntityDamageSource("explosion.player", attacker)).setScalesWithDifficulty().setExplosion() : (new DamageSource("explosion")).setScalesWithDifficulty().setExplosion(); + } + ++ @Deprecated // Parchment + public static DamageSource badRespawnPointExplosion() { + return new BadRespawnPointDamage(); + } + ++ // Parchment start ++ public static DamageSource badRespawnPointExplosion(org.bukkit.Location location) { ++ return new BadRespawnPointDamage(location); ++ } ++ // Parchment end ++ + public String toString() { + return "DamageSource (" + this.msgId + ")"; + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index c98202092752a9015aaf95bd1471135b88e84425..3acdb4d8ab90af1919a190502d6295559c78e041 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -101,10 +101,11 @@ public class EnderDragon extends Mob implements Enemy { + private final Node[] nodes = new Node[24]; + private final int[] nodeAdjacency = new int[24]; + private final BinaryHeap openSet = new BinaryHeap(); +- private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() ++ private Explosion explosionSource; // Parchment - moved into constructor to fix null world + + public EnderDragon(EntityType entitytypes, Level world) { + super(EntityType.ENDER_DRAGON, world); ++ explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource() // Parchment - fix null world + this.subEntities = new EnderDragonPart[]{this.head, this.neck, this.body, this.tail1, this.tail2, this.tail3, this.wing1, this.wing2}; + this.setHealth(this.getMaxHealth()); + this.noPhysics = true; +diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java +index 822a8dbfaea0a312c4eb2849f2386ecd401b13e9..e5632b4e763076730768fd627610ccdb90be7137 100644 +--- a/src/main/java/net/minecraft/world/level/Explosion.java ++++ b/src/main/java/net/minecraft/world/level/Explosion.java +@@ -453,6 +453,13 @@ public class Explosion { + return this.toBlow; + } + ++ // Parchment start ++ public @Nullable Location getBukkitLocation() { ++ if (this.level == null) return null; ++ return new Location(level.getWorld(), x, y, z); ++ } ++ // Parchment end ++ + public static enum BlockInteraction { + + NONE, BREAK, DESTROY; +diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java +index 163a7861f987c3832aac51cc6df950c768546731..1bd2d982569c6cd8a65f1f4c58d41a0e4a14e686 100644 +--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java +@@ -146,7 +146,10 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock + world.removeBlock(blockposition1, false); + } + +- world.explode((Entity) null, DamageSource.badRespawnPointExplosion(), (ExplosionDamageCalculator) null, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0F, true, Explosion.BlockInteraction.DESTROY); ++ // Parchment start ++ org.bukkit.Location location = new org.bukkit.Location(world.getWorld(), blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D); ++ world.explode((Entity) null, DamageSource.badRespawnPointExplosion(location), (ExplosionDamageCalculator) null, location.getX(), location.getY(), location.getZ(), 5.0F, true, Explosion.BlockInteraction.DESTROY); ++ // Parchment end + return InteractionResult.SUCCESS; + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java +index 93fae52a7531e1697e4fa63c82aef6ef24d0fb25..2620b42f7a6088aaecf3ccf8f05c5f4d5a4038f0 100644 +--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -139,7 +139,10 @@ public class RespawnAnchorBlock extends Block { + return pos.equals(explodedPos) && bl2 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState); + } + }; +- world.explode((Entity)null, DamageSource.badRespawnPointExplosion(), explosionDamageCalculator, (double)explodedPos.getX() + 0.5D, (double)explodedPos.getY() + 0.5D, (double)explodedPos.getZ() + 0.5D, 5.0F, true, Explosion.BlockInteraction.DESTROY); ++ // Parchment start ++ org.bukkit.Location location = new org.bukkit.Location(world.getWorld(), explodedPos.getX() + 0.5D, explodedPos.getY() + 0.5D, explodedPos.getZ() + 0.5D); ++ world.explode((Entity)null, DamageSource.badRespawnPointExplosion(location), explosionDamageCalculator, location.getX(), location.getY(), location.getZ(), 5.0F, true, Explosion.BlockInteraction.DESTROY); ++ // Parchment end + } + + public static boolean canSetSpawn(Level world) { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index e94fc60cd34678d7ce052e70728040f9999a9d00..5f5836c69ad437c3fc801dab032aa0c27d76b71e 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -934,7 +934,7 @@ public class CraftEventFactory { + CraftEventFactory.entityDamage = null; + EntityDamageEvent event; + if (damager == null) { +- event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions); ++ event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, source.getLocation(), modifiers, modifierFunctions); // Parchment - add location + } else if (entity instanceof EnderDragon && /*PAIL FIXME ((EntityEnderDragon) entity).target == damager*/ false) { + event = new EntityDamageEvent(entity.getBukkitEntity(), DamageCause.ENTITY_EXPLOSION, modifiers, modifierFunctions); + } else { +@@ -970,7 +970,7 @@ public class CraftEventFactory { + + return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, modifiers, modifierFunctions, cancelled); + } else if (source == DamageSource.OUT_OF_WORLD) { +- EntityDamageEvent event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.VOID, modifiers, modifierFunctions); ++ EntityDamageEvent event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.VOID, entity.getBukkitEntity().getLocation(), modifiers, modifierFunctions); // Parchment + event.setCancelled(cancelled); + CraftEventFactory.callEvent(event); + if (!event.isCancelled()) { +@@ -978,7 +978,7 @@ public class CraftEventFactory { + } + return event; + } else if (source == DamageSource.LAVA) { +- EntityDamageEvent event = (new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.LAVA, modifiers, modifierFunctions)); ++ EntityDamageEvent event = (new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.LAVA, entity.getBukkitEntity().getLocation().toBlockLocation(), modifiers, modifierFunctions)); // Parchment + event.setCancelled(cancelled); + CraftEventFactory.callEvent(event); + if (!event.isCancelled()) { diff --git a/patches/server/0005-Add-UnsafeValues-canPlaceItemOn.patch b/patches/server/0005-Add-UnsafeValues-canPlaceItemOn.patch new file mode 100644 index 0000000..ac99111 --- /dev/null +++ b/patches/server/0005-Add-UnsafeValues-canPlaceItemOn.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lexikiq +Date: Fri, 18 Jun 2021 03:18:47 -0400 +Subject: [PATCH] Add UnsafeValues#canPlaceItemOn + + +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index a2a62bfb747994c43b8b0b607af90d3be2836873..57ccac39c2c8b8a5c6d9a317ab514b337f7491ef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -512,6 +512,55 @@ public final class CraftMagicNumbers implements UnsafeValues { + } + // Paper end + ++ // Parchment start ++ @Override ++ public java.util.concurrent.CompletableFuture canPlaceItemOn(ItemStack item, me.lexikiq.OptionalHumanEntity player, org.bukkit.block.Block block, org.bukkit.block.BlockFace face) { ++ org.apache.commons.lang3.Validate.notNull(item, "item"); ++ org.apache.commons.lang3.Validate.notNull(block, "block"); ++ org.apache.commons.lang3.Validate.notNull(face, "face"); ++ org.bukkit.entity.HumanEntity human = player == null ? null : player.getPlayer(); ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); ++ if (block.getType().isEmpty() || block.isLiquid()) { ++ future.complete(false); ++ return future; ++ } else if (!face.isCartesian()) { ++ throw new IllegalArgumentException("face must be cartesian"); ++ } ++ ++ ++ net.minecraft.world.entity.player.Player nmsPlayer = human == null ? null : ((org.bukkit.craftbukkit.entity.CraftHumanEntity) human).getHandle(); ++ CraftBlock cBlock = (CraftBlock) block; ++ CraftBlock relativeBlock = (CraftBlock) block.getRelative(face); ++ if (!relativeBlock.isReplaceable()) { ++ future.complete(false); ++ return future; ++ } ++ ++ org.bukkit.Location playerLoc = human != null ? human.getLocation() : relativeBlock.getLocation(); ++ net.minecraft.core.Direction dir = net.minecraft.core.Direction.valueOf(face.name()); ++ net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); ++ Item nmsItem = nmsStack.getItem(); ++ if (!(nmsItem instanceof net.minecraft.world.item.BlockItem blockItem)) { ++ future.complete(false); ++ return future; ++ } ++ ++ net.minecraft.world.item.context.BlockPlaceContext context = new net.minecraft.world.item.context.BlockPlaceContext(new net.minecraft.world.item.context.UseOnContext(cBlock.getCraftWorld().getHandle(), nmsPlayer, net.minecraft.world.InteractionHand.MAIN_HAND, nmsStack, new net.minecraft.world.phys.BlockHitResult(CraftVector.toNMS(playerLoc.toVector()), dir, cBlock.getPosition(), false))); ++ context = blockItem.updatePlacementContext(context); ++ if (context == null) { ++ future.complete(false); ++ return future; ++ } ++ BlockState blockState = blockItem.getBlock().getStateForPlacement(context); ++ if (blockState == null) { ++ future.complete(false); ++ return future; ++ } ++ final net.minecraft.world.item.context.BlockPlaceContext ctx = context; ++ return future.completeAsync(() -> blockItem.canPlace(ctx, blockState), net.minecraft.server.MCUtil.MAIN_EXECUTOR); ++ } ++ // Parchment end ++ + /** + * This helper class represents the different NBT Tags. + *