diff --git a/gradle.properties b/gradle.properties index 36dfbe297..4ee1bcb0d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ group = org.purpurmc.purpur version = 1.19-R0.1-SNAPSHOT -paperCommit = a9c507310b02836e37d5d1e3ed9ba9620289fdb1 +paperCommit = b1f5e70075fa956e1a70bd1311c72a705896e88d org.gradle.caching = true org.gradle.parallel = true diff --git a/patches/api/0032-Add-enchantment-target-for-bows-and-crossbows.patch b/patches/api/0031-Add-enchantment-target-for-bows-and-crossbows.patch similarity index 100% rename from patches/api/0032-Add-enchantment-target-for-bows-and-crossbows.patch rename to patches/api/0031-Add-enchantment-target-for-bows-and-crossbows.patch diff --git a/patches/api/0031-Conflict-on-change-for-adventure-deprecations.patch b/patches/api/0031-Conflict-on-change-for-adventure-deprecations.patch deleted file mode 100644 index 7c6ef90c9..000000000 --- a/patches/api/0031-Conflict-on-change-for-adventure-deprecations.patch +++ /dev/null @@ -1,867 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 17 Mar 2021 15:56:47 -0500 -Subject: [PATCH] Conflict on change for adventure deprecations - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index cd7e04aa1de8f051ff4bb23f36912830ab573987..9ff99a1ea5183042d7eea89bb310386c6630663a 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -415,7 +415,7 @@ public final class Bukkit { - * @return the number of players - * @deprecated in favour of {@link Server#broadcast(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public static int broadcastMessage(@NotNull String message) { - return server.broadcastMessage(message); - } -@@ -1194,7 +1194,7 @@ public final class Bukkit { - * @return number of message recipients - * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public static int broadcast(@NotNull String message, @NotNull String permission) { - return server.broadcast(message, permission); - } -@@ -1530,7 +1530,7 @@ public final class Bukkit { - * - * @see InventoryType#isCreatable() - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { - return server.createInventory(owner, type, title); -@@ -1580,7 +1580,7 @@ public final class Bukkit { - * @throws IllegalArgumentException if the size is not a multiple of 9 - * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException { - return server.createInventory(owner, size, title); -@@ -1607,7 +1607,7 @@ public final class Bukkit { - * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public static Merchant createMerchant(@Nullable String title) { - return server.createMerchant(title); - } -@@ -1731,7 +1731,7 @@ public final class Bukkit { - * @deprecated in favour of {@link #motd()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public static String getMotd() { - return server.getMotd(); - } -@@ -1753,7 +1753,7 @@ public final class Bukkit { - * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public static String getShutdownMessage() { - return server.getShutdownMessage(); - } -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index cc026cbb487244851f8f58b763655a583c7b32e5..226dd08c1001c664d60f45a6d9370077f4b8c574 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -327,7 +327,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return the number of players - * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public int broadcastMessage(@NotNull String message); - - // Paper start -@@ -973,7 +973,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return number of message recipients - * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public int broadcast(@NotNull String message, @NotNull String permission); - // Paper start - /** -@@ -1286,7 +1286,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * - * @see InventoryType#isCreatable() - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); - -@@ -1330,7 +1330,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @throws IllegalArgumentException if the size is not a multiple of 9 - * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; - -@@ -1353,7 +1353,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - Merchant createMerchant(@Nullable String title); - - /** -@@ -1456,7 +1456,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @deprecated in favour of {@link #motd()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getMotd(); - - // Paper start -@@ -1474,7 +1474,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getShutdownMessage(); - - /** -diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java -index c8d37184d8e882a4084a1bfef85faa330588600b..46bae5c13ce2b973b114682f6a338981eb8d95bf 100644 ---- a/src/main/java/org/bukkit/block/Sign.java -+++ b/src/main/java/org/bukkit/block/Sign.java -@@ -48,7 +48,7 @@ public interface Sign extends TileState, Colorable { - * @deprecated in favour of {@link #lines()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String[] getLines(); - - /** -@@ -62,7 +62,7 @@ public interface Sign extends TileState, Colorable { - * @deprecated in favour of {@link #line(int)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getLine(int index) throws IndexOutOfBoundsException; - - /** -@@ -76,7 +76,7 @@ public interface Sign extends TileState, Colorable { - * @throws IndexOutOfBoundsException If the index is out of the range 0..3 - * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; - - /** -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 4f1213d5c5efb2c415eb22b927936eb932ed3a4a..935220b5fa5015def0c9c2f4b7772a72220d3c34 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -73,7 +73,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @return the friendly name - * @deprecated in favour of {@link #displayName()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - public String getDisplayName(); - -@@ -87,7 +87,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param name The new display name. - * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setDisplayName(@Nullable String name); - - // Paper start -@@ -128,7 +128,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @deprecated in favour of {@link #playerListName()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getPlayerListName(); - - /** -@@ -139,7 +139,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param name new player list name - * @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setPlayerListName(@Nullable String name); - - /** -@@ -148,7 +148,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @return player list header or null - * @deprecated in favour of {@link #playerListHeader()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @Nullable - public String getPlayerListHeader(); - -@@ -158,7 +158,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @return player list header or null - * @deprecated in favour of {@link #playerListFooter()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @Nullable - public String getPlayerListFooter(); - -@@ -168,7 +168,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param header player list header, null for empty - * @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setPlayerListHeader(@Nullable String header); - - /** -@@ -177,7 +177,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param footer player list footer, null for empty - * @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setPlayerListFooter(@Nullable String footer); - - /** -@@ -188,7 +188,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param footer player list footer, null for empty - * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); - - /** -@@ -228,7 +228,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param message kick message - * @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void kickPlayer(@Nullable String message); - - // Paper start -@@ -718,7 +718,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 - * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; - - /** -@@ -739,7 +739,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 - * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List, org.bukkit.DyeColor)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; - - /** -@@ -2238,7 +2238,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @deprecated in favour of {@link #locale()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getLocale(); - - // Paper start -diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -index 6a6021ad3a0e6aaf51f5144fa126e81bada9cfcf..1c5d268103cb6bd225c31f1ea1a49a52c412845a 100644 ---- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -@@ -34,7 +34,7 @@ public interface CommandMinecart extends Minecart, io.papermc.paper.command.Comm - * @param name New name for this CommandMinecart. - * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setName(@Nullable String name); - - } -diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -index 1268066e30ddb0cd3792ea4b3de894eb04196669..53c71489cfc10e8d4a334829639500978e7b825a 100644 ---- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java -+++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -@@ -90,7 +90,7 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * @deprecated in favour of {@link #lines()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String[] getLines() { - return adventure$lines.stream().map(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()::serialize).toArray(String[]::new); // Paper - } -@@ -106,7 +106,7 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * @deprecated in favour of {@link #line(int)} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getLine(int index) throws IndexOutOfBoundsException { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.adventure$lines.get(index)); // Paper - } -@@ -120,7 +120,7 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * or < 0} - * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { - adventure$lines.set(index, line != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line) : null); // Paper - } -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 9d95218b49895ab76b00fe9524d9b25ea9f9b8c2..d198fe1fbeeb6c769431f5a487097f09b3c0a2f6 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -162,7 +162,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { - * @param deathMessage Message to appear to other players on the server. - * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setDeathMessage(@Nullable String deathMessage) { - this.deathMessage = deathMessage; - this.adventure$deathMessage = deathMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper -@@ -175,7 +175,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { - * @deprecated in favour of {@link #deathMessage()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getDeathMessage() { - return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper - } -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java -index a31841b93964338c9325631dbfa59b3cad77b4f1..7d4a0375543a22a1e31d0506dcc72b1f12320ecd 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryType.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java -@@ -174,7 +174,7 @@ public enum InventoryType { - } - - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getDefaultTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index 635b8787fc235b61c0d5677def034656e4ec4cef..21c68f84e111fe834dbb452b3f40a0de0790f8df 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -188,7 +188,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - * @deprecated in favour of {@link #kickMessage()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getKickMessage() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper - } -@@ -199,7 +199,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - * @param message New kick message - * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setKickMessage(@NotNull final String message) { - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } -@@ -219,7 +219,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - * @param message Kick message to display to the user - * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper -diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -index 4af1d064fcb57773dfa8f6ad40d6482973f8e1a8..c9fe267660f9ec04f78b30182df28180d02f96a2 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -@@ -17,7 +17,7 @@ public class PlayerJoinEvent extends PlayerEvent { - this.joinMessage = joinMessage; - } - -- @Deprecated // Paper end -+ @Deprecated // Paper end // Purpur - conflict on change - public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { - super(playerJoined); - this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper end -@@ -50,7 +50,7 @@ public class PlayerJoinEvent extends PlayerEvent { - * @deprecated in favour of {@link #joinMessage()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getJoinMessage() { - return this.joinMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.joinMessage); // Paper - } -@@ -61,7 +61,7 @@ public class PlayerJoinEvent extends PlayerEvent { - * @param joinMessage join message. If null, no message will be sent - * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setJoinMessage(@Nullable String joinMessage) { - this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index b76966953753dabcb31293846d39a4b4d5ef472a..7a0b59e8b60f75f95ce62871bf5f26ec5f478426 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -@@ -85,7 +85,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * @deprecated in favour of {@link #reason()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getReason() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.kickReason); // Paper - } -@@ -97,7 +97,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * @deprecated in favour of {@link #leaveMessage()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getLeaveMessage() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.leaveMessage); // Paper - } -@@ -118,7 +118,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * @param kickReason kick reason - * @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setReason(@NotNull String kickReason) { - this.kickReason = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(kickReason); // Paper - } -@@ -129,7 +129,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * @param leaveMessage leave message - * @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setLeaveMessage(@NotNull String leaveMessage) { - this.leaveMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(leaveMessage); // Paper - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -index ebd499c1a2d11ea068e8c374edbc3967e4cece3d..61895d8d9f01f7ad0409a1cbd902e8a21472d6d4 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -@@ -36,7 +36,7 @@ public class PlayerLocaleChangeEvent extends PlayerEvent { - * @deprecated in favour of {@link #locale()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getLocale() { - return locale; - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -index 95c53d934f928d25f7b20cfbf2e5faa3df31ddc4..69f07fdb96ea34bb46181dd86b8b5c94dd040808 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -@@ -139,7 +139,7 @@ public class PlayerLoginEvent extends PlayerEvent { - * @deprecated in favour of {@link #kickMessage()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getKickMessage() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper - } -@@ -150,7 +150,7 @@ public class PlayerLoginEvent extends PlayerEvent { - * @param message New kick message - * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setKickMessage(@NotNull final String message) { - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } -@@ -181,7 +181,7 @@ public class PlayerLoginEvent extends PlayerEvent { - * @param message Kick message to display to the user - * @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper start -+ @Deprecated // Paper start // Purpur - conflict on change - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); -diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -index 6800132c6288b4588fd02b08d26f016c38f27129..f3b9ec7e0900c27f2b3fba6d95e9d870919b861a 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -@@ -95,7 +95,7 @@ public class PlayerPreLoginEvent extends Event { - * @return Current kick message - * @deprecated in favour of {@link #kickMessage()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - public String getKickMessage() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper -@@ -107,7 +107,7 @@ public class PlayerPreLoginEvent extends Event { - * @param message New kick message - * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setKickMessage(@NotNull final String message) { - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } -@@ -127,7 +127,7 @@ public class PlayerPreLoginEvent extends Event { - * @param message Kick message to display to the user - * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper -diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index 6e9205024ca9d3000a371bd0eb723dcd6c662bce..567630247c93404f312f8b4470185314d4d82d1a 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -61,7 +61,7 @@ public class PlayerQuitEvent extends PlayerEvent { - * @deprecated in favour of {@link #quitMessage()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getQuitMessage() { - return this.quitMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.quitMessage); // Paper - } -@@ -72,7 +72,7 @@ public class PlayerQuitEvent extends PlayerEvent { - * @param quitMessage quit message - * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setQuitMessage(@Nullable String quitMessage) { - this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper - } -diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -index 943d324435350d3f16fad3e21cb472a01a3ff60b..9f66a44977ab3248ce41733e424b5b71006db8b9 100644 ---- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -+++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -@@ -73,7 +73,7 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - * @deprecated in favour of {@link #message()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getMessage() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper - } -@@ -84,7 +84,7 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - * @param message New message to broadcast - * @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setMessage(@NotNull String message) { - this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } -diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -index 12cdae95c338d21684991d34aea5a643f4b4bcd3..f88356e5be4d33f403617b004e5cd76fe17f2e24 100644 ---- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -+++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -@@ -113,7 +113,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * @deprecated in favour of {@link #motd()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getMotd() { - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.motd); // Paper - } -@@ -124,7 +124,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * @param motd the message of the day - * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setMotd(@NotNull String motd) { - this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper - } -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 2448e70d75ae7a678c6befac4506c103edb78875..b645af3ec4e90789014c2399fb00124665a86cfa 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -464,7 +464,7 @@ public abstract class InventoryView { - * @return The title. - * @deprecated in favour of {@link #title()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - public abstract String getTitle(); - } -diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -index 36bcbb3f3acedf7ebecbf6f6b358cf64af0edfb2..8046b61a62f3cfecb6cd7cb7126b8cbc9617240e 100644 ---- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -@@ -241,7 +241,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @deprecated in favour of {@link #page(int)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getPage(int page); - - /** -@@ -257,7 +257,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @param data the data to set for that page - * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setPage(int page, @NotNull String data); - - /** -@@ -267,7 +267,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @deprecated in favour of {@link #pages()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - List getPages(); - - /** -@@ -277,7 +277,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @param pages A list of pages to set the book to use - * @deprecated in favour of {@link #pages(List)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setPages(@NotNull List pages); - - /** -@@ -287,7 +287,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @param pages A list of strings, each being a page - * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setPages(@NotNull String... pages); - - /** -@@ -297,7 +297,7 @@ public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { - * @param pages A list of strings, each being a page - * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void addPage(@NotNull String... pages); - - /** -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index f1e9a7626c4efb99be78f1056dc04b06bbe13c87..885625c1d54d81de47ed0bc42ee3250c4a54b492 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -59,7 +59,7 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * @return the display name that is set - * @deprecated in favour of {@link #displayName()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @NotNull - String getDisplayName(); - -@@ -83,7 +83,7 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * @param name the name to set - * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setDisplayName(@Nullable String name); - - // Paper start -@@ -161,7 +161,7 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * @return a list of lore that is set - * @deprecated in favour of {@link #lore()} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - @Nullable - List getLore(); - -@@ -185,7 +185,7 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * @param lore the lore that will be set - * @deprecated in favour of {@link #lore(List)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setLore(@Nullable List lore); - - /** -diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java -index ca763b231749f108b6773040a5c6109378b21b31..6db6fc85bd4c8bb94f6afd6f42a8ba447c25ea4b 100644 ---- a/src/main/java/org/bukkit/map/MapCursor.java -+++ b/src/main/java/org/bukkit/map/MapCursor.java -@@ -259,7 +259,7 @@ public final class MapCursor { - * @deprecated in favour of {@link #caption()} - */ - @Nullable -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public String getCaption() { - return this.caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.caption); // Paper - } -@@ -270,7 +270,7 @@ public final class MapCursor { - * @param caption new caption - * @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - public void setCaption(@Nullable String caption) { - this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper - } -diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java -index b93b1b0428d11589605c8edf5c053369e1031076..140ac3ebdb0aab58093429faf67a31f7e527e625 100644 ---- a/src/main/java/org/bukkit/scoreboard/Objective.java -+++ b/src/main/java/org/bukkit/scoreboard/Objective.java -@@ -47,7 +47,7 @@ public interface Objective { - * @deprecated in favour of {@link #displayName()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getDisplayName() throws IllegalStateException; - - /** -@@ -60,7 +60,7 @@ public interface Objective { - * characters. - * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -index fc3456bb79f2fe1504359455b937c162780110c2..c39ca39190c8eacff9e68ef2edd54d814f06d2fb 100644 ---- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java -+++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -@@ -89,7 +89,7 @@ public interface Scoreboard { - * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName) throws IllegalArgumentException; - - /** -@@ -113,7 +113,7 @@ public interface Scoreboard { - * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component, RenderType)} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java -index 06a5d3177ca7ab90c3fd9d2053b2ec5e887c7c62..50d991df5680a1ee1eb2eb38d10adbdea7107dae 100644 ---- a/src/main/java/org/bukkit/scoreboard/Team.java -+++ b/src/main/java/org/bukkit/scoreboard/Team.java -@@ -115,7 +115,7 @@ public interface Team { - * @deprecated in favour of {@link #displayName()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getDisplayName() throws IllegalStateException; - - /** -@@ -127,7 +127,7 @@ public interface Team { - * @throws IllegalStateException if this team has been unregistered - * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -138,7 +138,7 @@ public interface Team { - * @deprecated in favour of {@link #prefix()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getPrefix() throws IllegalStateException; - - /** -@@ -151,7 +151,7 @@ public interface Team { - * @throws IllegalStateException if this team has been unregistered - * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setPrefix(@NotNull String prefix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -162,7 +162,7 @@ public interface Team { - * @deprecated in favour of {@link #suffix()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - String getSuffix() throws IllegalStateException; - - /** -@@ -175,7 +175,7 @@ public interface Team { - * @throws IllegalStateException if this team has been unregistered - * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setSuffix(@NotNull String suffix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -189,7 +189,7 @@ public interface Team { - * @deprecated in favour of {@link #color()} - */ - @NotNull -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - ChatColor getColor() throws IllegalStateException; - - /** -@@ -202,7 +202,7 @@ public interface Team { - * no color - * @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)} - */ -- @Deprecated // Paper -+ @Deprecated // Paper // Purpur - conflict on change - void setColor(@NotNull ChatColor color); - - /** diff --git a/patches/api/0033-Iron-golem-poppy-calms-anger.patch b/patches/api/0032-Iron-golem-poppy-calms-anger.patch similarity index 100% rename from patches/api/0033-Iron-golem-poppy-calms-anger.patch rename to patches/api/0032-Iron-golem-poppy-calms-anger.patch diff --git a/patches/api/0034-API-for-any-mob-to-burn-daylight.patch b/patches/api/0033-API-for-any-mob-to-burn-daylight.patch similarity index 100% rename from patches/api/0034-API-for-any-mob-to-burn-daylight.patch rename to patches/api/0033-API-for-any-mob-to-burn-daylight.patch diff --git a/patches/api/0035-Flying-Fall-Damage-API.patch b/patches/api/0034-Flying-Fall-Damage-API.patch similarity index 92% rename from patches/api/0035-Flying-Fall-Damage-API.patch rename to patches/api/0034-Flying-Fall-Damage-API.patch index c89b5ac7d..22ff01acd 100644 --- a/patches/api/0035-Flying-Fall-Damage-API.patch +++ b/patches/api/0034-Flying-Fall-Damage-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Flying Fall Damage API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 935220b5fa5015def0c9c2f4b7772a72220d3c34..9e06d2cff73d3eed08b7e7855cd30fdad77891c3 100644 +index 4f1213d5c5efb2c415eb22b927936eb932ed3a4a..0fbc571e2990cf79216359454972b80863d2f803 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2746,5 +2746,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0036-Add-back-player-spawned-endermite-API.patch b/patches/api/0035-Add-back-player-spawned-endermite-API.patch similarity index 100% rename from patches/api/0036-Add-back-player-spawned-endermite-API.patch rename to patches/api/0035-Add-back-player-spawned-endermite-API.patch diff --git a/patches/api/0037-Fix-default-permission-system.patch b/patches/api/0036-Fix-default-permission-system.patch similarity index 100% rename from patches/api/0037-Fix-default-permission-system.patch rename to patches/api/0036-Fix-default-permission-system.patch diff --git a/patches/api/0038-Summoner-API.patch b/patches/api/0037-Summoner-API.patch similarity index 100% rename from patches/api/0038-Summoner-API.patch rename to patches/api/0037-Summoner-API.patch diff --git a/patches/api/0039-Clean-up-version-command-output.patch b/patches/api/0038-Clean-up-version-command-output.patch similarity index 100% rename from patches/api/0039-Clean-up-version-command-output.patch rename to patches/api/0038-Clean-up-version-command-output.patch diff --git a/patches/api/0040-Extended-OfflinePlayer-API.patch b/patches/api/0039-Extended-OfflinePlayer-API.patch similarity index 100% rename from patches/api/0040-Extended-OfflinePlayer-API.patch rename to patches/api/0039-Extended-OfflinePlayer-API.patch diff --git a/patches/api/0041-Added-the-ability-to-add-combustible-items.patch b/patches/api/0040-Added-the-ability-to-add-combustible-items.patch similarity index 91% rename from patches/api/0041-Added-the-ability-to-add-combustible-items.patch rename to patches/api/0040-Added-the-ability-to-add-combustible-items.patch index 87e352001..ac4a93a55 100644 --- a/patches/api/0041-Added-the-ability-to-add-combustible-items.patch +++ b/patches/api/0040-Added-the-ability-to-add-combustible-items.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Added the ability to add combustible items diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 9ff99a1ea5183042d7eea89bb310386c6630663a..c17e49f1eea2a70c70eea84820fc17fd5e263304 100644 +index cd7e04aa1de8f051ff4bb23f36912830ab573987..419808643514cf894db69f2ed00283a760d8d8b8 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -2387,5 +2387,24 @@ public final class Bukkit { @@ -34,7 +34,7 @@ index 9ff99a1ea5183042d7eea89bb310386c6630663a..c17e49f1eea2a70c70eea84820fc17fd // Purpur end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 226dd08c1001c664d60f45a6d9370077f4b8c574..5d1668c6f368843ec071df7d65dbd0a29be545d0 100644 +index cc026cbb487244851f8f58b763655a583c7b32e5..18376f615d5b00f6d41f006c5e0af7bd715e4364 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -2082,5 +2082,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi diff --git a/patches/api/0042-Potion-NamespacedKey.patch b/patches/api/0041-Potion-NamespacedKey.patch similarity index 100% rename from patches/api/0042-Potion-NamespacedKey.patch rename to patches/api/0041-Potion-NamespacedKey.patch diff --git a/patches/api/0043-Grindstone-API.patch b/patches/api/0042-Grindstone-API.patch similarity index 100% rename from patches/api/0043-Grindstone-API.patch rename to patches/api/0042-Grindstone-API.patch diff --git a/patches/api/0044-Shears-can-have-looting-enchantment.patch b/patches/api/0043-Shears-can-have-looting-enchantment.patch similarity index 100% rename from patches/api/0044-Shears-can-have-looting-enchantment.patch rename to patches/api/0043-Shears-can-have-looting-enchantment.patch diff --git a/patches/api/0045-Lobotomize-stuck-villagers.patch b/patches/api/0044-Lobotomize-stuck-villagers.patch similarity index 100% rename from patches/api/0045-Lobotomize-stuck-villagers.patch rename to patches/api/0044-Lobotomize-stuck-villagers.patch diff --git a/patches/server/.keep b/patches/server/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/patches/todo/server/0002-Rebrand.patch b/patches/server/0001-Rebrand.patch similarity index 96% rename from patches/todo/server/0002-Rebrand.patch rename to patches/server/0001-Rebrand.patch index 552f9742d..9b78a874b 100644 --- a/patches/todo/server/0002-Rebrand.patch +++ b/patches/server/0001-Rebrand.patch @@ -5,37 +5,40 @@ Subject: [PATCH] Rebrand diff --git a/build.gradle.kts b/build.gradle.kts -index b04e9ab317fbce9c090b61076eb07c40f069dc59..50112767dff03bc3d9b3cc527e20f1b0d8df7155 100644 +index 3ff7814add16834c70494afb76d8a7788545d009..a4a6318b8a79a51a514f121c82bb96d44e0cfd03 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -9,7 +9,7 @@ plugins { +@@ -9,8 +9,8 @@ plugins { } dependencies { -- implementation(project(":pufferfish-api")) // Pufferfish // Paper -+ implementation(project(":purpur-api")) // Pufferfish // Paper // Purpur - // Pufferfish start - implementation("io.papermc.paper:paper-mojangapi:1.18.2-R0.1-SNAPSHOT") { - exclude("io.papermc.paper", "paper-api") -@@ -45,6 +45,8 @@ dependencies { - isTransitive = false - } - // Paper end +- implementation(project(":paper-api")) +- implementation(project(":paper-mojangapi")) ++ implementation(project(":purpur-api")) // Purpur ++ implementation("io.papermc.paper:paper-mojangapi:1.18.2-R0.1-SNAPSHOT") // Purpur // todo: 1.19 + // Paper start + implementation("org.jline:jline-terminal-jansi:3.21.0") + implementation("net.minecrell:terminalconsoleappender:1.3.0") +@@ -32,6 +32,9 @@ dependencies { + runtimeOnly("mysql:mysql-connector-java:8.0.29") + runtimeOnly("com.lmax:disruptor:3.4.4") // Paper + + implementation("cat.inspiracio:rhino-js-engine:1.7.7.1") // Purpur + implementation("dev.omega24:upnp4j:1.0") // Purpur - - // Pufferfish start - implementation("org.yaml:snakeyaml:1.30") -@@ -80,7 +82,7 @@ tasks.jar { ++ + runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.5") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3") + runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3") +@@ -61,7 +64,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", -- "Implementation-Version" to "git-Pufferfish-$implementationVersion", // Pufferfish -+ "Implementation-Version" to "git-Purpur-$implementationVersion", // Pufferfish // Purpur +- "Implementation-Version" to "git-Paper-$implementationVersion", ++ "Implementation-Version" to "git-Purpur-$implementationVersion",// Purpur "Implementation-Vendor" to date, // Paper "Specification-Title" to "Bukkit", "Specification-Version" to project.version, -@@ -168,7 +170,7 @@ fun TaskContainer.registerRunTask( +@@ -149,7 +152,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { @@ -167,10 +170,10 @@ index 1a859fef0848cf23a672012e9764965ae1c07ec5..14ed740609b14242c2a8d377a78b2f71 stringbuilder.append(CrashReport.getErrorComment()); stringbuilder.append("\n\n"); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 22ad31a4320906ee6b56180324a48258c6e461f2..3cd0a4f4fc1ac3bc935368db0340e14b495942a0 100644 +index 5a642dc7cd2fed59c3e5b6ff4ac9ea2f11b401da..ac70a4e739d8d0de09e27dcbf463a41ef56a2a9f 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -957,7 +957,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Purpur"; // Purpur - Purpur > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! +- return "Paper"; // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return "Purpur"; // Purpur - Purpur > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! } public SystemReport fillSystemReport(SystemReport details) { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 6afd7c8b3a0db90dbab14b4405ae4c750e5b0ef1..db2c73390d846f6428546fe18b961147ac092ba2 100644 +index 9ad11f56daff4aa575c2079e54d0239dbab22d8d..23435bdcf53af99032b0d7ca683081d7e72d4d22 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -295,11 +295,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -285,11 +285,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); // Spigot start @@ -221,15 +224,15 @@ index 303b70f0433ff49a3bee2a0d92c41f01aec38bee..5e9fc979daced5dad9977ab12ea019f4 private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 04a1c7b37e44de50a1a201df3d61255b3bcd9b3e..3785c6372667ee238795d2e126edaa0ddb638a36 100644 +index 406f236a658b591ad7db700ad24e580da3a588ca..bf8ce41b89821d3a44d74ad09c561ac7d904a4ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -249,7 +249,7 @@ import javax.annotation.Nullable; // Paper +@@ -243,7 +243,7 @@ import javax.annotation.Nullable; // Paper import javax.annotation.Nonnull; // Paper public final class CraftServer implements Server { -- private final String serverName = "Pufferfish"; // Paper // Pufferfish -+ private final String serverName = "Purpur"; // Paper // Pufferfish // Purpur +- private final String serverName = "Paper"; // Paper ++ private final String serverName = "Purpur"; // Paper // Purpur private final String serverVersion; private final String bukkitVersion = Versioning.getBukkitVersion(); private final Logger logger = Logger.getLogger("Minecraft"); @@ -287,28 +290,28 @@ index cdefb2025eedea7e204d70d568adaf1c1ec4c03c..d1526ed7197b883e1d1f07baf285bf5e // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index f71af7ecad4b6b0328da8cf8c4e5a8e163866e19..f5a490814268949894581b6caeedb53d7588a621 100644 +index 377b018aa60b5efdae0e55960670748d6ec68191..aaded790feb71c3f36aa313a6de3e14533ce108e 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -430,7 +430,7 @@ public final class CraftMagicNumbers implements UnsafeValues { @Override public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new gg.pufferfish.pufferfish.PufferfishVersionFetcher(); // Pufferfish -+ return new com.destroystokyo.paper.PaperVersionFetcher(); // Pufferfish // Purpur +- return new com.destroystokyo.paper.PaperVersionFetcher(); ++ return new com.destroystokyo.paper.PaperVersionFetcher(); // Purpur } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 80553face9c70c2a3d897681e7761df85b22d464..99597258e8e88cd9e2c901c4ac3ff7faeeabee2b 100644 +index 774556a62eb240da42e84db4502e2ed43495be17..fb87620c742ff7912f5e8ccd2a7930dd605576d9 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/gg.pufferfish.pufferfish/pufferfish-api/pom.properties"); // Pufferfish -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.purpurmc.purpur/purpur-api/pom.properties"); // Pufferfish // Purpur +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.purpurmc.purpur/purpur-api/pom.properties"); // Purpur Properties properties = new Properties(); if (stream != null) { diff --git a/patches/todo/server/0003-Purpur-config-files.patch b/patches/server/0002-Purpur-config-files.patch similarity index 92% rename from patches/todo/server/0003-Purpur-config-files.patch rename to patches/server/0002-Purpur-config-files.patch index a0a072666..92a6e8b44 100644 --- a/patches/todo/server/0003-Purpur-config-files.patch +++ b/patches/server/0002-Purpur-config-files.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Purpur config files diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index f2fe6ea3719ff8b2913b7a3a939d7a5b75cb8b28..ed13b7b3f9d2a0b644d17d1019d42cbc4bbe72f7 100644 +index 218f5bafeed8551b55b91c7fccaf6935c8b631ca..4d8740678049aa749b42618470e9cc838555528d 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -593,7 +593,7 @@ public class Metrics { boolean logFailedRequests = config.getBoolean("logFailedRequests", false); // Only start Metrics, if it's enabled in the config if (config.getBoolean("enabled", true)) { -- Metrics metrics = new Metrics("Pufferfish", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish -+ Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish // Purpur +- Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); ++ Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Purpur metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { String minecraftVersion = Bukkit.getVersion(); @@ -22,18 +22,18 @@ index f2fe6ea3719ff8b2913b7a3a939d7a5b75cb8b28..ed13b7b3f9d2a0b644d17d1019d42cbc metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); - metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline")); -- metrics.addCustomChart(new Metrics.SimplePie("pufferfish_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); +- metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); + metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (PaperConfig.isProxyOnlineMode() ? "bungee" : "offline"))); // Purpur + metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); // Purpur metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { Map> map = new HashMap<>(); diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index 00bbf33aa44e2d5a4e755a2d7c1a60de9e36674f..9d884da26e6515a85b0a8f8f611fafc17c19debc 100644 +index e6c254cfa83b218ad2a0e957306d8019adf0aaa7..25b38ae65250a0b3c34dfbf2d853f65368fd916f 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java -@@ -236,6 +236,30 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy - return this.anchor; +@@ -272,6 +272,30 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + return this.signingContext; } + // Purpur start @@ -62,12 +62,12 @@ index 00bbf33aa44e2d5a4e755a2d7c1a60de9e36674f..9d884da26e6515a85b0a8f8f611fafc1 + public void sendSuccess(Component message, boolean broadcastToOps) { if (this.source.acceptsSuccess() && !this.silent) { - this.source.sendMessage(message, Util.NIL_UUID); + this.source.sendSystemMessage(message); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index db2c73390d846f6428546fe18b961147ac092ba2..a4a07a7cc9a33f01234e461aa3c19e1c2e4d6aef 100644 +index 23435bdcf53af99032b0d7ca683081d7e72d4d22..814f24d5d38062799e51cc7e07b3f55fe59579f5 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -231,6 +231,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -224,6 +224,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } thread.start(); // Paper - start console thread after MinecraftServer.console & PaperConfig are initialized com.destroystokyo.paper.PaperConfig.registerCommands(); @@ -84,10 +84,10 @@ index db2c73390d846f6428546fe18b961147ac092ba2..a4a07a7cc9a33f01234e461aa3c19e1c io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // load mappings for stacktrace deobf and etc. io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index b830c2199a22252116619520f407fd84eddb28f3..ba4a6579be392f26f2d89ec910918c4ccf2a2c91 100644 +index e3052c32624538d5394bf098c3b5db84e4cdb9b4..1671cb165df030bf5a5a8f8fb0aabeaf6e7ac487 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -164,6 +164,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -170,6 +170,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray @@ -96,8 +96,8 @@ index b830c2199a22252116619520f407fd84eddb28f3..ba4a6579be392f26f2d89ec910918c4c public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -273,6 +275,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor +@@ -270,6 +272,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper + this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur @@ -105,10 +105,10 @@ index b830c2199a22252116619520f407fd84eddb28f3..ba4a6579be392f26f2d89ec910918c4c this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3785c6372667ee238795d2e126edaa0ddb638a36..c5b20bf5085000319c0c5473f0630610409e4ede 100644 +index bf8ce41b89821d3a44d74ad09c561ac7d904a4ce..13f422993a585a6bcb69791b61001feefd9bcb18 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -956,6 +956,7 @@ public final class CraftServer implements Server { +@@ -950,6 +950,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper @@ -116,7 +116,7 @@ index 3785c6372667ee238795d2e126edaa0ddb638a36..c5b20bf5085000319c0c5473f0630610 for (ServerLevel world : this.console.getAllLevels()) { // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) -@@ -972,6 +973,7 @@ public final class CraftServer implements Server { +@@ -966,6 +967,7 @@ public final class CraftServer implements Server { } world.spigotConfig.init(); // Spigot world.paperConfig.init(); // Paper @@ -124,7 +124,7 @@ index 3785c6372667ee238795d2e126edaa0ddb638a36..c5b20bf5085000319c0c5473f0630610 } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -987,6 +989,7 @@ public final class CraftServer implements Server { +@@ -981,6 +983,7 @@ public final class CraftServer implements Server { this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper @@ -132,7 +132,7 @@ index 3785c6372667ee238795d2e126edaa0ddb638a36..c5b20bf5085000319c0c5473f0630610 this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -2719,6 +2722,18 @@ public final class CraftServer implements Server { +@@ -2695,6 +2698,18 @@ public final class CraftServer implements Server { return com.destroystokyo.paper.PaperConfig.config; } @@ -152,7 +152,7 @@ index 3785c6372667ee238795d2e126edaa0ddb638a36..c5b20bf5085000319c0c5473f0630610 public void restart() { org.spigotmc.RestartCommand.restart(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index fbe68bd4739d9a0e7d9bc4c3d5ba8ecfd2d13954..dd8ab900bb3ff451c7c200f9cb3e3eca3e78a2c6 100644 +index 344d93f1d7f25a3f26064469e78dd698af66dc0d..e8f88084b0998649c422c6011566e334b58a0c93 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -153,6 +153,14 @@ public class Main { diff --git a/patches/todo/server/0004-Purpur-client-support.patch b/patches/server/0003-Purpur-client-support.patch similarity index 84% rename from patches/todo/server/0004-Purpur-client-support.patch rename to patches/server/0003-Purpur-client-support.patch index e83c2cd2c..c6d9cb201 100644 --- a/patches/todo/server/0004-Purpur-client-support.patch +++ b/patches/server/0003-Purpur-client-support.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Purpur client support diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a6edf5117d4ae03d8294e7bb74dd2d77048895a5..46ddb309ee4296b9d3464e716b4b36ef8927261d 100644 +index 49a2a99bc0aaedb27524c64db5ce3907bf55cc28..062a06dbff672235acc87624f1b7c28f04ffce32 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -253,6 +253,7 @@ public class ServerPlayer extends Player { +@@ -260,6 +260,7 @@ public class ServerPlayer extends Player { public Integer clientViewDistance; // CraftBukkit end public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper @@ -17,10 +17,10 @@ index a6edf5117d4ae03d8294e7bb74dd2d77048895a5..46ddb309ee4296b9d3464e716b4b36ef public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 676f2cd4b152984aa76903fcf4377c745775bfc8..ee4b826cb5c680939b19c6ae2b5ae778a7cc4a55 100644 +index b53876746fcc23e7517da3287fdc58909865eb39..a7bc4eefd73337bfabb84032cd98aba42f5870fd 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3186,6 +3186,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -3366,6 +3366,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support @@ -28,7 +28,7 @@ index 676f2cd4b152984aa76903fcf4377c745775bfc8..ee4b826cb5c680939b19c6ae2b5ae778 @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { -@@ -3210,6 +3211,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -3390,6 +3391,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause } @@ -43,10 +43,10 @@ index 676f2cd4b152984aa76903fcf4377c745775bfc8..ee4b826cb5c680939b19c6ae2b5ae778 try { byte[] data = new byte[packet.data.readableBytes()]; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ce78e024244c14530270b8276e5b0fd853f0a110..9ea7691df5d19e4f7d65869af508e38280027467 100644 +index 01ac24f0999c9829bffeb76c228779f80a571687..331d9b64fd3e005c8b95fe3c926f3691392a05dc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2797,4 +2797,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2768,4 +2768,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.spigot; } // Spigot end diff --git a/patches/todo/server/0005-Component-related-conveniences.patch b/patches/server/0004-Component-related-conveniences.patch similarity index 83% rename from patches/todo/server/0005-Component-related-conveniences.patch rename to patches/server/0004-Component-related-conveniences.patch index 3ea3e710e..b8a2b9617 100644 --- a/patches/todo/server/0005-Component-related-conveniences.patch +++ b/patches/server/0004-Component-related-conveniences.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Component related conveniences diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 46ddb309ee4296b9d3464e716b4b36ef8927261d..23ef3a12dcd184edeaad3f939d2a9cbffa7fd35e 100644 +index 062a06dbff672235acc87624f1b7c28f04ffce32..54999c41a39e8c5baed67e01be3d28385d9f64b7 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1698,6 +1698,26 @@ public class ServerPlayer extends Player { +@@ -1699,6 +1699,26 @@ public class ServerPlayer extends Player { + this.lastSentExp = -1; // CraftBukkit - Added to reset } - // CraftBukkit end + // Purpur start + public void sendActionBarMessage(@Nullable String message) { @@ -34,12 +34,12 @@ index 46ddb309ee4296b9d3464e716b4b36ef8927261d..23ef3a12dcd184edeaad3f939d2a9cbf + @Override public void displayClientMessage(Component message, boolean actionBar) { - this.sendMessage(message, actionBar ? ChatType.GAME_INFO : ChatType.CHAT, Util.NIL_UUID); + this.sendSystemMessage(message, actionBar ? ChatType.GAME_INFO : ChatType.SYSTEM); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 624946f48f0811c94d05174f28d0b1fc6d5e6a00..9f5ff0455fe4217737169e442f4786cba951f253 100644 +index 5134af3c96b8df8534db543971c1d574eec31f55..65a7113aec71db08d642946278472f58b6da7bd9 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1384,6 +1384,62 @@ public abstract class PlayerList { +@@ -1064,6 +1064,62 @@ public abstract class PlayerList { } // CraftBukkit end @@ -99,15 +99,15 @@ index 624946f48f0811c94d05174f28d0b1fc6d5e6a00..9f5ff0455fe4217737169e442f4786cb + } + // Purpur end + - public void broadcastMessage(Component message, ChatType type, UUID sender) { - this.server.sendMessage(message, sender); + public void broadcastAll(Packet packet, ResourceKey dimension) { Iterator iterator = this.players.iterator(); + diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index a828cad27fcd39f8bfbaefa97052a2a3b6650ee7..67e559d63c543ff716d610cb04ff9426cc20ae00 100644 +index 67bce77093dcc126098731047447da2031e3388d..c4088446d30c3b25cf196f51fd394cd056be0495 100644 --- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java +++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -234,6 +234,15 @@ public class DamageSource { - return entityliving1 != null ? new TranslatableComponent(s1, new Object[]{entity.getDisplayName(), entityliving1.getDisplayName()}) : new TranslatableComponent(s, new Object[]{entity.getDisplayName()}); +@@ -247,6 +247,15 @@ public class DamageSource { + return entityliving1 != null ? Component.translatable(s1, entity.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, entity.getDisplayName()); } + // Purpur start @@ -123,10 +123,10 @@ index a828cad27fcd39f8bfbaefa97052a2a3b6650ee7..67e559d63c543ff716d610cb04ff9426 return this.isFireSource; } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b47165433d43592742e508f9b918ab36b42c6df6..e7bbd01ad8d070979fb2066db1b06068ef10b56d 100644 +index 87a2228c5c5038153935184f0e4a2f11053b202d..8c74d436f3f5ffa47ab8991035339c4206df8c43 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3683,6 +3683,34 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { +@@ -3696,6 +3696,34 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { return SlotAccess.NULL; } @@ -159,5 +159,5 @@ index b47165433d43592742e508f9b918ab36b42c6df6..e7bbd01ad8d070979fb2066db1b06068 + // Purpur end + @Override - public void sendMessage(Component message, UUID sender) {} + public void sendSystemMessage(Component message) {} diff --git a/patches/server/0005-Ridables.patch b/patches/server/0005-Ridables.patch new file mode 100644 index 000000000..6526139f2 --- /dev/null +++ b/patches/server/0005-Ridables.patch @@ -0,0 +1,6339 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 Jul 2020 22:19:49 -0500 +Subject: [PATCH] Ridables + + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 153451ecd5b3c8e8ecb2d5ec91ccd582d4300899..56536c39bccfe097f8227c74a0d1679943826610 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -41,6 +41,12 @@ public class BlockPos extends Vec3i { + private static final int X_OFFSET = 38; + // Paper end + ++ // Purpur start ++ public BlockPos(net.minecraft.world.entity.Entity entity) { ++ super(entity.getX(), entity.getY(), entity.getZ()); ++ } ++ // Purpur end ++ + public BlockPos(int x, int y, int z) { + super(x, y, z); + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index ac70a4e739d8d0de09e27dcbf463a41ef56a2a9f..8184fcc7c2ec8e3fdfeb7d089860e7aa9c17ac4e 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1531,6 +1531,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper + worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper ++ worldserver.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur + net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 31fadaf364bf52018132df5ea721e0303ba5b65a..805025d7b446110a6949635a7064d05fb51638fd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -216,6 +216,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper + public boolean hasEntityMoveEvent = false; // Paper ++ public boolean hasRidableMoveEvent = false; // Purpur + public static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 54999c41a39e8c5baed67e01be3d28385d9f64b7..347c01f091144f82f6eed996d424400d82634cff 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -668,6 +668,15 @@ public class ServerPlayer extends Player { + this.trackStartFallingPosition(); + this.trackEnteredOrExitedLavaOnVehicle(); + this.advancements.flushDirty(this); ++ ++ // Purpur start ++ if (this.level.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && this.level.getGameTime() % 100 == 0) { // 5 seconds ++ MobEffectInstance nightVision = this.getEffect(MobEffects.NIGHT_VISION); ++ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds ++ this.addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds ++ } ++ } ++ // Purpur end + } + + public void doTick() { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index a7bc4eefd73337bfabb84032cd98aba42f5870fd..076c482e6844f6a188267556cd8fbcc592ad53f7 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2653,6 +2653,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); + ++ player.processClick(enumhand); // Purpur ++ + // Entity in bucket - SPIGOT-4048 and SPIGOT-6859 + if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) { + ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity)); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 8c74d436f3f5ffa47ab8991035339c4206df8c43..8f8740b40a37e91eedc3496985ba0d2964cbafe5 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -320,7 +320,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + private final Set tags; + private final double[] pistonDeltas; + private long pistonDeltasGameTime; +- private EntityDimensions dimensions; ++ protected EntityDimensions dimensions; // Purpur - private -> protected + private float eyeHeight; + public boolean isInPowderSnow; + public boolean wasInPowderSnow; +@@ -2687,6 +2687,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + this.passengers = ImmutableList.copyOf(list); + } + ++ // Purpur start ++ if (isRidable() && this.passengers.get(0) == entity && entity instanceof Player player) { ++ onMount(player); ++ this.rider = player; ++ } ++ // Purpur end + } + return true; // CraftBukkit + } +@@ -2727,6 +2733,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + return false; + } + // Spigot end ++ ++ // Purpur start ++ if (this.rider != null && this.passengers.get(0) == this.rider) { ++ onDismount(this.rider); ++ this.rider = null; ++ } ++ // Purpur end ++ + if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { +@@ -4395,4 +4409,45 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + return ((ServerChunkCache) level.getChunkSource()).isPositionTicking(this); + } + // Paper end ++ ++ // Purpur start ++ @Nullable ++ private Player rider = null; ++ ++ @Nullable ++ public Player getRider() { ++ return rider; ++ } ++ ++ public boolean isRidable() { ++ return false; ++ } ++ ++ public boolean isControllable() { ++ return true; ++ } ++ ++ public void onMount(Player rider) { ++ if (this instanceof Mob) { ++ ((Mob) this).setTarget(null, null, false); ++ ((Mob) this).getNavigation().stop(); ++ } ++ rider.setJumping(false); // fixes jump on mount ++ } ++ ++ public void onDismount(Player player) { ++ } ++ ++ public boolean onSpacebar() { ++ return false; ++ } ++ ++ public boolean onClick(InteractionHand hand) { ++ return false; ++ } ++ ++ public boolean processClick(InteractionHand hand) { ++ return false; ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/GlowSquid.java b/src/main/java/net/minecraft/world/entity/GlowSquid.java +index c1e9b40a4a0f9cdc650caa88b5ea132e06ee2496..882ab40c8cdea8c214cb8344b3ccecddb2967c1c 100644 +--- a/src/main/java/net/minecraft/world/entity/GlowSquid.java ++++ b/src/main/java/net/minecraft/world/entity/GlowSquid.java +@@ -23,6 +23,23 @@ public class GlowSquid extends Squid { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.glowSquidRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.glowSquidControllable; ++ } ++ // Purpur end ++ + @Override + protected ParticleOptions getInkParticle() { + return ParticleTypes.GLOW_SQUID_INK; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 32b0603063032677d734a1c173677f544ce7cc5c..52086efc539b854c159d5166e33b49d933128185 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -221,9 +221,9 @@ public abstract class LivingEntity extends Entity { + protected int deathScore; + public float lastHurt; + public boolean jumping; +- public float xxa; +- public float yya; +- public float zza; ++ public float xxa; public float getStrafeMot() { return xxa; } public void setStrafeMot(float strafe) { xxa = strafe; } // Purpur - OBFHELPER ++ public float yya; public float getVerticalMot() { return yya; } public void setVerticalMot(float vertical) { yya = vertical; } // Purpur - OBFHELPER ++ public float zza; public float getForwardMot() { return zza; } public void setForwardMot(float forward) { zza = forward; } // Purpur - OBFHELPER + protected int lerpSteps; + protected double lerpX; + protected double lerpY; +@@ -288,7 +288,7 @@ public abstract class LivingEntity extends Entity { + this.effectsDirty = true; + this.useItem = ItemStack.EMPTY; + this.lastClimbablePos = Optional.empty(); +- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type)); ++ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur + this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit + // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor + this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); +@@ -339,6 +339,7 @@ public abstract class LivingEntity extends Entity { + public static AttributeSupplier.Builder createLivingAttributes() { + return AttributeSupplier.builder().add(Attributes.MAX_HEALTH).add(Attributes.KNOCKBACK_RESISTANCE).add(Attributes.MOVEMENT_SPEED).add(Attributes.ARMOR).add(Attributes.ARMOR_TOUGHNESS); + } ++ public boolean shouldSendAttribute(Attribute attribute) { return true; } // Purpur + + @Override + protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) { +@@ -2627,7 +2628,7 @@ public abstract class LivingEntity extends Entity { + } + + protected long lastJumpTime = 0L; // Paper +- protected void jumpFromGround() { ++ public void jumpFromGround() { // Purpur - protected -> public + double d0 = (double) this.getJumpPower() + this.getJumpBoostPower(); + Vec3 vec3d = this.getDeltaMovement(); + // Paper start +@@ -3377,8 +3378,10 @@ public abstract class LivingEntity extends Entity { + this.pushEntities(); + this.level.getProfiler().pop(); + // Paper start +- if (((ServerLevel) this.level).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { +- if (this.xo != getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { ++ // Purpur start ++ if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { ++ if (((ServerLevel) this.level).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { ++ // Purpur end + Location from = new Location(this.level.getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); + Location to = new Location (this.level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); +@@ -3388,6 +3391,21 @@ public abstract class LivingEntity extends Entity { + absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); + } + } ++ // Purpur start ++ if (getRider() != null) { ++ getRider().resetLastActionTime(); ++ if (((ServerLevel) level).hasRidableMoveEvent && this instanceof Mob) { ++ Location from = new Location(level.getWorld(), xo, yo, zo, this.yRotO, this.xRotO); ++ Location to = new Location(level.getWorld(), getX(), getY(), getZ(), this.getYRot(), this.getXRot()); ++ org.purpurmc.purpur.event.entity.RidableMoveEvent event = new org.purpurmc.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getRider().getBukkitEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ absMoveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ } ++ } ++ } ++ // Purpur end + } + // Paper end + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index a55c30d86793bf224b536a7ceefce75c70b618c7..fdb8f0bb0996dec6724066ae6de103131fdde6a1 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -146,8 +146,8 @@ public abstract class Mob extends LivingEntity { + this.restrictRadius = -1.0F; + this.goalSelector = new GoalSelector(world.getProfilerSupplier()); + this.targetSelector = new GoalSelector(world.getProfilerSupplier()); +- this.lookControl = new LookControl(this); +- this.moveControl = new MoveControl(this); ++ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this); // Purpur ++ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this); // Purpur + this.jumpControl = new JumpControl(this); + this.bodyRotationControl = this.createBodyControl(); + this.navigation = this.createNavigation(world); +@@ -1317,7 +1317,7 @@ public abstract class Mob extends LivingEntity { + protected void onOffspringSpawnedFromEgg(Player player, Mob child) {} + + protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + + public boolean isWithinRestriction() { +@@ -1688,4 +1688,52 @@ public abstract class Mob extends LivingEntity { + public Iterable iteratePathfindingStartNodeCandidatePositions() { + return ImmutableSet.of(new BlockPos(this.getBoundingBox().minX, (double) this.getBlockY(), this.getBoundingBox().minZ), new BlockPos(this.getBoundingBox().minX, (double) this.getBlockY(), this.getBoundingBox().maxZ), new BlockPos(this.getBoundingBox().maxX, (double) this.getBlockY(), this.getBoundingBox().minZ), new BlockPos(this.getBoundingBox().maxX, (double) this.getBlockY(), this.getBoundingBox().maxZ)); + } ++ ++ // Purpur start ++ public double getMaxY() { ++ return level.getHeight(); ++ } ++ ++ public InteractionResult tryRide(Player player, InteractionHand hand) { ++ if (!isRidable()) { ++ return InteractionResult.PASS; ++ } ++ if (hand != InteractionHand.MAIN_HAND) { ++ return InteractionResult.PASS; ++ } ++ if (player.isShiftKeyDown()) { ++ return InteractionResult.PASS; ++ } ++ if (!player.getItemInHand(hand).isEmpty()) { ++ return InteractionResult.PASS; ++ } ++ if (!passengers.isEmpty() || player.isPassenger()) { ++ return InteractionResult.PASS; ++ } ++ if (this instanceof TamableAnimal tamable) { ++ if (tamable.isTame() && !tamable.isOwnedBy(player)) { ++ return InteractionResult.PASS; ++ } ++ if (!tamable.isTame() && !level.purpurConfig.untamedTamablesAreRidable) { ++ return InteractionResult.PASS; ++ } ++ } ++ if (this instanceof AgeableMob ageable) { ++ if (ageable.isBaby() && !level.purpurConfig.babiesAreRidable) { ++ return InteractionResult.PASS; ++ } ++ } ++ if (!player.getBukkitEntity().hasPermission("allow.ride." + getType().id)) { ++ player.sendMessage(org.purpurmc.purpur.PurpurConfig.cannotRideMob); ++ return InteractionResult.PASS; ++ } ++ player.setYRot(this.getYRot()); ++ player.setXRot(this.getXRot()); ++ if (player.startRiding(this)) { ++ return InteractionResult.SUCCESS; ++ } else { ++ return InteractionResult.PASS; ++ } ++ } ++ // Purpur end + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +index c770ee21b7b699522941f6a1584d532001c04082..f274bef4726f9e23640f3a84c620e7343e96deb3 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +@@ -22,13 +22,20 @@ public class AttributeMap { + private final Map attributes = Maps.newHashMap(); + private final Set dirtyAttributes = Sets.newHashSet(); + private final AttributeSupplier supplier; ++ private final net.minecraft.world.entity.LivingEntity entity; // Purpur + + public AttributeMap(AttributeSupplier defaultAttributes) { ++ // Purpur start ++ this(defaultAttributes, null); ++ } ++ public AttributeMap(AttributeSupplier defaultAttributes, net.minecraft.world.entity.LivingEntity entity) { ++ this.entity = entity; ++ // Purpur end + this.supplier = defaultAttributes; + } + + private void onAttributeModified(AttributeInstance instance) { +- if (instance.getAttribute().isClientSyncable()) { ++ if (instance.getAttribute().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute()))) { // Purpur + this.dirtyAttributes.add(instance); + } + +@@ -40,7 +47,7 @@ public class AttributeMap { + + public Collection getSyncableAttributes() { + return this.attributes.values().stream().filter((attribute) -> { +- return attribute.getAttribute().isClientSyncable(); ++ return attribute.getAttribute().isClientSyncable() && (entity == null || entity.shouldSendAttribute(attribute.getAttribute())); // Purpur + }).collect(Collectors.toList()); + } + +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java +index d5d2b58f103d6bb50a4657299876ac02b77f258a..449b13ab3aeaebdf1e315700446b62b20e275e9b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java +@@ -2,7 +2,9 @@ package net.minecraft.world.entity.ai.attributes; + + import com.google.common.collect.ImmutableMap; + import com.mojang.logging.LogUtils; ++ + import java.util.Map; ++ + import net.minecraft.Util; + import net.minecraft.core.Registry; + import net.minecraft.world.entity.EntityType; +@@ -78,7 +80,88 @@ import org.slf4j.Logger; + + public class DefaultAttributes { + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Map, AttributeSupplier> SUPPLIERS = ImmutableMap., AttributeSupplier>builder().put(EntityType.ALLAY, Allay.createAttributes().build()).put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build()).put(EntityType.AXOLOTL, Axolotl.createAttributes().build()).put(EntityType.BAT, Bat.createAttributes().build()).put(EntityType.BEE, Bee.createAttributes().build()).put(EntityType.BLAZE, Blaze.createAttributes().build()).put(EntityType.CAT, Cat.createAttributes().build()).put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build()).put(EntityType.CHICKEN, Chicken.createAttributes().build()).put(EntityType.COD, AbstractFish.createAttributes().build()).put(EntityType.COW, Cow.createAttributes().build()).put(EntityType.CREEPER, Creeper.createAttributes().build()).put(EntityType.DOLPHIN, Dolphin.createAttributes().build()).put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.DROWNED, Zombie.createAttributes().build()).put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build()).put(EntityType.ENDERMAN, EnderMan.createAttributes().build()).put(EntityType.ENDERMITE, Endermite.createAttributes().build()).put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build()).put(EntityType.EVOKER, Evoker.createAttributes().build()).put(EntityType.FOX, Fox.createAttributes().build()).put(EntityType.FROG, Frog.createAttributes().build()).put(EntityType.GHAST, Ghast.createAttributes().build()).put(EntityType.GIANT, Giant.createAttributes().build()).put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build()).put(EntityType.GOAT, Goat.createAttributes().build()).put(EntityType.GUARDIAN, Guardian.createAttributes().build()).put(EntityType.HOGLIN, Hoglin.createAttributes().build()).put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build()).put(EntityType.HUSK, Zombie.createAttributes().build()).put(EntityType.ILLUSIONER, Illusioner.createAttributes().build()).put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build()).put(EntityType.LLAMA, Llama.createAttributes().build()).put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build()).put(EntityType.MOOSHROOM, Cow.createAttributes().build()).put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.OCELOT, Ocelot.createAttributes().build()).put(EntityType.PANDA, Panda.createAttributes().build()).put(EntityType.PARROT, Parrot.createAttributes().build()).put(EntityType.PHANTOM, Monster.createMonsterAttributes().build()).put(EntityType.PIG, Pig.createAttributes().build()).put(EntityType.PIGLIN, Piglin.createAttributes().build()).put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build()).put(EntityType.PILLAGER, Pillager.createAttributes().build()).put(EntityType.PLAYER, Player.createAttributes().build()).put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build()).put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build()).put(EntityType.RABBIT, Rabbit.createAttributes().build()).put(EntityType.RAVAGER, Ravager.createAttributes().build()).put(EntityType.SALMON, AbstractFish.createAttributes().build()).put(EntityType.SHEEP, Sheep.createAttributes().build()).put(EntityType.SHULKER, Shulker.createAttributes().build()).put(EntityType.SILVERFISH, Silverfish.createAttributes().build()).put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build()).put(EntityType.SLIME, Monster.createMonsterAttributes().build()).put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build()).put(EntityType.SPIDER, Spider.createAttributes().build()).put(EntityType.SQUID, Squid.createAttributes().build()).put(EntityType.STRAY, AbstractSkeleton.createAttributes().build()).put(EntityType.STRIDER, Strider.createAttributes().build()).put(EntityType.TADPOLE, Tadpole.createAttributes().build()).put(EntityType.TRADER_LLAMA, Llama.createAttributes().build()).put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build()).put(EntityType.TURTLE, Turtle.createAttributes().build()).put(EntityType.VEX, Vex.createAttributes().build()).put(EntityType.VILLAGER, Villager.createAttributes().build()).put(EntityType.VINDICATOR, Vindicator.createAttributes().build()).put(EntityType.WARDEN, Warden.createAttributes().build()).put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build()).put(EntityType.WITCH, Witch.createAttributes().build()).put(EntityType.WITHER, WitherBoss.createAttributes().build()).put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.WOLF, Wolf.createAttributes().build()).put(EntityType.ZOGLIN, Zoglin.createAttributes().build()).put(EntityType.ZOMBIE, Zombie.createAttributes().build()).put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build()).put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build()).put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build(); ++ // Purpur start ++ private static final Map, AttributeSupplier> SUPPLIERS = ImmutableMap., AttributeSupplier>builder() ++ .put(EntityType.ALLAY, Allay.createAttributes().build()) ++ .put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build()) ++ .put(EntityType.AXOLOTL, Axolotl.createAttributes().build()) ++ .put(EntityType.BAT, Bat.createAttributes().build()) ++ .put(EntityType.BEE, Bee.createAttributes().build()) ++ .put(EntityType.BLAZE, Blaze.createAttributes().build()) ++ .put(EntityType.CAT, Cat.createAttributes().build()) ++ .put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build()) ++ .put(EntityType.CHICKEN, Chicken.createAttributes().build()) ++ .put(EntityType.COD, AbstractFish.createAttributes().build()) ++ .put(EntityType.COW, Cow.createAttributes().build()) ++ .put(EntityType.CREEPER, Creeper.createAttributes().build()) ++ .put(EntityType.DOLPHIN, Dolphin.createAttributes().build()) ++ .put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build()) ++ .put(EntityType.DROWNED, Zombie.createAttributes().build()) ++ .put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build()) ++ .put(EntityType.ENDERMAN, EnderMan.createAttributes().build()) ++ .put(EntityType.ENDERMITE, Endermite.createAttributes().build()) ++ .put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build()) ++ .put(EntityType.EVOKER, Evoker.createAttributes().build()) ++ .put(EntityType.FOX, Fox.createAttributes().build()) ++ .put(EntityType.FROG, Frog.createAttributes().build()) ++ .put(EntityType.GHAST, Ghast.createAttributes().build()) ++ .put(EntityType.GIANT, Giant.createAttributes().build()) ++ .put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build()) ++ .put(EntityType.GOAT, Goat.createAttributes().build()) ++ .put(EntityType.GUARDIAN, Guardian.createAttributes().build()) ++ .put(EntityType.HOGLIN, Hoglin.createAttributes().build()) ++ .put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build()) ++ .put(EntityType.HUSK, Zombie.createAttributes().build()) ++ .put(EntityType.ILLUSIONER, Illusioner.createAttributes().build()) ++ .put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build()) ++ .put(EntityType.LLAMA, Llama.createAttributes().build()) ++ .put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build()) ++ .put(EntityType.MOOSHROOM, Cow.createAttributes().build()) ++ .put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build()) ++ .put(EntityType.OCELOT, Ocelot.createAttributes().build()) ++ .put(EntityType.PANDA, Panda.createAttributes().build()) ++ .put(EntityType.PARROT, Parrot.createAttributes().build()) ++ .put(EntityType.PHANTOM, net.minecraft.world.entity.monster.Phantom.createAttributes().build()) // Purpur ++ .put(EntityType.PIG, Pig.createAttributes().build()) ++ .put(EntityType.PIGLIN, Piglin.createAttributes().build()) ++ .put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build()) ++ .put(EntityType.PILLAGER, Pillager.createAttributes().build()) ++ .put(EntityType.PLAYER, Player.createAttributes().build()) ++ .put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build()) ++ .put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build()) ++ .put(EntityType.RABBIT, Rabbit.createAttributes().build()) ++ .put(EntityType.RAVAGER, Ravager.createAttributes().build()) ++ .put(EntityType.SALMON, AbstractFish.createAttributes().build()) ++ .put(EntityType.SHEEP, Sheep.createAttributes().build()) ++ .put(EntityType.SHULKER, Shulker.createAttributes().build()) ++ .put(EntityType.SILVERFISH, Silverfish.createAttributes().build()) ++ .put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build()) ++ .put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build()) ++ .put(EntityType.SLIME, Monster.createMonsterAttributes().build()) ++ .put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build()) ++ .put(EntityType.SPIDER, Spider.createAttributes().build()) ++ .put(EntityType.SQUID, Squid.createAttributes().build()) ++ .put(EntityType.STRAY, AbstractSkeleton.createAttributes().build()) ++ .put(EntityType.STRIDER, Strider.createAttributes().build()) ++ .put(EntityType.TADPOLE, Tadpole.createAttributes().build()) ++ .put(EntityType.TRADER_LLAMA, Llama.createAttributes().build()) ++ .put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build()) ++ .put(EntityType.TURTLE, Turtle.createAttributes().build()) ++ .put(EntityType.VEX, Vex.createAttributes().build()) ++ .put(EntityType.VILLAGER, Villager.createAttributes().build()) ++ .put(EntityType.VINDICATOR, Vindicator.createAttributes().build()) ++ .put(EntityType.WARDEN, Warden.createAttributes().build()) ++ .put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build()) ++ .put(EntityType.WITCH, Witch.createAttributes().build()) ++ .put(EntityType.WITHER, WitherBoss.createAttributes().build()) ++ .put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build()) ++ .put(EntityType.WOLF, Wolf.createAttributes().build()) ++ .put(EntityType.ZOGLIN, Zoglin.createAttributes().build()) ++ .put(EntityType.ZOMBIE, Zombie.createAttributes().build()) ++ .put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build()) ++ .put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build()) ++ .put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build(); ++ // Purpur end + + public static AttributeSupplier getSupplier(EntityType type) { + return SUPPLIERS.get(type); +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +index e304d7bc0b6b7c167cfc163a9df4d7a3126037e3..bde157ec8f591445cf4660922f70fa904dac213b 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java +@@ -29,6 +29,20 @@ public class MoveControl implements Control { + this.mob = entity; + } + ++ // Purpur start ++ public void setSpeedModifier(double speed) { ++ this.speedModifier = speed; ++ } ++ ++ public void setForward(float forward) { ++ this.strafeForwards = forward; ++ } ++ ++ public void setStrafe(float strafe) { ++ this.strafeRight = strafe; ++ } ++ // Purpur end ++ + public boolean hasWanted() { + return this.operation == MoveControl.Operation.MOVE_TO; + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java +index 7df56705a4a0de2dc4ff7ab133fc26612c219162..60d21d6171b9af20a4c6fcc0d564a31aaa4ecdba 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java ++++ b/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java +@@ -3,7 +3,7 @@ package net.minecraft.world.entity.ai.control; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Mob; + +-public class SmoothSwimmingLookControl extends LookControl { ++public class SmoothSwimmingLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + private final int maxYRotFromCenter; + private static final int HEAD_TILT_X = 10; + private static final int HEAD_TILT_Y = 20; +@@ -14,7 +14,7 @@ public class SmoothSwimmingLookControl extends LookControl { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.lookAtCooldown > 0) { + --this.lookAtCooldown; + this.getYRotD().ifPresent((yaw) -> { +@@ -32,9 +32,9 @@ public class SmoothSwimmingLookControl extends LookControl { + } + + float f = Mth.wrapDegrees(this.mob.yHeadRot - this.mob.yBodyRot); +- if (f < (float)(-this.maxYRotFromCenter)) { ++ if (f < (float) (-this.maxYRotFromCenter)) { + this.mob.yBodyRot -= 4.0F; +- } else if (f > (float)this.maxYRotFromCenter) { ++ } else if (f > (float) this.maxYRotFromCenter) { + this.mob.yBodyRot += 4.0F; + } + +diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +index 50d4595b81f24949011c7565c5e3fc8c26c86019..f7f3daa646e3f43ae503a67b7c52faef84bff0da 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +@@ -18,6 +18,7 @@ import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -41,9 +42,56 @@ public class Bat extends AmbientCreature { + + public Bat(EntityType type, Level world) { + super(type, world); ++ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.075F); // Purpur + this.setResting(true); + } + ++ // Purpur start ++ @Override ++ public boolean shouldSendAttribute(net.minecraft.world.entity.ai.attributes.Attribute attribute) { return attribute != Attributes.FLYING_SPEED; } // Fixes log spam on clients ++ ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.batRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.batRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.batControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.batMaxY; ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ if (isResting()) { ++ setResting(false); ++ level.levelEvent(null, 1025, new BlockPos(this).above(), 0); ++ } ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2; ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(MoverType.SELF, mot.multiply(speed, 0.25, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Override + public boolean isFlapping() { + return !this.isResting() && this.tickCount % Bat.TICKS_PER_FLAP == 0; +@@ -93,7 +141,7 @@ public class Bat extends AmbientCreature { + protected void pushEntities() {} + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur + } + + public boolean isResting() { +@@ -125,6 +173,14 @@ public class Bat extends AmbientCreature { + + @Override + protected void customServerAiStep() { ++ // Purpur start ++ if (getRider() != null && this.isControllable()) { ++ Vec3 mot = getDeltaMovement(); ++ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z()); ++ return; ++ } ++ // Purpur end ++ + super.customServerAiStep(); + BlockPos blockposition = this.blockPosition(); + BlockPos blockposition1 = blockposition.above(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java +index 1f85f34c1e50f34fb270d2fac7d307c82a550bfa..324f52edd95b5f9a498e46def8c14435cfd00abb 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java +@@ -94,7 +94,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { + @Override + protected void registerGoals() { + super.registerGoals(); +- this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 1.6D, 1.4D, EntitySelector.NO_SPECTATORS::test)); + this.goalSelector.addGoal(4, new AbstractFish.FishSwimGoal(this)); + } +@@ -107,7 +107,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { + @Override + public void travel(Vec3 movementInput) { + if (this.isEffectiveAi() && this.isInWater()) { +- this.moveRelative(0.01F, movementInput); ++ this.moveRelative(getRider() != null ? getSpeed() : 0.01F, movementInput); // Purpur + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (this.getTarget() == null) { +@@ -166,7 +166,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { + protected void playStepSound(BlockPos pos, BlockState state) { + } + +- static class FishMoveControl extends MoveControl { ++ static class FishMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur + private final AbstractFish fish; + + FishMoveControl(AbstractFish owner) { +@@ -174,14 +174,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { + this.fish = owner; + } + ++ // Purpur start + @Override +- public void tick() { ++ public void purpurTick(Player rider) { ++ super.purpurTick(rider); ++ fish.setDeltaMovement(fish.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); ++ } ++ // Purpur end ++ ++ @Override ++ public void vanillaTick() { // Purpur + if (this.fish.isEyeInFluid(FluidTags.WATER)) { + this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); + } + + if (this.operation == MoveControl.Operation.MOVE_TO && !this.fish.getNavigation().isDone()) { +- float f = (float)(this.speedModifier * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f = (float)(this.getSpeedModifier() * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur + this.fish.setSpeed(Mth.lerp(0.125F, this.fish.getSpeed(), f)); + double d = this.wantedX - this.fish.getX(); + double e = this.wantedY - this.fish.getY(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index bd048cc30046f19f9eee89c6ba45d0816a160e67..2c6e1a970d8922047a186fc7eb82abd7066b1fd9 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -43,6 +43,7 @@ import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobType; ++import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.NeutralMob; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.Pose; +@@ -143,6 +144,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public Bee(EntityType type, Level world) { + super(type, world); + this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); ++ final org.purpurmc.purpur.controller.FlyingMoveControllerWASD flyingController = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this, 0.25F, false); // Purpur + // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 + class BeeFlyingMoveControl extends FlyingMoveControl { + public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) { +@@ -151,11 +153,24 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + @Override + public void tick() { ++ // Purpur start ++ if (mob.getRider() != null && mob.isControllable()) { ++ flyingController.purpurTick(mob.getRider()); ++ return; ++ } ++ // Purpur end + if (this.mob.getY() <= Bee.this.level.getMinBuildHeight()) { + this.mob.setNoGravity(false); + } + super.tick(); + } ++ ++ // Purpur start ++ @Override ++ public boolean hasWanted() { ++ return mob.getRider() != null || !mob.isControllable() || super.hasWanted(); ++ } ++ // Purpur end + } + this.moveControl = new BeeFlyingMoveControl(this, 20, true); + // Paper end +@@ -167,6 +182,40 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.setPathfindingMalus(BlockPathTypes.FENCE, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.beeRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.beeRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.beeControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.beeMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2; ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(MoverType.SELF, mot.multiply(speed, speed, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +@@ -181,6 +230,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true)); + this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal()); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); +@@ -196,6 +246,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.goalSelector.addGoal(7, new Bee.BeeGrowCropGoal()); + this.goalSelector.addGoal(8, new Bee.BeeWanderGoal()); + this.goalSelector.addGoal(9, new FloatGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new Bee.BeeHurtByOtherGoal(this)).setAlertOthers(new Class[0])); + this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); +@@ -880,16 +931,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + } + } + +- private class BeeLookControl extends LookControl { ++ private class BeeLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + + BeeLookControl(Mob entity) { + super(entity); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (!Bee.this.isAngry()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java +index 4e42bcb48c75c816e89e652c898242a9bd8c9d5a..dd59f83fd6adff8d1ade76aac6f3563bfbea15b1 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java +@@ -95,6 +95,31 @@ public class Cat extends TamableAnimal { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.catRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.catRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.catControllable; ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setInSittingPose(false); ++ setLying(false); ++ setRelaxStateOne(false); ++ } ++ // Purpur end ++ + public ResourceLocation getResourceLocation() { + return this.getCatVariant().texture(); + } +@@ -103,6 +128,7 @@ public class Cat extends TamableAnimal { + protected void registerGoals() { + this.temptGoal = new Cat.CatTemptGoal(this, 0.6D, Cat.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(2, new Cat.CatRelaxOnOwnerGoal(this)); + this.goalSelector.addGoal(3, this.temptGoal); +@@ -114,6 +140,7 @@ public class Cat extends TamableAnimal { + this.goalSelector.addGoal(10, new BreedGoal(this, 0.8D)); + this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F)); ++ this.targetSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate) null)); + this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); + } +@@ -371,6 +398,7 @@ public class Cat extends TamableAnimal { + + @Override + public InteractionResult mobInteract(Player player, InteractionHand hand) { ++ if (getRider() != null) return InteractionResult.PASS; // Purpur + ItemStack itemstack = player.getItemInHand(hand); + Item item = itemstack.getItem(); + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Chicken.java b/src/main/java/net/minecraft/world/entity/animal/Chicken.java +index ab5f7c69f35acbddd9a4fec7dbbb1df296880d25..58c1102b483ccdddb74023959b9234bcd2af6548 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Chicken.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Chicken.java +@@ -53,9 +53,27 @@ public class Chicken extends Animal { + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.chickenRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.chickenRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.chickenControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Chicken.FOOD_ITEMS, false)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cod.java b/src/main/java/net/minecraft/world/entity/animal/Cod.java +index 824e5e4fe7619ae46061c3c978c9a044db8c84ab..545ef4ab037b3173cc7377ad8147a44a2050d56f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cod.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cod.java +@@ -13,6 +13,23 @@ public class Cod extends AbstractSchoolingFish { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.codRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.codControllable; ++ } ++ // Purpur end ++ + @Override + public ItemStack getBucketItemStack() { + return new ItemStack(Items.COD_BUCKET); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java +index 425c6da0de40983b0870c9fd1b53f16b6a11c34c..8f046fb76b6967e72abde523ffb790e0f46b80e0 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java +@@ -40,9 +40,27 @@ public class Cow extends Animal { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.cowRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.cowRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.cowControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.WHEAT), false)); +@@ -83,6 +101,7 @@ public class Cow extends Animal { + + @Override + public InteractionResult mobInteract(Player player, InteractionHand hand) { ++ if (getRider() != null) return InteractionResult.PASS; // Purpur + ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { +@@ -90,7 +109,7 @@ public class Cow extends Animal { + org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + // CraftBukkit end + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java +index 7c53dddb598de85abf1eb8b8ee183a6e8e6f9c74..badaa1cb7919cc4699c5e732f9c84254416efdc3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java +@@ -78,14 +78,87 @@ public class Dolphin extends WaterAnimal { + public static final Predicate ALLOWED_ITEMS = (entityitem) -> { + return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater(); + }; ++ private int spitCooldown; // Purpur + + public Dolphin(EntityType type, Level world) { + super(type, world); +- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); ++ // Purpur start ++ class DolphinMoveControl extends SmoothSwimmingMoveControl { ++ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterMoveControllerWASD; ++ private final Dolphin dolphin; ++ ++ public DolphinMoveControl(Dolphin dolphin, int pitchChange, int yawChange, float speedInWater, float speedInAir, boolean buoyant) { ++ super(dolphin, pitchChange, yawChange, speedInWater, speedInAir, buoyant); ++ this.dolphin = dolphin; ++ this.waterMoveControllerWASD = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(dolphin); ++ } ++ ++ @Override ++ public void tick() { ++ if (dolphin.getRider() != null && dolphin.isControllable()) { ++ purpurTick(dolphin.getRider()); ++ } else { ++ super.tick(); ++ } ++ } ++ ++ public void purpurTick(Player rider) { ++ if (dolphin.getAirSupply() < 150) { ++ // if drowning override player WASD controls to find air ++ super.tick(); ++ } else { ++ waterMoveControllerWASD.purpurTick(rider); ++ dolphin.setDeltaMovement(dolphin.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); ++ } ++ } ++ }; ++ this.moveControl = new DolphinMoveControl(this, 85, 10, 0.02F, 0.1F, true); ++ // Purpur end + this.lookControl = new SmoothSwimmingLookControl(this, 10); + this.setCanPickUpLoot(true); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.dolphinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.dolphinControllable; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (spitCooldown == 0 && getRider() != null) { ++ spitCooldown = level.purpurConfig.dolphinSpitCooldown; ++ ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getRider().getBukkitEntity(); ++ if (!player.hasPermission("allow.special.dolphin")) { ++ return false; ++ } ++ ++ org.bukkit.Location loc = player.getEyeLocation(); ++ loc.setPitch(loc.getPitch() - 10); ++ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector()); ++ ++ org.purpurmc.purpur.entity.DolphinSpit spit = new org.purpurmc.purpur.entity.DolphinSpit(level, this); ++ spit.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), level.purpurConfig.dolphinSpitSpeed, 5.0F); ++ ++ level.addFreshEntity(spit); ++ playSound(SoundEvents.DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F); ++ return true; ++ } ++ return false; ++ } ++ // Purpur end ++ + @Nullable + @Override + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { +@@ -160,6 +233,7 @@ public class Dolphin extends WaterAnimal { + protected void registerGoals() { + this.goalSelector.addGoal(0, new BreathAirGoal(this)); + this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this)); + this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D)); + this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10)); +@@ -170,6 +244,7 @@ public class Dolphin extends WaterAnimal { + this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal()); + this.goalSelector.addGoal(8, new FollowBoatGoal(this)); + this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers()); + } + +@@ -221,7 +296,7 @@ public class Dolphin extends WaterAnimal { + + @Override + protected boolean canRide(Entity entity) { +- return true; ++ return boardingCooldown <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs; + } + + @Override +@@ -256,6 +331,11 @@ public class Dolphin extends WaterAnimal { + @Override + public void tick() { + super.tick(); ++ // Purpur start ++ if (spitCooldown > 0) { ++ spitCooldown--; ++ } ++ // Purpur end + if (this.isNoAi()) { + this.setAirSupply(this.getMaxAirSupply()); + } else { +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index 8f294f10aca2df007830b12da0506f7614206a89..7bb7aaaff1e6e11db68b0f206bdf04fda0e88fc4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -140,6 +140,44 @@ public class Fox extends Animal { + this.setCanPickUpLoot(true); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.foxRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.foxRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.foxControllable; ++ } ++ ++ @Override ++ public float getJumpPower() { ++ return getRider() != null && this.isControllable() ? 0.5F : super.getJumpPower(); ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setCanPickUpLoot(false); ++ clearStates(); ++ setIsPouncing(false); ++ spitOutItem(getItemBySlot(EquipmentSlot.MAINHAND)); ++ setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); ++ } ++ ++ @Override ++ public void onDismount(Player rider) { ++ super.onDismount(rider); ++ setCanPickUpLoot(true); ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +@@ -159,6 +197,7 @@ public class Fox extends Animal { + return entityliving instanceof AbstractSchoolingFish; + }); + this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level)); + this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); + this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D)); +@@ -185,6 +224,7 @@ public class Fox extends Animal { + this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal()); + this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F)); + this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal()); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> { + return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID()); + })); +@@ -746,16 +786,16 @@ public class Fox extends Animal { + return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + +- public class FoxLookControl extends LookControl { ++ public class FoxLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + + public FoxLookControl() { + super(Fox.this); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (!Fox.this.isSleeping()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + } +@@ -766,16 +806,16 @@ public class Fox extends Animal { + } + } + +- private class FoxMoveControl extends MoveControl { ++ private class FoxMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + + public FoxMoveControl() { + super(Fox.this); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (Fox.this.canMove()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +index 0a239df9a43669047be3d6006597128860862060..467d3b4b750e816f1c9d03114e9514252039bad4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +@@ -69,8 +69,27 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + this.maxUpStep = 1.0F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.ironGolemRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.ironGolemRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.ironGolemControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ if (level.purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true)); + this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F)); + this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6D, false)); +@@ -78,6 +97,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + this.goalSelector.addGoal(5, new OfferFlowerGoal(this)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); + this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +@@ -279,13 +299,13 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.IRON_INGOT)) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } else { + float f = this.getHealth(); + + this.heal(25.0F); + if (this.getHealth() == f) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } else { + float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; + +diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +index e84d4ecc1fd8e196743a37b18306a4769abbcb77..2be73f6dfb7edf8a4019fc29209fee54b9be6b47 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +@@ -64,6 +64,23 @@ public class MushroomCow extends Cow implements Shearable { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.mooshroomRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.mooshroomRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.mooshroomControllable; ++ } ++ // Purpur end ++ + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader world) { + return world.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : world.getPathfindingCostFromLightLevels(pos); +@@ -125,7 +142,7 @@ public class MushroomCow extends Cow implements Shearable { + } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { + // CraftBukkit start + if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + // CraftBukkit end + this.shear(SoundSource.PLAYERS); +@@ -146,7 +163,7 @@ public class MushroomCow extends Cow implements Shearable { + Optional> optional = this.getEffectFromItemStack(itemstack); + + if (!optional.isPresent()) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + + Pair pair = (Pair) optional.get(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +index 6a459435493295ee5bb44fe2ba79cba6acea2e35..041c2d330a245826fc2fa4c1327aeadd24a44254 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +@@ -68,6 +68,23 @@ public class Ocelot extends Animal { + this.reassessTrustingGoals(); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.ocelotRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.ocelotRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.ocelotControllable; ++ } ++ // Purpur end ++ + public boolean isTrusting() { + return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING); + } +@@ -99,12 +116,14 @@ public class Ocelot extends Animal { + protected void registerGoals() { + this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6D, Ocelot.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(3, this.temptGoal); + this.goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3F)); + this.goalSelector.addGoal(8, new OcelotAttackGoal(this)); + this.goalSelector.addGoal(9, new BreedGoal(this, 0.8D)); + this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Chicken.class, false)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR)); + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java +index 39c26f486d6392eb0a9b623cdb2161846357174b..129358e127227efb6adbcf4c436f59f2004c9814 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java +@@ -107,6 +107,32 @@ public class Panda extends Animal { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.pandaRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.pandaRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.pandaControllable; ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setForwardMot(0.0F); ++ sit(false); ++ eat(false); ++ setOnBack(false); ++ } ++ // Purpur end ++ + @Override + public boolean canTakeItem(ItemStack stack) { + EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(stack); +@@ -262,6 +288,7 @@ public class Panda extends Animal { + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D)); + this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2000000476837158D, true)); +@@ -277,6 +304,7 @@ public class Panda extends Animal { + this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this)); + this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new Panda.PandaHurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0])); + } + +@@ -623,7 +651,7 @@ public class Panda extends Animal { + ItemStack itemstack = player.getItemInHand(hand); + + if (this.isScared()) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } else if (this.isOnBack()) { + this.setOnBack(false); + return InteractionResult.sidedSuccess(this.level.isClientSide); +@@ -640,7 +668,7 @@ public class Panda extends Animal { + this.setInLove(player); + } else { + if (this.level.isClientSide || this.isSitting() || this.isInWater()) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + + this.tryToSit(); +@@ -657,7 +685,7 @@ public class Panda extends Animal { + + return InteractionResult.SUCCESS; + } else { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + } + +@@ -697,7 +725,7 @@ public class Panda extends Animal { + return !this.isOnBack() && !this.isScared() && !this.isEating() && !this.isRolling() && !this.isSitting(); + } + +- private static class PandaMoveControl extends MoveControl { ++ private static class PandaMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + + private final Panda panda; + +@@ -707,9 +735,9 @@ public class Panda extends Animal { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.panda.canPerformAction()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + } + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +index a2977596c672a5a435f56bb20fbfb7b59882dda6..9a433b96fa468aab604c6874e1814e09dc9d621d 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +@@ -125,12 +125,68 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + + public Parrot(EntityType type, Level world) { + super(type, world); +- this.moveControl = new FlyingMoveControl(this, 10, false); ++ // Purpur start ++ final org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD flyingController = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); ++ class ParrotMoveControl extends FlyingMoveControl { ++ public ParrotMoveControl(Mob entity, int maxPitchChange, boolean noGravity) { ++ super(entity, maxPitchChange, noGravity); ++ } ++ ++ @Override ++ public void tick() { ++ if (mob.getRider() != null && mob.isControllable()) { ++ flyingController.purpurTick(mob.getRider()); ++ } else { ++ super.tick(); ++ } ++ } ++ ++ @Override ++ public boolean hasWanted() { ++ return mob.getRider() != null && mob.isControllable() ? getForwardMot() != 0 || getStrafeMot() != 0 : super.hasWanted(); ++ } ++ } ++ this.moveControl = new ParrotMoveControl(this, 10, false); ++ // Purpur end + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.COCOA, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.parrotRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.parrotRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.parrotControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.parrotMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2; ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.25, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Nullable + @Override + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) { +@@ -149,8 +205,10 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); ++ //this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); // Purpur - move down + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); // Purpur + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java +index a90fa7e0dab84a0faa026094a9f068b4df136a86..9815f012569a72d64941c732eecabd63ba277570 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -64,9 +64,27 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { + this.steering = new ItemBasedSteering(this.entityData, Pig.DATA_BOOST_TIME, Pig.DATA_SADDLE_ID); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.pigRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.pigRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.pigControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); + this.goalSelector.addGoal(3, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(4, new TemptGoal(this, 1.2D, Ingredient.of(Items.CARROT_ON_A_STICK), false)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java +index b1e05acfb0f0d6517682c12e1ba06a685f0280db..8d123d6ce4c1fb5176d93a651363ba8bbd984550 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java ++++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java +@@ -60,11 +60,40 @@ public class PolarBear extends Animal implements NeutralMob { + private int remainingPersistentAngerTime; + @Nullable + private UUID persistentAngerTarget; ++ private int standTimer = 0; // Purpur + + public PolarBear(EntityType type, Level world) { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.polarBearRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.polarBearRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.polarBearControllable; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (!isStanding()) { ++ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0) { ++ setStanding(true); ++ playSound(SoundEvents.POLAR_BEAR_WARNING, 1.0F, 1.0F); ++ } ++ } ++ return false; ++ } ++ // Purpur end ++ + @Override + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { + return EntityType.POLAR_BEAR.create(world); +@@ -79,12 +108,14 @@ public class PolarBear extends Animal implements NeutralMob { + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal()); + this.goalSelector.addGoal(1, new PolarBear.PolarBearPanicGoal()); + this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new PolarBear.PolarBearHurtByTargetGoal()); + this.targetSelector.addGoal(2, new PolarBear.PolarBearAttackPlayersGoal()); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +@@ -201,6 +232,11 @@ public class PolarBear extends Animal implements NeutralMob { + this.updatePersistentAnger((ServerLevel)this.level, true); + } + ++ // Purpur start ++ if (isStanding() && --standTimer <= 0) { ++ setStanding(false); ++ } ++ // Purpur end + } + + @Override +@@ -230,6 +266,7 @@ public class PolarBear extends Animal implements NeutralMob { + + public void setStanding(boolean warning) { + this.entityData.set(DATA_STANDING_ID, warning); ++ standTimer = warning ? 20 : -1; // Purpur + } + + public float getStandingAnimationScale(float tickDelta) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +index ce02552c1b3c62cf9f48425838a129a3ec40a049..71929e5fe8851ad5620f25b6ed5058653231d769 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +@@ -45,6 +45,23 @@ public class Pufferfish extends AbstractFish { + this.refreshDimensions(); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.pufferfishRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.pufferfishControllable; ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +index 6152ffec28c9cf93d45ea8c2d9d66ba15110a9aa..895e93e114e12a402812c19fab9581f47ed5020e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +@@ -85,6 +85,7 @@ public class Rabbit extends Animal { + private boolean wasOnGround; + private int jumpDelayTicks; + int moreCarrotTicks; ++ private boolean actualJump; // Purpur + + public Rabbit(EntityType type, Level world) { + super(type, world); +@@ -93,6 +94,51 @@ public class Rabbit extends Animal { + this.initializePathFinderGoals(); // CraftBukkit - moved code + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.rabbitRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.rabbitRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.rabbitControllable; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (onGround) { ++ actualJump = true; ++ jumpFromGround(); ++ actualJump = false; ++ } ++ return true; ++ } ++ ++ private void handleJumping() { ++ if (onGround) { ++ RabbitJumpControl jumpController = (RabbitJumpControl) jumpControl; ++ if (!wasOnGround) { ++ setJumping(false); ++ jumpController.setCanJump(false); ++ } ++ if (!jumpController.wantJump()) { ++ if (moveControl.hasWanted()) { ++ startJumping(); ++ } ++ } else if (!jumpController.canJump()) { ++ jumpController.setCanJump(true); ++ } ++ } ++ wasOnGround = onGround; ++ } ++ // Purpur end ++ + // CraftBukkit start - code from constructor + public void initializePathFinderGoals(){ + this.setSpeedModifier(0.0D); +@@ -102,6 +148,7 @@ public class Rabbit extends Animal { + @Override + public void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level)); + this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 0.8D)); +@@ -116,6 +163,13 @@ public class Rabbit extends Animal { + + @Override + protected float getJumpPower() { ++ if (getRider() != null && this.isControllable()) { ++ if (getForwardMot() < 0) { ++ setSpeed(getForwardMot() * 2F); ++ } ++ return actualJump ? 0.5F : 0.3F; ++ } ++ // Purpur end + if (!this.horizontalCollision && (!this.moveControl.hasWanted() || this.moveControl.getWantedY() <= this.getY() + 0.5D)) { + Path pathentity = this.navigation.getPath(); + +@@ -134,7 +188,7 @@ public class Rabbit extends Animal { + } + + @Override +- protected void jumpFromGround() { ++ public void jumpFromGround() { // Purpur - protected -> public + super.jumpFromGround(); + double d0 = this.moveControl.getSpeedModifier(); + +@@ -184,6 +238,13 @@ public class Rabbit extends Animal { + + @Override + public void customServerAiStep() { ++ // Purpur start ++ if (getRider() != null && this.isControllable()) { ++ handleJumping(); ++ return; ++ } ++ // Purpur end ++ + if (this.jumpDelayTicks > 0) { + --this.jumpDelayTicks; + } +@@ -454,7 +515,7 @@ public class Rabbit extends Animal { + } + } + +- private static class RabbitMoveControl extends MoveControl { ++ private static class RabbitMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + + private final Rabbit rabbit; + private double nextJumpSpeed; +@@ -465,14 +526,14 @@ public class Rabbit extends Animal { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.rabbit.onGround && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl) this.rabbit.jumpControl).wantJump()) { + this.rabbit.setSpeedModifier(0.0D); + } else if (this.hasWanted()) { + this.rabbit.setSpeedModifier(this.nextJumpSpeed); + } + +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/Salmon.java b/src/main/java/net/minecraft/world/entity/animal/Salmon.java +index 0af79daa357f53a8871e293b57e16c099e5d3f64..59cb21bc3166f4cc77b962c253ed786fd04090de 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Salmon.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Salmon.java +@@ -13,6 +13,23 @@ public class Salmon extends AbstractSchoolingFish { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.salmonRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.salmonControllable; ++ } ++ // Purpur end ++ + @Override + public int getMaxSchoolSize() { + return 5; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java +index ed289bdc0455e737c79e8630e1cdfdeb957e2c03..15b2677018abc5047ddedaaf2b640de8dd1966ae 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java +@@ -116,10 +116,28 @@ public class Sheep extends Animal implements Shearable { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.sheepRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.sheepRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.sheepControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.eatBlockGoal = new EatBlockGoal(this); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.1D, Ingredient.of(Items.WHEAT), false)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +index 35e53663e4a6c4d56ec4577d08e7b040cc0c720f..c6700d12fffbfea0fced14e466da0b760a73a237 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +@@ -54,12 +54,31 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.snowGolemRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.snowGolemRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.snowGolemControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F)); + this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> { + return entityliving instanceof Enemy; + })); +@@ -113,6 +132,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + return; + } + ++ if (getRider() != null && this.isControllable() && !level.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden + BlockState iblockdata = Blocks.SNOW.defaultBlockState(); + + for (int l = 0; l < 4; ++l) { +@@ -160,7 +180,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { + // CraftBukkit start + if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + // CraftBukkit end + this.shear(SoundSource.PLAYERS); +@@ -173,7 +193,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index a51424d29ac353cf1bec4d1484db0acb63bebba5..30687391baacd693fa3bb9e3efbd492d4e4d32c8 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -50,9 +50,37 @@ public class Squid extends WaterAnimal { + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.squidRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.squidControllable; ++ } ++ ++ protected void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) { ++ double rad = Math.toRadians(degrees); ++ double cos = Math.cos(rad); ++ double sine = Math.sin(rad); ++ double x = vector.getX(); ++ double z = vector.getZ(); ++ vector.setX(cos * x - sine * z); ++ vector.setZ(sine * x + cos * z); ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Squid.SquidFleeGoal()); + } + +@@ -244,6 +272,38 @@ public class Squid extends WaterAnimal { + + @Override + public void tick() { ++ // Purpur start ++ Player rider = squid.getRider(); ++ if (rider != null && squid.isControllable()) { ++ if (rider.jumping) { ++ squid.onSpacebar(); ++ } ++ float forward = rider.getForwardMot(); ++ float strafe = rider.getStrafeMot(); ++ float speed = (float) squid.getAttributeValue(Attributes.MOVEMENT_SPEED) * 10F; ++ if (forward < 0.0F) { ++ speed *= -0.5; ++ } ++ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F); ++ if (strafe != 0.0F) { ++ if (forward == 0.0F) { ++ dir.setY(0); ++ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90); ++ } else if (forward < 0.0F) { ++ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45); ++ } else { ++ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45); ++ } ++ } ++ if (forward != 0.0F || strafe != 0.0F) { ++ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); ++ } else { ++ squid.setMovementVector(0.0F, 0.0F, 0.0F); ++ } ++ return; ++ } ++ // Purpur end ++ + int i = this.squid.getNoActionTime(); + + if (i > 100) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java +index 559a4995d3530c0d402ab6306f9ac4c46b934c2b..cac2845978b9beebb4e1ed6fed3eb33a698bc545 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java +@@ -49,6 +49,23 @@ public class TropicalFish extends AbstractSchoolingFish { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.tropicalFishRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.tropicalFishControllable; ++ } ++ // Purpur end ++ + public static String getPredefinedName(int variant) { + return "entity.minecraft.tropical_fish.predefined." + variant; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 5575730aa6f77a91467c394fa8465c335d73db8e..b185a58c0adb9a0dde014dd7fdeb3bd465feb706 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -82,6 +82,23 @@ public class Turtle extends Animal { + this.maxUpStep = 1.0F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.turtleRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.turtleRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.turtleControllable; ++ } ++ // Purpur end ++ + public void setHomePos(BlockPos pos) { + this.entityData.set(Turtle.HOME_POS, pos.immutable()); // Paper - called with mutablepos... + } +@@ -184,6 +201,7 @@ public class Turtle extends Animal { + + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D)); + this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D)); + this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D)); +@@ -341,13 +359,15 @@ public class Turtle extends Animal { + org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + +- private static class TurtleMoveControl extends MoveControl { ++ private static class TurtleMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + + private final Turtle turtle; ++ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur + + TurtleMoveControl(Turtle turtle) { + super(turtle); + this.turtle = turtle; ++ waterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(turtle, 0.25D); // Purpur + } + + private void updateSpeed() { +@@ -366,8 +386,18 @@ public class Turtle extends Animal { + + } + ++ // Purpur start ++ public void purpurTick(Player rider) { ++ if (turtle.isInWater()) { ++ waterController.purpurTick(rider); ++ } else { ++ super.purpurTick(rider); ++ } ++ } ++ // Purpur end ++ + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + this.updateSpeed(); + if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { + double d0 = this.wantedX - this.turtle.getX(); +@@ -380,7 +410,7 @@ public class Turtle extends Animal { + + this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F)); + this.turtle.yBodyRot = this.turtle.getYRot(); +- float f1 = (float) (this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f1 = (float) (this.getSpeedModifier() * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED)); + + this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1)); + this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, (double) this.turtle.getSpeed() * d1 * 0.1D, 0.0D)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java +index 45c3cec839a7c23903dedf6e3e004305da2adceb..248531727dcafb71d7d2d2767205e09a8c0f1876 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java +@@ -102,9 +102,32 @@ public class Wolf extends TamableAnimal implements NeutralMob { + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.wolfRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.wolfRidableInWater; ++ } ++ ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setInSittingPose(false); ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.wolfControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Wolf.WolfPanicGoal(1.5D)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5D, 1.5D)); +@@ -116,6 +139,7 @@ public class Wolf extends TamableAnimal implements NeutralMob { + this.goalSelector.addGoal(9, new BegGoal(this, 8.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(10, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); + this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); + this.targetSelector.addGoal(3, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); +diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java +index da5e6141f548539cac720aba558e1b6f3a87e474..bd88b617eb5a496943b4c21d4fad1be8e208eb23 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -97,6 +97,28 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { + this.maxUpStep = 1.0F; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.axolotlRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.axolotlControllable; ++ } ++ ++ @Override ++ protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur ++ } ++ // Purpur end ++ + @Override + public Map getModelRotationValues() { + return this.modelRotationValues; +@@ -523,14 +545,22 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { + private static class AxolotlMoveControl extends SmoothSwimmingMoveControl { + + private final Axolotl axolotl; ++ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur + + public AxolotlMoveControl(Axolotl axolotl) { + super(axolotl, 85, 10, 0.1F, 0.5F, false); + this.axolotl = axolotl; ++ waterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(axolotl, 0.5D); // Purpur + } + + @Override + public void tick() { ++ // Purpur start ++ if (axolotl.getRider() != null && axolotl.isControllable()) { ++ waterController.purpurTick(axolotl.getRider()); ++ return; ++ } ++ // Purpur end + if (!this.axolotl.isPlayingDead()) { + super.tick(); + } +@@ -545,9 +575,9 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (!Axolotl.this.isPlayingDead()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +index 56dd01801f56c56d07101e7e22b58ac059f5f07f..edf7defbd600f289de35af4a7fc57aedf8504442 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +@@ -89,6 +89,23 @@ public class Goat extends Animal { + return InstrumentItem.create(Items.GOAT_HORN, (Holder) holderset.getRandomElement(randomsource).get()); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.goatRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.goatRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.goatControllable; ++ } ++ // Purpur end ++ + @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Goat.MEMORY_TYPES, Goat.SENSOR_TYPES); +@@ -166,6 +183,7 @@ public class Goat extends Animal { + @Override + protected void customServerAiStep() { + this.level.getProfiler().push("goatBrain"); ++ if (getRider() == null || !this.isControllable())// Purpur - only use brain if no rider + this.getBrain().tick((ServerLevel) this.level, this); + this.level.getProfiler().pop(); + this.level.getProfiler().push("goatActivityUpdate"); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index a8da601b8342aa6e4902b452eb588c76c98a7adf..f4190b1e1f9b4d2af04c15c472001f7f943a3cd3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -116,12 +116,22 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + + protected AbstractHorse(EntityType type, Level world) { + super(type, world); ++ this.moveControl = new net.minecraft.world.entity.ai.control.MoveControl(this); // Purpur - use vanilla controller ++ this.lookControl = new net.minecraft.world.entity.ai.control.LookControl(this); // Purpur - use vanilla controller + this.maxUpStep = 1.0F; + this.createInventory(); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return false; // vanilla handles ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D)); + this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D, AbstractHorse.class)); +@@ -129,6 +139,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.7D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur + this.addBehaviourGoals(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java +index 4e68ba557e86250b61ce0b20eacb3bcd36a23806..db4d5d5e38a44f85c343b632c914f2252c30a3c3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java +@@ -15,6 +15,13 @@ public class Donkey extends AbstractChestedHorse { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.donkeyRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected SoundEvent getAmbientSound() { + super.getAmbientSound(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java +index 34299274e7dd57076a1043d735a41b9c34f0a349..f711ea32db68fb7aece5081e741c4e161123467f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java +@@ -40,6 +40,13 @@ public class Horse extends AbstractHorse { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.horseRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void randomizeAttributes(RandomSource random) { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)this.generateRandomMaxHealth(random)); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +index 5ffae9d3be22b5e78645da57a6bd0e7350749ef1..b6a5ac35bed88e9d55b4de0551a13ea58901315e 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +@@ -71,7 +71,51 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { + + public Llama(EntityType type, Level world) { + super(type, world); ++ // Purpur start ++ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this) { ++ @Override ++ public void tick() { ++ if (entity.getRider() != null && entity.isControllable() && isSaddled()) { ++ purpurTick(entity.getRider()); ++ } else { ++ vanillaTick(); ++ } ++ } ++ }; ++ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) { ++ @Override ++ public void tick() { ++ if (entity.getRider() != null && entity.isControllable() && isSaddled()) { ++ purpurTick(entity.getRider()); ++ } else { ++ vanillaTick(); ++ } ++ } ++ }; ++ // Purpur end ++ } ++ ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.llamaRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.llamaRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.llamaControllable; ++ } ++ ++ @Override ++ public boolean isSaddled() { ++ return super.isSaddled() || (isTamed() && getSwag() != null); + } ++ // Purpur end + + public boolean isTraderLlama() { + return false; +@@ -123,6 +167,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.LlamaHasRider(this)); // Purpur + this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); + this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.0999999046325684D)); + this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25D, 40, 20.0F)); +@@ -133,6 +178,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7D)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.LlamaHasRider(this)); // Purpur + this.targetSelector.addGoal(1, new Llama.LlamaHurtByTargetGoal(this)); + this.targetSelector.addGoal(2, new Llama.LlamaAttackWolfGoal(this)); + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java +index 51821a71bb0eb9cd22c657a46ef148c84a2355c1..a67061b875468777ee6256c0b28894c62ebb926c 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java +@@ -14,6 +14,13 @@ public class Mule extends AbstractChestedHorse { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.muleRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected SoundEvent getAmbientSound() { + super.getAmbientSound(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +index 0519385be9e9ebeefebd986017746f057df40fdc..9b96cff17568325d5a9ffaf4b38f1ae06630a5b4 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +@@ -30,6 +30,13 @@ public class SkeletonHorse extends AbstractHorse { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0D).add(Attributes.MOVEMENT_SPEED, (double)0.2F); + } +@@ -41,6 +48,7 @@ public class SkeletonHorse extends AbstractHorse { + + @Override + protected void addBehaviourGoals() { ++ if (level.purpurConfig.skeletonHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); + } + + @Override +@@ -136,7 +144,7 @@ public class SkeletonHorse extends AbstractHorse { + + @Override + public boolean rideableUnderWater() { +- return true; ++ return level.purpurConfig.skeletonHorseRidableInWater; // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java +index 7dbdb6529350b34c0260ca50dfff2b4583fd9c2a..a4a88be0cbf94b633f486ce57d4fccd38002ac9f 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java +@@ -27,6 +27,28 @@ public class TraderLlama extends Llama { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.traderLlamaRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.traderLlamaRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.traderLlamaControllable; ++ } ++ ++ @Override ++ public boolean isSaddled() { ++ return super.isSaddled() || isTamed(); ++ } ++ // Purpur end ++ + @Override + public boolean isTraderLlama() { + return true; +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java +index ea30f391c4d36b5fd1a0d8fae862005fbf9f3201..0f8ce0c6ddbb37a61c6b15bb769b627bcd8105fa 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java +@@ -23,6 +23,18 @@ public class ZombieHorse extends AbstractHorse { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zombieHorseRidableInWater; ++ } ++ ++ @Override ++ public boolean isTamed() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0D).add(Attributes.MOVEMENT_SPEED, (double)0.2F); + } +@@ -93,5 +105,6 @@ public class ZombieHorse extends AbstractHorse { + + @Override + protected void addBehaviourGoals() { ++ if (level.purpurConfig.zombieHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur + } + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java +index 305a891e4b51d1031d9e9238ff00e2ea7de8d954..84625d09df800fcfd477fc493fb5f8246567b7e8 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java ++++ b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java +@@ -21,6 +21,13 @@ public class EnderDragonPart extends Entity { + this.name = name; + } + ++ // Purpur start ++ @Override ++ public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) { ++ return parentMob.isAlive() ? parentMob.tryRide(player, hand) : net.minecraft.world.InteractionResult.PASS; ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + } +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 69c6a0c64ef5371dc57da1fdb60a8ac295bf327a..314454b8c0197002c6c2529ffb75724de16cf7a6 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 +@@ -103,6 +103,7 @@ public class EnderDragon extends Mob implements Enemy { + @Nullable + private BlockPos podium; + // Paper end ++ private boolean hadRider; // Purpur + + public EnderDragon(EntityType entitytypes, Level world) { + super(EntityType.ENDER_DRAGON, world); +@@ -117,8 +118,50 @@ public class EnderDragon extends Mob implements Enemy { + } + + this.phaseManager = new EnderDragonPhaseManager(this); ++ ++ // Purpur start ++ this.moveControl = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this) { ++ @Override ++ public void vanillaTick() { ++ // dragon doesn't use the controller. do nothing ++ } ++ }; ++ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) { ++ @Override ++ public void vanillaTick() { ++ // dragon doesn't use the controller. do nothing ++ } ++ ++ @Override ++ public void purpurTick(Player rider) { ++ setYawPitch(rider.yRot - 180F, rider.xRotO * 0.5F); ++ } ++ }; ++ // Purpur end ++ } ++ ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.enderDragonRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.enderDragonRidableInWater; + } + ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.enderDragonControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.enderDragonMaxY; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D); + } +@@ -180,6 +223,37 @@ public class EnderDragon extends Mob implements Enemy { + + @Override + public void aiStep() { ++ // Purpur start ++ boolean hasRider = getRider() != null && this.isControllable(); ++ if (hasRider) { ++ if (!hadRider) { ++ hadRider = true; ++ noPhysics = false; ++ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(4.0F, 2.0F); ++ } ++ ++ // dragon doesn't use controllers, so must tick manually ++ moveControl.tick(); ++ lookControl.tick(); ++ ++ moveRelative((float) getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.1F, new Vec3(-getStrafeMot(), getVerticalMot(), -getForwardMot())); ++ Vec3 mot = getDeltaMovement(); ++ setDeltaMovement(mot); ++ move(MoverType.PLAYER, mot); ++ ++ mot = mot.multiply(0.9F, 0.9F, 0.9F); ++ setDeltaMovement(mot); ++ ++ // control wing flap speed on client ++ phaseManager.setPhase(mot.x() * mot.x() + mot.z() * mot.z() < 0.005F ? EnderDragonPhase.HOVERING : EnderDragonPhase.HOLDING_PATTERN); ++ } else if (hadRider) { ++ hadRider = false; ++ noPhysics = true; ++ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(16.0F, 8.0F); ++ phaseManager.setPhase(EnderDragonPhase.HOLDING_PATTERN); // HoldingPattern ++ } ++ // Purpur end ++ + this.processFlappingMovement(); + if (this.level.isClientSide) { + this.setHealth(this.getHealth()); +@@ -193,6 +267,8 @@ public class EnderDragon extends Mob implements Enemy { + float f; + + if (this.isDeadOrDying()) { ++ if (hasRider) ejectPassengers(); // Purpur ++ + float f1 = (this.random.nextFloat() - 0.5F) * 8.0F; + + f = (this.random.nextFloat() - 0.5F) * 4.0F; +@@ -205,9 +281,9 @@ public class EnderDragon extends Mob implements Enemy { + + f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F); + f *= (float) Math.pow(2.0D, vec3d.y); +- if (this.phaseManager.getCurrentPhase().isSitting()) { ++ if (!hasRider && this.phaseManager.getCurrentPhase().isSitting()) { // Purpur + this.flapTime += 0.1F; +- } else if (this.inWall) { ++ } else if (!hasRider && this.inWall) { // Purpur + this.flapTime += f * 0.5F; + } else { + this.flapTime += f; +@@ -252,7 +328,7 @@ public class EnderDragon extends Mob implements Enemy { + } + + this.phaseManager.getCurrentPhase().doClientTick(); +- } else { ++ } else if (!hasRider) { // Purpur + DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); + + idragoncontroller.doServerTick(); +@@ -321,7 +397,7 @@ public class EnderDragon extends Mob implements Enemy { + this.tickPart(this.body, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); + this.tickPart(this.wing1, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); + this.tickPart(this.wing2, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); +- if (!this.level.isClientSide && this.hurtTime == 0) { ++ if (!hasRider && !this.level.isClientSide && this.hurtTime == 0) { // Purpur + this.knockBack(this.level.getEntities((Entity) this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + this.knockBack(this.level.getEntities((Entity) this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + this.hurt(this.level.getEntities((Entity) this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); +@@ -365,7 +441,7 @@ public class EnderDragon extends Mob implements Enemy { + } + + if (!this.level.isClientSide) { +- this.inWall = this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); ++ this.inWall = !hasRider && this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); // Purpur + if (this.dragonFight != null) { + this.dragonFight.updateDragon(this); + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +index d347ab0a638a972ea53a982f29af40423919870c..b09b8d79e837b613e20fdac2a419403f3e0d07d7 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -84,6 +84,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); + }; + private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); ++ private int shootCooldown = 0; // Purpur + // Paper start + private boolean canPortal = false; + +@@ -105,16 +106,123 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + navigationflying.setCanOpenDoors(false); + navigationflying.setCanFloat(true); + navigationflying.setCanPassDoors(true); ++ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.1F); // Purpur + return navigationflying; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.witherRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.witherRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.witherControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.witherMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 5F; ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.5, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ this.entityData.set(DATA_TARGETS.get(0), 0); ++ this.entityData.set(DATA_TARGETS.get(1), 0); ++ this.entityData.set(DATA_TARGETS.get(2), 0); ++ getNavigation().stop(); ++ shootCooldown = 20; ++ } ++ ++ @Override ++ public boolean onClick(net.minecraft.world.InteractionHand hand) { ++ return shoot(getRider(), hand == net.minecraft.world.InteractionHand.MAIN_HAND ? new int[]{1} : new int[]{2}); ++ } ++ ++ public boolean shoot(@Nullable Player rider, int[] heads) { ++ if (shootCooldown > 0) { ++ return false; ++ } ++ ++ shootCooldown = 20; ++ if (rider == null) { ++ return false; ++ } ++ ++ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity(); ++ if (!player.hasPermission("allow.special.wither")) { ++ return false; ++ } ++ ++ net.minecraft.world.phys.HitResult rayTrace = getRayTrace(120, net.minecraft.world.level.ClipContext.Fluid.NONE); ++ if (rayTrace == null) { ++ return false; ++ } ++ ++ Vec3 loc; ++ if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) { ++ BlockPos pos = ((net.minecraft.world.phys.BlockHitResult) rayTrace).getBlockPos(); ++ loc = new Vec3(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); ++ } else if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.ENTITY) { ++ Entity target = ((net.minecraft.world.phys.EntityHitResult) rayTrace).getEntity(); ++ loc = new Vec3(target.getX(), target.getY() + (target.getEyeHeight() / 2), target.getZ()); ++ } else { ++ org.bukkit.block.Block block = player.getTargetBlock(null, 120); ++ loc = new Vec3(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D); ++ } ++ ++ for (int head : heads) { ++ shoot(head, loc.x(), loc.y(), loc.z(), rider); ++ } ++ ++ return true; // handled ++ } ++ ++ public void shoot(int head, double x, double y, double z, Player rider) { ++ level.levelEvent(null, 1024, blockPosition(), 0); ++ double headX = getHeadX(head); ++ double headY = getHeadY(head); ++ double headZ = getHeadZ(head); ++ WitherSkull skull = new WitherSkull(level, this, x - headX, y - headY, z - headZ) { ++ @Override ++ public boolean canHitEntity(Entity target) { ++ // do not hit rider ++ return target != rider && super.canHitEntity(target); ++ } ++ }; ++ skull.setPosRaw(headX, headY, headZ); ++ level.addFreshEntity(skull); ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal()); + this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 40, 20.0F)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomFlyingGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); + } +@@ -256,6 +364,16 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + + @Override + protected void customServerAiStep() { ++ // Purpur start ++ if (getRider() != null && this.isControllable()) { ++ Vec3 mot = getDeltaMovement(); ++ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z()); ++ } ++ if (shootCooldown > 0) { ++ shootCooldown--; ++ } ++ // Purpur end ++ + int i; + + if (this.getInvulnerableTicks() > 0) { +@@ -583,11 +701,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + } + + public int getAlternativeTarget(int headIndex) { +- return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex)); ++ return getRider() != null && this.isControllable() ? 0 : this.entityData.get(WitherBoss.DATA_TARGETS.get(headIndex)); // Purpur + } + + public void setAlternativeTarget(int headIndex, int id) { +- this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id); ++ if (getRider() == null || !this.isControllable()) this.entityData.set(WitherBoss.DATA_TARGETS.get(headIndex), id); // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index e5bb1baa22db202a6d17ef639bc4940ed1605337..4188d8b564999ba3befa53e78f103a6d2777845f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -69,12 +69,14 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new RestrictSunGoal(this)); + this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0D, 1.2D)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java +index 4595b734abb88df7da6dddf7b24c6c5ffcf6556a..d195edea9b898e230d7837b8ab4eb7c5d4ddfaf2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java +@@ -32,6 +32,7 @@ public class Blaze extends Monster { + + public Blaze(EntityType type, Level world) { + super(type, world); ++ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); // Purpur + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 0.0F); +@@ -39,19 +40,55 @@ public class Blaze extends Monster { + this.xpReward = 10; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.blazeRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.blazeRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.blazeControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.blazeMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(4, new Blaze.BlazeAttackGoal(this)); + this.goalSelector.addGoal(5, new MoveTowardsRestrictionGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, (double)0.23F).add(Attributes.FOLLOW_RANGE, 48.0D); ++ return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, (double)0.23F).add(Attributes.FOLLOW_RANGE, 48.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur + } + + @Override +@@ -106,6 +143,14 @@ public class Blaze extends Monster { + + @Override + protected void customServerAiStep() { ++ // Purpur start ++ if (getRider() != null && this.isControllable()) { ++ Vec3 mot = getDeltaMovement(); ++ setDeltaMovement(mot.x(), getVerticalMot() > 0 ? 0.07D : -0.07D, mot.z()); ++ return; ++ } ++ // Purpur end ++ + --this.nextHeightOffsetChangeTick; + if (this.nextHeightOffsetChangeTick <= 0) { + this.nextHeightOffsetChangeTick = 100; +diff --git a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java +index d980b906d9206560741576fa4153c57212f307a0..790d4abbc8e0b288e20e72e63f8190e938e2fecb 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java +@@ -28,6 +28,23 @@ public class CaveSpider extends Spider { + return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.caveSpiderRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.caveSpiderRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.caveSpiderControllable; ++ } ++ // Purpur end ++ + @Override + public boolean doHurtTarget(Entity target) { + if (super.doHurtTarget(target)) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +index f9193f8cd3b0d0e689a523c7142a897c342c2931..1476372a78092b103c037028f08cb1eae9464706 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -60,21 +60,98 @@ public class Creeper extends Monster implements PowerableMob { + public int maxSwell = 30; + public int explosionRadius = 3; + private int droppedSkulls; ++ // Purpur start ++ private int spacebarCharge = 0; ++ private int prevSpacebarCharge = 0; ++ private int powerToggleDelay = 0; ++ // Purpur end + + public Creeper(EntityType type, Level world) { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.creeperRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.creeperRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.creeperControllable; ++ } ++ ++ @Override ++ protected void customServerAiStep() { ++ if (powerToggleDelay > 0) { ++ powerToggleDelay--; ++ } ++ if (getRider() != null && this.isControllable()) { ++ if (getRider().getForwardMot() != 0 || getRider().getStrafeMot() != 0) { ++ spacebarCharge = 0; ++ setIgnited(false); ++ setSwellDir(-1); ++ } ++ if (spacebarCharge == prevSpacebarCharge) { ++ spacebarCharge = 0; ++ } ++ prevSpacebarCharge = spacebarCharge; ++ } ++ super.customServerAiStep(); ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setIgnited(false); ++ setSwellDir(-1); ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (powerToggleDelay > 0) { ++ return true; // just toggled power, do not jump or ignite ++ } ++ spacebarCharge++; ++ if (spacebarCharge > maxSwell - 2) { ++ spacebarCharge = 0; ++ if (getRider() != null && getRider().getBukkitEntity().hasPermission("allow.powered.creeper")) { ++ powerToggleDelay = 20; ++ setPowered(!isPowered()); ++ setIgnited(false); ++ setSwellDir(-1); ++ return true; ++ } ++ } ++ if (!isIgnited()) { ++ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0 && ++ getRider().getBukkitEntity().hasPermission("allow.special.creeper")) { ++ setIgnited(true); ++ setSwellDir(1); ++ return true; ++ } ++ } ++ return getForwardMot() == 0 && getStrafeMot() == 0; // do not jump if standing still ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new SwellGoal(this)); ++ this.goalSelector.addGoal(3, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0D, 1.2D)); + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0D, 1.2D)); + this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + } +@@ -318,6 +395,7 @@ public class Creeper extends Monster implements PowerableMob { + com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); + if (event.callEvent()) { + this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); ++ if (!event.isIgnited()) setSwellDir(-1); // Purpur + } + } + // Paper end +diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +index 1b1305f5eaf5710b72c57ab4c3953e703a23f1e0..869a2ee5e0775cc477fb56063dfa4ce4a0c6e3f2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +@@ -68,6 +68,23 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.groundNavigation = new GroundPathNavigation(this, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.drownedRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.drownedRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.drownedControllable; ++ } ++ // Purpur end ++ + @Override + protected void addBehaviourGoals() { + this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); +@@ -254,8 +271,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.searchingForLand = targetingUnderwater; + } + +- private static class DrownedMoveControl extends MoveControl { +- ++ private static class DrownedMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + private final Drowned drowned; + + public DrownedMoveControl(Drowned drowned) { +@@ -264,7 +280,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + LivingEntity entityliving = this.drowned.getTarget(); + + if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { +@@ -287,7 +303,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + + this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); + this.drowned.yBodyRot = this.drowned.getYRot(); +- float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f1 = (float) (this.getSpeedModifier() * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur + float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); + + this.drowned.setSpeed(f2); +@@ -297,7 +313,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D)); + } + +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +index 0da2eecda83ba4e4acd4dd0603c77066d4fd060f..1bf856171a9eccf77857232a30d6327b9d8017c6 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -33,6 +33,23 @@ public class ElderGuardian extends Guardian { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.elderGuardianRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.elderGuardianControllable; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index f22e615dba31619c97bf58930da060476a52facf..94dbdbd161202e346e1c496924139a18f6cdf9fe 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -87,9 +87,27 @@ public class EnderMan extends Monster implements NeutralMob { + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.endermanRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.endermanRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.endermanControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); +@@ -97,6 +115,7 @@ public class EnderMan extends Monster implements NeutralMob { + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(10, new EnderMan.EndermanLeaveBlockGoal(this)); + this.goalSelector.addGoal(11, new EnderMan.EndermanTakeBlockGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt)); + this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false)); +@@ -278,7 +297,7 @@ public class EnderMan extends Monster implements NeutralMob { + + @Override + protected void customServerAiStep() { +- if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { ++ if ((getRider() == null || !this.isControllable()) && this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - no random teleporting + float f = this.getLightLevelDependentMagicValue(); + + if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper +@@ -382,6 +401,7 @@ public class EnderMan extends Monster implements NeutralMob { + public boolean hurt(DamageSource source, float amount) { + if (this.isInvulnerableTo(source)) { + return false; ++ } else if (getRider() != null && this.isControllable()) { return super.hurt(source, amount); // Purpur - no teleporting on damage + } else if (source instanceof IndirectEntityDamageSource) { + Entity entity = source.getDirectEntity(); + boolean flag; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Endermite.java b/src/main/java/net/minecraft/world/entity/monster/Endermite.java +index d5b4733915ff0f3219ada055a1bf88a871bec452..8fe770c5d5ed990edd94d707827cba02222975ff 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Endermite.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Endermite.java +@@ -37,14 +37,33 @@ public class Endermite extends Monster { + this.xpReward = 3; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.endermiteRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.endermiteRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.endermiteControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level)); + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +index 7f695625134ba55f85c54efddd049e167e0d1d8b..169a19b605a4b7edda0d1d04e83d9bb5ea554b99 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +@@ -48,10 +48,28 @@ public class Evoker extends SpellcasterIllager { + this.xpReward = 10; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.evokerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.evokerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.evokerControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal()); + this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D)); + this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal()); +@@ -60,6 +78,7 @@ public class Evoker extends SpellcasterIllager { + this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Ghast.java b/src/main/java/net/minecraft/world/entity/monster/Ghast.java +index bb2cb17e4e5ce142eeec18951c8948e3d6b3209c..612ef4aa63b6076a69bfd830282394c49bff205a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Ghast.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Ghast.java +@@ -44,11 +44,47 @@ public class Ghast extends FlyingMob implements Enemy { + this.moveControl = new Ghast.GhastMoveControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.ghastRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.ghastRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.ghastControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.ghastMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(5, new Ghast.RandomFloatAroundGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { + return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; + })); +@@ -103,7 +139,7 @@ public class Ghast extends FlyingMob implements Enemy { + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur + } + + @Override +@@ -160,7 +196,7 @@ public class Ghast extends FlyingMob implements Enemy { + return 2.6F; + } + +- private static class GhastMoveControl extends MoveControl { ++ private static class GhastMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur + + private final Ghast ghast; + private int floatDuration; +@@ -171,7 +207,7 @@ public class Ghast extends FlyingMob implements Enemy { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.operation == MoveControl.Operation.MOVE_TO) { + if (this.floatDuration-- <= 0) { + this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java +index 41004c28edb748e12c4f868aa07b4672891197c1..e310f4c451d751f4ce03562c9e3db3be313fa7db 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Giant.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java +@@ -14,6 +14,29 @@ public class Giant extends Monster { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.giantRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.giantRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.giantControllable; ++ } ++ ++ @Override ++ protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); ++ } ++ // Purpur end ++ + @Override + protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { + return 10.440001F; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Guardian.java b/src/main/java/net/minecraft/world/entity/monster/Guardian.java +index 2f43700c01a0f0a4749f56d3f6294cf648b10f51..01157172c06e022996b25ea0f566ebf703b2b3a8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java +@@ -65,14 +65,40 @@ public class Guardian extends Monster { + this.xpReward = 10; + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + this.moveControl = new Guardian.GuardianMoveControl(this); ++ // Purpur start ++ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) { ++ @Override ++ public void setYawPitch(float yaw, float pitch) { ++ super.setYawPitch(yaw, pitch * 0.35F); ++ } ++ }; ++ // Purpur end + this.clientSideTailAnimation = this.random.nextFloat(); + this.clientSideTailAnimationO = this.clientSideTailAnimation; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.guardianRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.guardianControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0D); + this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); + this.goalSelector.addGoal(5, moveTowardsRestrictionGoal); + this.goalSelector.addGoal(7, this.randomStrollGoal); +@@ -81,6 +107,7 @@ public class Guardian extends Monster { + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); + this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); + moveTowardsRestrictionGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); + } + +@@ -330,7 +357,7 @@ public class Guardian extends Monster { + @Override + public void travel(Vec3 movementInput) { + if (this.isEffectiveAi() && this.isInWater()) { +- this.moveRelative(0.1F, movementInput); ++ this.moveRelative(getRider() != null && this.isControllable() ? getSpeed() : 0.1F, movementInput); // Purpur + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (!this.isMoving() && this.getTarget() == null) { +@@ -437,7 +464,7 @@ public class Guardian extends Monster { + } + } + +- static class GuardianMoveControl extends MoveControl { ++ static class GuardianMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur + private final Guardian guardian; + + public GuardianMoveControl(Guardian guardian) { +@@ -445,8 +472,17 @@ public class Guardian extends Monster { + this.guardian = guardian; + } + ++ // Purpur start + @Override +- public void tick() { ++ public void purpurTick(Player rider) { ++ super.purpurTick(rider); ++ guardian.setDeltaMovement(guardian.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); ++ guardian.setMoving(guardian.getForwardMot() > 0.0F); // control tail speed ++ } ++ // Purpur end ++ ++ @Override ++ public void vanillaTick() { // Purpur + if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { + Vec3 vec3 = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); + double d = vec3.length(); +@@ -456,7 +492,7 @@ public class Guardian extends Monster { + float h = (float)(Mth.atan2(vec3.z, vec3.x) * (double)(180F / (float)Math.PI)) - 90.0F; + this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), h, 90.0F)); + this.guardian.yBodyRot = this.guardian.getYRot(); +- float i = (float)(this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float i = (float)(this.getSpeedModifier() * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur + float j = Mth.lerp(0.125F, this.guardian.getSpeed(), i); + this.guardian.setSpeed(j); + double k = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.5D) * 0.05D; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Husk.java b/src/main/java/net/minecraft/world/entity/monster/Husk.java +index 4996347c6dde85a2dc9aa37fdf495160093fac64..87e77fe01c9ffbbc6bcc2f8d4c10545481155bf0 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Husk.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Husk.java +@@ -22,6 +22,23 @@ public class Husk extends Zombie { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.huskRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.huskRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.huskControllable; ++ } ++ // Purpur end ++ + public static boolean checkHuskSpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { + return checkMonsterSpawnRules(type, world, spawnReason, pos, random) && (spawnReason == MobSpawnType.SPAWNER || world.canSeeSky(pos)); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index 86f7fdd42461db151221d2c0d5cff6953392fa80..98c85e31a2238cbfa31c12214ade49c4ba181702 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -59,10 +59,28 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.illusionerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.illusionerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.illusionerControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal()); + this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal()); + this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal()); +@@ -70,6 +88,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +index ea4fa9eba301e462c159cdb970079f6d87d25f4d..3a2261687ec8b3b1f69b89ceeb2cc8cc524ab57a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java ++++ b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +@@ -25,6 +25,28 @@ public class MagmaCube extends Slime { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.magmaCubeRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.magmaCubeRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.magmaCubeControllable; ++ } ++ ++ @Override ++ public float getJumpPower() { ++ return 0.42F * this.getBlockJumpFactor(); // from EntityLiving ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, (double)0.2F); + } +@@ -70,10 +92,11 @@ public class MagmaCube extends Slime { + } + + @Override +- protected void jumpFromGround() { ++ public void jumpFromGround() { // Purpur - protected -> public + Vec3 vec3 = this.getDeltaMovement(); + this.setDeltaMovement(vec3.x, (double)(this.getJumpPower() + (float)this.getSize() * 0.1F), vec3.z); + this.hasImpulse = true; ++ this.actualJump = false; // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index b55640ed068becd40cbb7d7507b4e67ae9ee792a..79c2f0482a7adbd50e1063edf2839f4fb3ab0847 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -60,6 +60,64 @@ public class Phantom extends FlyingMob implements Enemy { + this.lookControl = new Phantom.PhantomLookControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.phantomRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.phantomRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.phantomControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.phantomMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable() && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ ++ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() { ++ return Monster.createMonsterAttributes().add(Attributes.FLYING_SPEED, 3.0D); ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (getRider() != null && getRider().getBukkitEntity().hasPermission("allow.special.phantom")) { ++ shoot(); ++ } ++ return false; ++ } ++ ++ public boolean shoot() { ++ org.bukkit.Location loc = ((org.bukkit.entity.LivingEntity) getBukkitEntity()).getEyeLocation(); ++ loc.setPitch(-loc.getPitch()); ++ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(100).add(loc.toVector()); ++ ++ org.purpurmc.purpur.entity.PhantomFlames flames = new org.purpurmc.purpur.entity.PhantomFlames(level, this); ++ flames.canGrief = level.purpurConfig.phantomAllowGriefing; ++ flames.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), 1.0F, 5.0F); ++ level.addFreshEntity(flames); ++ return true; ++ } ++ // Purpur end ++ + @Override + public boolean isFlapping() { + return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0; +@@ -72,9 +130,11 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal()); + this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal()); + this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal()); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); + } + +@@ -145,6 +205,7 @@ public class Phantom extends FlyingMob implements Enemy { + @Override + public void aiStep() { + if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning ++ if (getRider() == null || !this.isControllable()) // Purpur + this.setSecondsOnFire(8); + } + +@@ -264,7 +325,7 @@ public class Phantom extends FlyingMob implements Enemy { + private AttackPhase() {} + } + +- private class PhantomMoveControl extends MoveControl { ++ private class PhantomMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur + + private float speed = 0.1F; + +@@ -272,8 +333,19 @@ public class Phantom extends FlyingMob implements Enemy { + super(entity); + } + ++ // Purpur start ++ public void purpurTick(Player rider) { ++ if (!Phantom.this.onGround) { ++ // phantom is always in motion when flying ++ // TODO - FIX THIS ++ // rider.setForward(1.0F); ++ } ++ super.purpurTick(rider); ++ } ++ // Purpur end ++ + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (Phantom.this.horizontalCollision) { + Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); + this.speed = 0.1F; +@@ -319,14 +391,20 @@ public class Phantom extends FlyingMob implements Enemy { + } + } + +- private class PhantomLookControl extends LookControl { ++ private class PhantomLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + + public PhantomLookControl(Mob entity) { + super(entity); + } + ++ // Purpur start ++ public void purpurTick(Player rider) { ++ setYawPitch(rider.yRot, -rider.xRotO * 0.75F); ++ } ++ // Purpur end ++ + @Override +- public void tick() {} ++ public void vanillaTick() {} // Purpur + } + + private class PhantomBodyRotationControl extends BodyRotationControl { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Pillager.java b/src/main/java/net/minecraft/world/entity/monster/Pillager.java +index 682beb556bbe2b74c0a08e780fa25dcb301c281c..e3e1743e4a8d6ddccdbd08351b3524e6e2bed38c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Pillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Pillager.java +@@ -63,15 +63,34 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.pillagerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.pillagerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.pillagerControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new Raider.HoldGroundAttackGoal(this, 10.0F)); + this.goalSelector.addGoal(3, new RangedCrossbowAttackGoal<>(this, 1.0D, 8.0F)); + this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 15.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 15.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, Raider.class)).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +index f747aa85beab98fbecdbe15b188be6614478bac6..fe4f2690a562601ca64e4969beadc65516edc7b2 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java +@@ -69,14 +69,39 @@ public class Ravager extends Raider { + this.xpReward = 20; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.ravagerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.ravagerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.ravagerControllable; ++ } ++ ++ @Override ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ getNavigation().stop(); ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(4, new Ravager.RavagerMeleeAttackGoal()); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> { +@@ -151,7 +176,7 @@ public class Ravager extends Raider { + @Override + public void aiStep() { + super.aiStep(); +- if (this.isAlive()) { ++ if (this.isAlive() && (getRider() == null || !this.isControllable())) { // Purpur + if (this.isImmobile()) { + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0D); + } else { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java +index 524eed4042c7a83eb8b4a0769a66330dd141261d..7db7e4ae2ad164dd622ab9b803a5e395dff08ea5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java +@@ -92,12 +92,31 @@ public class Shulker extends AbstractGolem implements Enemy { + this.lookControl = new Shulker.ShulkerLookControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.shulkerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.shulkerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.shulkerControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true)); + this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal()); + this.goalSelector.addGoal(7, new Shulker.ShulkerPeekGoal()); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{this.getClass()})).setAlertOthers()); + this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this)); + this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this)); +@@ -599,7 +618,7 @@ public class Shulker extends AbstractGolem implements Enemy { + return b0 != 16 && b0 <= 15 ? DyeColor.byId(b0) : null; + } + +- private class ShulkerLookControl extends LookControl { ++ private class ShulkerLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + + public ShulkerLookControl(Mob entity) { + super(entity); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +index 2dcda3b03796655da443e1b3dd68c6f6bca20d21..5f1f9ecb06555f15a464efa27f06a5dbdd255c1e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +@@ -42,14 +42,33 @@ public class Silverfish extends Monster { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.silverfishRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.silverfishRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.silverfishControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.friendsGoal = new Silverfish.SilverfishWakeUpFriendsGoal(this); + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level)); + this.goalSelector.addGoal(3, this.friendsGoal); + this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java +index 3a3f3358c4bbd16bdcadc56c6a865ecfb942ad54..e73644f453bed8523bfad47764018362a416b5ea 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java +@@ -25,6 +25,23 @@ public class Skeleton extends AbstractSkeleton { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.skeletonRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.skeletonRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.skeletonControllable; ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 0c5ca7fabb7dc95587bae72d714d4712bdf0cc40..14be612dbef97f26f7a0bb145452e44e9d50edb5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -64,18 +64,55 @@ public class Slime extends Mob implements Enemy { + public float squish; + public float oSquish; + private boolean wasOnGround; ++ protected boolean actualJump; // Purpur + + public Slime(EntityType type, Level world) { + super(type, world); + this.moveControl = new Slime.SlimeMoveControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.slimeRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.slimeRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.slimeControllable; ++ } ++ ++ @Override ++ public float getJumpPower() { ++ float height = super.getJumpPower(); ++ return getRider() != null && this.isControllable() && actualJump ? height * 1.5F : height; ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (onGround && getRider() != null && this.isControllable()) { ++ actualJump = true; ++ if (getRider().getForwardMot() == 0 || getRider().getStrafeMot() == 0) { ++ jumpFromGround(); // jump() here if not moving ++ } ++ } ++ return true; // do not jump() in wasd controller, let vanilla controller handle ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Slime.SlimeFloatGoal(this)); + this.goalSelector.addGoal(2, new Slime.SlimeAttackGoal(this)); + this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this)); + this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { + return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; + })); +@@ -366,11 +403,12 @@ public class Slime extends Mob implements Enemy { + } + + @Override +- protected void jumpFromGround() { ++ public void jumpFromGround() { // Purpur - protected -> public + Vec3 vec3d = this.getDeltaMovement(); + + this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + this.hasImpulse = true; ++ this.actualJump = false; // Purpur + } + + @Nullable +@@ -404,7 +442,7 @@ public class Slime extends Mob implements Enemy { + return super.getDimensions(pose).scale(0.255F * (float) this.getSize()); + } + +- private static class SlimeMoveControl extends MoveControl { ++ private static class SlimeMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + + private float yRot; + private int jumpDelay; +@@ -423,21 +461,33 @@ public class Slime extends Mob implements Enemy { + } + + public void setWantedMovement(double speed) { +- this.speedModifier = speed; ++ this.setSpeedModifier(speed); // Purpur + this.operation = MoveControl.Operation.MOVE_TO; + } + + @Override + public void tick() { ++ // Purpur start ++ if (slime.getRider() != null && slime.isControllable()) { ++ purpurTick(slime.getRider()); ++ if (slime.getForwardMot() != 0 || slime.getStrafeMot() != 0) { ++ if (jumpDelay > 10) { ++ jumpDelay = 6; ++ } ++ } else { ++ jumpDelay = 20; ++ } ++ } else { ++ // Purpur end + this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); + this.mob.yHeadRot = this.mob.getYRot(); + this.mob.yBodyRot = this.mob.getYRot(); +- if (this.operation != MoveControl.Operation.MOVE_TO) { ++ } if ((slime.getRider() == null || !slime.isControllable()) && this.operation != MoveControl.Operation.MOVE_TO) { // Purpur + this.mob.setZza(0.0F); + } else { + this.operation = MoveControl.Operation.WAIT; + if (this.mob.isOnGround()) { +- this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ this.mob.setSpeed((float) (this.getSpeedModifier() * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED) * (slime.getRider() != null && slime.isControllable() && (slime.getRider().getForwardMot() != 0 || slime.getRider().getStrafeMot() != 0) ? 2.0D : 1.0D))); // Purpur + if (this.jumpDelay-- <= 0) { + this.jumpDelay = this.slime.getJumpDelay(); + if (this.isAggressive) { +@@ -454,7 +504,7 @@ public class Slime extends Mob implements Enemy { + this.mob.setSpeed(0.0F); + } + } else { +- this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ this.mob.setSpeed((float) (this.getSpeedModifier() * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED) * (slime.getRider() != null && slime.isControllable() && (slime.getRider().getForwardMot() != 0 || slime.getRider().getStrafeMot() != 0) ? 2.0D : 1.0D))); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java +index 694643c8ee7447da01ae02ca242338dbdbb3412a..2a0821c288dd07d7a87f5df91d04d739030fa3c5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java +@@ -51,14 +51,33 @@ public class Spider extends Monster { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.spiderRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.spiderRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.spiderControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4F)); + this.goalSelector.addGoal(4, new Spider.SpiderAttackGoal(this)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class)); + this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Stray.java b/src/main/java/net/minecraft/world/entity/monster/Stray.java +index 118b636a44e4b062e812e433f603b039276337da..5737b1b2c2882e67082e2c0243b192ac1d50f8b7 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Stray.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Stray.java +@@ -21,6 +21,23 @@ public class Stray extends AbstractSkeleton { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.strayRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.strayRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.strayControllable; ++ } ++ // Purpur end ++ + public static boolean checkStraySpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { + BlockPos blockPos = pos; + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Strider.java b/src/main/java/net/minecraft/world/entity/monster/Strider.java +index 8ff4aa933b80eee45fbc1fdf6ce19110bef31b49..7bdb28de468681884f1cffdda207932ba0412a06 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Strider.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Strider.java +@@ -96,6 +96,23 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, 0.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.striderRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.striderRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.striderControllable; ++ } ++ // Purpur end ++ + public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +@@ -157,6 +174,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { + @Override + protected void registerGoals() { + this.panicGoal = new PanicGoal(this, 1.65D); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, this.panicGoal); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.temptGoal = new TemptGoal(this, 1.4D, Strider.TEMPT_ITEMS, false); +@@ -439,7 +457,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { + if (!enuminteractionresult.consumesAction()) { + ItemStack itemstack = player.getItemInHand(hand); + +- return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : tryRide(player, hand); // Purpur + } else { + if (flag && !this.isSilent()) { + this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java +index 78b1fb5e163cbe6b95ab39aa3b1b33da95c62cee..9bc60081a1d3f63f3b452ee5a8c8ae327f64b16e 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java +@@ -59,6 +59,50 @@ public class Vex extends Monster { + this.xpReward = 3; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.vexRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.vexRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.vexControllable; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.vexMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && this.isControllable()) { ++ float speed; ++ if (onGround) { ++ speed = (float) getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.1F; ++ } else { ++ speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ } ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(MoverType.SELF, mot.multiply(speed, 1.0, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ ++ @Override ++ public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { ++ return false; // no fall damage please ++ } ++ // Purpur end ++ + @Override + public boolean isFlapping() { + return this.tickCount % Vex.TICKS_PER_FLAP == 0; +@@ -72,7 +116,7 @@ public class Vex extends Monster { + + @Override + public void tick() { +- this.noPhysics = true; ++ this.noPhysics = getRider() == null || !this.isControllable(); // Purpur + super.tick(); + this.noPhysics = false; + this.setNoGravity(true); +@@ -87,17 +131,19 @@ public class Vex extends Monster { + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(4, new Vex.VexChargeAttackGoal()); + this.goalSelector.addGoal(8, new Vex.VexRandomMoveGoal()); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(2, new Vex.VexCopyOwnerTargetGoal(this)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur; + } + + @Override +@@ -220,14 +266,14 @@ public class Vex extends Monster { + this.setDropChance(EquipmentSlot.MAINHAND, 0.0F); + } + +- private class VexMoveControl extends MoveControl { ++ private class VexMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur + + public VexMoveControl(Vex entityvex) { + super(entityvex); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.operation == MoveControl.Operation.MOVE_TO) { + Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); + double d0 = vec3d.length(); +@@ -236,7 +282,7 @@ public class Vex extends Monster { + this.operation = MoveControl.Operation.WAIT; + Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D)); + } else { +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.speedModifier * 0.05D / d0))); ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.getSpeedModifier() * 0.05D / d0))); // Purpur + if (Vex.this.getTarget() == null) { + Vec3 vec3d1 = Vex.this.getDeltaMovement(); + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 8914a0e2aab28fe2198f8e117f206abffae8b7d0..5f550e683b61ef3312f4500e43d6723fcbdef214 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -58,14 +58,33 @@ public class Vindicator extends AbstractIllager { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.vindicatorRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.vindicatorRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.vindicatorControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Vindicator.VindicatorBreakDoorGoal(this)); + this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); + this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); + this.goalSelector.addGoal(4, new Vindicator.VindicatorMeleeAttackGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, Raider.class)).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index f9eb4a3a37454de78c65f895a82e67a854b6909b..7775f1428a455f0d52f43ed07102cb242f6d23ad 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -59,6 +59,23 @@ public class Witch extends Raider implements RangedAttackMob { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.witchRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.witchRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.witchControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); +@@ -67,10 +84,12 @@ public class Witch extends Raider implements RangedAttackMob { + }); + this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null); + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 60, 10.0F)); + this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(3, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[]{Raider.class})); + this.targetSelector.addGoal(2, this.healRaidersGoal); + this.targetSelector.addGoal(3, this.attackPlayersGoal); +diff --git a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java +index c65319caa4bf95bd1d3bc41811b9cd401cc5c705..7259a56007ac0af079a4794952f69bf2706841c8 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -35,6 +35,23 @@ public class WitherSkeleton extends AbstractSkeleton { + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.witherSkeletonRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.witherSkeletonRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.witherSkeletonControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java +index 056e4c2f7f632dadc0015710c032a0b718d46ff9..a6aaffc41a39be4ae1da44d54a27d324927e47d0 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java +@@ -68,6 +68,23 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { + this.xpReward = 5; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.zoglinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zoglinRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.zoglinControllable; ++ } ++ // Purpur end ++ + @Override + protected Brain.Provider brainProvider() { + return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); +@@ -90,11 +107,11 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { + } + + private static void initIdleActivity(Brain brain) { +- brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new StartAttacking<>(Zoglin::findNearestValidAttackTarget), new RunSometimes(new SetEntityLookTarget(8.0F), UniformInt.of(30, 60)), new RunOne(ImmutableList.of(Pair.of(new RandomStroll(0.4F), 2), Pair.of(new SetWalkTargetFromLookTarget(0.4F, 3), 2), Pair.of(new DoNothing(30, 60), 1))))); ++ brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new StartAttacking<>(Zoglin::findNearestValidAttackTarget), new RunSometimes<>(new SetEntityLookTarget(8.0F), UniformInt.of(30, 60)), new RunOne<>(ImmutableList.of(Pair.of(new RandomStroll(0.4F), 2), Pair.of(new SetWalkTargetFromLookTarget(0.4F, 3), 2), Pair.of(new DoNothing(30, 60), 1))))); // Purpur - decompile fix + } + + private static void initFightActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(new SetWalkTargetFromAttackTargetIfTargetOutOfReach(1.0F), new RunIf<>(Zoglin::isAdult, new MeleeAttack(40)), new RunIf<>(Zoglin::isBaby, new MeleeAttack(15)), new StopAttackingIfTargetInvalid()), MemoryModuleType.ATTACK_TARGET); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(new SetWalkTargetFromAttackTargetIfTargetOutOfReach(1.0F), new RunIf<>(Zoglin::isAdult, new MeleeAttack(40)), new RunIf<>(Zoglin::isBaby, new MeleeAttack(15)), new StopAttackingIfTargetInvalid<>()), MemoryModuleType.ATTACK_TARGET); // Purpur - decompile fix + } + + private Optional findNearestValidAttackTarget() { +@@ -183,7 +200,7 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { + + @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // Purpur - decompile error + } + + protected void updateActivity() { +@@ -200,6 +217,7 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { + @Override + protected void customServerAiStep() { + this.level.getProfiler().push("zoglinBrain"); ++ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider + this.getBrain().tick((ServerLevel)this.level, this); + this.level.getProfiler().pop(); + this.updateActivity(); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 7b01bd1409dcb64c097badbbd73110d40e712751..87676587c71306f38e25d0f9548132526a7e481f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -104,11 +104,30 @@ public class Zombie extends Monster { + this(EntityType.ZOMBIE, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.zombieRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zombieRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.zombieControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.addBehaviourGoals(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +index b75c0ff18aa7adb673fbb2b5ada7775dd8ac1e29..42f6de4e9277d7208d5e0afb5a80d33f7f81ac46 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -78,6 +78,23 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { + }); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.zombieVillagerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zombieVillagerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.zombieVillagerControllable; ++ } ++ // Purpur end ++ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index d0567234d1261227d29bb254f959604dc91b3c72..cf9f43d1205453af88ffdc2e96fe4376ecd45fbf 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -59,6 +59,23 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.zombifiedPiglinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zombifiedPiglinRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.zombifiedPiglinControllable; ++ } ++ // Purpur end ++ + @Override + public void setPersistentAngerTarget(@Nullable UUID angryAt) { + this.persistentAngerTarget = angryAt; +diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java +index 45741410a13cffe3419e34b5607b048bbcf1c3ff..8e93f0c152a5ac98588b3afaa631ebbbc9e4ed79 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java +@@ -67,6 +67,23 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { + this.xpReward = 5; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.hoglinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.hoglinRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.hoglinControllable; ++ } ++ // Purpur end ++ + @Override + public boolean canBeLeashed(Player player) { + return !this.isLeashed(); +@@ -129,6 +146,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { + @Override + protected void customServerAiStep() { + this.level.getProfiler().push("hoglinBrain"); ++ if (getRider() == null || !this.isControllable())// Purpur - only use brain if no rider + this.getBrain().tick((ServerLevel)this.level, this); + this.level.getProfiler().pop(); + HoglinAi.updateActivity(this); +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +index 793576928dad6752dddd86e62d4c0800d8515fc4..d30e9c880323481695824f39abc1cb02204bfe44 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -95,6 +95,23 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + this.xpReward = 5; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.piglinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.piglinRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.piglinControllable; ++ } ++ // Purpur end ++ + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); +@@ -292,6 +309,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + @Override + protected void customServerAiStep() { + this.level.getProfiler().push("piglinBrain"); ++ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider + this.getBrain().tick((ServerLevel) this.level, this); + this.level.getProfiler().pop(); + PiglinAi.updateActivity(this); +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +index ac75c54e897565e340b66823caeed92ba1d1641a..ff149234a8f3e1c94961e41d5bc8117460b301d9 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +@@ -41,6 +41,23 @@ public class PiglinBrute extends AbstractPiglin { + this.xpReward = 20; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.piglinBruteRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.piglinBruteRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.piglinBruteControllable; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 50.0D).add(Attributes.MOVEMENT_SPEED, (double)0.35F).add(Attributes.ATTACK_DAMAGE, 7.0D); + } +@@ -70,7 +87,7 @@ public class PiglinBrute extends AbstractPiglin { + + @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // Purpur - decompile error + } + + @Override +@@ -86,6 +103,7 @@ public class PiglinBrute extends AbstractPiglin { + @Override + protected void customServerAiStep() { + this.level.getProfiler().push("piglinBruteBrain"); ++ if (getRider() == null || this.isControllable()) // Purpur - only use brain if no rider + this.getBrain().tick((ServerLevel)this.level, this); + this.level.getProfiler().pop(); + PiglinBruteAi.updateActivity(this); +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 98debcec829ddaa9d37b7e9cc1f42dfd9123393c..75fbf7f29e1cb90f87a4ba074f4ce256c810a3f8 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -153,6 +153,28 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.setVillagerData(this.getVillagerData().setType(type).setProfession(VillagerProfession.NONE)); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.villagerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.villagerRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.villagerControllable; ++ } ++ ++ @Override ++ protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); ++ } ++ // Purpur end ++ + @Override + public Brain getBrain() { + return (Brain) super.getBrain(); // CraftBukkit - decompile error +@@ -247,6 +269,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + protected void customServerAiStep() { mobTick(false); } + protected void mobTick(boolean inactive) { + this.level.getProfiler().push("villagerBrain"); ++ if (getRider() == null || !this.isControllable())// Purpur - only use brain if no rider + if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // Paper + this.level.getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { +@@ -304,7 +327,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) { + if (this.isBaby()) { + this.setUnhappy(); +- return InteractionResult.sidedSuccess(this.level.isClientSide); ++ return tryRide(player, hand); // Purpur + } else { + boolean flag = this.getOffers().isEmpty(); + +@@ -317,8 +340,9 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + if (flag) { +- return InteractionResult.sidedSuccess(this.level.isClientSide); ++ return tryRide(player, hand); // Purpur + } else { ++ if (level.purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(player, hand); // Purpur + if (!this.level.isClientSide && !this.offers.isEmpty()) { + this.startTrading(player); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 86e1ba898d6b92735258419fa74352e5116226dc..2ae9a5da91ad20f1b566a686dcc8d4f14c62ecc5 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -66,6 +66,23 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. + } + ++ // Purpur - start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.wanderingTraderRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.wanderingTraderRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level.purpurConfig.wanderingTraderControllable; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -113,8 +130,9 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + } + + if (this.getOffers().isEmpty()) { +- return InteractionResult.sidedSuccess(this.level.isClientSide); ++ return tryRide(player, hand); // Purpur + } else { ++ if (level.purpurConfig.wanderingTraderRidable && itemstack.isEmpty()) return tryRide(player, hand); // Purpur + if (!this.level.isClientSide) { + this.setTradingPlayer(player); + this.openTradingScreen(player, this.getDisplayName(), 1); +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 2987d675af3b778d20be66e2ac2cddf6b4957d1d..4a04249441959340ad5f3a1879edd21208c7a9dc 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -197,6 +197,19 @@ public abstract class Player extends LivingEntity { + } + // CraftBukkit end + ++ // Purpur start ++ public abstract void resetLastActionTime(); ++ ++ @Override ++ public boolean processClick(InteractionHand hand) { ++ Entity vehicle = getRootVehicle(); ++ if (vehicle != null && vehicle.getRider() == this) { ++ return vehicle.onClick(hand); ++ } ++ return false; ++ } ++ // Purpur end ++ + public Player(Level world, BlockPos pos, float yaw, GameProfile gameProfile, @Nullable ProfilePublicKey publicKey) { + super(EntityType.PLAYER, world); + this.lastItemInMainHand = ItemStack.EMPTY; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +index 4132c1113f5437a776e5e3c1cb306904775aed88..1a945a32c3d3705a318ebca72a365931a8c001b7 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -27,6 +27,12 @@ public class LlamaSpit extends Projectile { + this.setPos(owner.getX() - (double) (owner.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(owner.yBodyRot * 0.017453292F), owner.getEyeY() - 0.10000000149011612D, owner.getZ() + (double) (owner.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(owner.yBodyRot * 0.017453292F)); + } + ++ // Purpur start ++ public void super_tick() { ++ super.tick(); ++ } ++ // Purpur end ++ + @Override + public void tick() { + super.tick(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 5b92c2ca03baed38f7d41a73fae7dd23ce541d43..3cc9dab362141fdf61bdcd542ffa5e5c11f99e24 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1322,4 +1322,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed. + } + // Paper end ++ ++ // Purpur start ++ @Override ++ public org.bukkit.entity.Player getRider() { ++ Player rider = getHandle().getRider(); ++ return rider != null ? (org.bukkit.entity.Player) rider.getBukkitEntity() : null; ++ } ++ ++ @Override ++ public boolean hasRider() { ++ return getHandle().getRider() != null; ++ } ++ ++ @Override ++ public boolean isRidable() { ++ return getHandle().isRidable(); ++ } ++ ++ @Override ++ public boolean isRidableInWater() { ++ return getHandle().rideableUnderWater(); ++ } ++ // Purpur end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index ceacb62aef0dd0f73f1542a1898ceb62c3f4c367..97108c2317a38e11d45fdbef448dca5cb3ddad1c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -543,6 +543,15 @@ public class CraftEventFactory { + } + craftServer.getPluginManager().callEvent(event); + ++ // Purpur start ++ if (who != null) { ++ switch (action) { ++ case LEFT_CLICK_BLOCK, LEFT_CLICK_AIR -> who.processClick(InteractionHand.MAIN_HAND); ++ case RIGHT_CLICK_BLOCK, RIGHT_CLICK_AIR -> who.processClick(InteractionHand.OFF_HAND); ++ } ++ } ++ // Purpur end ++ + return event; + } + +@@ -979,6 +988,7 @@ public class CraftEventFactory { + damageCause = DamageCause.ENTITY_EXPLOSION; + } + event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions, source.isCritical()); // Paper - add critical damage API ++ damager.processClick(InteractionHand.MAIN_HAND); // Purpur + } + event.setCancelled(cancelled); + +@@ -1083,6 +1093,7 @@ public class CraftEventFactory { + } else { + entity.lastDamageCancelled = true; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled + } ++ damager.getHandle().processClick(InteractionHand.MAIN_HAND); // Purpur + return event; + } + +@@ -1142,6 +1153,7 @@ public class CraftEventFactory { + EntityDamageEvent event; + if (damager != null) { + event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions, critical); // Paper - add critical damage API ++ damager.processClick(InteractionHand.MAIN_HAND); // Purpur + } else { + event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); + } +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index b3bfc56859d00f9e27bd1d230dd19b92985b5718..e8150d1bec60f7e32d5475c8402fd7b53df359e7 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -167,4 +167,9 @@ public class PurpurConfig { + } + return builder.build(); + } ++ ++ public static String cannotRideMob = "You cannot mount that mob"; ++ private static void messages() { ++ cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); ++ } + } +diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +index 0ce93836629522c2ff2a57226583009302271daf..969c78aef40aae497a76dd7f3e9c230577a8d31f 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +@@ -88,4 +88,668 @@ public class PurpurWorldConfig { + final Map value = PurpurConfig.getMap("world-settings." + worldName + "." + path, null); + return value.isEmpty() ? fallback : value; + } ++ ++ public boolean babiesAreRidable = true; ++ public boolean untamedTamablesAreRidable = true; ++ public boolean useNightVisionWhenRiding = false; ++ private void ridableSettings() { ++ babiesAreRidable = getBoolean("ridable-settings.babies-are-ridable", babiesAreRidable); ++ untamedTamablesAreRidable = getBoolean("ridable-settings.untamed-tamables-are-ridable", untamedTamablesAreRidable); ++ useNightVisionWhenRiding = getBoolean("ridable-settings.use-night-vision", useNightVisionWhenRiding); ++ } ++ ++ public boolean axolotlRidable = false; ++ public boolean axolotlControllable = true; ++ private void axolotlSettings() { ++ axolotlRidable = getBoolean("mobs.axolotl.ridable", axolotlRidable); ++ axolotlControllable = getBoolean("mobs.axolotl.controllable", axolotlControllable); ++ } ++ ++ public boolean batRidable = false; ++ public boolean batRidableInWater = false; ++ public boolean batControllable = true; ++ public double batMaxY = 320D; ++ private void batSettings() { ++ batRidable = getBoolean("mobs.bat.ridable", batRidable); ++ batRidableInWater = getBoolean("mobs.bat.ridable-in-water", batRidableInWater); ++ batControllable = getBoolean("mobs.bat.controllable", batControllable); ++ batMaxY = getDouble("mobs.bat.ridable-max-y", batMaxY); ++ } ++ ++ public boolean beeRidable = false; ++ public boolean beeRidableInWater = false; ++ public boolean beeControllable = true; ++ public double beeMaxY = 320D; ++ private void beeSettings() { ++ beeRidable = getBoolean("mobs.bee.ridable", beeRidable); ++ beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater); ++ beeControllable = getBoolean("mobs.bee.controllable", beeControllable); ++ beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY); ++ } ++ ++ public boolean blazeRidable = false; ++ public boolean blazeRidableInWater = false; ++ public boolean blazeControllable = true; ++ public double blazeMaxY = 320D; ++ private void blazeSettings() { ++ blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable); ++ blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater); ++ blazeControllable = getBoolean("mobs.blaze.controllable", blazeControllable); ++ blazeMaxY = getDouble("mobs.blaze.ridable-max-y", blazeMaxY); ++ } ++ ++ public boolean catRidable = false; ++ public boolean catRidableInWater = false; ++ public boolean catControllable = true; ++ private void catSettings() { ++ catRidable = getBoolean("mobs.cat.ridable", catRidable); ++ catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater); ++ catControllable = getBoolean("mobs.cat.controllable", catControllable); ++ } ++ ++ public boolean caveSpiderRidable = false; ++ public boolean caveSpiderRidableInWater = false; ++ public boolean caveSpiderControllable = true; ++ private void caveSpiderSettings() { ++ caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable); ++ caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater); ++ caveSpiderControllable = getBoolean("mobs.cave_spider.controllable", caveSpiderControllable); ++ } ++ ++ public boolean chickenRidable = false; ++ public boolean chickenRidableInWater = false; ++ public boolean chickenControllable = true; ++ private void chickenSettings() { ++ chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable); ++ chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater); ++ chickenControllable = getBoolean("mobs.chicken.controllable", chickenControllable); ++ } ++ ++ public boolean codRidable = false; ++ public boolean codControllable = true; ++ private void codSettings() { ++ codRidable = getBoolean("mobs.cod.ridable", codRidable); ++ codControllable = getBoolean("mobs.cod.controllable", codControllable); ++ } ++ ++ public boolean cowRidable = false; ++ public boolean cowRidableInWater = false; ++ public boolean cowControllable = true; ++ private void cowSettings() { ++ cowRidable = getBoolean("mobs.cow.ridable", cowRidable); ++ cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater); ++ cowControllable = getBoolean("mobs.cow.controllable", cowControllable); ++ } ++ ++ public boolean creeperRidable = false; ++ public boolean creeperRidableInWater = false; ++ public boolean creeperControllable = true; ++ private void creeperSettings() { ++ creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); ++ creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); ++ creeperControllable = getBoolean("mobs.creeper.controllable", creeperControllable); ++ } ++ ++ public boolean dolphinRidable = false; ++ public boolean dolphinControllable = true; ++ public int dolphinSpitCooldown = 20; ++ public float dolphinSpitSpeed = 1.0F; ++ public float dolphinSpitDamage = 2.0F; ++ private void dolphinSettings() { ++ dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable); ++ dolphinControllable = getBoolean("mobs.dolphin.controllable", dolphinControllable); ++ dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown); ++ dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed); ++ dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage); ++ } ++ ++ public boolean donkeyRidableInWater = false; ++ private void donkeySettings() { ++ donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater); ++ } ++ ++ public boolean drownedRidable = false; ++ public boolean drownedRidableInWater = false; ++ public boolean drownedControllable = true; ++ private void drownedSettings() { ++ drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable); ++ drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater); ++ drownedControllable = getBoolean("mobs.drowned.controllable", drownedControllable); ++ } ++ ++ public boolean elderGuardianRidable = false; ++ public boolean elderGuardianControllable = true; ++ private void elderGuardianSettings() { ++ elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable); ++ elderGuardianControllable = getBoolean("mobs.elder_guardian.controllable", elderGuardianControllable); ++ } ++ ++ public boolean enderDragonRidable = false; ++ public boolean enderDragonRidableInWater = false; ++ public boolean enderDragonControllable = true; ++ public double enderDragonMaxY = 320D; ++ private void enderDragonSettings() { ++ enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable); ++ enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater); ++ enderDragonControllable = getBoolean("mobs.ender_dragon.controllable", enderDragonControllable); ++ enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY); ++ } ++ ++ public boolean endermanRidable = false; ++ public boolean endermanRidableInWater = false; ++ public boolean endermanControllable = true; ++ private void endermanSettings() { ++ endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable); ++ endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater); ++ endermanControllable = getBoolean("mobs.enderman.controllable", endermanControllable); ++ } ++ ++ public boolean endermiteRidable = false; ++ public boolean endermiteRidableInWater = false; ++ public boolean endermiteControllable = true; ++ private void endermiteSettings() { ++ endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable); ++ endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater); ++ endermiteControllable = getBoolean("mobs.endermite.controllable", endermiteControllable); ++ } ++ ++ public boolean evokerRidable = false; ++ public boolean evokerRidableInWater = false; ++ public boolean evokerControllable = true; ++ private void evokerSettings() { ++ evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable); ++ evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater); ++ evokerControllable = getBoolean("mobs.evoker.controllable", evokerControllable); ++ } ++ ++ public boolean foxRidable = false; ++ public boolean foxRidableInWater = false; ++ public boolean foxControllable = true; ++ private void foxSettings() { ++ foxRidable = getBoolean("mobs.fox.ridable", foxRidable); ++ foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater); ++ foxControllable = getBoolean("mobs.fox.controllable", foxControllable); ++ } ++ ++ public boolean ghastRidable = false; ++ public boolean ghastRidableInWater = false; ++ public boolean ghastControllable = true; ++ public double ghastMaxY = 320D; ++ private void ghastSettings() { ++ ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable); ++ ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater); ++ ghastControllable = getBoolean("mobs.ghast.controllable", ghastControllable); ++ ghastMaxY = getDouble("mobs.ghast.ridable-max-y", ghastMaxY); ++ } ++ ++ public boolean giantRidable = false; ++ public boolean giantRidableInWater = false; ++ public boolean giantControllable = true; ++ private void giantSettings() { ++ giantRidable = getBoolean("mobs.giant.ridable", giantRidable); ++ giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater); ++ giantControllable = getBoolean("mobs.giant.controllable", giantControllable); ++ } ++ ++ public boolean glowSquidRidable = false; ++ public boolean glowSquidControllable = true; ++ private void glowSquidSettings() { ++ glowSquidRidable = getBoolean("mobs.glow_squid.ridable", glowSquidRidable); ++ glowSquidControllable = getBoolean("mobs.glow_squid.controllable", glowSquidControllable); ++ } ++ ++ public boolean goatRidable = false; ++ public boolean goatRidableInWater = false; ++ public boolean goatControllable = true; ++ private void goatSettings() { ++ goatRidable = getBoolean("mobs.goat.ridable", goatRidable); ++ goatRidableInWater = getBoolean("mobs.goat.ridable-in-water", goatRidableInWater); ++ goatControllable = getBoolean("mobs.goat.controllable", goatControllable); ++ } ++ ++ public boolean guardianRidable = false; ++ public boolean guardianControllable = true; ++ private void guardianSettings() { ++ guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable); ++ guardianControllable = getBoolean("mobs.guardian.controllable", guardianControllable); ++ } ++ ++ public boolean hoglinRidable = false; ++ public boolean hoglinRidableInWater = false; ++ public boolean hoglinControllable = true; ++ private void hoglinSettings() { ++ hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable); ++ hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater); ++ hoglinControllable = getBoolean("mobs.hoglin.controllable", hoglinControllable); ++ } ++ ++ public boolean horseRidableInWater = false; ++ private void horseSettings() { ++ horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater); ++ } ++ ++ public boolean huskRidable = false; ++ public boolean huskRidableInWater = false; ++ public boolean huskControllable = true; ++ private void huskSettings() { ++ huskRidable = getBoolean("mobs.husk.ridable", huskRidable); ++ huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater); ++ huskControllable = getBoolean("mobs.husk.controllable", huskControllable); ++ } ++ ++ public boolean illusionerRidable = false; ++ public boolean illusionerRidableInWater = false; ++ public boolean illusionerControllable = true; ++ private void illusionerSettings() { ++ illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable); ++ illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater); ++ illusionerControllable = getBoolean("mobs.illusioner.controllable", illusionerControllable); ++ } ++ ++ public boolean ironGolemRidable = false; ++ public boolean ironGolemRidableInWater = false; ++ public boolean ironGolemControllable = true; ++ public boolean ironGolemCanSwim = false; ++ private void ironGolemSettings() { ++ ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); ++ ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); ++ ironGolemControllable = getBoolean("mobs.iron_golem.controllable", ironGolemControllable); ++ ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); ++ } ++ ++ public boolean llamaRidable = false; ++ public boolean llamaRidableInWater = false; ++ public boolean llamaControllable = true; ++ private void llamaSettings() { ++ llamaRidable = getBoolean("mobs.llama.ridable", llamaRidable); ++ llamaRidableInWater = getBoolean("mobs.llama.ridable-in-water", llamaRidableInWater); ++ llamaControllable = getBoolean("mobs.llama.controllable", llamaControllable); ++ } ++ ++ public boolean magmaCubeRidable = false; ++ public boolean magmaCubeRidableInWater = false; ++ public boolean magmaCubeControllable = true; ++ private void magmaCubeSettings() { ++ magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable); ++ magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater); ++ magmaCubeControllable = getBoolean("mobs.magma_cube.controllable", magmaCubeControllable); ++ } ++ ++ public boolean mooshroomRidable = false; ++ public boolean mooshroomRidableInWater = false; ++ public boolean mooshroomControllable = true; ++ private void mooshroomSettings() { ++ mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable); ++ mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater); ++ mooshroomControllable = getBoolean("mobs.mooshroom.controllable", mooshroomControllable); ++ } ++ ++ public boolean muleRidableInWater = false; ++ private void muleSettings() { ++ muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater); ++ } ++ ++ public boolean ocelotRidable = false; ++ public boolean ocelotRidableInWater = false; ++ public boolean ocelotControllable = true; ++ private void ocelotSettings() { ++ ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable); ++ ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater); ++ ocelotControllable = getBoolean("mobs.ocelot.controllable", ocelotControllable); ++ } ++ ++ public boolean pandaRidable = false; ++ public boolean pandaRidableInWater = false; ++ public boolean pandaControllable = true; ++ private void pandaSettings() { ++ pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable); ++ pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater); ++ pandaControllable = getBoolean("mobs.panda.controllable", pandaControllable); ++ } ++ ++ public boolean parrotRidable = false; ++ public boolean parrotRidableInWater = false; ++ public boolean parrotControllable = true; ++ public double parrotMaxY = 320D; ++ private void parrotSettings() { ++ parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); ++ parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); ++ parrotControllable = getBoolean("mobs.parrot.controllable", parrotControllable); ++ parrotMaxY = getDouble("mobs.parrot.ridable-max-y", parrotMaxY); ++ } ++ ++ public boolean phantomRidable = false; ++ public boolean phantomRidableInWater = false; ++ public boolean phantomControllable = true; ++ public double phantomMaxY = 320D; ++ public float phantomFlameDamage = 1.0F; ++ public int phantomFlameFireTime = 8; ++ public boolean phantomAllowGriefing = false; ++ private void phantomSettings() { ++ phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable); ++ phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater); ++ phantomControllable = getBoolean("mobs.phantom.controllable", phantomControllable); ++ phantomMaxY = getDouble("mobs.phantom.ridable-max-y", phantomMaxY); ++ phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage); ++ phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime); ++ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing); ++ } ++ ++ public boolean pigRidable = false; ++ public boolean pigRidableInWater = false; ++ public boolean pigControllable = true; ++ private void pigSettings() { ++ pigRidable = getBoolean("mobs.pig.ridable", pigRidable); ++ pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater); ++ pigControllable = getBoolean("mobs.pig.controllable", pigControllable); ++ } ++ ++ public boolean piglinRidable = false; ++ public boolean piglinRidableInWater = false; ++ public boolean piglinControllable = true; ++ private void piglinSettings() { ++ piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable); ++ piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater); ++ piglinControllable = getBoolean("mobs.piglin.controllable", piglinControllable); ++ } ++ ++ public boolean piglinBruteRidable = false; ++ public boolean piglinBruteRidableInWater = false; ++ public boolean piglinBruteControllable = true; ++ private void piglinBruteSettings() { ++ piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable); ++ piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater); ++ piglinBruteControllable = getBoolean("mobs.piglin_brute.controllable", piglinBruteControllable); ++ } ++ ++ public boolean pillagerRidable = false; ++ public boolean pillagerRidableInWater = false; ++ public boolean pillagerControllable = true; ++ private void pillagerSettings() { ++ pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable); ++ pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater); ++ pillagerControllable = getBoolean("mobs.pillager.controllable", pillagerControllable); ++ } ++ ++ public boolean polarBearRidable = false; ++ public boolean polarBearRidableInWater = false; ++ public boolean polarBearControllable = true; ++ private void polarBearSettings() { ++ polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable); ++ polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater); ++ polarBearControllable = getBoolean("mobs.polar_bear.controllable", polarBearControllable); ++ } ++ ++ public boolean pufferfishRidable = false; ++ public boolean pufferfishControllable = true; ++ private void pufferfishSettings() { ++ pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable); ++ pufferfishControllable = getBoolean("mobs.pufferfish.controllable", pufferfishControllable); ++ } ++ ++ public boolean rabbitRidable = false; ++ public boolean rabbitRidableInWater = false; ++ public boolean rabbitControllable = true; ++ private void rabbitSettings() { ++ rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable); ++ rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater); ++ rabbitControllable = getBoolean("mobs.rabbit.controllable", rabbitControllable); ++ } ++ ++ public boolean ravagerRidable = false; ++ public boolean ravagerRidableInWater = false; ++ public boolean ravagerControllable = true; ++ private void ravagerSettings() { ++ ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable); ++ ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater); ++ ravagerControllable = getBoolean("mobs.ravager.controllable", ravagerControllable); ++ } ++ ++ public boolean salmonRidable = false; ++ public boolean salmonControllable = true; ++ private void salmonSettings() { ++ salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable); ++ salmonControllable = getBoolean("mobs.salmon.controllable", salmonControllable); ++ } ++ ++ public boolean sheepRidable = false; ++ public boolean sheepRidableInWater = false; ++ public boolean sheepControllable = true; ++ private void sheepSettings() { ++ sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable); ++ sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater); ++ sheepControllable = getBoolean("mobs.sheep.controllable", sheepControllable); ++ } ++ ++ public boolean shulkerRidable = false; ++ public boolean shulkerRidableInWater = false; ++ public boolean shulkerControllable = true; ++ private void shulkerSettings() { ++ shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable); ++ shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater); ++ shulkerControllable = getBoolean("mobs.shulker.controllable", shulkerControllable); ++ } ++ ++ public boolean silverfishRidable = false; ++ public boolean silverfishRidableInWater = false; ++ public boolean silverfishControllable = true; ++ private void silverfishSettings() { ++ silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable); ++ silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater); ++ silverfishControllable = getBoolean("mobs.silverfish.controllable", silverfishControllable); ++ } ++ ++ public boolean skeletonRidable = false; ++ public boolean skeletonRidableInWater = false; ++ public boolean skeletonControllable = true; ++ private void skeletonSettings() { ++ skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable); ++ skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater); ++ skeletonControllable = getBoolean("mobs.skeleton.controllable", skeletonControllable); ++ } ++ ++ public boolean skeletonHorseRidableInWater = true; ++ public boolean skeletonHorseCanSwim = false; ++ private void skeletonHorseSettings() { ++ skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater); ++ skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim); ++ } ++ ++ public boolean slimeRidable = false; ++ public boolean slimeRidableInWater = false; ++ public boolean slimeControllable = true; ++ private void slimeSettings() { ++ slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable); ++ slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater); ++ slimeControllable = getBoolean("mobs.slime.controllable", slimeControllable); ++ } ++ ++ public boolean snowGolemRidable = false; ++ public boolean snowGolemRidableInWater = false; ++ public boolean snowGolemControllable = true; ++ public boolean snowGolemLeaveTrailWhenRidden = false; ++ private void snowGolemSettings() { ++ snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable); ++ snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater); ++ snowGolemControllable = getBoolean("mobs.snow_golem.controllable", snowGolemControllable); ++ snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden); ++ } ++ ++ public boolean squidRidable = false; ++ public boolean squidControllable = true; ++ private void squidSettings() { ++ squidRidable = getBoolean("mobs.squid.ridable", squidRidable); ++ squidControllable = getBoolean("mobs.squid.controllable", squidControllable); ++ } ++ ++ public boolean spiderRidable = false; ++ public boolean spiderRidableInWater = false; ++ public boolean spiderControllable = true; ++ private void spiderSettings() { ++ spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable); ++ spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater); ++ spiderControllable = getBoolean("mobs.spider.controllable", spiderControllable); ++ } ++ ++ public boolean strayRidable = false; ++ public boolean strayRidableInWater = false; ++ public boolean strayControllable = true; ++ private void straySettings() { ++ strayRidable = getBoolean("mobs.stray.ridable", strayRidable); ++ strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater); ++ strayControllable = getBoolean("mobs.stray.controllable", strayControllable); ++ } ++ ++ public boolean striderRidable = false; ++ public boolean striderRidableInWater = false; ++ public boolean striderControllable = true; ++ private void striderSettings() { ++ striderRidable = getBoolean("mobs.strider.ridable", striderRidable); ++ striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater); ++ striderControllable = getBoolean("mobs.strider.controllable", striderControllable); ++ } ++ ++ public boolean traderLlamaRidable = false; ++ public boolean traderLlamaRidableInWater = false; ++ public boolean traderLlamaControllable = true; ++ private void traderLlamaSettings() { ++ traderLlamaRidable = getBoolean("mobs.trader_llama.ridable", traderLlamaRidable); ++ traderLlamaRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", traderLlamaRidableInWater); ++ traderLlamaControllable = getBoolean("mobs.trader_llama.controllable", traderLlamaControllable); ++ } ++ ++ public boolean tropicalFishRidable = false; ++ public boolean tropicalFishControllable = true; ++ private void tropicalFishSettings() { ++ tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable); ++ tropicalFishControllable = getBoolean("mobs.tropical_fish.controllable", tropicalFishControllable); ++ } ++ ++ public boolean turtleRidable = false; ++ public boolean turtleRidableInWater = false; ++ public boolean turtleControllable = true; ++ private void turtleSettings() { ++ turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable); ++ turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater); ++ turtleControllable = getBoolean("mobs.turtle.controllable", turtleControllable); ++ } ++ ++ public boolean vexRidable = false; ++ public boolean vexRidableInWater = false; ++ public boolean vexControllable = true; ++ public double vexMaxY = 320D; ++ private void vexSettings() { ++ vexRidable = getBoolean("mobs.vex.ridable", vexRidable); ++ vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater); ++ vexControllable = getBoolean("mobs.vex.controllable", vexControllable); ++ vexMaxY = getDouble("mobs.vex.ridable-max-y", vexMaxY); ++ } ++ ++ public boolean villagerRidable = false; ++ public boolean villagerRidableInWater = false; ++ public boolean villagerControllable = true; ++ private void villagerSettings() { ++ villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable); ++ villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater); ++ villagerControllable = getBoolean("mobs.villager.controllable", villagerControllable); ++ } ++ ++ public boolean vindicatorRidable = false; ++ public boolean vindicatorRidableInWater = false; ++ public boolean vindicatorControllable = true; ++ private void vindicatorSettings() { ++ vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable); ++ vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater); ++ vindicatorControllable = getBoolean("mobs.vindicator.controllable", vindicatorControllable); ++ } ++ ++ public boolean wanderingTraderRidable = false; ++ public boolean wanderingTraderRidableInWater = false; ++ public boolean wanderingTraderControllable = true; ++ private void wanderingTraderSettings() { ++ wanderingTraderRidable = getBoolean("mobs.wandering_trader.ridable", wanderingTraderRidable); ++ wanderingTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", wanderingTraderRidableInWater); ++ wanderingTraderControllable = getBoolean("mobs.wandering_trader.controllable", wanderingTraderControllable); ++ } ++ ++ public boolean witchRidable = false; ++ public boolean witchRidableInWater = false; ++ public boolean witchControllable = true; ++ private void witchSettings() { ++ witchRidable = getBoolean("mobs.witch.ridable", witchRidable); ++ witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater); ++ witchControllable = getBoolean("mobs.witch.controllable", witchControllable); ++ } ++ ++ public boolean witherRidable = false; ++ public boolean witherRidableInWater = false; ++ public boolean witherControllable = true; ++ public double witherMaxY = 320D; ++ private void witherSettings() { ++ witherRidable = getBoolean("mobs.wither.ridable", witherRidable); ++ witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater); ++ witherControllable = getBoolean("mobs.wither.controllable", witherControllable); ++ witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY); ++ } ++ ++ public boolean witherSkeletonRidable = false; ++ public boolean witherSkeletonRidableInWater = false; ++ public boolean witherSkeletonControllable = true; ++ private void witherSkeletonSettings() { ++ witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable); ++ witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater); ++ witherSkeletonControllable = getBoolean("mobs.wither_skeleton.controllable", witherSkeletonControllable); ++ } ++ ++ public boolean wolfRidable = false; ++ public boolean wolfRidableInWater = false; ++ public boolean wolfControllable = true; ++ private void wolfSettings() { ++ wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable); ++ wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater); ++ wolfControllable = getBoolean("mobs.wolf.controllable", wolfControllable); ++ } ++ ++ public boolean zoglinRidable = false; ++ public boolean zoglinRidableInWater = false; ++ public boolean zoglinControllable = true; ++ private void zoglinSettings() { ++ zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable); ++ zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater); ++ zoglinControllable = getBoolean("mobs.zoglin.controllable", zoglinControllable); ++ } ++ ++ public boolean zombieRidable = false; ++ public boolean zombieRidableInWater = false; ++ public boolean zombieControllable = true; ++ private void zombieSettings() { ++ zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable); ++ zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater); ++ zombieControllable = getBoolean("mobs.zombie.controllable", zombieControllable); ++ } ++ ++ public boolean zombieHorseRidableInWater = false; ++ public boolean zombieHorseCanSwim = false; ++ private void zombieHorseSettings() { ++ zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater); ++ zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim); ++ } ++ ++ public boolean zombieVillagerRidable = false; ++ public boolean zombieVillagerRidableInWater = false; ++ public boolean zombieVillagerControllable = true; ++ private void zombieVillagerSettings() { ++ zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable); ++ zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater); ++ zombieVillagerControllable = getBoolean("mobs.zombie_villager.controllable", zombieVillagerControllable); ++ } ++ ++ public boolean zombifiedPiglinRidable = false; ++ public boolean zombifiedPiglinRidableInWater = false; ++ public boolean zombifiedPiglinControllable = true; ++ private void zombifiedPiglinSettings() { ++ zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable); ++ zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater); ++ zombifiedPiglinControllable = getBoolean("mobs.zombified_piglin.controllable", zombifiedPiglinControllable); ++ } + } +diff --git a/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java +new file mode 100644 +index 0000000000000000000000000000000000000000..315d76526a1a9e95d29384e4598d8d77a27466c7 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java +@@ -0,0 +1,63 @@ ++package org.purpurmc.purpur.controller; ++ ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.player.Player; ++ ++public class FlyingMoveControllerWASD extends MoveControllerWASD { ++ protected final float groundSpeedModifier; ++ protected int tooHighCooldown = 0; ++ protected boolean setGravityFlag = true; ++ ++ public FlyingMoveControllerWASD(Mob entity) { ++ this(entity, 1.0F); ++ } ++ ++ public FlyingMoveControllerWASD(Mob entity, float groundSpeedModifier) { ++ this(entity, groundSpeedModifier, true); ++ } ++ ++ public FlyingMoveControllerWASD(Mob entity, float groundSpeedModifier, boolean setGravityFlag) { ++ super(entity); ++ this.groundSpeedModifier = groundSpeedModifier; ++ this.setGravityFlag = setGravityFlag; ++ } ++ ++ @Override ++ public void purpurTick(Player rider) { ++ float forward = Math.max(0.0F, rider.getForwardMot()); ++ float vertical = forward == 0.0F ? 0.0F : -(rider.xRotO / 45.0F); ++ float strafe = rider.getStrafeMot(); ++ ++ if (rider.jumping && spacebarEvent(entity)) { ++ entity.onSpacebar(); ++ } ++ ++ if (entity.getY() >= entity.getMaxY() || --tooHighCooldown > 0) { ++ if (tooHighCooldown <= 0) { ++ tooHighCooldown = 20; ++ } ++ entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, -0.05D, 0.0D)); ++ vertical = 0.0F; ++ } ++ ++ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float speed = (float) getSpeedModifier(); ++ ++ if (entity.onGround) { ++ speed *= groundSpeedModifier; // TODO = fix this! ++ } ++ ++ if (setGravityFlag) { ++ entity.setNoGravity(forward > 0); ++ } ++ ++ entity.setSpeed(speed); ++ entity.setVerticalMot(vertical); ++ entity.setStrafeMot(strafe); ++ entity.setForwardMot(forward); ++ ++ setForward(entity.getForwardMot()); ++ setStrafe(entity.getStrafeMot()); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9383c07fa53141127106a1f289366a040960d52e +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java +@@ -0,0 +1,63 @@ ++package org.purpurmc.purpur.controller; ++ ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.phys.Vec3; ++ ++public class FlyingWithSpacebarMoveControllerWASD extends FlyingMoveControllerWASD { ++ public FlyingWithSpacebarMoveControllerWASD(Mob entity) { ++ super(entity); ++ } ++ ++ public FlyingWithSpacebarMoveControllerWASD(Mob entity, float groundSpeedModifier) { ++ super(entity, groundSpeedModifier); ++ } ++ ++ @Override ++ public void purpurTick(Player rider) { ++ float forward = rider.getForwardMot(); ++ float strafe = rider.getStrafeMot() * 0.5F; ++ float vertical = 0; ++ ++ if (forward < 0.0F) { ++ forward *= 0.5F; ++ strafe *= 0.5F; ++ } ++ ++ float speed = (float) entity.getAttributeValue(Attributes.MOVEMENT_SPEED); ++ ++ if (entity.onGround) { ++ speed *= groundSpeedModifier; ++ } ++ ++ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar()) { ++ entity.setNoGravity(true); ++ vertical = 1.0F; ++ } else { ++ entity.setNoGravity(false); ++ } ++ ++ if (entity.getY() >= entity.getMaxY() || --tooHighCooldown > 0) { ++ if (tooHighCooldown <= 0) { ++ tooHighCooldown = 20; ++ } ++ entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, -0.2D, 0.0D)); ++ vertical = 0.0F; ++ } ++ ++ setSpeedModifier(speed); ++ entity.setSpeed((float) getSpeedModifier()); ++ entity.setVerticalMot(vertical); ++ entity.setStrafeMot(strafe); ++ entity.setForwardMot(forward); ++ ++ setForward(entity.getForwardMot()); ++ setStrafe(entity.getStrafeMot()); ++ ++ Vec3 mot = entity.getDeltaMovement(); ++ if (mot.y > 0.2D) { ++ entity.setDeltaMovement(mot.x, 0.2D, mot.z); ++ } ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b8c25c96e95dd5ec3ad9fa4c41bd6c08e144832d +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java +@@ -0,0 +1,76 @@ ++package org.purpurmc.purpur.controller; ++ ++ ++import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket; ++import net.minecraft.util.Mth; ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.control.LookControl; ++import net.minecraft.world.entity.player.Player; ++ ++public class LookControllerWASD extends LookControl { ++ protected final Mob entity; ++ private float yOffset = 0; ++ private float xOffset = 0; ++ ++ public LookControllerWASD(Mob entity) { ++ super(entity); ++ this.entity = entity; ++ } ++ ++ // tick ++ @Override ++ public void tick() { ++ if (entity.getRider() != null && entity.isControllable()) { ++ purpurTick(entity.getRider()); ++ } else { ++ vanillaTick(); ++ } ++ } ++ ++ protected void purpurTick(Player rider) { ++ setYawPitch(rider.getYRot(), rider.getXRot()); ++ } ++ ++ public void vanillaTick() { ++ super.tick(); ++ } ++ ++ public void setYawPitch(float yRot, float xRot) { ++ entity.setXRot(normalizePitch(xRot + xOffset)); ++ entity.setYRot(normalizeYaw(yRot + yOffset)); ++ entity.setYHeadRot(entity.getYRot()); ++ entity.xRotO = entity.getXRot(); ++ entity.yRotO = entity.getYRot(); ++ ++ entity.tracker.broadcast(new ClientboundMoveEntityPacket ++ .PosRot(entity.getId(), ++ (short) 0, (short) 0, (short) 0, ++ (byte) Mth.floor(entity.getYRot() * 256.0F / 360.0F), ++ (byte) Mth.floor(entity.getXRot() * 256.0F / 360.0F), ++ entity.onGround)); ++ } ++ ++ public void setOffsets(float yaw, float pitch) { ++ yOffset = yaw; ++ xOffset = pitch; ++ } ++ ++ public float normalizeYaw(float yaw) { ++ yaw %= 360.0f; ++ if (yaw >= 180.0f) { ++ yaw -= 360.0f; ++ } else if (yaw < -180.0f) { ++ yaw += 360.0f; ++ } ++ return yaw; ++ } ++ ++ public float normalizePitch(float pitch) { ++ if (pitch > 90.0f) { ++ pitch = 90.0f; ++ } else if (pitch < -90.0f) { ++ pitch = -90.0f; ++ } ++ return pitch; ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java +new file mode 100644 +index 0000000000000000000000000000000000000000..21fd6ea2a482758a3016e3bc2cdebe2d89267481 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java +@@ -0,0 +1,89 @@ ++package org.purpurmc.purpur.controller; ++ ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.ai.control.MoveControl; ++import net.minecraft.world.entity.player.Player; ++import org.purpurmc.purpur.event.entity.RidableSpacebarEvent; ++ ++public class MoveControllerWASD extends MoveControl { ++ protected final Mob entity; ++ private final double speedModifier; ++ ++ public MoveControllerWASD(Mob entity) { ++ this(entity, 1.0D); ++ } ++ ++ public MoveControllerWASD(Mob entity, double speedModifier) { ++ super(entity); ++ this.entity = entity; ++ this.speedModifier = speedModifier; ++ } ++ ++ @Override ++ public boolean hasWanted() { ++ return entity.getRider() != null ? strafeForwards != 0 || strafeRight != 0 : super.hasWanted(); ++ } ++ ++ @Override ++ public void tick() { ++ if (entity.getRider() != null && entity.isControllable()) { ++ purpurTick(entity.getRider()); ++ } else { ++ vanillaTick(); ++ } ++ } ++ ++ public void vanillaTick() { ++ super.tick(); ++ } ++ ++ public void purpurTick(Player rider) { ++ float forward = rider.getForwardMot() * 0.5F; ++ float strafe = rider.getStrafeMot() * 0.25F; ++ ++ if (forward <= 0.0F) { ++ forward *= 0.5F; ++ } ++ ++ float yawOffset = 0; ++ if (strafe != 0) { ++ if (forward == 0) { ++ yawOffset += strafe > 0 ? -90 : 90; ++ forward = Math.abs(strafe * 2); ++ } else { ++ yawOffset += strafe > 0 ? -30 : 30; ++ strafe /= 2; ++ if (forward < 0) { ++ yawOffset += strafe > 0 ? -110 : 110; ++ forward *= -1; ++ } ++ } ++ } else if (forward < 0) { ++ yawOffset -= 180; ++ forward *= -1; ++ } ++ ++ ((LookControllerWASD) entity.getLookControl()).setOffsets(yawOffset, 0); ++ ++ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar() && entity.onGround) { ++ entity.jumpFromGround(); ++ } ++ ++ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED) * speedModifier); ++ ++ entity.setSpeed((float) getSpeedModifier()); ++ entity.setForwardMot(forward); ++ ++ setForward(entity.getForwardMot()); ++ setStrafe(entity.getStrafeMot()); ++ } ++ ++ public static boolean spacebarEvent(Mob entity) { ++ if (RidableSpacebarEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ return new RidableSpacebarEvent(entity.getBukkitEntity()).callEvent(); ++ } else { ++ return true; ++ } ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ba2a37dad43e238e54632975abea8ee6fafaa9e0 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java +@@ -0,0 +1,50 @@ ++package org.purpurmc.purpur.controller; ++ ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.player.Player; ++ ++public class WaterMoveControllerWASD extends MoveControllerWASD { ++ private final double speedModifier; ++ ++ public WaterMoveControllerWASD(Mob entity) { ++ this(entity, 1.0D); ++ } ++ ++ public WaterMoveControllerWASD(Mob entity, double speedModifier) { ++ super(entity); ++ this.speedModifier = speedModifier; ++ } ++ ++ @Override ++ public void purpurTick(Player rider) { ++ float forward = rider.getForwardMot(); ++ float strafe = rider.getStrafeMot() * 0.5F; // strafe slower by default ++ float vertical = -(rider.xRotO / 90); ++ ++ if (forward == 0.0F) { ++ // strafe slower if not moving forward ++ strafe *= 0.5F; ++ // do not move vertically if not moving forward ++ vertical = 0.0F; ++ } else if (forward < 0.0F) { ++ // water animals can't swim backwards ++ forward = 0.0F; ++ vertical = 0.0F; ++ } ++ ++ if (rider.jumping && spacebarEvent(entity)) { ++ entity.onSpacebar(); ++ } ++ ++ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED) * speedModifier); ++ entity.setSpeed((float) getSpeedModifier() * 0.1F); ++ ++ entity.setForwardMot(forward * (float) speedModifier); ++ entity.setStrafeMot(strafe * (float) speedModifier); ++ entity.setVerticalMot(vertical * (float) speedModifier); ++ ++ setForward(entity.getForwardMot()); ++ setStrafe(entity.getStrafeMot()); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java b/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d55f7611599b2a339293688861100cb8dae9f6c6 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java +@@ -0,0 +1,99 @@ ++package org.purpurmc.purpur.entity; ++ ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.util.Mth; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.animal.Dolphin; ++import net.minecraft.world.entity.projectile.LlamaSpit; ++import net.minecraft.world.entity.projectile.ProjectileUtil; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; ++import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; ++ ++public class DolphinSpit extends LlamaSpit { ++ public LivingEntity dolphin; ++ public int ticksLived; ++ ++ public DolphinSpit(EntityType type, Level world) { ++ super(type, world); ++ } ++ ++ public DolphinSpit(Level world, Dolphin dolphin) { ++ this(EntityType.LLAMA_SPIT, world); ++ setOwner(dolphin.getRider() != null ? dolphin.getRider() : dolphin); ++ this.dolphin = dolphin; ++ this.setPos( ++ dolphin.getX() - (double) (dolphin.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(dolphin.yBodyRot * 0.017453292F), ++ dolphin.getEyeY() - 0.10000000149011612D, ++ dolphin.getZ() + (double) (dolphin.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(dolphin.yBodyRot * 0.017453292F)); ++ } ++ ++ public void tick() { ++ super_tick(); ++ ++ Vec3 mot = this.getDeltaMovement(); ++ HitResult hitResult = ProjectileUtil.getHitResult(this, this::canHitEntity); ++ ++ this.preOnHit(hitResult); ++ ++ double x = this.getX() + mot.x; ++ double y = this.getY() + mot.y; ++ double z = this.getZ() + mot.z; ++ ++ this.updateRotation(); ++ ++ Vec3 motDouble = mot.scale(2.0); ++ for (int i = 0; i < 5; i++) { ++ ((ServerLevel) level).sendParticles(null, ParticleTypes.BUBBLE, ++ getX() + random.nextFloat() / 2 - 0.25F, ++ getY() + random.nextFloat() / 2 - 0.25F, ++ getZ() + random.nextFloat() / 2 - 0.25F, ++ 0, motDouble.x(), motDouble.y(), motDouble.z(), 0.1D, true); ++ } ++ ++ if (++ticksLived > 20) { ++ this.discard(); ++ } else { ++ this.setDeltaMovement(mot.scale(0.99D)); ++ if (!this.isNoGravity()) { ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.06D, 0.0D)); ++ } ++ ++ this.setPos(x, y, z); ++ } ++ } ++ ++ @Override ++ public void shoot(double x, double y, double z, float speed, float inaccuracy) { ++ setDeltaMovement(new Vec3(x, y, z).normalize().add( ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy) ++ .scale(speed)); ++ } ++ ++ @Override ++ protected void onHitEntity(EntityHitResult entityHitResult) { ++ Entity shooter = this.getOwner(); ++ if (shooter instanceof LivingEntity) { ++ entityHitResult.getEntity().hurt(DamageSource.indirectMobAttack(this, (LivingEntity) shooter).setProjectile(), level.purpurConfig.dolphinSpitDamage); ++ } ++ } ++ ++ @Override ++ protected void onHitBlock(BlockHitResult blockHitResult) { ++ if (this.hitCancelled) { ++ return; ++ } ++ BlockState state = this.level.getBlockState(blockHitResult.getBlockPos()); ++ state.onProjectileHit(this.level, state, blockHitResult, this); ++ this.discard(); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2eca8317e991ec46cc88a4c7d6d8b50152ba4ea7 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java +@@ -0,0 +1,114 @@ ++package org.purpurmc.purpur.entity; ++ ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.util.Mth; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.decoration.ArmorStand; ++import net.minecraft.world.entity.monster.Phantom; ++import net.minecraft.world.entity.projectile.LlamaSpit; ++import net.minecraft.world.entity.projectile.ProjectileUtil; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.BlockBehaviour; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; ++import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; ++ ++public class PhantomFlames extends LlamaSpit { ++ public Phantom phantom; ++ public int ticksLived; ++ public boolean canGrief = false; ++ ++ public PhantomFlames(EntityType type, Level world) { ++ super(type, world); ++ } ++ ++ public PhantomFlames(Level world, Phantom phantom) { ++ this(EntityType.LLAMA_SPIT, world); ++ setOwner(phantom.getRider() != null ? phantom.getRider() : phantom); ++ this.phantom = phantom; ++ this.setPos( ++ phantom.getX() - (double) (phantom.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(phantom.yBodyRot * 0.017453292F), ++ phantom.getEyeY() - 0.10000000149011612D, ++ phantom.getZ() + (double) (phantom.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(phantom.yBodyRot * 0.017453292F)); ++ } ++ ++ public void tick() { ++ super_tick(); ++ ++ Vec3 mot = this.getDeltaMovement(); ++ HitResult hitResult = ProjectileUtil.getHitResult(this, this::canHitEntity); ++ ++ this.preOnHit(hitResult); ++ ++ double x = this.getX() + mot.x; ++ double y = this.getY() + mot.y; ++ double z = this.getZ() + mot.z; ++ ++ this.updateRotation(); ++ ++ Vec3 motDouble = mot.scale(2.0); ++ for (int i = 0; i < 5; i++) { ++ ((ServerLevel) level).sendParticles(null, ParticleTypes.FLAME, ++ getX() + random.nextFloat() / 2 - 0.25F, ++ getY() + random.nextFloat() / 2 - 0.25F, ++ getZ() + random.nextFloat() / 2 - 0.25F, ++ 0, motDouble.x(), motDouble.y(), motDouble.z(), 0.1D, true); ++ } ++ ++ if (++ticksLived > 20) { ++ this.discard(); ++ } else if (this.level.getBlockStates(this.getBoundingBox()).noneMatch(BlockBehaviour.BlockStateBase::isAir)) { ++ this.discard(); ++ } else if (this.isInWaterOrBubble()) { ++ this.discard(); ++ } else { ++ this.setDeltaMovement(mot.scale(0.99D)); ++ if (!this.isNoGravity()) { ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.06D, 0.0D)); ++ } ++ ++ this.setPos(x, y, z); ++ } ++ } ++ ++ @Override ++ public void shoot(double x, double y, double z, float speed, float inaccuracy) { ++ setDeltaMovement(new Vec3(x, y, z).normalize().add( ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy, ++ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy) ++ .scale(speed)); ++ } ++ ++ @Override ++ protected void onHitEntity(EntityHitResult entityHitResult) { ++ Entity shooter = this.getOwner(); ++ if (shooter instanceof LivingEntity) { ++ Entity target = entityHitResult.getEntity(); ++ if (canGrief || (target instanceof LivingEntity && !(target instanceof ArmorStand))) { ++ boolean hurt = target.hurt(DamageSource.indirectMobAttack(this, (LivingEntity) shooter).setProjectile(), level.purpurConfig.phantomFlameDamage); ++ if (hurt && level.purpurConfig.phantomFlameFireTime > 0) { ++ target.setSecondsOnFire(level.purpurConfig.phantomFlameFireTime); ++ } ++ } ++ } ++ } ++ ++ @Override ++ protected void onHitBlock(BlockHitResult blockHitResult) { ++ if (this.hitCancelled) { ++ return; ++ } ++ if (this.canGrief) { ++ BlockState state = this.level.getBlockState(blockHitResult.getBlockPos()); ++ state.onProjectileHit(this.level, state, blockHitResult, this); ++ } ++ this.discard(); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8babdaddd8b33278aea0369dbbeeb445abe45016 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java +@@ -0,0 +1,20 @@ ++package org.purpurmc.purpur.entity.ai; ++ ++import net.minecraft.world.entity.Mob; ++import net.minecraft.world.entity.ai.goal.Goal; ++ ++import java.util.EnumSet; ++ ++public class HasRider extends Goal { ++ public final Mob entity; ++ ++ public HasRider(Mob entity) { ++ this.entity = entity; ++ setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.TARGET, Flag.UNKNOWN_BEHAVIOR)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ return entity.getRider() != null && entity.isControllable(); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..432f4f3d82af2f19820890b68d33189a9f2c69f9 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java +@@ -0,0 +1,17 @@ ++package org.purpurmc.purpur.entity.ai; ++ ++import net.minecraft.world.entity.animal.horse.AbstractHorse; ++ ++public class HorseHasRider extends HasRider { ++ public final AbstractHorse horse; ++ ++ public HorseHasRider(AbstractHorse entity) { ++ super(entity); ++ this.horse = entity; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && horse.isSaddled(); ++ } ++} +diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..18a95e043cbffa65eeaaf65ff7695e5dc939820c +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java +@@ -0,0 +1,17 @@ ++package org.purpurmc.purpur.entity.ai; ++ ++import net.minecraft.world.entity.animal.horse.Llama; ++ ++public class LlamaHasRider extends HasRider { ++ public final Llama llama; ++ ++ public LlamaHasRider(Llama entity) { ++ super(entity); ++ this.llama = entity; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && llama.isSaddled() && llama.isControllable(); ++ } ++} +diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +index b2d510459bcf90a3611f3d91dae4ccc3d29b4079..7a052f6deaa30f8a177a2aaf172f9da6c308a22b 100644 +--- a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java ++++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java +@@ -37,7 +37,7 @@ public class VanillaMobGoalTest { + } + + List> classes; +- try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { ++ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft", "org.purpurmc.purpur.entity.ai").scan()) { // Purpur + classes = scanResult.getSubclasses(net.minecraft.world.entity.ai.goal.Goal.class.getName()).loadClasses(); + } + diff --git a/patches/todo/server/0007-Configurable-entity-base-attributes.patch b/patches/server/0006-Configurable-entity-base-attributes.patch similarity index 94% rename from patches/todo/server/0007-Configurable-entity-base-attributes.patch rename to patches/server/0006-Configurable-entity-base-attributes.patch index 8216c4e91..e1b5b6292 100644 --- a/patches/todo/server/0007-Configurable-entity-base-attributes.patch +++ b/patches/server/0006-Configurable-entity-base-attributes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable entity base attributes diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 8dda017467fb9a41fb1ca6a3bdd4cc31e23dd848..19756aac2e13914d0cf3cabed3621d2a4228330b 100644 +index 8f8740b40a37e91eedc3496985ba0d2964cbafe5..be3545469c486f1dd6de42bb29a82a339d5a6a22 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -152,7 +152,7 @@ import org.bukkit.plugin.PluginManager; +@@ -155,7 +155,7 @@ import org.bukkit.plugin.PluginManager; // CraftBukkit end public abstract class Entity implements Nameable, EntityAccess, CommandSource { @@ -18,7 +18,7 @@ index 8dda017467fb9a41fb1ca6a3bdd4cc31e23dd848..19756aac2e13914d0cf3cabed3621d2a private static final int CURRENT_LEVEL = 2; public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation diff --git a/src/main/java/net/minecraft/world/entity/GlowSquid.java b/src/main/java/net/minecraft/world/entity/GlowSquid.java -index 2ce9b08535cf3783e6823de3489433003a1aae0d..9734ed30af10832fbbede43848fd82591320d1ce 100644 +index 882ab40c8cdea8c214cb8344b3ccecddb2967c1c..cb79d2c958fbd34f8c8818e7e1c0db8887dd15ba 100644 --- a/src/main/java/net/minecraft/world/entity/GlowSquid.java +++ b/src/main/java/net/minecraft/world/entity/GlowSquid.java @@ -38,6 +38,11 @@ public class GlowSquid extends Squid { @@ -34,10 +34,10 @@ index 2ce9b08535cf3783e6823de3489433003a1aae0d..9734ed30af10832fbbede43848fd8259 @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index fa4abf237820665ce25cebc6ecaeef2940bf33c7..50700ddb0cd2dc62cfa703375ac05a99d0251244 100644 +index 52086efc539b854c159d5166e33b49d933128185..68bbd0c1facef4d3e21975ead5b7af19ac3c1254 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -286,6 +286,7 @@ public abstract class LivingEntity extends Entity { +@@ -289,6 +289,7 @@ public abstract class LivingEntity extends Entity { this.useItem = ItemStack.EMPTY; this.lastClimbablePos = Optional.empty(); this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur @@ -45,7 +45,7 @@ index fa4abf237820665ce25cebc6ecaeef2940bf33c7..50700ddb0cd2dc62cfa703375ac05a99 this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); -@@ -301,6 +302,8 @@ public abstract class LivingEntity extends Entity { +@@ -304,6 +305,8 @@ public abstract class LivingEntity extends Entity { this.brain = this.makeBrain(new Dynamic(dynamicopsnbt, (Tag) dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), (Tag) dynamicopsnbt.emptyMap())))); } @@ -55,7 +55,7 @@ index fa4abf237820665ce25cebc6ecaeef2940bf33c7..50700ddb0cd2dc62cfa703375ac05a99 return this.brain; } diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index ca053df9d4d9120c7bd926b3d2d511b71332b5df..70b8698ef3863c957ac4639f113f235705da4667 100644 +index f7f3daa646e3f43ae503a67b7c52faef84bff0da..a02502ce8916c6b817270297412f961d5fcf4689 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java @@ -90,6 +90,18 @@ public class Bat extends AmbientCreature { @@ -78,10 +78,10 @@ index ca053df9d4d9120c7bd926b3d2d511b71332b5df..70b8698ef3863c957ac4639f113f2357 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 793e7c659af32e8bdc07bd7ecfa31fb5d302ad22..9245baa69aefee786c442e3b46a323a9c7f22eea 100644 +index 2c6e1a970d8922047a186fc7eb82abd7066b1fd9..21bd1f6f24715351d46573964438bcb7304575f5 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -213,6 +213,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -214,6 +214,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { setDeltaMovement(mot.scale(0.9D)); } } @@ -94,10 +94,10 @@ index 793e7c659af32e8bdc07bd7ecfa31fb5d302ad22..9245baa69aefee786c442e3b46a323a9 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index 2edd9efb8bf71071807ac1ff5b58bc4b555ecc6b..81b63da3bca3e3942ed037fad15ad8f883fc0c82 100644 +index dd59f83fd6adff8d1ade76aac6f3563bfbea15b1..ed4a42b850b24eeaa9f885f79868c2c1a9a7e781 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java -@@ -147,6 +147,11 @@ public class Cat extends TamableAnimal { +@@ -118,6 +118,11 @@ public class Cat extends TamableAnimal { setLying(false); setRelaxStateOne(false); } @@ -110,10 +110,10 @@ index 2edd9efb8bf71071807ac1ff5b58bc4b555ecc6b..81b63da3bca3e3942ed037fad15ad8f8 public ResourceLocation getResourceLocation() { diff --git a/src/main/java/net/minecraft/world/entity/animal/Chicken.java b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -index ddb199c003d07aa0172c09de32e82337baab64bf..43073c639bfbf60a0b396dff6f5f701d26d49342 100644 +index 58c1102b483ccdddb74023959b9234bcd2af6548..8503a3393026134df18601ed87dcec1f3e6680b8 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Chicken.java +++ b/src/main/java/net/minecraft/world/entity/animal/Chicken.java -@@ -67,6 +67,11 @@ public class Chicken extends Animal { +@@ -68,6 +68,11 @@ public class Chicken extends Animal { public boolean isControllable() { return level.purpurConfig.chickenControllable; } @@ -158,7 +158,7 @@ index 8f046fb76b6967e72abde523ffb790e0f46b80e0..dd4d5e2e7cbfed18cf3b4664dbe08eaf @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -index 4a535ea98a9a786eeebe26c21b86a8c3286b57f3..8a71339b5efacf326f3fbd5a3085b2db25c26071 100644 +index badaa1cb7919cc4699c5e732f9c84254416efdc3..b3e53f922a424a407adb0111c29c8be6f89f8115 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java +++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java @@ -157,6 +157,11 @@ public class Dolphin extends WaterAnimal { @@ -174,7 +174,7 @@ index 4a535ea98a9a786eeebe26c21b86a8c3286b57f3..8a71339b5efacf326f3fbd5a3085b2db @Nullable diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index c389a2b368b7c5ae77293e8315302f0b08134a4c..1e0239434fc6a9b39e2326d5ee98f01e9bcb263f 100644 +index 7bb7aaaff1e6e11db68b0f206bdf04fda0e88fc4..8d25d79be606b173a59264706172561165f82143 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java @@ -176,6 +176,11 @@ public class Fox extends Animal { @@ -190,10 +190,10 @@ index c389a2b368b7c5ae77293e8315302f0b08134a4c..1e0239434fc6a9b39e2326d5ee98f01e @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index 6b56e324900d809615d80f38528f302db60cfbc9..fe7d88d81d70d46acf031f82495d0503f5b6b5d8 100644 +index 467d3b4b750e816f1c9d03114e9514252039bad4..9474324ace8ad2c9f54930cea4ee825275493075 100644 --- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -@@ -85,6 +85,11 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -84,6 +84,11 @@ public class IronGolem extends AbstractGolem implements NeutralMob { public boolean isControllable() { return level.purpurConfig.ironGolemControllable; } @@ -206,7 +206,7 @@ index 6b56e324900d809615d80f38528f302db60cfbc9..fe7d88d81d70d46acf031f82495d0503 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -index 9d47d010c3917616732ff10a1b0166f410cf6c25..2846c17ddbb546d49407338f136e171a329b347e 100644 +index 2be73f6dfb7edf8a4019fc29209fee54b9be6b47..380fe61157048da5df1781a0622af290f8adbf82 100644 --- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java @@ -79,6 +79,11 @@ public class MushroomCow extends Cow implements Shearable { @@ -222,7 +222,7 @@ index 9d47d010c3917616732ff10a1b0166f410cf6c25..2846c17ddbb546d49407338f136e171a @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -index 22e0c5dee4efa2e041671c980851db46eabe9402..a90c3e0c9f0064690bd17e5b132fbcfb360fa6b2 100644 +index 041c2d330a245826fc2fa4c1327aeadd24a44254..3697238a818aac364d62f779fe6b622494a9f658 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java @@ -83,6 +83,11 @@ public class Ocelot extends Animal { @@ -238,7 +238,7 @@ index 22e0c5dee4efa2e041671c980851db46eabe9402..a90c3e0c9f0064690bd17e5b132fbcfb public boolean isTrusting() { diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index c477671b68d243dbead2067066e56044a5a38e7c..bcbf20728b4c9a181771984c54af742f07fd9855 100644 +index 129358e127227efb6adbcf4c436f59f2004c9814..47b03fd6a45b03f438fc9e4025dd2d7e70c273b6 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Panda.java +++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java @@ -131,6 +131,12 @@ public class Panda extends Animal { @@ -254,7 +254,7 @@ index c477671b68d243dbead2067066e56044a5a38e7c..bcbf20728b4c9a181771984c54af742f // Purpur end @Override -@@ -626,7 +632,10 @@ public class Panda extends Animal { +@@ -628,7 +634,10 @@ public class Panda extends Animal { public void setAttributes() { if (this.isWeak()) { @@ -267,10 +267,10 @@ index c477671b68d243dbead2067066e56044a5a38e7c..bcbf20728b4c9a181771984c54af742f if (this.isLazy()) { diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -index 19af87b2496178be9d2d09ba16ac511a1882d2ed..91b8117238e76c00d758180df5cfd70ae76ace22 100644 +index 9a433b96fa468aab604c6874e1814e09dc9d621d..d8dce6968861cb03f2b1b7631fc54f3c91ebdd9f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -@@ -184,6 +184,11 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { +@@ -185,6 +185,11 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { setDeltaMovement(mot.scale(0.9D)); } } @@ -283,7 +283,7 @@ index 19af87b2496178be9d2d09ba16ac511a1882d2ed..91b8117238e76c00d758180df5cfd70a @Nullable diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java -index c4c0d7958156b0d587999032c8f9fac9fd689c72..62a1e63fb6ca80e165db46c4d03e28815196aaff 100644 +index 9815f012569a72d64941c732eecabd63ba277570..a02476bdc34a4e3e0389abaf08687393cc3bff97 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Pig.java +++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java @@ -79,6 +79,11 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { @@ -299,7 +299,7 @@ index c4c0d7958156b0d587999032c8f9fac9fd689c72..62a1e63fb6ca80e165db46c4d03e2881 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -index 2c723250eea3454d6b7aafb307612a2c06c42b73..4a21babeb23efe2b4bfd99ae3d08eb677b93bac9 100644 +index 8d123d6ce4c1fb5176d93a651363ba8bbd984550..798269a1098008e14fc2548e480c815fa4ff4d25 100644 --- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java +++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java @@ -92,6 +92,11 @@ public class PolarBear extends Animal implements NeutralMob { @@ -331,10 +331,10 @@ index 71929e5fe8851ad5620f25b6ed5058653231d769..988093b46a4c386f8d47a4c530b8e9f6 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -index 0819503e8651afa9ff42df7077667eaa3a310df4..76ea5b3d0d70eb8bdbbbb4bf7bed31d0d7d712a3 100644 +index 895e93e114e12a402812c19fab9581f47ed5020e..eaf040f10e33fdfb57391b6e7bc6901c87270853 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -@@ -136,6 +136,11 @@ public class Rabbit extends Animal { +@@ -137,6 +137,11 @@ public class Rabbit extends Animal { } wasOnGround = onGround; } @@ -363,7 +363,7 @@ index 59cb21bc3166f4cc77b962c253ed786fd04090de..3873fb0e2d95973397f9a23dc363f7a6 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java -index e267e7b3b4ba96f5423327a336088942dcb4e14c..9d6765e2bd6bfdd39728bdd14cabbe4bf33d96ac 100644 +index 15b2677018abc5047ddedaaf2b640de8dd1966ae..2368c807e9c7146c186654a390e23af99addb804 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java +++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java @@ -131,6 +131,11 @@ public class Sheep extends Animal implements Shearable { @@ -379,7 +379,7 @@ index e267e7b3b4ba96f5423327a336088942dcb4e14c..9d6765e2bd6bfdd39728bdd14cabbe4b @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -index 3ead4cc2fa875b8839410d7b4b5871e5b1d39074..f7863f9703c7ab5f2f1faac7a52311ed7ef79042 100644 +index c6700d12fffbfea0fced14e466da0b760a73a237..e2f0f1d7ed8004a03f14887750a470e08ee1f42d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java @@ -69,6 +69,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM @@ -411,7 +411,7 @@ index 30687391baacd693fa3bb9e3efbd492d4e4d32c8..99248a9e2769a573839b199150da312d @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java -index 6295c88832dd2f4ceec67f4f4a3477629494ccf7..f570600ca77b1b48e879198095ea54e692f3d243 100644 +index cac2845978b9beebb4e1ed6fed3eb33a698bc545..e439f0e24851697e663f783edf643d5b1602a0ff 100644 --- a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java +++ b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java @@ -64,6 +64,11 @@ public class TropicalFish extends AbstractSchoolingFish { @@ -427,10 +427,10 @@ index 6295c88832dd2f4ceec67f4f4a3477629494ccf7..f570600ca77b1b48e879198095ea54e6 public static String getPredefinedName(int variant) { diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index bd370b91e482913971816dac5f04f494c3951563..54ad776603158f101c0199395f70dadb80301a8d 100644 +index b185a58c0adb9a0dde014dd7fdeb3bd465feb706..94d0a8d94a210f62e4102f091c886bb7c48f8834 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -99,6 +99,11 @@ public class Turtle extends Animal { +@@ -97,6 +97,11 @@ public class Turtle extends Animal { public boolean isControllable() { return level.purpurConfig.turtleControllable; } @@ -443,7 +443,7 @@ index bd370b91e482913971816dac5f04f494c3951563..54ad776603158f101c0199395f70dadb public void setHomePos(BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -index b4825647058df6803be24ea30028c95179a34fb8..6312284ee33eef280a51392d7e0ba8d2ae3c9d5e 100644 +index 248531727dcafb71d7d2d2767205e09a8c0f1876..01c8508571a88c22359cbf36341338c5497e4d45 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java +++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java @@ -122,6 +122,11 @@ public class Wolf extends TamableAnimal implements NeutralMob { @@ -459,10 +459,10 @@ index b4825647058df6803be24ea30028c95179a34fb8..6312284ee33eef280a51392d7e0ba8d2 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java -index 89b6eedb23bea9239dadb8e5e06549eb7d6c3a26..c194c215ec742dd5a527af98ef7d8a707193921a 100644 +index bd88b617eb5a496943b4c21d4fad1be8e208eb23..53aef0ac481c3e79dfb04c33cb17bbdd89b2438b 100644 --- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java +++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java -@@ -119,6 +119,11 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { +@@ -117,6 +117,11 @@ public class Axolotl extends Animal implements LerpingModel, Bucketable { protected void registerGoals() { this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur } @@ -475,10 +475,10 @@ index 89b6eedb23bea9239dadb8e5e06549eb7d6c3a26..c194c215ec742dd5a527af98ef7d8a70 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java -index ea82e3f2dc219c11de7841358a6d2e1408825387..c5a86e91465e725fd11d19fd668c1ba6bbe981ac 100644 +index edf7defbd600f289de35af4a7fc57aedf8504442..49b289fce943719a63df454fefab725a2b3a7de5 100644 --- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java -@@ -84,6 +84,11 @@ public class Goat extends Animal { +@@ -104,6 +104,11 @@ public class Goat extends Animal { public boolean isControllable() { return level.purpurConfig.goatControllable; } @@ -491,10 +491,10 @@ index ea82e3f2dc219c11de7841358a6d2e1408825387..c5a86e91465e725fd11d19fd668c1ba6 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index e73045a7046850f10d79809c53b6cdd9ceb8775a..c6ee03e25adac9ecebd1e1718588b84f57184ce9 100644 +index f4190b1e1f9b4d2af04c15c472001f7f943a3cd3..66dfa478f941b47f470759f6b5e7050dae6387ab 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -125,6 +125,32 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -127,6 +127,32 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, public boolean isRidable() { return false; // vanilla handles } @@ -527,12 +527,12 @@ index e73045a7046850f10d79809c53b6cdd9ceb8775a..c6ee03e25adac9ecebd1e1718588b84f // Purpur end @Override -@@ -1149,7 +1175,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -1157,7 +1183,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, entityData = new AgeableMob.AgeableMobGroupData(0.2F); } -- this.randomizeAttributes(); -+ //this.randomizeAttributes(); // Purpur - replaced by initAttributes() +- this.randomizeAttributes(world.getRandom()); ++ // this.randomizeAttributes(world.getRandom()); // Purpur - replaced by initAttributes() return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityNbt); } @@ -563,10 +563,10 @@ index db4d5d5e38a44f85c343b632c914f2252c30a3c3..f0da5d107ddb2987ccc89f880ddba5e7 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -index a91152df3d443d70b1aa9aff97b3746e0331c0a6..9f7203608e15fdce1bfbaf419838768763d61378 100644 +index f711ea32db68fb7aece5081e741c4e161123467f..559378175e0de56b4b4eb3b8ad4cf8a4980895a9 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -@@ -44,6 +44,21 @@ public class Horse extends AbstractHorse { +@@ -45,6 +45,21 @@ public class Horse extends AbstractHorse { public boolean rideableUnderWater() { return level.purpurConfig.horseRidableInWater; } @@ -589,7 +589,7 @@ index a91152df3d443d70b1aa9aff97b3746e0331c0a6..9f7203608e15fdce1bfbaf4198387687 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 2b72dc5c76fe717bd8643a6ac45fdbb8d36bd632..7041154cf1c8fa279ab8fa9faaa3b7416e0f7f42 100644 +index b6a5ac35bed88e9d55b4de0551a13ea58901315e..19457fa164c81fd640dbe8bf1f666cb437a20487 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java @@ -115,6 +115,21 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { @@ -641,7 +641,7 @@ index a67061b875468777ee6256c0b28894c62ebb926c..1ba32a3ba56974425762026026d1e5ba @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java -index 235dae1b47641fb69e6b34e419797a1a8bf499f2..3c3be1a40f04def3f2ffb6567fa5be0581b5608d 100644 +index 9b96cff17568325d5a9ffaf4b38f1ae06630a5b4..c74f6d3384d3d18a5c591c87fc2f0850443b5afc 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java @@ -35,6 +35,21 @@ public class SkeletonHorse extends AbstractHorse { @@ -693,10 +693,10 @@ index a4a88be0cbf94b633f486ce57d4fccd38002ac9f..89f3c480d2e8cc28bb26fcd65a5a51a6 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java -index 77d05979331af91a1fbe619d1c26fa883146add8..48b72eb4051d612648a1978b38299c0c37a3a289 100644 +index 0f8ce0c6ddbb37a61c6b15bb769b627bcd8105fa..cb5981c2233dcf880fef660fe2c3f39408e8984f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java -@@ -32,6 +32,21 @@ public class ZombieHorse extends AbstractHorse { +@@ -33,6 +33,21 @@ public class ZombieHorse extends AbstractHorse { public boolean isTamed() { return true; } @@ -719,10 +719,10 @@ index 77d05979331af91a1fbe619d1c26fa883146add8..48b72eb4051d612648a1978b38299c0c public static AttributeSupplier.Builder createAttributes() { 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 114e5296645a06e222c5ed977e984f9611c27789..63ba8083c4f4a7ead9fec21eb96584f192c5cade 100644 +index 314454b8c0197002c6c2529ffb75724de16cf7a6..49454ad2de73c0a50ac1e3b9cda35f6c66e416f6 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 -@@ -161,6 +161,11 @@ public class EnderDragon extends Mob implements Enemy { +@@ -160,6 +160,11 @@ public class EnderDragon extends Mob implements Enemy { public double getMaxY() { return level.purpurConfig.enderDragonMaxY; } @@ -735,7 +735,7 @@ index 114e5296645a06e222c5ed977e984f9611c27789..63ba8083c4f4a7ead9fec21eb96584f1 public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index c475a8f53e7076f7655cebc3ac420eabee166674..a39ed2d5c52d5555ebc9c595c9541a5561b61f26 100644 +index b09b8d79e837b613e20fdac2a419403f3e0d07d7..a7d06c64dea9872e96d7f0e7dbb3a409f222b63c 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java @@ -212,6 +212,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @@ -760,7 +760,7 @@ index c475a8f53e7076f7655cebc3ac420eabee166674..a39ed2d5c52d5555ebc9c595c9541a55 } else { diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -index 6454992aa70e1476eaea67a8d9a1c27ab66f088d..1fc653194718eb4698450af5d1865a6da090c76d 100644 +index d195edea9b898e230d7837b8ab4eb7c5d4ddfaf2..773884b49ba5d0586c43f4c58cdcf9a8ce3de9e8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java +++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java @@ -72,6 +72,11 @@ public class Blaze extends Monster { @@ -808,7 +808,7 @@ index 1476372a78092b103c037028f08cb1eae9464706..9921fd8278d14deeae9d61101f6800be @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index 3ea303558940ceb925babdd2ce019f730ad12aed..20529a611faef742fcd3c4c2706bbe8009f1defa 100644 +index 869a2ee5e0775cc477fb56063dfa4ce4a0c6e3f2..4b58ca48deda0410edf9ad3c9079858d5a31a762 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java @@ -83,6 +83,16 @@ public class Drowned extends Zombie implements RangedAttackMob { @@ -829,10 +829,10 @@ index 3ea303558940ceb925babdd2ce019f730ad12aed..20529a611faef742fcd3c4c2706bbe80 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -index 7e79fe61e4fd0d26f62a0515c437370ccb0abf58..25fab7497a80a8fa65bd9cd9bdb0cd498f240bd1 100644 +index 1bf856171a9eccf77857232a30d6327b9d8017c6..725e98128fca670e370a35e763050909074b2653 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -@@ -45,6 +45,11 @@ public class ElderGuardian extends Guardian { +@@ -48,6 +48,11 @@ public class ElderGuardian extends Guardian { public boolean isControllable() { return level.purpurConfig.elderGuardianControllable; } @@ -845,7 +845,7 @@ index 7e79fe61e4fd0d26f62a0515c437370ccb0abf58..25fab7497a80a8fa65bd9cd9bdb0cd49 public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 5117838e37730f81f8089d467e861adc3edd2829..5d2dc22c920c61d4afb7b61c863f2facf8d6ec10 100644 +index 94dbdbd161202e346e1c496924139a18f6cdf9fe..1878375dc4535e0b681c9fe11c3d04b4811679be 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java @@ -102,6 +102,11 @@ public class EnderMan extends Monster implements NeutralMob { @@ -861,7 +861,7 @@ index 5117838e37730f81f8089d467e861adc3edd2829..5d2dc22c920c61d4afb7b61c863f2fac @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Endermite.java b/src/main/java/net/minecraft/world/entity/monster/Endermite.java -index 97b4342af7232bdf89382bda6a5ea50f5882cedc..2d43bdae159f1345f1f50bb9b0c5aebffa33ed96 100644 +index 8fe770c5d5ed990edd94d707827cba02222975ff..1058897ab91e13884b480ad0e5028fb2a205fe05 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Endermite.java +++ b/src/main/java/net/minecraft/world/entity/monster/Endermite.java @@ -52,6 +52,11 @@ public class Endermite extends Monster { @@ -893,7 +893,7 @@ index 169a19b605a4b7edda0d1d04e83d9bb5ea554b99..1641d5083cad8b7cd62fc1168834ff99 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Ghast.java b/src/main/java/net/minecraft/world/entity/monster/Ghast.java -index edc38e172712ebd79c1bf427d8898ab0f8244874..d9886e6831b3034781aded2b3ab6ab5e06ba9a1c 100644 +index 612ef4aa63b6076a69bfd830282394c49bff205a..3cb9b399db596b90d7885e2003ba41f4f79a3588 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Ghast.java +++ b/src/main/java/net/minecraft/world/entity/monster/Ghast.java @@ -76,6 +76,11 @@ public class Ghast extends FlyingMob implements Enemy { @@ -909,7 +909,7 @@ index edc38e172712ebd79c1bf427d8898ab0f8244874..d9886e6831b3034781aded2b3ab6ab5e @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java -index 8730d6be52a2edeccceb2ac3e6af12cdb20be5c2..fe4eb55cdfa62c169f2b7ac76d086b41c5b08892 100644 +index e310f4c451d751f4ce03562c9e3db3be313fa7db..8b1942b396606f0c989645a6ac587fbdd26a3dc5 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Giant.java +++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java @@ -35,6 +35,13 @@ public class Giant extends Monster { @@ -927,7 +927,7 @@ index 8730d6be52a2edeccceb2ac3e6af12cdb20be5c2..fe4eb55cdfa62c169f2b7ac76d086b41 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Guardian.java b/src/main/java/net/minecraft/world/entity/monster/Guardian.java -index a11e0a181323f1c409f583a8c647f433ad611d79..07f7cddb1faac701ae05e6a29c3427e7f8557cb1 100644 +index 01157172c06e022996b25ea0f566ebf703b2b3a8..aad07e8af58158079b0e54e759a08c735af91a40 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java +++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java @@ -92,6 +92,11 @@ public class Guardian extends Monster { @@ -943,7 +943,7 @@ index a11e0a181323f1c409f583a8c647f433ad611d79..07f7cddb1faac701ae05e6a29c3427e7 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Husk.java b/src/main/java/net/minecraft/world/entity/monster/Husk.java -index 80b0d8145e0901af15a7b5e423e3d605a2803dd1..ff84c706d42bc6859faaa9302ba688f43ddcb537 100644 +index 87e77fe01c9ffbbc6bcc2f8d4c10545481155bf0..e41cc68649c79dd4ce7455f36112e8347e7c84e6 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Husk.java +++ b/src/main/java/net/minecraft/world/entity/monster/Husk.java @@ -37,6 +37,16 @@ public class Husk extends Zombie { @@ -962,7 +962,7 @@ index 80b0d8145e0901af15a7b5e423e3d605a2803dd1..ff84c706d42bc6859faaa9302ba688f4 + } // Purpur end - public static boolean checkHuskSpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { + public static boolean checkHuskSpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java index 98c85e31a2238cbfa31c12214ade49c4ba181702..171e2fef10ac75dd4585a82057edb4452a6f0d22 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java @@ -982,10 +982,10 @@ index 98c85e31a2238cbfa31c12214ade49c4ba181702..171e2fef10ac75dd4585a82057edb445 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java -index 3e9ab5db23799e67e28d7fc88d4c3ad96bc44fdc..a9c8dd788affd122d98bc9a2eef068c5fb9a58ba 100644 +index 3a2261687ec8b3b1f69b89ceeb2cc8cc524ab57a..69375fdb63b9edde3d161bac7a1946a36306f0c5 100644 --- a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +++ b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java -@@ -47,6 +47,26 @@ public class MagmaCube extends Slime { +@@ -45,6 +45,26 @@ public class MagmaCube extends Slime { public float getJumpPower() { return 0.42F * this.getBlockJumpFactor(); // from EntityLiving } @@ -1051,7 +1051,7 @@ index 79c2f0482a7adbd50e1063edf2839f4fb3ab0847..6df40b92a7006c8ad6a8d89c7d81a0f4 public int getPhantomSize() { diff --git a/src/main/java/net/minecraft/world/entity/monster/Pillager.java b/src/main/java/net/minecraft/world/entity/monster/Pillager.java -index 9223c5cc4d5a1755020eb91ec7fea4943ffe499e..efb80248d3c7318aaf58861b21d497ce57fcecdc 100644 +index e3e1743e4a8d6ddccdbd08351b3524e6e2bed38c..13c0c270dc56f0e3d6e60714a3b9abeb6413c74f 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Pillager.java +++ b/src/main/java/net/minecraft/world/entity/monster/Pillager.java @@ -78,6 +78,11 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve @@ -1067,7 +1067,7 @@ index 9223c5cc4d5a1755020eb91ec7fea4943ffe499e..efb80248d3c7318aaf58861b21d497ce @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java -index aa33c5c709babb88d017d47e43de7a06954b940a..0b916be0e0ed6fcf4263759da368732f4e16542a 100644 +index fe4f2690a562601ca64e4969beadc65516edc7b2..647e0fbd0ff54944fbe7e2a9a6ac40a32919359c 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java +++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java @@ -90,6 +90,11 @@ public class Ravager extends Raider { @@ -1083,7 +1083,7 @@ index aa33c5c709babb88d017d47e43de7a06954b940a..0b916be0e0ed6fcf4263759da368732f @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java -index 9507e4817e62c749726e4cf9914f51da0aeaba71..545ca8ada7ef9cff3619d2a556ddbd01742703f1 100644 +index 7db7e4ae2ad164dd622ab9b803a5e395dff08ea5..9cc44ccd584253cb16a19e7a4747ef39a3ae82f5 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java +++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java @@ -107,6 +107,11 @@ public class Shulker extends AbstractGolem implements Enemy { @@ -1099,7 +1099,7 @@ index 9507e4817e62c749726e4cf9914f51da0aeaba71..545ca8ada7ef9cff3619d2a556ddbd01 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java -index 46539619fedda76185dc40d24f74df0b93067d61..cfbbdea914eb55f5c772f68f6494ac90c1c4c0ea 100644 +index 5f1f9ecb06555f15a464efa27f06a5dbdd255c1e..4f0f7b2685696c48f2fe297ceea7a03322b8d45e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java @@ -57,6 +57,11 @@ public class Silverfish extends Monster { @@ -1131,10 +1131,10 @@ index e73644f453bed8523bfad47764018362a416b5ea..e239bcc4d4afe48e9fc204ad38d8bc76 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index a76cc2a88a14db90901869b9bcb24e9e045501c9..d26f6bfb961cced818cfcf700bfd58f6703c7f39 100644 +index 14be612dbef97f26f7a0bb145452e44e9d50edb5..5c122ece695f61c58c90b853a0cb9a249f15b184 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -104,6 +104,37 @@ public class Slime extends Mob implements Enemy { +@@ -103,6 +103,37 @@ public class Slime extends Mob implements Enemy { } return true; // do not jump() in wasd controller, let vanilla controller handle } @@ -1185,7 +1185,7 @@ index a76cc2a88a14db90901869b9bcb24e9e045501c9..d26f6bfb961cced818cfcf700bfd58f6 this.setHealth(this.getMaxHealth()); } diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java -index a1870354e1ea5d4ef4248c04f9fe8a3dc93b9d8b..219aeced44c99e64267cff8df39e4f4e8aa55da7 100644 +index 2a0821c288dd07d7a87f5df91d04d739030fa3c5..0314b3ac32595a22e89619a928a3c5b1b0135ed4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Spider.java +++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java @@ -66,6 +66,11 @@ public class Spider extends Monster { @@ -1201,7 +1201,7 @@ index a1870354e1ea5d4ef4248c04f9fe8a3dc93b9d8b..219aeced44c99e64267cff8df39e4f4e @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Stray.java b/src/main/java/net/minecraft/world/entity/monster/Stray.java -index b97862f653fe0aca93335fdd1ef0cf871626a58c..b54368f53d3cf87f35132f811f8a917999968c1e 100644 +index 5737b1b2c2882e67082e2c0243b192ac1d50f8b7..e7f0807cc4e57c99bbd0debaebb3b9f6243c591c 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Stray.java +++ b/src/main/java/net/minecraft/world/entity/monster/Stray.java @@ -36,6 +36,11 @@ public class Stray extends AbstractSkeleton { @@ -1215,9 +1215,9 @@ index b97862f653fe0aca93335fdd1ef0cf871626a58c..b54368f53d3cf87f35132f811f8a9179 + } // Purpur end - public static boolean checkStraySpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { + public static boolean checkStraySpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Strider.java b/src/main/java/net/minecraft/world/entity/monster/Strider.java -index f809b68b0250670c07a2e0ed0f62efa8499b133f..e3f7816bb261c7772d86bd117ce30a53e77f44d1 100644 +index 7bdb28de468681884f1cffdda207932ba0412a06..c252a8f04fefbf50a8065026ace02e532ff6e307 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Strider.java +++ b/src/main/java/net/minecraft/world/entity/monster/Strider.java @@ -111,6 +111,11 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { @@ -1231,12 +1231,12 @@ index f809b68b0250670c07a2e0ed0f62efa8499b133f..e3f7816bb261c7772d86bd117ce30a53 + } // Purpur end - public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { + public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index 0f67b219e761712e9befbef4a6012a5e247c9770..ee8a1b2e5ace89a1b2f457608903fbbc80e05973 100644 +index 9bc60081a1d3f63f3b452ee5a8c8ae327f64b16e..cad3d3741460c21da2e163ed9ec6ba7894ab2712 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vex.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -100,6 +100,11 @@ public class Vex extends Monster { +@@ -101,6 +101,11 @@ public class Vex extends Monster { public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { return false; // no fall damage please } @@ -1249,7 +1249,7 @@ index 0f67b219e761712e9befbef4a6012a5e247c9770..ee8a1b2e5ace89a1b2f457608903fbbc @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index daf76124bfb812141ba7cf66a30599e9a01d4fcc..1a063c934a726c5f6a8ca1071980e18e62ba3fba 100644 +index 5f550e683b61ef3312f4500e43d6723fcbdef214..656dd2b01250c749db0acfa41992210709f5dcd3 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java @@ -73,6 +73,11 @@ public class Vindicator extends AbstractIllager { @@ -1281,10 +1281,10 @@ index 7775f1428a455f0d52f43ed07102cb242f6d23ad..0359db7ccca286df046066b4a2356a50 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java -index 54020eefe310f7cf653e97dfb525713d098e85ed..d7d15eaaed3d184c0a4f81b09f7d2b564742ecd1 100644 +index 7259a56007ac0af079a4794952f69bf2706841c8..59797dd2521d349cb1d7c2a3d5344e2b14a510ac 100644 --- a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java -@@ -49,6 +49,11 @@ public class WitherSkeleton extends AbstractSkeleton { +@@ -50,6 +50,11 @@ public class WitherSkeleton extends AbstractSkeleton { public boolean isControllable() { return level.purpurConfig.witherSkeletonControllable; } @@ -1313,7 +1313,7 @@ index a6aaffc41a39be4ae1da44d54a27d324927e47d0..a91ec2e385940b12bc41d9c09819c908 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 8d121dcb646d6d77bde48540b14c5d3770d0b276..0b3d90208b97513d295235249dfa366a2e6b3baf 100644 +index 87676587c71306f38e25d0f9548132526a7e481f..e382b739392d884ba659423e8f50c81f59a8f3fa 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -119,6 +119,11 @@ public class Zombie extends Monster { @@ -1328,7 +1328,7 @@ index 8d121dcb646d6d77bde48540b14c5d3770d0b276..0b3d90208b97513d295235249dfa366a // Purpur end @Override -@@ -601,7 +606,7 @@ public class Zombie extends Monster { +@@ -606,7 +611,7 @@ public class Zombie extends Monster { } protected void randomizeReinforcementsChance() { @@ -1338,10 +1338,10 @@ index 8d121dcb646d6d77bde48540b14c5d3770d0b276..0b3d90208b97513d295235249dfa366a @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -index fff7aeab25f3a48136f0e5d75cc66a1348091178..1c39e1ccbe8d7d3393d32babf01f045004f60bd3 100644 +index 42f6de4e9277d7208d5e0afb5a80d33f7f81ac46..e2e530aeba1311a0d89f1193ee0f6899e78ddfc0 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -94,6 +94,16 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -93,6 +93,16 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { public boolean isControllable() { return level.purpurConfig.zombieVillagerControllable; } @@ -1359,7 +1359,7 @@ index fff7aeab25f3a48136f0e5d75cc66a1348091178..1c39e1ccbe8d7d3393d32babf01f0450 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index c2cd88e8ef4b543635b02e1fdd2ac257f64a05c2..43e8eac09accc1f5f9d4b821ccff1a7a92b24121 100644 +index cf9f43d1205453af88ffdc2e96fe4376ecd45fbf..bc3ffb8867d5f7c2fa548d31256341d388bf8112 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java @@ -74,6 +74,11 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { @@ -1384,7 +1384,7 @@ index c2cd88e8ef4b543635b02e1fdd2ac257f64a05c2..43e8eac09accc1f5f9d4b821ccff1a7a @Nullable diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java -index cb1d7f09195473da382aadb82ffe552a95052254..65e6fbd8077777c63908f9faf6e387d28c86e808 100644 +index 8e93f0c152a5ac98588b3afaa631ebbbc9e4ed79..958b32de685653e75a9495cb0108e6982cc4cc97 100644 --- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java @@ -82,6 +82,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { @@ -1400,10 +1400,10 @@ index cb1d7f09195473da382aadb82ffe552a95052254..65e6fbd8077777c63908f9faf6e387d2 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -index d2c7a7e38a3bac24a176f51d7c143ecedd4ce215..ee1aadfa838aaed81760648bb6cf5b42e96d2a94 100644 +index d30e9c880323481695824f39abc1cb02204bfe44..9b8925fe938962264fdf49e97abc660d7fe8476a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -@@ -111,6 +111,11 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -110,6 +110,11 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento public boolean isControllable() { return level.purpurConfig.piglinControllable; } @@ -1416,10 +1416,10 @@ index d2c7a7e38a3bac24a176f51d7c143ecedd4ce215..ee1aadfa838aaed81760648bb6cf5b42 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -index 8ad63ae82a8b6a26c03e53b6d043128a8e038863..ec532ba1ccb0dbe50b91ba698a4f30d5bc89ca82 100644 +index ff149234a8f3e1c94961e41d5bc8117460b301d9..75db61c5aab66234b26f7899229ddca8896e2086 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -@@ -55,6 +55,11 @@ public class PiglinBrute extends AbstractPiglin { +@@ -56,6 +56,11 @@ public class PiglinBrute extends AbstractPiglin { public boolean isControllable() { return level.purpurConfig.piglinBruteControllable; } @@ -1432,10 +1432,10 @@ index 8ad63ae82a8b6a26c03e53b6d043128a8e038863..ec532ba1ccb0dbe50b91ba698a4f30d5 public static AttributeSupplier.Builder createAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index c6d232f73dd1cfe5c88848e5a89f8716c3b7dee4..d55d0a1a188813f83bc99149d38b5d4339cc9d9b 100644 +index 75fbf7f29e1cb90f87a4ba074f4ce256c810a3f8..1e56f842c0c76ae2c8ee79a31b319cb2c5c29765 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -175,6 +175,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -173,6 +173,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler protected void registerGoals() { this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); } diff --git a/patches/todo/server/0008-Timings-stuff.patch b/patches/server/0007-Timings-stuff.patch similarity index 79% rename from patches/todo/server/0008-Timings-stuff.patch rename to patches/server/0007-Timings-stuff.patch index 74d447839..3dd65241a 100644 --- a/patches/todo/server/0008-Timings-stuff.patch +++ b/patches/server/0007-Timings-stuff.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Timings stuff diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 088585a1075cd8790e2599eb6a8372adcff050e3..a2c90fb0bb297fb2faaa306dd0c032211a6e1121 100644 +index e2f60115370f19e935eb3b14d5de99aa4126c6b0..cc9536fbf472f464686343cdab729e37a14b4973 100644 --- a/src/main/java/co/aikar/timings/TimingsExport.java +++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -238,10 +238,14 @@ public class TimingsExport extends Thread { +@@ -234,9 +234,13 @@ public class TimingsExport extends Thread { // Information on the users Config parent.put("config", createObject( @@ -16,17 +16,15 @@ index 088585a1075cd8790e2599eb6a8372adcff050e3..a2c90fb0bb297fb2faaa306dd0c03221 + // Purpur start + pair("server.properties", mapAsJSON(Bukkit.spigot().getServerProperties())), pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Pufferfish -- pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)) // Pufferfish +- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) + pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), + pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), -+ pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)), // Pufferfish -+ pair("purpur", mapAsJSON(Bukkit.spigot().getPurpurConfig(), null)) ++ pair("purpur", mapAsJSON(Bukkit.spigot().getPurpurConfig()), null) + // Purpur end )); new TimingsExport(listeners, parent, history).start(); -@@ -282,6 +286,19 @@ public class TimingsExport extends Thread { +@@ -277,6 +281,19 @@ public class TimingsExport extends Thread { return timingsCost; } @@ -47,11 +45,11 @@ index 088585a1075cd8790e2599eb6a8372adcff050e3..a2c90fb0bb297fb2faaa306dd0c03221 JSONObject object = new JSONObject(); diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7a7d0566611aafafba30b7b25c2f1f3e78b054fa..820f87f8ab226c68d7ad7e125178f323e0327594 100644 +index 83121be2274a33d4188ff6fe37752432dd4e6b22..ed8b470e9d75f04d4c0277be11f81540a7f51d1c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -252,6 +252,12 @@ public class PaperConfig { - // Pufferfish end +@@ -239,6 +239,12 @@ public class PaperConfig { + boolean timings = getBoolean("timings.enabled", true); boolean verboseTimings = getBoolean("timings.verbose", true); TimingsManager.url = getString("timings.url", "https://timings.aikar.co/"); + // Purpur start diff --git a/patches/todo/server/0009-Barrels-and-enderchests-6-rows.patch b/patches/server/0008-Barrels-and-enderchests-6-rows.patch similarity index 94% rename from patches/todo/server/0009-Barrels-and-enderchests-6-rows.patch rename to patches/server/0008-Barrels-and-enderchests-6-rows.patch index 1fdf09a82..87165ee90 100644 --- a/patches/todo/server/0009-Barrels-and-enderchests-6-rows.patch +++ b/patches/server/0008-Barrels-and-enderchests-6-rows.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Barrels and enderchests 6 rows diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 409598b0bf90b7faf84b3fcac52e15b0c32b789c..a2af387c671f344d1b302e5aceab0be42c80756f 100644 +index 65a7113aec71db08d642946278472f58b6da7bd9..0fabd5998c20f6b6a682bed2086db047c19dd9c3 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1175,6 +1175,27 @@ public abstract class PlayerList { +@@ -1231,6 +1231,27 @@ public abstract class PlayerList { player.getBukkitEntity().recalculatePermissions(); // CraftBukkit this.server.getCommands().sendCommands(player); } // Paper @@ -35,12 +35,12 @@ index 409598b0bf90b7faf84b3fcac52e15b0c32b789c..a2af387c671f344d1b302e5aceab0be4 + //Purpur end } - // Paper start + public boolean isWhiteListed(GameProfile profile) { 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 54b0e70dc8d89ebcad345b414c759d70d47dd4a2..60120fcfc2127a53d90ce5bd3a819eb76801c9e8 100644 +index 4a04249441959340ad5f3a1879edd21208c7a9dc..e0a30fdeeb3402f9b34dc6b53594c85b10eab86f 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -181,6 +181,7 @@ public abstract class Player extends LivingEntity { +@@ -186,6 +186,7 @@ public abstract class Player extends LivingEntity { // Paper start public boolean affectsSpawning = true; // Paper end @@ -108,10 +108,10 @@ index 59acb1aab21e2dce0f046942f124b50ac1cb8d0f..5058b30994fe38d8db2336267121476e this.activeChest = blockEntity; } diff --git a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java -index 16d677234616daec24e7250ff3e93aa3a83e9715..51ef849b2a3af0276ed28dd3b27437d08b0387ce 100644 +index 7385e91f32f070e86a4e0fd3d214f55d832c7979..c3b78dd2d06be7d64920c6bcffcd16c82caa52b4 100644 --- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java -@@ -86,6 +86,27 @@ public class EnderChestBlock extends AbstractChestBlock i +@@ -85,6 +85,27 @@ public class EnderChestBlock extends AbstractChestBlock i EnderChestBlockEntity enderChestBlockEntity = (EnderChestBlockEntity)blockEntity; playerEnderChestContainer.setActiveChest(enderChestBlockEntity); player.openMenu(new SimpleMenuProvider((syncId, inventory, playerx) -> { @@ -140,10 +140,10 @@ index 16d677234616daec24e7250ff3e93aa3a83e9715..51ef849b2a3af0276ed28dd3b27437d0 }, CONTAINER_TITLE)); player.awardStat(Stats.OPEN_ENDERCHEST); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index 5a47d58071b83ea911e4cb5e1cc5468801ad0d55..673052e683520976399f38569e35faad83af9fe0 100644 +index f52487e1cfcfab1bf22ab2cb52f998283a86e340..da80e16b7886f22da7028a376d8e8b99c5a829b1 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -@@ -68,7 +68,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -67,7 +67,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { public BarrelBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.BARREL, pos, state); @@ -161,7 +161,7 @@ index 5a47d58071b83ea911e4cb5e1cc5468801ad0d55..673052e683520976399f38569e35faad this.openersCounter = new ContainerOpenersCounter() { @Override protected void onOpen(Level world, BlockPos pos, BlockState state) { -@@ -119,7 +128,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -118,7 +127,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @Override public int getContainerSize() { @@ -179,7 +179,7 @@ index 5a47d58071b83ea911e4cb5e1cc5468801ad0d55..673052e683520976399f38569e35faad } @Override -@@ -139,7 +157,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -138,7 +156,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @Override protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) { @@ -198,7 +198,7 @@ index 5a47d58071b83ea911e4cb5e1cc5468801ad0d55..673052e683520976399f38569e35faad @Override diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index c50813f3a3ef78ce053249ca0c93360c0bc22e8d..3c8027dafd02d3f98054c0ab79ef124953f80ff7 100644 +index a2eeaad280569c9ab2c02d2885611db50462bf2b..2bb405c2ddb32604f70328ff1f67b2bafcf6a9cb 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -165,8 +165,19 @@ public class CraftContainer extends AbstractContainerMenu { diff --git a/patches/todo/server/0010-Llama-API.patch b/patches/server/0009-Llama-API.patch similarity index 98% rename from patches/todo/server/0010-Llama-API.patch rename to patches/server/0009-Llama-API.patch index 0ccd71cd0..5275159c0 100644 --- a/patches/todo/server/0010-Llama-API.patch +++ b/patches/server/0009-Llama-API.patch @@ -25,7 +25,7 @@ index 721971f7618751a2e95f1c49fdc48a9c0c672cab..7b141c495095afcd9c8b04c059d692e8 double d = this.llama.distanceToSqr(this.llama.getCaravanHead()); if (d > 676.0D) { diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 7041154cf1c8fa279ab8fa9faaa3b7416e0f7f42..93c6e0d538dfa796b5a5b4f57d3f76fa2eef77ab 100644 +index 19457fa164c81fd640dbe8bf1f666cb437a20487..5b15b9451007a0ffcf442a33de81ff5d8b8649a5 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java @@ -68,6 +68,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { diff --git a/patches/todo/server/0011-AFK-API.patch b/patches/server/0010-AFK-API.patch similarity index 92% rename from patches/todo/server/0011-AFK-API.patch rename to patches/server/0010-AFK-API.patch index 0ac120658..3780eb51d 100644 --- a/patches/todo/server/0011-AFK-API.patch +++ b/patches/server/0010-AFK-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] AFK API diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 923a0afad1b2b14941c94332b373a704c32160a8..4f6aa9caaa471ecbeaff895508d3874577dbe5cd 100644 +index 347c01f091144f82f6eed996d424400d82634cff..b75986ae56d0a0ad6a8d347852eb94b1e4b16a79 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1974,8 +1974,58 @@ public class ServerPlayer extends Player { +@@ -2000,8 +2000,58 @@ public class ServerPlayer extends Player { public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); @@ -68,10 +68,10 @@ index 923a0afad1b2b14941c94332b373a704c32160a8..4f6aa9caaa471ecbeaff895508d38745 return this.stats; } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fe1bcca1af2bcb9e19a01ddd5cd5a8bb3789f7aa..974a94086c06cceffff3be2e0fa702967ef11d56 100644 +index 076c482e6844f6a188267556cd8fbcc592ad53f7..90b6b10ddba0224b8bc7e5f0f70edea809670e3c 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -292,6 +292,20 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -312,6 +312,20 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser private boolean justTeleported = false; private boolean hasMoved; // Spigot @@ -92,7 +92,7 @@ index fe1bcca1af2bcb9e19a01ddd5cd5a8bb3789f7aa..974a94086c06cceffff3be2e0fa70296 public CraftPlayer getCraftPlayer() { return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); } -@@ -388,6 +402,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -413,6 +427,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60) && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits. @@ -103,9 +103,9 @@ index fe1bcca1af2bcb9e19a01ddd5cd5a8bb3789f7aa..974a94086c06cceffff3be2e0fa70296 + } + // Purpur end this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 - this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause + this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause } -@@ -676,6 +696,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -702,6 +722,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -114,7 +114,7 @@ index fe1bcca1af2bcb9e19a01ddd5cd5a8bb3789f7aa..974a94086c06cceffff3be2e0fa70296 // Skip the first time we do this if (true) { // Spigot - don't skip any move events Location oldTo = to.clone(); -@@ -1449,7 +1471,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1477,7 +1499,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser if (!this.player.isChangingDimension() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot flag2 = true; // Paper - diff on change, this should be moved wrongly @@ -123,7 +123,7 @@ index fe1bcca1af2bcb9e19a01ddd5cd5a8bb3789f7aa..974a94086c06cceffff3be2e0fa70296 } this.player.absMoveTo(d0, d1, d2, f, f1); -@@ -1499,6 +1521,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -1527,6 +1549,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -167,7 +167,7 @@ index e39965c2e50bc8ee424ea07819346e0611398e28..212ea98eeaaf4b20ba0896dab03cd092 private EntitySelector() {} // Paper start diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index e752c83df50fb9b670ecea2abc95426c2a009b6f..baa4f9026d31de92210300ecb8ee8c1b6d575435 100644 +index a7575b5ef56af6f53448d391abb4956e130148ca..0a9e4dc5d6d567605c587df9bcbb57d379b62877 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java @@ -64,6 +64,10 @@ public class TargetingConditions { @@ -182,10 +182,10 @@ index e752c83df50fb9b670ecea2abc95426c2a009b6f..baa4f9026d31de92210300ecb8ee8c1b if (baseEntity == null) { if (this.isCombat && (!targetEntity.canBeSeenAsEnemy() || targetEntity.level.getDifficulty() == Difficulty.PEACEFUL)) { 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 e13b2b88e427aba1c4e6a924f4c8474d60976eb1..0228eb3bd816c35fcf4607f0a140b1e6ef56decd 100644 +index e0a30fdeeb3402f9b34dc6b53594c85b10eab86f..597b75bb429ac5a36f912c0a1f9361356dcdb726 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -196,6 +196,13 @@ public abstract class Player extends LivingEntity { +@@ -201,6 +201,13 @@ public abstract class Player extends LivingEntity { // Purpur start public abstract void resetLastActionTime(); @@ -213,10 +213,10 @@ index 3f458ddd4dc04ed28510a212be76bb19e7f6a61e..a36469186f72eccf8c4428d920d0583b if (range < 0.0D || d < range * range) { return true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 9ea7691df5d19e4f7d65869af508e38280027467..796eb59a14ace2918e0fd88b43b56b275221d6fc 100644 +index 331d9b64fd3e005c8b95fe3c926f3691392a05dc..c8becc0ece63387df0a17d192f92f35609acc181 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -445,10 +445,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -442,10 +442,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setPlayerListName(String name) { @@ -233,7 +233,7 @@ index 9ea7691df5d19e4f7d65869af508e38280027467..796eb59a14ace2918e0fd88b43b56b27 for (ServerPlayer player : (List) server.getHandle().players) { if (player.getBukkitEntity().canSee(this)) { player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, this.getHandle())); -@@ -2803,5 +2808,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2774,5 +2779,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean usesPurpurClient() { return getHandle().purpurClient; } @@ -305,10 +305,10 @@ index c38d9583d8ce50670d78b60d92c90d1d5eb4bbfc..01a2d17790b3adbc63fe742b9e5c11dd public boolean untamedTamablesAreRidable = true; public boolean useNightVisionWhenRiding = false; diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 8643df8d81714edf60eebd6984bac2c933d1fbd6..4e5583cdd78608108bb1788e6881d4b4fbf014af 100644 +index 1a1a1f4d0ac025daccc2d3f84faf6592819f4d5c..1ae88964fc3c05493516278d150537fd6699df2d 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -203,6 +203,7 @@ public class ActivationRange +@@ -199,6 +199,7 @@ public class ActivationRange continue; } diff --git a/patches/todo/server/0012-Bring-back-server-name.patch b/patches/server/0011-Bring-back-server-name.patch similarity index 82% rename from patches/todo/server/0012-Bring-back-server-name.patch rename to patches/server/0011-Bring-back-server-name.patch index 876b85ebd..350571e75 100644 --- a/patches/todo/server/0012-Bring-back-server-name.patch +++ b/patches/server/0011-Bring-back-server-name.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bring back server name diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index ebfaa8d5de5b905bd2dd7778728b8c9939d01252..8153f1aa510474d2f831799a1c1495589eca0b14 100644 +index 26345494ce190b5cd2ab58dd7d4b046796767b20..20d579a20e186e59975df1b35112015e183cee36 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -21,6 +21,7 @@ public class DedicatedServerProperties extends Settings // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return org.purpurmc.purpur.PurpurConfig.serverModName; // Purpur - Purpur > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! +- return "Purpur"; // Purpur - Purpur > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! ++ return org.purpurmc.purpur.PurpurConfig.serverModName; // Purpur - Purpur > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! } public SystemReport fillSystemReport(SystemReport details) { diff --git a/patches/todo/server/0014-LivingEntity-safeFallDistance.patch b/patches/server/0013-LivingEntity-safeFallDistance.patch similarity index 86% rename from patches/todo/server/0014-LivingEntity-safeFallDistance.patch rename to patches/server/0013-LivingEntity-safeFallDistance.patch index 122cba4ee..8bfae8d12 100644 --- a/patches/todo/server/0014-LivingEntity-safeFallDistance.patch +++ b/patches/server/0013-LivingEntity-safeFallDistance.patch @@ -5,18 +5,18 @@ Subject: [PATCH] LivingEntity safeFallDistance diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 0b671716ed700d735c76798f61abd0f5b509c2fc..86d3e06aa27357240c9c24672dc8430d8b02dd3a 100644 +index 68bbd0c1facef4d3e21975ead5b7af19ac3c1254..33235a2aa69726b14b37dfbab0f6518f7874e4d9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -253,6 +253,7 @@ public abstract class LivingEntity extends Entity { - protected Brain brain; +@@ -256,6 +256,7 @@ public abstract class LivingEntity extends Entity { + private boolean skipDropExperience; // CraftBukkit start public int expToDrop; + public float safeFallDistance = 3.0F; // Purpur public boolean forceDrops; public ArrayList drops = new ArrayList(); public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; -@@ -352,8 +353,8 @@ public abstract class LivingEntity extends Entity { +@@ -355,8 +356,8 @@ public abstract class LivingEntity extends Entity { this.tryAddSoulSpeed(); } @@ -25,9 +25,9 @@ index 0b671716ed700d735c76798f61abd0f5b509c2fc..86d3e06aa27357240c9c24672dc8430d + if (!this.level.isClientSide && this.fallDistance > this.safeFallDistance && onGround) { // Purpur + float f = (float) Mth.ceil(this.fallDistance - this.safeFallDistance); // Purpur - if (!landedState.isAir()) { + if (!state.isAir()) { double d1 = Math.min((double) (0.2F + f / 15.0F), 2.5D); -@@ -1936,7 +1937,7 @@ public abstract class LivingEntity extends Entity { +@@ -1945,7 +1946,7 @@ public abstract class LivingEntity extends Entity { MobEffectInstance mobeffect = this.getEffect(MobEffects.JUMP); float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1); @@ -37,10 +37,10 @@ index 0b671716ed700d735c76798f61abd0f5b509c2fc..86d3e06aa27357240c9c24672dc8430d protected void playBlockFallSound() { diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index c6ee03e25adac9ecebd1e1718588b84f57184ce9..0be0c81f2b0a58eba75eb8559f78d8a58014d0ae 100644 +index 66dfa478f941b47f470759f6b5e7050dae6387ab..aaf1264886394b156bd7d80a2021d2e8294ade99 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -323,7 +323,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -325,7 +325,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, @Override protected int calculateFallDamage(float fallDistance, float damageMultiplier) { @@ -50,7 +50,7 @@ index c6ee03e25adac9ecebd1e1718588b84f57184ce9..0be0c81f2b0a58eba75eb8559f78d8a5 protected int getInventorySize() { diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java -index fe4eb55cdfa62c169f2b7ac76d086b41c5b08892..61d39062021ca23aa94d9fcf584f14599fd7411c 100644 +index 8b1942b396606f0c989645a6ac587fbdd26a3dc5..c1c5e884f00398032196ee71b55b348fcfce21ce 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Giant.java +++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.LevelReader; diff --git a/patches/todo/server/0015-Lagging-threshold.patch b/patches/server/0014-Lagging-threshold.patch similarity index 77% rename from patches/todo/server/0015-Lagging-threshold.patch rename to patches/server/0014-Lagging-threshold.patch index f3bcb41ce..b0cb5d46a 100644 --- a/patches/todo/server/0015-Lagging-threshold.patch +++ b/patches/server/0014-Lagging-threshold.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Lagging threshold diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f9108dae8a563648d2f0d2c57be079c5108cec92..3e514e341632c813898a9af295e6233a91243c51 100644 +index d0fef308a6b8848a7473484956716e6c36c315c0..a653b79b3c81d5908d73e4f444d8c2baf62662de 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements EntityTypeTest { +@@ -297,6 +297,16 @@ public class EntityType implements EntityTypeTest { return (EntityType) Registry.register(Registry.ENTITY_TYPE, id, (EntityType) type.build(id)); // CraftBukkit - decompile error } @@ -25,7 +25,7 @@ index 5ec5e8a30c75b36412bacb0b60b560dfab7eeb22..811ebb8d81ab1f35743e694f925adc26 public static ResourceLocation getKey(EntityType type) { return Registry.ENTITY_TYPE.getKey(type); } -@@ -456,6 +466,16 @@ public class EntityType implements EntityTypeTest { +@@ -463,6 +473,16 @@ public class EntityType implements EntityTypeTest { return this.category; } @@ -43,7 +43,7 @@ index 5ec5e8a30c75b36412bacb0b60b560dfab7eeb22..811ebb8d81ab1f35743e694f925adc26 if (this.descriptionId == null) { this.descriptionId = Util.makeDescriptionId("entity", Registry.ENTITY_TYPE.getKey(this)); diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -index 3d9daa9e2c35d7fd277bde37cd5d1bfc9362d2ee..738120a3ec05cfa927b2a9d5d51b98b98ba42a0d 100644 +index fb37846e1c9b7715e32d0d5416b1ce4968e543df..d041b9e0a3e497f173cc64b191291c19f9b5b6bb 100644 --- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java +++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java @@ -68,6 +68,15 @@ public class SpawnEggItem extends Item { diff --git a/patches/todo/server/0017-EMC-MonsterEggSpawnEvent.patch b/patches/server/0016-EMC-MonsterEggSpawnEvent.patch similarity index 96% rename from patches/todo/server/0017-EMC-MonsterEggSpawnEvent.patch rename to patches/server/0016-EMC-MonsterEggSpawnEvent.patch index d728a4e69..04dafae77 100644 --- a/patches/todo/server/0017-EMC-MonsterEggSpawnEvent.patch +++ b/patches/server/0016-EMC-MonsterEggSpawnEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] EMC - MonsterEggSpawnEvent diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 811ebb8d81ab1f35743e694f925adc26dfdbf44e..cfa2e9a79a7917537f0f78b13c4a12bbc0826523 100644 +index 6ab4b747647f6fcd36a1f4d7ef8a3423a8171fcf..f2a59e99e35e5c704bb8399e48d92aebcd17ed35 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -339,22 +339,40 @@ public class EntityType implements EntityTypeTest { +@@ -346,22 +346,40 @@ public class EntityType implements EntityTypeTest { @Nullable public Entity spawn(ServerLevel world, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, MobSpawnType spawnReason, boolean alignPosition, boolean invertY) { @@ -52,7 +52,7 @@ index 811ebb8d81ab1f35743e694f925adc26dfdbf44e..cfa2e9a79a7917537f0f78b13c4a12bb // Paper end // Paper start - Call PreCreatureSpawnEvent org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); -@@ -373,6 +391,19 @@ public class EntityType implements EntityTypeTest { +@@ -380,6 +398,19 @@ public class EntityType implements EntityTypeTest { T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); if (t0 != null && op != null) op.accept(t0); // Paper diff --git a/patches/todo/server/0018-Player-invulnerabilities.patch b/patches/server/0017-Player-invulnerabilities.patch similarity index 87% rename from patches/todo/server/0018-Player-invulnerabilities.patch rename to patches/server/0017-Player-invulnerabilities.patch index 8e563d304..808083ad4 100644 --- a/patches/todo/server/0018-Player-invulnerabilities.patch +++ b/patches/server/0017-Player-invulnerabilities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player invulnerabilities diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e86f1b4b3 100644 +index b75986ae56d0a0ad6a8d347852eb94b1e4b16a79..39d86b7b3a01f2eefb7c0725e930a5371e7baf46 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -254,6 +254,7 @@ public class ServerPlayer extends Player { +@@ -261,6 +261,7 @@ public class ServerPlayer extends Player { // CraftBukkit end public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper public boolean purpurClient = false; // Purpur @@ -16,7 +16,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -@@ -330,6 +331,7 @@ public class ServerPlayer extends Player { +@@ -337,6 +338,7 @@ public class ServerPlayer extends Player { this.bukkitPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper @@ -24,7 +24,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e } // Paper start - Chunk priority public BlockPos getPointInFront(double inFront) { -@@ -1010,6 +1012,12 @@ public class ServerPlayer extends Player { +@@ -1019,6 +1021,12 @@ public class ServerPlayer extends Player { } @@ -37,7 +37,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e @Override public boolean hurt(DamageSource source, float amount) { if (this.isInvulnerableTo(source)) { -@@ -1017,7 +1025,7 @@ public class ServerPlayer extends Player { +@@ -1026,7 +1034,7 @@ public class ServerPlayer extends Player { } else { boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && "fall".equals(source.msgId); @@ -46,7 +46,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e return false; } else { if (source instanceof EntityDamageSource) { -@@ -1190,6 +1198,7 @@ public class ServerPlayer extends Player { +@@ -1199,6 +1207,7 @@ public class ServerPlayer extends Player { } // Paper end @@ -54,7 +54,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e return this; } } -@@ -1964,6 +1973,7 @@ public class ServerPlayer extends Player { +@@ -1986,6 +1995,7 @@ public class ServerPlayer extends Player { } public void sendTexturePack(String url, String hash, boolean required, @Nullable Component resourcePackPrompt) { @@ -62,7 +62,7 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e this.connection.send(new ClientboundResourcePackPacket(url, hash, required, resourcePackPrompt)); } -@@ -2474,9 +2484,17 @@ public class ServerPlayer extends Player { +@@ -2511,9 +2521,17 @@ public class ServerPlayer extends Player { @Override public boolean isImmobile() { @@ -82,10 +82,10 @@ index 4f6aa9caaa471ecbeaff895508d3874577dbe5cd..46f536d45470da1af7cae8eb6524ad5e public Scoreboard getScoreboard() { return this.getBukkitEntity().getScoreboard().getHandle(); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 974a94086c06cceffff3be2e0fa702967ef11d56..d9e4a2c56820ea6de0d31721e1796ea7165cb256 100644 +index 90b6b10ddba0224b8bc7e5f0f70edea809670e3c..f9ff242f05fc5b1c0614403a7e81876f0ad85ca0 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1984,12 +1984,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -2001,12 +2001,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override public void handleResourcePackResponse(ServerboundResourcePackPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); @@ -98,7 +98,7 @@ index 974a94086c06cceffff3be2e0fa702967ef11d56..d9e4a2c56820ea6de0d31721e1796ea7 + // Purpur end if (packet.getAction() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); - this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"), org.bukkit.event.player.PlayerKickEvent.Cause.RESOURCE_PACK_REJECTION); // Paper - add cause + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"), org.bukkit.event.player.PlayerKickEvent.Cause.RESOURCE_PACK_REJECTION); // Paper - add cause } // Paper start PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; @@ -108,7 +108,7 @@ index 974a94086c06cceffff3be2e0fa702967ef11d56..d9e4a2c56820ea6de0d31721e1796ea7 this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packStatus)); // CraftBukkit // Paper end diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index f126020b99c2dc32fd2e34e1fd7ae6bc9872e67f..c5be8e891534cc41e3b530f303f18d88cf5340cc 100644 +index 0fabd5998c20f6b6a682bed2086db047c19dd9c3..68478f19e029d3544505188fd42950d63d91c86f 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -1004,6 +1004,8 @@ public abstract class PlayerList { @@ -121,10 +121,10 @@ index f126020b99c2dc32fd2e34e1fd7ae6bc9872e67f..c5be8e891534cc41e3b530f303f18d88 return entityplayer1; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 796eb59a14ace2918e0fd88b43b56b275221d6fc..2cd475ac88b3d28aa918ca7f8599a70a5b5c2ea4 100644 +index c8becc0ece63387df0a17d192f92f35609acc181..cc623f511a69c3fdc8bfc196d48d4938010c909a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2823,5 +2823,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2794,5 +2794,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void resetIdleTimer() { getHandle().resetLastActionTime(); } diff --git a/patches/todo/server/0019-Anvil-API.patch b/patches/server/0018-Anvil-API.patch similarity index 88% rename from patches/todo/server/0019-Anvil-API.patch rename to patches/server/0018-Anvil-API.patch index 015dc1b67..0761b70ba 100644 --- a/patches/todo/server/0019-Anvil-API.patch +++ b/patches/server/0018-Anvil-API.patch @@ -5,22 +5,24 @@ Subject: [PATCH] Anvil API diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf4f724659 100644 +index 506d758efbf16da9467f120321d2359a8832e477..c1ed57bae737fca803c2dd8666207dbffc6758c3 100644 --- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java -@@ -3,7 +3,11 @@ package net.minecraft.world.inventory; - import com.mojang.logging.LogUtils; - import java.util.Iterator; - import java.util.Map; +@@ -21,6 +21,13 @@ import org.slf4j.Logger; + import org.bukkit.craftbukkit.inventory.CraftInventoryView; + // CraftBukkit end + ++// Purpur start +import net.minecraft.nbt.IntTag; - import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.protocol.game.ClientboundContainerSetDataPacket; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.server.level.ServerPlayer; - import net.minecraft.tags.BlockTags; - import net.minecraft.world.entity.player.Inventory; - import net.minecraft.world.entity.player.Player; -@@ -41,6 +45,8 @@ public class AnvilMenu extends ItemCombinerMenu { ++// Purpur end ++ + public class AnvilMenu extends ItemCombinerMenu { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -41,6 +48,8 @@ public class AnvilMenu extends ItemCombinerMenu { public int maximumRepairCost = 40; private CraftInventoryView bukkitEntity; // CraftBukkit end @@ -29,7 +31,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf public AnvilMenu(int syncId, Inventory inventory) { this(syncId, inventory, ContainerLevelAccess.NULL); -@@ -59,12 +65,14 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -59,12 +68,14 @@ public class AnvilMenu extends ItemCombinerMenu { @Override protected boolean mayPickup(Player player, boolean present) { @@ -45,7 +47,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf player.giveExperienceLevels(-this.cost.get()); } -@@ -115,6 +123,12 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -115,6 +126,12 @@ public class AnvilMenu extends ItemCombinerMenu { @Override public void createResult() { @@ -58,7 +60,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf ItemStack itemstack = this.inputSlots.getItem(0); this.cost.set(1); -@@ -191,7 +205,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -191,7 +208,7 @@ public class AnvilMenu extends ItemCombinerMenu { int i2 = (Integer) map1.get(enchantment); i2 = l1 == i2 ? i2 + 1 : Math.max(i2, l1); @@ -67,7 +69,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf if (this.player.getAbilities().instabuild || itemstack.is(Items.ENCHANTED_BOOK)) { flag3 = true; -@@ -203,7 +217,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -203,7 +220,7 @@ public class AnvilMenu extends ItemCombinerMenu { Enchantment enchantment1 = (Enchantment) iterator1.next(); if (enchantment1 != enchantment && !enchantment.isCompatibleWith(enchantment1)) { @@ -76,7 +78,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf ++i; } } -@@ -274,6 +288,13 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -274,6 +291,13 @@ public class AnvilMenu extends ItemCombinerMenu { this.cost.set(this.maximumRepairCost - 1); // CraftBukkit } @@ -90,7 +92,7 @@ index ec89526f1eabef4681fed57b74fc1bef5be4c0c1..a88efd9b435349ae00c4152f09d87ebf if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit itemstack1 = ItemStack.EMPTY; } -@@ -296,6 +317,12 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -296,6 +320,12 @@ public class AnvilMenu extends ItemCombinerMenu { org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemstack1); // CraftBukkit sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client this.broadcastChanges(); diff --git a/patches/todo/server/0020-Configurable-villager-brain-ticks.patch b/patches/server/0019-Configurable-villager-brain-ticks.patch similarity index 69% rename from patches/todo/server/0020-Configurable-villager-brain-ticks.patch rename to patches/server/0019-Configurable-villager-brain-ticks.patch index 6a0207d53..10a1a0505 100644 --- a/patches/todo/server/0020-Configurable-villager-brain-ticks.patch +++ b/patches/server/0019-Configurable-villager-brain-ticks.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Configurable villager brain ticks diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index d55d0a1a188813f83bc99149d38b5d4339cc9d9b..2786df9e1ee9f7e774fef3d9f4bb3db3b9440b10 100644 +index 1e56f842c0c76ae2c8ee79a31b319cb2c5c29765..32eb697dd08c1ef0b832659e702675f70f9145cf 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -139,6 +139,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - }, MemoryModuleType.MEETING_POINT, (entityvillager, villageplacetype) -> { - return villageplacetype == PoiType.MEETING; + }, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> { + return holder.is(PoiTypes.MEETING); }); + private final int brainTickOffset; // Purpur - public long nextGolemPanic = -1; // Pufferfish - -@@ -153,6 +154,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + public Villager(EntityType entityType, Level world) { + this(entityType, world, VillagerType.PLAINS); +@@ -151,6 +152,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.getNavigation().setCanFloat(true); this.setCanPickUpLoot(true); this.setVillagerData(this.getVillagerData().setType(type).setProfession(VillagerProfession.NONE)); @@ -24,17 +24,17 @@ index d55d0a1a188813f83bc99149d38b5d4339cc9d9b..2786df9e1ee9f7e774fef3d9f4bb3db3 } // Purpur start -@@ -279,6 +281,10 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -274,6 +276,10 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + protected void customServerAiStep() { mobTick(false); } + protected void mobTick(boolean inactive) { this.level.getProfiler().push("villagerBrain"); - // Pufferfish start - if (!inactive) { -+ // Purpur start -+ boolean tick = (level.getGameTime() + brainTickOffset) % level.purpurConfig.villagerBrainTicks == 0; -+ if (((ServerLevel) level).getServer().lagging ? tick : level.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick) -+ // Purpur end - if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level, this); // Paper - } ++ // Purpur start ++ boolean tick = (level.getGameTime() + brainTickOffset) % level.purpurConfig.villagerBrainTicks == 0; ++ if (((ServerLevel) level).getServer().lagging ? tick : level.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick) ++ // Purpur end + if (getRider() == null || !this.isControllable())// Purpur - only use brain if no rider + if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // Paper + this.level.getProfiler().pop(); diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java index 81524c4f676766c09125187876b46e0704294880..93d89fb27044e5e97574122b0e7863694d245bf0 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java diff --git a/patches/todo/server/0006-Ridables.patch b/patches/todo/pufferfish/0006-Ridables.patch similarity index 100% rename from patches/todo/server/0006-Ridables.patch rename to patches/todo/pufferfish/0006-Ridables.patch diff --git a/patches/todo/server/0021-Alternative-Keepalive-Handling.patch b/patches/unapplied/0021-Alternative-Keepalive-Handling.patch similarity index 100% rename from patches/todo/server/0021-Alternative-Keepalive-Handling.patch rename to patches/unapplied/0021-Alternative-Keepalive-Handling.patch diff --git a/patches/todo/server/0022-Silk-touch-spawners.patch b/patches/unapplied/0022-Silk-touch-spawners.patch similarity index 100% rename from patches/todo/server/0022-Silk-touch-spawners.patch rename to patches/unapplied/0022-Silk-touch-spawners.patch diff --git a/patches/todo/server/0023-MC-168772-Fix-Add-turtle-egg-block-options.patch b/patches/unapplied/0023-MC-168772-Fix-Add-turtle-egg-block-options.patch similarity index 100% rename from patches/todo/server/0023-MC-168772-Fix-Add-turtle-egg-block-options.patch rename to patches/unapplied/0023-MC-168772-Fix-Add-turtle-egg-block-options.patch diff --git a/patches/todo/server/0024-Fix-vanilla-command-permission-handler.patch b/patches/unapplied/0024-Fix-vanilla-command-permission-handler.patch similarity index 100% rename from patches/todo/server/0024-Fix-vanilla-command-permission-handler.patch rename to patches/unapplied/0024-Fix-vanilla-command-permission-handler.patch diff --git a/patches/todo/server/0025-Logger-settings-suppressing-pointless-logs.patch b/patches/unapplied/0025-Logger-settings-suppressing-pointless-logs.patch similarity index 100% rename from patches/todo/server/0025-Logger-settings-suppressing-pointless-logs.patch rename to patches/unapplied/0025-Logger-settings-suppressing-pointless-logs.patch diff --git a/patches/todo/server/0026-Disable-outdated-build-check.patch b/patches/unapplied/0026-Disable-outdated-build-check.patch similarity index 100% rename from patches/todo/server/0026-Disable-outdated-build-check.patch rename to patches/unapplied/0026-Disable-outdated-build-check.patch diff --git a/patches/todo/server/0027-Giants-AI-settings.patch b/patches/unapplied/0027-Giants-AI-settings.patch similarity index 100% rename from patches/todo/server/0027-Giants-AI-settings.patch rename to patches/unapplied/0027-Giants-AI-settings.patch diff --git a/patches/todo/server/0028-Zombie-horse-naturally-spawn.patch b/patches/unapplied/0028-Zombie-horse-naturally-spawn.patch similarity index 100% rename from patches/todo/server/0028-Zombie-horse-naturally-spawn.patch rename to patches/unapplied/0028-Zombie-horse-naturally-spawn.patch diff --git a/patches/todo/server/0029-Charged-creeper-naturally-spawn.patch b/patches/unapplied/0029-Charged-creeper-naturally-spawn.patch similarity index 100% rename from patches/todo/server/0029-Charged-creeper-naturally-spawn.patch rename to patches/unapplied/0029-Charged-creeper-naturally-spawn.patch diff --git a/patches/todo/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch b/patches/unapplied/0030-Rabbit-naturally-spawn-toast-and-killer.patch similarity index 100% rename from patches/todo/server/0030-Rabbit-naturally-spawn-toast-and-killer.patch rename to patches/unapplied/0030-Rabbit-naturally-spawn-toast-and-killer.patch diff --git a/patches/todo/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch b/patches/unapplied/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch similarity index 100% rename from patches/todo/server/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch rename to patches/unapplied/0031-Fix-outdated-server-showing-in-ping-before-server-fu.patch diff --git a/patches/todo/server/0032-Tulips-change-fox-type.patch b/patches/unapplied/0032-Tulips-change-fox-type.patch similarity index 100% rename from patches/todo/server/0032-Tulips-change-fox-type.patch rename to patches/unapplied/0032-Tulips-change-fox-type.patch diff --git a/patches/todo/server/0033-Breedable-Polar-Bears.patch b/patches/unapplied/0033-Breedable-Polar-Bears.patch similarity index 100% rename from patches/todo/server/0033-Breedable-Polar-Bears.patch rename to patches/unapplied/0033-Breedable-Polar-Bears.patch diff --git a/patches/todo/server/0034-Chickens-can-retaliate.patch b/patches/unapplied/0034-Chickens-can-retaliate.patch similarity index 100% rename from patches/todo/server/0034-Chickens-can-retaliate.patch rename to patches/unapplied/0034-Chickens-can-retaliate.patch diff --git a/patches/todo/server/0035-Add-option-to-set-armorstand-step-height.patch b/patches/unapplied/0035-Add-option-to-set-armorstand-step-height.patch similarity index 100% rename from patches/todo/server/0035-Add-option-to-set-armorstand-step-height.patch rename to patches/unapplied/0035-Add-option-to-set-armorstand-step-height.patch diff --git a/patches/todo/server/0036-Cat-spawning-options.patch b/patches/unapplied/0036-Cat-spawning-options.patch similarity index 100% rename from patches/todo/server/0036-Cat-spawning-options.patch rename to patches/unapplied/0036-Cat-spawning-options.patch diff --git a/patches/todo/server/0037-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch b/patches/unapplied/0037-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch similarity index 100% rename from patches/todo/server/0037-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch rename to patches/unapplied/0037-MC-147659-Fix-non-black-cats-spawning-in-swamp-huts.patch diff --git a/patches/todo/server/0038-Cows-eat-mushrooms.patch b/patches/unapplied/0038-Cows-eat-mushrooms.patch similarity index 100% rename from patches/todo/server/0038-Cows-eat-mushrooms.patch rename to patches/unapplied/0038-Cows-eat-mushrooms.patch diff --git a/patches/todo/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch b/patches/unapplied/0039-Fix-cow-rotation-when-shearing-mooshroom.patch similarity index 100% rename from patches/todo/server/0039-Fix-cow-rotation-when-shearing-mooshroom.patch rename to patches/unapplied/0039-Fix-cow-rotation-when-shearing-mooshroom.patch diff --git a/patches/todo/server/0040-Pigs-give-saddle-back.patch b/patches/unapplied/0040-Pigs-give-saddle-back.patch similarity index 100% rename from patches/todo/server/0040-Pigs-give-saddle-back.patch rename to patches/unapplied/0040-Pigs-give-saddle-back.patch diff --git a/patches/todo/server/0041-Snowman-drop-and-put-back-pumpkin.patch b/patches/unapplied/0041-Snowman-drop-and-put-back-pumpkin.patch similarity index 100% rename from patches/todo/server/0041-Snowman-drop-and-put-back-pumpkin.patch rename to patches/unapplied/0041-Snowman-drop-and-put-back-pumpkin.patch diff --git a/patches/todo/server/0042-Ender-dragon-always-drop-full-exp.patch b/patches/unapplied/0042-Ender-dragon-always-drop-full-exp.patch similarity index 100% rename from patches/todo/server/0042-Ender-dragon-always-drop-full-exp.patch rename to patches/unapplied/0042-Ender-dragon-always-drop-full-exp.patch diff --git a/patches/todo/server/0043-Signs-editable-on-right-click.patch b/patches/unapplied/0043-Signs-editable-on-right-click.patch similarity index 100% rename from patches/todo/server/0043-Signs-editable-on-right-click.patch rename to patches/unapplied/0043-Signs-editable-on-right-click.patch diff --git a/patches/todo/server/0044-Allow-soil-to-moisten-from-water-directly-under-it.patch b/patches/unapplied/0044-Allow-soil-to-moisten-from-water-directly-under-it.patch similarity index 100% rename from patches/todo/server/0044-Allow-soil-to-moisten-from-water-directly-under-it.patch rename to patches/unapplied/0044-Allow-soil-to-moisten-from-water-directly-under-it.patch diff --git a/patches/todo/server/0045-Minecart-settings-and-WASD-controls.patch b/patches/unapplied/0045-Minecart-settings-and-WASD-controls.patch similarity index 100% rename from patches/todo/server/0045-Minecart-settings-and-WASD-controls.patch rename to patches/unapplied/0045-Minecart-settings-and-WASD-controls.patch diff --git a/patches/todo/server/0046-Disable-loot-drops-on-death-by-cramming.patch b/patches/unapplied/0046-Disable-loot-drops-on-death-by-cramming.patch similarity index 100% rename from patches/todo/server/0046-Disable-loot-drops-on-death-by-cramming.patch rename to patches/unapplied/0046-Disable-loot-drops-on-death-by-cramming.patch diff --git a/patches/todo/server/0047-Option-to-toggle-milk-curing-bad-omen.patch b/patches/unapplied/0047-Option-to-toggle-milk-curing-bad-omen.patch similarity index 100% rename from patches/todo/server/0047-Option-to-toggle-milk-curing-bad-omen.patch rename to patches/unapplied/0047-Option-to-toggle-milk-curing-bad-omen.patch diff --git a/patches/todo/server/0048-End-gateway-should-check-if-entity-can-use-portal.patch b/patches/unapplied/0048-End-gateway-should-check-if-entity-can-use-portal.patch similarity index 100% rename from patches/todo/server/0048-End-gateway-should-check-if-entity-can-use-portal.patch rename to patches/unapplied/0048-End-gateway-should-check-if-entity-can-use-portal.patch diff --git a/patches/todo/server/0049-Fix-the-dead-lagging-the-server.patch b/patches/unapplied/0049-Fix-the-dead-lagging-the-server.patch similarity index 100% rename from patches/todo/server/0049-Fix-the-dead-lagging-the-server.patch rename to patches/unapplied/0049-Fix-the-dead-lagging-the-server.patch diff --git a/patches/todo/server/0050-Skip-events-if-there-s-no-listeners.patch b/patches/unapplied/0050-Skip-events-if-there-s-no-listeners.patch similarity index 100% rename from patches/todo/server/0050-Skip-events-if-there-s-no-listeners.patch rename to patches/unapplied/0050-Skip-events-if-there-s-no-listeners.patch diff --git a/patches/todo/server/0051-Add-permission-for-F3-N-debug.patch b/patches/unapplied/0051-Add-permission-for-F3-N-debug.patch similarity index 100% rename from patches/todo/server/0051-Add-permission-for-F3-N-debug.patch rename to patches/unapplied/0051-Add-permission-for-F3-N-debug.patch diff --git a/patches/todo/server/0052-Configurable-TPS-Catchup.patch b/patches/unapplied/0052-Configurable-TPS-Catchup.patch similarity index 100% rename from patches/todo/server/0052-Configurable-TPS-Catchup.patch rename to patches/unapplied/0052-Configurable-TPS-Catchup.patch diff --git a/patches/todo/server/0053-Add-option-to-allow-loyalty-on-tridents-to-work-in-t.patch b/patches/unapplied/0053-Add-option-to-allow-loyalty-on-tridents-to-work-in-t.patch similarity index 100% rename from patches/todo/server/0053-Add-option-to-allow-loyalty-on-tridents-to-work-in-t.patch rename to patches/unapplied/0053-Add-option-to-allow-loyalty-on-tridents-to-work-in-t.patch diff --git a/patches/todo/server/0054-Add-enderman-and-creeper-griefing-controls.patch b/patches/unapplied/0054-Add-enderman-and-creeper-griefing-controls.patch similarity index 100% rename from patches/todo/server/0054-Add-enderman-and-creeper-griefing-controls.patch rename to patches/unapplied/0054-Add-enderman-and-creeper-griefing-controls.patch diff --git a/patches/todo/server/0055-Villagers-follow-emerald-blocks.patch b/patches/unapplied/0055-Villagers-follow-emerald-blocks.patch similarity index 100% rename from patches/todo/server/0055-Villagers-follow-emerald-blocks.patch rename to patches/unapplied/0055-Villagers-follow-emerald-blocks.patch diff --git a/patches/todo/server/0056-Allow-leashing-villagers.patch b/patches/unapplied/0056-Allow-leashing-villagers.patch similarity index 100% rename from patches/todo/server/0056-Allow-leashing-villagers.patch rename to patches/unapplied/0056-Allow-leashing-villagers.patch diff --git a/patches/todo/server/0057-Implement-configurable-search-radius-for-villagers-t.patch b/patches/unapplied/0057-Implement-configurable-search-radius-for-villagers-t.patch similarity index 100% rename from patches/todo/server/0057-Implement-configurable-search-radius-for-villagers-t.patch rename to patches/unapplied/0057-Implement-configurable-search-radius-for-villagers-t.patch diff --git a/patches/todo/server/0058-Implement-infinite-liquids.patch b/patches/unapplied/0058-Implement-infinite-liquids.patch similarity index 100% rename from patches/todo/server/0058-Implement-infinite-liquids.patch rename to patches/unapplied/0058-Implement-infinite-liquids.patch diff --git a/patches/todo/server/0059-Make-lava-flow-speed-configurable.patch b/patches/unapplied/0059-Make-lava-flow-speed-configurable.patch similarity index 100% rename from patches/todo/server/0059-Make-lava-flow-speed-configurable.patch rename to patches/unapplied/0059-Make-lava-flow-speed-configurable.patch diff --git a/patches/todo/server/0060-Add-player-death-exp-control-options.patch b/patches/unapplied/0060-Add-player-death-exp-control-options.patch similarity index 100% rename from patches/todo/server/0060-Add-player-death-exp-control-options.patch rename to patches/unapplied/0060-Add-player-death-exp-control-options.patch diff --git a/patches/todo/server/0061-Configurable-void-damage-height-and-damage.patch b/patches/unapplied/0061-Configurable-void-damage-height-and-damage.patch similarity index 100% rename from patches/todo/server/0061-Configurable-void-damage-height-and-damage.patch rename to patches/unapplied/0061-Configurable-void-damage-height-and-damage.patch diff --git a/patches/todo/server/0062-Add-canSaveToDisk-to-Entity.patch b/patches/unapplied/0062-Add-canSaveToDisk-to-Entity.patch similarity index 100% rename from patches/todo/server/0062-Add-canSaveToDisk-to-Entity.patch rename to patches/unapplied/0062-Add-canSaveToDisk-to-Entity.patch diff --git a/patches/todo/server/0063-Dispenser-curse-of-binding-protection.patch b/patches/unapplied/0063-Dispenser-curse-of-binding-protection.patch similarity index 100% rename from patches/todo/server/0063-Dispenser-curse-of-binding-protection.patch rename to patches/unapplied/0063-Dispenser-curse-of-binding-protection.patch diff --git a/patches/todo/server/0064-Add-option-for-boats-to-eject-players-on-land.patch b/patches/unapplied/0064-Add-option-for-boats-to-eject-players-on-land.patch similarity index 100% rename from patches/todo/server/0064-Add-option-for-boats-to-eject-players-on-land.patch rename to patches/unapplied/0064-Add-option-for-boats-to-eject-players-on-land.patch diff --git a/patches/todo/server/0065-Mending-mends-most-damages-equipment-first.patch b/patches/unapplied/0065-Mending-mends-most-damages-equipment-first.patch similarity index 100% rename from patches/todo/server/0065-Mending-mends-most-damages-equipment-first.patch rename to patches/unapplied/0065-Mending-mends-most-damages-equipment-first.patch diff --git a/patches/todo/server/0066-Add-5-second-tps-average-in-tps.patch b/patches/unapplied/0066-Add-5-second-tps-average-in-tps.patch similarity index 100% rename from patches/todo/server/0066-Add-5-second-tps-average-in-tps.patch rename to patches/unapplied/0066-Add-5-second-tps-average-in-tps.patch diff --git a/patches/todo/server/0067-Implement-elytra-settings.patch b/patches/unapplied/0067-Implement-elytra-settings.patch similarity index 100% rename from patches/todo/server/0067-Implement-elytra-settings.patch rename to patches/unapplied/0067-Implement-elytra-settings.patch diff --git a/patches/todo/server/0068-Item-entity-immunities.patch b/patches/unapplied/0068-Item-entity-immunities.patch similarity index 100% rename from patches/todo/server/0068-Item-entity-immunities.patch rename to patches/unapplied/0068-Item-entity-immunities.patch diff --git a/patches/todo/server/0069-Add-ping-command.patch b/patches/unapplied/0069-Add-ping-command.patch similarity index 100% rename from patches/todo/server/0069-Add-ping-command.patch rename to patches/unapplied/0069-Add-ping-command.patch diff --git a/patches/todo/server/0070-Add-demo-command.patch b/patches/unapplied/0070-Add-demo-command.patch similarity index 100% rename from patches/todo/server/0070-Add-demo-command.patch rename to patches/unapplied/0070-Add-demo-command.patch diff --git a/patches/todo/server/0071-Add-credits-command.patch b/patches/unapplied/0071-Add-credits-command.patch similarity index 100% rename from patches/todo/server/0071-Add-credits-command.patch rename to patches/unapplied/0071-Add-credits-command.patch diff --git a/patches/todo/server/0072-Configurable-jockey-options.patch b/patches/unapplied/0072-Configurable-jockey-options.patch similarity index 100% rename from patches/todo/server/0072-Configurable-jockey-options.patch rename to patches/unapplied/0072-Configurable-jockey-options.patch diff --git a/patches/todo/server/0073-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/unapplied/0073-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch similarity index 100% rename from patches/todo/server/0073-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch rename to patches/unapplied/0073-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch diff --git a/patches/todo/server/0074-Add-phantom-spawning-options.patch b/patches/unapplied/0074-Add-phantom-spawning-options.patch similarity index 100% rename from patches/todo/server/0074-Add-phantom-spawning-options.patch rename to patches/unapplied/0074-Add-phantom-spawning-options.patch diff --git a/patches/todo/server/0075-Implement-bed-explosion-options.patch b/patches/unapplied/0075-Implement-bed-explosion-options.patch similarity index 100% rename from patches/todo/server/0075-Implement-bed-explosion-options.patch rename to patches/unapplied/0075-Implement-bed-explosion-options.patch diff --git a/patches/todo/server/0076-Implement-respawn-anchor-explosion-options.patch b/patches/unapplied/0076-Implement-respawn-anchor-explosion-options.patch similarity index 100% rename from patches/todo/server/0076-Implement-respawn-anchor-explosion-options.patch rename to patches/unapplied/0076-Implement-respawn-anchor-explosion-options.patch diff --git a/patches/todo/server/0077-Add-allow-water-in-end-world-option.patch b/patches/unapplied/0077-Add-allow-water-in-end-world-option.patch similarity index 100% rename from patches/todo/server/0077-Add-allow-water-in-end-world-option.patch rename to patches/unapplied/0077-Add-allow-water-in-end-world-option.patch diff --git a/patches/todo/server/0078-Allow-color-codes-in-books.patch b/patches/unapplied/0078-Allow-color-codes-in-books.patch similarity index 100% rename from patches/todo/server/0078-Allow-color-codes-in-books.patch rename to patches/unapplied/0078-Allow-color-codes-in-books.patch diff --git a/patches/todo/server/0079-Entity-lifespan.patch b/patches/unapplied/0079-Entity-lifespan.patch similarity index 100% rename from patches/todo/server/0079-Entity-lifespan.patch rename to patches/unapplied/0079-Entity-lifespan.patch diff --git a/patches/todo/server/0080-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch b/patches/unapplied/0080-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch similarity index 100% rename from patches/todo/server/0080-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch rename to patches/unapplied/0080-Add-option-to-teleport-to-spawn-if-outside-world-bor.patch diff --git a/patches/todo/server/0081-Squid-EAR-immunity.patch b/patches/unapplied/0081-Squid-EAR-immunity.patch similarity index 100% rename from patches/todo/server/0081-Squid-EAR-immunity.patch rename to patches/unapplied/0081-Squid-EAR-immunity.patch diff --git a/patches/todo/server/0082-Phantoms-burn-in-light.patch b/patches/unapplied/0082-Phantoms-burn-in-light.patch similarity index 100% rename from patches/todo/server/0082-Phantoms-burn-in-light.patch rename to patches/unapplied/0082-Phantoms-burn-in-light.patch diff --git a/patches/todo/server/0083-Configurable-villager-breeding.patch b/patches/unapplied/0083-Configurable-villager-breeding.patch similarity index 100% rename from patches/todo/server/0083-Configurable-villager-breeding.patch rename to patches/unapplied/0083-Configurable-villager-breeding.patch diff --git a/patches/todo/server/0084-Redstone-deactivates-spawners.patch b/patches/unapplied/0084-Redstone-deactivates-spawners.patch similarity index 100% rename from patches/todo/server/0084-Redstone-deactivates-spawners.patch rename to patches/unapplied/0084-Redstone-deactivates-spawners.patch diff --git a/patches/todo/server/0085-Totems-work-in-inventory.patch b/patches/unapplied/0085-Totems-work-in-inventory.patch similarity index 100% rename from patches/todo/server/0085-Totems-work-in-inventory.patch rename to patches/unapplied/0085-Totems-work-in-inventory.patch diff --git a/patches/todo/server/0086-Add-vindicator-johnny-spawn-chance.patch b/patches/unapplied/0086-Add-vindicator-johnny-spawn-chance.patch similarity index 100% rename from patches/todo/server/0086-Add-vindicator-johnny-spawn-chance.patch rename to patches/unapplied/0086-Add-vindicator-johnny-spawn-chance.patch diff --git a/patches/todo/server/0087-Add-option-to-disable-certain-block-updates.patch b/patches/unapplied/0087-Add-option-to-disable-certain-block-updates.patch similarity index 100% rename from patches/todo/server/0087-Add-option-to-disable-certain-block-updates.patch rename to patches/unapplied/0087-Add-option-to-disable-certain-block-updates.patch diff --git a/patches/todo/server/0088-Dispensers-place-anvils-option.patch b/patches/unapplied/0088-Dispensers-place-anvils-option.patch similarity index 100% rename from patches/todo/server/0088-Dispensers-place-anvils-option.patch rename to patches/unapplied/0088-Dispensers-place-anvils-option.patch diff --git a/patches/todo/server/0089-Allow-anvil-colors.patch b/patches/unapplied/0089-Allow-anvil-colors.patch similarity index 100% rename from patches/todo/server/0089-Allow-anvil-colors.patch rename to patches/unapplied/0089-Allow-anvil-colors.patch diff --git a/patches/todo/server/0090-Add-option-to-disable-dolphin-treasure-searching.patch b/patches/unapplied/0090-Add-option-to-disable-dolphin-treasure-searching.patch similarity index 100% rename from patches/todo/server/0090-Add-option-to-disable-dolphin-treasure-searching.patch rename to patches/unapplied/0090-Add-option-to-disable-dolphin-treasure-searching.patch diff --git a/patches/todo/server/0091-Short-enderman-height.patch b/patches/unapplied/0091-Short-enderman-height.patch similarity index 100% rename from patches/todo/server/0091-Short-enderman-height.patch rename to patches/unapplied/0091-Short-enderman-height.patch diff --git a/patches/todo/server/0092-Stop-squids-floating-on-top-of-water.patch b/patches/unapplied/0092-Stop-squids-floating-on-top-of-water.patch similarity index 100% rename from patches/todo/server/0092-Stop-squids-floating-on-top-of-water.patch rename to patches/unapplied/0092-Stop-squids-floating-on-top-of-water.patch diff --git a/patches/todo/server/0093-Crying-obsidian-valid-for-portal-frames.patch b/patches/unapplied/0093-Crying-obsidian-valid-for-portal-frames.patch similarity index 100% rename from patches/todo/server/0093-Crying-obsidian-valid-for-portal-frames.patch rename to patches/unapplied/0093-Crying-obsidian-valid-for-portal-frames.patch diff --git a/patches/todo/server/0094-Entities-can-use-portals-configuration.patch b/patches/unapplied/0094-Entities-can-use-portals-configuration.patch similarity index 100% rename from patches/todo/server/0094-Entities-can-use-portals-configuration.patch rename to patches/unapplied/0094-Entities-can-use-portals-configuration.patch diff --git a/patches/todo/server/0095-LivingEntity-broadcastItemBreak.patch b/patches/unapplied/0095-LivingEntity-broadcastItemBreak.patch similarity index 100% rename from patches/todo/server/0095-LivingEntity-broadcastItemBreak.patch rename to patches/unapplied/0095-LivingEntity-broadcastItemBreak.patch diff --git a/patches/todo/server/0096-Customizable-wither-health-and-healing.patch b/patches/unapplied/0096-Customizable-wither-health-and-healing.patch similarity index 100% rename from patches/todo/server/0096-Customizable-wither-health-and-healing.patch rename to patches/unapplied/0096-Customizable-wither-health-and-healing.patch diff --git a/patches/todo/server/0097-Allow-toggling-special-MobSpawners-per-world.patch b/patches/unapplied/0097-Allow-toggling-special-MobSpawners-per-world.patch similarity index 100% rename from patches/todo/server/0097-Allow-toggling-special-MobSpawners-per-world.patch rename to patches/unapplied/0097-Allow-toggling-special-MobSpawners-per-world.patch diff --git a/patches/todo/server/0098-Raid-cooldown-setting.patch b/patches/unapplied/0098-Raid-cooldown-setting.patch similarity index 100% rename from patches/todo/server/0098-Raid-cooldown-setting.patch rename to patches/unapplied/0098-Raid-cooldown-setting.patch diff --git a/patches/todo/server/0099-Despawn-rate-config-options-per-projectile-type.patch b/patches/unapplied/0099-Despawn-rate-config-options-per-projectile-type.patch similarity index 100% rename from patches/todo/server/0099-Despawn-rate-config-options-per-projectile-type.patch rename to patches/unapplied/0099-Despawn-rate-config-options-per-projectile-type.patch diff --git a/patches/todo/server/0100-Add-option-to-disable-zombie-aggressiveness-towards-.patch b/patches/unapplied/0100-Add-option-to-disable-zombie-aggressiveness-towards-.patch similarity index 100% rename from patches/todo/server/0100-Add-option-to-disable-zombie-aggressiveness-towards-.patch rename to patches/unapplied/0100-Add-option-to-disable-zombie-aggressiveness-towards-.patch diff --git a/patches/todo/server/0101-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch b/patches/unapplied/0101-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch similarity index 100% rename from patches/todo/server/0101-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch rename to patches/unapplied/0101-Add-predicate-to-recipe-s-ExactChoice-ingredient.patch diff --git a/patches/todo/server/0102-Flying-squids-Oh-my.patch b/patches/unapplied/0102-Flying-squids-Oh-my.patch similarity index 100% rename from patches/todo/server/0102-Flying-squids-Oh-my.patch rename to patches/unapplied/0102-Flying-squids-Oh-my.patch diff --git a/patches/todo/server/0103-Infinity-bow-settings.patch b/patches/unapplied/0103-Infinity-bow-settings.patch similarity index 100% rename from patches/todo/server/0103-Infinity-bow-settings.patch rename to patches/unapplied/0103-Infinity-bow-settings.patch diff --git a/patches/todo/server/0104-Stonecutter-damage.patch b/patches/unapplied/0104-Stonecutter-damage.patch similarity index 100% rename from patches/todo/server/0104-Stonecutter-damage.patch rename to patches/unapplied/0104-Stonecutter-damage.patch diff --git a/patches/todo/server/0105-Configurable-daylight-cycle.patch b/patches/unapplied/0105-Configurable-daylight-cycle.patch similarity index 100% rename from patches/todo/server/0105-Configurable-daylight-cycle.patch rename to patches/unapplied/0105-Configurable-daylight-cycle.patch diff --git a/patches/todo/server/0106-Allow-infinite-and-mending-enchantments-together.patch b/patches/unapplied/0106-Allow-infinite-and-mending-enchantments-together.patch similarity index 100% rename from patches/todo/server/0106-Allow-infinite-and-mending-enchantments-together.patch rename to patches/unapplied/0106-Allow-infinite-and-mending-enchantments-together.patch diff --git a/patches/todo/server/0107-Furnace-uses-lava-from-underneath.patch b/patches/unapplied/0107-Furnace-uses-lava-from-underneath.patch similarity index 100% rename from patches/todo/server/0107-Furnace-uses-lava-from-underneath.patch rename to patches/unapplied/0107-Furnace-uses-lava-from-underneath.patch diff --git a/patches/todo/server/0108-Arrows-should-not-reset-despawn-counter.patch b/patches/unapplied/0108-Arrows-should-not-reset-despawn-counter.patch similarity index 100% rename from patches/todo/server/0108-Arrows-should-not-reset-despawn-counter.patch rename to patches/unapplied/0108-Arrows-should-not-reset-despawn-counter.patch diff --git a/patches/todo/server/0109-Ability-to-re-add-farmland-mechanics-from-Alpha.patch b/patches/unapplied/0109-Ability-to-re-add-farmland-mechanics-from-Alpha.patch similarity index 100% rename from patches/todo/server/0109-Ability-to-re-add-farmland-mechanics-from-Alpha.patch rename to patches/unapplied/0109-Ability-to-re-add-farmland-mechanics-from-Alpha.patch diff --git a/patches/todo/server/0110-Add-adjustable-breeding-cooldown-to-config.patch b/patches/unapplied/0110-Add-adjustable-breeding-cooldown-to-config.patch similarity index 100% rename from patches/todo/server/0110-Add-adjustable-breeding-cooldown-to-config.patch rename to patches/unapplied/0110-Add-adjustable-breeding-cooldown-to-config.patch diff --git a/patches/todo/server/0111-Make-entity-breeding-times-configurable.patch b/patches/unapplied/0111-Make-entity-breeding-times-configurable.patch similarity index 100% rename from patches/todo/server/0111-Make-entity-breeding-times-configurable.patch rename to patches/unapplied/0111-Make-entity-breeding-times-configurable.patch diff --git a/patches/todo/server/0112-Apply-display-names-from-item-forms-of-entities-to-e.patch b/patches/unapplied/0112-Apply-display-names-from-item-forms-of-entities-to-e.patch similarity index 100% rename from patches/todo/server/0112-Apply-display-names-from-item-forms-of-entities-to-e.patch rename to patches/unapplied/0112-Apply-display-names-from-item-forms-of-entities-to-e.patch diff --git a/patches/todo/server/0113-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch b/patches/unapplied/0113-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch similarity index 100% rename from patches/todo/server/0113-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch rename to patches/unapplied/0113-Set-name-visible-when-using-a-Name-Tag-on-an-Armor-S.patch diff --git a/patches/todo/server/0114-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch b/patches/unapplied/0114-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch similarity index 100% rename from patches/todo/server/0114-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch rename to patches/unapplied/0114-Add-config-for-allowing-Endermen-to-despawn-even-whi.patch diff --git a/patches/todo/server/0115-Add-configurable-snowball-damage.patch b/patches/unapplied/0115-Add-configurable-snowball-damage.patch similarity index 100% rename from patches/todo/server/0115-Add-configurable-snowball-damage.patch rename to patches/unapplied/0115-Add-configurable-snowball-damage.patch diff --git a/patches/todo/server/0116-Changeable-Mob-Left-Handed-Chance.patch b/patches/unapplied/0116-Changeable-Mob-Left-Handed-Chance.patch similarity index 100% rename from patches/todo/server/0116-Changeable-Mob-Left-Handed-Chance.patch rename to patches/unapplied/0116-Changeable-Mob-Left-Handed-Chance.patch diff --git a/patches/todo/server/0117-Add-boat-fall-damage-config.patch b/patches/unapplied/0117-Add-boat-fall-damage-config.patch similarity index 100% rename from patches/todo/server/0117-Add-boat-fall-damage-config.patch rename to patches/unapplied/0117-Add-boat-fall-damage-config.patch diff --git a/patches/todo/server/0118-Snow-Golem-rate-of-fire-config.patch b/patches/unapplied/0118-Snow-Golem-rate-of-fire-config.patch similarity index 100% rename from patches/todo/server/0118-Snow-Golem-rate-of-fire-config.patch rename to patches/unapplied/0118-Snow-Golem-rate-of-fire-config.patch diff --git a/patches/todo/server/0119-EMC-Configurable-disable-give-dropping.patch b/patches/unapplied/0119-EMC-Configurable-disable-give-dropping.patch similarity index 100% rename from patches/todo/server/0119-EMC-Configurable-disable-give-dropping.patch rename to patches/unapplied/0119-EMC-Configurable-disable-give-dropping.patch diff --git a/patches/todo/server/0120-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch b/patches/unapplied/0120-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch similarity index 100% rename from patches/todo/server/0120-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch rename to patches/unapplied/0120-Option-for-Villager-Clerics-to-farm-Nether-Wart.patch diff --git a/patches/todo/server/0121-Toggle-for-Zombified-Piglin-death-always-counting-as.patch b/patches/unapplied/0121-Toggle-for-Zombified-Piglin-death-always-counting-as.patch similarity index 100% rename from patches/todo/server/0121-Toggle-for-Zombified-Piglin-death-always-counting-as.patch rename to patches/unapplied/0121-Toggle-for-Zombified-Piglin-death-always-counting-as.patch diff --git a/patches/todo/server/0122-Spread-out-and-optimise-player-list-ticksSpread-out-.patch b/patches/unapplied/0122-Spread-out-and-optimise-player-list-ticksSpread-out-.patch similarity index 100% rename from patches/todo/server/0122-Spread-out-and-optimise-player-list-ticksSpread-out-.patch rename to patches/unapplied/0122-Spread-out-and-optimise-player-list-ticksSpread-out-.patch diff --git a/patches/todo/server/0123-Configurable-chance-for-wolves-to-spawn-rabid.patch b/patches/unapplied/0123-Configurable-chance-for-wolves-to-spawn-rabid.patch similarity index 100% rename from patches/todo/server/0123-Configurable-chance-for-wolves-to-spawn-rabid.patch rename to patches/unapplied/0123-Configurable-chance-for-wolves-to-spawn-rabid.patch diff --git a/patches/todo/server/0124-Configurable-default-collar-color.patch b/patches/unapplied/0124-Configurable-default-collar-color.patch similarity index 100% rename from patches/todo/server/0124-Configurable-default-collar-color.patch rename to patches/unapplied/0124-Configurable-default-collar-color.patch diff --git a/patches/todo/server/0125-Phantom-flames-on-swoop.patch b/patches/unapplied/0125-Phantom-flames-on-swoop.patch similarity index 100% rename from patches/todo/server/0125-Phantom-flames-on-swoop.patch rename to patches/unapplied/0125-Phantom-flames-on-swoop.patch diff --git a/patches/todo/server/0126-Option-for-chests-to-open-even-with-a-solid-block-on.patch b/patches/unapplied/0126-Option-for-chests-to-open-even-with-a-solid-block-on.patch similarity index 100% rename from patches/todo/server/0126-Option-for-chests-to-open-even-with-a-solid-block-on.patch rename to patches/unapplied/0126-Option-for-chests-to-open-even-with-a-solid-block-on.patch diff --git a/patches/todo/server/0127-Implement-TPSBar.patch b/patches/unapplied/0127-Implement-TPSBar.patch similarity index 100% rename from patches/todo/server/0127-Implement-TPSBar.patch rename to patches/unapplied/0127-Implement-TPSBar.patch diff --git a/patches/todo/server/0128-Striders-give-saddle-back.patch b/patches/unapplied/0128-Striders-give-saddle-back.patch similarity index 100% rename from patches/todo/server/0128-Striders-give-saddle-back.patch rename to patches/unapplied/0128-Striders-give-saddle-back.patch diff --git a/patches/todo/server/0129-PlayerBookTooLargeEvent.patch b/patches/unapplied/0129-PlayerBookTooLargeEvent.patch similarity index 100% rename from patches/todo/server/0129-PlayerBookTooLargeEvent.patch rename to patches/unapplied/0129-PlayerBookTooLargeEvent.patch diff --git a/patches/todo/server/0130-Full-netherite-armor-grants-fire-resistance.patch b/patches/unapplied/0130-Full-netherite-armor-grants-fire-resistance.patch similarity index 100% rename from patches/todo/server/0130-Full-netherite-armor-grants-fire-resistance.patch rename to patches/unapplied/0130-Full-netherite-armor-grants-fire-resistance.patch diff --git a/patches/todo/server/0131-Fix-rotating-UP-DOWN-CW-and-CCW.patch b/patches/unapplied/0131-Fix-rotating-UP-DOWN-CW-and-CCW.patch similarity index 100% rename from patches/todo/server/0131-Fix-rotating-UP-DOWN-CW-and-CCW.patch rename to patches/unapplied/0131-Fix-rotating-UP-DOWN-CW-and-CCW.patch diff --git a/patches/todo/server/0132-Add-mobGriefing-bypass-to-everything-affected.patch b/patches/unapplied/0132-Add-mobGriefing-bypass-to-everything-affected.patch similarity index 100% rename from patches/todo/server/0132-Add-mobGriefing-bypass-to-everything-affected.patch rename to patches/unapplied/0132-Add-mobGriefing-bypass-to-everything-affected.patch diff --git a/patches/todo/server/0133-Config-to-allow-Note-Block-sounds-when-blocked.patch b/patches/unapplied/0133-Config-to-allow-Note-Block-sounds-when-blocked.patch similarity index 100% rename from patches/todo/server/0133-Config-to-allow-Note-Block-sounds-when-blocked.patch rename to patches/unapplied/0133-Config-to-allow-Note-Block-sounds-when-blocked.patch diff --git a/patches/todo/server/0134-Add-EntityTeleportHinderedEvent.patch b/patches/unapplied/0134-Add-EntityTeleportHinderedEvent.patch similarity index 100% rename from patches/todo/server/0134-Add-EntityTeleportHinderedEvent.patch rename to patches/unapplied/0134-Add-EntityTeleportHinderedEvent.patch diff --git a/patches/todo/server/0135-Farmland-trampling-changes.patch b/patches/unapplied/0135-Farmland-trampling-changes.patch similarity index 100% rename from patches/todo/server/0135-Farmland-trampling-changes.patch rename to patches/unapplied/0135-Farmland-trampling-changes.patch diff --git a/patches/todo/server/0136-Movement-options-for-armor-stands.patch b/patches/unapplied/0136-Movement-options-for-armor-stands.patch similarity index 100% rename from patches/todo/server/0136-Movement-options-for-armor-stands.patch rename to patches/unapplied/0136-Movement-options-for-armor-stands.patch diff --git a/patches/todo/server/0137-Fix-stuck-in-portals.patch b/patches/unapplied/0137-Fix-stuck-in-portals.patch similarity index 100% rename from patches/todo/server/0137-Fix-stuck-in-portals.patch rename to patches/unapplied/0137-Fix-stuck-in-portals.patch diff --git a/patches/todo/server/0138-Toggle-for-water-sensitive-mob-damage.patch b/patches/unapplied/0138-Toggle-for-water-sensitive-mob-damage.patch similarity index 100% rename from patches/todo/server/0138-Toggle-for-water-sensitive-mob-damage.patch rename to patches/unapplied/0138-Toggle-for-water-sensitive-mob-damage.patch diff --git a/patches/todo/server/0139-Config-to-always-tame-in-Creative.patch b/patches/unapplied/0139-Config-to-always-tame-in-Creative.patch similarity index 100% rename from patches/todo/server/0139-Config-to-always-tame-in-Creative.patch rename to patches/unapplied/0139-Config-to-always-tame-in-Creative.patch diff --git a/patches/todo/server/0140-End-crystal-explosion-options.patch b/patches/unapplied/0140-End-crystal-explosion-options.patch similarity index 100% rename from patches/todo/server/0140-End-crystal-explosion-options.patch rename to patches/unapplied/0140-End-crystal-explosion-options.patch diff --git a/patches/todo/server/0141-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch b/patches/unapplied/0141-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch similarity index 100% rename from patches/todo/server/0141-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch rename to patches/unapplied/0141-Configs-for-if-Wither-Ender-Dragon-can-ride-vehicles.patch diff --git a/patches/todo/server/0142-Dont-run-with-scissors.patch b/patches/unapplied/0142-Dont-run-with-scissors.patch similarity index 100% rename from patches/todo/server/0142-Dont-run-with-scissors.patch rename to patches/unapplied/0142-Dont-run-with-scissors.patch diff --git a/patches/todo/server/0143-One-Punch-Man.patch b/patches/unapplied/0143-One-Punch-Man.patch similarity index 100% rename from patches/todo/server/0143-One-Punch-Man.patch rename to patches/unapplied/0143-One-Punch-Man.patch diff --git a/patches/todo/server/0144-Add-config-for-snow-on-blue-ice.patch b/patches/unapplied/0144-Add-config-for-snow-on-blue-ice.patch similarity index 100% rename from patches/todo/server/0144-Add-config-for-snow-on-blue-ice.patch rename to patches/unapplied/0144-Add-config-for-snow-on-blue-ice.patch diff --git a/patches/todo/server/0145-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch b/patches/unapplied/0145-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch similarity index 100% rename from patches/todo/server/0145-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch rename to patches/unapplied/0145-Configurable-Ender-Pearl-cooldown-damage-and-Endermi.patch diff --git a/patches/todo/server/0146-Config-to-ignore-nearby-mobs-when-sleeping.patch b/patches/unapplied/0146-Config-to-ignore-nearby-mobs-when-sleeping.patch similarity index 100% rename from patches/todo/server/0146-Config-to-ignore-nearby-mobs-when-sleeping.patch rename to patches/unapplied/0146-Config-to-ignore-nearby-mobs-when-sleeping.patch diff --git a/patches/todo/server/0147-Add-back-player-spawned-endermite-API.patch b/patches/unapplied/0147-Add-back-player-spawned-endermite-API.patch similarity index 100% rename from patches/todo/server/0147-Add-back-player-spawned-endermite-API.patch rename to patches/unapplied/0147-Add-back-player-spawned-endermite-API.patch diff --git a/patches/todo/server/0148-Config-Enderman-aggressiveness-towards-Endermites.patch b/patches/unapplied/0148-Config-Enderman-aggressiveness-towards-Endermites.patch similarity index 100% rename from patches/todo/server/0148-Config-Enderman-aggressiveness-towards-Endermites.patch rename to patches/unapplied/0148-Config-Enderman-aggressiveness-towards-Endermites.patch diff --git a/patches/todo/server/0149-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch b/patches/unapplied/0149-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch similarity index 100% rename from patches/todo/server/0149-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch rename to patches/unapplied/0149-Config-to-ignore-Dragon-Head-wearers-and-stare-aggro.patch diff --git a/patches/todo/server/0150-Tick-fluids-config.patch b/patches/unapplied/0150-Tick-fluids-config.patch similarity index 100% rename from patches/todo/server/0150-Tick-fluids-config.patch rename to patches/unapplied/0150-Tick-fluids-config.patch diff --git a/patches/todo/server/0151-Config-to-disable-Llama-caravans.patch b/patches/unapplied/0151-Config-to-disable-Llama-caravans.patch similarity index 100% rename from patches/todo/server/0151-Config-to-disable-Llama-caravans.patch rename to patches/unapplied/0151-Config-to-disable-Llama-caravans.patch diff --git a/patches/todo/server/0152-Config-to-make-Creepers-explode-on-death.patch b/patches/unapplied/0152-Config-to-make-Creepers-explode-on-death.patch similarity index 100% rename from patches/todo/server/0152-Config-to-make-Creepers-explode-on-death.patch rename to patches/unapplied/0152-Config-to-make-Creepers-explode-on-death.patch diff --git a/patches/todo/server/0153-Configurable-ravager-griefable-blocks-list.patch b/patches/unapplied/0153-Configurable-ravager-griefable-blocks-list.patch similarity index 100% rename from patches/todo/server/0153-Configurable-ravager-griefable-blocks-list.patch rename to patches/unapplied/0153-Configurable-ravager-griefable-blocks-list.patch diff --git a/patches/todo/server/0154-Sneak-to-bulk-process-composter.patch b/patches/unapplied/0154-Sneak-to-bulk-process-composter.patch similarity index 100% rename from patches/todo/server/0154-Sneak-to-bulk-process-composter.patch rename to patches/unapplied/0154-Sneak-to-bulk-process-composter.patch diff --git a/patches/todo/server/0155-Config-for-skipping-night.patch b/patches/unapplied/0155-Config-for-skipping-night.patch similarity index 100% rename from patches/todo/server/0155-Config-for-skipping-night.patch rename to patches/unapplied/0155-Config-for-skipping-night.patch diff --git a/patches/todo/server/0156-Add-config-for-villager-trading.patch b/patches/unapplied/0156-Add-config-for-villager-trading.patch similarity index 100% rename from patches/todo/server/0156-Add-config-for-villager-trading.patch rename to patches/unapplied/0156-Add-config-for-villager-trading.patch diff --git a/patches/todo/server/0157-Allow-infinity-on-crossbows.patch b/patches/unapplied/0157-Allow-infinity-on-crossbows.patch similarity index 100% rename from patches/todo/server/0157-Allow-infinity-on-crossbows.patch rename to patches/unapplied/0157-Allow-infinity-on-crossbows.patch diff --git a/patches/todo/server/0158-Drowning-Settings.patch b/patches/unapplied/0158-Drowning-Settings.patch similarity index 100% rename from patches/todo/server/0158-Drowning-Settings.patch rename to patches/unapplied/0158-Drowning-Settings.patch diff --git a/patches/todo/server/0159-Break-individual-slabs-when-sneaking.patch b/patches/unapplied/0159-Break-individual-slabs-when-sneaking.patch similarity index 100% rename from patches/todo/server/0159-Break-individual-slabs-when-sneaking.patch rename to patches/unapplied/0159-Break-individual-slabs-when-sneaking.patch diff --git a/patches/todo/server/0160-Config-to-disable-hostile-mob-spawn-on-ice.patch b/patches/unapplied/0160-Config-to-disable-hostile-mob-spawn-on-ice.patch similarity index 100% rename from patches/todo/server/0160-Config-to-disable-hostile-mob-spawn-on-ice.patch rename to patches/unapplied/0160-Config-to-disable-hostile-mob-spawn-on-ice.patch diff --git a/patches/todo/server/0161-Config-to-show-Armor-Stand-arms-on-spawn.patch b/patches/unapplied/0161-Config-to-show-Armor-Stand-arms-on-spawn.patch similarity index 100% rename from patches/todo/server/0161-Config-to-show-Armor-Stand-arms-on-spawn.patch rename to patches/unapplied/0161-Config-to-show-Armor-Stand-arms-on-spawn.patch diff --git a/patches/todo/server/0162-Option-to-make-doors-require-redstone.patch b/patches/unapplied/0162-Option-to-make-doors-require-redstone.patch similarity index 100% rename from patches/todo/server/0162-Option-to-make-doors-require-redstone.patch rename to patches/unapplied/0162-Option-to-make-doors-require-redstone.patch diff --git a/patches/todo/server/0163-Config-to-allow-for-unsafe-enchants.patch b/patches/unapplied/0163-Config-to-allow-for-unsafe-enchants.patch similarity index 100% rename from patches/todo/server/0163-Config-to-allow-for-unsafe-enchants.patch rename to patches/unapplied/0163-Config-to-allow-for-unsafe-enchants.patch diff --git a/patches/todo/server/0164-Configurable-sponge-absorption.patch b/patches/unapplied/0164-Configurable-sponge-absorption.patch similarity index 100% rename from patches/todo/server/0164-Configurable-sponge-absorption.patch rename to patches/unapplied/0164-Configurable-sponge-absorption.patch diff --git a/patches/todo/server/0165-Projectile-offset-config.patch b/patches/unapplied/0165-Projectile-offset-config.patch similarity index 100% rename from patches/todo/server/0165-Projectile-offset-config.patch rename to patches/unapplied/0165-Projectile-offset-config.patch diff --git a/patches/todo/server/0166-Config-for-powered-rail-activation-distance.patch b/patches/unapplied/0166-Config-for-powered-rail-activation-distance.patch similarity index 100% rename from patches/todo/server/0166-Config-for-powered-rail-activation-distance.patch rename to patches/unapplied/0166-Config-for-powered-rail-activation-distance.patch diff --git a/patches/todo/server/0167-Piglin-portal-spawn-modifier.patch b/patches/unapplied/0167-Piglin-portal-spawn-modifier.patch similarity index 100% rename from patches/todo/server/0167-Piglin-portal-spawn-modifier.patch rename to patches/unapplied/0167-Piglin-portal-spawn-modifier.patch diff --git a/patches/todo/server/0168-Config-to-change-max-number-of-bees.patch b/patches/unapplied/0168-Config-to-change-max-number-of-bees.patch similarity index 100% rename from patches/todo/server/0168-Config-to-change-max-number-of-bees.patch rename to patches/unapplied/0168-Config-to-change-max-number-of-bees.patch diff --git a/patches/todo/server/0169-Configurable-damage-settings-for-magma-blocks.patch b/patches/unapplied/0169-Configurable-damage-settings-for-magma-blocks.patch similarity index 100% rename from patches/todo/server/0169-Configurable-damage-settings-for-magma-blocks.patch rename to patches/unapplied/0169-Configurable-damage-settings-for-magma-blocks.patch diff --git a/patches/todo/server/0170-Config-for-wither-explosion-radius.patch b/patches/unapplied/0170-Config-for-wither-explosion-radius.patch similarity index 100% rename from patches/todo/server/0170-Config-for-wither-explosion-radius.patch rename to patches/unapplied/0170-Config-for-wither-explosion-radius.patch diff --git a/patches/todo/server/0171-Gamemode-extra-permissions.patch b/patches/unapplied/0171-Gamemode-extra-permissions.patch similarity index 100% rename from patches/todo/server/0171-Gamemode-extra-permissions.patch rename to patches/unapplied/0171-Gamemode-extra-permissions.patch diff --git a/patches/todo/server/0172-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch b/patches/unapplied/0172-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch similarity index 100% rename from patches/todo/server/0172-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch rename to patches/unapplied/0172-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch diff --git a/patches/todo/server/0173-Configurable-piston-push-limit.patch b/patches/unapplied/0173-Configurable-piston-push-limit.patch similarity index 100% rename from patches/todo/server/0173-Configurable-piston-push-limit.patch rename to patches/unapplied/0173-Configurable-piston-push-limit.patch diff --git a/patches/todo/server/0174-Configurable-broadcast-settings.patch b/patches/unapplied/0174-Configurable-broadcast-settings.patch similarity index 100% rename from patches/todo/server/0174-Configurable-broadcast-settings.patch rename to patches/unapplied/0174-Configurable-broadcast-settings.patch diff --git a/patches/todo/server/0175-Configurable-mob-blindness.patch b/patches/unapplied/0175-Configurable-mob-blindness.patch similarity index 100% rename from patches/todo/server/0175-Configurable-mob-blindness.patch rename to patches/unapplied/0175-Configurable-mob-blindness.patch diff --git a/patches/todo/server/0176-Hide-hidden-players-from-entity-selector.patch b/patches/unapplied/0176-Hide-hidden-players-from-entity-selector.patch similarity index 100% rename from patches/todo/server/0176-Hide-hidden-players-from-entity-selector.patch rename to patches/unapplied/0176-Hide-hidden-players-from-entity-selector.patch diff --git a/patches/todo/server/0177-Config-for-health-to-impact-Creeper-explosion-radius.patch b/patches/unapplied/0177-Config-for-health-to-impact-Creeper-explosion-radius.patch similarity index 100% rename from patches/todo/server/0177-Config-for-health-to-impact-Creeper-explosion-radius.patch rename to patches/unapplied/0177-Config-for-health-to-impact-Creeper-explosion-radius.patch diff --git a/patches/todo/server/0178-Iron-golem-calm-anger-options.patch b/patches/unapplied/0178-Iron-golem-calm-anger-options.patch similarity index 100% rename from patches/todo/server/0178-Iron-golem-calm-anger-options.patch rename to patches/unapplied/0178-Iron-golem-calm-anger-options.patch diff --git a/patches/todo/server/0179-Breedable-parrots.patch b/patches/unapplied/0179-Breedable-parrots.patch similarity index 100% rename from patches/todo/server/0179-Breedable-parrots.patch rename to patches/unapplied/0179-Breedable-parrots.patch diff --git a/patches/todo/server/0180-Configurable-powered-rail-boost-modifier.patch b/patches/unapplied/0180-Configurable-powered-rail-boost-modifier.patch similarity index 100% rename from patches/todo/server/0180-Configurable-powered-rail-boost-modifier.patch rename to patches/unapplied/0180-Configurable-powered-rail-boost-modifier.patch diff --git a/patches/todo/server/0181-Add-config-change-multiplier-critical-damage-value.patch b/patches/unapplied/0181-Add-config-change-multiplier-critical-damage-value.patch similarity index 100% rename from patches/todo/server/0181-Add-config-change-multiplier-critical-damage-value.patch rename to patches/unapplied/0181-Add-config-change-multiplier-critical-damage-value.patch diff --git a/patches/todo/server/0182-Option-to-disable-dragon-egg-teleporting.patch b/patches/unapplied/0182-Option-to-disable-dragon-egg-teleporting.patch similarity index 100% rename from patches/todo/server/0182-Option-to-disable-dragon-egg-teleporting.patch rename to patches/unapplied/0182-Option-to-disable-dragon-egg-teleporting.patch diff --git a/patches/todo/server/0183-Config-for-unverified-username-message.patch b/patches/unapplied/0183-Config-for-unverified-username-message.patch similarity index 100% rename from patches/todo/server/0183-Config-for-unverified-username-message.patch rename to patches/unapplied/0183-Config-for-unverified-username-message.patch diff --git a/patches/todo/server/0184-Make-anvil-cumulative-cost-configurable.patch b/patches/unapplied/0184-Make-anvil-cumulative-cost-configurable.patch similarity index 100% rename from patches/todo/server/0184-Make-anvil-cumulative-cost-configurable.patch rename to patches/unapplied/0184-Make-anvil-cumulative-cost-configurable.patch diff --git a/patches/todo/server/0185-ShulkerBox-allow-oversized-stacks.patch b/patches/unapplied/0185-ShulkerBox-allow-oversized-stacks.patch similarity index 100% rename from patches/todo/server/0185-ShulkerBox-allow-oversized-stacks.patch rename to patches/unapplied/0185-ShulkerBox-allow-oversized-stacks.patch diff --git a/patches/todo/server/0186-Bee-can-work-when-raining-or-at-night.patch b/patches/unapplied/0186-Bee-can-work-when-raining-or-at-night.patch similarity index 100% rename from patches/todo/server/0186-Bee-can-work-when-raining-or-at-night.patch rename to patches/unapplied/0186-Bee-can-work-when-raining-or-at-night.patch diff --git a/patches/todo/server/0187-API-for-any-mob-to-burn-daylight.patch b/patches/unapplied/0187-API-for-any-mob-to-burn-daylight.patch similarity index 100% rename from patches/todo/server/0187-API-for-any-mob-to-burn-daylight.patch rename to patches/unapplied/0187-API-for-any-mob-to-burn-daylight.patch diff --git a/patches/todo/server/0188-Config-MobEffect-by-world.patch b/patches/unapplied/0188-Config-MobEffect-by-world.patch similarity index 100% rename from patches/todo/server/0188-Config-MobEffect-by-world.patch rename to patches/unapplied/0188-Config-MobEffect-by-world.patch diff --git a/patches/todo/server/0189-Beacon-Activation-Range-Configurable.patch b/patches/unapplied/0189-Beacon-Activation-Range-Configurable.patch similarity index 100% rename from patches/todo/server/0189-Beacon-Activation-Range-Configurable.patch rename to patches/unapplied/0189-Beacon-Activation-Range-Configurable.patch diff --git a/patches/todo/server/0190-Add-toggle-for-sand-duping-fix.patch b/patches/unapplied/0190-Add-toggle-for-sand-duping-fix.patch similarity index 100% rename from patches/todo/server/0190-Add-toggle-for-sand-duping-fix.patch rename to patches/unapplied/0190-Add-toggle-for-sand-duping-fix.patch diff --git a/patches/todo/server/0191-Add-toggle-for-end-portal-safe-teleporting.patch b/patches/unapplied/0191-Add-toggle-for-end-portal-safe-teleporting.patch similarity index 100% rename from patches/todo/server/0191-Add-toggle-for-end-portal-safe-teleporting.patch rename to patches/unapplied/0191-Add-toggle-for-end-portal-safe-teleporting.patch diff --git a/patches/todo/server/0192-Flying-Fall-Damage-API.patch b/patches/unapplied/0192-Flying-Fall-Damage-API.patch similarity index 100% rename from patches/todo/server/0192-Flying-Fall-Damage-API.patch rename to patches/unapplied/0192-Flying-Fall-Damage-API.patch diff --git a/patches/todo/server/0193-Make-lightning-rod-range-configurable.patch b/patches/unapplied/0193-Make-lightning-rod-range-configurable.patch similarity index 100% rename from patches/todo/server/0193-Make-lightning-rod-range-configurable.patch rename to patches/unapplied/0193-Make-lightning-rod-range-configurable.patch diff --git a/patches/todo/server/0194-Burp-after-eating-food-fills-hunger-bar-completely.patch b/patches/unapplied/0194-Burp-after-eating-food-fills-hunger-bar-completely.patch similarity index 100% rename from patches/todo/server/0194-Burp-after-eating-food-fills-hunger-bar-completely.patch rename to patches/unapplied/0194-Burp-after-eating-food-fills-hunger-bar-completely.patch diff --git a/patches/todo/server/0195-Allow-player-join-full-server-by-permission.patch b/patches/unapplied/0195-Allow-player-join-full-server-by-permission.patch similarity index 100% rename from patches/todo/server/0195-Allow-player-join-full-server-by-permission.patch rename to patches/unapplied/0195-Allow-player-join-full-server-by-permission.patch diff --git a/patches/todo/server/0196-Add-permission-bypass-for-portal-waiting.patch b/patches/unapplied/0196-Add-permission-bypass-for-portal-waiting.patch similarity index 100% rename from patches/todo/server/0196-Add-permission-bypass-for-portal-waiting.patch rename to patches/unapplied/0196-Add-permission-bypass-for-portal-waiting.patch diff --git a/patches/todo/server/0197-Shulker-spawn-from-bullet-options.patch b/patches/unapplied/0197-Shulker-spawn-from-bullet-options.patch similarity index 100% rename from patches/todo/server/0197-Shulker-spawn-from-bullet-options.patch rename to patches/unapplied/0197-Shulker-spawn-from-bullet-options.patch diff --git a/patches/todo/server/0198-Eating-glow-berries-adds-glow-effect.patch b/patches/unapplied/0198-Eating-glow-berries-adds-glow-effect.patch similarity index 100% rename from patches/todo/server/0198-Eating-glow-berries-adds-glow-effect.patch rename to patches/unapplied/0198-Eating-glow-berries-adds-glow-effect.patch diff --git a/patches/todo/server/0199-Option-to-make-drowned-break-doors.patch b/patches/unapplied/0199-Option-to-make-drowned-break-doors.patch similarity index 100% rename from patches/todo/server/0199-Option-to-make-drowned-break-doors.patch rename to patches/unapplied/0199-Option-to-make-drowned-break-doors.patch diff --git a/patches/todo/server/0200-Configurable-hunger-starvation-damage.patch b/patches/unapplied/0200-Configurable-hunger-starvation-damage.patch similarity index 100% rename from patches/todo/server/0200-Configurable-hunger-starvation-damage.patch rename to patches/unapplied/0200-Configurable-hunger-starvation-damage.patch diff --git a/patches/todo/server/0201-Enhance-SysoutCatcher.patch b/patches/unapplied/0201-Enhance-SysoutCatcher.patch similarity index 100% rename from patches/todo/server/0201-Enhance-SysoutCatcher.patch rename to patches/unapplied/0201-Enhance-SysoutCatcher.patch diff --git a/patches/todo/server/0202-Armor-click-equip-options.patch b/patches/unapplied/0202-Armor-click-equip-options.patch similarity index 100% rename from patches/todo/server/0202-Armor-click-equip-options.patch rename to patches/unapplied/0202-Armor-click-equip-options.patch diff --git a/patches/todo/server/0203-Add-uptime-command.patch b/patches/unapplied/0203-Add-uptime-command.patch similarity index 100% rename from patches/todo/server/0203-Add-uptime-command.patch rename to patches/unapplied/0203-Add-uptime-command.patch diff --git a/patches/todo/server/0204-Structure-seed-options.patch b/patches/unapplied/0204-Structure-seed-options.patch similarity index 100% rename from patches/todo/server/0204-Structure-seed-options.patch rename to patches/unapplied/0204-Structure-seed-options.patch diff --git a/patches/todo/server/0205-Tool-actionable-options.patch b/patches/unapplied/0205-Tool-actionable-options.patch similarity index 100% rename from patches/todo/server/0205-Tool-actionable-options.patch rename to patches/unapplied/0205-Tool-actionable-options.patch diff --git a/patches/todo/server/0206-Store-placer-on-Block-when-placed.patch b/patches/unapplied/0206-Store-placer-on-Block-when-placed.patch similarity index 100% rename from patches/todo/server/0206-Store-placer-on-Block-when-placed.patch rename to patches/unapplied/0206-Store-placer-on-Block-when-placed.patch diff --git a/patches/todo/server/0207-Summoner-API.patch b/patches/unapplied/0207-Summoner-API.patch similarity index 100% rename from patches/todo/server/0207-Summoner-API.patch rename to patches/unapplied/0207-Summoner-API.patch diff --git a/patches/todo/server/0208-Customizable-sleeping-actionbar-messages.patch b/patches/unapplied/0208-Customizable-sleeping-actionbar-messages.patch similarity index 100% rename from patches/todo/server/0208-Customizable-sleeping-actionbar-messages.patch rename to patches/unapplied/0208-Customizable-sleeping-actionbar-messages.patch diff --git a/patches/todo/server/0209-option-to-disable-shulker-box-items-from-dropping-co.patch b/patches/unapplied/0209-option-to-disable-shulker-box-items-from-dropping-co.patch similarity index 100% rename from patches/todo/server/0209-option-to-disable-shulker-box-items-from-dropping-co.patch rename to patches/unapplied/0209-option-to-disable-shulker-box-items-from-dropping-co.patch diff --git a/patches/todo/server/0210-Silk-touchable-budding-amethyst.patch b/patches/unapplied/0210-Silk-touchable-budding-amethyst.patch similarity index 100% rename from patches/todo/server/0210-Silk-touchable-budding-amethyst.patch rename to patches/unapplied/0210-Silk-touchable-budding-amethyst.patch diff --git a/patches/todo/server/0211-Big-dripleaf-tilt-delay.patch b/patches/unapplied/0211-Big-dripleaf-tilt-delay.patch similarity index 100% rename from patches/todo/server/0211-Big-dripleaf-tilt-delay.patch rename to patches/unapplied/0211-Big-dripleaf-tilt-delay.patch diff --git a/patches/todo/server/0212-Player-ridable-in-water-option.patch b/patches/unapplied/0212-Player-ridable-in-water-option.patch similarity index 100% rename from patches/todo/server/0212-Player-ridable-in-water-option.patch rename to patches/unapplied/0212-Player-ridable-in-water-option.patch diff --git a/patches/todo/server/0213-Config-to-disable-Enderman-teleport-on-projectile-hi.patch b/patches/unapplied/0213-Config-to-disable-Enderman-teleport-on-projectile-hi.patch similarity index 100% rename from patches/todo/server/0213-Config-to-disable-Enderman-teleport-on-projectile-hi.patch rename to patches/unapplied/0213-Config-to-disable-Enderman-teleport-on-projectile-hi.patch diff --git a/patches/todo/server/0214-Add-compass-command.patch b/patches/unapplied/0214-Add-compass-command.patch similarity index 100% rename from patches/todo/server/0214-Add-compass-command.patch rename to patches/unapplied/0214-Add-compass-command.patch diff --git a/patches/todo/server/0215-Config-to-prevent-horses-from-standing-with-riders.patch b/patches/unapplied/0215-Config-to-prevent-horses-from-standing-with-riders.patch similarity index 100% rename from patches/todo/server/0215-Config-to-prevent-horses-from-standing-with-riders.patch rename to patches/unapplied/0215-Config-to-prevent-horses-from-standing-with-riders.patch diff --git a/patches/todo/server/0216-Toggle-for-kinetic-damage.patch b/patches/unapplied/0216-Toggle-for-kinetic-damage.patch similarity index 100% rename from patches/todo/server/0216-Toggle-for-kinetic-damage.patch rename to patches/unapplied/0216-Toggle-for-kinetic-damage.patch diff --git a/patches/todo/server/0217-Add-Option-for-disable-observer-clocks.patch b/patches/unapplied/0217-Add-Option-for-disable-observer-clocks.patch similarity index 100% rename from patches/todo/server/0217-Add-Option-for-disable-observer-clocks.patch rename to patches/unapplied/0217-Add-Option-for-disable-observer-clocks.patch diff --git a/patches/todo/server/0218-Customizeable-Zombie-Villager-curing-times.patch b/patches/unapplied/0218-Customizeable-Zombie-Villager-curing-times.patch similarity index 100% rename from patches/todo/server/0218-Customizeable-Zombie-Villager-curing-times.patch rename to patches/unapplied/0218-Customizeable-Zombie-Villager-curing-times.patch diff --git a/patches/todo/server/0219-Option-for-sponges-to-work-on-lava.patch b/patches/unapplied/0219-Option-for-sponges-to-work-on-lava.patch similarity index 100% rename from patches/todo/server/0219-Option-for-sponges-to-work-on-lava.patch rename to patches/unapplied/0219-Option-for-sponges-to-work-on-lava.patch diff --git a/patches/todo/server/0220-Toggle-for-Wither-s-spawn-sound.patch b/patches/unapplied/0220-Toggle-for-Wither-s-spawn-sound.patch similarity index 100% rename from patches/todo/server/0220-Toggle-for-Wither-s-spawn-sound.patch rename to patches/unapplied/0220-Toggle-for-Wither-s-spawn-sound.patch diff --git a/patches/todo/server/0221-Cactus-breaks-from-solid-neighbors-config.patch b/patches/unapplied/0221-Cactus-breaks-from-solid-neighbors-config.patch similarity index 100% rename from patches/todo/server/0221-Cactus-breaks-from-solid-neighbors-config.patch rename to patches/unapplied/0221-Cactus-breaks-from-solid-neighbors-config.patch diff --git a/patches/todo/server/0222-Config-to-remove-curse-of-binding-with-weakness.patch b/patches/unapplied/0222-Config-to-remove-curse-of-binding-with-weakness.patch similarity index 100% rename from patches/todo/server/0222-Config-to-remove-curse-of-binding-with-weakness.patch rename to patches/unapplied/0222-Config-to-remove-curse-of-binding-with-weakness.patch diff --git a/patches/todo/server/0223-Conduit-behavior-configuration.patch b/patches/unapplied/0223-Conduit-behavior-configuration.patch similarity index 100% rename from patches/todo/server/0223-Conduit-behavior-configuration.patch rename to patches/unapplied/0223-Conduit-behavior-configuration.patch diff --git a/patches/todo/server/0224-Cauldron-fill-chances.patch b/patches/unapplied/0224-Cauldron-fill-chances.patch similarity index 100% rename from patches/todo/server/0224-Cauldron-fill-chances.patch rename to patches/unapplied/0224-Cauldron-fill-chances.patch diff --git a/patches/todo/server/0225-Config-to-allow-mobs-to-pathfind-over-rails.patch b/patches/unapplied/0225-Config-to-allow-mobs-to-pathfind-over-rails.patch similarity index 100% rename from patches/todo/server/0225-Config-to-allow-mobs-to-pathfind-over-rails.patch rename to patches/unapplied/0225-Config-to-allow-mobs-to-pathfind-over-rails.patch diff --git a/patches/todo/server/0226-Shulker-change-color-with-dye.patch b/patches/unapplied/0226-Shulker-change-color-with-dye.patch similarity index 100% rename from patches/todo/server/0226-Shulker-change-color-with-dye.patch rename to patches/unapplied/0226-Shulker-change-color-with-dye.patch diff --git a/patches/todo/server/0227-Extended-OfflinePlayer-API.patch b/patches/unapplied/0227-Extended-OfflinePlayer-API.patch similarity index 100% rename from patches/todo/server/0227-Extended-OfflinePlayer-API.patch rename to patches/unapplied/0227-Extended-OfflinePlayer-API.patch diff --git a/patches/todo/server/0228-Added-the-ability-to-add-combustible-items.patch b/patches/unapplied/0228-Added-the-ability-to-add-combustible-items.patch similarity index 100% rename from patches/todo/server/0228-Added-the-ability-to-add-combustible-items.patch rename to patches/unapplied/0228-Added-the-ability-to-add-combustible-items.patch diff --git a/patches/todo/server/0229-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch b/patches/unapplied/0229-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch similarity index 100% rename from patches/todo/server/0229-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch rename to patches/unapplied/0229-Option-for-if-rain-and-thunder-should-stop-on-sleep.patch diff --git a/patches/todo/server/0230-Chance-for-azalea-blocks-to-grow-into-trees-naturall.patch b/patches/unapplied/0230-Chance-for-azalea-blocks-to-grow-into-trees-naturall.patch similarity index 100% rename from patches/todo/server/0230-Chance-for-azalea-blocks-to-grow-into-trees-naturall.patch rename to patches/unapplied/0230-Chance-for-azalea-blocks-to-grow-into-trees-naturall.patch diff --git a/patches/todo/server/0231-Shift-right-click-to-use-exp-for-mending.patch b/patches/unapplied/0231-Shift-right-click-to-use-exp-for-mending.patch similarity index 100% rename from patches/todo/server/0231-Shift-right-click-to-use-exp-for-mending.patch rename to patches/unapplied/0231-Shift-right-click-to-use-exp-for-mending.patch diff --git a/patches/todo/server/0232-Dolphins-naturally-aggressive-to-players-chance.patch b/patches/unapplied/0232-Dolphins-naturally-aggressive-to-players-chance.patch similarity index 100% rename from patches/todo/server/0232-Dolphins-naturally-aggressive-to-players-chance.patch rename to patches/unapplied/0232-Dolphins-naturally-aggressive-to-players-chance.patch diff --git a/patches/todo/server/0233-Cows-naturally-aggressive-to-players-chance.patch b/patches/unapplied/0233-Cows-naturally-aggressive-to-players-chance.patch similarity index 100% rename from patches/todo/server/0233-Cows-naturally-aggressive-to-players-chance.patch rename to patches/unapplied/0233-Cows-naturally-aggressive-to-players-chance.patch diff --git a/patches/todo/server/0234-Option-for-beds-to-explode-on-villager-sleep.patch b/patches/unapplied/0234-Option-for-beds-to-explode-on-villager-sleep.patch similarity index 100% rename from patches/todo/server/0234-Option-for-beds-to-explode-on-villager-sleep.patch rename to patches/unapplied/0234-Option-for-beds-to-explode-on-villager-sleep.patch diff --git a/patches/todo/server/0235-Halloween-options-and-optimizations.patch b/patches/unapplied/0235-Halloween-options-and-optimizations.patch similarity index 100% rename from patches/todo/server/0235-Halloween-options-and-optimizations.patch rename to patches/unapplied/0235-Halloween-options-and-optimizations.patch diff --git a/patches/todo/server/0236-Config-for-grindstones.patch b/patches/unapplied/0236-Config-for-grindstones.patch similarity index 100% rename from patches/todo/server/0236-Config-for-grindstones.patch rename to patches/unapplied/0236-Config-for-grindstones.patch diff --git a/patches/todo/server/0237-UPnP-Port-Forwarding.patch b/patches/unapplied/0237-UPnP-Port-Forwarding.patch similarity index 100% rename from patches/todo/server/0237-UPnP-Port-Forwarding.patch rename to patches/unapplied/0237-UPnP-Port-Forwarding.patch diff --git a/patches/todo/server/0238-Campfire-option-for-lit-when-placed.patch b/patches/unapplied/0238-Campfire-option-for-lit-when-placed.patch similarity index 100% rename from patches/todo/server/0238-Campfire-option-for-lit-when-placed.patch rename to patches/unapplied/0238-Campfire-option-for-lit-when-placed.patch diff --git a/patches/todo/server/0239-options-to-extinguish-fire-blocks-with-snowballs.patch b/patches/unapplied/0239-options-to-extinguish-fire-blocks-with-snowballs.patch similarity index 100% rename from patches/todo/server/0239-options-to-extinguish-fire-blocks-with-snowballs.patch rename to patches/unapplied/0239-options-to-extinguish-fire-blocks-with-snowballs.patch diff --git a/patches/todo/server/0240-Add-option-to-disable-zombie-villagers-cure.patch b/patches/unapplied/0240-Add-option-to-disable-zombie-villagers-cure.patch similarity index 100% rename from patches/todo/server/0240-Add-option-to-disable-zombie-villagers-cure.patch rename to patches/unapplied/0240-Add-option-to-disable-zombie-villagers-cure.patch diff --git a/patches/todo/server/0241-Persistent-BlockEntity-Lore-and-DisplayName.patch b/patches/unapplied/0241-Persistent-BlockEntity-Lore-and-DisplayName.patch similarity index 100% rename from patches/todo/server/0241-Persistent-BlockEntity-Lore-and-DisplayName.patch rename to patches/unapplied/0241-Persistent-BlockEntity-Lore-and-DisplayName.patch diff --git a/patches/todo/server/0242-Signs-allow-color-codes.patch b/patches/unapplied/0242-Signs-allow-color-codes.patch similarity index 100% rename from patches/todo/server/0242-Signs-allow-color-codes.patch rename to patches/unapplied/0242-Signs-allow-color-codes.patch diff --git a/patches/todo/server/0243-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch b/patches/unapplied/0243-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch similarity index 100% rename from patches/todo/server/0243-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch rename to patches/unapplied/0243-Kelp-weeping-and-twisting-vines-configurable-max-gro.patch diff --git a/patches/todo/server/0244-Mobs-always-drop-experience.patch b/patches/unapplied/0244-Mobs-always-drop-experience.patch similarity index 100% rename from patches/todo/server/0244-Mobs-always-drop-experience.patch rename to patches/unapplied/0244-Mobs-always-drop-experience.patch diff --git a/patches/todo/server/0245-Potion-NamespacedKey.patch b/patches/unapplied/0245-Potion-NamespacedKey.patch similarity index 100% rename from patches/todo/server/0245-Potion-NamespacedKey.patch rename to patches/unapplied/0245-Potion-NamespacedKey.patch diff --git a/patches/todo/server/0246-Grindstone-API.patch b/patches/unapplied/0246-Grindstone-API.patch similarity index 100% rename from patches/todo/server/0246-Grindstone-API.patch rename to patches/unapplied/0246-Grindstone-API.patch diff --git a/patches/todo/server/0247-Option-to-prevent-spiders-from-climbing-world-border.patch b/patches/unapplied/0247-Option-to-prevent-spiders-from-climbing-world-border.patch similarity index 100% rename from patches/todo/server/0247-Option-to-prevent-spiders-from-climbing-world-border.patch rename to patches/unapplied/0247-Option-to-prevent-spiders-from-climbing-world-border.patch diff --git a/patches/todo/server/0248-Ability-for-hoe-to-replant-crops-and-nether-warts.patch b/patches/unapplied/0248-Ability-for-hoe-to-replant-crops-and-nether-warts.patch similarity index 100% rename from patches/todo/server/0248-Ability-for-hoe-to-replant-crops-and-nether-warts.patch rename to patches/unapplied/0248-Ability-for-hoe-to-replant-crops-and-nether-warts.patch diff --git a/patches/todo/server/0249-Shearing-jeb-produces-random-color-wool.patch b/patches/unapplied/0249-Shearing-jeb-produces-random-color-wool.patch similarity index 100% rename from patches/todo/server/0249-Shearing-jeb-produces-random-color-wool.patch rename to patches/unapplied/0249-Shearing-jeb-produces-random-color-wool.patch diff --git a/patches/todo/server/0250-Turtle-eggs-random-tick-crack-chance.patch b/patches/unapplied/0250-Turtle-eggs-random-tick-crack-chance.patch similarity index 100% rename from patches/todo/server/0250-Turtle-eggs-random-tick-crack-chance.patch rename to patches/unapplied/0250-Turtle-eggs-random-tick-crack-chance.patch diff --git a/patches/todo/server/0251-Mob-head-visibility-percent.patch b/patches/unapplied/0251-Mob-head-visibility-percent.patch similarity index 100% rename from patches/todo/server/0251-Mob-head-visibility-percent.patch rename to patches/unapplied/0251-Mob-head-visibility-percent.patch diff --git a/patches/todo/server/0252-Configurable-valid-characters-for-usernames.patch b/patches/unapplied/0252-Configurable-valid-characters-for-usernames.patch similarity index 100% rename from patches/todo/server/0252-Configurable-valid-characters-for-usernames.patch rename to patches/unapplied/0252-Configurable-valid-characters-for-usernames.patch diff --git a/patches/todo/server/0253-Shears-can-have-looting-enchantment.patch b/patches/unapplied/0253-Shears-can-have-looting-enchantment.patch similarity index 100% rename from patches/todo/server/0253-Shears-can-have-looting-enchantment.patch rename to patches/unapplied/0253-Shears-can-have-looting-enchantment.patch diff --git a/patches/todo/server/0254-Stop-bees-from-dying-after-stinging.patch b/patches/unapplied/0254-Stop-bees-from-dying-after-stinging.patch similarity index 100% rename from patches/todo/server/0254-Stop-bees-from-dying-after-stinging.patch rename to patches/unapplied/0254-Stop-bees-from-dying-after-stinging.patch diff --git a/patches/todo/server/0255-Give-bee-counts-in-beehives-to-Purpur-clients.patch b/patches/unapplied/0255-Give-bee-counts-in-beehives-to-Purpur-clients.patch similarity index 100% rename from patches/todo/server/0255-Give-bee-counts-in-beehives-to-Purpur-clients.patch rename to patches/unapplied/0255-Give-bee-counts-in-beehives-to-Purpur-clients.patch diff --git a/patches/todo/server/0256-Configurable-farmland-trample-height.patch b/patches/unapplied/0256-Configurable-farmland-trample-height.patch similarity index 100% rename from patches/todo/server/0256-Configurable-farmland-trample-height.patch rename to patches/unapplied/0256-Configurable-farmland-trample-height.patch diff --git a/patches/todo/server/0257-Configurable-player-pickup-exp-delay.patch b/patches/unapplied/0257-Configurable-player-pickup-exp-delay.patch similarity index 100% rename from patches/todo/server/0257-Configurable-player-pickup-exp-delay.patch rename to patches/unapplied/0257-Configurable-player-pickup-exp-delay.patch diff --git a/patches/todo/server/0258-Allow-void-trading.patch b/patches/unapplied/0258-Allow-void-trading.patch similarity index 100% rename from patches/todo/server/0258-Allow-void-trading.patch rename to patches/unapplied/0258-Allow-void-trading.patch diff --git a/patches/todo/server/0259-Dont-eat-blocks-in-non-ticking-chunks.patch b/patches/unapplied/0259-Dont-eat-blocks-in-non-ticking-chunks.patch similarity index 100% rename from patches/todo/server/0259-Dont-eat-blocks-in-non-ticking-chunks.patch rename to patches/unapplied/0259-Dont-eat-blocks-in-non-ticking-chunks.patch diff --git a/patches/todo/server/0260-Configurable-phantom-size.patch b/patches/unapplied/0260-Configurable-phantom-size.patch similarity index 100% rename from patches/todo/server/0260-Configurable-phantom-size.patch rename to patches/unapplied/0260-Configurable-phantom-size.patch diff --git a/patches/todo/server/0261-Configurable-food-attributes.patch b/patches/unapplied/0261-Configurable-food-attributes.patch similarity index 100% rename from patches/todo/server/0261-Configurable-food-attributes.patch rename to patches/unapplied/0261-Configurable-food-attributes.patch diff --git a/patches/todo/server/0262-Max-joins-per-second.patch b/patches/unapplied/0262-Max-joins-per-second.patch similarity index 100% rename from patches/todo/server/0262-Max-joins-per-second.patch rename to patches/unapplied/0262-Max-joins-per-second.patch diff --git a/patches/todo/server/0263-Configurable-minimum-demand-for-trades.patch b/patches/unapplied/0263-Configurable-minimum-demand-for-trades.patch similarity index 100% rename from patches/todo/server/0263-Configurable-minimum-demand-for-trades.patch rename to patches/unapplied/0263-Configurable-minimum-demand-for-trades.patch diff --git a/patches/todo/server/0264-Lobotomize-stuck-villagers.patch b/patches/unapplied/0264-Lobotomize-stuck-villagers.patch similarity index 100% rename from patches/todo/server/0264-Lobotomize-stuck-villagers.patch rename to patches/unapplied/0264-Lobotomize-stuck-villagers.patch diff --git a/patches/todo/server/0265-Option-for-villager-display-trade-item.patch b/patches/unapplied/0265-Option-for-villager-display-trade-item.patch similarity index 100% rename from patches/todo/server/0265-Option-for-villager-display-trade-item.patch rename to patches/unapplied/0265-Option-for-villager-display-trade-item.patch diff --git a/patches/todo/server/0266-Fill-command-max-area-option.patch b/patches/unapplied/0266-Fill-command-max-area-option.patch similarity index 100% rename from patches/todo/server/0266-Fill-command-max-area-option.patch rename to patches/unapplied/0266-Fill-command-max-area-option.patch diff --git a/patches/todo/server/0267-MC-238526-Fix-spawner-not-spawning-water-animals-cor.patch b/patches/unapplied/0267-MC-238526-Fix-spawner-not-spawning-water-animals-cor.patch similarity index 100% rename from patches/todo/server/0267-MC-238526-Fix-spawner-not-spawning-water-animals-cor.patch rename to patches/unapplied/0267-MC-238526-Fix-spawner-not-spawning-water-animals-cor.patch diff --git a/patches/todo/server/0268-Config-for-mob-last-hurt-by-player-time.patch b/patches/unapplied/0268-Config-for-mob-last-hurt-by-player-time.patch similarity index 100% rename from patches/todo/server/0268-Config-for-mob-last-hurt-by-player-time.patch rename to patches/unapplied/0268-Config-for-mob-last-hurt-by-player-time.patch diff --git a/patches/todo/server/0269-Anvil-repair-damage-options.patch b/patches/unapplied/0269-Anvil-repair-damage-options.patch similarity index 100% rename from patches/todo/server/0269-Anvil-repair-damage-options.patch rename to patches/unapplied/0269-Anvil-repair-damage-options.patch diff --git a/patches/todo/server/0270-Fix-legacy-colors-in-console.patch b/patches/unapplied/0270-Fix-legacy-colors-in-console.patch similarity index 100% rename from patches/todo/server/0270-Fix-legacy-colors-in-console.patch rename to patches/unapplied/0270-Fix-legacy-colors-in-console.patch diff --git a/patches/todo/server/0271-Option-to-disable-turtle-egg-trampling-with-feather-.patch b/patches/unapplied/0271-Option-to-disable-turtle-egg-trampling-with-feather-.patch similarity index 100% rename from patches/todo/server/0271-Option-to-disable-turtle-egg-trampling-with-feather-.patch rename to patches/unapplied/0271-Option-to-disable-turtle-egg-trampling-with-feather-.patch diff --git a/patches/todo/server/0272-Add-toggle-for-enchant-level-clamping.patch b/patches/unapplied/0272-Add-toggle-for-enchant-level-clamping.patch similarity index 100% rename from patches/todo/server/0272-Add-toggle-for-enchant-level-clamping.patch rename to patches/unapplied/0272-Add-toggle-for-enchant-level-clamping.patch diff --git a/patches/todo/server/0273-Config-to-prevent-horses-from-standing-when-hurt.patch b/patches/unapplied/0273-Config-to-prevent-horses-from-standing-when-hurt.patch similarity index 100% rename from patches/todo/server/0273-Config-to-prevent-horses-from-standing-when-hurt.patch rename to patches/unapplied/0273-Config-to-prevent-horses-from-standing-when-hurt.patch diff --git a/patches/todo/server/0274-Drop-incompatible-tests.patch b/patches/unapplied/0274-Drop-incompatible-tests.patch similarity index 100% rename from patches/todo/server/0274-Drop-incompatible-tests.patch rename to patches/unapplied/0274-Drop-incompatible-tests.patch