diff --git a/leaf-archived-patches/unapplied/server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch b/leaf-server/minecraft-patches/features/0099-Purpur-Server-Minecraft-Changes.patch similarity index 91% rename from leaf-archived-patches/unapplied/server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch rename to leaf-server/minecraft-patches/features/0099-Purpur-Server-Minecraft-Changes.patch index de6d525b..8d729045 100644 --- a/leaf-archived-patches/unapplied/server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch +++ b/leaf-server/minecraft-patches/features/0099-Purpur-Server-Minecraft-Changes.patch @@ -1,12 +1,12 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Github Actions -Date: Thu, 16 Jan 2025 11:21:12 +0000 +Date: Sun, 6 Apr 2025 06:33:24 +0000 Subject: [PATCH] Purpur Server Minecraft Changes Original license: MIT Original project: https://github.com/PurpurMC/Purpur -Commit: b34d675fef91bae2df723705f2568c7afd552d2d +Commit: 54283ad076012dd5308b92f2469c842ad054a782 Patches listed below are removed in this patch, They exists in Gale or Leaf: * "net/minecraft/CrashReport.java.patch" @@ -42,7 +42,7 @@ Patches listed below are removed in this patch, They exists in Gale or Leaf: - Rebrand diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java -index a9269356de964585028e69a3713ca64f67ba02bf..9a81a642698ade8a06c3a3bb4766f3c004a0b030 100644 +index f3ca86e09a4a076d143fb21eac529967ff004df4..fff12ee449878b7a6eab2edef9476bd90bafef45 100644 --- a/io/papermc/paper/entity/activation/ActivationRange.java +++ b/io/papermc/paper/entity/activation/ActivationRange.java @@ -155,6 +155,8 @@ public final class ActivationRange { @@ -63,7 +63,7 @@ index a9269356de964585028e69a3713ca64f67ba02bf..9a81a642698ade8a06c3a3bb4766f3c0 if (entity instanceof FireworkRocketEntity || (entity instanceof ItemEntity && (entity.tickCount + entity.getId()) % 4 == 0)) { // Needed for item gravity, see ItemEntity tick return true; diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java -index c2b7164a1395842ab95428540782eeda4c7960b0..59c70c567051bc7dba0d308387352d1b15f3c842 100644 +index cb63e4c264a31788cd1405428af70f7a018910e9..4d06587cd55af988eecdda5186577ab72ca3d533 100644 --- a/net/minecraft/commands/CommandSourceStack.java +++ b/net/minecraft/commands/CommandSourceStack.java @@ -455,6 +455,19 @@ public class CommandSourceStack implements ExecutionCommandSource processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; // Paper - don't store the vanilla dispatcher -@@ -285,7 +286,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping -+ public boolean lagging = false; // Purpur - Lagging threshold public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation -+ protected boolean upnp = false; // Purpur - UPnP Port Forwarding public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("MobSpawning"); // Pufferfish - optimize mob spawning ++ public boolean lagging = false; // Purpur - Lagging threshold ++ protected boolean upnp = false; // Purpur - UPnP Port Forwarding public static S spin(Function threadFunction) { -@@ -983,6 +986,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop atomicReference = new AtomicReference<>(); +@@ -975,6 +978,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - Add EntityMoveEvent serverLevel.updateLagCompensationTick(); // Paper - lag compensation net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = serverLevel.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers @@ -421,7 +418,7 @@ index a76b67a846b12a7b3d0c41b6ac4833d4f0372531..5fb7a76faf72f7d91122e5bf01c51853 if (this.tickCount % 20 == 0) { this.synchronizeTime(serverLevel); diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java -index 2dd779b300d20ff3e58f78d59dd59c73f526c9a1..abccabb8a0a1a9730b7df070dd25f3ca215af362 100644 +index 741894ed6df81fce41d9f906d6198d038aab44a8..edf115439c630a4471460db02109bbce7868de81 100644 --- a/net/minecraft/server/PlayerAdvancements.java +++ b/net/minecraft/server/PlayerAdvancements.java @@ -195,6 +195,7 @@ public class PlayerAdvancements { @@ -433,7 +430,7 @@ index 2dd779b300d20ff3e58f78d59dd59c73f526c9a1..abccabb8a0a1a9730b7df070dd25f3ca // Paper end } diff --git a/net/minecraft/server/commands/EnchantCommand.java b/net/minecraft/server/commands/EnchantCommand.java -index fe86823f1a02d66df143756f00ee56fb9f634475..53accb9ec72100c8b95bbfe083009f4ad9c9e4de 100644 +index 709690044ec506c50a73197f5ba43e89f3403a5e..60baf9a5dc4a583d08007acb68bbed61768270d5 100644 --- a/net/minecraft/server/commands/EnchantCommand.java +++ b/net/minecraft/server/commands/EnchantCommand.java @@ -70,7 +70,7 @@ public class EnchantCommand { @@ -445,7 +442,7 @@ index fe86823f1a02d66df143756f00ee56fb9f634475..53accb9ec72100c8b95bbfe083009f4a throw ERROR_LEVEL_TOO_HIGH.create(level, enchantment1.getMaxLevel()); } else { int i = 0; -@@ -81,7 +81,7 @@ public class EnchantCommand { +@@ -80,7 +80,7 @@ public class EnchantCommand { ItemStack mainHandItem = livingEntity.getMainHandItem(); if (!mainHandItem.isEmpty()) { if (enchantment1.canEnchant(mainHandItem) @@ -478,7 +475,7 @@ index c44cdbbdc06b25bd20a208386545a10af9b96df8..a88b8f999b181071ebb492bc1afa2d72 for (ServerPlayer serverPlayer : players) { diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java -index 8b7af734ca4ed3cafa810460b2cea6c1e6342a69..c394e4ea9b066895a8ad370615383a4a58d11c19 100644 +index b81f98738ef166336e4cc3092b6ba63f385b68e3..ca4bad763602f202423409ffb16f797f91a5dadc 100644 --- a/net/minecraft/server/commands/GiveCommand.java +++ b/net/minecraft/server/commands/GiveCommand.java @@ -66,6 +66,7 @@ public class GiveCommand { @@ -487,21 +484,21 @@ index 8b7af734ca4ed3cafa810460b2cea6c1e6342a69..c394e4ea9b066895a8ad370615383a4a boolean flag = serverPlayer.getInventory().add(itemStack1); + if (org.purpurmc.purpur.PurpurConfig.disableGiveCommandDrops) continue; // Purpur - add config option for toggling give command dropping if (flag && itemStack1.isEmpty()) { - ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event + ItemEntity itemEntity = serverPlayer.drop(itemStack, false); if (itemEntity != null) { diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 649403ef1d5d898052412d6d47783769f291b94f..5151c24697ceb01b4728d7d3fda5fee31db682d7 100644 +index 349eafa321c955c6bda7a5aa6931311d85867565..8fe1834250f8a708791f76a3f008198c6abf1ef4 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -106,6 +106,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - // CraftBukkit start - if (!org.bukkit.craftbukkit.Main.useConsole) return; +@@ -105,6 +105,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + public void run() { + if (!org.bukkit.craftbukkit.Main.useConsole) return; // CraftBukkit // Paper start - Use TerminalConsoleAppender + if (DedicatedServer.this.gui == null || System.console() != null) // Purpur - GUI Improvements - has no GUI or has console (did not double-click) new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start(); /* - jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader; -@@ -208,6 +209,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); +@@ -167,6 +168,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.spigotmc.SpigotConfig.registerCommands(); // Spigot end io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc. @@ -517,7 +514,7 @@ index 649403ef1d5d898052412d6d47783769f291b94f..5151c24697ceb01b4728d7d3fda5fee3 // Paper start - initialize global and world-defaults configuration this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); -@@ -230,6 +240,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -188,6 +198,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.dreeam.leaf.command.LeafCommands.registerCommands(this); // Leaf - Leaf commands this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics @@ -533,7 +530,7 @@ index 649403ef1d5d898052412d6d47783769f291b94f..5151c24697ceb01b4728d7d3fda5fee3 com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now // Gale start - Pufferfish - SIMD support -@@ -284,6 +303,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -242,6 +261,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (true) throw new IllegalStateException("Failed to bind to port", var10); // Paper - Propagate failed to bind to port error return false; } @@ -563,16 +560,16 @@ index 649403ef1d5d898052412d6d47783769f291b94f..5151c24697ceb01b4728d7d3fda5fee3 + // Purpur end - UPnP Port Forwarding // CraftBukkit start - // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up -@@ -365,6 +408,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + this.server.loadPlugins(); +@@ -321,6 +364,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) mobSpawnExecutor.start(); // Pufferfish - + org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur - Implement TPSBar + if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur - Give bee counts in beehives to Purpur clients + return true; } - } diff --git a/net/minecraft/server/dedicated/DedicatedServerProperties.java b/net/minecraft/server/dedicated/DedicatedServerProperties.java index f6518e29f805018c72222f5aaa7b662071665b65..5748658abf0b90812005ae9d426df92daf5532f0 100644 --- a/net/minecraft/server/dedicated/DedicatedServerProperties.java @@ -724,10 +721,10 @@ index f262a7c5ae4e7d56f16f5c0f4f145a2e428abbe4..614c7d9f673c926562acc8fa3b378862 private JComponent buildOnboardingPanel() { String onboardingLink = "https://docs.papermc.io/paper/next-steps"; diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c1db4f547 100644 +index cce8c151e46873c2de9be77d832bf695ee44ee24..0f09a2b0cbc17f1d64638f677f2518617f906576 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -205,6 +205,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -201,6 +201,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private final StructureManager structureManager; private final StructureCheck structureCheck; private final boolean tickTime; @@ -736,15 +733,15 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c private final RandomSequences randomSequences; // CraftBukkit start -@@ -213,6 +215,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -209,6 +211,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) + public boolean hasRidableMoveEvent = false; // Purpur - Ridables - public LevelChunk getChunkIfLoaded(int x, int z) { - return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -593,7 +596,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + @Override + public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { +@@ -585,7 +588,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // CraftBukkit end this.tickTime = tickTime; this.server = server; @@ -770,7 +767,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c this.serverLevelData = serverLevelData; ChunkGenerator chunkGenerator = levelStem.generator(); // CraftBukkit start -@@ -679,6 +699,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -669,6 +689,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit @@ -778,7 +775,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c } // Paper start -@@ -721,7 +742,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -711,7 +732,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); @@ -787,12 +784,12 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c // Paper start - create time skip event - move up calculations final long newDayTime = this.levelData.getDayTime() + 24000L; org.bukkit.event.world.TimeSkipEvent event = new org.bukkit.event.world.TimeSkipEvent( -@@ -833,6 +854,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -822,6 +843,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setGameTime(l); this.serverLevelData.getScheduledEvents().tick(this.server, l); if (this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + // Purpur start - Configurable daylight cycle -+ int incrementTicks = isDay() ? this.purpurConfig.daytimeTicks : this.purpurConfig.nighttimeTicks; ++ int incrementTicks = isBrightOutside() ? this.purpurConfig.daytimeTicks : this.purpurConfig.nighttimeTicks; + if (incrementTicks != 12000) { + this.preciseTime += 12000 / (double) incrementTicks; + this.setDayTime(this.preciseTime); @@ -801,7 +798,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c this.setDayTime(this.levelData.getDayTime() + 1L); } } -@@ -840,8 +868,22 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -829,8 +857,22 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void setDayTime(long time) { this.serverLevelData.setDayTime(time); @@ -824,7 +821,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c public void tickCustomSpawners(boolean spawnEnemies, boolean spawnFriendlies) { for (CustomSpawner customSpawner : this.customSpawners) { customSpawner.tick(this, spawnEnemies, spawnFriendlies); -@@ -919,9 +961,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -926,9 +968,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe && this.random.nextDouble() < currentDifficultyAt.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01) // Paper - Configurable spawn chances for skeleton horses && !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD); if (flag) { @@ -844,7 +841,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c skeletonHorse.setAge(0); skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); this.addFreshEntity(skeletonHorse, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit -@@ -989,7 +1039,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -984,7 +1034,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe pointOfInterestType -> pointOfInterestType.is(PoiTypes.LIGHTNING_ROD), blockPos -> blockPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()) - 1, pos, @@ -853,7 +850,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c PoiManager.Occupancy.ANY ); return optional.map(blockPos -> blockPos.above(1)); -@@ -1037,8 +1087,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1033,8 +1083,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); Component component; if (this.sleepStatus.areEnoughSleeping(_int)) { @@ -880,7 +877,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c component = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(_int)); } -@@ -1171,6 +1239,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1167,6 +1235,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @VisibleForTesting public void resetWeatherCycle() { // CraftBukkit start @@ -888,7 +885,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... -@@ -1178,6 +1247,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1174,6 +1243,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setRainTime(0); } // CraftBukkit end @@ -896,7 +893,7 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // CraftBukkit start // If we stop due to everyone sleeping we should reset the weather duration to some other random value. -@@ -2660,7 +2730,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2652,7 +2722,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Spigot start if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message // Paper start - Fix merchant inventory not closing on entity removal @@ -906,13 +903,13 @@ index 101f1a87a5fe920b57a5179da41cc91d88afa32e..94ee31a4a02edb003b98a09b0311355c } // Paper end - Fix merchant inventory not closing on entity removal diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b9afd7ee7 100644 +index 9d5051a65dcbd87b7d29db4643fa2b070717845b..57d301a9528a16c0fcdb9e45ae957629c2363457 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -399,6 +399,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent +@@ -427,6 +427,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + public @Nullable com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent public @Nullable String clientBrandName = null; // Paper - Brand support - public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event + public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event + public boolean purpurClient = false; // Purpur - Purpur client support + private boolean tpsBar = false; // Purpur - Implement TPSBar + private boolean compassBar = false; // Purpur - Add compass command @@ -920,31 +917,31 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; -@@ -567,6 +571,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - if (tag != null) { - BlockPos.CODEC.parse(NbtOps.INSTANCE, tag).resultOrPartial(LOGGER::error).ifPresent(pos -> this.raidOmenPosition = pos); - } +@@ -560,6 +564,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + this.respawnConfig = compound.read("respawn", ServerPlayer.RespawnConfig.CODEC).orElse(null); + this.spawnExtraParticlesOnFall = compound.getBooleanOr("spawn_extra_particles_on_fall", false); + this.raidOmenPosition = compound.read("raid_omen_position", BlockPos.CODEC).orElse(null); + -+ if (compound.contains("Purpur.TPSBar")) { this.tpsBar = compound.getBoolean("Purpur.TPSBar"); } // Purpur - Implement TPSBar -+ if (compound.contains("Purpur.CompassBar")) { this.compassBar = compound.getBoolean("Purpur.CompassBar"); } // Purpur - Add compass command -+ if (compound.contains("Purpur.RamBar")) { this.ramBar = compound.getBoolean("Purpur.RamBar"); } // Purpur - Implement rambar command ++ this.tpsBar = compound.getBooleanOr("Purpur.TPSBar", false); // Purpur - Implement TPSBar ++ this.compassBar = compound.getBooleanOr("Purpur.CompassBar", false); // Purpur - Add compass command ++ this.ramBar = compound.getBooleanOr("Purpur.RamBar", false); // Purpur - Implement rambar command } @Override -@@ -611,6 +619,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - } - +@@ -577,6 +585,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + compound.storeNullable("raid_omen_position", BlockPos.CODEC, this.raidOmenPosition); this.saveEnderPearls(compound); + this.getBukkitEntity().setExtraData(compound); // CraftBukkit + compound.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur - Implement TPSBar + compound.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur - Add compass command + compound.putBoolean("Purpur.RamBar", this.ramBar); // Purpur - Add rambar command } private void saveParentVehicle(CompoundTag tag) { -@@ -843,6 +854,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -788,6 +799,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.trackEnteredOrExitedLavaOnVehicle(); this.updatePlayerAttributes(); - this.advancements.flushDirty(this); + this.advancements.flushDirty(this, true); + + // Purpur start - Ridables + if (this.level().purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && this.level().getGameTime() % 100 == 0) { // 5 seconds @@ -957,7 +954,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b } private void updatePlayerAttributes() { -@@ -1130,6 +1150,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1059,6 +1079,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc ) ); Team team = this.getTeam(); @@ -965,7 +962,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) { this.server.getPlayerList().broadcastSystemMessage(deathMessage, false); } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { -@@ -1223,6 +1244,18 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1165,6 +1186,18 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc if (this.isInvulnerableTo(level, damageSource)) { return false; } else { @@ -984,15 +981,15 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b Entity entity = damageSource.getEntity(); if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false. !(entity instanceof Player player && !this.canHarmPlayer(player)) -@@ -1448,6 +1481,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1391,6 +1424,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); this.unsetRemoved(); // CraftBukkit end -+ this.portalPos = io.papermc.paper.util.MCUtil.toBlockPosition(exit); // Purpur - Fix stuck in portals ++ this.portalPos = org.bukkit.craftbukkit.util.CraftLocation.toBlockPosition(exit); // Purpur - Fix stuck in portals this.setServerLevel(level); this.connection.internalTeleport(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); // CraftBukkit - use internal teleport without event this.connection.resetPosition(); -@@ -1565,7 +1599,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1507,7 +1541,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc new AABB(vec3.x() - 8.0, vec3.y() - 5.0, vec3.z() - 8.0, vec3.x() + 8.0, vec3.y() + 5.0, vec3.z() + 8.0), monster -> monster.isPreventingPlayerRest(this.serverLevel(), this) ); @@ -1001,7 +998,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b return Either.left(Player.BedSleepingProblem.NOT_SAFE); } } -@@ -1602,7 +1636,19 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1544,7 +1578,19 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc CriteriaTriggers.SLEPT_IN_BED.trigger(this); }); if (!this.serverLevel().canSleepThroughNights()) { @@ -1022,7 +1019,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b } ((ServerLevel)this.level()).updateSleepingPlayerList(); -@@ -1710,6 +1756,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1636,6 +1682,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @Override public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) { @@ -1030,7 +1027,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signEntity.getBlockPos())); this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); } -@@ -2015,6 +2062,26 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1938,6 +1985,26 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.lastSentExp = -1; // CraftBukkit - Added to reset } @@ -1057,7 +1054,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b @Override public void displayClientMessage(Component chatComponent, boolean actionBar) { this.sendSystemMessage(chatComponent, actionBar); -@@ -2242,6 +2309,20 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2161,6 +2228,20 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc ); } @@ -1078,7 +1075,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b public void sendSystemMessage(Component mesage) { this.sendSystemMessage(mesage, false); } -@@ -2380,8 +2461,68 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2299,8 +2380,68 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); @@ -1147,7 +1144,7 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b public ServerStatsCounter getStats() { return this.stats; } -@@ -3085,4 +3226,56 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2927,4 +3068,56 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -1205,10 +1202,10 @@ index f51d699461f5aef81e1187a4068c78f844e83878..668c173dc69b4ab77d91666dc2059f2b + // Purpur end - Add rambar command } diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..a660bad3dfdb442c6aca5eb939ee103e14d37b4b 100644 +index b604cba2490a747661d6819251bc3b9a1d35c7d4..d1f74d10e5e3d65895d7e87dd77f298cd9689b33 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -351,6 +351,7 @@ public class ServerPlayerGameMode { +@@ -348,6 +348,7 @@ public class ServerPlayerGameMode { } return false; } @@ -1216,7 +1213,7 @@ index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..a660bad3dfdb442c6aca5eb939ee103e } // CraftBukkit end -@@ -464,6 +465,7 @@ public class ServerPlayerGameMode { +@@ -461,6 +462,7 @@ public class ServerPlayerGameMode { public InteractionHand interactHand; public ItemStack interactItemStack; public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) { @@ -1224,7 +1221,7 @@ index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..a660bad3dfdb442c6aca5eb939ee103e BlockPos blockPos = hitResult.getBlockPos(); BlockState blockState = level.getBlockState(blockPos); boolean cancelledBlock = false; -@@ -506,7 +508,7 @@ public class ServerPlayerGameMode { +@@ -503,7 +505,7 @@ public class ServerPlayerGameMode { boolean flag = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty(); boolean flag1 = player.isSecondaryUseActive() && flag; ItemStack itemStack = stack.copy(); @@ -1233,7 +1230,7 @@ index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..a660bad3dfdb442c6aca5eb939ee103e InteractionResult interactionResult = blockState.useItemOn(player.getItemInHand(hand), level, player, hand, hitResult); if (interactionResult.consumesAction()) { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockPos, itemStack); -@@ -552,4 +554,18 @@ public class ServerPlayerGameMode { +@@ -549,4 +551,18 @@ public class ServerPlayerGameMode { public void setLevel(ServerLevel serverLevel) { this.level = serverLevel; } @@ -1253,7 +1250,7 @@ index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..a660bad3dfdb442c6aca5eb939ee103e + // Purpur end - Shift right click to use exp for mending } diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 060becd4c0b7aa399496ad70ba28cb3449cfaea3..921ad69b699f693e3dfc8d912b0f1a05d8f81743 100644 +index 8c3255661221f8afbccb661bec3afb47e4059403..ea7710c17bfc9fcfe736c3a2e83898b7ad6a7869 100644 --- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -54,6 +54,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @@ -1270,7 +1267,7 @@ index 060becd4c0b7aa399496ad70ba28cb3449cfaea3..921ad69b699f693e3dfc8d912b0f1a05 + // Purpur start - Purpur client support + if (identifier.equals(PURPUR_CLIENT)) { -+ player.purpurClient = true; ++ this.player.purpurClient = true; + } + // Purpur end - Purpur client support + @@ -1278,10 +1275,10 @@ index 060becd4c0b7aa399496ad70ba28cb3449cfaea3..921ad69b699f693e3dfc8d912b0f1a05 this.player.clientBrandName = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.wrappedBuffer(data)).readUtf(256); } diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9abc1db6b2 100644 +index 7142de40a5ff9d1009bb06e73172877e8bf80962..4b59db324e71846d233e43bafcdae658bcc70328 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -328,6 +328,20 @@ public class ServerGamePacketListenerImpl +@@ -321,6 +321,20 @@ public class ServerGamePacketListenerImpl this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event } @@ -1302,7 +1299,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a @Override public void tick() { if (this.ackBlockChangesUpTo > -1) { -@@ -386,6 +400,12 @@ public class ServerGamePacketListenerImpl +@@ -379,6 +393,12 @@ public class ServerGamePacketListenerImpl if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits @@ -1315,7 +1312,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause } -@@ -631,6 +651,8 @@ public class ServerGamePacketListenerImpl +@@ -615,6 +635,8 @@ public class ServerGamePacketListenerImpl this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -1324,7 +1321,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -711,6 +733,7 @@ public class ServerGamePacketListenerImpl +@@ -671,6 +693,7 @@ public class ServerGamePacketListenerImpl PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (packet.getId() == this.awaitingTeleport) { if (this.awaitingPositionFromClient == null) { @@ -1332,7 +1329,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause return; } -@@ -1184,6 +1207,10 @@ public class ServerGamePacketListenerImpl +@@ -1204,6 +1227,10 @@ public class ServerGamePacketListenerImpl final int maxBookPageSize = pageMax.intValue(); final double multiplier = Math.clamp(io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier, 0.3D, 1D); long byteAllowed = maxBookPageSize; @@ -1343,7 +1340,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a for (final String page : pageList) { final int byteLength = page.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; byteTotal += byteLength; -@@ -1208,7 +1235,8 @@ public class ServerGamePacketListenerImpl +@@ -1228,7 +1255,8 @@ public class ServerGamePacketListenerImpl } if (byteTotal > byteAllowed) { @@ -1353,7 +1350,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect return; } -@@ -1227,31 +1255,45 @@ public class ServerGamePacketListenerImpl +@@ -1247,31 +1275,45 @@ public class ServerGamePacketListenerImpl Optional optional = packet.title(); optional.ifPresent(list::add); list.addAll(packet.pages()); @@ -1363,9 +1360,9 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a + // Purpur end - Allow color codes in books Consumer> consumer = optional.isPresent() - ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot) -- : texts -> this.updateBookContents(texts, slot); +- : list1 -> this.updateBookContents(list1, slot); + ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot, hasSignPerm) // Purpur - Allow color codes in books -+ : texts -> this.updateBookContents(texts, slot, hasEditPerm); // Purpur - Allow color codes in books ++ : list1 -> this.updateBookContents(list1, slot, hasEditPerm); // Purpur - Allow color codes in books this.filterTextPacket(list).thenAcceptAsync(consumer, this.server); } } @@ -1403,7 +1400,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a itemStack.set( DataComponents.WRITTEN_BOOK_CONTENT, new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getName().getString(), 0, list, true) -@@ -1265,6 +1307,16 @@ public class ServerGamePacketListenerImpl +@@ -1285,6 +1327,16 @@ public class ServerGamePacketListenerImpl return this.player.isTextFilteringEnabled() ? Filterable.passThrough(filteredText.filteredOrEmpty()) : Filterable.from(filteredText); } @@ -1420,7 +1417,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a @Override public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); -@@ -1300,7 +1352,15 @@ public class ServerGamePacketListenerImpl +@@ -1320,7 +1372,15 @@ public class ServerGamePacketListenerImpl @Override public void handleMovePlayer(ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1437,39 +1434,39 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause } else { ServerLevel serverLevel = this.player.serverLevel(); -@@ -1475,7 +1535,7 @@ public class ServerGamePacketListenerImpl - movedWrongly = true; - if (event.getLogWarning()) - // Paper end -- LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); -+ LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), verticalDelta); // Purpur - AFK API - } // Paper - } - -@@ -1541,6 +1601,8 @@ public class ServerGamePacketListenerImpl - this.lastYaw = to.getYaw(); - this.lastPitch = to.getPitch(); - -+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur - AFK API -+ - Location oldTo = to.clone(); - PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); - this.cserver.getPluginManager().callEvent(event); -@@ -1597,6 +1659,13 @@ public class ServerGamePacketListenerImpl - this.player.tryResetCurrentImpulseContext(); +@@ -1501,7 +1561,7 @@ public class ServerGamePacketListenerImpl + movedWrongly = true; + if (event.getLogWarning()) + // Paper end +- LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); ++ LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), verticalDelta); // Purpur - AFK API + } // Paper } -+ // Purpur start - Dont run with scissors! -+ if (this.player.serverLevel().purpurConfig.dontRunWithScissors && this.player.isSprinting() && !(this.player.serverLevel().purpurConfig.ignoreScissorsInWater && this.player.isInWater()) && !(this.player.serverLevel().purpurConfig.ignoreScissorsInLava && this.player.isInLava()) && (isScissors(this.player.getItemInHand(InteractionHand.MAIN_HAND)) || isScissors(this.player.getItemInHand(InteractionHand.OFF_HAND))) && (int) (Math.random() * 10) == 0) { -+ this.player.hurtServer(this.player.serverLevel(), this.player.damageSources().scissors(), (float) this.player.serverLevel().purpurConfig.scissorsRunningDamage); -+ if (!org.purpurmc.purpur.PurpurConfig.dontRunWithScissors.isBlank()) this.player.sendActionBarMessage(org.purpurmc.purpur.PurpurConfig.dontRunWithScissors); -+ } -+ // Purpur end - Dont run with scissors! +@@ -1557,6 +1617,8 @@ public class ServerGamePacketListenerImpl + this.lastYaw = to.getYaw(); + this.lastPitch = to.getPitch(); + ++ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur - AFK API + - this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); - this.lastGoodX = this.player.getX(); - this.lastGoodY = this.player.getY(); -@@ -1645,6 +1714,17 @@ public class ServerGamePacketListenerImpl + Location oldTo = to.clone(); + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); + this.cserver.getPluginManager().callEvent(event); +@@ -1612,6 +1674,13 @@ public class ServerGamePacketListenerImpl + this.player.tryResetCurrentImpulseContext(); + } + ++ // Purpur start - Dont run with scissors! ++ if (this.player.serverLevel().purpurConfig.dontRunWithScissors && this.player.isSprinting() && !(this.player.serverLevel().purpurConfig.ignoreScissorsInWater && this.player.isInWater()) && !(this.player.serverLevel().purpurConfig.ignoreScissorsInLava && this.player.isInLava()) && (isScissors(this.player.getItemInHand(InteractionHand.MAIN_HAND)) || isScissors(this.player.getItemInHand(InteractionHand.OFF_HAND))) && (int) (Math.random() * 10) == 0) { ++ this.player.hurtServer(this.player.serverLevel(), this.player.damageSources().scissors(), (float) this.player.serverLevel().purpurConfig.scissorsRunningDamage); ++ if (!org.purpurmc.purpur.PurpurConfig.dontRunWithScissors.isBlank()) this.player.sendActionBarMessage(org.purpurmc.purpur.PurpurConfig.dontRunWithScissors); ++ } ++ // Purpur end - Dont run with scissors! ++ + this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); + this.lastGoodX = this.player.getX(); + this.lastGoodY = this.player.getY(); +@@ -1629,6 +1698,17 @@ public class ServerGamePacketListenerImpl } } @@ -1484,10 +1481,10 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a + } + // Purpur end - Dont run with scissors! + - // Paper start - optimise out extra getCubes - private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) { - final List collisionsBB = new java.util.ArrayList<>(); -@@ -2015,6 +2095,7 @@ public class ServerGamePacketListenerImpl + private boolean shouldCheckPlayerMovement(boolean isElytraMovement) { + if (this.isSingleplayerOwner()) { + return false; +@@ -2005,6 +2085,7 @@ public class ServerGamePacketListenerImpl boolean cancelled; if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) { @@ -1495,7 +1492,7 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemInHand, hand); cancelled = event.useItemInHand() == Event.Result.DENY; } else { -@@ -2758,6 +2839,7 @@ public class ServerGamePacketListenerImpl +@@ -2677,6 +2758,7 @@ public class ServerGamePacketListenerImpl AABB boundingBox = target.getBoundingBox(); if (this.player.canInteractWithEntity(boundingBox, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(3.0))) { // Paper - configurable lenience value for interact range @@ -1503,20 +1500,20 @@ index a3d0d331d367b8ddfd0ac450acd143ce7d3f7a9a..5fcd389b5483c4c11e7a007b2b6abb9a packet.dispatch( new ServerboundInteractPacket.Handler() { private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction entityInteraction, PlayerInteractEntityEvent event) { // CraftBukkit -@@ -2770,6 +2852,8 @@ public class ServerGamePacketListenerImpl +@@ -2689,6 +2771,8 @@ public class ServerGamePacketListenerImpl ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); + player.processClick(hand); // Purpur - Ridables + // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a - if ((target instanceof Bucketable && target instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) { + if ((target instanceof net.minecraft.world.entity.animal.Bucketable && target instanceof LivingEntity && origItem != null && origItem == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelectedItem().isEmpty() || !ServerGamePacketListenerImpl.this.player.getInventory().getSelectedItem().is(origItem))) { target.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index e802cecf30a2bfa4390ca70c45a9840032c8c046..7401200f6a11bf552d128d833f25d825f93f57c9 100644 +index dc225eaa0daf238e091a0cf63a42158a30ecb7f0..c61a94a08486cdeba84ccfbc58ef3cabd4a461d8 100644 --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -320,7 +320,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -319,7 +319,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!"); ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(string1)); // Spigot } else { @@ -1526,10 +1523,10 @@ index e802cecf30a2bfa4390ca70c45a9840032c8c046..7401200f6a11bf552d128d833f25d825 } } catch (AuthenticationUnavailableException var4) { diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 7abdd083d84a1bd1af086eb04c757e0a8ab5f5c8..13edcfd9debc68167a3ea45699229d525d931f68 100644 +index 11015e8c0f2b5f8bd2eb083d8e093beb72c43cf0..800f773ca2cee6310a86d3f8043d57bd078a2dfd 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -407,6 +407,7 @@ public abstract class PlayerList { +@@ -411,6 +411,7 @@ public abstract class PlayerList { scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - Configurable player collision @@ -1537,15 +1534,15 @@ index 7abdd083d84a1bd1af086eb04c757e0a8ab5f5c8..13edcfd9debc68167a3ea45699229d52 if (org.galemc.gale.configuration.GaleGlobalConfiguration.get().logToConsole.playerLoginLocations) { // Gale - JettPack - make logging login location configurable PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); // Gale start - JettPack - make logging login location configurable -@@ -518,6 +519,7 @@ public abstract class PlayerList { +@@ -522,6 +523,7 @@ public abstract class PlayerList { } - public net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) { + public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) { // Paper end - Fix kick event leave message not being sent + org.purpurmc.purpur.task.BossBarTask.removeFromAll(player.getBukkitEntity()); // Purpur - Implement TPSBar ServerLevel serverLevel = player.serverLevel(); player.awardStat(Stats.LEAVE_GAME); // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it -@@ -683,7 +685,7 @@ public abstract class PlayerList { +@@ -681,7 +683,7 @@ public abstract class PlayerList { // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile) // ? Component.translatable("multiplayer.disconnect.server_full") // : null; @@ -1554,7 +1551,7 @@ index 7abdd083d84a1bd1af086eb04c757e0a8ab5f5c8..13edcfd9debc68167a3ea45699229d52 event.disallow(org.bukkit.event.player.PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -988,6 +990,20 @@ public abstract class PlayerList { +@@ -990,6 +992,20 @@ public abstract class PlayerList { } } @@ -1575,7 +1572,7 @@ index 7abdd083d84a1bd1af086eb04c757e0a8ab5f5c8..13edcfd9debc68167a3ea45699229d52 public void broadcastAll(Packet packet, ResourceKey dimension) { for (ServerPlayer serverPlayer : this.players) { if (serverPlayer.level().dimension() == dimension) { -@@ -1071,6 +1087,7 @@ public abstract class PlayerList { +@@ -1074,6 +1090,7 @@ public abstract class PlayerList { } else { b = (byte)(24 + permLevel); } @@ -1583,7 +1580,7 @@ index 7abdd083d84a1bd1af086eb04c757e0a8ab5f5c8..13edcfd9debc68167a3ea45699229d52 player.connection.send(new ClientboundEntityEventPacket(player, b)); } -@@ -1079,6 +1096,27 @@ public abstract class PlayerList { +@@ -1082,6 +1099,27 @@ public abstract class PlayerList { player.getBukkitEntity().recalculatePermissions(); // CraftBukkit this.server.getCommands().sendCommands(player); } // Paper - Add sendOpLevel API @@ -1668,10 +1665,10 @@ index d5524038314591a10c9f08a68e2ac91f6079a897..bf82de45bf98e8605a1fdb69803f75f4 } } diff --git a/net/minecraft/world/damagesource/CombatTracker.java b/net/minecraft/world/damagesource/CombatTracker.java -index d3de87eaf0eb84af77165391c7b94085d425f21d..edaa6f66f33b6a9bfb4862ec5557080bf702f4bd 100644 +index 7f653d6c0be10254f54312f3a576feb15c1c93c5..09716bececdca792c42372dbd03d260dd6be5d98 100644 --- a/net/minecraft/world/damagesource/CombatTracker.java +++ b/net/minecraft/world/damagesource/CombatTracker.java -@@ -54,7 +54,7 @@ public class CombatTracker { +@@ -55,7 +55,7 @@ public class CombatTracker { private Component getMessageForAssistedFall(Entity entity, Component entityDisplayName, String hasWeaponTranslationKey, String noWeaponTranslationKey) { ItemStack itemStack = entity instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY; @@ -1680,7 +1677,7 @@ index d3de87eaf0eb84af77165391c7b94085d425f21d..edaa6f66f33b6a9bfb4862ec5557080b ? Component.translatable(hasWeaponTranslationKey, this.mob.getDisplayName(), entityDisplayName, itemStack.getDisplayName()) : Component.translatable(noWeaponTranslationKey, this.mob.getDisplayName(), entityDisplayName); } -@@ -98,6 +98,15 @@ public class CombatTracker { +@@ -99,6 +99,15 @@ public class CombatTracker { Component component = ComponentUtils.wrapInSquareBrackets(Component.translatable(string + ".link")).withStyle(INTENTIONAL_GAME_DESIGN_STYLE); return Component.translatable(string + ".message", this.mob.getDisplayName(), component); } else { @@ -1697,7 +1694,7 @@ index d3de87eaf0eb84af77165391c7b94085d425f21d..edaa6f66f33b6a9bfb4862ec5557080b } } diff --git a/net/minecraft/world/damagesource/DamageSource.java b/net/minecraft/world/damagesource/DamageSource.java -index 0d9e5aab214df54a7a24bec45fcc8ad85f699710..bf9520bf4f314dacc66db9a7d30dbcc239db2c7d 100644 +index 9926848124f0b74ebb615fbbc45d95ebce64233f..5a663f66820d95449ccf9117e72159a10bcd04d6 100644 --- a/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java @@ -30,6 +30,8 @@ public class DamageSource { @@ -1773,7 +1770,7 @@ index 0d9e5aab214df54a7a24bec45fcc8ad85f699710..bf9520bf4f314dacc66db9a7d30dbcc2 return this.type().msgId(); } diff --git a/net/minecraft/world/damagesource/DamageSources.java b/net/minecraft/world/damagesource/DamageSources.java -index cc206ecff2d95f0398ca424c178a336ad80cc396..40ab73fb626cbb8b9132b0fec939a66145272e2e 100644 +index cc206ecff2d95f0398ca424c178a336ad80cc396..7afad362801082e5f2e3aceda864ad2a7d4e5ebb 100644 --- a/net/minecraft/world/damagesource/DamageSources.java +++ b/net/minecraft/world/damagesource/DamageSources.java @@ -42,6 +42,8 @@ public class DamageSources { @@ -1798,7 +1795,7 @@ index cc206ecff2d95f0398ca424c178a336ad80cc396..40ab73fb626cbb8b9132b0fec939a661 return new DamageSource(this.damageTypes.getOrThrow(damageTypeKey), causingEntity, directEntity); } -+ // Purpur start - Dont run with scissors! ++ // Purpur start - Dont run with scissor + public DamageSource scissors() { + return this.scissors; + } @@ -1882,31 +1879,29 @@ index 1fc9e1ad541c46124183a401b2a7d99aea69cecf..881271f0bc77a8a8a7d31daad9a8188b } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1cd52a530 100644 +index 209d897fdf5a5d19990f6dd8ee11d42d74bd0e92..1539e039d4d5fd539cfc552a4d420ae5a6fb8b56 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -134,7 +134,7 @@ import net.minecraft.world.scores.Team; - import org.slf4j.Logger; +@@ -139,6 +139,7 @@ import net.minecraft.world.scores.Team; + import org.jetbrains.annotations.Contract; - public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker -- + public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker + public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes // CraftBukkit start + private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); private static final int CURRENT_LEVEL = 2; - public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation -@@ -252,9 +252,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -259,8 +260,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public double xOld; public double yOld; public double zOld; + public float maxUpStep; // Purpur - Add option to set armorstand step height public boolean noPhysics; - private boolean wasOnFire; - public final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random + public final RandomSource random; // Paper - Share random for entities to make them more random // Add toggle for RNG manipulation public int tickCount; private int remainingFireTicks = -this.getFireImmuneTicks(); public boolean wasTouchingWater; -@@ -288,8 +289,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -294,8 +296,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public PortalProcessor portalProcess; public int portalCooldown; private boolean invulnerable; @@ -1917,7 +1912,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 private boolean hasGlowingTag; private final Set tags = new io.papermc.paper.util.SizeLimitedSet<>(new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(), MAX_ENTITY_TAG_COUNT); // Paper - fully limit tag size - replace set impl private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0}; -@@ -344,6 +345,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -351,6 +353,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public long activatedTick = Integer.MIN_VALUE; public boolean isTemporarilyActive; public long activatedImmunityTick = Integer.MIN_VALUE; @@ -1925,7 +1920,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 public void inactiveTick() { } -@@ -525,10 +527,39 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -513,10 +516,39 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } // Paper end - optimise entity tracker @@ -1937,10 +1932,10 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 + + // Purpur start - copied from Mob - API for any mob to burn daylight + public boolean isSunBurnTick() { -+ if (this.level().isDay() && !this.level().isClientSide) { ++ if (this.level().isBrightOutside() && !this.level().isClientSide) { + float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); + BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); -+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; ++ boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; + if (lightLevelDependentMagicValue > 0.5F + && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F + && !flag @@ -1965,15 +1960,15 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 this.position = Vec3.ZERO; this.blockPosition = BlockPos.ZERO; this.chunkPosition = ChunkPos.ZERO; -@@ -909,6 +940,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -888,6 +920,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v) && (!(this instanceof Player player) || !player.getAbilities().invulnerable))) { // Paper end - Configurable nether ceiling damage -+ if (this.level.purpurConfig.teleportOnNetherCeilingDamage && this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this instanceof ServerPlayer player) player.teleport(io.papermc.paper.util.MCUtil.toLocation(this.level, this.level.getSharedSpawnPos())); else // Purpur - Add option to teleport to spawn on nether ceiling damage ++ if (this.level.purpurConfig.teleportOnNetherCeilingDamage && this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this instanceof ServerPlayer player) player.teleport(org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.level.getSharedSpawnPos(), this.level)); else // Purpur - Add option to teleport to spawn on nether ceiling damage this.onBelowWorld(); } } -@@ -1839,7 +1871,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1841,7 +1874,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean fireImmune() { @@ -1981,8 +1976,8 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 + return this.immuneToFire != null ? immuneToFire : this.getType().fireImmune(); // Purpur - add fire immune API } - public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { -@@ -1908,7 +1940,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + public boolean causeFallDamage(double fallDistance, float damageMultiplier, DamageSource damageSource) { +@@ -1901,7 +1934,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.isInWater() || flag; } @@ -1991,7 +1986,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 if (this.getVehicle() instanceof AbstractBoat abstractBoat && !abstractBoat.isUnderWater()) { this.wasTouchingWater = false; } else if (this.updateFluidHeightAndDoFluidPushing(FluidTags.WATER, 0.014)) { -@@ -2544,6 +2576,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2533,6 +2566,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess compound.putBoolean("Paper.FreezeLock", true); } // Paper end @@ -2003,23 +1998,23 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 + // Purpur end - Fire immune API + return compound; - } catch (Throwable var9) { - CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT"); -@@ -2693,6 +2732,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - freezeLocked = compound.getBoolean("Paper.FreezeLock"); + } catch (Throwable var8) { + CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT"); +@@ -2650,6 +2690,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + freezeLocked = compound.getBooleanOr("Paper.FreezeLock", false); } // Paper end + + // Purpur start - Fire immune API + if (compound.contains("Purpur.FireImmune")) { -+ immuneToFire = compound.getBoolean("Purpur.FireImmune"); ++ immuneToFire = compound.getBoolean("Purpur.FireImmune").orElse(null); + } + // Purpur end - Fire immune API + - } catch (Throwable var17) { - CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT"); + } catch (Throwable var8) { + CrashReport crashReport = CrashReport.forThrowable(var8, "Loading entity NBT"); CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); -@@ -2939,6 +2985,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2878,6 +2925,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (this.isAlive() && this instanceof Leashable leashable) { if (leashable.getLeashHolder() == player) { if (!this.level().isClientSide()) { @@ -2027,7 +2022,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 // CraftBukkit start - fire PlayerUnleashEntityEvent // Paper start - Expand EntityUnleashEvent org.bukkit.event.player.PlayerUnleashEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials()); -@@ -3145,6 +3192,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3084,6 +3132,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.passengers = ImmutableList.copyOf(list); } @@ -2041,7 +2036,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 this.gameEvent(GameEvent.ENTITY_MOUNT, passenger); } } -@@ -3186,6 +3240,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3125,6 +3180,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -2056,7 +2051,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) { this.passengers = ImmutableList.of(); } else { -@@ -3264,15 +3326,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3194,15 +3257,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Vec3.directionFromRotation(this.getRotationVector()); } @@ -2076,7 +2071,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 } } } -@@ -3474,7 +3539,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3404,7 +3470,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public int getMaxAirSupply() { @@ -2085,7 +2080,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 } public int getAirSupply() { -@@ -3962,7 +4027,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3925,7 +3991,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // CraftBukkit end public boolean canUsePortal(boolean allowPassengers) { @@ -2094,7 +2089,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 } public boolean canTeleport(Level fromLevel, Level toLevel) { -@@ -4499,6 +4564,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4467,6 +4533,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(partialTick, this.yRotO, this.yRot); } @@ -2107,7 +2102,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 // Paper start - optimise collisions public boolean updateFluidHeightAndDoFluidPushing(final TagKey fluid, final double flowScale) { if (this.touchingUnloadedChunk()) { -@@ -4907,7 +4978,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4885,7 +4957,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public float maxUpStep() { @@ -2116,8 +2111,8 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 } public void onExplosionHit(@Nullable Entity entity) { -@@ -5105,4 +5176,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - return ((ServerLevel) this.level).isPositionEntityTicking(this.blockPosition()); +@@ -5123,4 +5195,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition()); } // Paper end - Expose entity id counter + // Purpur start - Ridables @@ -2139,7 +2134,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 + + public void onMount(Player rider) { + if (this instanceof Mob) { -+ ((Mob) this).setTarget(null, null, false); ++ ((Mob) this).setTarget(null, null); + ((Mob) this).getNavigation().stop(); + } + rider.setJumping(false); // fixes jump on mount @@ -2162,7 +2157,7 @@ index 63f94b2fdf1e8395d3e76aebd4466c916c73dc59..a5a8bdecddadac3de1b5a0c1a9849ce1 + // Purpur end - Ridables } diff --git a/net/minecraft/world/entity/EntitySelector.java b/net/minecraft/world/entity/EntitySelector.java -index 2aa54ee4ae742a68b79b906062528696beedf60d..002ec5f1ec14411ca48ae04b3379db0c70f81942 100644 +index bfd58eb04eee606ac0a8071de9bf75f46c35decb..0c1953754220ff72e18f0396134507d93ba7b1b8 100644 --- a/net/minecraft/world/entity/EntitySelector.java +++ b/net/minecraft/world/entity/EntitySelector.java @@ -28,6 +28,8 @@ public final class EntitySelector { @@ -2175,10 +2170,10 @@ index 2aa54ee4ae742a68b79b906062528696beedf60d..002ec5f1ec14411ca48ae04b3379db0c public static final Predicate PLAYER_AFFECTS_SPAWNING = (entity) -> { return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning; diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java -index 303bd2d3ea5c313477c8ab48359a01f230327447..adeab8980b590e4a8b64b62cb60f623b2a842982 100644 +index a1379aa8eaf84868ceb8b3762f7ca3b87a2d7785..d92045528d1a63799322418d86fab0bc580b7a99 100644 --- a/net/minecraft/world/entity/EntityType.java +++ b/net/minecraft/world/entity/EntityType.java -@@ -1084,6 +1084,16 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -1096,6 +1096,16 @@ public class EntityType implements FeatureElement, EntityTypeT return register(vanillaEntityId(key), builder); } @@ -2195,7 +2190,7 @@ index 303bd2d3ea5c313477c8ab48359a01f230327447..adeab8980b590e4a8b64b62cb60f623b public static ResourceLocation getKey(EntityType entityType) { return BuiltInRegistries.ENTITY_TYPE.getKey(entityType); } -@@ -1313,6 +1323,16 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -1326,6 +1336,16 @@ public class EntityType implements FeatureElement, EntityTypeT return this.category; } @@ -2212,36 +2207,33 @@ index 303bd2d3ea5c313477c8ab48359a01f230327447..adeab8980b590e4a8b64b62cb60f623b public String getDescriptionId() { return this.descriptionId; } -@@ -1371,7 +1391,14 @@ public class EntityType implements FeatureElement, EntityTypeT - entity.load(tag); - }, - // Paper end - Don't fire sync event during generation -- () -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id")) +@@ -1385,7 +1405,11 @@ public class EntityType implements FeatureElement, EntityTypeT + entity.load(tag); + }, + // Paper end - Don't fire sync event during generation +- () -> LOGGER.warn("Skipping Entity with id {}", tag.getStringOr("id", "[invalid]")) + // Purpur start - log skipped entity's position -+ () -> {LOGGER.warn("Skipping Entity with id {}", tag.getString("id")); -+ try { -+ ListTag pos = tag.getList("Pos", 6); -+ EntityType.LOGGER.warn("Location: {} {},{},{}", level.getWorld().getName(), pos.getDouble(0), pos.getDouble(1), pos.getDouble(2)); -+ } catch (Throwable ignore) {} ++ () -> {LOGGER.warn("Skipping Entity with id {}", tag.getStringOr("id", "[invalid]")); ++ EntityType.LOGGER.warn("Location: {} {}", level.getWorld().getName(), tag.read("Pos", net.minecraft.world.phys.Vec3.CODEC).orElse(net.minecraft.world.phys.Vec3.ZERO)); + } + // Purpur end - log skipped entity's position ); } diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java -index a5fd13641d134eae9d8f1d998cfc456b8fccd140..a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1 100644 +index a890d5d95ad6e8d9f729a7ce61bf316bef10f405..c9ddd8db21d21f93c7f8353df13d2d9bc78fe58f 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java -@@ -323,7 +323,7 @@ public class ExperienceOrb extends Entity { +@@ -328,7 +328,7 @@ public class ExperienceOrb extends Entity { public void playerTouch(Player entity) { if (entity instanceof ServerPlayer serverPlayer) { if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent -- entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; -+ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, this.level().purpurConfig.playerExpPickupDelay, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay +- entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; ++ entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, this.level().purpurConfig.playerExpPickupDelay, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay entity.take(this, 1); - int i = this.repairPlayerItems(serverPlayer, this.value); + int i = this.repairPlayerItems(serverPlayer, this.getValue()); if (i > 0) { -@@ -339,7 +339,7 @@ public class ExperienceOrb extends Entity { +@@ -344,7 +344,7 @@ public class ExperienceOrb extends Entity { } private int repairPlayerItems(ServerPlayer player, int value) { @@ -2251,10 +2243,10 @@ index a5fd13641d134eae9d8f1d998cfc456b8fccd140..a43e5190c0f9ae14ccecccd5b58dc0e1 ); if (randomItemWith.isPresent()) { diff --git a/net/minecraft/world/entity/GlowSquid.java b/net/minecraft/world/entity/GlowSquid.java -index efee812785240c1ab1fd47514cfb236a3548f9cf..b982d4b7bdf39fcaf5f22cc889467d7b953e3a8e 100644 +index 3f351fdb3cb76612d88bde713a2639d4319a7c6d..745f73e1f80d9c433630e31769b404eeeb63cb88 100644 --- a/net/minecraft/world/entity/GlowSquid.java +++ b/net/minecraft/world/entity/GlowSquid.java -@@ -25,6 +25,47 @@ public class GlowSquid extends Squid { +@@ -26,6 +26,47 @@ public class GlowSquid extends Squid { super(entityType, level); } @@ -2303,11 +2295,11 @@ index efee812785240c1ab1fd47514cfb236a3548f9cf..b982d4b7bdf39fcaf5f22cc889467d7b protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442ce302a476 100644 +index 08c2021a43f626ae142d38d0d0492bffeb1b346b..dfca015796b87059b19db55b4911bd0de2580798 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -248,9 +248,9 @@ public abstract class LivingEntity extends Entity implements Attackable { - protected float rotOffs; +@@ -224,9 +224,9 @@ public abstract class LivingEntity extends Entity implements Attackable { + protected int noActionTime; public float lastHurt; public boolean jumping; - public float xxa; @@ -2316,29 +2308,26 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + 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; -@@ -299,6 +299,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + protected InterpolationHandler interpolation = new InterpolationHandler(this); + protected double lerpYHeadRot; + protected int lerpHeadSteps; +@@ -271,11 +271,13 @@ public abstract class LivingEntity extends Entity implements Attackable { public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API + public int shieldBlockingDelay = this.level().paperConfig().misc.shieldBlockingDelay; // Paper - Make shield blocking delay configurable + protected boolean shouldBurnInDay = false; public boolean shouldBurnInDay() { return this.shouldBurnInDay; } public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Purpur - API for any mob to burn daylight - - @Override - public float getBukkitYaw() { -@@ -308,7 +309,8 @@ public abstract class LivingEntity extends Entity implements Attackable { + // CraftBukkit end protected LivingEntity(EntityType entityType, Level level) { super(entityType, level); - this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); + this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType), this); // Purpur - Ridables + this.initAttributes(); // Purpur - Configurable entity base attributes - this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit + this.craftAttributes = new org.bukkit.craftbukkit.attribute.CraftAttributeMap(this.attributes); // CraftBukkit // CraftBukkit - this.setHealth(this.getMaxHealth()) inlined and simplified to skip the instanceof check for Player, as getBukkitEntity() is not initialized in constructor this.entityData.set(LivingEntity.DATA_HEALTH_ID, this.getMaxHealth()); -@@ -322,6 +324,8 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.brain = this.makeBrain(new Dynamic<>(nbtOps, nbtOps.createMap(ImmutableMap.of(nbtOps.createString("memories"), nbtOps.emptyMap())))); +@@ -295,6 +297,8 @@ public abstract class LivingEntity extends Entity implements Attackable { + return new EntityEquipment(); } + protected void initAttributes() {}// Purpur - Configurable entity base attributes @@ -2346,7 +2335,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c public Brain getBrain() { return this.brain; } -@@ -375,6 +379,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -348,6 +352,7 @@ public abstract class LivingEntity extends Entity implements Attackable { .add(Attributes.MOVEMENT_EFFICIENCY) .add(Attributes.ATTACK_KNOCKBACK); } @@ -2354,59 +2343,49 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c @Override protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { -@@ -458,6 +463,12 @@ public abstract class LivingEntity extends Entity implements Attackable { - if (d < 0.0) { - double damagePerBlock = this.level().getWorldBorder().getDamagePerBlock(); - if (damagePerBlock > 0.0) { -+ // Purpur start - Add option to teleport to spawn if outside world border -+ if (this.level().purpurConfig.teleportIfOutsideBorder && this instanceof ServerPlayer serverPlayer) { -+ serverPlayer.teleport(io.papermc.paper.util.MCUtil.toLocation(this.level(), this.level().getSharedSpawnPos())); -+ return; -+ } -+ // Purpur end - Add option to teleport to spawn if outside world border - this.hurtServer(serverLevel1, this.damageSources().outOfBorder(), Math.max(1, Mth.floor(-d * damagePerBlock))); - } +@@ -429,6 +434,12 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (d < 0.0) { + double damagePerBlock = serverLevel1.getWorldBorder().getDamagePerBlock(); + if (damagePerBlock > 0.0) { ++ // Purpur start - Add option to teleport to spawn if outside world border ++ if (this.level().purpurConfig.teleportIfOutsideBorder && this instanceof ServerPlayer serverPlayer) { ++ serverPlayer.teleport(org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.level().getSharedSpawnPos(), this.level())); ++ return; ++ } ++ // Purpur end - Add option to teleport to spawn if outside world border + this.hurtServer(serverLevel1, this.damageSources().outOfBorder(), Math.max(1, Mth.floor(-d * damagePerBlock))); } -@@ -471,7 +482,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } +@@ -441,10 +452,10 @@ public abstract class LivingEntity extends Entity implements Attackable { && (!flag || !((Player)this).getAbilities().invulnerable); if (flag1) { this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); - if (this.getAirSupply() == -20) { + if (this.getAirSupply() == -this.level().purpurConfig.drowningDamageInterval) { // Purpur - Drowning Settings this.setAirSupply(0); - Vec3 deltaMovement = this.getDeltaMovement(); - -@@ -491,7 +502,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - ); - } - -- this.hurt(this.damageSources().drown(), 2.0F); -+ this.hurt(this.damageSources().drown(), (float) this.level().purpurConfig.damageFromDrowning); // Purpur - Drowning Settings + serverLevel1.broadcastEntityEvent(this, (byte)67); +- this.hurtServer(serverLevel1, this.damageSources().drown(), 2.0F); ++ this.hurtServer(serverLevel1, this.damageSources().drown(), (float) this.level().purpurConfig.damageFromDrowning); // Purpur - Drowning Settings } } else if (this.getAirSupply() < this.getMaxAirSupply()) { this.setAirSupply(this.increaseAirSupply(this.getAirSupply())); -@@ -795,6 +806,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - }); +@@ -754,6 +765,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.getSleepingPos().ifPresent(pos -> compound.store("sleeping_pos", BlockPos.CODEC, pos)); DataResult dataResult = this.brain.serializeStart(NbtOps.INSTANCE); - dataResult.resultOrPartial(LOGGER::error).ifPresent(brain -> compound.put("Brain", brain)); + dataResult.resultOrPartial(LOGGER::error).ifPresent(tag -> compound.put("Brain", tag)); + compound.putBoolean("Purpur.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - API for any mob to burn daylight - } - - @Override -@@ -878,6 +890,12 @@ public abstract class LivingEntity extends Entity implements Attackable { - if (compound.contains("Brain", 10)) { - this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compound.get("Brain"))); - } -+ -+ // Purpur start - API for any mob to burn daylight -+ if (compound.contains("Purpur.ShouldBurnInDay")) { -+ this.shouldBurnInDay = compound.getBoolean("Purpur.ShouldBurnInDay"); -+ } -+ // Purpur end - API for any mob to burn daylight - } - - // CraftBukkit start -@@ -1005,15 +1023,30 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (this.lastHurtByPlayer != null) { + this.lastHurtByPlayer.store(compound, "last_hurt_by_player"); + compound.putInt("last_hurt_by_player_memory_time", this.lastHurtByPlayerMemoryTime); +@@ -877,6 +889,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong + }, this::clearSleepingPos); + compound.getCompound("Brain").ifPresent(compoundTag -> this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compoundTag))); ++ this.shouldBurnInDay = compound.getBooleanOr("Purpur.ShouldBurnInDay", false); // Purpur - API for any mob to burn daylight + this.lastHurtByPlayer = EntityReference.read(compound, "last_hurt_by_player"); + this.lastHurtByPlayerMemoryTime = compound.getIntOr("last_hurt_by_player_memory_time", 0); + this.lastHurtByMob = EntityReference.read(compound, "last_hurt_by_mob"); +@@ -1010,16 +1023,31 @@ public abstract class LivingEntity extends Entity implements Attackable { if (lookingEntity != null) { // Gale start - Petal - reduce skull ItemStack lookups for reduced visibility EntityType type = lookingEntity.getType(); @@ -2416,6 +2395,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c - || type == EntityType.PIGLIN_BRUTE && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.PIGLIN_HEAD) - || type == EntityType.CREEPER && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.CREEPER_HEAD)) { - d *= 0.5; +- } + // Purpur start - Mob head visibility percent + if (type == EntityType.SKELETON && itemBySlot.is(Items.SKELETON_SKULL)) { + d *= lookingEntity.level().purpurConfig.skeletonHeadVisibilityPercent; @@ -2427,8 +2407,9 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + d *= lookingEntity.level().purpurConfig.creeperHeadVisibilityPercent; + } + // Purpur end - Mob head visibility percent -+ } -+ + // Gale end - Petal - reduce skull ItemStack lookups for reduced visibility + } + + // Purpur start - Configurable mob blindness + if (lookingEntity instanceof LivingEntity entityliving) { + if (entityliving.hasEffect(MobEffects.BLINDNESS)) { @@ -2436,14 +2417,14 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + for (int i = 0; i < amplifier; i++) { + d *= this.level().purpurConfig.mobsBlindnessMultiplier; + } - } - // Gale end - Petal - reduce skull ItemStack lookups for reduced visibility - } ++ } ++ } + // Purpur end - Configurable mob blindness - ++ return d; } -@@ -1060,6 +1093,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + +@@ -1065,6 +1093,7 @@ public abstract class LivingEntity extends Entity implements Attackable { Iterator iterator = this.activeEffects.values().iterator(); while (iterator.hasNext()) { MobEffectInstance effect = iterator.next(); @@ -2451,7 +2432,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); if (event.isCancelled()) { continue; -@@ -1375,6 +1409,24 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1388,6 +1417,24 @@ public abstract class LivingEntity extends Entity implements Attackable { this.stopSleeping(); } @@ -2476,27 +2457,26 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c this.noActionTime = 0; if (amount < 0.0F) { amount = 0.0F; -@@ -1539,11 +1591,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1649,10 +1696,10 @@ public abstract class LivingEntity extends Entity implements Attackable { protected Player resolvePlayerResponsibleForDamage(DamageSource damageSource) { Entity entity = damageSource.getEntity(); if (entity instanceof Player player) { -- this.lastHurtByPlayerTime = 100; -+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur - Config for mob last hurt by player time - this.lastHurtByPlayer = player; - return player; +- this.setLastHurtByPlayer(player, 100); ++ this.setLastHurtByPlayer(player, this.level().purpurConfig.mobLastHurtByPlayerTime); // Purpur - Config for mob last hurt by player time } else if (entity instanceof Wolf wolf && wolf.isTame()) { -- this.lastHurtByPlayerTime = 100; -+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur - Config for mob last hurt by player time - if (wolf.getOwner() instanceof Player player1) { - this.lastHurtByPlayer = player1; + if (wolf.getOwnerReference() != null) { +- this.setLastHurtByPlayer(wolf.getOwnerReference().getUUID(), 100); ++ this.setLastHurtByPlayer(wolf.getOwnerReference().getUUID(), this.level().purpurConfig.mobLastHurtByPlayerTime); // Purpur - Config for mob last hurt by player time } else { -@@ -1597,6 +1649,18 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.lastHurtByPlayer = null; + this.lastHurtByPlayerMemoryTime = 0; +@@ -1703,6 +1750,18 @@ public abstract class LivingEntity extends Entity implements Attackable { } } + // Purpur start - Totems work in inventory + if (level().purpurConfig.totemOfUndyingWorksInInventory && this instanceof ServerPlayer player && (itemStack == null || itemStack.getItem() != Items.TOTEM_OF_UNDYING) && player.getBukkitEntity().hasPermission("purpur.inventory_totem")) { -+ for (ItemStack item : player.getInventory().items) { ++ for (ItemStack item : player.getInventory().getNonEquipmentItems()) { + if (item.getItem() == Items.TOTEM_OF_UNDYING) { + itemInHand = item; + itemStack = item.copy(); @@ -2509,7 +2489,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot); event.setCancelled(itemStack == null); -@@ -1762,7 +1826,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1848,7 +1907,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.level() instanceof ServerLevel serverLevel) { boolean var6 = false; if (this.dead && entitySource instanceof WitherBoss) { // Paper @@ -2518,15 +2498,15 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c BlockPos blockPos = this.blockPosition(); BlockState blockState = Blocks.WITHER_ROSE.defaultBlockState(); if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) { -@@ -1793,6 +1857,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - boolean flag = this.lastHurtByPlayerTime > 0; +@@ -1878,6 +1937,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + boolean flag = this.lastHurtByPlayerMemoryTime > 0; this.dropEquipment(level); // CraftBukkit - from below if (this.shouldDropLoot() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + if (!(damageSource.is(net.minecraft.world.damagesource.DamageTypes.CRAMMING) && level().purpurConfig.disableDropsOnCrammingDeath)) { // Purpur - Disable loot drops on death by cramming this.dropFromLootTable(level, damageSource, flag); // Paper start final boolean prev = this.clearEquipmentSlots; -@@ -1801,6 +1866,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1886,6 +1946,7 @@ public abstract class LivingEntity extends Entity implements Attackable { // Paper end this.dropCustomDeathLoot(level, damageSource, flag); this.clearEquipmentSlots = prev; // Paper @@ -2534,7 +2514,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c } // CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment -@@ -3040,6 +3106,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3101,6 +3162,7 @@ public abstract class LivingEntity extends Entity implements Attackable { float f = (float)(d * 10.0 - 3.0); if (f > 0.0F) { this.playSound(this.getFallDamageSound((int)f), 1.0F, 1.0F); @@ -2542,7 +2522,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c this.hurt(this.damageSources().flyIntoWall(), f); } } -@@ -3530,8 +3597,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3544,8 +3606,10 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); // Paper start - Add EntityMoveEvent @@ -2555,8 +2535,8 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c 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()); -@@ -3541,11 +3610,52 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); +@@ -3555,11 +3619,52 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); } } + // Purpur start - Ridables @@ -2567,16 +2547,16 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + 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(), (org.bukkit.entity.Player) getRider().getBukkitEntity(), from, to.clone()); + if (!event.callEvent()) { -+ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ this.absSnapTo(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()); ++ this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); + } + } + } + // Purpur end - Ridables } // Paper end - Add EntityMoveEvent - if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) { this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F); } + @@ -2607,10 +2587,10 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + // Purpur end - copied from Zombie - API for any mob to burn daylight } - public boolean isSensitiveToWater() { -@@ -3567,7 +3677,18 @@ public abstract class LivingEntity extends Entity implements Attackable { - if (i1 % 2 == 0) { - List list = EquipmentSlot.VALUES.stream().filter(slot -> canGlideUsing(this.getItemBySlot(slot), slot)).toList(); + protected void applyInput() { +@@ -3589,7 +3694,18 @@ public abstract class LivingEntity extends Entity implements Attackable { + .filter(equipmentSlot1 -> canGlideUsing(this.getItemBySlot(equipmentSlot1), equipmentSlot1)) + .toList(); EquipmentSlot equipmentSlot = Util.getRandom(list, this.random); - this.getItemBySlot(equipmentSlot).hurtAndBreak(1, this, equipmentSlot); + @@ -2628,7 +2608,7 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c } this.gameEvent(GameEvent.ELYTRA_GLIDE); -@@ -4450,6 +4571,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4477,6 +4593,12 @@ public abstract class LivingEntity extends Entity implements Attackable { : slot == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.getType()); } @@ -2640,12 +2620,12 @@ index 696ef08b2d897c91a20bc22987b1f5c7047615be..ac006d8738592bc5cb77033adc8c442c + private static SlotAccess createEquipmentSlotAccess(LivingEntity entity, EquipmentSlot slot) { return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND - ? SlotAccess.forEquipmentSlot(entity, slot, stack -> stack.isEmpty() || entity.getEquipmentSlotForItem(stack) == slot) + ? SlotAccess.forEquipmentSlot(entity, slot, itemStack -> itemStack.isEmpty() || entity.getEquipmentSlotForItem(itemStack) == slot) diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf6352155d 100644 +index 92ebc61aa7f6f70292a384b56bd8ef77a15e485c..ba2f9ab55e52e25788b38c81e1070ae953b66371 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -143,13 +143,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -134,13 +134,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab private BlockPos restrictCenter = BlockPos.ZERO; private float restrictRadius = -1.0F; public boolean aware = true; // CraftBukkit @@ -2662,7 +2642,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf this.jumpControl = new JumpControl(this); this.bodyRotationControl = this.createBodyControl(); this.navigation = this.createNavigation(level); -@@ -294,6 +295,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -281,6 +282,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab target = null; } } @@ -2670,11 +2650,10 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf this.target = target; return true; // CraftBukkit end -@@ -333,8 +335,29 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -320,8 +322,28 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.resetAmbientSoundTime(); this.playAmbientSound(); } -+ + incrementTicksSinceLastInteraction(); // Purpur - Entity lifespan } @@ -2700,7 +2679,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf @Override protected void playHurtSound(DamageSource source) { this.resetAmbientSoundTime(); -@@ -482,6 +505,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -416,6 +438,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab compound.putBoolean("NoAI", this.isNoAi()); } compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit @@ -2708,19 +2687,15 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf } @Override -@@ -564,6 +588,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - this.aware = compound.getBoolean("Bukkit.Aware"); - } - // CraftBukkit end -+ // Purpur start - Entity lifespan -+ if (compound.contains("Purpur.ticksSinceLastInteraction")) { -+ this.ticksSinceLastInteraction = compound.getInt("Purpur.ticksSinceLastInteraction"); -+ } -+ // Purpur end - Entity lifespan +@@ -439,6 +462,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + this.lootTableSeed = compound.getLongOr("DeathLootTableSeed", 0L); + this.setNoAi(compound.getBooleanOr("NoAI", false)); + this.aware = compound.getBooleanOr("Bukkit.Aware", true); // CraftBukkit ++ this.ticksSinceLastInteraction = compound.getIntOr("Purpur.ticksSinceLastInteraction", 0); // Purpur- Entity lifespan } @Override -@@ -614,7 +643,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -489,7 +513,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab && this.canPickUpLoot() && this.isAlive() && !this.dead @@ -2729,7 +2704,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf Vec3i pickupReach = this.getPickupReach(); for (ItemEntity itemEntity : this.level() -@@ -1257,7 +1286,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1142,7 +1166,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab ); } @@ -2738,7 +2713,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf return spawnGroupData; } -@@ -1354,7 +1383,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1230,7 +1254,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } protected InteractionResult mobInteract(Player player, InteractionHand hand) { @@ -2747,7 +2722,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf } public boolean isWithinRestriction() { -@@ -1596,6 +1625,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1474,6 +1498,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.playAttackSound(); } @@ -2755,11 +2730,11 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf return flag; } -@@ -1608,26 +1638,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1485,26 +1510,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + private net.minecraft.world.phys.Vec3 cached_position; // Gale end - JettPack - optimize sun burn tick - cache eye blockpos - public boolean isSunBurnTick() { -- if (this.level().isDay() && !this.level().isClientSide) { +- if (this.level().isBrightOutside() && !this.level().isClientSide) { - // Gale start - JettPack - optimize sun burn tick - optimizations and cache eye blockpos - if (this.cached_position != this.position) { - this.cached_eye_blockpos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); @@ -2773,7 +2748,7 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf - if (this.random.nextFloat() * 30.0F >= (lightLevelDependentMagicValue - 0.4F) * 2.0F) return false; - // Gale end - JettPack - optimize sun burn tick - optimizations and cache eye blockpos - -- boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; +- boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; - - return !flag && this.level().canSeeSky(this.cached_eye_blockpos); // Gale - JettPack - optimize sun burn tick - optimizations and cache eye blockpos - } @@ -2784,9 +2759,9 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf } @Override -@@ -1683,4 +1695,58 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - public float[] getArmorDropChances() { - return this.armorDropChances; +@@ -1552,4 +1559,58 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + this.getNavigation().updatePathfinderMaxVisitedNodes(); + } } + + // Purpur start - Ridables @@ -2844,10 +2819,10 @@ index 4b4fa6674916d227500ce03823477a3958729190..fbcb803fb575cb1f81afa9d03d5fddbf + // Purpur end - Ridables } diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index df3724294a3297ebdc11aef3f935bf0cf36b9c95..89f4c5b2d61e27acd48063f9f24ce9ea91898b8b 100644 +index 93a079df455e371a0ca7ada253dc8b7e16b0146f..701025715e0aca3c1f920a66f9b3d03ec08eaf02 100644 --- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java +++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java -@@ -26,15 +26,22 @@ public class AttributeMap { +@@ -21,15 +21,22 @@ public class AttributeMap { // Gale end - Lithium - replace AI attributes with optimized collections private final AttributeSupplier supplier; private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations @@ -2872,7 +2847,7 @@ index df3724294a3297ebdc11aef3f935bf0cf36b9c95..89f4c5b2d61e27acd48063f9f24ce9ea this.attributesToSync.add(instance); } } -@@ -48,7 +55,7 @@ public class AttributeMap { +@@ -43,7 +50,7 @@ public class AttributeMap { } public Collection getSyncableAttributes() { @@ -2882,10 +2857,16 @@ index df3724294a3297ebdc11aef3f935bf0cf36b9c95..89f4c5b2d61e27acd48063f9f24ce9ea @Nullable diff --git a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java -index 33527a1825119f3667fb3c7ccec318f2c7328ec9..e773c426567964fc8269237d71c3434a5473985c 100644 +index e6fd15c3172a951d6551cf3fb42f92f39f1cf7b8..9952eed6a8ac31c757d5c27e043b85d7a949b481 100644 --- a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java +++ b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java -@@ -131,7 +131,7 @@ public class DefaultAttributes { +@@ -126,12 +126,12 @@ public class DefaultAttributes { + .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.MOOSHROOM, net.minecraft.world.entity.animal.AbstractCow.createAttributes().build()) // Purpur - Cows naturally aggressive to players chance + .put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build()) .put(EntityType.OCELOT, Ocelot.createAttributes().build()) .put(EntityType.PANDA, Panda.createAttributes().build()) .put(EntityType.PARROT, Parrot.createAttributes().build()) @@ -2929,7 +2910,7 @@ index 751e91a922b20c96f27885c3eb085ec4ae39091b..7f0975f8bd6d5f8ca28f503f93c8cb5c for (final Pair, BlockPos> poiPose : poiposes) { if (predicate.test(level, poiPose.getSecond())) { diff --git a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java -index 4106549bd4dec1cc47d8765be8f5d119fe33bf56..56d49bc71cb0cb0a08ff771991fd77ab774b4b59 100644 +index de89e45ecd4ac4c6db8b74bbe3dd6b4a7cf21671..d90a616eca474ae940d46cda94e816bddda70183 100644 --- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java @@ -32,6 +32,7 @@ public class HarvestFarmland extends Behavior { @@ -2947,11 +2928,11 @@ index 4106549bd4dec1cc47d8765be8f5d119fe33bf56..56d49bc71cb0cb0a08ff771991fd77ab - if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + if (!level.purpurConfig.villagerBypassMobGriefing == !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected return false; -- } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER) { -+ } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER && !(level.purpurConfig.villagerClericsFarmWarts && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC)) { // Purpur - Option for Villager Clerics to farm Nether Wart +- } else if (!owner.getVillagerData().profession().is(VillagerProfession.FARMER)) { ++ } else if (!owner.getVillagerData().profession().is(VillagerProfession.FARMER) && !(level.purpurConfig.villagerClericsFarmWarts && owner.getVillagerData().profession().is(VillagerProfession.CLERIC))) { // Purpur - Option for Villager Clerics to farm Nether Wart return false; } else { -+ if (!this.clericWartFarmer && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC) this.clericWartFarmer = true; // Purpur - Option for Villager Clerics to farm Nether Wart ++ if (!this.clericWartFarmer && owner.getVillagerData().profession().is(VillagerProfession.CLERIC)) this.clericWartFarmer = true; // Purpur - Option for Villager Clerics to farm Nether Wart BlockPos.MutableBlockPos mutableBlockPos = owner.blockPosition().mutable(); this.validFarmlandAroundVillager.clear(); @@ -3039,7 +3020,7 @@ index 400e6d49144b3e5803901938dcd2ac4e52e9c131..45c45afeffcfba3558bdf46cbe39ff60 && this.lookTime > 0 && entity.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).isPresent(); diff --git a/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java b/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java -index 243ac036f95794e7766aefb4630b635681ae5a5f..4d8523a43d60cd6b4fd5546ffb3a61417b2c475b 100644 +index 623dd33a85cb67ecb835de18e9aac29f3394ce28..72cca4897f9697573fd6987a5f0d2df52761b8c3 100644 --- a/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java +++ b/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java @@ -59,6 +59,12 @@ public class TradeWithVillager extends Behavior { @@ -3047,7 +3028,7 @@ index 243ac036f95794e7766aefb4630b635681ae5a5f..4d8523a43d60cd6b4fd5546ffb3a6141 } + // Purpur start - Option for Villager Clerics to farm Nether Wart -+ if (level.purpurConfig.villagerClericsFarmWarts && level.purpurConfig.villagerClericFarmersThrowWarts && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC && owner.getInventory().countItem(Items.NETHER_WART) > Items.NETHER_WART.getDefaultMaxStackSize() / 2) { ++ if (level.purpurConfig.villagerClericsFarmWarts && level.purpurConfig.villagerClericFarmersThrowWarts && owner.getVillagerData().profession().is(VillagerProfession.CLERIC) && owner.getInventory().countItem(Items.NETHER_WART) > Items.NETHER_WART.getDefaultMaxStackSize() / 2) { + throwHalfStack(owner, ImmutableSet.of(Items.NETHER_WART), villager); + } + // Purpur end - Option for Villager Clerics to farm Nether Wart @@ -3056,32 +3037,32 @@ index 243ac036f95794e7766aefb4630b635681ae5a5f..4d8523a43d60cd6b4fd5546ffb3a6141 throwHalfStack(owner, this.trades, villager); } diff --git a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java -index 84afd8646b05409c582f29d73f9fea4b09feb603..32779b121322688a4b14e460b1f902ef67770b32 100644 +index c65f80aadeb27685653f6a4731888c612d4a59d6..bb07aa944ce60ec7db96e2b57bd6c2c862e2f787 100644 --- a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java +++ b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java -@@ -74,8 +74,13 @@ public class VillagerGoalPackages { - } - - public static ImmutableList>> getWorkPackage(VillagerProfession profession, float speedModifier) { +@@ -79,8 +79,13 @@ public class VillagerGoalPackages { + public static ImmutableList>> getWorkPackage( + Holder profession, float speedModifier + ) { + // Purpur start - Option for Villager Clerics to farm Nether Wart + return getWorkPackage(profession, speedModifier, false); + } -+ public static ImmutableList>> getWorkPackage(VillagerProfession profession, float speedModifier, boolean clericsFarmWarts) { ++ public static ImmutableList>> getWorkPackage(Holder profession, float speedModifier, boolean clericsFarmWarts) { + // Purpur end - Option for Villager Clerics to farm Nether Wart WorkAtPoi workAtPoi; -- if (profession == VillagerProfession.FARMER) { -+ if (profession == VillagerProfession.FARMER || (clericsFarmWarts && profession == VillagerProfession.CLERIC)) { // Purpur - Option for Villager Clerics to farm Nether Wart +- if (profession.is(VillagerProfession.FARMER)) { ++ if (profession.is(VillagerProfession.FARMER) || (clericsFarmWarts && profession.is(VillagerProfession.CLERIC))) { // Purpur - Option for Villager Clerics to farm Nether Wart workAtPoi = new WorkAtComposter(); } else { workAtPoi = new WorkAtPoi(); diff --git a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java -index 8fe5bd54b5a4848da1f08ea65fe2bc3514bed8c8..54eeb72b638127b180470887a3b59d55773f3bc9 100644 +index 2591e4bbd234e51ff2c6b00db888d3b158f5a07d..e3d48c7c6615185f8a14bc96476a665bdadc275b 100644 --- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java +++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java @@ -118,8 +118,10 @@ public class VillagerMakeLove extends Behavior { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, parent, partner, null, null, 0).isCancelled()) { return Optional.empty(); } - // Move age setting down - parent.setAge(6000); - partner.setAge(6000); + // Purpur start - Make entity breeding times configurable @@ -3092,7 +3073,7 @@ index 8fe5bd54b5a4848da1f08ea65fe2bc3514bed8c8..54eeb72b638127b180470887a3b59d55 // CraftBukkit end - call EntityBreedEvent level.broadcastEntityEvent(breedOffspring, (byte)12); diff --git a/net/minecraft/world/entity/ai/control/MoveControl.java b/net/minecraft/world/entity/ai/control/MoveControl.java -index 0f9bf0cb0655a6ed449a86e99b17f89b4e3264df..1860b4ab2314f5da017313977c6423e735a4f96b 100644 +index cdd85c11a214db4829305eb54e0de9670a9241ac..88adfbb7998515f1f64b2d4121549179dc719375 100644 --- a/net/minecraft/world/entity/ai/control/MoveControl.java +++ b/net/minecraft/world/entity/ai/control/MoveControl.java @@ -29,6 +29,20 @@ public class MoveControl implements Control { @@ -3152,13 +3133,13 @@ index e026e07ca86700c864a3dceda6817fb7b6cb11e9..f1dfe0bf047e7d331b2379a672ff7b8e && !this.isOpen(); } diff --git a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java -index e84893780b533b1ecb3675606b5c2daf7339b861..65eb4d8001b07cb3f7cda17565eea10a88a9c47c 100644 +index 7a75415a469bc99f45a5cfaab038181717903f1d..fc244a1fbd401f6ea92e7428b9738939e0cb2b1e 100644 --- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java @@ -67,7 +67,7 @@ public class EatBlockGoal extends Goal { BlockPos blockPos = this.mob.blockPosition(); final BlockState blockState = this.level.getBlockState(blockPos); // Paper - fix wrong block state - if (IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state + if (IS_EDIBLE.test(blockState)) { // Paper - fix wrong block state - if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state + if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).purpurConfig.sheepBypassMobGriefing == !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state // Purpur - Add mobGriefing bypass to everything affected this.level.destroyBlock(blockPos, false); @@ -3194,7 +3175,7 @@ index 6eaf0bd944349cd0c6084462ac385fa2caafe933..be59d0c27a83b329ec3f97c029cfb9c1 double d = this.llama.distanceToSqr(this.llama.getCaravanHead()); if (d > 676.0) { diff --git a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -index 579ca031d461ed4327fe4fb45c5289565322e64e..95fa516910a3834bbd4db6d11279e13a1f0dac41 100644 +index 3d40911970caf6f1de2a1ebee1df4c077703226a..9b29c0c676a45de2abdc76e0502ac06ac1e53097 100644 --- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java @@ -35,7 +35,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { @@ -3265,16 +3246,16 @@ index 066faa704338c573472381e1ebd063e0d52aaaa4..1f96fd5085bacb4c584576c7cb9f51e7 // Paper end - optimise POI access if (path != null && path.canReach()) { diff --git a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java -index d9318a5a9eb3de89f48efa23b944c6d9e2ba37d1..135e19e921c9592cec83f6f940f2abe47757fbb8 100644 +index a608092a6e72b9be92624e36dbf19539985cd9d5..60ec389615cfcad388ed37b8d3ee04e87db36755 100644 --- a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java +++ b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java -@@ -30,6 +30,13 @@ public class SecondaryPoiSensor extends Sensor { +@@ -29,6 +29,13 @@ public class SecondaryPoiSensor extends Sensor { return; } // Gale end - Lithium - skip secondary POI sensor if absent + // Purpur start - Option for Villager Clerics to farm Nether Wart - make sure clerics don't wander to soul sand when the option is off + Brain brain = entity.getBrain(); -+ if (!level.purpurConfig.villagerClericsFarmWarts && entity.getVillagerData().getProfession() == net.minecraft.world.entity.npc.VillagerProfession.CLERIC) { ++ if (!level.purpurConfig.villagerClericsFarmWarts && entity.getVillagerData().profession().is(net.minecraft.world.entity.npc.VillagerProfession.CLERIC)) { + brain.eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE); + return; + } @@ -3282,7 +3263,7 @@ index d9318a5a9eb3de89f48efa23b944c6d9e2ba37d1..135e19e921c9592cec83f6f940f2abe4 ResourceKey resourceKey = level.dimension(); BlockPos blockPos = entity.blockPosition(); List list = Lists.newArrayList(); -@@ -46,7 +53,7 @@ public class SecondaryPoiSensor extends Sensor { +@@ -45,7 +52,7 @@ public class SecondaryPoiSensor extends Sensor { } } @@ -3307,10 +3288,10 @@ index 17a08a3af468093668a41f154c2beb69c6617efa..398a97a72dca785204f6b7b8fc4abe5c if (entity == null) { if (this.isCombat && (!target.canBeSeenAsEnemy() || level.getDifficulty() == Difficulty.PEACEFUL)) { diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java -index 62085eecd2bb55721208c5fd126aaae56a50ed6b..e042a4df5a9ad16751f64ce71537969932ae81fd 100644 +index 65a9ea8d4a208f447b5e78b58b10a0917e35e4f2..cfb7b21269933ff3b053fa180ae8d5d9db4f68bc 100644 --- a/net/minecraft/world/entity/ambient/Bat.java +++ b/net/minecraft/world/entity/ambient/Bat.java -@@ -42,11 +42,87 @@ public class Bat extends AmbientCreature { +@@ -43,11 +43,87 @@ public class Bat extends AmbientCreature { public Bat(EntityType entityType, Level level) { super(entityType, level); @@ -3398,7 +3379,7 @@ index 62085eecd2bb55721208c5fd126aaae56a50ed6b..e042a4df5a9ad16751f64ce715379699 @Override public boolean isFlapping() { return !this.isResting() && this.tickCount % 10.0F == 0.0F; -@@ -98,7 +174,7 @@ public class Bat extends AmbientCreature { +@@ -99,7 +175,7 @@ public class Bat extends AmbientCreature { } public static AttributeSupplier.Builder createAttributes() { @@ -3407,7 +3388,7 @@ index 62085eecd2bb55721208c5fd126aaae56a50ed6b..e042a4df5a9ad16751f64ce715379699 } public boolean isResting() { -@@ -129,6 +205,14 @@ public class Bat extends AmbientCreature { +@@ -130,6 +206,14 @@ public class Bat extends AmbientCreature { @Override protected void customServerAiStep(ServerLevel level) { @@ -3422,7 +3403,7 @@ index 62085eecd2bb55721208c5fd126aaae56a50ed6b..e042a4df5a9ad16751f64ce715379699 super.customServerAiStep(level); BlockPos blockPos = this.blockPosition(); BlockPos blockPos1 = blockPos.above(); -@@ -231,7 +315,7 @@ public class Bat extends AmbientCreature { +@@ -232,7 +316,7 @@ public class Bat extends AmbientCreature { } else { int maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos); int i = 4; @@ -3431,20 +3412,129 @@ index 62085eecd2bb55721208c5fd126aaae56a50ed6b..e042a4df5a9ad16751f64ce715379699 i = 7; } else if (randomSource.nextBoolean()) { return false; -@@ -276,6 +360,8 @@ public class Bat extends AmbientCreature { +@@ -277,6 +361,7 @@ public class Bat extends AmbientCreature { */ private static long nextHalloweenEnd = 0; + public static boolean isHalloweenSeason(Level level) { return level.purpurConfig.forceHalloweenSeason || isHalloween(); } // Purpur - Halloween options and optimizations -+ // The Halloween begins at 10/20 0:00, and end with 11/04 0:00 // Only when the current Halloween period ends, the `nextHalloweenStart` // and `nextHalloweenEnd` will adjust to the epoch ms of date of next year +diff --git a/net/minecraft/world/entity/animal/AbstractCow.java b/net/minecraft/world/entity/animal/AbstractCow.java +index dd8ea03ba823996a5c97562e357650ab34d0e32e..61e7300bbf272398b2faebf5e537d9c2ddedc6d6 100644 +--- a/net/minecraft/world/entity/animal/AbstractCow.java ++++ b/net/minecraft/world/entity/animal/AbstractCow.java +@@ -37,9 +37,10 @@ public abstract class AbstractCow 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 - Ridables + this.goalSelector.addGoal(1, new PanicGoal(this, 2.0)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> itemStack.is(ItemTags.COW_FOOD), false)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms + this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); +@@ -82,19 +83,24 @@ public abstract class AbstractCow extends Animal { + + @Override + public InteractionResult mobInteract(Player player, InteractionHand hand) { ++ if (getRider() != null) return InteractionResult.PASS; // Purpur - Ridables + ItemStack itemInHand = player.getItemInHand(hand); + if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { + // CraftBukkit start - Got milk? + org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(player.level(), player, this.blockPosition(), this.blockPosition(), null, itemInHand, Items.MILK_BUCKET, hand); + if (event.isCancelled()) { + player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur - Ridables + } + // CraftBukkit end + player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); + ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + player.setItemInHand(hand, itemStack); + return InteractionResult.SUCCESS; ++ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom ++ } else if (level().purpurConfig.cowFeedMushrooms > 0 && this.getType() != EntityType.MOOSHROOM && isMushroom(itemInHand)) { ++ return this.feedMushroom(player, itemInHand); ++ // Purpur end - Cows eat mushrooms + } else { + return super.mobInteract(player, hand); + } +@@ -104,4 +110,67 @@ public abstract class AbstractCow extends Animal { + public EntityDimensions getDefaultDimensions(Pose pose) { + return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose); + } ++ ++ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom ++ private int redMushroomsFed = 0; ++ private int brownMushroomsFed = 0; ++ ++ private boolean isMushroom(ItemStack stack) { ++ return stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem() || stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem(); ++ } ++ ++ private int incrementFeedCount(ItemStack stack) { ++ if (stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) { ++ return ++redMushroomsFed; ++ } else { ++ return ++brownMushroomsFed; ++ } ++ } ++ ++ private InteractionResult feedMushroom(Player player, ItemStack stack) { ++ level().broadcastEntityEvent(this, (byte) 18); // hearts ++ playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); ++ if (incrementFeedCount(stack) < level().purpurConfig.cowFeedMushrooms) { ++ if (!player.getAbilities().instabuild) { ++ stack.shrink(1); ++ } ++ return InteractionResult.CONSUME; // require 5 mushrooms to transform (prevents mushroom duping) ++ } ++ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level(), net.minecraft.world.entity.EntitySpawnReason.CONVERSION); ++ if (mooshroom == null) { ++ return InteractionResult.PASS; ++ } ++ if (stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem()) { ++ mooshroom.setVariant(MushroomCow.Variant.BROWN); ++ } else { ++ mooshroom.setVariant(MushroomCow.Variant.RED); ++ } ++ mooshroom.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ mooshroom.setHealth(this.getHealth()); ++ mooshroom.setAge(getAge()); ++ mooshroom.copyPosition(this); ++ mooshroom.setYBodyRot(this.yBodyRot); ++ mooshroom.setYHeadRot(this.getYHeadRot()); ++ mooshroom.yRotO = this.yRotO; ++ mooshroom.xRotO = this.xRotO; ++ if (this.hasCustomName()) { ++ mooshroom.setCustomName(this.getCustomName()); ++ } ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ this.level().addFreshEntity(mooshroom); ++ this.remove(RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); ++ if (!player.getAbilities().instabuild) { ++ stack.shrink(1); ++ } ++ for (int i = 0; i < 15; ++i) { ++ ((net.minecraft.server.level.ServerLevel) level()).sendParticlesSource(((net.minecraft.server.level.ServerLevel) level()).players(), null, net.minecraft.core.particles.ParticleTypes.HAPPY_VILLAGER, ++ false, true, ++ getX() + random.nextFloat(), getY() + (random.nextFloat() * 2), getZ() + random.nextFloat(), 1, ++ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0); ++ } ++ return InteractionResult.SUCCESS; ++ } ++ // Purpur end - Cows eat mushrooms + } diff --git a/net/minecraft/world/entity/animal/AbstractFish.java b/net/minecraft/world/entity/animal/AbstractFish.java -index c0997c8c0f8ee4474d3acdd5938b1879c4e589a2..28ae152125ed83d8917674b6068f227f87890f30 100644 +index 363582056339f64dbe7e686b61451c095c538c00..2cf95769ec3a1662443ea31e1bc2ba01cb7b523e 100644 --- a/net/minecraft/world/entity/animal/AbstractFish.java +++ b/net/minecraft/world/entity/animal/AbstractFish.java -@@ -87,6 +87,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { +@@ -88,6 +88,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { @Override protected void registerGoals() { super.registerGoals(); @@ -3452,16 +3542,16 @@ index c0997c8c0f8ee4474d3acdd5938b1879c4e589a2..28ae152125ed83d8917674b6068f227f this.goalSelector.addGoal(0, new PanicGoal(this, 1.25)); this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 1.6, 1.4, EntitySelector.NO_SPECTATORS::test)); this.goalSelector.addGoal(4, new AbstractFish.FishSwimGoal(this)); -@@ -100,7 +101,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { +@@ -101,7 +102,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { @Override public void travel(Vec3 travelVector) { - if (this.isControlledByLocalInstance() && this.isInWater()) { + if (this.isInWater()) { - this.moveRelative(0.01F, travelVector); + this.moveRelative(getRider() != null ? getSpeed() : 0.01F, travelVector); // Purpur - Ridables this.move(MoverType.SELF, this.getDeltaMovement()); this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); if (this.getTarget() == null) { -@@ -160,7 +161,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { +@@ -161,7 +162,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { protected void playStepSound(BlockPos pos, BlockState block) { } @@ -3470,7 +3560,7 @@ index c0997c8c0f8ee4474d3acdd5938b1879c4e589a2..28ae152125ed83d8917674b6068f227f private final AbstractFish fish; FishMoveControl(AbstractFish mob) { -@@ -168,14 +169,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { +@@ -169,14 +170,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { this.fish = mob; } @@ -3496,13 +3586,13 @@ index c0997c8c0f8ee4474d3acdd5938b1879c4e589a2..28ae152125ed83d8917674b6068f227f double d = this.wantedX - this.fish.getX(); double d1 = this.wantedY - this.fish.getY(); diff --git a/net/minecraft/world/entity/animal/Animal.java b/net/minecraft/world/entity/animal/Animal.java -index 28697020ba838c86dde5b2b11b2fe8f347a147a7..452270f7f1c54ca98c34dcf9a9d29acae77737c8 100644 +index b851f94d63a049292a3657009d68bc1641222104..1cae770340e969ec4f037b9121142878894102d3 100644 --- a/net/minecraft/world/entity/animal/Animal.java +++ b/net/minecraft/world/entity/animal/Animal.java -@@ -40,6 +40,7 @@ public abstract class Animal extends AgeableMob { +@@ -42,6 +42,7 @@ public abstract class Animal extends AgeableMob { @Nullable public UUID loveCause; - public ItemStack breedItem; // CraftBukkit - Add breedItem variable + public @Nullable ItemStack breedItem; // CraftBukkit - Add breedItem variable + public abstract int getPurpurBreedTime(); // Purpur - Make entity breeding times configurable protected Animal(EntityType entityType, Level level) { @@ -3521,10 +3611,10 @@ index 28697020ba838c86dde5b2b11b2fe8f347a147a7..452270f7f1c54ca98c34dcf9a9d29aca AgeableMob breedOffspring = this.getBreedOffspring(level, mate); if (breedOffspring != null) { - breedOffspring.setBaby(true); -- breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- breedOffspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); + //breedOffspring.setBaby(true); // Purpur - Add adjustable breeding cooldown to config - moved down -+ //breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); // Purpur - Add adjustable breeding cooldown to config - moved down - // CraftBukkit start - call EntityBreedEvent ++ //breedOffspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); // Purpur - Add adjustable breeding cooldown to config - moved down + // CraftBukkit start - Call EntityBreedEvent ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(mate.getLoveCause())).orElse(null); + // Purpur start - Add adjustable breeding cooldown to config + if (breeder != null && level.purpurConfig.animalBreedingCooldownSeconds > 0) { @@ -3534,15 +3624,15 @@ index 28697020ba838c86dde5b2b11b2fe8f347a147a7..452270f7f1c54ca98c34dcf9a9d29aca + level.addBreedingCooldown(breeder.getUUID(), this.getClass()); + } + breedOffspring.setBaby(true); -+ breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); ++ breedOffspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); + // Purpur end - Add adjustable breeding cooldown to config int experience = this.getRandom().nextInt(7) + 1; org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, this, mate, breeder, this.breedItem, experience); if (entityBreedEvent.isCancelled()) { -@@ -272,8 +283,10 @@ public abstract class Animal extends AgeableMob { +@@ -273,8 +284,10 @@ public abstract class Animal extends AgeableMob { player.awardStat(Stats.ANIMALS_BRED); CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby); - } // Paper - call EntityBreedEvent + } // Paper - Call EntityBreedEvent - this.setAge(6000); - animal.setAge(6000); + // Purpur start - Make entity breeding times configurable @@ -3553,10 +3643,10 @@ index 28697020ba838c86dde5b2b11b2fe8f347a147a7..452270f7f1c54ca98c34dcf9a9d29aca animal.resetLove(); level.broadcastEntityEvent(this, (byte)18); diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java -index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d59452483338e170 100644 +index edca2fa21e600fa1e7ef91af673adaae7d4c86c4..e9dfff7e3726cd2229f89bb39fa1ca4815d99a6d 100644 --- a/net/minecraft/world/entity/animal/Bee.java +++ b/net/minecraft/world/entity/animal/Bee.java -@@ -145,6 +145,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -149,6 +149,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { public Bee(EntityType entityType, Level level) { super(entityType, level); @@ -3564,7 +3654,7 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 // Paper start - Fix MC-167279 class BeeFlyingMoveControl extends FlyingMoveControl { public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) { -@@ -153,22 +154,69 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -157,22 +158,69 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public void tick() { @@ -3635,7 +3725,7 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -183,6 +231,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -187,6 +235,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override protected void registerGoals() { @@ -3643,7 +3733,7 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.4F, true)); this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal()); this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); -@@ -200,6 +249,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -204,6 +253,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)); @@ -3655,8 +3745,8 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 } public static boolean isNightOrRaining(Level level) { -- return level.dimensionType().hasSkyLight() && (level.isNight() || level.isRaining()); -+ return level.dimensionType().hasSkyLight() && (level.isNight() && !level.purpurConfig.beeCanWorkAtNight || level.isRaining() && !level.purpurConfig.beeCanWorkInRain); // Purpur - Bee can work when raining or at night +- return level.dimensionType().hasSkyLight() && (level.isDarkOutside() || level.isRaining()); ++ return level.dimensionType().hasSkyLight() && (level.isDarkOutside() && !level.purpurConfig.beeCanWorkAtNight || level.isRaining() && !level.purpurConfig.beeCanWorkInRain); // Purpur - Bee can work when raining or at night } public void setStayOutOfHiveCountdown(int stayOutOfHiveCountdown) { @@ -3664,8 +3754,8 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 @Override protected void customServerAiStep(ServerLevel level) { boolean hasStung = this.hasStung(); -- if (this.isInWaterOrBubble()) { -+ if (this.level().purpurConfig.beeCanInstantlyStartDrowning && this.isInWaterOrBubble()) { // Purpur - bee can instantly start drowning in water option +- if (this.isInWater()) { ++ if (this.level().purpurConfig.beeCanInstantlyStartDrowning && this.isInWater()) { // Purpur - bee can instantly start drowning in water option this.underWaterTicks++; } else { this.underWaterTicks = 0; @@ -3713,7 +3803,7 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 @Override public int getRemainingPersistentAngerTime() { return this.entityData.get(DATA_REMAINING_ANGER_TIME); -@@ -1083,15 +1163,15 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1082,15 +1162,15 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { } } @@ -3732,35 +3822,35 @@ index 94244b148533ef026bf5c56abbc2bb5cfa83c938..d5727999eb67ff30dbf47865d5945248 } } -@@ -1136,6 +1216,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1135,6 +1215,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { Bee.this.savedFlowerPos = optional.get(); Bee.this.navigation .moveTo(Bee.this.savedFlowerPos.getX() + 0.5, Bee.this.savedFlowerPos.getY() + 0.5, Bee.this.savedFlowerPos.getZ() + 0.5, 1.2F); -+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - Bee API ++ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level())).callEvent(); // Purpur - Bee API return true; } else { Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60); -@@ -1182,6 +1263,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1181,6 +1262,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { this.pollinating = false; Bee.this.navigation.stop(); Bee.this.remainingCooldownBeforeLocatingNewFlower = 200; -+ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos), Bee.this.hasNectar()).callEvent(); // Purpur - Bee API ++ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level()), Bee.this.hasNectar()).callEvent(); // Purpur - Bee API } @Override -@@ -1228,6 +1310,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1227,6 +1309,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { this.setWantedPos(); } -+ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - Bee API ++ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level())).callEvent(); // Purpur - Bee API this.successfulPollinatingTicks++; if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) { this.lastSoundPlayedTick = this.successfulPollinatingTicks; diff --git a/net/minecraft/world/entity/animal/Cat.java b/net/minecraft/world/entity/animal/Cat.java -index 1a7a5c81a260cc740994d1a63c4775c41c238dea..e5d4dc41a72cdae15a08e6bb5425056a325c584c 100644 +index 9c60140ef1ae9973ce39643c5253ddb0eac1c97b..db536a60f3f370d163e4429865634b449f4c0cfb 100644 --- a/net/minecraft/world/entity/animal/Cat.java +++ b/net/minecraft/world/entity/animal/Cat.java -@@ -93,10 +93,65 @@ public class Cat extends TamableAnimal implements VariantHolder itemStack.is(ItemTags.CAT_FOOD), true); + this.temptGoal = new Cat.CatTemptGoal(this, 0.6, stack -> stack.is(ItemTags.CAT_FOOD), true); this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5)); this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this)); -@@ -109,6 +164,7 @@ public class Cat extends TamableAnimal implements VariantHolder(this, Rabbit.class, false, null)); this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); } -@@ -332,6 +388,14 @@ public class Cat extends TamableAnimal implements VariantHolder> DATA_VARIANT_ID = SynchedEntityData.defineId(Cow.class, EntityDataSerializers.COW_VARIANT); public Cow(EntityType entityType, Level level) { super(entityType, level); @@ -4037,9 +4127,9 @@ index befb99f0a96cb23f139061f92497737e9203a8fd..a0297ac3ba520122ed2095d6008c057d + // Purpur start - Configurable entity base attributes + @Override + public void initAttributes() { -+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth); -+ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.cowScale); -+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(this.level().purpurConfig.cowNaturallyAggressiveToPlayersDamage); // Purpur - Cows naturally aggressive to players chance ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth); ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.SCALE).setBaseValue(this.level().purpurConfig.cowScale); ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.ATTACK_DAMAGE).setBaseValue(this.level().purpurConfig.cowNaturallyAggressiveToPlayersDamage); // Purpur - Cows naturally aggressive to players chance + } + // Purpur end - Configurable entity base attributes + @@ -4057,14 +4147,6 @@ index befb99f0a96cb23f139061f92497737e9203a8fd..a0297ac3ba520122ed2095d6008c057d + } + // Purpur end - Toggle for water sensitive mob damage + -+ // Purpur start - Cows naturally aggressive to players chance -+ @Override -+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, net.minecraft.world.entity.SpawnGroupData entityData) { -+ this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance; -+ return super.finalizeSpawn(world, difficulty, spawnReason, entityData); -+ } -+ // Purpur end - Cows naturally aggressive to players chance -+ + // Purpur start - Mobs always drop experience + @Override + protected boolean isAlwaysExperienceDropper() { @@ -4072,134 +4154,45 @@ index befb99f0a96cb23f139061f92497737e9203a8fd..a0297ac3ba520122ed2095d6008c057d + } + // Purpur end - Mobs always drop experience + - @Override - protected void registerGoals() { - this.goalSelector.addGoal(0, new FloatGoal(this)); -+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables - this.goalSelector.addGoal(1, new PanicGoal(this, 2.0)); ++ @Override ++ protected void registerGoals() { ++ super.registerGoals(); + this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - Cows naturally aggressive to players chance - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); -- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> itemStack.is(ItemTags.COW_FOOD), false)); -+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms - this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25)); - this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); - this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Cows naturally aggressive to players chance - } - - @Override -@@ -56,7 +116,7 @@ public class Cow extends Animal { - } - - public static AttributeSupplier.Builder createAttributes() { -- return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F); -+ return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur - Cows naturally aggressive to players chance - } - - @Override -@@ -86,19 +146,24 @@ public class Cow extends Animal { - - @Override - public InteractionResult mobInteract(Player player, InteractionHand hand) { -+ if (getRider() != null) return InteractionResult.PASS; // Purpur - Ridables - ItemStack itemInHand = player.getItemInHand(hand); - if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { - // CraftBukkit start - Got milk? - org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemInHand, Items.MILK_BUCKET, hand); - if (event.isCancelled()) { - player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - Ridables - } - // CraftBukkit end - player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); - ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit - player.setItemInHand(hand, itemStack); - return InteractionResult.SUCCESS; -+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom -+ } else if (level().purpurConfig.cowFeedMushrooms > 0 && this.getType() != EntityType.MOOSHROOM && isMushroom(itemInHand)) { -+ return this.feedMushroom(player, itemInHand); -+ // Purpur end - Cows eat mushrooms - } else { - return super.mobInteract(player, hand); - } -@@ -114,4 +179,67 @@ public class Cow extends Animal { - public EntityDimensions getDefaultDimensions(Pose pose) { - return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose); - } -+ -+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom -+ private int redMushroomsFed = 0; -+ private int brownMushroomsFed = 0; -+ -+ private boolean isMushroom(ItemStack stack) { -+ return stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem() || stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem(); ++ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, net.minecraft.world.entity.player.Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Cows naturally aggressive to players chance + } + -+ private int incrementFeedCount(ItemStack stack) { -+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) { -+ return ++redMushroomsFed; -+ } else { -+ return ++brownMushroomsFed; -+ } + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); +@@ -40,6 +96,12 @@ public class Cow extends AbstractCow { + VariantUtils.writeVariant(compound, this.getVariant()); + } + ++ // Purpur start - Cows naturally aggressive to players chance ++ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() { ++ return AbstractCow.createAttributes().add(net.minecraft.world.entity.ai.attributes.Attributes.ATTACK_DAMAGE, 0.0D); + } ++ // Purpur end - Cows naturally aggressive to players chance + -+ private InteractionResult feedMushroom(Player player, ItemStack stack) { -+ level().broadcastEntityEvent(this, (byte) 18); // hearts -+ playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); -+ if (incrementFeedCount(stack) < level().purpurConfig.cowFeedMushrooms) { -+ if (!player.getAbilities().instabuild) { -+ stack.shrink(1); -+ } -+ return InteractionResult.CONSUME; // require 5 mushrooms to transform (prevents mushroom duping) -+ } -+ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level(), EntitySpawnReason.CONVERSION); -+ if (mooshroom == null) { -+ return InteractionResult.PASS; -+ } -+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem()) { -+ mooshroom.setVariant(MushroomCow.Variant.BROWN); -+ } else { -+ mooshroom.setVariant(MushroomCow.Variant.RED); -+ } -+ mooshroom.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); -+ mooshroom.setHealth(this.getHealth()); -+ mooshroom.setAge(getAge()); -+ mooshroom.copyPosition(this); -+ mooshroom.setYBodyRot(this.yBodyRot); -+ mooshroom.setYHeadRot(this.getYHeadRot()); -+ mooshroom.yRotO = this.yRotO; -+ mooshroom.xRotO = this.xRotO; -+ if (this.hasCustomName()) { -+ mooshroom.setCustomName(this.getCustomName()); -+ } -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) { -+ return InteractionResult.PASS; -+ } -+ this.level().addFreshEntity(mooshroom); -+ this.remove(RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); -+ if (!player.getAbilities().instabuild) { -+ stack.shrink(1); -+ } -+ for (int i = 0; i < 15; ++i) { -+ ((ServerLevel) level()).sendParticlesSource(((ServerLevel) level()).players(), null, net.minecraft.core.particles.ParticleTypes.HAPPY_VILLAGER, -+ false, true, -+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 2), getZ() + random.nextFloat(), 1, -+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0); -+ } -+ return InteractionResult.SUCCESS; -+ } -+ // Purpur end - Cows eat mushrooms - } + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +@@ -61,6 +123,7 @@ public class Cow extends AbstractCow { + public SpawnGroupData finalizeSpawn( + ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData spawnGroupData + ) { ++ this.isNaturallyAggressiveToPlayers = level.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance; // Purpur - Cows naturally aggressive to players chance + CowVariants.selectVariantToSpawn(this.random, this.registryAccess(), SpawnContext.create(level, this.blockPosition())).ifPresent(this::setVariant); + return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData); + } diff --git a/net/minecraft/world/entity/animal/Dolphin.java b/net/minecraft/world/entity/animal/Dolphin.java -index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72e6b308aa 100644 +index 8f2af65c58da50be2776a21b10db5eb9cb5f3076..87ba416479df56bad5d13c01e96e92e45b7802a3 100644 --- a/net/minecraft/world/entity/animal/Dolphin.java +++ b/net/minecraft/world/entity/animal/Dolphin.java -@@ -71,14 +71,105 @@ public class Dolphin extends AgeableWaterCreature { - private static final int TOTAL_MOISTNESS_LEVEL = 2400; - public static final Predicate ALLOWED_ITEMS = itemEntity -> !itemEntity.hasPickUpDelay() && itemEntity.isAlive() && itemEntity.isInWater(); - public static final float BABY_SCALE = 0.65F; +@@ -73,14 +73,105 @@ public class Dolphin extends AgeableWaterCreature { + private static final boolean DEFAULT_GOT_FISH = false; + @Nullable + public BlockPos treasurePos; + private boolean isNaturallyAggressiveToPlayers; // Purpur - Dolphins naturally aggressive to players chance + private int spitCooldown; // Purpur - Ridables @@ -4303,7 +4296,7 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 @Nullable @Override public SpawnGroupData finalizeSpawn( -@@ -87,6 +178,7 @@ public class Dolphin extends AgeableWaterCreature { +@@ -89,6 +180,7 @@ public class Dolphin extends AgeableWaterCreature { this.setAirSupply(this.getMaxAirSupply()); this.setXRot(0.0F); SpawnGroupData spawnGroupData1 = Objects.requireNonNullElseGet(spawnGroupData, () -> new AgeableMob.AgeableMobGroupData(0.1F)); @@ -4311,7 +4304,7 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData1); } -@@ -169,17 +261,21 @@ public class Dolphin extends AgeableWaterCreature { +@@ -155,17 +247,21 @@ public class Dolphin extends AgeableWaterCreature { protected void registerGoals() { this.goalSelector.addGoal(0, new BreathAirGoal(this)); this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); @@ -4334,7 +4327,7 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 } public static AttributeSupplier.Builder createAttributes() { -@@ -223,7 +319,7 @@ public class Dolphin extends AgeableWaterCreature { +@@ -209,7 +305,7 @@ public class Dolphin extends AgeableWaterCreature { @Override protected boolean canRide(Entity entity) { @@ -4343,7 +4336,7 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 } @Override -@@ -252,6 +348,11 @@ public class Dolphin extends AgeableWaterCreature { +@@ -238,6 +334,11 @@ public class Dolphin extends AgeableWaterCreature { @Override public void tick() { super.tick(); @@ -4355,7 +4348,7 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 if (this.isNoAi()) { this.setAirSupply(this.getMaxAirSupply()); } else { -@@ -412,6 +513,7 @@ public class Dolphin extends AgeableWaterCreature { +@@ -398,6 +499,7 @@ public class Dolphin extends AgeableWaterCreature { @Override public boolean canUse() { @@ -4364,10 +4357,10 @@ index 4141052dfd635804195a5cfa24dbd0394355a7da..7003b532182737a745491e397a967b72 } diff --git a/net/minecraft/world/entity/animal/Fox.java b/net/minecraft/world/entity/animal/Fox.java -index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f522d38bccd 100644 +index 5c7572b75afcfa9965fcda5965f6ae2e59babb46..fcda990a5575288b39f6aa16b0ec48d2a57542e9 100644 --- a/net/minecraft/world/entity/animal/Fox.java +++ b/net/minecraft/world/entity/animal/Fox.java -@@ -129,6 +129,73 @@ public class Fox extends Animal implements VariantHolder { +@@ -141,6 +141,73 @@ public class Fox extends Animal { this.getNavigation().setRequiredPathLength(32.0F); } @@ -4441,7 +4434,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -148,6 +215,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -160,6 +227,7 @@ public class Fox extends Animal { this, AbstractFish.class, 20, false, false, (entity, level) -> entity instanceof AbstractSchoolingFish ); this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); @@ -4449,7 +4442,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level())); this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2)); -@@ -175,6 +243,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -185,6 +253,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()); @@ -4457,7 +4450,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 this.targetSelector .addGoal( 3, -@@ -335,6 +404,11 @@ public class Fox extends Animal implements VariantHolder { +@@ -345,6 +414,11 @@ public class Fox extends Animal { } private void setTargetGoals() { @@ -4469,15 +4462,15 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 if (this.getVariant() == Fox.Variant.RED) { this.targetSelector.addGoal(4, this.landTargetGoal); this.targetSelector.addGoal(4, this.turtleEggTargetGoal); -@@ -364,6 +438,7 @@ public class Fox extends Animal implements VariantHolder { - @Override +@@ -372,6 +446,7 @@ public class Fox extends Animal { + public void setVariant(Fox.Variant variant) { this.entityData.set(DATA_TYPE_ID, variant.getId()); + this.setTargetGoals(); // Purpur - Tulips change fox type - fix API bug not updating pathfinders on type change } - List getTrustedUUIDs() { -@@ -685,6 +760,29 @@ public class Fox extends Animal implements VariantHolder { + @Nullable +@@ -706,6 +781,29 @@ public class Fox extends Animal { } // Paper end @@ -4507,7 +4500,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 @Override // Paper start - Cancellable death event protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(ServerLevel level, DamageSource damageSource) { -@@ -896,8 +994,10 @@ public class Fox extends Animal implements VariantHolder { +@@ -919,8 +1017,10 @@ public class Fox extends Animal { CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer, this.animal, this.partner, fox); } @@ -4520,7 +4513,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 this.animal.resetLove(); this.partner.resetLove(); serverLevel.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason -@@ -952,7 +1052,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -975,7 +1075,7 @@ public class Fox extends Animal { } protected void onReachedTarget() { @@ -4529,7 +4522,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 BlockState blockState = Fox.this.level().getBlockState(this.blockPos); if (blockState.is(Blocks.SWEET_BERRY_BUSH)) { this.pickSweetBerries(blockState); -@@ -1066,15 +1166,15 @@ public class Fox extends Animal implements VariantHolder { +@@ -1089,15 +1189,15 @@ public class Fox extends Animal { } } @@ -4548,7 +4541,7 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 } } -@@ -1110,15 +1210,15 @@ public class Fox extends Animal implements VariantHolder { +@@ -1133,15 +1233,15 @@ public class Fox extends Animal { } } @@ -4568,10 +4561,10 @@ index b4f3bc7938060cf55b6b242759606bf5100a1f56..90452f0945e761077608692877677f52 } } diff --git a/net/minecraft/world/entity/animal/IronGolem.java b/net/minecraft/world/entity/animal/IronGolem.java -index 8e9ba307a0528eb1aef56bdc0f4ded0e71621253..ccadc9a151e258ff2c74c65c374b1f09d56d10ec 100644 +index 33245f28c02c5cd42f2daec8748d615b7f5e21ec..21ed6bfcba6ea58663dc8e932814c1ac084d0402 100644 --- a/net/minecraft/world/entity/animal/IronGolem.java +++ b/net/minecraft/world/entity/animal/IronGolem.java -@@ -56,13 +56,67 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -57,13 +57,67 @@ public class IronGolem extends AbstractGolem implements NeutralMob { private int remainingPersistentAngerTime; @Nullable private UUID persistentAngerTarget; @@ -4639,7 +4632,7 @@ index 8e9ba307a0528eb1aef56bdc0f4ded0e71621253..ccadc9a151e258ff2c74c65c374b1f09 this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true)); this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32.0F)); this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6, false)); -@@ -70,6 +124,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -71,6 +125,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)); @@ -4647,23 +4640,23 @@ index 8e9ba307a0528eb1aef56bdc0f4ded0e71621253..ccadc9a151e258ff2c74c65c374b1f09 this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); -@@ -140,6 +195,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -141,6 +196,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); compound.putBoolean("PlayerCreated", this.isPlayerCreated()); -+ if (getSummoner() != null) compound.putUUID("Purpur.Summoner", getSummoner()); // Purpur - Summoner API ++ compound.storeNullable("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC, getSummoner()); // Purpur - Summoner API this.addPersistentAngerSaveData(compound); } -@@ -147,6 +203,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -148,6 +204,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); - this.setPlayerCreated(compound.getBoolean("PlayerCreated")); -+ if (compound.contains("Purpur.Summoner")) setSummoner(compound.getUUID("Purpur.Summoner")); // Purpur - Summoner API + this.setPlayerCreated(compound.getBooleanOr("PlayerCreated", false)); ++ this.setSummoner(compound.read("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC).orElse(null)); // Purpur - Summoner API this.readPersistentAngerSaveData(this.level(), compound); } -@@ -256,16 +313,17 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -257,16 +314,17 @@ public class IronGolem extends AbstractGolem implements NeutralMob { protected InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemInHand = player.getItemInHand(hand); if (!itemInHand.is(Items.IRON_INGOT)) { @@ -4684,10 +4677,10 @@ index 8e9ba307a0528eb1aef56bdc0f4ded0e71621253..ccadc9a151e258ff2c74c65c374b1f09 } } diff --git a/net/minecraft/world/entity/animal/MushroomCow.java b/net/minecraft/world/entity/animal/MushroomCow.java -index 12099a5eb45ee21520d3ba68ef26909d5949206d..81a50166e5baaa3b059308b69107c430f2926966 100644 +index cc2fd681d2383e62191e7b380322f2e176d79f1e..91b03b8f01ff7dd3c4a00c088fd8ba2387a5b2f7 100644 --- a/net/minecraft/world/entity/animal/MushroomCow.java +++ b/net/minecraft/world/entity/animal/MushroomCow.java -@@ -55,6 +55,51 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder drops = this.generateDefaultDrops(serverLevel, itemInHand); org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemInHand, hand, drops); if (event != null) { @@ -4749,10 +4742,10 @@ index 12099a5eb45ee21520d3ba68ef26909d5949206d..81a50166e5baaa3b059308b69107c430 // Paper end - custom shear drops } diff --git a/net/minecraft/world/entity/animal/Ocelot.java b/net/minecraft/world/entity/animal/Ocelot.java -index 5b59f68141c2ceeaf7907bbf5e7b9e08cbe2239e..681f1256d8bbedc7731fd2906a7f439da4333552 100644 +index 9e86a42f04d06c3dcd241f16ab876b0c8422fd81..dcfa57bc691e997969bc9fef1983088322e4e4e4 100644 --- a/net/minecraft/world/entity/animal/Ocelot.java +++ b/net/minecraft/world/entity/animal/Ocelot.java -@@ -62,6 +62,52 @@ public class Ocelot extends Animal { +@@ -63,6 +63,52 @@ public class Ocelot extends Animal { this.reassessTrustingGoals(); } @@ -4805,7 +4798,7 @@ index 5b59f68141c2ceeaf7907bbf5e7b9e08cbe2239e..681f1256d8bbedc7731fd2906a7f439d public boolean isTrusting() { return this.entityData.get(DATA_TRUSTING); } -@@ -93,12 +139,14 @@ public class Ocelot extends Animal { +@@ -94,12 +140,14 @@ public class Ocelot extends Animal { protected void registerGoals() { this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6, itemStack -> itemStack.is(ItemTags.OCELOT_FOOD), true); this.goalSelector.addGoal(1, new FloatGoal(this)); @@ -4820,7 +4813,7 @@ index 5b59f68141c2ceeaf7907bbf5e7b9e08cbe2239e..681f1256d8bbedc7731fd2906a7f439d 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)); } -@@ -232,7 +280,7 @@ public class Ocelot extends Animal { +@@ -233,7 +281,7 @@ public class Ocelot extends Animal { public boolean checkSpawnObstruction(LevelReader level) { if (level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox())) { BlockPos blockPos = this.blockPosition(); @@ -4830,10 +4823,10 @@ index 5b59f68141c2ceeaf7907bbf5e7b9e08cbe2239e..681f1256d8bbedc7731fd2906a7f439d } diff --git a/net/minecraft/world/entity/animal/Panda.java b/net/minecraft/world/entity/animal/Panda.java -index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c5dc20688 100644 +index ecd85f3e33f80084b9ee06c9ff1f57b73399be50..99d99d59ec0eb13dc40bc88bd70ad884bb9e2859 100644 --- a/net/minecraft/world/entity/animal/Panda.java +++ b/net/minecraft/world/entity/animal/Panda.java -@@ -105,6 +105,62 @@ public class Panda extends Animal { +@@ -106,6 +106,62 @@ public class Panda extends Animal { } } @@ -4896,7 +4889,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c @Override protected boolean canDispenserEquipIntoSlot(EquipmentSlot slot) { return slot == EquipmentSlot.MAINHAND && this.canPickUpLoot(); -@@ -258,6 +314,7 @@ public class Panda extends Animal { +@@ -259,6 +315,7 @@ public class Panda extends Animal { @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); @@ -4904,7 +4897,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0)); this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0)); this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2F, true)); -@@ -273,6 +330,7 @@ public class Panda extends Animal { +@@ -274,6 +331,7 @@ public class Panda extends Animal { this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this)); this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25)); this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0)); @@ -4912,7 +4905,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c this.targetSelector.addGoal(1, new Panda.PandaHurtByTargetGoal(this).setAlertOthers(new Class[0])); } -@@ -596,7 +654,11 @@ public class Panda extends Animal { +@@ -597,7 +655,11 @@ public class Panda extends Animal { public void setAttributes() { if (this.isWeak()) { @@ -4925,7 +4918,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c } if (this.isLazy()) { -@@ -616,7 +678,7 @@ public class Panda extends Animal { +@@ -617,7 +679,7 @@ public class Panda extends Animal { public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemInHand = player.getItemInHand(hand); if (this.isScared()) { @@ -4934,7 +4927,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c } else if (this.isOnBack()) { this.setOnBack(false); return InteractionResult.SUCCESS; -@@ -652,7 +714,7 @@ public class Panda extends Animal { +@@ -653,7 +715,7 @@ public class Panda extends Animal { return InteractionResult.SUCCESS_SERVER; } else { @@ -4943,7 +4936,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c } } -@@ -964,7 +1026,7 @@ public class Panda extends Animal { +@@ -961,7 +1023,7 @@ public class Panda extends Animal { } } @@ -4952,7 +4945,7 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c private final Panda panda; public PandaMoveControl(Panda mob) { -@@ -973,9 +1035,9 @@ public class Panda extends Animal { +@@ -970,9 +1032,9 @@ public class Panda extends Animal { } @Override @@ -4965,10 +4958,10 @@ index 283ddf7d13a17c0a6df5a52b7fd26ed7b7a4826b..0a6a3060f3690ab2d8439d66e6fd6f0c } } diff --git a/net/minecraft/world/entity/animal/Parrot.java b/net/minecraft/world/entity/animal/Parrot.java -index 16cc69b14fba16a5a5dfc05d63a40a5112314031..4fa9f50ef6869b181e4e48ed66aaee210b303cd9 100644 +index cff10bb74a216238288280399910ab1fa85cb1a5..1b8350a09a9f2a708c8cd1b0669828912f1e4214 100644 --- a/net/minecraft/world/entity/animal/Parrot.java +++ b/net/minecraft/world/entity/animal/Parrot.java -@@ -124,12 +124,97 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder entityType, Level level) { super(entityType, level); @@ -5067,7 +5060,7 @@ index 16cc69b14fba16a5a5dfc05d63a40a5112314031..4fa9f50ef6869b181e4e48ed66aaee21 @Nullable @Override public SpawnGroupData finalizeSpawn( -@@ -150,8 +235,11 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder itemStack.is(Items.CARROT_ON_A_STICK), false)); -@@ -132,6 +179,19 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { +@@ -141,6 +188,19 @@ public class Pig extends Animal implements ItemSteerable { @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { boolean isFood = this.isFood(player.getItemInHand(hand)); + // Purpur start - Pigs give saddle back + if (level().purpurConfig.pigGiveSaddleBack && player.isSecondaryUseActive() && !isFood && isSaddled() && !isVehicle()) { -+ this.steering.setSaddle(false); ++ this.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); + if (!player.getAbilities().instabuild) { + ItemStack saddle = new ItemStack(Items.SADDLE); + if (!player.getInventory().add(saddle)) { @@ -5204,7 +5197,7 @@ index d203d9c63c13f40a913235ad78a24a3bf489a083..1a504a3d887f5294c5a2fec3f4bc6654 if (!this.level().isClientSide) { player.startRiding(this); diff --git a/net/minecraft/world/entity/animal/PolarBear.java b/net/minecraft/world/entity/animal/PolarBear.java -index f568c385e1427e183aefb5819013838aca95407b..026e64bf743aa79ba6409fa5cd4374b368f98caa 100644 +index fcdaaed31c38acb55e66599cd3314606d223cd67..ab08e5e589dac3341c006876378903f7cf1db25f 100644 --- a/net/minecraft/world/entity/animal/PolarBear.java +++ b/net/minecraft/world/entity/animal/PolarBear.java @@ -59,11 +59,92 @@ public class PolarBear extends Animal implements NeutralMob { @@ -5351,10 +5344,10 @@ index f568c385e1427e183aefb5819013838aca95407b..026e64bf743aa79ba6409fa5cd4374b3 public float getStandingAnimationScale(float partialTick) { diff --git a/net/minecraft/world/entity/animal/Pufferfish.java b/net/minecraft/world/entity/animal/Pufferfish.java -index d94a7cfcd0f7a15ce97d3b12daa8b2c71acf997a..5889a9ceb54a354a79f33c9e4fc338cbf912ddda 100644 +index 4a7201fe9e946fc20ed04e729d00f7986a748bad..3b815f3ad9068eb2bdf93eac1c1aff38dffdb850 100644 --- a/net/minecraft/world/entity/animal/Pufferfish.java +++ b/net/minecraft/world/entity/animal/Pufferfish.java -@@ -45,6 +45,39 @@ public class Pufferfish extends AbstractFish { +@@ -46,6 +46,39 @@ public class Pufferfish extends AbstractFish { this.refreshDimensions(); } @@ -5395,18 +5388,18 @@ index d94a7cfcd0f7a15ce97d3b12daa8b2c71acf997a..5889a9ceb54a354a79f33c9e4fc338cb protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); diff --git a/net/minecraft/world/entity/animal/Rabbit.java b/net/minecraft/world/entity/animal/Rabbit.java -index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d928aeff5 100644 +index cc7d990f271af1371aa62e8a2ee2ee1bfffb621a..38e2698c5084f0c14c7fde5de542ed61a7cb7f1d 100644 --- a/net/minecraft/world/entity/animal/Rabbit.java +++ b/net/minecraft/world/entity/animal/Rabbit.java -@@ -83,6 +83,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -90,6 +90,7 @@ public class Rabbit extends Animal { private boolean wasOnGround; private int jumpDelayTicks; - public int moreCarrotTicks; + public int moreCarrotTicks = 0; + private boolean actualJump; // Purpur - Ridables public Rabbit(EntityType entityType, Level level) { super(entityType, level); -@@ -91,9 +92,84 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -98,9 +99,84 @@ public class Rabbit extends Animal { //this.setSpeedModifier(0.0); // CraftBukkit } @@ -5491,7 +5484,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2)); this.goalSelector.addGoal(2, new BreedGoal(this, 0.8)); -@@ -108,6 +184,14 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -115,6 +191,14 @@ public class Rabbit extends Animal { @Override protected float getJumpPower() { @@ -5506,7 +5499,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d float f = 0.3F; if (this.moveControl.getSpeedModifier() <= 0.6) { f = 0.2F; -@@ -175,6 +259,12 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -182,6 +266,12 @@ public class Rabbit extends Animal { @Override public void customServerAiStep(ServerLevel level) { @@ -5519,7 +5512,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d if (this.jumpDelayTicks > 0) { this.jumpDelayTicks--; } -@@ -376,10 +466,23 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -403,10 +493,23 @@ public class Rabbit extends Animal { } this.setVariant(randomRabbitVariant); @@ -5543,7 +5536,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d Holder biome = level.getBiome(pos); int randomInt = level.getRandom().nextInt(100); if (biome.is(BiomeTags.SPAWNS_WHITE_RABBITS)) { -@@ -470,7 +573,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -497,7 +600,7 @@ public class Rabbit extends Animal { } } @@ -5552,7 +5545,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d private final Rabbit rabbit; private double nextJumpSpeed; -@@ -480,14 +583,14 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -507,14 +610,14 @@ public class Rabbit extends Animal { } @Override @@ -5569,7 +5562,7 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d } @Override -@@ -531,7 +634,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -558,7 +661,7 @@ public class Rabbit extends Animal { @Override public boolean canUse() { if (this.nextStartTick <= 0) { @@ -5579,10 +5572,10 @@ index c5346b6e4ffe09ca1ec4b85e612c9ee52ae77329..da5b32a17283e540615373097acc511d } diff --git a/net/minecraft/world/entity/animal/Salmon.java b/net/minecraft/world/entity/animal/Salmon.java -index 41366f7b9af176a33b20ea26dd53d50994d2c600..5da2f14770aebb2286c3e8cbd9622a89a33e0e20 100644 +index 1786205346bb02835b10676155b65d2f11f0c221..25811130990e680174a0e930a6d066ad2d580f60 100644 --- a/net/minecraft/world/entity/animal/Salmon.java +++ b/net/minecraft/world/entity/animal/Salmon.java -@@ -35,6 +35,39 @@ public class Salmon extends AbstractSchoolingFish implements VariantHolder stack.is(ItemTags.SHEEP_FOOD), false)); diff --git a/net/minecraft/world/entity/animal/SnowGolem.java b/net/minecraft/world/entity/animal/SnowGolem.java -index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc28a54b98 100644 +index 7d73f02efb37aeafe41c23325a02d641d57bdaf4..ed7492af66a2ad678fe7a19f779ab7c4fb3dd8ae 100644 --- a/net/minecraft/world/entity/animal/SnowGolem.java +++ b/net/minecraft/world/entity/animal/SnowGolem.java -@@ -44,17 +44,63 @@ import net.minecraft.world.phys.Vec3; - public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob { +@@ -45,17 +45,63 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM private static final EntityDataAccessor DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE); private static final byte PUMPKIN_FLAG = 16; + private static final boolean DEFAULT_PUMPKIN = true; + @Nullable private java.util.UUID summoner; // Purpur - Summoner API public SnowGolem(EntityType entityType, Level level) { @@ -5754,19 +5685,18 @@ index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entity, level) -> entity instanceof Enemy)); } -@@ -72,6 +118,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -73,17 +119,19 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); compound.putBoolean("Pumpkin", this.hasPumpkin()); -+ if (getSummoner() != null) compound.putUUID("Purpur.Summoner", getSummoner()); // Purpur - Summoner API ++ compound.storeNullable("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC, getSummoner()); // Purpur - Summoner API } @Override -@@ -80,11 +127,12 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - if (compound.contains("Pumpkin")) { - this.setPumpkin(compound.getBoolean("Pumpkin")); - } -+ if (compound.contains("Purpur.Summoner")) setSummoner(compound.getUUID("Purpur.Summoner")); // Purpur - Summoner API + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.setPumpkin(compound.getBooleanOr("Pumpkin", true)); ++ this.setSummoner(compound.read("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC).orElse(null)); // Purpur - Summoner API } @Override @@ -5776,7 +5706,7 @@ index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc } @Override -@@ -95,10 +143,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -94,10 +142,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM this.hurtServer(serverLevel, this.damageSources().onFire().knownCause(org.bukkit.event.entity.EntityDamageEvent.DamageCause.MELTING), 1.0F); // CraftBukkit } @@ -5789,7 +5719,7 @@ index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc BlockState blockState = Blocks.SNOW.defaultBlockState(); for (int i = 0; i < 4; i++) { -@@ -141,7 +190,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -140,7 +189,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemInHand, hand, drops); if (event != null) { if (event.isCancelled()) { @@ -5798,7 +5728,7 @@ index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc } drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); // Paper end - custom shear drops -@@ -153,8 +202,16 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -152,8 +201,16 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM } return InteractionResult.SUCCESS; @@ -5817,7 +5747,7 @@ index 8a63b656b86b98f3756807498721d4daac5a38ef..eccf5f67bdacaf018e368843448754bc } diff --git a/net/minecraft/world/entity/animal/Squid.java b/net/minecraft/world/entity/animal/Squid.java -index 687ac3f50ed517a0b4df70c0c0a01215691ac718..0a103e6f3f6b0ec05c5d22b1258eb6e2f776e7dd 100644 +index 58e1bc90cbc32669fa6c66d214119f0c459ff38c..8371f3892e50150db018f0b265986ffab37f21e7 100644 --- a/net/minecraft/world/entity/animal/Squid.java +++ b/net/minecraft/world/entity/animal/Squid.java @@ -46,13 +46,77 @@ public class Squid extends AgeableWaterCreature { @@ -5902,12 +5832,12 @@ index 687ac3f50ed517a0b4df70c0c0a01215691ac718..0a103e6f3f6b0ec05c5d22b1258eb6e2 @@ -127,6 +191,7 @@ public class Squid extends AgeableWaterCreature { } - if (this.isInWaterOrBubble()) { + if (this.isInWater()) { + if (canFly()) setNoGravity(!wasTouchingWater); // Purpur - Flying squids! Oh my! if (this.tentacleMovement < (float) Math.PI) { float f = this.tentacleMovement / (float) Math.PI; this.tentacleAngle = Mth.sin(f * f * (float) Math.PI) * (float) Math.PI * 0.25F; -@@ -307,10 +372,41 @@ public class Squid extends AgeableWaterCreature { +@@ -305,10 +370,41 @@ public class Squid extends AgeableWaterCreature { @Override public void tick() { @@ -5951,10 +5881,10 @@ index 687ac3f50ed517a0b4df70c0c0a01215691ac718..0a103e6f3f6b0ec05c5d22b1258eb6e2 this.squid.movementVector = new Vec3(Mth.cos(f) * 0.2F, -0.1F + this.squid.getRandom().nextFloat() * 0.2F, Mth.sin(f) * 0.2F); } diff --git a/net/minecraft/world/entity/animal/TropicalFish.java b/net/minecraft/world/entity/animal/TropicalFish.java -index fa5f7f7d54083f9ea2095dd44362069d00e0b9a5..41074e7847583583331ef8d685a9f9b85ddf0243 100644 +index 89e14f04328995e6491c01321789be0bf9ddd438..f3c7e8b244eb7ba3d99cc0d29e388bab8e743351 100644 --- a/net/minecraft/world/entity/animal/TropicalFish.java +++ b/net/minecraft/world/entity/animal/TropicalFish.java -@@ -67,6 +67,39 @@ public class TropicalFish extends AbstractSchoolingFish implements VariantHolder +@@ -76,6 +76,39 @@ public class TropicalFish extends AbstractSchoolingFish { super(entityType, level); } @@ -5995,10 +5925,10 @@ index fa5f7f7d54083f9ea2095dd44362069d00e0b9a5..41074e7847583583331ef8d685a9f9b8 return "entity.minecraft.tropical_fish.predefined." + variantId; } diff --git a/net/minecraft/world/entity/animal/Turtle.java b/net/minecraft/world/entity/animal/Turtle.java -index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625be690e68 100644 +index d24ddf8a585395c0f7b1cd5a61aaea0516636d93..c84f63f064a7769761f75cdedaceacde858b9b4e 100644 --- a/net/minecraft/world/entity/animal/Turtle.java +++ b/net/minecraft/world/entity/animal/Turtle.java -@@ -84,6 +84,52 @@ public class Turtle extends Animal { +@@ -85,6 +85,52 @@ public class Turtle extends Animal { this.moveControl = new Turtle.TurtleMoveControl(this); } @@ -6049,9 +5979,9 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 + // Purpur end - Mobs always drop experience + public void setHomePos(BlockPos homePos) { - this.entityData.set(HOME_POS, homePos); + this.homePos = homePos; } -@@ -188,6 +234,7 @@ public class Turtle extends Animal { +@@ -144,6 +190,7 @@ public class Turtle extends Animal { @Override protected void registerGoals() { @@ -6059,7 +5989,7 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2)); this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0)); this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0)); -@@ -368,8 +415,10 @@ public class Turtle extends Animal { +@@ -324,8 +371,10 @@ public class Turtle extends Animal { } this.turtle.setHasEgg(true); @@ -6072,7 +6002,7 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 this.animal.resetLove(); this.partner.resetLove(); RandomSource random = this.animal.getRandom(); -@@ -539,12 +588,14 @@ public class Turtle extends Animal { +@@ -492,12 +541,14 @@ public class Turtle extends Animal { } } @@ -6088,7 +6018,7 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 } private void updateSpeed() { -@@ -563,7 +614,7 @@ public class Turtle extends Animal { +@@ -516,7 +567,7 @@ public class Turtle extends Animal { } @Override @@ -6097,7 +6027,7 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 this.updateSpeed(); if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { double d = this.wantedX - this.turtle.getX(); -@@ -577,7 +628,7 @@ public class Turtle extends Animal { +@@ -530,7 +581,7 @@ public class Turtle extends Animal { float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F; this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F)); this.turtle.yBodyRot = this.turtle.getYRot(); @@ -6106,238 +6036,11 @@ index 0e2d2dd3f2ef2783f3773a9a05c4f718991f7784..10477fea8fcd70bf0c1ba4b6e1113625 this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1)); this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, this.turtle.getSpeed() * d1 * 0.1, 0.0)); } -diff --git a/net/minecraft/world/entity/animal/Wolf.java b/net/minecraft/world/entity/animal/Wolf.java -index 133e14efb19f8984061b8cb5922aa4f0c7aaf4d9..7cb292de6b27fa4ba3c5fce526a4e939c576789f 100644 ---- a/net/minecraft/world/entity/animal/Wolf.java -+++ b/net/minecraft/world/entity/animal/Wolf.java -@@ -94,6 +94,37 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder type = entity.getType(); - return type == EntityType.SHEEP || type == EntityType.RABBIT || type == EntityType.FOX; - }; -+ // Purpur start - Configurable chance for wolves to spawn rabid -+ private boolean isRabid = false; -+ private static final TargetingConditions.Selector RABID_PREDICATE = (entity, ignored) -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof net.minecraft.world.entity.Mob; -+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR); -+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE); -+ private static final class AvoidRabidWolfGoal extends AvoidEntityGoal { -+ private final Wolf wolf; -+ -+ public AvoidRabidWolfGoal(Wolf wolf, float distance, double minSpeed, double maxSpeed) { -+ super(wolf, Wolf.class, distance, minSpeed, maxSpeed); -+ this.wolf = wolf; -+ } -+ -+ @Override -+ public boolean canUse() { -+ return super.canUse() && !this.wolf.isRabid() && this.toAvoid != null && this.toAvoid.isRabid(); // wolves which are not rabid run away from rabid wolves -+ } -+ -+ @Override -+ public void start() { -+ this.wolf.setTarget(null); -+ super.start(); -+ } -+ -+ @Override -+ public void tick() { -+ this.wolf.setTarget(null); -+ super.tick(); -+ } -+ } -+ // Purpur end - Configurable chance for wolves to spawn rabid - private static final float START_HEALTH = 8.0F; - private static final float TAME_HEALTH = 40.0F; - private static final float ARMOR_REPAIR_UNIT = 0.125F; -@@ -115,12 +146,99 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder(this, Llama.class, 24.0F, 1.5, 1.5)); -+ this.goalSelector.addGoal(3, new AvoidRabidWolfGoal(this, 24.0F, 1.5D, 1.5D)); // Purpur - Configurable chance for wolves to spawn rabid - this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F)); - this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, true)); - this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 2.0F)); -@@ -129,11 +247,12 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder(this, Player.class, 10, true, false, this::isAngryAt)); -- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); -+ // this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); // Purpur - Configurable chance for wolves to spawn rabid - moved to updatePathfinders() - this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); - this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false)); - this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true)); -@@ -182,6 +301,7 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder compound.putString("variant", resourceKey.location().toString())); - this.addPersistentAngerSaveData(compound); - } -@@ -196,6 +316,10 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.wolfNaturalRabid; -+ this.updatePathfinders(false); -+ // Purpur end - Configurable chance for wolves to spawn rabid - return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData); - } - -@@ -263,6 +391,11 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder brainProvider() { return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -@@ -244,6 +287,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS +@@ -240,6 +283,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS private int behaviorTick = 0; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -6408,10 +6111,10 @@ index 8f1d66d005413fe4eadb993b61568fa84336345a..10d2a1138d814b83ce4233205a7f0ab2 this.getBrain().tick(level, this); AllayAi.updateActivity(this); diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index 86e78ce740b27f9714145a690e8b182a2ccb3fb9..a24ed1747fb8836927ac41b822dc666862701516 100644 +index 657f4b56699c33590a0494ef860275e952794c2a..aea96e036846c66d411fdea55fbbf0efb60d467d 100644 --- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java +++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -@@ -78,6 +78,38 @@ public class Armadillo extends Animal { +@@ -79,6 +79,38 @@ public class Armadillo extends Animal { return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 12.0).add(Attributes.MOVEMENT_SPEED, 0.14); } @@ -6451,10 +6154,10 @@ index 86e78ce740b27f9714145a690e8b182a2ccb3fb9..a24ed1747fb8836927ac41b822dc6668 protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java -index 4fb36e2a6d71b79219e10f5089eb0daebf830ee7..1323cedcacd3072cdf5f1eac644688cd098b53db 100644 +index f54b854adedd58a37b5c38c63abc3fc94ed9ba80..de207d747026453fabe2e6e725d2aa8504fbc9a1 100644 --- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java +++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java -@@ -113,6 +113,52 @@ public class Axolotl extends Animal implements VariantHolder, B +@@ -118,6 +118,52 @@ public class Axolotl extends Animal implements Bucketable { this.lookControl = new Axolotl.AxolotlLookControl(this, 20); } @@ -6507,7 +6210,7 @@ index 4fb36e2a6d71b79219e10f5089eb0daebf830ee7..1323cedcacd3072cdf5f1eac644688cd @Override public float getWalkTargetValue(BlockPos pos, LevelReader level) { return 0.0F; -@@ -301,6 +347,7 @@ public class Axolotl extends Animal implements VariantHolder, B +@@ -326,6 +372,7 @@ public class Axolotl extends Animal implements Bucketable { private int behaviorTick = 0; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -6515,7 +6218,7 @@ index 4fb36e2a6d71b79219e10f5089eb0daebf830ee7..1323cedcacd3072cdf5f1eac644688cd if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish this.getBrain().tick(level, this); AxolotlAi.updateActivity(this); -@@ -550,23 +597,31 @@ public class Axolotl extends Animal implements VariantHolder, B +@@ -573,23 +620,31 @@ public class Axolotl extends Animal implements Bucketable { } @Override @@ -6550,10 +6253,10 @@ index 4fb36e2a6d71b79219e10f5089eb0daebf830ee7..1323cedcacd3072cdf5f1eac644688cd super.tick(); } diff --git a/net/minecraft/world/entity/animal/camel/Camel.java b/net/minecraft/world/entity/animal/camel/Camel.java -index 1ac4b13554d2699c3e04d41946e1adfd5e854a17..64ff0d2923f16a567aa753cad028a1b21c20101b 100644 +index b63b32bac1872db7be64fcb645acd0a0a4290cee..101931ff4474ab4445be3fa1a241a731ad3ac1da 100644 --- a/net/minecraft/world/entity/animal/camel/Camel.java +++ b/net/minecraft/world/entity/animal/camel/Camel.java -@@ -81,6 +81,20 @@ public class Camel extends AbstractHorse { +@@ -87,6 +87,20 @@ public class Camel extends AbstractHorse { groundPathNavigation.setCanWalkOverFences(true); } @@ -6574,7 +6277,7 @@ index 1ac4b13554d2699c3e04d41946e1adfd5e854a17..64ff0d2923f16a567aa753cad028a1b2 @Override public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); -@@ -308,6 +322,23 @@ public class Camel extends AbstractHorse { +@@ -320,6 +334,23 @@ public class Camel extends AbstractHorse { return this.dashCooldown; } @@ -6596,13 +6299,13 @@ index 1ac4b13554d2699c3e04d41946e1adfd5e854a17..64ff0d2923f16a567aa753cad028a1b2 + // Purpur end - Configurable entity base attributes + @Override - protected SoundEvent getAmbientSound() { + public SoundEvent getAmbientSound() { return SoundEvents.CAMEL_AMBIENT; diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java -index 10a0779bf8611ade19e64031bb00beb277e98598..aca0877319d507c3a672589bd4de5268d7a4c3dc 100644 +index bd80e58179fe577693fa419a77989b0db39abb04..89fa6a785ff73b30effd58dde4fbcbf99fdad168 100644 --- a/net/minecraft/world/entity/animal/frog/Frog.java +++ b/net/minecraft/world/entity/animal/frog/Frog.java -@@ -104,6 +104,8 @@ public class Frog extends Animal implements VariantHolder> { +@@ -103,6 +103,8 @@ public class Frog extends Animal { public final AnimationState croakAnimationState = new AnimationState(); public final AnimationState tongueAnimationState = new AnimationState(); public final AnimationState swimIdleAnimationState = new AnimationState(); @@ -6611,7 +6314,7 @@ index 10a0779bf8611ade19e64031bb00beb277e98598..aca0877319d507c3a672589bd4de5268 public Frog(EntityType entityType, Level level) { super(entityType, level); -@@ -111,7 +113,62 @@ public class Frog extends Animal implements VariantHolder> { +@@ -110,7 +112,62 @@ public class Frog extends Animal { this.setPathfindingMalus(PathType.WATER, 4.0F); this.setPathfindingMalus(PathType.TRAPDOOR, -1.0F); this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); @@ -6674,7 +6377,7 @@ index 10a0779bf8611ade19e64031bb00beb277e98598..aca0877319d507c3a672589bd4de5268 @Override protected Brain.Provider brainProvider() { -@@ -185,6 +242,7 @@ public class Frog extends Animal implements VariantHolder> { +@@ -202,6 +259,7 @@ public class Frog extends Animal { private int behaviorTick = 0; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -6682,7 +6385,7 @@ index 10a0779bf8611ade19e64031bb00beb277e98598..aca0877319d507c3a672589bd4de5268 if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish this.getBrain().tick(level, this); FrogAi.updateActivity(this); -@@ -375,7 +433,7 @@ public class Frog extends Animal implements VariantHolder> { +@@ -384,7 +442,7 @@ public class Frog extends Animal { return level.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); } @@ -6692,10 +6395,10 @@ index 10a0779bf8611ade19e64031bb00beb277e98598..aca0877319d507c3a672589bd4de5268 super(mob); } diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java -index 77691e10f7c511eca4384f2974e538d78d55c2ca..0ca35514a920dddf230d749bc1a5fe15f1c7940a 100644 +index 72c4403a4b5fa817f91dbcd842d4b7939a4834ab..a445bbe84d919ffadd8f3f0006b12140cd8060fd 100644 --- a/net/minecraft/world/entity/animal/frog/Tadpole.java +++ b/net/minecraft/world/entity/animal/frog/Tadpole.java -@@ -61,13 +61,50 @@ public class Tadpole extends AbstractFish { +@@ -62,13 +62,50 @@ public class Tadpole extends AbstractFish { MemoryModuleType.IS_PANICKING ); public boolean ageLocked; // Paper @@ -6747,7 +6450,7 @@ index 77691e10f7c511eca4384f2974e538d78d55c2ca..0ca35514a920dddf230d749bc1a5fe15 @Override protected PathNavigation createNavigation(Level level) { return new WaterBoundPathNavigation(this, level); -@@ -96,6 +133,7 @@ public class Tadpole extends AbstractFish { +@@ -97,6 +134,7 @@ public class Tadpole extends AbstractFish { private int behaviorTick = 0; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -6756,10 +6459,10 @@ index 77691e10f7c511eca4384f2974e538d78d55c2ca..0ca35514a920dddf230d749bc1a5fe15 this.getBrain().tick(level, this); TadpoleAi.updateActivity(this); diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java -index dde7f05b8664d9a60edc716a370917d6cab03c18..35d1b99b873d9f8c9aa2a1178a449a8625b18406 100644 +index 048e62b361e33b3edd5122fd4a47c5627491bcaf..40ba2e6dc6b1efbd17dba582561c133f6b41df25 100644 --- a/net/minecraft/world/entity/animal/goat/Goat.java +++ b/net/minecraft/world/entity/animal/goat/Goat.java -@@ -109,6 +109,44 @@ public class Goat extends Animal { +@@ -112,6 +112,44 @@ public class Goat extends Animal { .orElseGet(() -> new ItemStack(Items.GOAT_HORN)); } @@ -6804,7 +6507,7 @@ index dde7f05b8664d9a60edc716a370917d6cab03c18..35d1b99b873d9f8c9aa2a1178a449a86 @Override protected Brain.Provider brainProvider() { return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -@@ -185,6 +223,7 @@ public class Goat extends Animal { +@@ -188,6 +226,7 @@ public class Goat extends Animal { private int behaviorTick = 0; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -6812,7 +6515,7 @@ index dde7f05b8664d9a60edc716a370917d6cab03c18..35d1b99b873d9f8c9aa2a1178a449a86 if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish this.getBrain().tick(level, this); GoatAi.updateActivity(this); -@@ -387,6 +426,7 @@ public class Goat extends Animal { +@@ -390,6 +429,7 @@ public class Goat extends Animal { // Paper start - Goat ram API public void ram(net.minecraft.world.entity.LivingEntity entity) { @@ -6821,10 +6524,10 @@ index dde7f05b8664d9a60edc716a370917d6cab03c18..35d1b99b873d9f8c9aa2a1178a449a86 brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position()); brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS); diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index d52a8315f1e6876c26c732f4c4caa47bc6bebf6e..56dc7011ed07f0bd5870fbadde2b5c0c630c5edd 100644 +index 7c473eea481f5e055cc70512027726f41f0c6f67..601e2912790759487c8d2f270f30a82689c52236 100644 --- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -206,11 +206,61 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -126,11 +126,61 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory protected AbstractHorse(EntityType entityType, Level level) { super(entityType, level); @@ -6886,7 +6589,7 @@ index d52a8315f1e6876c26c732f4c4caa47bc6bebf6e..56dc7011ed07f0bd5870fbadde2b5c0c this.goalSelector.addGoal(1, new PanicGoal(this, 1.2)); this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2)); this.goalSelector.addGoal(2, new BreedGoal(this, 1.0, AbstractHorse.class)); -@@ -221,6 +271,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -141,6 +191,7 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory if (this.canPerformRearing()) { this.goalSelector.addGoal(9, new RandomStandGoal(this)); } @@ -6894,7 +6597,7 @@ index d52a8315f1e6876c26c732f4c4caa47bc6bebf6e..56dc7011ed07f0bd5870fbadde2b5c0c this.addBehaviourGoals(); } -@@ -1207,7 +1258,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -1043,7 +1094,7 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory spawnGroupData = new AgeableMob.AgeableMobGroupData(0.2F); } @@ -6904,7 +6607,7 @@ index d52a8315f1e6876c26c732f4c4caa47bc6bebf6e..56dc7011ed07f0bd5870fbadde2b5c0c } diff --git a/net/minecraft/world/entity/animal/horse/Donkey.java b/net/minecraft/world/entity/animal/horse/Donkey.java -index 9b97f3d3675f5051b18a68ff7fa056d859a283e9..3e0181578a6f2d22d1da3776abf30bf97d124620 100644 +index 5dff98b5b2e4bba5f874d6a99d034a3905775c9b..0783d41a6c4622b03d9d368c1af949af1292dcb7 100644 --- a/net/minecraft/world/entity/animal/horse/Donkey.java +++ b/net/minecraft/world/entity/animal/horse/Donkey.java @@ -16,6 +16,51 @@ public class Donkey extends AbstractChestedHorse { @@ -6957,13 +6660,13 @@ index 9b97f3d3675f5051b18a68ff7fa056d859a283e9..3e0181578a6f2d22d1da3776abf30bf9 + // Purpur end - Mobs always drop experience + @Override - protected SoundEvent getAmbientSound() { + public SoundEvent getAmbientSound() { return SoundEvents.DONKEY_AMBIENT; diff --git a/net/minecraft/world/entity/animal/horse/Horse.java b/net/minecraft/world/entity/animal/horse/Horse.java -index c6d0700f29d6c8123e96efe225faf2d99202ac81..be0d636ca894c5995f28f59c196cd8e56dd228c4 100644 +index a0d85cd6c5306385b074a636166ff8eee2b320ce..206f911d1184a22f401d217f713495e6e85263be 100644 --- a/net/minecraft/world/entity/animal/horse/Horse.java +++ b/net/minecraft/world/entity/animal/horse/Horse.java -@@ -43,6 +43,51 @@ public class Horse extends AbstractHorse implements VariantHolder { +@@ -46,6 +46,51 @@ public class Horse extends AbstractHorse { super(entityType, level); } @@ -7016,10 +6719,10 @@ index c6d0700f29d6c8123e96efe225faf2d99202ac81..be0d636ca894c5995f28f59c196cd8e5 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 58bb056ce934c793b16e63e44a4029be955c7caa..c21d558a6a3a61d6c54b8163f8cb4963846b2c26 100644 +index 6916adb865ff8fea498d3a61c2b5560472a223f4..e300a1284fd98791871ba1780bb7352cd848766a 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -72,12 +72,95 @@ public class Llama extends AbstractChestedHorse implements VariantHolder stack.is(ItemTags.SHEEP_FOOD), false)); diff --git a/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/net/minecraft/world/entity/animal/sniffer/Sniffer.java -index 5f0efcfb88bee09f1cccc53cedbef22b14c5f554..68751f7ed123c3e99f56259ccc23121661f89bc1 100644 +index 622c2eac70c81ed7ccf605069b8dd68508bebf76..0565b37dd5320b49efb11cf28f064d6a970048aa 100644 --- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java +++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java @@ -86,6 +86,38 @@ public class Sniffer extends Animal { @@ -7464,6 +7229,233 @@ index 5f0efcfb88bee09f1cccc53cedbef22b14c5f554..68751f7ed123c3e99f56259ccc231216 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); +diff --git a/net/minecraft/world/entity/animal/wolf/Wolf.java b/net/minecraft/world/entity/animal/wolf/Wolf.java +index d926ecd041ca2a421057bc22efe66a8b811ee649..936ee9e80239ad965be75ceeb38d5248243e9c4e 100644 +--- a/net/minecraft/world/entity/animal/wolf/Wolf.java ++++ b/net/minecraft/world/entity/animal/wolf/Wolf.java +@@ -100,6 +100,37 @@ public class Wolf extends TamableAnimal implements NeutralMob { + EntityType type = entity.getType(); + return type == EntityType.SHEEP || type == EntityType.RABBIT || type == EntityType.FOX; + }; ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ private boolean isRabid = false; ++ private static final TargetingConditions.Selector RABID_PREDICATE = (entity, ignored) -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof net.minecraft.world.entity.Mob; ++ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR); ++ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE); ++ private static final class AvoidRabidWolfGoal extends AvoidEntityGoal { ++ private final Wolf wolf; ++ ++ public AvoidRabidWolfGoal(Wolf wolf, float distance, double minSpeed, double maxSpeed) { ++ super(wolf, Wolf.class, distance, minSpeed, maxSpeed); ++ this.wolf = wolf; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && !this.wolf.isRabid() && this.toAvoid != null && this.toAvoid.isRabid(); // wolves which are not rabid run away from rabid wolves ++ } ++ ++ @Override ++ public void start() { ++ this.wolf.setTarget(null); ++ super.start(); ++ } ++ ++ @Override ++ public void tick() { ++ this.wolf.setTarget(null); ++ super.tick(); ++ } ++ } ++ // Purpur end - Configurable chance for wolves to spawn rabid + private static final float START_HEALTH = 8.0F; + private static final float TAME_HEALTH = 40.0F; + private static final float ARMOR_REPAIR_UNIT = 0.125F; +@@ -122,12 +153,99 @@ public class Wolf extends TamableAnimal implements NeutralMob { + this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F); + } + ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ public boolean isRabid() { ++ return this.isRabid; ++ } ++ ++ public void setRabid(boolean isRabid) { ++ this.isRabid = isRabid; ++ updatePathfinders(true); ++ } ++ ++ public void updatePathfinders(boolean modifyEffects) { ++ this.targetSelector.removeGoal(PATHFINDER_VANILLA); ++ this.targetSelector.removeGoal(PATHFINDER_RABID); ++ if (this.isRabid) { ++ this.setOwnerReference(null); ++ setTame(false, true); ++ this.targetSelector.addGoal(5, PATHFINDER_RABID); ++ if (modifyEffects) this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.NAUSEA, 1200)); ++ } else { ++ this.targetSelector.addGoal(5, PATHFINDER_VANILLA); ++ this.stopBeingAngry(); ++ if (modifyEffects) this.removeEffect(net.minecraft.world.effect.MobEffects.NAUSEA); ++ } ++ } ++ // Purpur end - Configurable chance for wolves to spawn rabid ++ ++ // Purpur start - Configurable default collar color ++ @Override ++ public void tame(Player player) { ++ setCollarColor(level().purpurConfig.wolfDefaultCollarColor); ++ super.tame(player); ++ } ++ // Purpur end - Configurable default collar color ++ ++ // Purpur start - Ridables ++ @Override ++ public boolean isRidable() { ++ return level().purpurConfig.wolfRidable; ++ } ++ ++ @Override ++ public boolean dismountsUnderwater() { ++ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.wolfRidableInWater; ++ } ++ ++ public void onMount(Player rider) { ++ super.onMount(rider); ++ setInSittingPose(false); ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level().purpurConfig.wolfControllable; ++ } ++ // Purpur end - Ridables ++ ++ // Purpur start - Configurable entity base attributes ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.wolfMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.wolfScale); ++ } ++ // Purpur end - Configurable entity base attributes ++ ++ // Purpur start - Make entity breeding times configurable ++ @Override ++ public int getPurpurBreedTime() { ++ return this.level().purpurConfig.wolfBreedingTicks; ++ } ++ // Purpur end - Make entity breeding times configurable ++ ++ // Purpur start - Toggle for water sensitive mob damage ++ @Override ++ public boolean isSensitiveToWater() { ++ return this.level().purpurConfig.wolfTakeDamageFromWater; ++ } ++ // Purpur end - Toggle for water sensitive mob damage ++ ++ // Purpur start - Mobs always drop experience ++ @Override ++ protected boolean isAlwaysExperienceDropper() { ++ return this.level().purpurConfig.wolfAlwaysDropExp; ++ } ++ // Purpur end - Mobs always drop experience ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables + this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5, DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5, 1.5)); ++ this.goalSelector.addGoal(3, new AvoidRabidWolfGoal(this, 24.0F, 1.5D, 1.5D)); // Purpur - Configurable chance for wolves to spawn rabid + this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F)); + this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, true)); + this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 2.0F)); +@@ -136,11 +254,12 @@ 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 - Ridables + this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); + this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); + this.targetSelector.addGoal(3, new HurtByTargetGoal(this).setAlertOthers()); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); ++ //this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); // Purpur - Configurable chance for wolves to spawn rabid - moved to updatePathfinders() + this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); + this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false)); + this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true)); +@@ -231,6 +350,7 @@ public class Wolf extends TamableAnimal implements NeutralMob { + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + compound.store("CollarColor", DyeColor.LEGACY_ID_CODEC, this.getCollarColor()); ++ compound.putBoolean("Purpur.IsRabid", this.isRabid); // Purpur - Configurable chance for wolves to spawn rabid + VariantUtils.writeVariant(compound, this.getVariant()); + this.addPersistentAngerSaveData(compound); + this.getSoundVariant() +@@ -245,6 +365,10 @@ public class Wolf extends TamableAnimal implements NeutralMob { + super.readAdditionalSaveData(compound); + VariantUtils.readVariant(compound, this.registryAccess(), Registries.WOLF_VARIANT).ifPresent(this::setVariant); + this.setCollarColor(compound.read("CollarColor", DyeColor.LEGACY_ID_CODEC).orElse(DEFAULT_COLLAR_COLOR)); ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ this.isRabid = compound.getBooleanOr("Purpur.IsRabid", false); ++ this.updatePathfinders(false); ++ // Purpur end - Configurable chance for wolves to spawn rabid + this.readPersistentAngerSaveData(this.level(), compound); + compound.read("sound_variant", ResourceKey.codec(Registries.WOLF_SOUND_VARIANT)) + .flatMap(resourceKey -> this.registryAccess().lookupOrThrow(Registries.WOLF_SOUND_VARIANT).get((ResourceKey)resourceKey)) +@@ -269,6 +393,10 @@ public class Wolf extends TamableAnimal implements NeutralMob { + } + + this.setSoundVariant(WolfSoundVariants.pickRandomSoundVariant(this.registryAccess(), this.random)); ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ this.isRabid = level.getLevel().purpurConfig.wolfNaturalRabid > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.wolfNaturalRabid; ++ this.updatePathfinders(false); ++ // Purpur end - Configurable chance for wolves to spawn rabid + return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData); + } + +@@ -319,6 +447,11 @@ public class Wolf extends TamableAnimal implements NeutralMob { + public void tick() { + super.tick(); + if (this.isAlive()) { ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ if (this.age % 300 == 0 && this.isRabid()) { ++ this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.NAUSEA, 400)); ++ } ++ // Purpur end - Configurable chance for wolves to spawn rabid + this.interestedAngleO = this.interestedAngle; + if (this.isInterested()) { + this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F; +@@ -532,13 +665,27 @@ public class Wolf extends TamableAnimal implements NeutralMob { + itemInHand.consume(1, player); + this.tryToTame(player); + return InteractionResult.SUCCESS_SERVER; ++ // Purpur start - Configurable chance for wolves to spawn rabid ++ } else if (this.level().purpurConfig.wolfMilkCuresRabies && itemInHand.getItem() == Items.MILK_BUCKET && this.isRabid()) { ++ if (!player.isCreative()) { ++ player.setItemInHand(hand, new ItemStack(Items.BUCKET)); ++ } ++ this.setRabid(false); ++ for (int i = 0; i < 10; ++i) { ++ ((ServerLevel) level()).sendParticlesSource(((ServerLevel) level()).players(), null, ParticleTypes.HAPPY_VILLAGER, ++ false, true, ++ getX() + random.nextFloat(), getY() + (random.nextFloat() * 1.5), getZ() + random.nextFloat(), 1, ++ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0); ++ } ++ return InteractionResult.SUCCESS_SERVER; ++ // Purpur end - Configurable chance for wolves to spawn rabid + } + + return super.mobInteract(player, hand); + } + + private void tryToTame(Player player) { +- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check. ++ if (((this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials()) || this.random.nextInt(3) == 0) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check. // Purpur - Config to always tame in Creative + this.tame(player); + this.navigation.stop(); + this.setTarget(null); diff --git a/net/minecraft/world/entity/boss/EnderDragonPart.java b/net/minecraft/world/entity/boss/EnderDragonPart.java index 31f064267514e590944ad809c95915b481e65aaa..c8bc09c3fe27e69360027698c41fd51a111ffa66 100644 --- a/net/minecraft/world/entity/boss/EnderDragonPart.java @@ -7483,11 +7475,11 @@ index 31f064267514e590944ad809c95915b481e65aaa..c8bc09c3fe27e69360027698c41fd51a protected void defineSynchedData(SynchedEntityData.Builder builder) { } diff --git a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index ff1c84d37db48e1bd0283a900e199647c0e8eba1..d58829c88b86358a0c06a982b302fc9a31c15853 100644 +index d813427cf20117014bc42af0eb7cdee037fbcd9c..90ac1e4bdca5b6233eeae9bc84549770bed383da 100644 --- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java @@ -26,6 +26,12 @@ public class EndCrystal extends Entity { - private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + private static final boolean DEFAULT_SHOW_BOTTOM = true; public int time; public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms @@ -7576,7 +7568,7 @@ index ff1c84d37db48e1bd0283a900e199647c0e8eba1..d58829c88b86358a0c06a982b302fc9a } @Override -@@ -119,15 +188,17 @@ public class EndCrystal extends Entity { +@@ -114,15 +183,17 @@ public class EndCrystal extends Entity { } // CraftBukkit end if (!damageSource.is(DamageTypeTags.IS_EXPLOSION)) { @@ -7597,10 +7589,10 @@ index ff1c84d37db48e1bd0283a900e199647c0e8eba1..d58829c88b86358a0c06a982b302fc9a this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // Paper - add Bukkit remove cause // CraftBukkit end diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4d9c8a789 100644 +index 0f3c88601357399d3b8efd2f0e3a531482bc1f3d..b782ddd14d68717c387754300fc1be69d05df66f 100644 --- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -90,6 +90,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -91,6 +91,7 @@ public class EnderDragon extends Mob implements Enemy { private final net.minecraft.world.level.Explosion explosionSource; // Paper - reusable source for CraftTNTPrimed.getSource() @Nullable private BlockPos podium; // Paper end @@ -7608,7 +7600,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 public EnderDragon(EntityType entityType, Level level) { super(EntityType.ENDER_DRAGON, level); -@@ -106,6 +107,37 @@ public class EnderDragon extends Mob implements Enemy { +@@ -107,6 +108,37 @@ public class EnderDragon extends Mob implements Enemy { this.noPhysics = true; this.phaseManager = new EnderDragonPhaseManager(this); this.explosionSource = new net.minecraft.world.level.ServerExplosion(level.getMinecraftWorld(), this, null, null, new Vec3(Double.NaN, Double.NaN, Double.NaN), Float.NaN, true, net.minecraft.world.level.Explosion.BlockInteraction.DESTROY); // Paper @@ -7646,7 +7638,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 } public void setDragonFight(EndDragonFight dragonFight) { -@@ -120,6 +152,31 @@ public class EnderDragon extends Mob implements Enemy { +@@ -121,6 +153,31 @@ public class EnderDragon extends Mob implements Enemy { return this.fightOrigin; } @@ -7678,7 +7670,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 public static AttributeSupplier.Builder createAttributes() { return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0); } -@@ -169,6 +226,37 @@ public class EnderDragon extends Mob implements Enemy { +@@ -170,6 +227,37 @@ public class EnderDragon extends Mob implements Enemy { @Override public void aiStep() { @@ -7716,7 +7708,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 this.processFlappingMovement(); if (this.level().isClientSide) { this.setHealth(this.getHealth()); -@@ -197,6 +285,8 @@ public class EnderDragon extends Mob implements Enemy { +@@ -198,6 +286,8 @@ public class EnderDragon extends Mob implements Enemy { this.oFlapTime = this.flapTime; if (this.isDeadOrDying()) { @@ -7725,7 +7717,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 float f = (this.random.nextFloat() - 0.5F) * 8.0F; float f1 = (this.random.nextFloat() - 0.5F) * 4.0F; float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; -@@ -206,9 +296,9 @@ public class EnderDragon extends Mob implements Enemy { +@@ -207,9 +297,9 @@ public class EnderDragon extends Mob implements Enemy { Vec3 deltaMovement = this.getDeltaMovement(); float f1 = 0.2F / ((float)deltaMovement.horizontalDistance() * 10.0F + 1.0F); f1 *= (float)Math.pow(2.0, deltaMovement.y); @@ -7737,7 +7729,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 this.flapTime += f1 * 0.5F; } else { this.flapTime += f1; -@@ -219,7 +309,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -220,7 +310,7 @@ public class EnderDragon extends Mob implements Enemy { this.flapTime = 0.5F; } else { this.flightHistory.record(this.getY(), this.getYRot()); @@ -7746,7 +7738,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 DragonPhaseInstance currentPhase = this.phaseManager.getCurrentPhase(); currentPhase.doServerTick(serverLevel1); if (this.phaseManager.getCurrentPhase() != currentPhase) { -@@ -298,7 +388,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -295,7 +385,7 @@ public class EnderDragon extends Mob implements Enemy { this.tickPart(this.body, sin1 * 0.5F, 0.0, -cos1 * 0.5F); this.tickPart(this.wing1, cos1 * 4.5F, 2.0, sin1 * 4.5F); this.tickPart(this.wing2, cos1 * -4.5F, 2.0, sin1 * -4.5F); @@ -7755,7 +7747,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 this.knockBack( serverLevel2, serverLevel2.getEntities( -@@ -348,9 +438,9 @@ public class EnderDragon extends Mob implements Enemy { +@@ -345,9 +435,9 @@ public class EnderDragon extends Mob implements Enemy { } if (this.level() instanceof ServerLevel serverLevel3) { @@ -7767,7 +7759,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 if (this.dragonFight != null) { this.dragonFight.updateDragon(this); } -@@ -464,7 +554,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -460,7 +550,7 @@ public class EnderDragon extends Mob implements Enemy { BlockPos blockPos = new BlockPos(i, i1, i2); BlockState blockState = level.getBlockState(blockPos); if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) { @@ -7776,7 +7768,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 // CraftBukkit start - Add blocks to list rather than destroying them //flag1 = level.removeBlock(blockPos, false) || flag1; flag1 = true; -@@ -974,6 +1064,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -960,6 +1050,7 @@ public class EnderDragon extends Mob implements Enemy { @Override protected boolean canRide(Entity entity) { @@ -7784,7 +7776,7 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 return false; } -@@ -999,7 +1090,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -985,7 +1076,7 @@ public class EnderDragon extends Mob implements Enemy { @Override protected float sanitizeScale(float scale) { @@ -7793,8 +7785,8 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 } // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. -@@ -1009,7 +1100,7 @@ public class EnderDragon extends Mob implements Enemy { - boolean flag = worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); +@@ -995,7 +1086,7 @@ public class EnderDragon extends Mob implements Enemy { + boolean flag = level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); int i = 500; - if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { @@ -7803,10 +7795,10 @@ index 403bcd056bf9c385599383983bf7a0cc117a1881..b2a0ba6faa117ad781aaa3e6932482d4 } diff --git a/net/minecraft/world/entity/boss/wither/WitherBoss.java b/net/minecraft/world/entity/boss/wither/WitherBoss.java -index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b16203e3fd90 100644 +index 09924cccf9208abda22cc7e1635b567ed166e95a..bbcb03548052b28bd622d7d8ce161ccaed1ed386 100644 --- a/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -69,6 +69,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -70,6 +70,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { private final int[] nextHeadUpdate = new int[2]; private final int[] idleHeadUpdates = new int[2]; private int destroyBlocksTick; @@ -7814,7 +7806,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 private boolean canPortal = false; // Paper public final ServerBossEvent bossEvent = (ServerBossEvent)new ServerBossEvent( this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS -@@ -77,14 +78,161 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -78,14 +79,161 @@ public class WitherBoss extends Monster implements RangedAttackMob { private static final TargetingConditions.Selector LIVING_ENTITY_SELECTOR = (entity, level) -> !entity.getType().is(EntityTypeTags.WITHER_FRIENDS) && entity.attackable(); private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0).selector(LIVING_ENTITY_SELECTOR); @@ -7976,7 +7968,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 @Override protected PathNavigation createNavigation(Level level) { FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level); -@@ -95,11 +243,13 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -96,11 +244,13 @@ public class WitherBoss extends Monster implements RangedAttackMob { @Override protected void registerGoals() { @@ -7990,23 +7982,23 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, LIVING_ENTITY_SELECTOR)); } -@@ -117,6 +267,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -118,6 +268,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); compound.putInt("Invul", this.getInvulnerableTicks()); -+ if (getSummoner() != null) compound.putUUID("Purpur.Summoner", getSummoner()); // Purpur - Summoner API ++ compound.storeNullable("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC, getSummoner()); // Purpur - Summoner API } @Override -@@ -126,6 +277,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -127,6 +278,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { if (this.hasCustomName()) { this.bossEvent.setName(this.getDisplayName()); } -+ if (compound.contains("Purpur.Summoner")) setSummoner(compound.getUUID("Purpur.Summoner")); // Purpur - Summoner API ++ this.setSummoner(compound.read("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC).orElse(null)); // Purpur - Summoner API } @Override -@@ -257,6 +409,15 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -258,6 +410,15 @@ public class WitherBoss extends Monster implements RangedAttackMob { @Override protected void customServerAiStep(ServerLevel level) { @@ -8022,7 +8014,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 if (this.getInvulnerableTicks() > 0) { int i = this.getInvulnerableTicks() - 1; this.bossEvent.setProgress(1.0F - i / 220.0F); -@@ -269,7 +430,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -270,7 +431,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { level.explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); } // CraftBukkit end @@ -8031,7 +8023,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 // CraftBukkit start - Use relative location for far away sounds // level.globalLevelEvent(1023, this.blockPosition(), 0); int viewDistance = level.getCraftServer().getViewDistance() * 16; -@@ -294,7 +455,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -295,7 +456,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { this.setInvulnerableTicks(i); if (this.tickCount % 10 == 0) { @@ -8040,7 +8032,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 } } else { super.customServerAiStep(level); -@@ -346,7 +507,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -347,7 +508,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { if (this.destroyBlocksTick > 0) { this.destroyBlocksTick--; @@ -8049,7 +8041,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 boolean flag = false; int alternativeTarget = Mth.floor(this.getBbWidth() / 2.0F + 1.0F); int floor = Mth.floor(this.getBbHeight()); -@@ -376,8 +537,10 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -377,8 +538,10 @@ public class WitherBoss extends Monster implements RangedAttackMob { } } @@ -8062,7 +8054,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 } this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); -@@ -561,11 +724,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -562,11 +725,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { } public int getAlternativeTarget(int head) { @@ -8076,7 +8068,7 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 } public boolean isPowered() { -@@ -574,6 +737,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { +@@ -575,6 +738,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { @Override protected boolean canRide(Entity entity) { @@ -8085,10 +8077,10 @@ index afe43600c4976e01e61d716034a2823d50fb55cb..2d9f64cddbec782de1775ec6da67b162 } diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index 3e0830c70c0b3fda8631679c7426cc303600d1fa..a31bbd8f3fff4fb4b1b33877d5835b93fc248f65 100644 +index 99b8f53fc553bf3e752208a5c007bc49266ffc27..49500127eb3a471c41dc3ff32372ad6f20c6d69a 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -93,10 +93,13 @@ public class ArmorStand extends LivingEntity { +@@ -95,10 +95,13 @@ public class ArmorStand extends LivingEntity { private boolean noTickPoseDirty = false; public boolean noTickEquipmentDirty = false; // Paper end - Allow ArmorStands not to tick @@ -8102,7 +8094,7 @@ index 3e0830c70c0b3fda8631679c7426cc303600d1fa..a31bbd8f3fff4fb4b1b33877d5835b93 } public ArmorStand(Level level, double x, double y, double z) { -@@ -561,6 +564,7 @@ public class ArmorStand extends LivingEntity { +@@ -489,6 +492,7 @@ public class ArmorStand extends LivingEntity { private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(ServerLevel level, DamageSource damageSource) { // Paper ItemStack itemStack = new ItemStack(Items.ARMOR_STAND); @@ -8110,7 +8102,7 @@ index 3e0830c70c0b3fda8631679c7426cc303600d1fa..a31bbd8f3fff4fb4b1b33877d5835b93 itemStack.set(DataComponents.CUSTOM_NAME, this.getCustomName()); this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior return this.brokenByAnything(level, damageSource); // Paper -@@ -620,6 +624,7 @@ public class ArmorStand extends LivingEntity { +@@ -538,6 +542,7 @@ public class ArmorStand extends LivingEntity { @Override public void tick() { @@ -8118,7 +8110,7 @@ index 3e0830c70c0b3fda8631679c7426cc303600d1fa..a31bbd8f3fff4fb4b1b33877d5835b93 // Paper start - Allow ArmorStands not to tick if (!this.canTick) { if (this.noTickPoseDirty) { -@@ -949,4 +954,18 @@ public class ArmorStand extends LivingEntity { +@@ -867,4 +872,18 @@ public class ArmorStand extends LivingEntity { } } // Paper end @@ -8138,10 +8130,10 @@ index 3e0830c70c0b3fda8631679c7426cc303600d1fa..a31bbd8f3fff4fb4b1b33877d5835b93 + // Purpur end - Movement options for armor stands } diff --git a/net/minecraft/world/entity/decoration/ItemFrame.java b/net/minecraft/world/entity/decoration/ItemFrame.java -index 65e1d7c5ac94b1cfb921fa009be59d3e5872f0b5..3ee1d8798db666ee8d83556047e40ff217cda732 100644 +index f9a97000b75db7999b1cbe1f72d680d4d7b803b7..9dfadb5639e840e69274b35f3366322141527104 100644 --- a/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/net/minecraft/world/entity/decoration/ItemFrame.java -@@ -223,7 +223,11 @@ public class ItemFrame extends HangingEntity { +@@ -232,7 +232,11 @@ public class ItemFrame extends HangingEntity { this.removeFramedMap(item); } else { if (dropItem) { @@ -8155,10 +8147,10 @@ index 65e1d7c5ac94b1cfb921fa009be59d3e5872f0b5..3ee1d8798db666ee8d83556047e40ff2 if (!item.isEmpty()) { diff --git a/net/minecraft/world/entity/decoration/Painting.java b/net/minecraft/world/entity/decoration/Painting.java -index 5b905a4d49c44b04d5795c2bf297f3c69d183d7c..b6429a2bbb6fc1e08610ab20e50f8f0414f0ad26 100644 +index 3f13bb1ad260d250efe2622297e432dc300e73a0..b1ee059501532cc2df5f0824e5becbd2bc6727b2 100644 --- a/net/minecraft/world/entity/decoration/Painting.java +++ b/net/minecraft/world/entity/decoration/Painting.java -@@ -162,7 +162,11 @@ public class Painting extends HangingEntity implements VariantHolder entityType, Level level) { super(entityType, level); -@@ -365,7 +371,16 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -372,7 +378,16 @@ public class ItemEntity extends Entity implements TraceableEntity { @Override public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) { @@ -8206,7 +8198,7 @@ index 8e450c9d0111c0ce44feb386cf8b2715e407bf25..bbd3253dc6ab09f166447b163b197302 return false; } else if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && damageSource.getEntity() instanceof Mob) { return false; -@@ -567,6 +582,12 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -556,6 +571,12 @@ public class ItemEntity extends Entity implements TraceableEntity { public void setItem(ItemStack stack) { this.getEntityData().set(DATA_ITEM, stack); this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate @@ -8220,10 +8212,10 @@ index 8e450c9d0111c0ce44feb386cf8b2715e407bf25..bbd3253dc6ab09f166447b163b197302 @Override diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index 40da052e7fea1306a007b3cb5c9daa33e0ef523e..40f5534b425ef57c435b365f156d3b988b74f911 100644 +index 5d23d8754b304d5e2fd54400cc81c7fe5c14a804..9a00aead39e194de076ee651d2f75b29673cad1e 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java -@@ -251,4 +251,32 @@ public class PrimedTnt extends Entity implements TraceableEntity { +@@ -253,4 +253,32 @@ public class PrimedTnt extends Entity implements TraceableEntity { return !this.level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid(); } // Paper end - Option to prevent TNT from moving in water @@ -8257,7 +8249,7 @@ index 40da052e7fea1306a007b3cb5c9daa33e0ef523e..40f5534b425ef57c435b365f156d3b98 + // Purpur end - Shears can defuse TNT } diff --git a/net/minecraft/world/entity/monster/AbstractSkeleton.java b/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 37abc7769573e3cdda380166dd086551d5e7bd88..223739818e9ac6c9fe396b82bce53a3ab029610a 100644 +index 408c72a28bde6d2f0a7c410c5c7558e5fe7ad4c8..185edd9878f5193c44b75a126e8182caade7e943 100644 --- a/net/minecraft/world/entity/monster/AbstractSkeleton.java +++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java @@ -64,21 +64,24 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo @@ -8325,7 +8317,7 @@ index 37abc7769573e3cdda380166dd086551d5e7bd88..223739818e9ac6c9fe396b82bce53a3a - if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { + if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(level.getMinecraftWorld()) && this.random.nextFloat() < this.level().purpurConfig.chanceHeadHalloweenOnEntity) { // Purpur - Halloween options and optimizations this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); - this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + this.setDropChance(EquipmentSlot.HEAD, 0.0F); } @@ -217,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo if (event.getProjectile() == arrow.getBukkitEntity()) { @@ -8336,16 +8328,15 @@ index 37abc7769573e3cdda380166dd086551d5e7bd88..223739818e9ac6c9fe396b82bce53a3a ); } // CraftBukkit } -@@ -244,7 +224,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -243,14 +223,14 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); this.reassessWeaponGoal(); - // Paper start - shouldBurnInDay API -- if (compound.contains("Paper.ShouldBurnInDay")) { -+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight - this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay"); - } - // Paper end - shouldBurnInDay API -@@ -253,7 +233,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +- this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - shouldBurnInDay API ++ //this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - shouldBurnInDay API // Purpur - implemented in LivingEntity - API for any mob to burn daylight + } + + // Paper start - shouldBurnInDay API @Override public void addAdditionalSaveData(final net.minecraft.nbt.CompoundTag nbt) { super.addAdditionalSaveData(nbt); @@ -8355,7 +8346,7 @@ index 37abc7769573e3cdda380166dd086551d5e7bd88..223739818e9ac6c9fe396b82bce53a3a // Paper end - shouldBurnInDay API diff --git a/net/minecraft/world/entity/monster/Blaze.java b/net/minecraft/world/entity/monster/Blaze.java -index 419c729502ee708bba9e750f1b951450eca82695..79f5f0dbf95ed72dd031495c75675d7b6c7dfc34 100644 +index 4ab7072b4290db7fbe72f81b89d3c428b05f737c..fa21b7dba208d5ba6ecf1d2b68965bb50642b53a 100644 --- a/net/minecraft/world/entity/monster/Blaze.java +++ b/net/minecraft/world/entity/monster/Blaze.java @@ -33,26 +33,78 @@ public class Blaze extends Monster { @@ -8460,10 +8451,10 @@ index 419c729502ee708bba9e750f1b951450eca82695..79f5f0dbf95ed72dd031495c75675d7b if (this.nextHeightOffsetChangeTick <= 0) { this.nextHeightOffsetChangeTick = 100; diff --git a/net/minecraft/world/entity/monster/Bogged.java b/net/minecraft/world/entity/monster/Bogged.java -index f01670f7106a39957c9b37839fcca0d9f29208f0..2774602455b92745e789d83f17480c141eb89abf 100644 +index c279d38ed8d5d0fef6dea4afdc3ab308456f31a7..bc8f46b656895d916e44a9e1dc9175da96c2fde8 100644 --- a/net/minecraft/world/entity/monster/Bogged.java +++ b/net/minecraft/world/entity/monster/Bogged.java -@@ -41,6 +41,31 @@ public class Bogged extends AbstractSkeleton implements Shearable { +@@ -42,6 +42,31 @@ public class Bogged extends AbstractSkeleton implements Shearable { super(entityType, level); } @@ -8546,13 +8537,13 @@ index 2e32567fca7a2a4cd87bc078a6eeb30e3ffabfce..7eca4b751d900c6d6ee34993c3e23681 public boolean doHurtTarget(ServerLevel level, Entity source) { if (super.doHurtTarget(level, source)) { diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java -index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436cd46f049 100644 +index 3f5e1e98802e5dd1cfc9075559e1102046605a04..567e1bc0bb2e96f831206e70612dfe8bcb825b74 100644 --- a/net/minecraft/world/entity/monster/Creeper.java +++ b/net/minecraft/world/entity/monster/Creeper.java -@@ -50,21 +50,107 @@ public class Creeper extends Monster { +@@ -54,21 +54,107 @@ public class Creeper extends Monster { public int explosionRadius = 3; private int droppedSkulls; - public Entity entityIgniter; // CraftBukkit + public @Nullable Entity entityIgniter; // CraftBukkit + private boolean exploding = false; // Purpur - Config to make Creepers explode on death + // Purpur start - Ridables + private int spacebarCharge = 0; @@ -8657,11 +8648,12 @@ index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436 this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); } -@@ -161,6 +247,40 @@ public class Creeper extends Monster { - } +@@ -157,6 +243,41 @@ public class Creeper extends Monster { + return false; // CraftBukkit } + // Purpur start - Special mobs naturally spawn ++ @Override + public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, @Nullable net.minecraft.world.entity.SpawnGroupData entityData) { + double chance = world.getLevel().purpurConfig.creeperChargedChance; + if (chance > 0D && random.nextDouble() <= chance) { @@ -8696,9 +8688,9 @@ index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436 + // Purpur end - Mobs always drop experience + @Override - protected SoundEvent getHurtSound(DamageSource damageSource) { + public SoundEvent getHurtSound(DamageSource damageSource) { return SoundEvents.CREEPER_HURT; -@@ -243,14 +363,16 @@ public class Creeper extends Monster { +@@ -239,14 +360,16 @@ public class Creeper extends Monster { } public void explodeCreeper() { @@ -8717,7 +8709,7 @@ index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436 this.spawnLingeringCloud(); this.triggerOnDeathMobEffects(serverLevel, Entity.RemovalReason.KILLED); this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause -@@ -261,6 +383,7 @@ public class Creeper extends Monster { +@@ -257,6 +380,7 @@ public class Creeper extends Monster { } // CraftBukkit end } @@ -8725,7 +8717,7 @@ index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436 } private void spawnLingeringCloud() { -@@ -288,6 +411,7 @@ public class Creeper extends Monster { +@@ -285,6 +409,7 @@ public class Creeper extends Monster { 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(DATA_IS_IGNITED, event.isIgnited()); @@ -8734,7 +8726,7 @@ index e832612a7ed3f25d087c4f8f85f5d737ade5d645..a85b64799faa860367cded67a264b436 } } diff --git a/net/minecraft/world/entity/monster/Drowned.java b/net/minecraft/world/entity/monster/Drowned.java -index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79a95db59d 100644 +index 4978cd2a7a84130fc0de1cc481b39d61f388c812..b85d1e196d2bf61ac4896205afb08eba89c4397e 100644 --- a/net/minecraft/world/entity/monster/Drowned.java +++ b/net/minecraft/world/entity/monster/Drowned.java @@ -75,6 +75,67 @@ public class Drowned extends Zombie implements RangedAttackMob { @@ -8830,7 +8822,7 @@ index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79 this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); -@@ -395,7 +469,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -398,7 +472,7 @@ public class Drowned extends Zombie implements RangedAttackMob { } } @@ -8839,7 +8831,7 @@ index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79 private final Drowned drowned; public DrownedMoveControl(Drowned mob) { -@@ -404,7 +478,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -407,7 +481,7 @@ public class Drowned extends Zombie implements RangedAttackMob { } @Override @@ -8848,7 +8840,7 @@ index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79 LivingEntity target = this.drowned.getTarget(); if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { if (target != null && target.getY() > this.drowned.getY() || this.drowned.searchingForLand) { -@@ -424,7 +498,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -427,7 +501,7 @@ public class Drowned extends Zombie implements RangedAttackMob { float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F; this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); this.drowned.yBodyRot = this.drowned.getYRot(); @@ -8857,7 +8849,7 @@ index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79 float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); this.drowned.setSpeed(f2); this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(f2 * d * 0.005, f2 * d1 * 0.1, f2 * d2 * 0.005)); -@@ -433,7 +507,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -436,7 +510,7 @@ public class Drowned extends Zombie implements RangedAttackMob { this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0)); } @@ -8867,7 +8859,7 @@ index c23c4e44ece85fb746a497cbb8a7cd14b2f9768a..6c73245b8d04f194e72165aa0000ca79 } } diff --git a/net/minecraft/world/entity/monster/ElderGuardian.java b/net/minecraft/world/entity/monster/ElderGuardian.java -index 4585b7c867685f8419c4d2b5b90af5946d337f90..358021a6eb936ac43e29c7c2c92c71e9cae6ab93 100644 +index fd33a8b59f40299ab644a4c52921b66a9b6552ca..a708692a71014aabc1fc842837e1c0a82fd3a343 100644 --- a/net/minecraft/world/entity/monster/ElderGuardian.java +++ b/net/minecraft/world/entity/monster/ElderGuardian.java @@ -31,6 +31,40 @@ public class ElderGuardian extends Guardian { @@ -8912,10 +8904,10 @@ index 4585b7c867685f8419c4d2b5b90af5946d337f90..358021a6eb936ac43e29c7c2c92c71e9 return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 8.0).add(Attributes.MAX_HEALTH, 80.0); } diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java -index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47dd61e3dfa 100644 +index 6c2bfad0ad7a5c20cd6eeba9fdc713c85c357ef4..b9160f939894f784e8a733b0c00055b51aec694a 100644 --- a/net/minecraft/world/entity/monster/EnderMan.java +++ b/net/minecraft/world/entity/monster/EnderMan.java -@@ -87,12 +87,45 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -88,12 +88,45 @@ public class EnderMan extends Monster implements NeutralMob { public EnderMan(EntityType entityType, Level level) { super(entityType, level); @@ -8962,7 +8954,7 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false)); this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F)); -@@ -100,9 +133,10 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -101,9 +134,10 @@ 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)); @@ -8974,16 +8966,16 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); } -@@ -230,7 +264,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -220,7 +254,7 @@ public class EnderMan extends Monster implements NeutralMob { boolean isBeingStaredBy(Player player) { // Paper start - EndermanAttackPlayerEvent -- final boolean shouldAttack = isBeingStaredBy0(player); -+ final boolean shouldAttack = !this.level().purpurConfig.endermanDisableStareAggro && isBeingStaredBy0(player); // Purpur - Config to ignore Dragon Head wearers and stare aggro +- final boolean shouldAttack = this.isBeingStaredBy0(player); ++ final boolean shouldAttack = !this.level().purpurConfig.endermanDisableStareAggro && this.isBeingStaredBy0(player); // Purpur - Config to ignore Dragon Head wearers and stare aggro final com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); event.setCancelled(!shouldAttack); return event.callEvent(); -@@ -267,12 +301,12 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -258,12 +292,12 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean isSensitiveToWater() { @@ -8993,29 +8985,29 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d @Override protected void customServerAiStep(ServerLevel level) { -- if (level.isDay() && this.tickCount >= this.targetChangeTime + 600) { -+ if ((getRider() == null || !this.isControllable()) && level.isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - Ridables - no random teleporting +- if (level.isBrightOutside() && this.tickCount >= this.targetChangeTime + 600) { ++ if ((getRider() == null || !this.isControllable()) && level.isBrightOutside() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - Ridables - no random teleporting float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); if (lightLevelDependentMagicValue > 0.5F && level.canSeeSky(this.blockPosition()) -@@ -393,6 +427,8 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -384,6 +418,8 @@ public class EnderMan extends Monster implements NeutralMob { public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) { if (this.isInvulnerableTo(level, damageSource)) { return false; + } else if (getRider() != null && this.isControllable()) { return super.hurtServer(level, damageSource, amount); // Purpur - no teleporting on damage + } else if (org.purpurmc.purpur.PurpurConfig.endermanShortHeight && damageSource.is(net.minecraft.world.damagesource.DamageTypes.IN_WALL)) { return false; // Purpur - no suffocation damage if short height - Short enderman height } else { - boolean flag = damageSource.getDirectEntity() instanceof ThrownPotion; - if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && !flag) { -@@ -405,6 +441,7 @@ public class EnderMan extends Monster implements NeutralMob { + AbstractThrownPotion abstractThrownPotion1 = damageSource.getDirectEntity() instanceof AbstractThrownPotion abstractThrownPotion + ? abstractThrownPotion +@@ -398,6 +434,7 @@ public class EnderMan extends Monster implements NeutralMob { } else { - boolean flag1 = flag && this.hurtWithCleanWater(level, damageSource, (ThrownPotion)damageSource.getDirectEntity(), amount); + boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount); -+ if (!flag1 && level.purpurConfig.endermanIgnoreProjectiles) return super.hurtServer(level, damageSource, amount); // Purpur - Config to disable Enderman teleport on projectile hit ++ if (!flag && level.purpurConfig.endermanIgnoreProjectiles) return super.hurtServer(level, damageSource, amount); // Purpur - Config to disable Enderman teleport on projectile hit if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent for (int i = 0; i < 64; i++) { if (this.teleport()) { -@@ -448,7 +485,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -441,7 +478,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean requiresCustomPersistence() { @@ -9024,7 +9016,7 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d } static class EndermanFreezeWhenLookedAt extends Goal { -@@ -492,8 +529,9 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -485,8 +522,9 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { @@ -9035,7 +9027,7 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d && this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0; } -@@ -641,8 +679,9 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -634,8 +672,9 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { @@ -9047,13 +9039,13 @@ index 00c0d2432b4a0e46f85f1f422772e6c43ef5222c..c7897532163d4fdf5a82982f7d24a47d } diff --git a/net/minecraft/world/entity/monster/Endermite.java b/net/minecraft/world/entity/monster/Endermite.java -index 2a219c9ae39d7cbee8484b2a93bd278d913afe95..441f7d3cfa1e9896a065dae51d871901ac4330e3 100644 +index 7fad96756972308e71fd38033f06148467a7aecd..7d3932dcb263500357e9aad28881229418a0d458 100644 --- a/net/minecraft/world/entity/monster/Endermite.java +++ b/net/minecraft/world/entity/monster/Endermite.java -@@ -28,20 +28,72 @@ import net.minecraft.world.level.block.state.BlockState; - public class Endermite extends Monster { +@@ -29,20 +29,72 @@ public class Endermite extends Monster { private static final int MAX_LIFE = 2400; - public int life; + private static final int DEFAULT_LIFE = 0; + public int life = 0; + private boolean isPlayerSpawned; // Purpur - Add back player spawned endermite API public Endermite(EntityType entityType, Level level) { @@ -9123,11 +9115,11 @@ index 2a219c9ae39d7cbee8484b2a93bd278d913afe95..441f7d3cfa1e9896a065dae51d871901 this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); } -@@ -79,12 +131,14 @@ public class Endermite extends Monster { +@@ -80,12 +132,14 @@ public class Endermite extends Monster { public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); - this.life = compound.getInt("Lifetime"); -+ this.isPlayerSpawned = compound.getBoolean("PlayerSpawned"); // Purpur - Add back player spawned endermite API + this.life = compound.getIntOr("Lifetime", 0); ++ this.isPlayerSpawned = compound.getBooleanOr("PlayerSpawned", false); // Purpur - Add back player spawned endermite API } @Override @@ -9139,7 +9131,7 @@ index 2a219c9ae39d7cbee8484b2a93bd278d913afe95..441f7d3cfa1e9896a065dae51d871901 @Override diff --git a/net/minecraft/world/entity/monster/Evoker.java b/net/minecraft/world/entity/monster/Evoker.java -index b70ea1af39cada6bb17001c6b65502510e34c4b2..5c32406d00ec20516649d7a219a5b3c27c8945aa 100644 +index cf9f0c60efc4f7cbc275ed9b154c979e82b4d50c..f32fa187ba6b16f1e8b1f308dc9073f808d52d86 100644 --- a/net/minecraft/world/entity/monster/Evoker.java +++ b/net/minecraft/world/entity/monster/Evoker.java @@ -50,10 +50,50 @@ public class Evoker extends SpellcasterIllager { @@ -9211,10 +9203,10 @@ index b70ea1af39cada6bb17001c6b65502510e34c4b2..5c32406d00ec20516649d7a219a5b3c2 } else { List nearbyEntities = serverLevel.getNearbyEntities( diff --git a/net/minecraft/world/entity/monster/Ghast.java b/net/minecraft/world/entity/monster/Ghast.java -index b97bbfbbc8c1a4f38b4b858ef4915b637cc8a627..a9d92e857c5d05da6f2a5b6264590efe235061a7 100644 +index 97b4352671910d2deedc6d280f3ce6e645597f3c..c2e6e2f4a2c1e72521f0afd1664d9ba02ef08d7d 100644 --- a/net/minecraft/world/entity/monster/Ghast.java +++ b/net/minecraft/world/entity/monster/Ghast.java -@@ -42,11 +42,69 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -43,11 +43,69 @@ public class Ghast extends FlyingMob implements Enemy { this.moveControl = new Ghast.GhastMoveControl(this); } @@ -9284,7 +9276,7 @@ index b97bbfbbc8c1a4f38b4b858ef4915b637cc8a627..a9d92e857c5d05da6f2a5b6264590efe this.targetSelector .addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entity, level) -> Math.abs(entity.getY() - this.getY()) <= 4.0)); } -@@ -101,7 +159,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -102,7 +160,7 @@ public class Ghast extends FlyingMob implements Enemy { } public static AttributeSupplier.Builder createAttributes() { @@ -9293,7 +9285,7 @@ index b97bbfbbc8c1a4f38b4b858ef4915b637cc8a627..a9d92e857c5d05da6f2a5b6264590efe } @Override -@@ -191,7 +249,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -190,7 +248,7 @@ public class Ghast extends FlyingMob implements Enemy { } } @@ -9302,7 +9294,7 @@ index b97bbfbbc8c1a4f38b4b858ef4915b637cc8a627..a9d92e857c5d05da6f2a5b6264590efe private final Ghast ghast; private int floatDuration; -@@ -201,7 +259,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -200,7 +258,7 @@ public class Ghast extends FlyingMob implements Enemy { } @Override @@ -9422,7 +9414,7 @@ index 969eb604851d1cce50f0f99ed479189061d5de0c..3f575abee4c8933d1642400d134b0fc9 } } diff --git a/net/minecraft/world/entity/monster/Guardian.java b/net/minecraft/world/entity/monster/Guardian.java -index c8e249b8f7ee8e9c075169ec988f5a0d459a3767..60278b2491f644b70ef96b2e14e1f07bb341a0f1 100644 +index a36f0181e1aa24538d6c868a8675da89427bdeae..3ba8da3bd04774fb3131fdbd2aa0bd6c9f31c817 100644 --- a/net/minecraft/world/entity/monster/Guardian.java +++ b/net/minecraft/world/entity/monster/Guardian.java @@ -66,14 +66,57 @@ public class Guardian extends Monster { @@ -9494,7 +9486,7 @@ index c8e249b8f7ee8e9c075169ec988f5a0d459a3767..60278b2491f644b70ef96b2e14e1f07b @@ -344,7 +388,7 @@ public class Guardian extends Monster { @Override public void travel(Vec3 travelVector) { - if (this.isControlledByLocalInstance() && this.isInWater()) { + if (this.isInWater()) { - this.moveRelative(0.1F, travelVector); + this.moveRelative(getRider() != null && this.isControllable() ? getSpeed() : 0.1F, travelVector); // Purpur - Ridables this.move(MoverType.SELF, this.getDeltaMovement()); @@ -9538,7 +9530,7 @@ index c8e249b8f7ee8e9c075169ec988f5a0d459a3767..60278b2491f644b70ef96b2e14e1f07b this.guardian.setSpeed(f2); double d3 = Math.sin((this.guardian.tickCount + this.guardian.getId()) * 0.5) * 0.05; diff --git a/net/minecraft/world/entity/monster/Husk.java b/net/minecraft/world/entity/monster/Husk.java -index 6155c544ad2722a49c5e41dd7d7b02fedc56474e..a5bfc6f5caba1da8cfcb345524e05e8676672cb0 100644 +index 8d6def85583a111841b28f20f58ddb8b8cbd7bc1..a4ce65911a5d778f60bcedb3acd9fe59a5094c96 100644 --- a/net/minecraft/world/entity/monster/Husk.java +++ b/net/minecraft/world/entity/monster/Husk.java @@ -19,8 +19,69 @@ import net.minecraft.world.level.ServerLevelAccessor; @@ -9621,7 +9613,7 @@ index 6155c544ad2722a49c5e41dd7d7b02fedc56474e..a5bfc6f5caba1da8cfcb345524e05e86 @Override diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java -index 40ca12e391b2adac6b132f1832b1427acb3748bc..9686658b90e886d6236f553d7406771814d18672 100644 +index 264ec7acfc03eca4a8f5758ad8d3e11714e934b4..b8ada9ebd0d8d4ca0e8eb7e6084a0057f4758ea4 100644 --- a/net/minecraft/world/entity/monster/Illusioner.java +++ b/net/minecraft/world/entity/monster/Illusioner.java @@ -57,10 +57,52 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { @@ -9686,7 +9678,7 @@ index 40ca12e391b2adac6b132f1832b1427acb3748bc..9686658b90e886d6236f553d74067718 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/net/minecraft/world/entity/monster/MagmaCube.java b/net/minecraft/world/entity/monster/MagmaCube.java -index 905ecbd8b22c785ee4ea18004ac50eb1b7005d3f..312d4a3d312b5c326d6ca13ccfc48171e18f4370 100644 +index 889c31cc9257fbbd5df8325ccee9ce39b026ec4b..7ef0f84d4c449a8991683ca66d7b16ca21ef4cdf 100644 --- a/net/minecraft/world/entity/monster/MagmaCube.java +++ b/net/minecraft/world/entity/monster/MagmaCube.java @@ -24,6 +24,64 @@ public class MagmaCube extends Slime { @@ -9763,7 +9755,7 @@ index 905ecbd8b22c785ee4ea18004ac50eb1b7005d3f..312d4a3d312b5c326d6ca13ccfc48171 @Override diff --git a/net/minecraft/world/entity/monster/Monster.java b/net/minecraft/world/entity/monster/Monster.java -index d0d3c825cf8088df4794cf5bfde12a69f4d71754..c1ebb74b0d4a8e2eb8880ccaf20f0f9bc1940094 100644 +index 5ef9566b16a4d0300ee45a993c46e734db156416..04d5910d736dee2a88a2602f4a98495459277157 100644 --- a/net/minecraft/world/entity/monster/Monster.java +++ b/net/minecraft/world/entity/monster/Monster.java @@ -88,6 +88,14 @@ public abstract class Monster extends PathfinderMob implements Enemy { @@ -9782,12 +9774,12 @@ index d0d3c825cf8088df4794cf5bfde12a69f4d71754..c1ebb74b0d4a8e2eb8880ccaf20f0f9b return false; } else { diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3fa48d267 100644 +index 483b0499f1f70b3aa8862e6cd8e512748492bee0..2e1e7cf0fe1bc25437cf2f429ff33b4263b1a6f1 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java -@@ -47,19 +47,123 @@ public class Phantom extends FlyingMob implements Enemy { - Vec3 moveTargetPoint = Vec3.ZERO; - public BlockPos anchorPoint = BlockPos.ZERO; +@@ -48,19 +48,123 @@ public class Phantom extends FlyingMob implements Enemy { + @Nullable + public BlockPos anchorPoint; Phantom.AttackPhase attackPhase = Phantom.AttackPhase.CIRCLE; + Vec3 crystalPosition; // Purpur - Phantoms attracted to crystals and crystals shoot phantoms // Paper start @@ -9909,7 +9901,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 @Override public boolean isFlapping() { return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0; -@@ -72,9 +176,17 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -73,9 +177,17 @@ public class Phantom extends FlyingMob implements Enemy { @Override protected void registerGoals() { @@ -9930,7 +9922,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); } -@@ -90,7 +202,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -91,7 +203,11 @@ public class Phantom extends FlyingMob implements Enemy { private void updatePhantomSizeInfo() { this.refreshDimensions(); @@ -9943,7 +9935,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 } public int getPhantomSize() { -@@ -115,6 +231,23 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -116,6 +232,23 @@ public class Phantom extends FlyingMob implements Enemy { return true; } @@ -9967,7 +9959,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 @Override public void tick() { super.tick(); -@@ -146,10 +279,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -147,10 +280,7 @@ public class Phantom extends FlyingMob implements Enemy { @Override public void aiStep() { @@ -9979,7 +9971,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 super.aiStep(); } -@@ -158,7 +288,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -159,7 +289,11 @@ public class Phantom extends FlyingMob implements Enemy { ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData spawnGroupData ) { this.anchorPoint = this.blockPosition().above(5); @@ -9992,25 +9984,25 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData); } -@@ -175,7 +309,7 @@ public class Phantom extends FlyingMob implements Enemy { - if (compound.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = compound.getUUID("Paper.SpawningEntity"); - } -- if (compound.contains("Paper.ShouldBurnInDay")) { -+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight - this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay"); - } +@@ -170,7 +304,7 @@ public class Phantom extends FlyingMob implements Enemy { + this.setPhantomSize(compound.getIntOr("size", 0)); + // Paper start + this.spawningEntity = compound.read("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC).orElse(null); +- this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); ++ //this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Purpur - implemented in LivingEntity - API for any mob to burn daylight // Paper end -@@ -192,7 +326,7 @@ public class Phantom extends FlyingMob implements Enemy { - if (this.spawningEntity != null) { - compound.putUUID("Paper.SpawningEntity", this.spawningEntity); - } + } + +@@ -181,7 +315,7 @@ public class Phantom extends FlyingMob implements Enemy { + compound.putInt("size", this.getPhantomSize()); + // Paper start + compound.storeNullable("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC, this.spawningEntity); - compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); + //compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - implemented in LivingEntity - API for any mob to burn daylight // Paper end } -@@ -262,6 +396,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -251,6 +385,7 @@ public class Phantom extends FlyingMob implements Enemy { List nearbyPlayers = serverLevel.getNearbyPlayers( this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0, 64.0, 16.0) ); @@ -10018,7 +10010,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 if (!nearbyPlayers.isEmpty()) { nearbyPlayers.sort(Comparator.comparing(Entity::getY).reversed()); -@@ -407,25 +542,160 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -400,25 +535,160 @@ public class Phantom extends FlyingMob implements Enemy { } } @@ -10182,7 +10174,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 if (Phantom.this.horizontalCollision) { Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); this.speed = 0.1F; -@@ -492,6 +762,12 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -485,6 +755,12 @@ public class Phantom extends FlyingMob implements Enemy { return false; } else if (!target.isAlive()) { return false; @@ -10196,7 +10188,7 @@ index a91aba11ecda561d117c9d8db85c92cdcd81887e..3c105d164acd9e45de2335ef28ddecf3 return false; } else if (!this.canUse()) { diff --git a/net/minecraft/world/entity/monster/Pillager.java b/net/minecraft/world/entity/monster/Pillager.java -index e855ebc5be2cef3b96e2c01a8c1d388e433c0d52..a57d869cdc6a05124237933437aa2d26ff72cab3 100644 +index d7b05fed206cfb63a75fab94f687d69fb230de9c..3d12b509a9b57f0326ec48eed93b2962f6f0e493 100644 --- a/net/minecraft/world/entity/monster/Pillager.java +++ b/net/minecraft/world/entity/monster/Pillager.java @@ -63,16 +63,57 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve @@ -10258,10 +10250,10 @@ index e855ebc5be2cef3b96e2c01a8c1d388e433c0d52..a57d869cdc6a05124237933437aa2d26 this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java -index 129479cedda20e77719f4f7237ec5b9acc5b00c8..ce5cd032203839887a29008c2a1420c6bb6f4fee 100644 +index ca1856b18878b94ebfb566395e5eee13cf3c1cd5..56b844a8252c7f7ece12db98775230134e1898d6 100644 --- a/net/minecraft/world/entity/monster/Ravager.java +++ b/net/minecraft/world/entity/monster/Ravager.java -@@ -66,14 +66,62 @@ public class Ravager extends Raider { +@@ -69,14 +69,62 @@ public class Ravager extends Raider { this.setPathfindingMalus(PathType.LEAVES, 0.0F); } @@ -10324,7 +10316,7 @@ index 129479cedda20e77719f4f7237ec5b9acc5b00c8..ce5cd032203839887a29008c2a1420c6 this.targetSelector.addGoal(2, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entity, level) -> !entity.isBaby())); -@@ -130,7 +178,7 @@ public class Ravager extends Raider { +@@ -133,7 +181,7 @@ public class Ravager extends Raider { @Override public void aiStep() { super.aiStep(); @@ -10333,7 +10325,7 @@ index 129479cedda20e77719f4f7237ec5b9acc5b00c8..ce5cd032203839887a29008c2a1420c6 if (this.isImmobile()) { this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0); } else { -@@ -141,7 +189,7 @@ public class Ravager extends Raider { +@@ -144,7 +192,7 @@ public class Ravager extends Raider { if (this.level() instanceof ServerLevel serverLevel && this.horizontalCollision @@ -10342,7 +10334,7 @@ index 129479cedda20e77719f4f7237ec5b9acc5b00c8..ce5cd032203839887a29008c2a1420c6 boolean flag = false; AABB aabb = this.getBoundingBox().inflate(0.2); -@@ -150,7 +198,7 @@ public class Ravager extends Raider { +@@ -153,7 +201,7 @@ public class Ravager extends Raider { )) { BlockState blockState = serverLevel.getBlockState(blockPos); Block block = blockState.getBlock(); @@ -10352,10 +10344,10 @@ index 129479cedda20e77719f4f7237ec5b9acc5b00c8..ce5cd032203839887a29008c2a1420c6 if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, blockState.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state continue; diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java -index 9df62e2ae02c680501cc9284e44c1672315a9cbf..a006300aea2cbb05400550f1c79e872d095384f8 100644 +index 1b8a4c548c1376d9cdd16a10d434da070c85f41d..56401c993d9a4c41b0782831a8b857646bf18f88 100644 --- a/net/minecraft/world/entity/monster/Shulker.java +++ b/net/minecraft/world/entity/monster/Shulker.java -@@ -50,6 +50,7 @@ import net.minecraft.world.level.Level; +@@ -53,6 +53,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; @@ -10363,7 +10355,7 @@ index 9df62e2ae02c680501cc9284e44c1672315a9cbf..a006300aea2cbb05400550f1c79e872d import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -@@ -88,12 +89,68 @@ public class Shulker extends AbstractGolem implements VariantHolder variant) { +@@ -572,7 +639,7 @@ public class Shulker extends AbstractGolem implements Enemy { + } - @Override public Optional getVariant() { - return Optional.ofNullable(this.getColor()); + return Optional.ofNullable(this.level().purpurConfig.shulkerSpawnFromBulletRandomColor ? DyeColor.random(this.level().random) : this.getColor()); // Purpur - Shulker spawn from bullet options } @Nullable -@@ -671,7 +738,7 @@ public class Shulker extends AbstractGolem implements VariantHolder entityType, Level level) { super(entityType, level); -@@ -64,12 +65,95 @@ public class Slime extends Mob implements Enemy { +@@ -65,12 +66,95 @@ public class Slime extends Mob implements Enemy { this.moveControl = new Slime.SlimeMoveControl(this); } @@ -10787,7 +10779,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 this.targetSelector .addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entity, level) -> Math.abs(entity.getY() - this.getY()) <= 4.0)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); -@@ -92,9 +176,9 @@ public class Slime extends Mob implements Enemy { +@@ -93,9 +177,9 @@ public class Slime extends Mob implements Enemy { this.entityData.set(ID_SIZE, i); this.reapplyPosition(); this.refreshDimensions(); @@ -10799,7 +10791,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 if (resetHealth) { this.setHealth(this.getMaxHealth()); } -@@ -371,6 +455,7 @@ public class Slime extends Mob implements Enemy { +@@ -359,6 +443,7 @@ public class Slime extends Mob implements Enemy { Vec3 deltaMovement = this.getDeltaMovement(); this.setDeltaMovement(deltaMovement.x, this.getJumpPower(), deltaMovement.z); this.hasImpulse = true; @@ -10807,7 +10799,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 } @Nullable -@@ -535,7 +620,7 @@ public class Slime extends Mob implements Enemy { +@@ -523,7 +608,7 @@ public class Slime extends Mob implements Enemy { } } @@ -10816,7 +10808,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 private float yRot; private int jumpDelay; private final Slime slime; -@@ -553,21 +638,33 @@ public class Slime extends Mob implements Enemy { +@@ -541,21 +626,33 @@ public class Slime extends Mob implements Enemy { } public void setWantedMovement(double speed) { @@ -10853,7 +10845,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 if (this.jumpDelay-- <= 0) { this.jumpDelay = this.slime.getJumpDelay(); if (this.isAggressive) { -@@ -584,7 +681,7 @@ public class Slime extends Mob implements Enemy { +@@ -572,7 +669,7 @@ public class Slime extends Mob implements Enemy { this.mob.setSpeed(0.0F); } } else { @@ -10863,7 +10855,7 @@ index 8db4cba1be6d7a5538295ba8da1fdaf7a77a16d0..240a54b210e23d5b79e6bcaf3806aa45 } } diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java -index af0305079a367899708ee2bbac82aefaa9129d2f..ece8d81e29709a1c0cb5c7b55b1193b630ecb113 100644 +index 60c4ac37bb491af13f9f9bf730b85bbe544cf81d..7c50ed0b7bd0d7138b80613ea08519ae457f49a3 100644 --- a/net/minecraft/world/entity/monster/Spider.java +++ b/net/minecraft/world/entity/monster/Spider.java @@ -50,15 +50,56 @@ public class Spider extends Monster { @@ -10924,7 +10916,7 @@ index af0305079a367899708ee2bbac82aefaa9129d2f..ece8d81e29709a1c0cb5c7b55b1193b6 this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class)); this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class)); diff --git a/net/minecraft/world/entity/monster/Stray.java b/net/minecraft/world/entity/monster/Stray.java -index 5fa2b7920a233afb3659b02cbd7ab82307ea9aaf..fdaa01c8bbaf9e613462e41f508fdc96b3467e03 100644 +index f3de370ee4bafc2cca033293d0d8e5c9c2a6737b..e69a5c552d2f57bc373cb2b89690a7dd9c2faefc 100644 --- a/net/minecraft/world/entity/monster/Stray.java +++ b/net/minecraft/world/entity/monster/Stray.java @@ -22,6 +22,44 @@ public class Stray extends AbstractSkeleton { @@ -10973,10 +10965,10 @@ index 5fa2b7920a233afb3659b02cbd7ab82307ea9aaf..fdaa01c8bbaf9e613462e41f508fdc96 EntityType entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random ) { diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java -index cbae85171a1bb64ee3be40ba211d88e68bf672e4..241526239bdbd5d9276f85e7fca46a7051f46a25 100644 +index afa584e2aba6bebfb2dd343215b043c983281853..fe31c4a45afd61be8b74efe9d0858ccd0aced075 100644 --- a/net/minecraft/world/entity/monster/Strider.java +++ b/net/minecraft/world/entity/monster/Strider.java -@@ -88,12 +88,51 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -86,12 +86,51 @@ public class Strider extends Animal implements ItemSteerable { public Strider(EntityType entityType, Level level) { super(entityType, level); this.blocksBuilding = true; @@ -11029,7 +11021,7 @@ index cbae85171a1bb64ee3be40ba211d88e68bf672e4..241526239bdbd5d9276f85e7fca46a70 public static boolean checkStriderSpawnRules( EntityType entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random ) { -@@ -156,6 +195,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -138,6 +177,7 @@ public class Strider extends Animal implements ItemSteerable { @Override protected void registerGoals() { this.goalSelector.addGoal(1, new PanicGoal(this, 1.65)); @@ -11037,7 +11029,7 @@ index cbae85171a1bb64ee3be40ba211d88e68bf672e4..241526239bdbd5d9276f85e7fca46a70 this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); this.temptGoal = new TemptGoal(this, 1.4, itemStack -> itemStack.is(ItemTags.STRIDER_TEMPT_ITEMS), false); this.goalSelector.addGoal(3, this.temptGoal); -@@ -370,7 +410,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -356,7 +396,7 @@ public class Strider extends Animal implements ItemSteerable { @Override public boolean isSensitiveToWater() { @@ -11046,13 +11038,13 @@ index cbae85171a1bb64ee3be40ba211d88e68bf672e4..241526239bdbd5d9276f85e7fca46a70 } @Override -@@ -414,6 +454,19 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -392,6 +432,19 @@ public class Strider extends Animal implements ItemSteerable { @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { boolean isFood = this.isFood(player.getItemInHand(hand)); + // Purpur start + if (level().purpurConfig.striderGiveSaddleBack && player.isSecondaryUseActive() && !isFood && isSaddled() && !isVehicle()) { -+ this.steering.setSaddle(false); ++ this.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); + if (!player.getAbilities().instabuild) { + ItemStack saddle = new ItemStack(Items.SADDLE); + if (!player.getInventory().add(saddle)) { @@ -11066,17 +11058,17 @@ index cbae85171a1bb64ee3be40ba211d88e68bf672e4..241526239bdbd5d9276f85e7fca46a70 if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { if (!this.level().isClientSide) { player.startRiding(this); -@@ -424,7 +477,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { - InteractionResult interactionResult = super.mobInteract(player, hand); - if (!interactionResult.consumesAction()) { +@@ -404,7 +457,7 @@ public class Strider extends Animal implements ItemSteerable { ItemStack itemInHand = player.getItemInHand(hand); -- return (InteractionResult)(itemInHand.is(Items.SADDLE) ? itemInHand.interactLivingEntity(player, this, hand) : InteractionResult.PASS); -+ return (InteractionResult)(itemInHand.is(Items.SADDLE) ? itemInHand.interactLivingEntity(player, this, hand) : tryRide(player, hand)); // Purpur - Ridables + return (InteractionResult)(this.isEquippableInSlot(itemInHand, EquipmentSlot.SADDLE) + ? itemInHand.interactLivingEntity(player, this, hand) +- : InteractionResult.PASS); ++ : tryRide(player, hand)); // Purpur - Ridables } else { if (isFood && !this.isSilent()) { this.level() diff --git a/net/minecraft/world/entity/monster/Vex.java b/net/minecraft/world/entity/monster/Vex.java -index af3fef70998cff4e4832adfa2071832324ebd91c..0d9dd9919b2b9902137df861bcac8057e4b741de 100644 +index bc74bdc3e13f1d51ed6d31470f3ac6f9855778c9..488e0605e9769d52faffecbc86c28c779d0ff25b 100644 --- a/net/minecraft/world/entity/monster/Vex.java +++ b/net/minecraft/world/entity/monster/Vex.java @@ -58,6 +58,72 @@ public class Vex extends Monster implements TraceableEntity { @@ -11122,7 +11114,7 @@ index af3fef70998cff4e4832adfa2071832324ebd91c..0d9dd9919b2b9902137df861bcac8057 + } + + @Override -+ public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { ++ public boolean causeFallDamage(double fallDistance, float damageMultiplier, DamageSource damageSource) { + return false; // no fall damage please + } + // Purpur end - Ridables @@ -11182,7 +11174,7 @@ index af3fef70998cff4e4832adfa2071832324ebd91c..0d9dd9919b2b9902137df861bcac8057 } @Override -@@ -301,13 +369,13 @@ public class Vex extends Monster implements TraceableEntity { +@@ -291,13 +359,13 @@ public class Vex extends Monster implements TraceableEntity { } } @@ -11198,7 +11190,7 @@ index af3fef70998cff4e4832adfa2071832324ebd91c..0d9dd9919b2b9902137df861bcac8057 if (this.operation == MoveControl.Operation.MOVE_TO) { Vec3 vec3 = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); double len = vec3.length(); -@@ -315,7 +383,7 @@ public class Vex extends Monster implements TraceableEntity { +@@ -305,7 +373,7 @@ public class Vex extends Monster implements TraceableEntity { this.operation = MoveControl.Operation.WAIT; Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5)); } else { @@ -11208,10 +11200,10 @@ index af3fef70998cff4e4832adfa2071832324ebd91c..0d9dd9919b2b9902137df861bcac8057 Vec3 deltaMovement = Vex.this.getDeltaMovement(); Vex.this.setYRot(-((float)Mth.atan2(deltaMovement.x, deltaMovement.z)) * (180.0F / (float)Math.PI)); diff --git a/net/minecraft/world/entity/monster/Vindicator.java b/net/minecraft/world/entity/monster/Vindicator.java -index 5f649d1e69d2be8d8e6963544e3aab6848616893..b584f71440a81ac09d24e59763a21e857f290e5a 100644 +index d02b4bfc3834cdfae37983ec616ee3cbcd9f0988..8ba772d9f5f53dc0dea269c5089e742f20dbc308 100644 --- a/net/minecraft/world/entity/monster/Vindicator.java +++ b/net/minecraft/world/entity/monster/Vindicator.java -@@ -55,15 +55,56 @@ public class Vindicator extends AbstractIllager { +@@ -56,15 +56,56 @@ public class Vindicator extends AbstractIllager { super(entityType, level); } @@ -11268,7 +11260,7 @@ index 5f649d1e69d2be8d8e6963544e3aab6848616893..b584f71440a81ac09d24e59763a21e85 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)); -@@ -132,6 +173,11 @@ public class Vindicator extends AbstractIllager { +@@ -131,6 +172,11 @@ public class Vindicator extends AbstractIllager { RandomSource random = level.getRandom(); this.populateDefaultEquipmentSlots(random, difficulty); this.populateDefaultEquipmentEnchantments(level, random, difficulty); @@ -11281,7 +11273,7 @@ index 5f649d1e69d2be8d8e6963544e3aab6848616893..b584f71440a81ac09d24e59763a21e85 } diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java -index 9f5676b5fa0f369adb8643391738c5ae33911df7..e4353c64732067198f082cdd266c1f1ee1fe4f4e 100644 +index cc156f6d98f193bc98eae75bd5aaf8abe69ace4c..4b253ae8149f5d9505c5140a00a96d8c8850b1c4 100644 --- a/net/minecraft/world/entity/monster/Witch.java +++ b/net/minecraft/world/entity/monster/Witch.java @@ -56,6 +56,45 @@ public class Witch extends Raider implements RangedAttackMob { @@ -11344,7 +11336,7 @@ index 9f5676b5fa0f369adb8643391738c5ae33911df7..e4353c64732067198f082cdd266c1f1e this.targetSelector.addGoal(2, this.healRaidersGoal); this.targetSelector.addGoal(3, this.attackPlayersGoal); diff --git a/net/minecraft/world/entity/monster/WitherSkeleton.java b/net/minecraft/world/entity/monster/WitherSkeleton.java -index eed8dbefd4d04082dc4e091c858e50309ed5c49b..ff2596f69d00b36c65872ab2e27e5d44a6ffa3e1 100644 +index 3ff71ba1bd29faa4d8380dad9397ab34ef930234..b3f5b2e3e2cfc378de948c0e186727d5687c0e98 100644 --- a/net/minecraft/world/entity/monster/WitherSkeleton.java +++ b/net/minecraft/world/entity/monster/WitherSkeleton.java @@ -34,6 +34,45 @@ public class WitherSkeleton extends AbstractSkeleton { @@ -11394,10 +11386,10 @@ index eed8dbefd4d04082dc4e091c858e50309ed5c49b..ff2596f69d00b36c65872ab2e27e5d44 protected void registerGoals() { this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); diff --git a/net/minecraft/world/entity/monster/Zoglin.java b/net/minecraft/world/entity/monster/Zoglin.java -index 8a7418db237553719671f3cd51f42ebed1eb7804..ee59cf42db965296e6e8d4aa4ec7b33dc5142237 100644 +index 33c7081c2aee7a31c4dd143f9d1a36cadcfcb29f..743946e69af541f6d5fe626108c70f96fe7fce65 100644 --- a/net/minecraft/world/entity/monster/Zoglin.java +++ b/net/minecraft/world/entity/monster/Zoglin.java -@@ -83,6 +83,45 @@ public class Zoglin extends Monster implements HoglinBase { +@@ -84,6 +84,45 @@ public class Zoglin extends Monster implements HoglinBase { this.xpReward = 5; } @@ -11443,7 +11435,7 @@ index 8a7418db237553719671f3cd51f42ebed1eb7804..ee59cf42db965296e6e8d4aa4ec7b33d @Override protected Brain.Provider brainProvider() { return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -@@ -246,6 +285,7 @@ public class Zoglin extends Monster implements HoglinBase { +@@ -247,6 +286,7 @@ public class Zoglin extends Monster implements HoglinBase { @Override protected void customServerAiStep(ServerLevel level) { @@ -11452,12 +11444,12 @@ index 8a7418db237553719671f3cd51f42ebed1eb7804..ee59cf42db965296e6e8d4aa4ec7b33d this.updateActivity(); } diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d30e92976 100644 +index 39b65970a48568c95ff482b9636e7391f300ffa8..783f8b9a05939b9f42fc77065f6347e3c6ddf8f5 100644 --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -89,22 +89,78 @@ public class Zombie extends Monster { - private boolean canBreakDoors; - private int inWaterTime; +@@ -93,22 +93,78 @@ public class Zombie extends Monster { + private boolean canBreakDoors = false; + private int inWaterTime = 0; public int conversionTime; - private boolean shouldBurnInDay = true; // Paper - Add more Zombie API + //private boolean shouldBurnInDay = true; // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight @@ -11535,7 +11527,7 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d this.addBehaviourGoals(); } -@@ -114,7 +170,19 @@ public class Zombie extends Monster { +@@ -118,7 +174,19 @@ public class Zombie extends Monster { this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0)); this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); @@ -11556,7 +11548,7 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); } -@@ -230,29 +298,7 @@ public class Zombie extends Monster { +@@ -234,29 +302,7 @@ public class Zombie extends Monster { @Override public void aiStep() { @@ -11587,7 +11579,7 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d super.aiStep(); } -@@ -311,6 +357,7 @@ public class Zombie extends Monster { +@@ -315,6 +361,7 @@ public class Zombie extends Monster { // CraftBukkit end } @@ -11595,7 +11587,7 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d public boolean isSunSensitive() { return this.shouldBurnInDay; // Paper - Add more Zombie API } -@@ -449,7 +496,7 @@ public class Zombie extends Monster { +@@ -452,7 +499,7 @@ public class Zombie extends Monster { compound.putBoolean("CanBreakDoors", this.canBreakDoors()); compound.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); compound.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); @@ -11604,16 +11596,16 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d } @Override -@@ -462,7 +509,7 @@ public class Zombie extends Monster { - this.startUnderWaterConversion(compound.getInt("DrownedConversionTime")); +@@ -467,7 +514,7 @@ public class Zombie extends Monster { + } else { + this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, false); } - // Paper start - Add more Zombie API -- if (compound.contains("Paper.ShouldBurnInDay")) { -+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight - this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay"); - } - // Paper end - Add more Zombie API -@@ -517,19 +564,18 @@ public class Zombie extends Monster { +- this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - Add more Zombie API ++ //this.shouldBurnInDay = compound.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight + } + + @Override +@@ -519,19 +566,18 @@ public class Zombie extends Monster { } if (spawnGroupData instanceof Zombie.ZombieGroupData zombieGroupData) { @@ -11638,8 +11630,8 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d + } else { // Purpur - Configurable jockey options Chicken chicken1 = EntityType.CHICKEN.create(this.level(), EntitySpawnReason.JOCKEY); if (chicken1 != null) { - chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); -@@ -538,6 +584,7 @@ public class Zombie extends Monster { + chicken1.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +@@ -540,6 +586,7 @@ public class Zombie extends Monster { this.startRiding(chicken1); level.addFreshEntity(chicken1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit } @@ -11647,7 +11639,7 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d } } } -@@ -550,10 +597,7 @@ public class Zombie extends Monster { +@@ -552,10 +599,7 @@ public class Zombie extends Monster { } if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { @@ -11657,9 +11649,9 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d - if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { + if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(level.getMinecraftWorld()) && this.random.nextFloat() < this.level().purpurConfig.chanceHeadHalloweenOnEntity) { // Purpur - Halloween options and optimizations this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); - this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + this.setDropChance(EquipmentSlot.HEAD, 0.0F); } -@@ -603,7 +647,7 @@ public class Zombie extends Monster { +@@ -605,7 +649,7 @@ public class Zombie extends Monster { } protected void randomizeReinforcementsChance() { @@ -11669,11 +11661,11 @@ index cf231380febd6d316eb902d43c636135ee0d7fa4..7af71c777dca26cd94b1807a2a77ea0d @Override diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java -index 8403257d81367c7371fa94d458a59a4589dc0bd7..aa5c02b5c949c80a96c1dd60fd3de8e2261fe797 100644 +index a8cd7103e636b57be1270d0f3549c709330b5536..ae5939c940bdd93977fa882360fc31e46479554f 100644 --- a/net/minecraft/world/entity/monster/ZombieVillager.java +++ b/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -78,6 +78,66 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { - .ifPresent(profession -> this.setVillagerData(this.getVillagerData().setProfession(profession.value()))); +@@ -77,6 +77,66 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { + .ifPresent(profession -> this.setVillagerData(this.getVillagerData().withProfession(profession))); } + // Purpur start - Ridables @@ -11739,7 +11731,7 @@ index 8403257d81367c7371fa94d458a59a4589dc0bd7..aa5c02b5c949c80a96c1dd60fd3de8e2 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -156,10 +216,10 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -130,10 +190,10 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemInHand = player.getItemInHand(hand); if (itemInHand.is(Items.GOLDEN_APPLE)) { @@ -11753,7 +11745,7 @@ index 8403257d81367c7371fa94d458a59a4589dc0bd7..aa5c02b5c949c80a96c1dd60fd3de8e2 return InteractionResult.SUCCESS_SERVER; diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index c7eab22fe4a0541ebdba96961521271ee5619cd4..fddbbffafea275dad187b7908386cf4c05c86743 100644 +index 05de183ce7b0be9b41f005b2ca36807a109fc634..39489c8a347031fb4f73faca46039786e35762ac 100644 --- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java +++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java @@ -63,6 +63,62 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { @@ -11819,25 +11811,33 @@ index c7eab22fe4a0541ebdba96961521271ee5619cd4..fddbbffafea275dad187b7908386cf4c @Override public void setPersistentAngerTarget(@Nullable UUID target) { this.persistentAngerTarget = target; -@@ -112,7 +168,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { +@@ -112,6 +168,12 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { this.maybeAlertOthers(); } -- if (this.isAngry()) { -+ if (this.isAngry() && this.level().purpurConfig.zombifiedPiglinCountAsPlayerKillWhenAngry) { // Purpur - Toggle for Zombified Piglin death always counting as player kill when angry - this.lastHurtByPlayerTime = this.tickCount; - } ++ // Purpur start - Toggle for Zombified Piglin death always counting as player kill when angry ++ if (this.isAngry() && this.level().purpurConfig.zombifiedPiglinCountAsPlayerKillWhenAngry) { ++ this.lastHurtByPlayerMemoryTime = this.tickCount; ++ } ++ // Purpur end - Toggle for Zombified Piglin death always counting as player kill when angry ++ + super.customServerAiStep(level); + } -@@ -163,7 +219,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { +@@ -159,6 +221,12 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); } -- if (livingEntity instanceof Player) { -+ if (livingEntity instanceof Player && this.level().purpurConfig.zombifiedPiglinCountAsPlayerKillWhenAngry) { // Purpur - Toggle for Zombified Piglin death always counting as player kill when angry - this.setLastHurtByPlayer((Player)livingEntity); - } ++ // Purpur start - Toggle for Zombified Piglin death always counting as player kill when angry ++ if (livingEntity instanceof Player player && this.level().purpurConfig.zombifiedPiglinCountAsPlayerKillWhenAngry) { ++ this.setLastHurtByPlayer(player, this.tickCount); ++ } ++ // Purpur end - Toggle for Zombified Piglin death always counting as player kill when angry ++ + return super.setTarget(livingEntity, reason); // CraftBukkit + } -@@ -245,7 +301,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { +@@ -236,7 +304,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { @Override protected void randomizeReinforcementsChance() { @@ -11847,7 +11847,7 @@ index c7eab22fe4a0541ebdba96961521271ee5619cd4..fddbbffafea275dad187b7908386cf4c @Nullable diff --git a/net/minecraft/world/entity/monster/creaking/Creaking.java b/net/minecraft/world/entity/monster/creaking/Creaking.java -index 6cd7d0f82bd97c6adb521eda3bc84c60f87c0cda..2c6833753950f1bb0941b0cbe54bebddb84b137d 100644 +index 2183f5aaf6cf7a4df8c659f0766af40289761987..c9404d72de59e18dc809b8dec107f1f23d50f441 100644 --- a/net/minecraft/world/entity/monster/creaking/Creaking.java +++ b/net/minecraft/world/entity/monster/creaking/Creaking.java @@ -100,6 +100,37 @@ public class Creaking extends Monster { @@ -11888,7 +11888,7 @@ index 6cd7d0f82bd97c6adb521eda3bc84c60f87c0cda..2c6833753950f1bb0941b0cbe54bebdd @Override protected BodyRotationControl createBodyControl() { return new Creaking.CreakingBodyRotationControl(this); -@@ -575,28 +606,28 @@ public class Creaking extends Monster { +@@ -566,28 +597,28 @@ public class Creaking extends Monster { } } @@ -11924,10 +11924,10 @@ index 6cd7d0f82bd97c6adb521eda3bc84c60f87c0cda..2c6833753950f1bb0941b0cbe54bebdd } } diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java -index f93d6564c59ae9a144b56ea3355c4c7425b99eeb..7c119b089259add643cd112efac55f92024d0275 100644 +index 6691dc90c35d05a7c28c4e3ac887ed9d3bb88de9..584955d151e95727406bc68d6a6f15a33c0f920c 100644 --- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java +++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java -@@ -90,6 +90,52 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { +@@ -93,6 +93,52 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { this.xpReward = 5; } @@ -11980,7 +11980,7 @@ index f93d6564c59ae9a144b56ea3355c4c7425b99eeb..7c119b089259add643cd112efac55f92 @VisibleForTesting public void setTimeInOverworld(int timeInOverworld) { this.timeInOverworld = timeInOverworld; -@@ -157,6 +203,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { +@@ -160,6 +206,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { private int behaviorTick; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -11989,10 +11989,10 @@ index f93d6564c59ae9a144b56ea3355c4c7425b99eeb..7c119b089259add643cd112efac55f92 this.getBrain().tick(level, this); HoglinAi.updateActivity(this); diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java -index 4c30f967c12e11c2e7ae24977509762747dd36de..242b2545b6082f567d0bb7900ef06ded3c0fdcdd 100644 +index 634c518c105c8dc50838a4a6690641d82fd637fb..bac328ebdf9f94d156211e03d3913157e2b80374 100644 --- a/net/minecraft/world/entity/monster/piglin/Piglin.java +++ b/net/minecraft/world/entity/monster/piglin/Piglin.java -@@ -149,6 +149,45 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -134,6 +134,45 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento this.xpReward = 5; } @@ -12038,7 +12038,7 @@ index 4c30f967c12e11c2e7ae24977509762747dd36de..242b2545b6082f567d0bb7900ef06ded @Override public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); -@@ -343,6 +382,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -318,6 +357,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento private int behaviorTick; // Pufferfish @Override protected void customServerAiStep(ServerLevel level) { @@ -12046,7 +12046,7 @@ index 4c30f967c12e11c2e7ae24977509762747dd36de..242b2545b6082f567d0bb7900ef06ded if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish this.getBrain().tick(level, this); PiglinAi.updateActivity(this); -@@ -444,7 +484,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -420,7 +460,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento @Override public boolean wantsToPickUp(ServerLevel level, ItemStack stack) { @@ -12056,27 +12056,22 @@ index 4c30f967c12e11c2e7ae24977509762747dd36de..242b2545b6082f567d0bb7900ef06ded protected boolean canReplaceCurrentItem(ItemStack candidate) { diff --git a/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/net/minecraft/world/entity/monster/piglin/PiglinAi.java -index d0af8fc156408db7172267d45636b3c9e66d638c..650783aaa4ab1a3198cdfb74fd02edff969d8921 100644 +index 4b1a3772f9e6b9e4efcf11e14b0fb882512ec86d..df1ef03f584fcaa31bd8cfd2c7301c784e4270d8 100644 --- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java +++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java -@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableSet; - import com.mojang.datafixers.util.Pair; - import java.util.Collections; -+import java.util.Iterator; - import java.util.List; - import java.util.Optional; - import net.minecraft.server.level.ServerLevel; -@@ -666,7 +667,7 @@ public class PiglinAi { +@@ -661,7 +661,10 @@ public class PiglinAi { public static boolean isWearingSafeArmor(LivingEntity entity) { - for (ItemStack itemStack : entity.getArmorAndBodyArmorSlots()) { -- if (itemStack.is(ItemTags.PIGLIN_SAFE_ARMOR)) { -+ if (itemStack.is(ItemTags.PIGLIN_SAFE_ARMOR) || (entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim && isWearingGoldTrim(itemStack.getItem()))) { // Purpur - piglins ignore gold-trimmed armor + for (EquipmentSlot equipmentSlot : EquipmentSlotGroup.ARMOR) { +- if (entity.getItemBySlot(equipmentSlot).is(ItemTags.PIGLIN_SAFE_ARMOR)) { ++ // Purpur start - piglins ignore gold-trimmed armor ++ net.minecraft.world.item.ItemStack itemStack = entity.getItemBySlot(equipmentSlot); ++ if (itemStack.is(ItemTags.PIGLIN_SAFE_ARMOR) || (entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim && isWearingGoldTrim(itemStack.getItem()))) { ++ // Purpur end - piglins ignore gold-trimmed armor return true; } } -@@ -674,6 +675,13 @@ public class PiglinAi { +@@ -669,6 +672,13 @@ public class PiglinAi { return false; } @@ -12091,7 +12086,7 @@ index d0af8fc156408db7172267d45636b3c9e66d638c..650783aaa4ab1a3198cdfb74fd02edff piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); piglin.getNavigation().stop(); diff --git a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -index e5f91e64f61bdb7b7f7e3f101083e9bd5dbe7551..460dace4818605ecd5409be887013713f06442a5 100644 +index 589a130f8855f464c1930a0aa8b54c0326a22e23..c4eb58d0b0c51e930f9cb72e1de0103902badba7 100644 --- a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +++ b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java @@ -63,6 +63,45 @@ public class PiglinBrute extends AbstractPiglin { @@ -12149,10 +12144,10 @@ index e5f91e64f61bdb7b7f7e3f101083e9bd5dbe7551..460dace4818605ecd5409be887013713 PiglinBruteAi.updateActivity(this); PiglinBruteAi.maybePlayActivitySound(this); diff --git a/net/minecraft/world/entity/monster/warden/Warden.java b/net/minecraft/world/entity/monster/warden/Warden.java -index f7b9824519fc22b35a7b5f4f0ef9f9891162a493..26f3fe1c80b0d87b96076432f35fe4f95f92ce13 100644 +index 42ca4243d86ef4a14a9ce70da4b79f6c8eeb3a7d..497ea5d5aad1641d5876f23f05db82ab649c0785 100644 --- a/net/minecraft/world/entity/monster/warden/Warden.java +++ b/net/minecraft/world/entity/monster/warden/Warden.java -@@ -127,8 +127,32 @@ public class Warden extends Monster implements VibrationSystem { +@@ -124,8 +124,32 @@ public class Warden extends Monster implements VibrationSystem { this.setPathfindingMalus(PathType.LAVA, 8.0F); this.setPathfindingMalus(PathType.DAMAGE_FIRE, 0.0F); this.setPathfindingMalus(PathType.DANGER_FIRE, 0.0F); @@ -12185,7 +12180,7 @@ index f7b9824519fc22b35a7b5f4f0ef9f9891162a493..26f3fe1c80b0d87b96076432f35fe4f9 @Override public Packet getAddEntityPacket(ServerEntity entity) { return new ClientboundAddEntityPacket(this, entity, this.hasPose(Pose.EMERGING) ? 1 : 0); -@@ -391,6 +415,7 @@ public class Warden extends Monster implements VibrationSystem { +@@ -388,6 +412,7 @@ public class Warden extends Monster implements VibrationSystem { @Contract("null->false") public boolean canTargetEntity(@Nullable Entity entity) { @@ -12194,64 +12189,65 @@ index f7b9824519fc22b35a7b5f4f0ef9f9891162a493..26f3fe1c80b0d87b96076432f35fe4f9 && this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java -index a71d16d968bb90fd7aca6f01a3dd56df4f9a7ce6..b4e79cac5611942240ce85120f7bbee329ae2fb8 100644 +index 1d3381f1481bb2b192bb78462c85c2a185d94ad5..e574c38e1c1c13fc2f96340138f784697cef8c48 100644 --- a/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -45,6 +45,8 @@ import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end +@@ -35,6 +35,7 @@ import net.minecraft.world.level.portal.TeleportTransition; + import net.minecraft.world.phys.Vec3; public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { + static final net.minecraft.world.item.crafting.Ingredient TEMPT_ITEMS = net.minecraft.world.item.crafting.Ingredient.of(net.minecraft.world.level.block.Blocks.EMERALD_BLOCK.asItem()); // Purpur - Villagers follow emerald blocks -+ - // CraftBukkit start - @Override - public CraftMerchant getCraftMerchant() { + private static final EntityDataAccessor DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; diff --git a/net/minecraft/world/entity/npc/CatSpawner.java b/net/minecraft/world/entity/npc/CatSpawner.java -index e6d368bc601357cfca694ce328c8e6e47491f3b5..489613b31fe47a0bd43fafddbeab6bb61c17505d 100644 +index e282b6ab6d0d1c11ee40f5f436bd50fa90ddc88b..d6ae13c19481ce33bfa0b6c9db63283009339d8c 100644 --- a/net/minecraft/world/entity/npc/CatSpawner.java +++ b/net/minecraft/world/entity/npc/CatSpawner.java -@@ -27,7 +27,7 @@ public class CatSpawner implements CustomSpawner { - if (this.nextTick > 0) { - return 0; - } else { +@@ -25,7 +25,7 @@ public class CatSpawner implements CustomSpawner { + if (spawnFriendlies && level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + this.nextTick--; + if (this.nextTick <= 0) { - this.nextTick = 1200; + this.nextTick = level.purpurConfig.catSpawnDelay; // Purpur - Cat spawning options Player randomPlayer = level.getRandomPlayer(); - if (randomPlayer == null) { - return 0; -@@ -61,8 +61,12 @@ public class CatSpawner implements CustomSpawner { - - private int spawnInVillage(ServerLevel serverLevel, BlockPos pos) { - int i = 48; -- if (serverLevel.getPoiManager().getCountInRange(holder -> holder.is(PoiTypes.HOME), pos, 48, PoiManager.Occupancy.IS_OCCUPIED) > 4L) { -- List entitiesOfClass = serverLevel.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(48.0, 8.0, 48.0)); -+ // Purpur start - Cat spawning options -+ int range = serverLevel.purpurConfig.catSpawnVillageScanRange; -+ if (range <= 0) return 0; -+ if (serverLevel.getPoiManager().getCountInRange(holder -> holder.is(PoiTypes.HOME), pos, range, PoiManager.Occupancy.IS_OCCUPIED) > 4L) { -+ List entitiesOfClass = serverLevel.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(range, 8.0, range)); -+ // Purpur end - Cat spawning options - if (entitiesOfClass.size() < 5) { - return this.spawnCat(pos, serverLevel); - } -@@ -73,7 +77,11 @@ public class CatSpawner implements CustomSpawner { - - private int spawnInHut(ServerLevel serverLevel, BlockPos pos) { - int i = 16; -- List entitiesOfClass = serverLevel.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(16.0, 8.0, 16.0)); -+ // Purpur start - Cat spawning options -+ int range = serverLevel.purpurConfig.catSpawnSwampHutScanRange; -+ if (range <= 0) return 0; -+ List entitiesOfClass = serverLevel.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(range, 8.0, range)); -+ // Purpur end - Cat spawning options - return entitiesOfClass.size() < 1 ? this.spawnCat(pos, serverLevel) : 0; + if (randomPlayer != null) { + RandomSource randomSource = level.random; +@@ -48,9 +48,12 @@ public class CatSpawner implements CustomSpawner { } + private void spawnInVillage(ServerLevel level, BlockPos pos) { +- int i = 48; +- if (level.getPoiManager().getCountInRange(holder -> holder.is(PoiTypes.HOME), pos, 48, PoiManager.Occupancy.IS_OCCUPIED) > 4L) { +- List entitiesOfClass = level.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(48.0, 8.0, 48.0)); ++ // Purpur start - Cat spawning options ++ int range = level.purpurConfig.catSpawnVillageScanRange; ++ if (range <= 0) return; ++ if (level.getPoiManager().getCountInRange(holder -> holder.is(PoiTypes.HOME), pos, range, PoiManager.Occupancy.IS_OCCUPIED) > 4L) { ++ List entitiesOfClass = level.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(range, 8.0, range)); ++ // Purpur end - Cat spawning options + if (entitiesOfClass.size() < 5) { + this.spawnCat(pos, level, false); + } +@@ -58,8 +61,11 @@ public class CatSpawner implements CustomSpawner { + } + + private void spawnInHut(ServerLevel level, BlockPos pos) { +- int i = 16; +- List entitiesOfClass = level.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(16.0, 8.0, 16.0)); ++ // Purpur start - Cat spawning options ++ int range = level.purpurConfig.catSpawnSwampHutScanRange; ++ if (range <= 0) return; ++ List entitiesOfClass = level.getEntitiesOfClass(Cat.class, new AABB(pos).inflate(range, 8.0, range)); ++ // Purpur end - Cat spawning options + if (entitiesOfClass.isEmpty()) { + this.spawnCat(pos, level, true); + } diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182ee291775 100644 +index cb9c722251e01cbbd827af9aff5f5942c62d2011..530a7873a0796bb5e8e25b91586d6c4cfa00a08c 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -179,6 +179,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -178,6 +178,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler ); public long nextGolemPanic = -1; // Pufferfish @@ -12260,8 +12256,8 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 public Villager(EntityType entityType, Level level) { this(entityType, level, VillagerType.PLAINS); -@@ -193,6 +195,103 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - this.setVillagerData(this.getVillagerData().setType(villagerType).setProfession(VillagerProfession.NONE)); +@@ -196,6 +198,103 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.setVillagerData(this.getVillagerData().withType(villagerType).withProfession(level.registryAccess(), VillagerProfession.NONE)); } + // Purpur start - Allow leashing villagers @@ -12364,16 +12360,16 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 @Override public Brain getBrain() { return (Brain)super.getBrain(); -@@ -226,7 +325,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -229,7 +328,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler villagerBrain.setSchedule(Schedule.VILLAGER_DEFAULT); villagerBrain.addActivityWithConditions( Activity.WORK, -- VillagerGoalPackages.getWorkPackage(profession, 0.5F), -+ VillagerGoalPackages.getWorkPackage(profession, 0.5F, this.level().purpurConfig.villagerClericsFarmWarts), // Purpur - Option for Villager Clerics to farm Nether Wart +- VillagerGoalPackages.getWorkPackage(holder, 0.5F), ++ VillagerGoalPackages.getWorkPackage(holder, 0.5F, this.level().purpurConfig.villagerClericsFarmWarts), // Purpur - Option for Villager Clerics to farm Nether Wart ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT)) ); } -@@ -258,7 +357,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -261,7 +360,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } public static AttributeSupplier.Builder createAttributes() { @@ -12382,7 +12378,7 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 } public boolean assignProfessionWhenSpawned() { -@@ -290,12 +389,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -293,12 +392,20 @@ public class Villager extends AbstractVillager implements ReputationEventHandler // Paper start - EAR 2 this.customServerAiStep(level, false); } @@ -12401,12 +12397,12 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 - if (!inactive && this.behaviorTick++ % this.activatedPriority == 0) { + if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur - Ridables this.getBrain().tick(level, this); // Paper - EAR 2 - } -+ else if (this.isLobotomized && shouldRestock()) restock(); // Purpur - Lobotomize stuck villagers +- } ++ } else if (this.isLobotomized && shouldRestock()) restock(); // Purpur - Lobotomize stuck villagers // Pufferfish end if (this.assignProfessionWhenSpawned) { this.assignProfessionWhenSpawned = false; -@@ -351,7 +459,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -354,7 +461,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler return super.mobInteract(player, hand); } else if (this.isBaby()) { this.setUnhappy(); @@ -12415,7 +12411,7 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 } else { if (!this.level().isClientSide) { boolean isEmpty = this.getOffers().isEmpty(); -@@ -364,9 +472,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -367,9 +474,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } if (isEmpty) { @@ -12429,7 +12425,7 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 this.startTrading(player); } -@@ -505,7 +616,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -506,7 +616,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler private void updateDemand() { for (MerchantOffer merchantOffer : this.getOffers()) { @@ -12438,7 +12434,7 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 } } -@@ -709,7 +820,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -699,7 +809,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public boolean canBreed() { @@ -12447,16 +12443,16 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 } private boolean hungry() { -@@ -878,7 +989,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -866,7 +976,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } public boolean hasFarmSeeds() { -- return this.getInventory().hasAnyMatching(itemStack -> itemStack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); -+ return this.getInventory().hasAnyMatching(itemStack -> this.level().purpurConfig.villagerClericsFarmWarts && this.getVillagerData().getProfession() == VillagerProfession.CLERIC ? itemStack.is(Items.NETHER_WART) : itemStack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); // Purpur - Option for Villager Clerics to farm Nether Wart +- return this.getInventory().hasAnyMatching(stack -> stack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); ++ return this.getInventory().hasAnyMatching(stack -> this.level().purpurConfig.villagerClericsFarmWarts && this.getVillagerData().profession().is(VillagerProfession.CLERIC) ? stack.is(Items.NETHER_WART) : stack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); // Purpur - Option for Villager Clerics to farm Nether Wart } @Override -@@ -930,6 +1041,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -921,6 +1031,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int minVillagerAmount) { @@ -12464,7 +12460,7 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 if (this.wantsToSpawnGolem(gameTime)) { AABB aabb = this.getBoundingBox().inflate(10.0, 10.0, 10.0); List entitiesOfClass = serverLevel.getEntitiesOfClass(Villager.class, aabb); -@@ -1003,6 +1115,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -994,6 +1105,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public void startSleeping(BlockPos pos) { @@ -12478,23 +12474,23 @@ index a02cd34bcd643c7abad3a355043cb88d035143a0..e8e2848c12e3cf2ad86fc3bd18f03182 this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); diff --git a/net/minecraft/world/entity/npc/VillagerProfession.java b/net/minecraft/world/entity/npc/VillagerProfession.java -index 1ec8ad124c76483d11057eb97fcfb9aebee0c301..f783d058a080408d572938d36ba031f33a08e9af 100644 +index 0b7fdbc19f8a977be8168bca198c157fbe90044b..abfc2542a486d5a64bf88eac69f7d9587869d3cf 100644 --- a/net/minecraft/world/entity/npc/VillagerProfession.java +++ b/net/minecraft/world/entity/npc/VillagerProfession.java -@@ -31,7 +31,7 @@ public record VillagerProfession( - public static final VillagerProfession ARMORER = register("armorer", PoiTypes.ARMORER, SoundEvents.VILLAGER_WORK_ARMORER); - public static final VillagerProfession BUTCHER = register("butcher", PoiTypes.BUTCHER, SoundEvents.VILLAGER_WORK_BUTCHER); - public static final VillagerProfession CARTOGRAPHER = register("cartographer", PoiTypes.CARTOGRAPHER, SoundEvents.VILLAGER_WORK_CARTOGRAPHER); -- public static final VillagerProfession CLERIC = register("cleric", PoiTypes.CLERIC, SoundEvents.VILLAGER_WORK_CLERIC); -+ public static final VillagerProfession CLERIC = register("cleric", PoiTypes.CLERIC, ImmutableSet.of(Items.NETHER_WART), ImmutableSet.of(Blocks.SOUL_SAND), SoundEvents.VILLAGER_WORK_CLERIC); // Purpur - Option for Villager Clerics to farm Nether Wart - public static final VillagerProfession FARMER = register( - "farmer", - PoiTypes.FARMER, +@@ -103,7 +103,7 @@ public record VillagerProfession( + register(registry, ARMORER, PoiTypes.ARMORER, SoundEvents.VILLAGER_WORK_ARMORER); + register(registry, BUTCHER, PoiTypes.BUTCHER, SoundEvents.VILLAGER_WORK_BUTCHER); + register(registry, CARTOGRAPHER, PoiTypes.CARTOGRAPHER, SoundEvents.VILLAGER_WORK_CARTOGRAPHER); +- register(registry, CLERIC, PoiTypes.CLERIC, SoundEvents.VILLAGER_WORK_CLERIC); ++ register(registry, CLERIC, PoiTypes.CLERIC, ImmutableSet.of(Items.NETHER_WART), ImmutableSet.of(Blocks.SOUL_SAND), SoundEvents.VILLAGER_WORK_CLERIC); // Purpur - Option for Villager Clerics to farm Nether Wart + register( + registry, + FARMER, diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java -index 6655d06e2011e20e7346dfe57527795269094d8a..c3fbcc7956a64d49466874776f257ba27f55f2a4 100644 +index 70cc20483905d3877e2ffb51afb4902bd59f0cd0..776e4d001bc6e6d419eb4392dc85bf4594e57058 100644 --- a/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -69,6 +69,58 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -59,6 +59,58 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill super(entityType, level); } @@ -12553,16 +12549,16 @@ index 6655d06e2011e20e7346dfe57527795269094d8a..c3fbcc7956a64d49466874776f257ba2 @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); -@@ -89,7 +141,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -79,7 +131,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, -- wanderingTrader -> this.canDrinkMilk && this.level().isDay() && wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API -+ wanderingTrader -> level().purpurConfig.milkClearsBeneficialEffects && this.canDrinkMilk && this.level().isDay() && wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API // // Purpur - Milk Keeps Beneficial Effects +- wanderingTrader -> this.canDrinkMilk && this.level().isBrightOutside() && wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API ++ wanderingTrader -> level().purpurConfig.milkClearsBeneficialEffects && this.canDrinkMilk && this.level().isBrightOutside() && wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API // // Purpur - Milk Keeps Beneficial Effects ) ); this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); -@@ -103,6 +155,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -93,6 +145,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill this.goalSelector.addGoal(1, new PanicGoal(this, 0.5)); this.goalSelector.addGoal(1, new LookAtTradingPlayerGoal(this)); this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0, 0.35)); @@ -12570,7 +12566,7 @@ index 6655d06e2011e20e7346dfe57527795269094d8a..c3fbcc7956a64d49466874776f257ba2 this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35)); this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35)); this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F)); -@@ -130,11 +183,14 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -120,11 +173,14 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill if (!this.level().isClientSide) { if (this.getOffers().isEmpty()) { @@ -12587,10 +12583,10 @@ index 6655d06e2011e20e7346dfe57527795269094d8a..c3fbcc7956a64d49466874776f257ba2 return InteractionResult.SUCCESS; diff --git a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index ef2afb17a22a703470e13d12c989a685e72f0ab8..80a01b8c6dfb0f3bcc6872cdf38b48f7a9ce4b8b 100644 +index 9d9ec2bf16027b479bbc4339ad4e9dcfc2077d40..d4527765262818099dfb695d6a84b56d33888e34 100644 --- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -@@ -147,7 +147,17 @@ public class WanderingTraderSpawner implements CustomSpawner { +@@ -137,7 +137,17 @@ public class WanderingTraderSpawner implements CustomSpawner { int i1 = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance; int i2 = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance; int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, i2); @@ -12610,11 +12606,11 @@ index ef2afb17a22a703470e13d12c989a685e72f0ab8..80a01b8c6dfb0f3bcc6872cdf38b48f7 blockPos = blockPos1; break; diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12dabb078d9b 100644 +index 2aca22f978daa826bf7ac2b25f13bf30a1bd4284..4217131b5f7aa985d5af452554849847a36ce9ce 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -201,11 +201,22 @@ public abstract class Player extends LivingEntity { - private int currentImpulseContextResetGraceTime; +@@ -211,11 +211,22 @@ public abstract class Player extends LivingEntity { + private int currentImpulseContextResetGraceTime = 0; public boolean affectsSpawning = true; // Paper - Affects Spawning API public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage + public int burpDelay = 0; // Purpur - Burp delay @@ -12636,7 +12632,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da @Override public org.bukkit.craftbukkit.entity.CraftHumanEntity getBukkitEntity() { return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity(); -@@ -214,6 +225,19 @@ public abstract class Player extends LivingEntity { +@@ -224,6 +235,19 @@ public abstract class Player extends LivingEntity { public final int sendAllPlayerInfoBucketIndex; // Gale - Purpur - spread out sending all player info @@ -12656,7 +12652,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { super(EntityType.PLAYER, level); this.setUUID(gameProfile.getId()); -@@ -266,6 +290,12 @@ public abstract class Player extends LivingEntity { +@@ -281,6 +305,12 @@ public abstract class Player extends LivingEntity { @Override public void tick() { @@ -12669,7 +12665,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da this.noPhysics = this.isSpectator(); if (this.isSpectator() || this.isPassenger()) { this.setOnGround(false); -@@ -348,6 +378,17 @@ public abstract class Player extends LivingEntity { +@@ -363,6 +393,17 @@ public abstract class Player extends LivingEntity { this.turtleHelmetTick(); } @@ -12687,7 +12683,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da this.cooldowns.tick(); this.updatePlayerPose(); if (this.currentImpulseContextResetGraceTime > 0) { -@@ -618,7 +659,7 @@ public abstract class Player extends LivingEntity { +@@ -628,7 +669,7 @@ public abstract class Player extends LivingEntity { List list = Lists.newArrayList(); for (Entity entity : entities) { @@ -12696,7 +12692,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da list.add(entity); } else if (!entity.isRemoved()) { this.touch(entity); -@@ -1277,7 +1318,7 @@ public abstract class Player extends LivingEntity { +@@ -1222,7 +1263,7 @@ public abstract class Player extends LivingEntity { flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits if (flag2) { damageSource = damageSource.critical(); // Paper - critical damage API @@ -12705,7 +12701,7 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da } float f2 = f + f1; -@@ -1892,7 +1933,23 @@ public abstract class Player extends LivingEntity { +@@ -1819,7 +1860,23 @@ public abstract class Player extends LivingEntity { @Override protected int getBaseExperienceReward(ServerLevel level) { @@ -12730,8 +12726,8 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da } @Override -@@ -1976,6 +2033,13 @@ public abstract class Player extends LivingEntity { - return slot != EquipmentSlot.BODY; +@@ -1858,6 +1915,13 @@ public abstract class Player extends LivingEntity { + return this.inventory.add(stack); } + // Purpur start - Player ridable in water option @@ -12745,18 +12741,18 @@ index e587f8125ab29b3f9c829cd225deb5b7a6b7affa..477455fdfcc591a89823e88983eb12da if (this.isPassenger() || !this.onGround() || this.isInWater() || this.isInPowderSnow) { return false; diff --git a/net/minecraft/world/entity/projectile/AbstractArrow.java b/net/minecraft/world/entity/projectile/AbstractArrow.java -index aa301c849b020fac951f8afa7cd27401def16d3a..ecf25b60096f6a77a7bd6b6212d322adb3fe5e8a 100644 +index b8f04b98d2117cfb274a5888d34b9836d3390ae9..6bb0653d1d033745ff419d4a59b4d89014b9cbe4 100644 --- a/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -74,6 +74,7 @@ public abstract class AbstractArrow extends Projectile { - public ItemStack pickupItemStack = this.getDefaultPickupItem(); // Paper - private -> public +@@ -79,6 +79,7 @@ public abstract class AbstractArrow extends Projectile { + public ItemStack pickupItemStack = this.getDefaultPickupItem(); @Nullable - public ItemStack firedFromWeapon = null; // Paper - private -> public + public ItemStack firedFromWeapon = null; + public net.minecraft.world.item.enchantment.ItemEnchantments actualEnchantments = net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY; // Purpur - Add an option to fix MC-3304 projectile looting protected AbstractArrow(EntityType entityType, Level level) { super(entityType, level); -@@ -560,6 +561,12 @@ public abstract class AbstractArrow extends Projectile { +@@ -576,6 +577,12 @@ public abstract class AbstractArrow extends Projectile { return this.firedFromWeapon; } @@ -12770,10 +12766,10 @@ index aa301c849b020fac951f8afa7cd27401def16d3a..ecf25b60096f6a77a7bd6b6212d322ad return SoundEvents.ARROW_HIT; } diff --git a/net/minecraft/world/entity/projectile/LargeFireball.java b/net/minecraft/world/entity/projectile/LargeFireball.java -index 4a752ace041228f095af7b1b4878a03c5ed2381f..3e8b5d042eddb817dee2504ff9aa263f6195b1c7 100644 +index db1b5bce212a5147be82504469f1fa9660812ebc..b97ea6fea26182945b6360644f17d172166574d3 100644 --- a/net/minecraft/world/entity/projectile/LargeFireball.java +++ b/net/minecraft/world/entity/projectile/LargeFireball.java -@@ -18,20 +18,20 @@ public class LargeFireball extends Fireball { +@@ -19,20 +19,20 @@ public class LargeFireball extends Fireball { public LargeFireball(EntityType entityType, Level level) { super(entityType, level); @@ -12796,9 +12792,9 @@ index 4a752ace041228f095af7b1b4878a03c5ed2381f..3e8b5d042eddb817dee2504ff9aa263f + boolean _boolean = serverLevel.purpurConfig.fireballsBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur - Add mobGriefing bypass to everything affected // CraftBukkit start - fire ExplosionPrimeEvent org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); - this.level().getCraftServer().getPluginManager().callEvent(event); + if (event.callEvent()) { diff --git a/net/minecraft/world/entity/projectile/LlamaSpit.java b/net/minecraft/world/entity/projectile/LlamaSpit.java -index 4880db97135d54fa72f64c108b2bd4ded096438b..bc102b049047d6e2a1d29e10f92cdf5ae2c140bd 100644 +index f736f72b8e76dd82236badcdd2756f0d4da89aa4..0dbfbadcabcf1b719addb034e676cb51b74199d7 100644 --- a/net/minecraft/world/entity/projectile/LlamaSpit.java +++ b/net/minecraft/world/entity/projectile/LlamaSpit.java @@ -33,6 +33,12 @@ public class LlamaSpit extends Projectile { @@ -12815,10 +12811,10 @@ index 4880db97135d54fa72f64c108b2bd4ded096438b..bc102b049047d6e2a1d29e10f92cdf5a protected double getDefaultGravity() { return 0.06; diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java -index 168f50523b00ab8d43cbcc5ea5675a840762be11..a33641dd6e0839fd1b557d8583fe8bb929fcc1cb 100644 +index 84c846d2ef4990befb2891631ac5ae16d881401b..bde9370798c037c494a9c73f328cb251e68c21b1 100644 --- a/net/minecraft/world/entity/projectile/Projectile.java +++ b/net/minecraft/world/entity/projectile/Projectile.java -@@ -503,7 +503,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -515,7 +515,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { @Override public boolean mayInteract(ServerLevel level, BlockPos pos) { Entity owner = this.getOwner(); @@ -12841,7 +12837,7 @@ index 8c84cea43fc0e42a576004663670977eac99f1a6..808aa5dcb27c87b6ba5c1eee63948606 // CraftBukkit end } diff --git a/net/minecraft/world/entity/projectile/Snowball.java b/net/minecraft/world/entity/projectile/Snowball.java -index c57bbdc13221d2ce349f3f1d894193f80ff1e24b..1d399532c67c213c95c06837b0c7855384f1a25c 100644 +index 677b4b681f9c2c09a8ae3cfdec72102265547a7b..d8f9fb603fd2e3e5c1dfc05face7f42b4844daf4 100644 --- a/net/minecraft/world/entity/projectile/Snowball.java +++ b/net/minecraft/world/entity/projectile/Snowball.java @@ -52,10 +52,40 @@ public class Snowball extends ThrowableItemProjectile { @@ -12887,10 +12883,10 @@ index c57bbdc13221d2ce349f3f1d894193f80ff1e24b..1d399532c67c213c95c06837b0c78553 protected void onHit(HitResult result) { super.onHit(result); diff --git a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index 1345097a2a417f95c44143fd7e0d4cec38990121..d212f57c8c0b2086f567fd30237b110203d9e8cb 100644 +index bda858b1e1c6b28cd9d5a664758b3e445eaf4f22..6575e8ef16f6011f7a799ba31531a2ebefee0c4d 100644 --- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -133,9 +133,10 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -129,9 +129,10 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { return; } // CraftBukkit end @@ -12899,10 +12895,10 @@ index 1345097a2a417f95c44143fd7e0d4cec38990121..d212f57c8c0b2086f567fd30237b1102 Endermite endermite = EntityType.ENDERMITE.create(serverLevel, EntitySpawnReason.TRIGGERED); if (endermite != null) { + endermite.setPlayerSpawned(true); // Purpur - Add back player spawned endermite API - endermite.moveTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot()); + endermite.snapTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot()); serverLevel.addFreshEntity(endermite, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.ENDER_PEARL); } -@@ -155,7 +156,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -151,7 +152,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { if (serverPlayer1 != null) { serverPlayer1.resetFallDistance(); serverPlayer1.resetCurrentImpulseContext(); @@ -12912,10 +12908,10 @@ index 1345097a2a417f95c44143fd7e0d4cec38990121..d212f57c8c0b2086f567fd30237b1102 this.playSound(serverLevel, vec3); diff --git a/net/minecraft/world/entity/projectile/ThrownTrident.java b/net/minecraft/world/entity/projectile/ThrownTrident.java -index 2c66f788759330fba412ccb2187945b6ca0cacb6..251e9a368800afab1a47bb9162077b2e76f4397f 100644 +index 00f805667ea48fd8699f3cea05781739e376cedd..e814daaa10c138b1497dffbdf9224d34cd9c9926 100644 --- a/net/minecraft/world/entity/projectile/ThrownTrident.java +++ b/net/minecraft/world/entity/projectile/ThrownTrident.java -@@ -64,7 +64,7 @@ public class ThrownTrident extends AbstractArrow { +@@ -65,7 +65,7 @@ public class ThrownTrident extends AbstractArrow { Entity owner = this.getOwner(); int i = this.entityData.get(ID_LOYALTY); @@ -12925,19 +12921,19 @@ index 2c66f788759330fba412ccb2187945b6ca0cacb6..251e9a368800afab1a47bb9162077b2e if (this.level() instanceof ServerLevel serverLevel && this.pickup == AbstractArrow.Pickup.ALLOWED) { this.spawnAtLocation(serverLevel, this.getPickupItem(), 0.1F); diff --git a/net/minecraft/world/entity/projectile/WitherSkull.java b/net/minecraft/world/entity/projectile/WitherSkull.java -index c4cdc7655a8e4931717e9fa788c5811879526e9e..a0b909c745ea60cae73def06f9d947345911c5e4 100644 +index a2fdc87bedd1a63064cb8c7a7615978483268fdc..8e95577de28fc4834dcfc3d4fed747d9d14b1618 100644 --- a/net/minecraft/world/entity/projectile/WitherSkull.java +++ b/net/minecraft/world/entity/projectile/WitherSkull.java -@@ -92,7 +92,7 @@ public class WitherSkull extends AbstractHurtingProjectile { +@@ -93,7 +93,7 @@ public class WitherSkull extends AbstractHurtingProjectile { super.onHit(result); if (!this.level().isClientSide) { // CraftBukkit start - org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); + org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent(this.getBukkitEntity(), this.level().purpurConfig.witherExplosionRadius, false); // Purpur - Config for wither explosion radius - this.level().getCraftServer().getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -@@ -103,6 +103,21 @@ public class WitherSkull extends AbstractHurtingProjectile { + if (event.callEvent()) { + this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); + } +@@ -102,6 +102,21 @@ public class WitherSkull extends AbstractHurtingProjectile { } } @@ -12960,10 +12956,10 @@ index c4cdc7655a8e4931717e9fa788c5811879526e9e..a0b909c745ea60cae73def06f9d94734 protected void defineSynchedData(SynchedEntityData.Builder builder) { builder.define(DATA_DANGEROUS, false); diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index 8270d76a753bfd26a4c8ef6610bee5c24ee59cfe..c06b589e669b055a26f662df60070d5908256220 100644 +index e81ae747fe95c22321fc69791a6509d601826fd6..77bb3aa7ff042aab6464aac55c846cb9082e5b97 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java -@@ -399,7 +399,7 @@ public abstract class Raider extends PatrollingMonster { +@@ -400,7 +400,7 @@ public abstract class Raider extends PatrollingMonster { } private boolean cannotPickUpBanner() { @@ -12973,20 +12969,20 @@ index 8270d76a753bfd26a4c8ef6610bee5c24ee59cfe..c06b589e669b055a26f662df60070d59 return true; } else if (this.mob.getCurrentRaid().isOver()) { diff --git a/net/minecraft/world/entity/raid/Raids.java b/net/minecraft/world/entity/raid/Raids.java -index 34eb038725d1577f1a2d7c35c897b1270eac5749..497915338d406815d6b54c661fbbf4024bdca7ea 100644 +index 693eef486f1a3b4ea7e5fd5ecf2d25d85f424d97..5837d976abf663bd46a64f46348613db9284254d 100644 --- a/net/minecraft/world/entity/raid/Raids.java +++ b/net/minecraft/world/entity/raid/Raids.java -@@ -25,6 +25,7 @@ import net.minecraft.world.phys.Vec3; +@@ -29,6 +29,7 @@ import net.minecraft.world.phys.Vec3; public class Raids extends SavedData { private static final String RAID_FILE_ID = "raids"; -+ public final Map playerCooldowns = Maps.newHashMap(); // Purpur - Raid cooldown setting - public final Map raidMap = Maps.newHashMap(); - private final ServerLevel level; - private int nextAvailableID; -@@ -46,6 +47,17 @@ public class Raids extends SavedData { ++ public final java.util.Map playerCooldowns = com.google.common.collect.Maps.newHashMap(); // Purpur - Raid cooldown setting + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Raids.RaidWithId.CODEC +@@ -81,6 +82,17 @@ public class Raids extends SavedData { - public void tick() { + public void tick(ServerLevel level) { this.tick++; + // Purpur start - Raid cooldown setting + if (level.purpurConfig.raidCooldownSeconds != 0 && this.tick % 20 == 0) { @@ -13002,25 +12998,25 @@ index 34eb038725d1577f1a2d7c35c897b1270eac5749..497915338d406815d6b54c661fbbf402 Iterator iterator = this.raidMap.values().iterator(); while (iterator.hasNext()) { -@@ -119,11 +131,13 @@ public class Raids extends SavedData { - */ +@@ -148,11 +160,13 @@ public class Raids extends SavedData { + // } - if (!raid.isStarted() || (raid.isInProgress() && raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel())) { // CraftBukkit - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished -+ if (level.purpurConfig.raidCooldownSeconds != 0 && playerCooldowns.containsKey(player.getUUID())) return null; // Purpur - Raid cooldown setting - // CraftBukkit start - if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, player)) { - player.removeEffect(net.minecraft.world.effect.MobEffects.RAID_OMEN); - return null; - } -+ if (level.purpurConfig.raidCooldownSeconds != 0) playerCooldowns.put(player.getUUID(), level.purpurConfig.raidCooldownSeconds); // Purpur - Raid cooldown setting + if (!raid.isStarted() || (raid.isInProgress() && raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel())) { // CraftBukkit - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ if (serverLevel.purpurConfig.raidCooldownSeconds != 0 && playerCooldowns.containsKey(player.getUUID())) return null; // Purpur - Raid cooldown setting + // CraftBukkit start + if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(serverLevel, raid, player)) { + player.removeEffect(net.minecraft.world.effect.MobEffects.RAID_OMEN); + return null; + } ++ if (serverLevel.purpurConfig.raidCooldownSeconds != 0) playerCooldowns.put(player.getUUID(), serverLevel.purpurConfig.raidCooldownSeconds); // Purpur - Raid cooldown setting - if (!raid.isStarted() && !this.raidMap.containsKey(raid.getId())) { - this.raidMap.put(raid.getId(), raid); + if (!raid.isStarted() && !this.raidMap.containsValue(raid)) { + this.raidMap.put(this.getUniqueId(), raid); diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java -index 467783b764eec361b190566cb3d9050bb0821864..b1b312e45ed4514eaa6fb3941af64b641220c5bd 100644 +index 4541bb5233e986d9993d8593afef9b12c935d00a..4f61c17e0a4a82773834bc21e00cac6eb75f794e 100644 --- a/net/minecraft/world/entity/vehicle/AbstractBoat.java +++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java -@@ -483,6 +483,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { +@@ -433,6 +433,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { float groundFriction = this.getGroundFriction(); if (groundFriction > 0.0F) { this.landFriction = groundFriction; @@ -13028,7 +13024,7 @@ index 467783b764eec361b190566cb3d9050bb0821864..b1b312e45ed4514eaa6fb3941af64b64 return AbstractBoat.Status.ON_LAND; } else { return AbstractBoat.Status.IN_AIR; -@@ -878,7 +879,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { +@@ -821,7 +822,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { @Override public final ItemStack getPickResult() { @@ -13044,13 +13040,13 @@ index 467783b764eec361b190566cb3d9050bb0821864..b1b312e45ed4514eaa6fb3941af64b64 public static enum Status { diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e37127aa64cd 100644 +index 99617c08cbd989092ba357d8df928786fd04c89a..9d88b260528c3cea2c5fe8e2760094b0a8a35667 100644 --- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -83,6 +83,10 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -103,6 +103,10 @@ public abstract class AbstractMinecart extends VehicleEntity { private double flyingY = 0.95; private double flyingZ = 0.95; - public Double maxSpeed; + public @Nullable Double maxSpeed; + // Purpur start - Minecart settings and WASD controls + public double storedMaxSpeed; + public boolean isNewBehavior; @@ -13058,7 +13054,7 @@ index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e371 public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API // CraftBukkit end -@@ -91,8 +95,13 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -111,8 +115,13 @@ public abstract class AbstractMinecart extends VehicleEntity { this.blocksBuilding = true; if (useExperimentalMovement(level)) { this.behavior = new NewMinecartBehavior(this); @@ -13072,7 +13068,7 @@ index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e371 } } -@@ -258,6 +267,14 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -277,6 +286,14 @@ public abstract class AbstractMinecart extends VehicleEntity { @Override public void tick() { @@ -13087,7 +13083,7 @@ index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e371 // CraftBukkit start double prevX = this.getX(); double prevY = this.getY(); -@@ -394,15 +411,61 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -384,15 +401,61 @@ public abstract class AbstractMinecart extends VehicleEntity { this.behavior.moveAlongTrack(level); } @@ -13150,7 +13146,7 @@ index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e371 this.move(MoverType.SELF, this.getDeltaMovement()); if (!this.onGround()) { diff --git a/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java b/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java -index f386bfa64ac11150845666b26e938a8ae0efe574..724466d14c925704671e510cea1919ee95a2ae02 100644 +index 090b19752fbfc856d9fbf118510afc6cda2b9989..325ec57df2885f5e81b8a6b61e3a9fed9484b30f 100644 --- a/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java +++ b/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java @@ -391,7 +391,7 @@ public class NewMinecartBehavior extends MinecartBehavior { @@ -13163,10 +13159,10 @@ index f386bfa64ac11150845666b26e938a8ae0efe574..724466d14c925704671e510cea1919ee Vec3 redstoneDirection = this.minecart.getRedstoneDirection(pos); return redstoneDirection.lengthSqr() <= 0.0 ? speed : redstoneDirection.scale(speed.length() + 0.2); diff --git a/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java b/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java -index d12d0c71479ea890ce41e5e43a135606db16fb21..8d1b70e526892860cc286314642fe51e5a44d7dc 100644 +index 0d09b0809e7b224538cf5cfac9e36ec5ba10b709..4d224dc127d245556892e761fa4927a76e4b8e9a 100644 --- a/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java +++ b/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java -@@ -279,8 +279,8 @@ public class OldMinecartBehavior extends MinecartBehavior { +@@ -243,8 +243,8 @@ public class OldMinecartBehavior extends MinecartBehavior { Vec3 deltaMovement1 = this.getDeltaMovement(); double d13 = deltaMovement1.horizontalDistance(); if (d13 > 0.01) { @@ -13178,10 +13174,10 @@ index d12d0c71479ea890ce41e5e43a135606db16fb21..8d1b70e526892860cc286314642fe51e Vec3 deltaMovement2 = this.getDeltaMovement(); double d15 = deltaMovement2.x; diff --git a/net/minecraft/world/food/FoodData.java b/net/minecraft/world/food/FoodData.java -index d46b27913797c5a2f433efe086463b91a9c31f63..f205401b24cdf0f43d531fb33e58d7183f98e510 100644 +index 89d783315dab8ca469a1fa724cd59a329d4c2b55..7fa061718989365725ff49abd2d19d1ba3f935f9 100644 --- a/net/minecraft/world/food/FoodData.java +++ b/net/minecraft/world/food/FoodData.java -@@ -36,6 +36,7 @@ public class FoodData { +@@ -38,6 +38,7 @@ public class FoodData { int oldFoodLevel = this.foodLevel; org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(serverPlayer, foodProperties.nutrition() + oldFoodLevel, stack); if (!event.isCancelled()) { @@ -13189,7 +13185,7 @@ index d46b27913797c5a2f433efe086463b91a9c31f63..f205401b24cdf0f43d531fb33e58d718 this.add(event.getFoodLevel() - oldFoodLevel, foodProperties.saturation()); } serverPlayer.getBukkitEntity().sendHealthUpdate(); -@@ -84,7 +85,7 @@ public class FoodData { +@@ -86,7 +87,7 @@ public class FoodData { this.tickTimer++; if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { @@ -13199,7 +13195,7 @@ index d46b27913797c5a2f433efe086463b91a9c31f63..f205401b24cdf0f43d531fb33e58d718 this.tickTimer = 0; diff --git a/net/minecraft/world/food/FoodProperties.java b/net/minecraft/world/food/FoodProperties.java -index 5e0d447409dc2223bb56cb8bb932e241bf88c78d..6e1544121c556cd8761dc86d4246e7270c08e732 100644 +index 793e4528755fa5688efbad75418188e693ad0157..20f702c8266eb54a8835861188eb937f4732e078 100644 --- a/net/minecraft/world/food/FoodProperties.java +++ b/net/minecraft/world/food/FoodProperties.java @@ -42,9 +42,11 @@ public record FoodProperties(int nutrition, float saturation, boolean canAlwaysE @@ -13218,7 +13214,7 @@ index 5e0d447409dc2223bb56cb8bb932e241bf88c78d..6e1544121c556cd8761dc86d4246e727 } diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index acca8c51d2030c675c157b10d0bbc6af631afe61..e6419715fab462b12790ecb175ce1e1a1fceed8f 100644 +index 029f50da9618b45880c1cfe9bed6e11d77fc68dc..8e97a20306652cdfc757b7102a07c58ce0e339e3 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -65,6 +65,7 @@ public abstract class AbstractContainerMenu { @@ -13230,7 +13226,7 @@ index acca8c51d2030c675c157b10d0bbc6af631afe61..e6419715fab462b12790ecb175ce1e1a public boolean checkReachable = true; public abstract org.bukkit.inventory.InventoryView getBukkitView(); diff --git a/net/minecraft/world/inventory/AbstractFurnaceMenu.java b/net/minecraft/world/inventory/AbstractFurnaceMenu.java -index d3814f351e3b0cd00b2b9ad0d122ca376c18e6a3..a23ff3defe4e49cd04008b7d793994bf2bf95159 100644 +index b42d55c1c0c405ce3ce073138343e74fa036fa65..b86e49b09a036532e7dbd56bc52b13cefe77f75b 100644 --- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java +++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java @@ -121,7 +121,13 @@ public abstract class AbstractFurnaceMenu extends RecipeBookMenu { @@ -13249,7 +13245,7 @@ index d3814f351e3b0cd00b2b9ad0d122ca376c18e6a3..a23ff3defe4e49cd04008b7d793994bf } else if (this.isFuel(item)) { if (!this.moveItemStackTo(item, 1, 2, false)) { diff --git a/net/minecraft/world/inventory/AnvilMenu.java b/net/minecraft/world/inventory/AnvilMenu.java -index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff83f4ebfa 100644 +index 65c400444314049d5529f1f76d65fbd6b1ea7af2..bcffac9f7781ea489e8e4d778181b9ae2392590f 100644 --- a/net/minecraft/world/inventory/AnvilMenu.java +++ b/net/minecraft/world/inventory/AnvilMenu.java @@ -20,6 +20,12 @@ import net.minecraft.world.level.block.AnvilBlock; @@ -13290,7 +13286,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff + ItemStack itemstack = this.activeQuickItem != null ? this.activeQuickItem : stack; + if (org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent.getHandlerList().getRegisteredListeners().length > 0) new org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)).callEvent(); + // Purpur end - Anvil API - if (!player.getAbilities().instabuild) { + if (!player.hasInfiniteMaterials()) { + if (this.bypassCost) ((ServerPlayer) player).lastSentExp = -1; else // Purpur - Anvil API player.giveExperienceLevels(-this.cost.get()); } @@ -13316,7 +13312,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff ItemStack itemStack = item.copy(); ItemStack item1 = this.inputSlots.getItem(1); ItemEnchantments.Mutable mutable = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(itemStack)); -@@ -191,23 +212,34 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -190,23 +211,34 @@ public class AnvilMenu extends ItemCombinerMenu { int intValue = entry.getIntValue(); intValue = level == intValue ? intValue + 1 : Math.max(intValue, level); Enchantment enchantment = holder.value(); @@ -13325,7 +13321,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff + boolean canEnchant = this.canDoUnsafeEnchants || org.purpurmc.purpur.PurpurConfig.allowInapplicableEnchants || enchantment.canEnchant(item); // whether the enchantment can be applied on specific item type + boolean canEnchant1 = true; // whether two incompatible enchantments can be applied on a single item + // Purpur end - Config to allow unsafe enchants - if (this.player.getAbilities().instabuild || item.is(Items.ENCHANTED_BOOK)) { + if (this.player.hasInfiniteMaterials() || item.is(Items.ENCHANTED_BOOK)) { canEnchant = true; } @@ -13355,7 +13351,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff intValue = enchantment.getMaxLevel(); } -@@ -236,6 +268,54 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -235,6 +267,54 @@ public class AnvilMenu extends ItemCombinerMenu { if (!this.itemName.equals(item.getHoverName().getString())) { i1 = 1; i += i1; @@ -13410,7 +13406,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff itemStack.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName)); } } else if (item.has(DataComponents.CUSTOM_NAME)) { -@@ -260,6 +340,12 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -259,6 +339,12 @@ public class AnvilMenu extends ItemCombinerMenu { this.onlyRenaming = true; } @@ -13420,10 +13416,10 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff + } + // Purpur end - Anvil API + - if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit + if (this.cost.get() >= this.maximumRepairCost && !this.player.hasInfiniteMaterials()) { // CraftBukkit itemStack = ItemStack.EMPTY; } -@@ -280,6 +366,13 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -279,6 +365,13 @@ public class AnvilMenu extends ItemCombinerMenu { org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemStack); // CraftBukkit this.broadcastChanges(); @@ -13437,7 +13433,7 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff } else { org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit this.cost.set(AnvilMenu.DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item -@@ -288,7 +381,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -287,7 +380,7 @@ public class AnvilMenu extends ItemCombinerMenu { } public static int calculateIncreasedRepairCost(int oldRepairCost) { @@ -13447,10 +13443,10 @@ index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..84c438f922321bb80906589ebee30bff public boolean setItemName(String itemName) { diff --git a/net/minecraft/world/inventory/ArmorSlot.java b/net/minecraft/world/inventory/ArmorSlot.java -index 6a1c0f2b11a289c419b9070feb08d9464570c5b7..f9d82d7f7e76032a13d196bc1d0a209015b461ee 100644 +index 0a440ea37d14cd840cf87a99264ace5ccde7c073..dec920727401de7f5bcc6c7e50f9dd325367ee90 100644 --- a/net/minecraft/world/inventory/ArmorSlot.java +++ b/net/minecraft/world/inventory/ArmorSlot.java -@@ -42,7 +42,7 @@ class ArmorSlot extends Slot { +@@ -47,7 +47,7 @@ class ArmorSlot extends Slot { @Override public boolean mayPickup(Player player) { ItemStack item = this.getItem(); @@ -13460,7 +13456,7 @@ index 6a1c0f2b11a289c419b9070feb08d9464570c5b7..f9d82d7f7e76032a13d196bc1d0a2090 } diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java -index 280169afbd637eeb67ddf7eaeb4eecd464a128d5..ba7730a24831efa33de4c5ffce57bfa7177f89d6 100644 +index 0fffa384f928ab84451331380968fb4650eafe26..0399092c9f7a43ac100c11505176ade6d95a39da 100644 --- a/net/minecraft/world/inventory/ChestMenu.java +++ b/net/minecraft/world/inventory/ChestMenu.java @@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu { @@ -13495,7 +13491,7 @@ index 280169afbd637eeb67ddf7eaeb4eecd464a128d5..ba7730a24831efa33de4c5ffce57bfa7 return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6); } diff --git a/net/minecraft/world/inventory/EnchantmentMenu.java b/net/minecraft/world/inventory/EnchantmentMenu.java -index 1bba36afb00ad2a63bbfba60aab0f614b4aa8174..0936e08f5f465dc34a1b4b5370fcc3e0d57eab0a 100644 +index cf9ab4c9fba11f5a0b293978853e205de81d6fc7..d0d6ae9c9c432f8bd5d9c91113fc5491e321afad 100644 --- a/net/minecraft/world/inventory/EnchantmentMenu.java +++ b/net/minecraft/world/inventory/EnchantmentMenu.java @@ -63,6 +63,22 @@ public class EnchantmentMenu extends AbstractContainerMenu { @@ -13538,7 +13534,7 @@ index 1bba36afb00ad2a63bbfba60aab0f614b4aa8174..0936e08f5f465dc34a1b4b5370fcc3e0 this.addStandardInventorySlots(playerInventory, 8, 84); this.addDataSlot(DataSlot.shared(this.costs, 0)); this.addDataSlot(DataSlot.shared(this.costs, 1)); -@@ -294,7 +320,7 @@ public class EnchantmentMenu extends AbstractContainerMenu { +@@ -299,7 +325,7 @@ public class EnchantmentMenu extends AbstractContainerMenu { @Override public void removed(Player player) { super.removed(player); @@ -13548,7 +13544,7 @@ index 1bba36afb00ad2a63bbfba60aab0f614b4aa8174..0936e08f5f465dc34a1b4b5370fcc3e0 @Override diff --git a/net/minecraft/world/inventory/GrindstoneMenu.java b/net/minecraft/world/inventory/GrindstoneMenu.java -index f85bd2a90c2694d96f67cc3701a9bbf081fe8475..2da45bd93f12aadae4e28357b3225353dba89427 100644 +index 6eaa468c90a826f9fdecf2cf672c4893122d2504..5cb69b7ffc82905e5ba8c99c76ce14348f89e21c 100644 --- a/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/net/minecraft/world/inventory/GrindstoneMenu.java @@ -91,11 +91,13 @@ public class GrindstoneMenu extends AbstractContainerMenu { @@ -13702,7 +13698,7 @@ index 34d52c941395645e77de810855b14012c259cf02..c605bd700fd9f5a6596a2bf964849278 return itemStack; diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java -index a6a359bab2a727f4631b633a8bb370dd40decc75..d2d75e5c34c97300ce5da8c7ea70958aba31fa4a 100644 +index bc2b95973192069fc64581b59583b19df876f55d..b68d57eee9605dba8ecd31f82185ec3ea81d60c1 100644 --- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java +++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java @@ -25,11 +25,18 @@ public class PlayerEnderChestContainer extends SimpleContainer { @@ -13726,7 +13722,7 @@ index a6a359bab2a727f4631b633a8bb370dd40decc75..d2d75e5c34c97300ce5da8c7ea70958a this.activeChest = enderChestBlockEntity; } diff --git a/net/minecraft/world/item/ArmorStandItem.java b/net/minecraft/world/item/ArmorStandItem.java -index d82e6651999a2650ec8884c4c3d8de4133cb42a4..a26b9fe964c79da57aaa0f755a81934f51a79913 100644 +index 962483d6f7225f13f121141882262d36dacad8cb..89d4bc00898fd8f6d40cda87c04c5983e2ea223c 100644 --- a/net/minecraft/world/item/ArmorStandItem.java +++ b/net/minecraft/world/item/ArmorStandItem.java @@ -51,6 +51,10 @@ public class ArmorStandItem extends Item { @@ -13741,11 +13737,11 @@ index d82e6651999a2650ec8884c4c3d8de4133cb42a4..a26b9fe964c79da57aaa0f755a81934f level.playSound( null, armorStand.getX(), armorStand.getY(), armorStand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F diff --git a/net/minecraft/world/item/AxeItem.java b/net/minecraft/world/item/AxeItem.java -index d4b79f897ee7950893d608dc343073dbcff6ab14..7cf309c1b119ef8432c04c2b3df248d7d96dc15c 100644 +index bd919b9a83f9736f02783b1ba3863fd1b77c7e89..eb8d2d6f9c65185f5fe16a13ab0cdbba78a25a40 100644 --- a/net/minecraft/world/item/AxeItem.java +++ b/net/minecraft/world/item/AxeItem.java -@@ -62,13 +62,15 @@ public class AxeItem extends DiggerItem { - if (playerHasShieldUseIntent(context)) { +@@ -62,13 +62,15 @@ public class AxeItem extends Item { + if (playerHasBlockingItemUseIntent(context)) { return InteractionResult.PASS; } else { - Optional optional = this.evaluateNewBlockState(level, clickedPos, player, level.getBlockState(clickedPos)); @@ -13762,7 +13758,7 @@ index d4b79f897ee7950893d608dc343073dbcff6ab14..7cf309c1b119ef8432c04c2b3df248d7 return InteractionResult.PASS; } // Paper end -@@ -76,8 +78,15 @@ public class AxeItem extends DiggerItem { +@@ -76,8 +78,15 @@ public class AxeItem extends Item { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, clickedPos, itemInHand); } @@ -13780,8 +13776,8 @@ index d4b79f897ee7950893d608dc343073dbcff6ab14..7cf309c1b119ef8432c04c2b3df248d7 if (player != null) { itemInHand.hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand())); } -@@ -92,22 +101,24 @@ public class AxeItem extends DiggerItem { - return context.getHand().equals(InteractionHand.MAIN_HAND) && player.getOffhandItem().is(Items.SHIELD) && !player.isSecondaryUseActive(); +@@ -94,22 +103,24 @@ public class AxeItem extends Item { + && !player.isSecondaryUseActive(); } - private Optional evaluateNewBlockState(Level level, BlockPos pos, @Nullable Player player, BlockState state) { @@ -13814,10 +13810,10 @@ index d4b79f897ee7950893d608dc343073dbcff6ab14..7cf309c1b119ef8432c04c2b3df248d7 return optional; } else { diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 68e50c6ade879d263424f244070677cb81c34c33..1df587402862d67a76ed090df60bfa20c3a9209d 100644 +index 2fbbbac9f1472354bd507926a85c25f48291edfe..5603ba2d570eda7459c91988f8d2f9e2fa517a90 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -152,7 +152,16 @@ public class BlockItem extends Item { +@@ -145,7 +145,16 @@ public class BlockItem extends Item { } protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) { @@ -13835,7 +13831,7 @@ index 68e50c6ade879d263424f244070677cb81c34c33..1df587402862d67a76ed090df60bfa20 } @Nullable -@@ -217,6 +226,7 @@ public class BlockItem extends Item { +@@ -212,6 +221,7 @@ public class BlockItem extends Item { } if (!type.onlyOpCanSetNbt() || player != null && (player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place")))) { // Spigot - add permission @@ -13843,7 +13839,7 @@ index 68e50c6ade879d263424f244070677cb81c34c33..1df587402862d67a76ed090df60bfa20 return customData.loadInto(blockEntity, level.registryAccess()); } -@@ -264,6 +274,7 @@ public class BlockItem extends Item { +@@ -253,6 +263,7 @@ public class BlockItem extends Item { public void onDestroyed(ItemEntity itemEntity) { ItemContainerContents itemContainerContents = itemEntity.getItem().set(DataComponents.CONTAINER, ItemContainerContents.EMPTY); if (itemContainerContents != null) { @@ -13898,13 +13894,13 @@ index 57c933af200551162774f1d473437521e5a85833..b3e003694ce0da357e91ab3ce2b1380f } else { player.startUsingItem(hand); diff --git a/net/minecraft/world/item/BucketItem.java b/net/minecraft/world/item/BucketItem.java -index 62d79cb25879e6e48a1541f864d0b3782d926313..b820ecfbe71dd57a0f04b1c3381ffb76b0c16f16 100644 +index de287715568f358dd83383d68f845df9a7b5a117..8c7be8a71348a3e66c8bf6b6cb39fe002c20bdb0 100644 --- a/net/minecraft/world/item/BucketItem.java +++ b/net/minecraft/world/item/BucketItem.java @@ -147,7 +147,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { // CraftBukkit end if (!flag) { - return result != null && this.emptyContents(player, level, result.getBlockPos().relative(result.getDirection()), null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit + return hitResult != null && this.emptyContents(entity, level, hitResult.getBlockPos().relative(hitResult.getDirection()), null, direction, clicked, itemstack, hand); // CraftBukkit - } else if (level.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { + } else if ((level.dimensionType().ultraWarm() || (level.isTheEnd() && !org.purpurmc.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) && this.content.is(FluidTags.WATER)) { // Purpur - Add allow water in end world option int x = pos.getX(); @@ -13920,10 +13916,10 @@ index 62d79cb25879e6e48a1541f864d0b3782d926313..b820ecfbe71dd57a0f04b1c3381ffb76 return true; diff --git a/net/minecraft/world/item/CrossbowItem.java b/net/minecraft/world/item/CrossbowItem.java -index 944b0c455d5f2183a04ea1a10bc5d5debd563dcb..318316d3aa14f1e9e863d435515c182619a81b3e 100644 +index f5189cf0a0006864ac67b191cc0f1cd63b40f9e2..ff4294b9bcb6e2bb0f9d51dee6dcc889e45df95c 100644 --- a/net/minecraft/world/item/CrossbowItem.java +++ b/net/minecraft/world/item/CrossbowItem.java -@@ -70,7 +70,7 @@ public class CrossbowItem extends ProjectileWeaponItem { +@@ -66,7 +66,7 @@ public class CrossbowItem extends ProjectileWeaponItem { ItemStack itemInHand = player.getItemInHand(hand); ChargedProjectiles chargedProjectiles = itemInHand.get(DataComponents.CHARGED_PROJECTILES); if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) { @@ -13933,10 +13929,10 @@ index 944b0c455d5f2183a04ea1a10bc5d5debd563dcb..318316d3aa14f1e9e863d435515c1826 } else if (!player.getProjectile(itemInHand).isEmpty()) { this.startSoundPlayed = false; diff --git a/net/minecraft/world/item/DyeColor.java b/net/minecraft/world/item/DyeColor.java -index 028bb51c6753d44cbae76890412aa55b070f8054..597e2357040af91fc8cfb81ff7e5d8815d61898d 100644 +index 0416f4ef5c50f6579a6ef495e699a5c8c95d3878..437db0888d50654702e1fa2286a4ea9cc08d6d67 100644 --- a/net/minecraft/world/item/DyeColor.java +++ b/net/minecraft/world/item/DyeColor.java -@@ -213,4 +213,10 @@ public enum DyeColor implements StringRepresentable { +@@ -216,4 +216,10 @@ public enum DyeColor implements StringRepresentable { private static CraftingInput makeCraftColorInput(DyeColor first, DyeColor second) { return CraftingInput.of(2, 1, List.of(new ItemStack(DyeItem.byColor(first)), new ItemStack(DyeItem.byColor(second)))); } @@ -13948,20 +13944,20 @@ index 028bb51c6753d44cbae76890412aa55b070f8054..597e2357040af91fc8cfb81ff7e5d881 + // Purpur end - Shulker spawn from bullet options } diff --git a/net/minecraft/world/item/EggItem.java b/net/minecraft/world/item/EggItem.java -index f22a3ad6228326f837e6c83576e14d9e4fa9c882..3560091fb5840d8170d6ea80f6db734591fe85fc 100644 +index ccae6089cdc4fffca7d759252006a13c2c14691a..c4097bd6acf671ddf857350154e6e1a04e76d64b 100644 --- a/net/minecraft/world/item/EggItem.java +++ b/net/minecraft/world/item/EggItem.java -@@ -26,7 +26,7 @@ public class EggItem extends Item implements ProjectileItem { - if (level instanceof ServerLevel serverLevel) { - // CraftBukkit start - // Paper start - PlayerLaunchProjectileEvent -- final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, serverLevel, itemInHand, player, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, 1.0F); -+ final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, serverLevel, itemInHand, player, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, (float) serverLevel.purpurConfig.eggProjectileOffset); // Purpur - Projectile offset config - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) thrownEgg.projectile().getBukkitEntity()); - if (event.callEvent() && thrownEgg.attemptSpawn()) { - if (event.shouldConsume()) { +@@ -24,7 +24,7 @@ public class EggItem extends Item implements ProjectileItem { + public InteractionResult use(Level level, Player player, InteractionHand hand) { + ItemStack itemInHand = player.getItemInHand(hand); + // Paper start +- final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, (ServerLevel) level, itemInHand, player, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, 1.0F); ++ final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, (ServerLevel) level, itemInHand, player, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, (float) level.purpurConfig.eggProjectileOffset); // Purpur - Projectile offset config + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) thrownEgg.projectile().getBukkitEntity()); + if (event.callEvent() && thrownEgg.attemptSpawn()) { + if (event.shouldConsume()) { diff --git a/net/minecraft/world/item/EndCrystalItem.java b/net/minecraft/world/item/EndCrystalItem.java -index a1570503d3e4dcc9f1cd0b119ab2e60f7c63b6d8..3c84f7ce77e58ba49567aff5bc718e6928000bc2 100644 +index 49f94f242a0906e74eb58313cf095a0b04c304c4..0db35674726e3039f2c20aed1993d6d3843f8d29 100644 --- a/net/minecraft/world/item/EndCrystalItem.java +++ b/net/minecraft/world/item/EndCrystalItem.java @@ -24,7 +24,7 @@ public class EndCrystalItem extends Item { @@ -13972,7 +13968,7 @@ index a1570503d3e4dcc9f1cd0b119ab2e60f7c63b6d8..3c84f7ce77e58ba49567aff5bc718e69 + if (!level.purpurConfig.endCrystalPlaceAnywhere && !blockState.is(Blocks.OBSIDIAN) && !blockState.is(Blocks.BEDROCK)) { // Purpur - place end crystal on any block return InteractionResult.FAIL; } else { - BlockPos blockPos = clickedPos.above(); final BlockPos aboveBlockPosition = blockPos; // Paper - OBFHELPER + BlockPos blockPos = clickedPos.above(); final BlockPos aboveBlockPos = blockPos; // Paper - OBFHELPER diff --git a/net/minecraft/world/item/EnderpearlItem.java b/net/minecraft/world/item/EnderpearlItem.java index 3becd19d3264fa631497e967656cc7ca39252586..f824f155549857d5205ba67eb5916e0b0b65efb4 100644 --- a/net/minecraft/world/item/EnderpearlItem.java @@ -13995,17 +13991,17 @@ index 3becd19d3264fa631497e967656cc7ca39252586..f824f155549857d5205ba67eb5916e0b if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { serverPlayer.deregisterEnderPearl(thrownEnderpearl.projectile()); diff --git a/net/minecraft/world/item/FireworkRocketItem.java b/net/minecraft/world/item/FireworkRocketItem.java -index 75a9bd205f32b77c5d242cb9fac0f571ce36045a..b03f182c62c699cc222e67c1ae6eadf99c45d48d 100644 +index 18d63d2da49451a2d5e1da7bf0c00e05e2f192bc..1f081e098ce3bec61b7f374e9b737838783657bb 100644 --- a/net/minecraft/world/item/FireworkRocketItem.java +++ b/net/minecraft/world/item/FireworkRocketItem.java -@@ -66,6 +66,19 @@ public class FireworkRocketItem extends Item implements ProjectileItem { +@@ -62,6 +62,19 @@ public class FireworkRocketItem extends Item implements ProjectileItem { com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); if (event.callEvent() && delayed.attemptSpawn()) { player.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below + + // Purpur start - Implement elytra settings + if (level.purpurConfig.elytraDamagePerFireworkBoost > 0) { -+ List list = net.minecraft.world.entity.EquipmentSlot.VALUES.stream().filter((enumitemslot) -> net.minecraft.world.entity.LivingEntity.canGlideUsing(player.getItemBySlot(enumitemslot), enumitemslot)).toList(); ++ java.util.List list = net.minecraft.world.entity.EquipmentSlot.VALUES.stream().filter((enumitemslot) -> net.minecraft.world.entity.LivingEntity.canGlideUsing(player.getItemBySlot(enumitemslot), enumitemslot)).toList(); + net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, player.random); + + ItemStack glideItem = player.getItemBySlot(enumitemslot); @@ -14019,22 +14015,23 @@ index 75a9bd205f32b77c5d242cb9fac0f571ce36045a..b03f182c62c699cc222e67c1ae6eadf9 itemInHand.shrink(1); // Moved up from below } else { diff --git a/net/minecraft/world/item/HangingEntityItem.java b/net/minecraft/world/item/HangingEntityItem.java -index fb301e4ba8faecf9c3b14e48fe9a8008a43f8cea..a11ef537a220fc16a4cea2fda221b649e74cea30 100644 +index 5f9c166b8ba9e9dcabb7398308e7520a88335eae..e9e3a036290a5facc36cf6a484d03d4d3bfb65a5 100644 --- a/net/minecraft/world/item/HangingEntityItem.java +++ b/net/minecraft/world/item/HangingEntityItem.java -@@ -62,6 +62,7 @@ public class HangingEntityItem extends Item { - CustomData customData = itemInHand.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); - if (!customData.isEmpty()) { - EntityType.updateCustomEntityTag(level, player, hangingEntity, customData); -+ if (!level.purpurConfig.persistentDroppableEntityDisplayNames) hangingEntity.setCustomName(null); // Purpur - Apply display names from item forms of entities to entities and vice versa +@@ -59,7 +59,7 @@ public class HangingEntityItem extends Item { + hangingEntity = new GlowItemFrame(level, blockPos, clickedFace); } +- EntityType.createDefaultStackConfig(level, itemInHand, player).accept(hangingEntity); ++ EntityType.appendDefaultStackConfig(entity -> {if (!level.purpurConfig.persistentDroppableEntityDisplayNames) entity.setCustomName(null);}, level, itemInHand, player).accept(hangingEntity); // Purpur - Apply display names from item forms of entities to entities and vice versa if (hangingEntity.survives()) { + if (!level.isClientSide) { + // CraftBukkit start - fire HangingPlaceEvent diff --git a/net/minecraft/world/item/HoeItem.java b/net/minecraft/world/item/HoeItem.java -index 4966b6cfb46c01691e087c466e636f58a65f45a7..acef797b884f6072ada4b9d5af53daf13273edca 100644 +index 3bf3d4030c4da65fa386a8b8083d259a6046d15e..77a8d5d334cd93d23149afa8e58f4114412632df 100644 --- a/net/minecraft/world/item/HoeItem.java +++ b/net/minecraft/world/item/HoeItem.java -@@ -46,15 +46,25 @@ public class HoeItem extends DiggerItem { +@@ -45,15 +45,25 @@ public class HoeItem extends Item { public InteractionResult useOn(UseOnContext context) { Level level = context.getLevel(); BlockPos clickedPos = context.getClickedPos(); @@ -14066,26 +14063,26 @@ index 4966b6cfb46c01691e087c466e636f58a65f45a7..acef797b884f6072ada4b9d5af53daf1 consumer.accept(context); if (player != null) { diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 7fbfbe7777cc66170cc616565a8b94f2081da50f..aa2c00be86f42a6674694a20545399e441b75199 100644 +index 3eb34df6bd4c4969ffbcc7abd1c24e556485d1c4..d2d9619f8156985ba38c0ef8c0f155adc8d40f34 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -461,6 +461,7 @@ public final class ItemStack implements DataComponentHolder { - serverLevel.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent +@@ -458,6 +458,7 @@ public final class ItemStack implements DataComponentHolder { + // revert back all captured blocks for (org.bukkit.block.BlockState blockstate : blocks) { - blockstate.update(true, false); + ((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).revertPlace(); + ((org.bukkit.craftbukkit.block.CraftBlock) blockstate.getBlock()).getNMS().getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed } - serverLevel.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent - serverLevel.preventPoiUpdated = false; -@@ -486,6 +487,7 @@ public final class ItemStack implements DataComponentHolder { + + SignItem.openSign = null; // SPIGOT-6758 - Reset on early return +@@ -481,6 +482,7 @@ public final class ItemStack implements DataComponentHolder { if (!(block.getBlock() instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // Containers get placed automatically block.onPlace(serverLevel, newPos, oldBlock, true, context); } + block.getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed - serverLevel.notifyAndUpdatePhysics(newPos, null, oldBlock, block, serverLevel.getBlockState(newPos), updateFlag, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point + serverLevel.notifyAndUpdatePhysics(newPos, null, oldBlock, block, serverLevel.getBlockState(newPos), updateFlags, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point } -@@ -627,6 +629,26 @@ public final class ItemStack implements DataComponentHolder { +@@ -618,6 +620,26 @@ public final class ItemStack implements DataComponentHolder { return this.isDamageableItem() && this.getDamageValue() > 0; } @@ -14110,9 +14107,9 @@ index 7fbfbe7777cc66170cc616565a8b94f2081da50f..aa2c00be86f42a6674694a20545399e4 + // Purpur end - Add option to mend the most damaged equipment first + public int getDamageValue() { - return Mth.clamp(this.getOrDefault(DataComponents.DAMAGE, Integer.valueOf(0)), 0, this.getMaxDamage()); + return Mth.clamp(this.getOrDefault(DataComponents.DAMAGE, 0), 0, this.getMaxDamage()); } -@@ -711,6 +733,14 @@ public final class ItemStack implements DataComponentHolder { +@@ -703,6 +725,14 @@ public final class ItemStack implements DataComponentHolder { org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent } // CraftBukkit end @@ -14127,7 +14124,7 @@ index 7fbfbe7777cc66170cc616565a8b94f2081da50f..aa2c00be86f42a6674694a20545399e4 this.shrink(1); onBreak.accept(item); } -@@ -1252,6 +1282,12 @@ public final class ItemStack implements DataComponentHolder { +@@ -1281,6 +1311,12 @@ public final class ItemStack implements DataComponentHolder { return !this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).isEmpty(); } @@ -14141,10 +14138,10 @@ index 7fbfbe7777cc66170cc616565a8b94f2081da50f..aa2c00be86f42a6674694a20545399e4 return this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); } diff --git a/net/minecraft/world/item/Items.java b/net/minecraft/world/item/Items.java -index 932565a2a3bf48b30ef53031d92afeb18623d549..d55e5e6deca43c7fddb15657fa5ceaeed8f95c67 100644 +index ae228cd15342ac159dd61bf4d09c2d80b7f44fee..4afa2d9f5825ccc70492b9c3d82ac5616d6f7faa 100644 --- a/net/minecraft/world/item/Items.java +++ b/net/minecraft/world/item/Items.java -@@ -367,7 +367,7 @@ public class Items { +@@ -382,7 +382,7 @@ public class Items { public static final Item PURPUR_BLOCK = registerBlock(Blocks.PURPUR_BLOCK); public static final Item PURPUR_PILLAR = registerBlock(Blocks.PURPUR_PILLAR); public static final Item PURPUR_STAIRS = registerBlock(Blocks.PURPUR_STAIRS); @@ -14153,7 +14150,7 @@ index 932565a2a3bf48b30ef53031d92afeb18623d549..d55e5e6deca43c7fddb15657fa5ceaee public static final Item CREAKING_HEART = registerBlock(Blocks.CREAKING_HEART); public static final Item CHEST = registerBlock(Blocks.CHEST, properties -> properties.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY)); public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE); -@@ -2010,7 +2010,7 @@ public class Items { +@@ -2034,7 +2034,7 @@ public class Items { "sweet_berries", createBlockItemWithCustomItemName(Blocks.SWEET_BERRY_BUSH), new Item.Properties().food(Foods.SWEET_BERRIES) ); public static final Item GLOW_BERRIES = registerItem( @@ -14163,10 +14160,10 @@ index 932565a2a3bf48b30ef53031d92afeb18623d549..d55e5e6deca43c7fddb15657fa5ceaee public static final Item CAMPFIRE = registerBlock( Blocks.CAMPFIRE, properties -> properties.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY) diff --git a/net/minecraft/world/item/MapItem.java b/net/minecraft/world/item/MapItem.java -index 8795d54cff569c911e0a535f38a0ec4130f7b4d5..309392d414ecbe60474abd0af534184740951707 100644 +index ba0b254d43651bca1f29b5272af05d068fc37ba8..780793750c99185e8139a1cd0ad52bc7b80899a9 100644 --- a/net/minecraft/world/item/MapItem.java +++ b/net/minecraft/world/item/MapItem.java -@@ -196,6 +196,7 @@ public class MapItem extends Item { +@@ -194,6 +194,7 @@ public class MapItem extends Item { public static void renderBiomePreviewMap(ServerLevel serverLevel, ItemStack stack) { MapItemSavedData savedData = getSavedData(stack, serverLevel); if (savedData != null) { @@ -14199,7 +14196,7 @@ index 620069daba04d48b57fc933328eda77f6ca9333e..0403b9b01994269d394820e8c8710ba1 } } diff --git a/net/minecraft/world/item/NameTagItem.java b/net/minecraft/world/item/NameTagItem.java -index 438d98b11275d792f18301c643254dfb733c0dd6..98fa29283994ec50c15591b13331bf9ae87683c6 100644 +index a928124ee46a10e9033f771970198e36712917a6..65ff8078474d5039238e9398d8cfc12e79cc6524 100644 --- a/net/minecraft/world/item/NameTagItem.java +++ b/net/minecraft/world/item/NameTagItem.java @@ -24,6 +24,7 @@ public class NameTagItem extends Item { @@ -14211,7 +14208,7 @@ index 438d98b11275d792f18301c643254dfb733c0dd6..98fa29283994ec50c15591b13331bf9a // Paper end - Add PlayerNameEntityEvent mob.setPersistenceRequired(); diff --git a/net/minecraft/world/item/ProjectileWeaponItem.java b/net/minecraft/world/item/ProjectileWeaponItem.java -index d3e45d6ad45b8f0b681d422edd0edd51ca07f252..f20c38c1ff978d00dc0c9810c050506deed44ebd 100644 +index 220a1d955f31698d5aa6c81c6c779a87c17de447..662e286f40e042823fa7cdd9e27b44e4bfad9cb9 100644 --- a/net/minecraft/world/item/ProjectileWeaponItem.java +++ b/net/minecraft/world/item/ProjectileWeaponItem.java @@ -108,6 +108,8 @@ public abstract class ProjectileWeaponItem extends Item { @@ -14224,10 +14221,10 @@ index d3e45d6ad45b8f0b681d422edd0edd51ca07f252..f20c38c1ff978d00dc0c9810c050506d } diff --git a/net/minecraft/world/item/ShovelItem.java b/net/minecraft/world/item/ShovelItem.java -index 75bbe901e79d9ba3250ed2426a36c1c3363c19c1..e93f35f3bf82994c9e901341c4d6194ef574e3c6 100644 +index 887ac9f547ceaf76fd533ae47239a64c29a64b18..a290ad578498da07093ea31080cc3fbc87aa3778 100644 --- a/net/minecraft/world/item/ShovelItem.java +++ b/net/minecraft/world/item/ShovelItem.java -@@ -47,9 +47,12 @@ public class ShovelItem extends DiggerItem { +@@ -46,9 +46,12 @@ public class ShovelItem extends Item { BlockState blockState1 = FLATTENABLES.get(blockState.getBlock()); BlockState blockState2 = null; Runnable afterAction = null; // Paper @@ -14256,7 +14253,7 @@ index 8eec16040fb9ae6bcccbd71bbe93521cdce5ccce..38b82537209449407922491506a7ca62 if (event.callEvent() && snowball.attemptSpawn()) { player.awardStat(Stats.ITEM_USED.get(this)); diff --git a/net/minecraft/world/item/SpawnEggItem.java b/net/minecraft/world/item/SpawnEggItem.java -index bdb7bfd5212f066517587877a331485afc898cbf..f4728999e41ce01eefe6ce2f359a7c32a268105f 100644 +index 7a961e5ebbdac061f6e73e4ed07fe957ba759066..d48c1dedbd39770ccf3c9c3ff3351b391601cd77 100644 --- a/net/minecraft/world/item/SpawnEggItem.java +++ b/net/minecraft/world/item/SpawnEggItem.java @@ -57,6 +57,23 @@ public class SpawnEggItem extends Item { @@ -14284,50 +14281,48 @@ index bdb7bfd5212f066517587877a331485afc898cbf..f4728999e41ce01eefe6ce2f359a7c32 level.sendBlockUpdated(clickedPos, blockState, blockState, 3); level.gameEvent(context.getPlayer(), GameEvent.BLOCK_CHANGE, clickedPos); diff --git a/net/minecraft/world/item/ThrowablePotionItem.java b/net/minecraft/world/item/ThrowablePotionItem.java -index 2a72ad6686f28127a85faf02024cc6119fa76c58..6a8d6c9835754d142841a6798b7692e64b237fe5 100644 +index 86198fb3150409b4b3e123982d8d3ba40b774621..6495c82fb88062875024c59a7c29d6d18b7a2f41 100644 --- a/net/minecraft/world/item/ThrowablePotionItem.java +++ b/net/minecraft/world/item/ThrowablePotionItem.java -@@ -23,7 +23,7 @@ public class ThrowablePotionItem extends PotionItem implements ProjectileItem { +@@ -24,7 +24,7 @@ public abstract class ThrowablePotionItem extends PotionItem implements Projecti ItemStack itemInHand = player.getItemInHand(hand); if (level instanceof ServerLevel serverLevel) { // Paper start - PlayerLaunchProjectileEvent -- final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F); -+ final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, (float) serverLevel.purpurConfig.throwablePotionProjectileOffset); // Purpur - Projectile offset config +- final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(this::createPotion, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F); ++ final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(this::createPotion, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, (float) serverLevel.purpurConfig.throwablePotionProjectileOffset); // Purpur - Projectile offset config com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) thrownPotion.projectile().getBukkitEntity()); if (event.callEvent() && thrownPotion.attemptSpawn()) { if (event.shouldConsume()) { diff --git a/net/minecraft/world/item/TridentItem.java b/net/minecraft/world/item/TridentItem.java -index 23284dbeff327d1b8dc89f3a0dc0ee549cec2daa..7ea7db834e7b627a1d7d37ca87cd43eb61408565 100644 +index df629e3f2defce5e65aaf874d7c5ddff71f39c28..34d15412b8f68ed1bae45b81ecf759c9c4d7e20c 100644 --- a/net/minecraft/world/item/TridentItem.java +++ b/net/minecraft/world/item/TridentItem.java -@@ -90,7 +90,7 @@ public class TridentItem extends Item implements ProjectileItem { - // stack.hurtWithoutBreaking(1, player); // CraftBukkit - moved down +@@ -83,7 +83,7 @@ public class TridentItem extends Item implements ProjectileItem { if (tridentSpinAttackStrength == 0.0F) { - Projectile.Delayed tridentDelayed = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent -- ThrownTrident::new, serverLevel, stack, player, 0.0F, 2.5F, 1.0F -+ ThrownTrident::new, serverLevel, stack, player, 0.0F, 2.5F, (float) serverLevel.purpurConfig.tridentProjectileOffset // Purpur - Projectile offset config + ItemStack itemStack = stack.copyWithCount(1); // Paper + Projectile.Delayed tridentDelayed = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent( +- ThrownTrident::new, serverLevel, itemStack, player, 0.0F, 2.5F, 1.0F ++ ThrownTrident::new, serverLevel, itemStack, player, 0.0F, 2.5F, (float) serverLevel.purpurConfig.tridentProjectileOffset // Purpur - Projectile offset config ); // Paper start - PlayerLaunchProjectileEvent com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity()); -@@ -101,6 +101,9 @@ public class TridentItem extends Item implements ProjectileItem { +@@ -94,6 +94,7 @@ public class TridentItem extends Item implements ProjectileItem { return false; } ThrownTrident thrownTrident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent -+ + thrownTrident.setActualEnchantments(stack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting -+ - if (event.shouldConsume()) stack.hurtWithoutBreaking(1, player); // Paper - PlayerLaunchProjectileEvent - thrownTrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved - // CraftBukkit end -@@ -130,6 +133,18 @@ public class TridentItem extends Item implements ProjectileItem { + if (event.shouldConsume()) { + stack.hurtWithoutBreaking(1, player); // Paper - PlayerLaunchProjectileEvent + } +@@ -126,6 +127,18 @@ public class TridentItem extends Item implements ProjectileItem { f1 *= tridentSpinAttackStrength / squareRoot; f2 *= tridentSpinAttackStrength / squareRoot; org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(player, stack, f, f1, f2); // CraftBukkit + + // Purpur start - Implement elytra settings -+ List list = EquipmentSlot.VALUES.stream().filter((enumitemslot) -> LivingEntity.canGlideUsing(entity.getItemBySlot(enumitemslot), enumitemslot)).toList(); ++ List list = net.minecraft.world.entity.EquipmentSlot.VALUES.stream().filter((enumitemslot) -> LivingEntity.canGlideUsing(entity.getItemBySlot(enumitemslot), enumitemslot)).toList(); + if (!list.isEmpty()) { -+ EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, entity.random); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, entity.random); + ItemStack glideItem = entity.getItemBySlot(enumitemslot); + if (glideItem.has(net.minecraft.core.component.DataComponents.GLIDER) && level.purpurConfig.elytraDamagePerTridentBoost > 0) { + glideItem.hurtAndBreak(level.purpurConfig.elytraDamagePerTridentBoost, entity, enumitemslot); @@ -14356,7 +14351,7 @@ index 41e1e076a4567d3d3202cf8e426a1ebb391d85e8..2d710dd3f20cbea06c16f14a558b575b // CraftBukkit end } diff --git a/net/minecraft/world/item/crafting/Ingredient.java b/net/minecraft/world/item/crafting/Ingredient.java -index 879c8fe1f20decc793cfa39e686b61d521bd76ba..e9189347cc145bc6dcca2c66d1bd0f23ea71516d 100644 +index 879c8fe1f20decc793cfa39e686b61d521bd76ba..9c383a1028988cdd3de8b29ba72a4d7bd2a37c7e 100644 --- a/net/minecraft/world/item/crafting/Ingredient.java +++ b/net/minecraft/world/item/crafting/Ingredient.java @@ -36,6 +36,7 @@ public final class Ingredient implements StackedContents.IngredientInfo> ENCHANTMENT_ORDER = java.util.Comparator.comparing(Holder::getRegisteredName); - public static final ItemEnchantments EMPTY = new ItemEnchantments(new it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap<>(ENCHANTMENT_ORDER), true); - // Paper end + public static final ItemEnchantments EMPTY = new ItemEnchantments(new it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap<>(ENCHANTMENT_ORDER)); + // Paper end - sort enchantments - private static final Codec LEVEL_CODEC = Codec.intRange(1, 255); + private static final Codec LEVEL_CODEC = Codec.intRange(1, (org.purpurmc.purpur.PurpurConfig.clampEnchantLevels ? 255 : 32767)); // Purpur - Add toggle for enchant level clamping - // Paper start - sort enchantments - private static final Codec>> LEVELS_CODEC = Codec.unboundedMap(Enchantment.CODEC, LEVEL_CODEC) - .xmap(m -> { -@@ -65,7 +65,7 @@ public class ItemEnchantments implements TooltipProvider { + public static final Codec CODEC = Codec.unboundedMap(Enchantment.CODEC, LEVEL_CODEC) + .xmap( + map -> new net.minecraft.world.item.enchantment.ItemEnchantments(net.minecraft.Util.make(new it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap<>(ENCHANTMENT_ORDER), m -> m.putAll(map))), // Paper - sort enchantments +@@ -50,7 +50,7 @@ public class ItemEnchantments implements TooltipProvider { for (Entry> entry : enchantments.object2IntEntrySet()) { int intValue = entry.getIntValue(); @@ -14464,7 +14459,7 @@ index cc87a5026a65192ae1f97b2bd03a918b75df0698..e10f1ffd7b3f17b5c0b6655c0b3edf21 throw new IllegalArgumentException("Enchantment " + entry.getKey() + " has invalid level " + intValue); } } -@@ -160,13 +160,13 @@ public class ItemEnchantments implements TooltipProvider { +@@ -133,13 +133,13 @@ public class ItemEnchantments implements TooltipProvider { if (level <= 0) { this.enchantments.removeInt(enchantment); } else { @@ -14481,7 +14476,7 @@ index cc87a5026a65192ae1f97b2bd03a918b75df0698..e10f1ffd7b3f17b5c0b6655c0b3edf21 } diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java -index 6c06350751db7543d5bde7723121d9d9dbb79071..455ceb46f1ad99f20bda2c31bc252426dc95719a 100644 +index 9333c63f217e1207eced37c5be150e192f2fcc3e..156cee58134ada34d249aab948c02adac4f6745a 100644 --- a/net/minecraft/world/item/trading/MerchantOffer.java +++ b/net/minecraft/world/item/trading/MerchantOffer.java @@ -143,7 +143,12 @@ public class MerchantOffer { @@ -14499,10 +14494,10 @@ index 6c06350751db7543d5bde7723121d9d9dbb79071..455ceb46f1ad99f20bda2c31bc252426 public ItemStack assemble() { diff --git a/net/minecraft/world/level/BaseSpawner.java b/net/minecraft/world/level/BaseSpawner.java -index 425fcc7872c6ebd2156be8bea1d516ce7aeeb280..8de482367f3d9d91048b7c85cbaefcda9f9fbcdc 100644 +index 650ebce14d618076cec2066d134d2ae51a87076a..0babc951d9fed6d32d3dba549cc5ced4dc6b0588 100644 --- a/net/minecraft/world/level/BaseSpawner.java +++ b/net/minecraft/world/level/BaseSpawner.java -@@ -52,6 +52,7 @@ public abstract class BaseSpawner { +@@ -54,6 +54,7 @@ public abstract class BaseSpawner { } public boolean isNearPlayer(Level level, BlockPos pos) { @@ -14524,19 +14519,19 @@ index 892a7c1eb1b321ca6d5ca709142e7feae1220815..7719bc8ff1fbbc67cdf15e1fec28dc92 if (distance < 0.0 || d < distance * distance) { return true; diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index b831f189bcee62a41a16017c2bb958aeee728984..98cb62d4b79c0918abe139f198c5be118b9133c4 100644 +index 96f29ce52dfbaebdaff287e4ae249f6628b22cf7..3b814983b91165ecee1a15d24cc0352247316a9f 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -174,6 +174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -163,6 +163,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl + return this.galeConfig; + } // Gale end - Gale configuration - - public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur - Purpur config files - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -183,6 +184,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public static @Nullable BlockPos lastPhysicsProblem; // Spigot + private int tileTickPosition; +@@ -170,6 +171,48 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here public final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // Gale - Pufferfish - move random tick random + // Purpur start - Add adjustable breeding cooldown to config @@ -14580,12 +14575,11 @@ index b831f189bcee62a41a16017c2bb958aeee728984..98cb62d4b79c0918abe139f198c5be11 + return java.util.Objects.hash(playerUUID, animalType); + } + } -+ // Purpur end - Add adjustable breeding cooldown to config + public CraftWorld getWorld() { return this.world; } -@@ -860,6 +904,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -846,6 +889,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config this.galeConfig = galeWorldConfigCreator.apply(this.spigotConfig); // Gale - Gale configuration @@ -14594,7 +14588,7 @@ index b831f189bcee62a41a16017c2bb958aeee728984..98cb62d4b79c0918abe139f198c5be11 this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); -@@ -2131,4 +2177,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -2127,4 +2172,14 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl return this.id; } } @@ -14610,10 +14604,10 @@ index b831f189bcee62a41a16017c2bb958aeee728984..98cb62d4b79c0918abe139f198c5be11 + // Purpur end - Add allow water in end world option } diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 4bee1ba137d078563cedfdd184a8b4603df17487..d3f5242fc66529bf3137da4d505a6cf55e749e43 100644 +index ec32d77447dd250857a2af1d8cc3e6e233aa3e6e..345d4b80bd4383e0fb66d744d87bc8ef4100fd32 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -260,7 +260,7 @@ public final class NaturalSpawner { +@@ -254,7 +254,7 @@ public final class NaturalSpawner { mutableBlockPos.set(x, y, z); double d = x + 0.5; double d1 = z + 0.5; @@ -14623,10 +14617,10 @@ index 4bee1ba137d078563cedfdd184a8b4603df17487..d3f5242fc66529bf3137da4d505a6cf5 double d2 = nearestPlayer.distanceToSqr(d, y, d1); if (level.isLoadedAndInBounds(mutableBlockPos) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { // Paper - don't load chunks for mob spawn diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index 4d183fb445c43621c5ce95edc1af27b6a41f0acb..6030c4eefd77969a1a9251de76d4291dcb0a2092 100644 +index 63d0b83d648ab1a6e7c84a49f7e2e825076904ad..619d00f79276665777f3a58dec7a5f353bd7d660 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java -@@ -317,7 +317,7 @@ public class ServerExplosion implements Explosion { +@@ -314,7 +314,7 @@ public class ServerExplosion implements Explosion { ) { this.level = level; this.source = source; @@ -14635,7 +14629,7 @@ index 4d183fb445c43621c5ce95edc1af27b6a41f0acb..6030c4eefd77969a1a9251de76d4291d this.center = center; this.fire = fire; this.blockInteraction = blockInteraction; -@@ -647,10 +647,27 @@ public class ServerExplosion implements Explosion { +@@ -636,10 +636,27 @@ public class ServerExplosion implements Explosion { public void explode() { // CraftBukkit start @@ -14647,7 +14641,7 @@ index 4d183fb445c43621c5ce95edc1af27b6a41f0acb..6030c4eefd77969a1a9251de76d4291d + // Purpur start - add PreExplodeEvents + if (this.source != null) { + Location location = new Location(this.level.getWorld(), this.center.x, this.center.y, this.center.z); -+ if(!new org.purpurmc.purpur.event.entity.PreEntityExplodeEvent(this.source.getBukkitEntity(), location, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { ++ if(!new org.purpurmc.purpur.event.entity.PreEntityExplodeEvent(this.source.getBukkitEntity(), location, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, org.bukkit.craftbukkit.CraftExplosionResult.toExplosionResult(getBlockInteraction())).callEvent()) { + this.wasCanceled = true; + return; + } @@ -14655,7 +14649,7 @@ index 4d183fb445c43621c5ce95edc1af27b6a41f0acb..6030c4eefd77969a1a9251de76d4291d + Location location = new Location(this.level.getWorld(), this.center.x, this.center.y, this.center.z); + org.bukkit.block.Block block = location.getBlock(); + org.bukkit.block.BlockState blockState = (this.damageSource.causingBlockSnapshot() != null) ? this.damageSource.causingBlockSnapshot() : block.getState(); -+ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { ++ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState, org.bukkit.craftbukkit.CraftExplosionResult.toExplosionResult(getBlockInteraction())).callEvent()) { + this.wasCanceled = true; + return; + } @@ -14665,10 +14659,10 @@ index 4d183fb445c43621c5ce95edc1af27b6a41f0acb..6030c4eefd77969a1a9251de76d4291d this.blockCache = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); this.chunkPosCache = new long[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH]; diff --git a/net/minecraft/world/level/block/AnvilBlock.java b/net/minecraft/world/level/block/AnvilBlock.java -index a788ebfac915a87df49b31467844fcb087a9b89b..c2eaacb4657d7329cc16e4f3d36fa545c7e4c2b7 100644 +index e8bac6deb63e0f94fb5f8b38602b2e3333e5fa8d..b14736c25cfdd94c6e3f159e53865150b06edef6 100644 --- a/net/minecraft/world/level/block/AnvilBlock.java +++ b/net/minecraft/world/level/block/AnvilBlock.java -@@ -59,6 +59,53 @@ public class AnvilBlock extends FallingBlock { +@@ -54,6 +54,53 @@ public class AnvilBlock extends FallingBlock { return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getClockWise()); } @@ -14723,10 +14717,10 @@ index a788ebfac915a87df49b31467844fcb087a9b89b..c2eaacb4657d7329cc16e4f3d36fa545 protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { if (!level.isClientSide) { diff --git a/net/minecraft/world/level/block/AzaleaBlock.java b/net/minecraft/world/level/block/AzaleaBlock.java -index 4555eb8e1be743f83b3f5b57b6e5f3301f9b4ee9..e9d92d29c5b403dd33463e968822e3414e7bf278 100644 +index 435a455ad2ec3dfb142d570a51a720bc6c49dac3..32a1dc20202bad7a15794e98cdc1bf2fb2ad5308 100644 --- a/net/minecraft/world/level/block/AzaleaBlock.java +++ b/net/minecraft/world/level/block/AzaleaBlock.java -@@ -50,6 +50,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock { +@@ -50,6 +50,20 @@ public class AzaleaBlock extends VegetationBlock implements BonemealableBlock { @Override public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { @@ -14748,7 +14742,7 @@ index 4555eb8e1be743f83b3f5b57b6e5f3301f9b4ee9..e9d92d29c5b403dd33463e968822e341 } diff --git a/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java b/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java -index 045d85b1267e20ca66ef08eb981f167c64d8c780..e804ca8d6c9c9b8d9f982a970cc3edddf5c03aa1 100644 +index fb6e9194440b85487660f91aea7e34fdf086187b..2653ae5bf66f2b117f86e4df04d9cc307ba09011 100644 --- a/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java +++ b/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java @@ -39,6 +39,7 @@ public abstract class BaseCoralPlantTypeBlock extends Block implements SimpleWat @@ -14760,10 +14754,10 @@ index 045d85b1267e20ca66ef08eb981f167c64d8c780..e804ca8d6c9c9b8d9f982a970cc3eddd return true; } else { diff --git a/net/minecraft/world/level/block/BedBlock.java b/net/minecraft/world/level/block/BedBlock.java -index 8c21e8aa4922691fa66cd22d631646c554251bdd..999abf6a27682eed16273c9a73dc9479fc3008c0 100644 +index e72ead9ff6541f821a61ad3c50fe068a8c8bb69d..a6f4db5c99d332ac26a52d5174f75e7dc9f51fe5 100644 --- a/net/minecraft/world/level/block/BedBlock.java +++ b/net/minecraft/world/level/block/BedBlock.java -@@ -100,7 +100,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -98,7 +98,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock } Vec3 center = pos.getCenter(); @@ -14772,7 +14766,7 @@ index 8c21e8aa4922691fa66cd22d631646c554251bdd..999abf6a27682eed16273c9a73dc9479 return InteractionResult.SUCCESS_SERVER; } else if (state.getValue(OCCUPIED)) { if (!BedBlock.canSetSpawn(level)) return this.explodeBed(state, level, pos); // Paper - check explode first -@@ -148,7 +148,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -146,7 +146,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock } Vec3 center = pos.getCenter(); @@ -14781,20 +14775,20 @@ index 8c21e8aa4922691fa66cd22d631646c554251bdd..999abf6a27682eed16273c9a73dc9479 return InteractionResult.SUCCESS_SERVER; } // CraftBukkit end -@@ -169,7 +169,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -167,7 +167,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock @Override - public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { -- super.fallOn(level, state, pos, entity, fallDistance * 0.5F); + public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) { +- super.fallOn(level, state, pos, entity, fallDistance * 0.5); + super.fallOn(level, state, pos, entity, fallDistance); // Purpur - Configurable block fall damage modifiers } @Override diff --git a/net/minecraft/world/level/block/BigDripleafBlock.java b/net/minecraft/world/level/block/BigDripleafBlock.java -index 1cc8fd0a273c3a7a75bf1ea522d109bd94718f43..3c7544569edb83e03fc0b9e01fbff9a368110427 100644 +index e1193bcb666b7d38c511df7c1ebddb5897cefa8f..29248afa290b3143375f0538b4dfc80a63f8945f 100644 --- a/net/minecraft/world/level/block/BigDripleafBlock.java +++ b/net/minecraft/world/level/block/BigDripleafBlock.java -@@ -261,7 +261,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone +@@ -254,7 +254,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone playTiltSound(level, pos, sound); } @@ -14804,10 +14798,10 @@ index 1cc8fd0a273c3a7a75bf1ea522d109bd94718f43..3c7544569edb83e03fc0b9e01fbff9a3 level.scheduleTick(pos, this, _int); } diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java -index 79de4c558f7cbeff7e55b6d9ad2644be46d72cd9..706a25c42580c0b7317bc85be5c8f2e66a1ef1e0 100644 +index 064e08e28acf7497e950d4e7f6ad7bddd92418b4..a425131042b46843c1f41ee0e9454866f193c5d3 100644 --- a/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java -@@ -90,6 +90,10 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -99,6 +99,10 @@ public class Block extends BlockBehaviour implements ItemLike { public static final int UPDATE_LIMIT = 512; protected final StateDefinition stateDefinition; private BlockState defaultBlockState; @@ -14818,7 +14812,7 @@ index 79de4c558f7cbeff7e55b6d9ad2644be46d72cd9..706a25c42580c0b7317bc85be5c8f2e6 // Paper start - Protect Bedrock and End Portal/Frames from being destroyed public final boolean isDestroyable() { return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || -@@ -299,7 +303,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -345,7 +349,7 @@ public class Block extends BlockBehaviour implements ItemLike { event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping event.callEvent(); for (org.bukkit.inventory.ItemStack drop : event.getDrops()) { @@ -14827,22 +14821,22 @@ index 79de4c558f7cbeff7e55b6d9ad2644be46d72cd9..706a25c42580c0b7317bc85be5c8f2e6 } state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping -@@ -317,7 +321,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -363,7 +367,7 @@ public class Block extends BlockBehaviour implements ItemLike { public static void dropResources(BlockState state, LevelAccessor level, BlockPos pos, @Nullable BlockEntity blockEntity) { if (level instanceof ServerLevel) { -- getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(itemStack -> popResource((ServerLevel)level, pos, itemStack)); -+ getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(itemStack -> popResource((ServerLevel)level, pos, applyLoreFromTile(itemStack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName +- getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(stack -> popResource((ServerLevel)level, pos, stack)); ++ getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(stack -> popResource((ServerLevel)level, pos, applyLoreFromTile(stack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName state.spawnAfterBreak((ServerLevel)level, pos, ItemStack.EMPTY, true); } } -@@ -329,11 +333,30 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -375,11 +379,30 @@ public class Block extends BlockBehaviour implements ItemLike { public static void dropResources(BlockState state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) { // Paper end - Properly handle xp dropping if (level instanceof ServerLevel) { -- getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, itemStack)); -+ getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, applyLoreFromTile(itemStack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName - state.spawnAfterBreak((ServerLevel) level, pos, tool, dropExperience); // Paper - Properly handle xp dropping +- getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(stack -> popResource(level, pos, stack)); ++ getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(stack -> popResource(level, pos, applyLoreFromTile(stack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName + state.spawnAfterBreak((ServerLevel)level, pos, tool, dropExperience); // Paper - Properly handle xp dropping } } @@ -14868,7 +14862,7 @@ index 79de4c558f7cbeff7e55b6d9ad2644be46d72cd9..706a25c42580c0b7317bc85be5c8f2e6 public static void popResource(Level level, BlockPos pos, ItemStack stack) { double d = EntityType.ITEM.getHeight() / 2.0; double d1 = pos.getX() + 0.5 + Mth.nextDouble(level.random, -0.25, 0.25); -@@ -412,7 +435,15 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -460,7 +483,15 @@ public class Block extends BlockBehaviour implements ItemLike { } public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { @@ -14884,20 +14878,20 @@ index 79de4c558f7cbeff7e55b6d9ad2644be46d72cd9..706a25c42580c0b7317bc85be5c8f2e6 public boolean isPossibleToRespawnInThis(BlockState state) { return !state.isSolid() && !state.liquid(); -@@ -423,7 +454,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -471,7 +502,7 @@ public class Block extends BlockBehaviour implements ItemLike { } - public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { + public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) { - entity.causeFallDamage(fallDistance, 1.0F, entity.damageSources().fall()); + entity.causeFallDamage(fallDistance * fallDistanceMultiplier, fallDamageMultiplier, entity.damageSources().fall()); // Purpur - Configurable block fall damage modifiers } public void updateEntityMovementAfterFallOn(BlockGetter level, Entity entity) { diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java -index 0401a5e88fe7840ae667748409411ab73888799c..bf047be5b577b0d1bf70458df14618bcfe2d1de2 100644 +index cea1e405c940cd51cf830f28bfc6ce72c0c36a12..4941bf9df0c8ed6316572920323f7c5f6791b002 100644 --- a/net/minecraft/world/level/block/Blocks.java +++ b/net/minecraft/world/level/block/Blocks.java -@@ -6486,6 +6486,7 @@ public class Blocks { +@@ -6583,6 +6583,7 @@ public class Blocks { BlockBehaviour.Properties.of() .mapColor(MapColor.PLANT) .forceSolidOff() @@ -14905,7 +14899,7 @@ index 0401a5e88fe7840ae667748409411ab73888799c..bf047be5b577b0d1bf70458df14618bc .instabreak() .sound(SoundType.AZALEA) .noOcclusion() -@@ -6497,6 +6498,7 @@ public class Blocks { +@@ -6594,6 +6595,7 @@ public class Blocks { BlockBehaviour.Properties.of() .mapColor(MapColor.PLANT) .forceSolidOff() @@ -14914,56 +14908,26 @@ index 0401a5e88fe7840ae667748409411ab73888799c..bf047be5b577b0d1bf70458df14618bc .sound(SoundType.FLOWERING_AZALEA) .noOcclusion() diff --git a/net/minecraft/world/level/block/BubbleColumnBlock.java b/net/minecraft/world/level/block/BubbleColumnBlock.java -index 400e213f4a2f8f09198257ce64d528932180edb5..1d907cfa53808464f6cfe631435a3b55030b6f29 100644 +index ab93da06d9e9858668aa796db497f282afa7020a..23a9c30baf8d33855703d45c2739fd5072d81adc 100644 --- a/net/minecraft/world/level/block/BubbleColumnBlock.java +++ b/net/minecraft/world/level/block/BubbleColumnBlock.java -@@ -124,10 +124,10 @@ public class BubbleColumnBlock extends Block implements BucketPickup { +@@ -98,9 +98,9 @@ public class BubbleColumnBlock extends Block implements BucketPickup { if (blockState.is(Blocks.BUBBLE_COLUMN)) { return blockState; } else if (blockState.is(Blocks.SOUL_SAND)) { -- return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(false)); -+ return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(org.purpurmc.purpur.PurpurConfig.soulSandBlockReverseBubbleColumnFlow)); // Purpur - Config to reverse bubble column flow +- return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, false); ++ return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, org.purpurmc.purpur.PurpurConfig.soulSandBlockReverseBubbleColumnFlow); // Purpur - Config to reverse bubble column flow } else { - return blockState.is(Blocks.MAGMA_BLOCK) -- ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(true)) -+ ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(!org.purpurmc.purpur.PurpurConfig.magmaBlockReverseBubbleColumnFlow)) // Purpur - Config to reverse bubble column flow - : Blocks.WATER.defaultBlockState(); +- return blockState.is(Blocks.MAGMA_BLOCK) ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, true) : Blocks.WATER.defaultBlockState(); ++ return blockState.is(Blocks.MAGMA_BLOCK) ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, !org.purpurmc.purpur.PurpurConfig.magmaBlockReverseBubbleColumnFlow) : Blocks.WATER.defaultBlockState(); // Purpur - Config to reverse bubble column flow } } -diff --git a/net/minecraft/world/level/block/BushBlock.java b/net/minecraft/world/level/block/BushBlock.java -index bc52568bfa56635300266424488e524d77d95e09..8f2eebc60d655d5a2c233e2b931cdca2c6a5e768 100644 ---- a/net/minecraft/world/level/block/BushBlock.java -+++ b/net/minecraft/world/level/block/BushBlock.java -@@ -61,4 +61,24 @@ public abstract class BushBlock extends Block { - protected boolean isPathfindable(BlockState state, PathComputationType pathComputationType) { - return pathComputationType == PathComputationType.AIR && !this.hasCollision || super.isPathfindable(state, pathComputationType); - } -+ -+ // Purpur start - Ability for hoe to replant crops -+ public void playerDestroyAndReplant(net.minecraft.world.level.Level world, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @javax.annotation.Nullable net.minecraft.world.level.block.entity.BlockEntity blockEntity, net.minecraft.world.item.ItemStack itemInHand, net.minecraft.world.level.ItemLike itemToReplant) { -+ player.awardStat(net.minecraft.stats.Stats.BLOCK_MINED.get(this)); -+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); -+ java.util.List dropList = Block.getDrops(state, (net.minecraft.server.level.ServerLevel) world, pos, blockEntity, player, itemInHand); -+ -+ boolean planted = false; -+ for (net.minecraft.world.item.ItemStack itemToDrop : dropList) { -+ if (!planted && itemToDrop.getItem() == itemToReplant) { -+ world.setBlock(pos, defaultBlockState(), 3); -+ itemToDrop.setCount(itemToDrop.getCount() - 1); -+ planted = true; -+ } -+ Block.popResource(world, pos, itemToDrop); -+ } -+ -+ state.spawnAfterBreak((net.minecraft.server.level.ServerLevel) world, pos, itemInHand, true); -+ } -+ // Purpur end - Ability for hoe to replant crops - } + diff --git a/net/minecraft/world/level/block/CactusBlock.java b/net/minecraft/world/level/block/CactusBlock.java -index 8c3aca2430eac2a31d1e0b1137e3324ec5b29a20..079b4c95cf81119ca99daeb159aefca389afed74 100644 +index 8f6878cc8e72513446895bfc79886075bfcd5565..0f8cfa5423cd1813c655237aa544dad2dc56ba4d 100644 --- a/net/minecraft/world/level/block/CactusBlock.java +++ b/net/minecraft/world/level/block/CactusBlock.java -@@ -21,7 +21,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; +@@ -22,7 +22,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; @@ -14972,7 +14936,7 @@ index 8c3aca2430eac2a31d1e0b1137e3324ec5b29a20..079b4c95cf81119ca99daeb159aefca3 public static final MapCodec CODEC = simpleCodec(CactusBlock::new); public static final IntegerProperty AGE = BlockStateProperties.AGE_15; public static final int MAX_AGE = 15; -@@ -104,7 +104,7 @@ public class CactusBlock extends Block { +@@ -117,7 +117,7 @@ public class CactusBlock extends Block { protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { for (Direction direction : Direction.Plane.HORIZONTAL) { BlockState blockState = level.getBlockState(pos.relative(direction)); @@ -14981,7 +14945,7 @@ index 8c3aca2430eac2a31d1e0b1137e3324ec5b29a20..079b4c95cf81119ca99daeb159aefca3 return false; } } -@@ -128,4 +128,34 @@ public class CactusBlock extends Block { +@@ -141,4 +141,34 @@ public class CactusBlock extends Block { protected boolean isPathfindable(BlockState state, PathComputationType pathComputationType) { return false; } @@ -15017,10 +14981,10 @@ index 8c3aca2430eac2a31d1e0b1137e3324ec5b29a20..079b4c95cf81119ca99daeb159aefca3 + // Purpur end - bonemealable cactus } diff --git a/net/minecraft/world/level/block/CakeBlock.java b/net/minecraft/world/level/block/CakeBlock.java -index f15b56cbfb6540ea26c6a0abdd701b7d7f1a974e..cf6cf43fc3b234cecccf5c7c0cd4571d8cf43099 100644 +index 72236993ebc4fbfc8b6316577caaa9c780bd447b..7c3b5170690af3bbdc856af96c3e01b0e55d6412 100644 --- a/net/minecraft/world/level/block/CakeBlock.java +++ b/net/minecraft/world/level/block/CakeBlock.java -@@ -119,6 +119,7 @@ public class CakeBlock extends Block { +@@ -109,6 +109,7 @@ public class CakeBlock extends Block { org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); if (!event.isCancelled()) { @@ -15029,20 +14993,20 @@ index f15b56cbfb6540ea26c6a0abdd701b7d7f1a974e..cf6cf43fc3b234cecccf5c7c0cd4571d } diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java -index 0bf42a5fdf2c606062b9be4443a9a22346159ecb..9dc0c206e325d2818923e56c97d83b24e1161c26 100644 +index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..642550d59e17330437028a84830520f394a41728 100644 --- a/net/minecraft/world/level/block/CampfireBlock.java +++ b/net/minecraft/world/level/block/CampfireBlock.java -@@ -141,7 +141,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB +@@ -124,7 +124,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB return this.defaultBlockState() - .setValue(WATERLOGGED, Boolean.valueOf(flag)) - .setValue(SIGNAL_FIRE, Boolean.valueOf(this.isSmokeSource(level.getBlockState(clickedPos.below())))) -- .setValue(LIT, Boolean.valueOf(!flag)) -+ .setValue(LIT, Boolean.valueOf(level.getMinecraftWorld().purpurConfig.campFireLitWhenPlaced && !flag)) // Purpur - Campfire option for lit when placed + .setValue(WATERLOGGED, flag) + .setValue(SIGNAL_FIRE, this.isSmokeSource(level.getBlockState(clickedPos.below()))) +- .setValue(LIT, !flag) ++ .setValue(LIT, level.getMinecraftWorld().purpurConfig.campFireLitWhenPlaced && !flag) // Purpur - Campfire option for lit when placed .setValue(FACING, context.getHorizontalDirection()); } diff --git a/net/minecraft/world/level/block/CarvedPumpkinBlock.java b/net/minecraft/world/level/block/CarvedPumpkinBlock.java -index 291107e21a858215821b82d184fcfb54abbc0d97..b05a96f66724cdfb2daf625f943d7e81377cb93f 100644 +index 7cdf16c7216878350537b5331081cb30f44d6dbb..a4854370dfdcbc7ec4c27975e4feb69d4cb48a11 100644 --- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java +++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java @@ -64,7 +64,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { @@ -15076,9 +15040,9 @@ index 291107e21a858215821b82d184fcfb54abbc0d97..b05a96f66724cdfb2daf625f943d7e81 + ironGolem.setSummoner(placer == null ? null : placer.getUUID()); + } + // Purpur end - Summoner API - // clearPatternBlocks(level, patternMatch); // CraftBukkit - moved down - golem.moveTo(pos.getX() + 0.5, pos.getY() + 0.05, pos.getZ() + 0.5, 0.0F, 0.0F); - if (!level.addFreshEntity(golem, (golem.getType() == EntityType.SNOW_GOLEM) ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM)) { + // clearPatternBlocks(level, patternMatch); // Paper - moved down + golem.snapTo(pos.getX() + 0.5, pos.getY() + 0.05, pos.getZ() + 0.5, 0.0F, 0.0F); + // Paper start diff --git a/net/minecraft/world/level/block/CauldronBlock.java b/net/minecraft/world/level/block/CauldronBlock.java index d58b49e550cfa683f753db2a913fddf307a1bba2..62ee64b97dfb2f1426d43cf1f8b0b0b6ec63b5b1 100644 --- a/net/minecraft/world/level/block/CauldronBlock.java @@ -15095,12 +15059,12 @@ index d58b49e550cfa683f753db2a913fddf307a1bba2..62ee64b97dfb2f1426d43cf1f8b0b0b6 @Override diff --git a/net/minecraft/world/level/block/CaveVinesBlock.java b/net/minecraft/world/level/block/CaveVinesBlock.java -index ff445bb33a97e3fd2ef0f8759e59ef762d0a578f..b7a7a8d6587cc9b32ee23797411b25d7eccd92d4 100644 +index 4e1a81c01a5c51a977e4fe9d2465e4ef20aab6d4..d67f278e8cb630b680cad22f4117a9545576bf0f 100644 --- a/net/minecraft/world/level/block/CaveVinesBlock.java +++ b/net/minecraft/world/level/block/CaveVinesBlock.java @@ -92,4 +92,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements CaveVines { public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { - level.setBlock(pos, state.setValue(BERRIES, Boolean.valueOf(true)), 2); + level.setBlock(pos, state.setValue(BERRIES, true), 2); } + + // Purpur start - cave vines configurable max growth age @@ -15111,7 +15075,7 @@ index ff445bb33a97e3fd2ef0f8759e59ef762d0a578f..b7a7a8d6587cc9b32ee23797411b25d7 + // Purpur end - cave vines configurable max growth age } diff --git a/net/minecraft/world/level/block/ChangeOverTimeBlock.java b/net/minecraft/world/level/block/ChangeOverTimeBlock.java -index 4f98ae8bd4bfb681883132eddb57cbc5703d7d9e..c84e1c124b733fb918de17340f7e0f57162b8051 100644 +index ba7dbfa3f95bf93f3e50b17aa48b772a3047b74d..d42062a86c1278b71bc085cc3fb29a69039873de 100644 --- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java +++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java @@ -51,7 +51,7 @@ public interface ChangeOverTimeBlock> { @@ -15124,10 +15088,10 @@ index 4f98ae8bd4bfb681883132eddb57cbc5703d7d9e..c84e1c124b733fb918de17340f7e0f57 } } diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java -index 4d2a5888695b99fb150e23b7d8c4b4d4a455b8c6..db4b26262e3ee1064f2930377b56f13298c47203 100644 +index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..43f9d4b8a7ab4cd0a1a5dee9d0c0c7790894a2ae 100644 --- a/net/minecraft/world/level/block/ChestBlock.java +++ b/net/minecraft/world/level/block/ChestBlock.java -@@ -357,6 +357,7 @@ public class ChestBlock extends AbstractChestBlock implements +@@ -337,6 +337,7 @@ public class ChestBlock extends AbstractChestBlock implements } public static boolean isBlockedChestByBlock(BlockGetter level, BlockPos pos) { @@ -15136,10 +15100,10 @@ index 4d2a5888695b99fb150e23b7d8c4b4d4a455b8c6..db4b26262e3ee1064f2930377b56f132 return level.getBlockState(blockPos).isRedstoneConductor(level, blockPos); } diff --git a/net/minecraft/world/level/block/ComposterBlock.java b/net/minecraft/world/level/block/ComposterBlock.java -index c8ffb634df661a6a4520731be725b51480764976..9fb36207ce829d1a8b952017d3b60db015efdaaf 100644 +index 7977ecd013c55359f179b4b7f895099b7eb02294..be9fe9147cca1293c09dbfae0109a3c07a5c1e16 100644 --- a/net/minecraft/world/level/block/ComposterBlock.java +++ b/net/minecraft/world/level/block/ComposterBlock.java -@@ -241,17 +241,27 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { +@@ -250,17 +250,27 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { ) { int levelValue = state.getValue(LEVEL); if (levelValue < 8 && COMPOSTABLES.containsKey(stack.getItem())) { @@ -15177,7 +15141,7 @@ index c8ffb634df661a6a4520731be725b51480764976..9fb36207ce829d1a8b952017d3b60db0 return InteractionResult.SUCCESS; } else { -@@ -259,6 +269,25 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { +@@ -268,6 +278,25 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { } } @@ -15216,19 +15180,19 @@ index e0be02eaa07d40d0738931383426517d20fe3b0b..b747af5f3c65f4b79a304b0e903f7b82 FluidState fluidState = level.getFluidState(pos.relative(direction)); if (fluidState.is(FluidTags.WATER)) { diff --git a/net/minecraft/world/level/block/CropBlock.java b/net/minecraft/world/level/block/CropBlock.java -index bc0969f40814094e42a860a72314fccd1a66fabe..27f0c5c886a3f8b14ef9a00e2aaaabf4bf09c7db 100644 +index a38ce03a4dab6c83a0b54f47fd3c36d6da46fa24..275eabf64977cdf262de55124c3e5f88d8667213 100644 --- a/net/minecraft/world/level/block/CropBlock.java +++ b/net/minecraft/world/level/block/CropBlock.java -@@ -182,7 +182,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { +@@ -169,7 +169,7 @@ public class CropBlock extends VegetationBlock implements BonemealableBlock { @Override - protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent - if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.purpurConfig.ravagerGriefableBlocks.contains(serverLevel.getBlockState(pos).getBlock()) && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !serverLevel.purpurConfig.ravagerBypassMobGriefing == !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Purpur - Configurable ravager griefable blocks list // Purpur - Add mobGriefing bypass to everything affected serverLevel.destroyBlock(pos, true, entity); } -@@ -217,4 +217,15 @@ public class CropBlock extends BushBlock implements BonemealableBlock { +@@ -204,4 +204,15 @@ public class CropBlock extends VegetationBlock implements BonemealableBlock { protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(AGE); } @@ -15245,10 +15209,10 @@ index bc0969f40814094e42a860a72314fccd1a66fabe..27f0c5c886a3f8b14ef9a00e2aaaabf4 + // Purpur end - Ability for hoe to replant crops } diff --git a/net/minecraft/world/level/block/DoorBlock.java b/net/minecraft/world/level/block/DoorBlock.java -index eaa735478d808f7279b6ca62c546cc3d357c11d0..46948eefac791f267695f5e8abb45ad6d61beaac 100644 +index 7f40ccfe379ab284424d730213b343e17239dc0c..2fa6a85b0f1694d0989905a421198c6495271beb 100644 --- a/net/minecraft/world/level/block/DoorBlock.java +++ b/net/minecraft/world/level/block/DoorBlock.java -@@ -206,6 +206,7 @@ public class DoorBlock extends Block { +@@ -199,6 +199,7 @@ public class DoorBlock extends Block { protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { if (!this.type.canOpenByHand()) { return InteractionResult.PASS; @@ -15256,7 +15220,7 @@ index eaa735478d808f7279b6ca62c546cc3d357c11d0..46948eefac791f267695f5e8abb45ad6 } else { state = state.cycle(OPEN); level.setBlock(pos, state, 10); -@@ -294,4 +295,18 @@ public class DoorBlock extends Block { +@@ -287,4 +288,18 @@ public class DoorBlock extends Block { public static boolean isWoodenDoor(BlockState state) { return state.getBlock() instanceof DoorBlock doorBlock && doorBlock.type().canOpenByHand(); } @@ -15276,7 +15240,7 @@ index eaa735478d808f7279b6ca62c546cc3d357c11d0..46948eefac791f267695f5e8abb45ad6 + // Purpur end - Option to make doors require redstone } diff --git a/net/minecraft/world/level/block/DragonEggBlock.java b/net/minecraft/world/level/block/DragonEggBlock.java -index 38f9003f8260eb2f0606cbd53aa30604cdeb48c0..e72c0f252138858f44e423b28d6e26fcab53a17e 100644 +index 5c2f10486e3aed090c6545a86276e6927e424cb2..9ed7ffb10e0a172fe5f3dd4613922428af82e5db 100644 --- a/net/minecraft/world/level/block/DragonEggBlock.java +++ b/net/minecraft/world/level/block/DragonEggBlock.java @@ -46,6 +46,7 @@ public class DragonEggBlock extends FallingBlock { @@ -15288,34 +15252,32 @@ index 38f9003f8260eb2f0606cbd53aa30604cdeb48c0..e72c0f252138858f44e423b28d6e26fc for (int i = 0; i < 1000; i++) { diff --git a/net/minecraft/world/level/block/EnchantingTableBlock.java b/net/minecraft/world/level/block/EnchantingTableBlock.java -index b2d7a8f45dc7bb447b7c1af3d4411bf8214aca05..92c75217860f1fca706f4e7105589f0f67ba81f4 100644 +index 523082c69aad8269cd058ad6864184c3ab51dbeb..4f4e81a845c4d3dc0e7d82ba323a8595581535e2 100644 --- a/net/minecraft/world/level/block/EnchantingTableBlock.java +++ b/net/minecraft/world/level/block/EnchantingTableBlock.java -@@ -119,4 +119,18 @@ public class EnchantingTableBlock extends BaseEntityBlock { +@@ -119,4 +119,16 @@ public class EnchantingTableBlock extends BaseEntityBlock { protected boolean isPathfindable(BlockState state, PathComputationType pathComputationType) { return false; } + + // Purpur start - Enchantment Table Persists Lapis + @Override -+ public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean moved) { ++ protected void affectNeighborsAfterRemoval(BlockState state, net.minecraft.server.level.ServerLevel level, BlockPos pos, boolean movedByPiston) { + BlockEntity blockEntity = level.getBlockEntity(pos); + + if (level.purpurConfig.enchantmentTableLapisPersists && blockEntity instanceof EnchantingTableBlockEntity enchantmentTable) { + net.minecraft.world.Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.LAPIS_LAZULI, enchantmentTable.getLapis())); -+ level.updateNeighbourForOutputSignal(pos, this); ++ net.minecraft.world.Containers.updateNeighboursAfterDestroy(state, level, pos); + } -+ -+ super.onRemove(state, level, pos, newState, moved); + } + // Purpur end - Enchantment Table Persists Lapis } diff --git a/net/minecraft/world/level/block/EndGatewayBlock.java b/net/minecraft/world/level/block/EndGatewayBlock.java -index 84a1bd5e40e635962d795506861447851e443eee..54abeb142e119edd1c1d1c263821b95b1f05c388 100644 +index 68914268ca9350a6c1d794e011e1f9a8aecd609c..8e53b45dbf740de6c6fe499ef424d11b2b15f9d8 100644 --- a/net/minecraft/world/level/block/EndGatewayBlock.java +++ b/net/minecraft/world/level/block/EndGatewayBlock.java -@@ -98,6 +98,13 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { - org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type +@@ -99,6 +99,13 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { + org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type if (!event.callEvent()) return; // Paper end - call EntityPortalEnterEvent + // Purpur start - Add EntityTeleportHinderedEvent @@ -15329,11 +15291,11 @@ index 84a1bd5e40e635962d795506861447851e443eee..54abeb142e119edd1c1d1c263821b95b TheEndGatewayBlockEntity.triggerCooldown(level, pos, state, theEndGatewayBlockEntity); } diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java -index c11366dd69e1c51bdab45c625b07c15ce2e42cb6..0e8dd3a62e9fca4701ee12acebf6c34e1fb3e6a2 100644 +index cf2b105c98a3b22b9bea59cbafcd598657dc92b5..65d3477ed32c3f0db58aab6ab87d8f1721cbe876 100644 --- a/net/minecraft/world/level/block/EndPortalBlock.java +++ b/net/minecraft/world/level/block/EndPortalBlock.java -@@ -58,6 +58,13 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { - protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +@@ -59,6 +59,13 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { + protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent if (entity.canUsePortal(false)) { + // Purpur start - Add EntityTeleportHinderedEvent @@ -15344,10 +15306,10 @@ index c11366dd69e1c51bdab45c625b07c15ce2e42cb6..0e8dd3a62e9fca4701ee12acebf6c34e + } + // Purpur end - Add EntityTeleportHinderedEvent // CraftBukkit start - Entity in portal - org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type + org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.ENDER); // Paper - add portal type level.getCraftServer().getPluginManager().callEvent(event); diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java -index f5533960708bdbaf2eacefbc7c7c3123b7d26502..17aa27885b4431bf7b98799e02d080b5a0ecbbf1 100644 +index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..72794e204f7fcc31ece94913b7fd9f36ae022b10 100644 --- a/net/minecraft/world/level/block/EnderChestBlock.java +++ b/net/minecraft/world/level/block/EnderChestBlock.java @@ -85,8 +85,8 @@ public class EnderChestBlock extends AbstractChestBlock i @@ -15398,28 +15360,28 @@ index f5533960708bdbaf2eacefbc7c7c3123b7d26502..17aa27885b4431bf7b98799e02d080b5 public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new EnderChestBlockEntity(pos, state); diff --git a/net/minecraft/world/level/block/FarmBlock.java b/net/minecraft/world/level/block/FarmBlock.java -index 1fdede769b67cb5d2f9159c779f19e3639bb6ff5..2ff5457300d66378dbbea492deff0136629bc365 100644 +index a31ac95237515b874f59941ec24c74e2c357b3d8..c816bd47577cbc898b10d0cfd9c40404429ef929 100644 --- a/net/minecraft/world/level/block/FarmBlock.java +++ b/net/minecraft/world/level/block/FarmBlock.java @@ -112,9 +112,9 @@ public class FarmBlock extends Block { - public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { + public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) { super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. if (level instanceof ServerLevel serverLevel -- && level.random.nextFloat() < fallDistance - 0.5F -+ && (serverLevel.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= serverLevel.purpurConfig.farmlandTrampleHeight : level.random.nextFloat() < fallDistance - 0.5F) // // Purpur - Configurable farmland trample height +- && level.random.nextFloat() < fallDistance - 0.5 ++ && (serverLevel.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= serverLevel.purpurConfig.farmlandTrampleHeight : level.random.nextFloat() < fallDistance - 0.5) // Purpur - Configurable farmland trample height && entity instanceof LivingEntity - && (entity instanceof Player || serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) -+ && (entity instanceof Player || serverLevel.purpurConfig.farmlandBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) ++ && (entity instanceof Player || serverLevel.purpurConfig.farmlandBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) // Purpur - Add mobGriefing bypass to everything affected && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { // CraftBukkit start - Interact soil org.bukkit.event.Cancellable cancellable; -@@ -129,6 +129,27 @@ public class FarmBlock extends Block { +@@ -129,6 +129,28 @@ public class FarmBlock extends Block { return; } + if (level.purpurConfig.farmlandTramplingDisabled) return; // Purpur - Farmland trampling changes + if (level.purpurConfig.farmlandTramplingOnlyPlayers && !(entity instanceof Player)) return; // Purpur - Farmland trampling changes -+ ++ + // Purpur start - Ability to re-add farmland mechanics from Alpha + if (level.purpurConfig.farmlandAlpha) { + Block block = level.getBlockState(pos.below()).getBlock(); @@ -15431,8 +15393,9 @@ index 1fdede769b67cb5d2f9159c779f19e3639bb6ff5..2ff5457300d66378dbbea492deff0136 + + // Purpur start - Farmland trampling changes + if (level.purpurConfig.farmlandTramplingFeatherFalling) { -+ java.util.Iterator armor = ((LivingEntity) entity).getArmorSlots().iterator(); -+ if (armor.hasNext() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FEATHER_FALLING, armor.next()) >= (int) entity.fallDistance) { ++ net.minecraft.world.item.ItemStack bootsItem = ((net.minecraft.world.entity.LivingEntity) entity).getItemBySlot(net.minecraft.world.entity.EquipmentSlot.FEET); ++ ++ if (bootsItem != net.minecraft.world.item.ItemStack.EMPTY && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FEATHER_FALLING, bootsItem) >= (int) entity.fallDistance) { + return; + } + } @@ -15441,7 +15404,7 @@ index 1fdede769b67cb5d2f9159c779f19e3639bb6ff5..2ff5457300d66378dbbea492deff0136 if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { return; } -@@ -177,7 +198,7 @@ public class FarmBlock extends Block { +@@ -177,7 +199,7 @@ public class FarmBlock extends Block { } } @@ -15451,15 +15414,15 @@ index 1fdede769b67cb5d2f9159c779f19e3639bb6ff5..2ff5457300d66378dbbea492deff0136 } diff --git a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java -index 0994f7265322d1f33365a1df0faaffd9df05fcc0..5dc1883ecd6e52666f553f30c150843c99fbef08 100644 +index fe11f3ec82ebdbdf3d024d7273fb16b6823b1ece..05a25847d0f32e3bb9679263b3090458cadd5756 100644 --- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java @@ -34,12 +34,12 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements @Override public BlockState getStateForPlacement(RandomSource random) { -- return this.defaultBlockState().setValue(AGE, Integer.valueOf(random.nextInt(25))); -+ return this.defaultBlockState().setValue(AGE, Integer.valueOf(random.nextInt(getMaxGrowthAge()))); // Purpur - kelp, cave, weeping, and twisting configurable max growth age +- return this.defaultBlockState().setValue(AGE, random.nextInt(25)); ++ return this.defaultBlockState().setValue(AGE, random.nextInt(getMaxGrowthAge())); // Purpur - kelp, cave, weeping, and twisting configurable max growth age } @Override @@ -15482,8 +15445,8 @@ index 0994f7265322d1f33365a1df0faaffd9df05fcc0..5dc1883ecd6e52666f553f30c150843c } public BlockState getMaxAgeState(BlockState state) { -- return state.setValue(AGE, Integer.valueOf(25)); -+ return state.setValue(AGE, Integer.valueOf(getMaxGrowthAge())); // Purpur - kelp, cave, weeping, and twisting configurable max growth age +- return state.setValue(AGE, 25); ++ return state.setValue(AGE, getMaxGrowthAge()); // Purpur - kelp, cave, weeping, and twisting configurable max growth age } public boolean isMaxAge(BlockState state) { @@ -15492,7 +15455,7 @@ index 0994f7265322d1f33365a1df0faaffd9df05fcc0..5dc1883ecd6e52666f553f30c150843c } protected BlockState updateBodyAfterConvertedFromHead(BlockState head, BlockState body) { -@@ -130,13 +130,13 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements +@@ -137,13 +137,13 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements @Override public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { BlockPos blockPos = pos.relative(this.growthDirection); @@ -15501,14 +15464,14 @@ index 0994f7265322d1f33365a1df0faaffd9df05fcc0..5dc1883ecd6e52666f553f30c150843c int blocksToGrowWhenBonemealed = this.getBlocksToGrowWhenBonemealed(random); for (int i = 0; i < blocksToGrowWhenBonemealed && this.canGrowInto(level.getBlockState(blockPos)); i++) { - level.setBlockAndUpdate(blockPos, state.setValue(AGE, Integer.valueOf(min))); + level.setBlockAndUpdate(blockPos, state.setValue(AGE, min)); blockPos = blockPos.relative(this.growthDirection); - min = Math.min(min + 1, 25); + min = Math.min(min + 1, getMaxGrowthAge()); // Purpur - kelp, cave, weeping, and twisting configurable max growth age } } -@@ -148,4 +148,6 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements +@@ -155,4 +155,6 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements protected GrowingPlantHeadBlock getHeadBlock() { return this; } @@ -15516,13 +15479,13 @@ index 0994f7265322d1f33365a1df0faaffd9df05fcc0..5dc1883ecd6e52666f553f30c150843c + public abstract int getMaxGrowthAge(); // Purpur - kelp, cave, weeping, and twisting configurable max growth age } diff --git a/net/minecraft/world/level/block/HayBlock.java b/net/minecraft/world/level/block/HayBlock.java -index 3d2ced08c1d40a558e82346672eaee9bf1315971..406e94e4a88921900f59a3a1b65e74a6482c3b8f 100644 +index cdde0a25e0a499d7575c00796143a033feb1f22f..999ecf16180b0a862cf8527ce532acf725ba869a 100644 --- a/net/minecraft/world/level/block/HayBlock.java +++ b/net/minecraft/world/level/block/HayBlock.java @@ -23,6 +23,6 @@ public class HayBlock extends RotatedPillarBlock { @Override - public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { + public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) { - entity.causeFallDamage(fallDistance, 0.2F, level.damageSources().fall()); + super.fallOn(level, state, pos, entity, fallDistance); // Purpur - Configurable block fall damage modifiers } @@ -15550,7 +15513,7 @@ index be7141a4009036bcf3f92bba5d0ad74459e99bfa..a4d735a4365fdaf9e602315aa1176dfd } else { level.setBlockAndUpdate(pos, meltsInto()); diff --git a/net/minecraft/world/level/block/KelpBlock.java b/net/minecraft/world/level/block/KelpBlock.java -index 72fc688eba837246ae9eb89ce3fa8e621774c37c..af4532f50eacb32a3ae1fc62ea6d564c127d8691 100644 +index 8e3f2518e705a4b8988a1c9da730f0c89f21bdce..6e6212fd891dcaea0d0a398a73416f31d2cb2406 100644 --- a/net/minecraft/world/level/block/KelpBlock.java +++ b/net/minecraft/world/level/block/KelpBlock.java @@ -72,4 +72,11 @@ public class KelpBlock extends GrowingPlantHeadBlock implements LiquidBlockConta @@ -15566,7 +15529,7 @@ index 72fc688eba837246ae9eb89ce3fa8e621774c37c..af4532f50eacb32a3ae1fc62ea6d564c + // Purpur end - kelp vines configurable max growth age } diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java -index 19d1906e9d4e92ff49a833bca03a7308ee8059e3..47a7ce88bf4d26408545dcc061aa763311af0dc9 100644 +index 7320b416e8d660419018b0699f49ab6f45a3373b..ae609e0603a78423c4c89b7efb9c41ab8fe7aa52 100644 --- a/net/minecraft/world/level/block/LiquidBlock.java +++ b/net/minecraft/world/level/block/LiquidBlock.java @@ -134,7 +134,7 @@ public class LiquidBlock extends Block implements BucketPickup { @@ -15610,20 +15573,20 @@ index db83c3630064a6875b477021a1f78bdf59c4ddc3..bbf8447cf986015f8a2e55f39d7b4f0d } diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java -index e2eb693b0130513115392cb0cb5a829ede5be8c5..eb659209008209c0930770e5f9671a3d7a4abae6 100644 +index 2f08780430fc643991ffb4aeba1f1ae8e78944d2..1c58af94050b75cd8f405a201448c822792e594a 100644 --- a/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/net/minecraft/world/level/block/NetherPortalBlock.java @@ -72,7 +72,7 @@ public class NetherPortalBlock extends Block implements Portal { protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (level.spigotConfig.enableZombiePigmenPortalSpawns && level.dimensionType().natural() // Spigot && level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) -- && random.nextInt(2000) < level.getDifficulty().getId()) { -+ && random.nextInt(level.purpurConfig.piglinPortalSpawnModifier) < level.getDifficulty().getId()) { // Purpur - Piglin portal spawn modifier +- && random.nextInt(2000) < level.getDifficulty().getId() ++ && random.nextInt(level.purpurConfig.piglinPortalSpawnModifier) < level.getDifficulty().getId() // Purpur - Piglin portal spawn modifier + && level.anyPlayerCloseEnoughForSpawning(pos)) { while (level.getBlockState(pos).is(this)) { pos = pos.below(); - } -@@ -117,6 +117,13 @@ public class NetherPortalBlock extends Block implements Portal { - protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +@@ -118,6 +118,13 @@ public class NetherPortalBlock extends Block implements Portal { + protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent if (entity.canUsePortal(false)) { + // Purpur start - Add EntityTeleportHinderedEvent @@ -15634,9 +15597,9 @@ index e2eb693b0130513115392cb0cb5a829ede5be8c5..eb659209008209c0930770e5f9671a3d + } + // Purpur end - Add EntityTeleportHinderedEvent // CraftBukkit start - Entity in portal - org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type + org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.NETHER); // Paper - add portal type level.getCraftServer().getPluginManager().callEvent(event); -@@ -129,7 +136,7 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -130,7 +137,7 @@ public class NetherPortalBlock extends Block implements Portal { @Override public int getPortalTransitionTime(ServerLevel level, Entity entity) { return entity instanceof Player player @@ -15646,19 +15609,19 @@ index e2eb693b0130513115392cb0cb5a829ede5be8c5..eb659209008209c0930770e5f9671a3d level.getGameRules() .getInt( diff --git a/net/minecraft/world/level/block/NetherWartBlock.java b/net/minecraft/world/level/block/NetherWartBlock.java -index 52891ddc14ad0e6f46a2f13d044723de9960b42d..4232fda95390be9faa9af6fa21e94deefe05ee69 100644 +index a8cb58de6223006150bc49b95e5964b8fc42cecc..d25e2a37abb5e4c98116048fe2e96194149763ca 100644 --- a/net/minecraft/world/level/block/NetherWartBlock.java +++ b/net/minecraft/world/level/block/NetherWartBlock.java @@ -16,7 +16,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; --public class NetherWartBlock extends BushBlock { -+public class NetherWartBlock extends BushBlock implements BonemealableBlock { // Purpur - bonemealable netherwart +-public class NetherWartBlock extends VegetationBlock { ++public class NetherWartBlock extends VegetationBlock implements BonemealableBlock { // Purpur - bonemealable netherwart public static final MapCodec CODEC = simpleCodec(NetherWartBlock::new); public static final int MAX_AGE = 3; public static final IntegerProperty AGE = BlockStateProperties.AGE_3; -@@ -70,4 +70,34 @@ public class NetherWartBlock extends BushBlock { +@@ -65,4 +65,34 @@ public class NetherWartBlock extends VegetationBlock { protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(AGE); } @@ -15694,10 +15657,10 @@ index 52891ddc14ad0e6f46a2f13d044723de9960b42d..4232fda95390be9faa9af6fa21e94dee + // Purpur end - bonemealable netherwart } diff --git a/net/minecraft/world/level/block/NoteBlock.java b/net/minecraft/world/level/block/NoteBlock.java -index 32d83e3ceceba37a8f76b1cd3591e8afed685141..62db23309d722868e406a52b8e67c23273e36c96 100644 +index 9467d5226797f67565edf8a46fd5b48135337410..7560d49b1952dba22e88758b15a24540ca576bbb 100644 --- a/net/minecraft/world/level/block/NoteBlock.java +++ b/net/minecraft/world/level/block/NoteBlock.java -@@ -107,7 +107,7 @@ public class NoteBlock extends Block { +@@ -101,7 +101,7 @@ public class NoteBlock extends Block { } private void playNote(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { @@ -15707,7 +15670,7 @@ index 32d83e3ceceba37a8f76b1cd3591e8afed685141..62db23309d722868e406a52b8e67c232 level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos); } diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java -index 9ca4ae8cdf9d88b8b6a6ed5d4c0b306bd0539ffe..42c696aa307516642029646305a4f71a93a56628 100644 +index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..9fa1ed439ef9adba44f3d4738688a95fb4625b68 100644 --- a/net/minecraft/world/level/block/ObserverBlock.java +++ b/net/minecraft/world/level/block/ObserverBlock.java @@ -81,6 +81,7 @@ public class ObserverBlock extends DirectionalBlock { @@ -15719,10 +15682,10 @@ index 9ca4ae8cdf9d88b8b6a6ed5d4c0b306bd0539ffe..42c696aa307516642029646305a4f71a } diff --git a/net/minecraft/world/level/block/PointedDripstoneBlock.java b/net/minecraft/world/level/block/PointedDripstoneBlock.java -index 6a3548ee9f7d31e1fb02a47f4d8b9c1ed0bc2bc6..aa1fd38f26459944f0a08d88e68b989cb54728ed 100644 +index ef164fb4f24412e506b8abce74d509e8be6c4676..85e9aecc2045e1599488d6a137f5f9713fb1a245 100644 --- a/net/minecraft/world/level/block/PointedDripstoneBlock.java +++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java -@@ -197,20 +197,20 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate +@@ -193,20 +193,20 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate @VisibleForTesting public static void maybeTransferFluid(BlockState state, ServerLevel level, BlockPos pos, float randChance) { @@ -15747,23 +15710,23 @@ index 6a3548ee9f7d31e1fb02a47f4d8b9c1ed0bc2bc6..aa1fd38f26459944f0a08d88e68b989c if (!(randChance >= f)) { diff --git a/net/minecraft/world/level/block/PowderSnowBlock.java b/net/minecraft/world/level/block/PowderSnowBlock.java -index 9c0ded7ae7e3a520704033a866f80743ae85d772..4f3646961beb877520e257e11224c3045467d351 100644 +index 248ac9bc820a96fc7653471308b18834fc735a77..5c6ebde129289f2f7feb44dc1083aa030f55fbff 100644 --- a/net/minecraft/world/level/block/PowderSnowBlock.java +++ b/net/minecraft/world/level/block/PowderSnowBlock.java -@@ -84,7 +84,7 @@ public class PowderSnowBlock extends Block implements BucketPickup { - // CraftBukkit - move down - && entity.mayInteract(serverLevel, pos)) { - // CraftBukkit start -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.purpurConfig.powderSnowBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { - return; - } - // CraftBukkit end +@@ -89,7 +89,7 @@ public class PowderSnowBlock extends Block implements BucketPickup { + // CraftBukkit - move down + && entity1.mayInteract(serverLevel, blockPos)) { + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity1, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity1 instanceof Player))) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity1, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.purpurConfig.powderSnowBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity1 instanceof Player))) { // Purpur - Add mobGriefing bypass to everything affected + return; + } + // CraftBukkit end diff --git a/net/minecraft/world/level/block/PoweredRailBlock.java b/net/minecraft/world/level/block/PoweredRailBlock.java -index f33b53257a231dccf16740f1e78a3cdfa6e70726..4b3d00b085ea5d345b418815c9869f5f8c9fe558 100644 +index 5ec12356e9f044d99762bf64a6d3bf74856d97a6..e80069d27ff60e0967d9333e2a0d6c8bf2f20a16 100644 --- a/net/minecraft/world/level/block/PoweredRailBlock.java +++ b/net/minecraft/world/level/block/PoweredRailBlock.java -@@ -34,7 +34,7 @@ public class PoweredRailBlock extends BaseRailBlock { +@@ -28,7 +28,7 @@ public class PoweredRailBlock extends BaseRailBlock { } protected boolean findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean searchForward, int recursionCount) { @@ -15773,10 +15736,10 @@ index f33b53257a231dccf16740f1e78a3cdfa6e70726..4b3d00b085ea5d345b418815c9869f5f } else { int x = pos.getX(); diff --git a/net/minecraft/world/level/block/RespawnAnchorBlock.java b/net/minecraft/world/level/block/RespawnAnchorBlock.java -index f90d1b0a9e4b80a42f450ff49a46765da19ce562..0631e6f0c242a1fc1dfa606a4d60686c31c7eb13 100644 +index 5b9d67d671ea70d4a8920a7f190d240c920971ac..f0b4ea2065f98f5430bba89f1a86ea5e8791aa1f 100644 --- a/net/minecraft/world/level/block/RespawnAnchorBlock.java +++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java -@@ -159,7 +159,7 @@ public class RespawnAnchorBlock extends Block { +@@ -160,7 +160,7 @@ public class RespawnAnchorBlock extends Block { }; Vec3 center = pos2.getCenter(); level.explode( @@ -15786,23 +15749,23 @@ index f90d1b0a9e4b80a42f450ff49a46765da19ce562..0631e6f0c242a1fc1dfa606a4d60686c } diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java -index 3e7c0a4df225f727d927c7a0ddb47e3d898858c3..63ccc1719a89ee43fb53c712bcbaf5947b136621 100644 +index 757f8453e147875ab9f14d9726bb734ef27447c9..f8c9a6d7c9f1a9d2afd820244017a709db79e080 100644 --- a/net/minecraft/world/level/block/SculkShriekerBlock.java +++ b/net/minecraft/world/level/block/SculkShriekerBlock.java -@@ -134,7 +134,7 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo +@@ -118,7 +118,7 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo + @Nullable @Override public BlockState getStateForPlacement(BlockPlaceContext context) { - return this.defaultBlockState() -- .setValue(WATERLOGGED, Boolean.valueOf(context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER)); -+ .setValue(WATERLOGGED, Boolean.valueOf(context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER)).setValue(SculkShriekerBlock.CAN_SUMMON, context.getLevel().purpurConfig.sculkShriekerCanSummonDefault); // Purpur - Config for sculk shrieker can_summon state +- return this.defaultBlockState().setValue(WATERLOGGED, context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER); ++ return this.defaultBlockState().setValue(WATERLOGGED, context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER).setValue(SculkShriekerBlock.CAN_SUMMON, context.getLevel().purpurConfig.sculkShriekerCanSummonDefault); // Purpur - Config for sculk shrieker can_summon state } @Override diff --git a/net/minecraft/world/level/block/SlabBlock.java b/net/minecraft/world/level/block/SlabBlock.java -index f6e39b69c1cafd9a429386cfd374ee643d258e97..ad57109f2766f44e386cb77fdce53580505efe33 100644 +index a71d72147db9766fa16bdb6254d8eb6f2f7dba7b..66b9862563932faf0044810bde7bd3fb522c109b 100644 --- a/net/minecraft/world/level/block/SlabBlock.java +++ b/net/minecraft/world/level/block/SlabBlock.java -@@ -150,4 +150,25 @@ public class SlabBlock extends Block implements SimpleWaterloggedBlock { +@@ -144,4 +144,25 @@ public class SlabBlock extends Block implements SimpleWaterloggedBlock { return false; } } @@ -15829,10 +15792,10 @@ index f6e39b69c1cafd9a429386cfd374ee643d258e97..ad57109f2766f44e386cb77fdce53580 + // Purpur end - Break individual slabs when sneaking } diff --git a/net/minecraft/world/level/block/SnowLayerBlock.java b/net/minecraft/world/level/block/SnowLayerBlock.java -index dd2bd6afd5e97a9ff3d102546361fc2332525611..b53b210707e32509ee4b3bc8c026608f1beceb06 100644 +index 9131098e3ae4e6ffdf1491eb62537e385f75b6b2..ddedc08a96e500a390421d39be36590f37f49d24 100644 --- a/net/minecraft/world/level/block/SnowLayerBlock.java +++ b/net/minecraft/world/level/block/SnowLayerBlock.java -@@ -96,6 +96,7 @@ public class SnowLayerBlock extends Block { +@@ -76,6 +76,7 @@ public class SnowLayerBlock extends Block { @Override protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { BlockState blockState = level.getBlockState(pos.below()); @@ -15841,10 +15804,10 @@ index dd2bd6afd5e97a9ff3d102546361fc2332525611..b53b210707e32509ee4b3bc8c026608f && ( blockState.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) diff --git a/net/minecraft/world/level/block/SpawnerBlock.java b/net/minecraft/world/level/block/SpawnerBlock.java -index 635e2608f9148c27d5d632c1618826226eb1d879..1121843e9db120ef02818369a1fe5f487342a49b 100644 +index e8d7b6adbcb84e8d89067b54318e0feb3c3276a6..2c7881028e68179f4cdb5d4dcca0b92589b5af5b 100644 --- a/net/minecraft/world/level/block/SpawnerBlock.java +++ b/net/minecraft/world/level/block/SpawnerBlock.java -@@ -43,6 +43,57 @@ public class SpawnerBlock extends BaseEntityBlock { +@@ -38,6 +38,57 @@ public class SpawnerBlock extends BaseEntityBlock { ); } @@ -15873,10 +15836,10 @@ index 635e2608f9148c27d5d632c1618826226eb1d879..1121843e9db120ef02818369a1fe5f48 + item.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); + } + -+ List lore = level.purpurConfig.silkTouchSpawnerLore; ++ java.util.List lore = level.purpurConfig.silkTouchSpawnerLore; + if (lore != null && !lore.isEmpty()) { + -+ List loreComponentList = new java.util.ArrayList<>(); ++ java.util.List loreComponentList = new java.util.ArrayList<>(); + for (String line : lore) { + net.kyori.adventure.text.Component lineComponent = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(line, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName)); + if (line.startsWith("")) { @@ -15887,7 +15850,7 @@ index 635e2608f9148c27d5d632c1618826226eb1d879..1121843e9db120ef02818369a1fe5f48 + + item.set(net.minecraft.core.component.DataComponents.LORE, new net.minecraft.world.item.component.ItemLore(loreComponentList, loreComponentList)); + } -+ item.set(net.minecraft.core.component.DataComponents.HIDE_ADDITIONAL_TOOLTIP, net.minecraft.util.Unit.INSTANCE); ++ item.set(net.minecraft.core.component.DataComponents.TOOLTIP_DISPLAY, net.minecraft.world.item.component.TooltipDisplay.DEFAULT.withHidden(net.minecraft.core.component.DataComponents.BLOCK_ENTITY_DATA, true)); + } + popResource(level, pos, item); + } @@ -15902,7 +15865,7 @@ index 635e2608f9148c27d5d632c1618826226eb1d879..1121843e9db120ef02818369a1fe5f48 @Override protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { super.spawnAfterBreak(state, level, pos, stack, dropExperience); -@@ -51,6 +102,7 @@ public class SpawnerBlock extends BaseEntityBlock { +@@ -46,6 +97,7 @@ public class SpawnerBlock extends BaseEntityBlock { @Override public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { @@ -15911,7 +15874,7 @@ index 635e2608f9148c27d5d632c1618826226eb1d879..1121843e9db120ef02818369a1fe5f48 int i = 15 + level.random.nextInt(15) + level.random.nextInt(15); // this.popExperience(level, pos, i); diff --git a/net/minecraft/world/level/block/SpongeBlock.java b/net/minecraft/world/level/block/SpongeBlock.java -index 88e7320a48b08f052ae1cac914ebbcb905baf693..a20bf795d56a8b8aa1536eed887b57957952c714 100644 +index 5d1b8c55bffc42924c4a95b1b4bd2e1e0b064af3..69822d21d0e71f4b29349af0bee2d80fa0802a3b 100644 --- a/net/minecraft/world/level/block/SpongeBlock.java +++ b/net/minecraft/world/level/block/SpongeBlock.java @@ -53,8 +53,8 @@ public class SpongeBlock extends Block { @@ -15946,7 +15909,7 @@ index 88e7320a48b08f052ae1cac914ebbcb905baf693..a20bf795d56a8b8aa1536eed887b5795 if (!blockState.is(Blocks.KELP) && !blockState.is(Blocks.KELP_PLANT) diff --git a/net/minecraft/world/level/block/StonecutterBlock.java b/net/minecraft/world/level/block/StonecutterBlock.java -index 04706b35549d7d9c1684a106ab6bff6de8199bc9..9dc7c3d0d6f8bcbc670fe10e594fa9c5495cffab 100644 +index 6d1ab251e7d09ada7edcde7f52ca49ae5efe16b6..a58c94a40bad1d60b970b06decde9851692a8b63 100644 --- a/net/minecraft/world/level/block/StonecutterBlock.java +++ b/net/minecraft/world/level/block/StonecutterBlock.java @@ -93,4 +93,14 @@ public class StonecutterBlock extends Block { @@ -15965,7 +15928,7 @@ index 04706b35549d7d9c1684a106ab6bff6de8199bc9..9dc7c3d0d6f8bcbc670fe10e594fa9c5 + // Purpur end - Stonecutter damage } diff --git a/net/minecraft/world/level/block/SugarCaneBlock.java b/net/minecraft/world/level/block/SugarCaneBlock.java -index 63d53f9090caca304c7f8c3f9910c57a6bdbb4d5..5a61216cea641f75fd1937d485651f6b6e4b6384 100644 +index a8de37e173e244d7a16c19ac8805e0e4327c837a..baa56c6422c0924bb8b7c5a78db17acf784f28d6 100644 --- a/net/minecraft/world/level/block/SugarCaneBlock.java +++ b/net/minecraft/world/level/block/SugarCaneBlock.java @@ -19,7 +19,7 @@ import net.minecraft.world.level.material.FluidState; @@ -15976,8 +15939,8 @@ index 63d53f9090caca304c7f8c3f9910c57a6bdbb4d5..5a61216cea641f75fd1937d485651f6b +public class SugarCaneBlock extends Block implements BonemealableBlock { // Purpur - bonemealable sugarcane public static final MapCodec CODEC = simpleCodec(SugarCaneBlock::new); public static final IntegerProperty AGE = BlockStateProperties.AGE_15; - protected static final float AABB_OFFSET = 6.0F; -@@ -113,4 +113,34 @@ public class SugarCaneBlock extends Block { + private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 16.0); +@@ -112,4 +112,34 @@ public class SugarCaneBlock extends Block { protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(AGE); } @@ -16013,10 +15976,10 @@ index 63d53f9090caca304c7f8c3f9910c57a6bdbb4d5..5a61216cea641f75fd1937d485651f6b + // Purpur end - bonemealable sugarcane } diff --git a/net/minecraft/world/level/block/TurtleEggBlock.java b/net/minecraft/world/level/block/TurtleEggBlock.java -index 8a09af26bbccdecd19607da84c11029c3cb9a11e..a3a093d95306baac22e5cf720f5b14f733b548d4 100644 +index 8ee103e2752290db4cb4b22bb3552bf80e2ceb92..bb3bba0d0bf89e82b929fe95247f50ccba964c02 100644 --- a/net/minecraft/world/level/block/TurtleEggBlock.java +++ b/net/minecraft/world/level/block/TurtleEggBlock.java -@@ -157,7 +157,7 @@ public class TurtleEggBlock extends Block { +@@ -156,7 +156,7 @@ public class TurtleEggBlock extends Block { private boolean shouldUpdateHatchLevel(Level level) { float timeOfDay = level.getTimeOfDay(1.0F); @@ -16025,7 +15988,7 @@ index 8a09af26bbccdecd19607da84c11029c3cb9a11e..a3a093d95306baac22e5cf720f5b14f7 } @Override -@@ -192,9 +192,31 @@ public class TurtleEggBlock extends Block { +@@ -189,9 +189,32 @@ public class TurtleEggBlock extends Block { } private boolean canDestroyEgg(ServerLevel level, Entity entity) { @@ -16051,8 +16014,9 @@ index 8a09af26bbccdecd19607da84c11029c3cb9a11e..a3a093d95306baac22e5cf720f5b14f7 + } + // Purpur start - Option to disable turtle egg trampling with feather falling + if (level.purpurConfig.turtleEggsTramplingFeatherFalling) { -+ java.util.Iterator armor = ((LivingEntity) entity).getArmorSlots().iterator(); -+ return !armor.hasNext() || net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FEATHER_FALLING, armor.next()) < (int) entity.fallDistance; ++ net.minecraft.world.item.ItemStack bootsItem = ((net.minecraft.world.entity.LivingEntity) entity).getItemBySlot(net.minecraft.world.entity.EquipmentSlot.FEET); ++ ++ return bootsItem != net.minecraft.world.item.ItemStack.EMPTY || net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FEATHER_FALLING, bootsItem) < (int) entity.fallDistance; + } + // Purpur end - Option to disable turtle egg trampling with feather falling + if (entity instanceof Player) return true; @@ -16062,7 +16026,7 @@ index 8a09af26bbccdecd19607da84c11029c3cb9a11e..a3a093d95306baac22e5cf720f5b14f7 } } diff --git a/net/minecraft/world/level/block/TwistingVinesBlock.java b/net/minecraft/world/level/block/TwistingVinesBlock.java -index 138832bb247f263aa393e9c3d9b5e9c79743c24c..3f7b0e488fd259badced8a2b4b09b4930b3d9573 100644 +index afb77747ea6966c435aca4b667bfbbc909f52232..361aaca76ae0375782310af0e03241625f08f7bd 100644 --- a/net/minecraft/world/level/block/TwistingVinesBlock.java +++ b/net/minecraft/world/level/block/TwistingVinesBlock.java @@ -34,4 +34,11 @@ public class TwistingVinesBlock extends GrowingPlantHeadBlock { @@ -16077,8 +16041,37 @@ index 138832bb247f263aa393e9c3d9b5e9c79743c24c..3f7b0e488fd259badced8a2b4b09b493 + } + // Purpur end - twisting vines configurable max growth age } +diff --git a/net/minecraft/world/level/block/VegetationBlock.java b/net/minecraft/world/level/block/VegetationBlock.java +index 0aa7c1084fd6ed35260469572cdd914d87f3922a..a1b5e815425fccbc601c8062fcc24598512e47dd 100644 +--- a/net/minecraft/world/level/block/VegetationBlock.java ++++ b/net/minecraft/world/level/block/VegetationBlock.java +@@ -61,4 +61,24 @@ public abstract class VegetationBlock extends Block { + protected boolean isPathfindable(BlockState state, PathComputationType pathComputationType) { + return pathComputationType == PathComputationType.AIR && !this.hasCollision || super.isPathfindable(state, pathComputationType); + } ++ ++ // Purpur start - Ability for hoe to replant crops ++ public void playerDestroyAndReplant(net.minecraft.world.level.Level world, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @javax.annotation.Nullable net.minecraft.world.level.block.entity.BlockEntity blockEntity, net.minecraft.world.item.ItemStack itemInHand, net.minecraft.world.level.ItemLike itemToReplant) { ++ player.awardStat(net.minecraft.stats.Stats.BLOCK_MINED.get(this)); ++ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); ++ java.util.List dropList = Block.getDrops(state, (net.minecraft.server.level.ServerLevel) world, pos, blockEntity, player, itemInHand); ++ ++ boolean planted = false; ++ for (net.minecraft.world.item.ItemStack itemToDrop : dropList) { ++ if (!planted && itemToDrop.getItem() == itemToReplant) { ++ world.setBlock(pos, defaultBlockState(), 3); ++ itemToDrop.setCount(itemToDrop.getCount() - 1); ++ planted = true; ++ } ++ Block.popResource(world, pos, itemToDrop); ++ } ++ ++ state.spawnAfterBreak((net.minecraft.server.level.ServerLevel) world, pos, itemInHand, true); ++ } ++ // Purpur end - Ability for hoe to replant crops + } diff --git a/net/minecraft/world/level/block/WeepingVinesBlock.java b/net/minecraft/world/level/block/WeepingVinesBlock.java -index 9d7fa63a699e7042118b29b154c62f406b51861a..92763699d12118ab0a304afbd564fd1c954ee749 100644 +index f4ff810cdd4206711312a4fffba18f4b30a5701f..96fb69aaf9ed020a328ff609d49f88ab29a69952 100644 --- a/net/minecraft/world/level/block/WeepingVinesBlock.java +++ b/net/minecraft/world/level/block/WeepingVinesBlock.java @@ -34,4 +34,11 @@ public class WeepingVinesBlock extends GrowingPlantHeadBlock { @@ -16094,7 +16087,7 @@ index 9d7fa63a699e7042118b29b154c62f406b51861a..92763699d12118ab0a304afbd564fd1c + // Purpur end - weeping vines configurable max growth age } diff --git a/net/minecraft/world/level/block/WitherSkullBlock.java b/net/minecraft/world/level/block/WitherSkullBlock.java -index dc70aaa8d929c40c5f34c8facc1ad2bff4e98768..31d776ce04a8035977ad82527e90ab3b215940c1 100644 +index 0b6debe0e55e404e6f34b3bc437fe7c7a30cec7c..a70f552fddc58efdce770c36abb548ef8359d939 100644 --- a/net/minecraft/world/level/block/WitherSkullBlock.java +++ b/net/minecraft/world/level/block/WitherSkullBlock.java @@ -71,6 +71,7 @@ public class WitherSkullBlock extends SkullBlock { @@ -16106,10 +16099,10 @@ index dc70aaa8d929c40c5f34c8facc1ad2bff4e98768..31d776ce04a8035977ad82527e90ab3b if (!level.addFreshEntity(witherBoss, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_WITHER)) { return; diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index ad9f009dd6c86e08c193839479b4b3285afd7dfb..901201c36c6dcd35e32e1da524a06d41e34da11f 100644 +index f6c3dac2a2a17760ab7015fe75c5a4dd04c11319..7185a084720a8b2d521227bb0e9bbf9758dec628 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -191,6 +191,21 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -186,6 +186,21 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } ItemStack itemStack = furnace.items.get(1); @@ -16131,7 +16124,7 @@ index ad9f009dd6c86e08c193839479b4b3285afd7dfb..901201c36c6dcd35e32e1da524a06d41 ItemStack itemStack1 = furnace.items.get(0); boolean flag1 = !itemStack1.isEmpty(); boolean flag2 = !itemStack.isEmpty(); -@@ -274,6 +289,8 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -269,6 +284,8 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit if (flag) { setChanged(level, pos, state); } @@ -16141,13 +16134,13 @@ index ad9f009dd6c86e08c193839479b4b3285afd7dfb..901201c36c6dcd35e32e1da524a06d41 private static boolean canBurn( diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index 0f808855f58281578c2758513787f0f7330c9291..9f6063089f0aa3a68d26ae7cfe39379123ab2f47 100644 +index 027502d0af5512c31878978c4d05c52fa3029cca..f5216355ef13593bc7333d50a003012e25b3d7ea 100644 --- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -@@ -55,7 +55,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { - this.maxStack = i; +@@ -56,7 +56,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { } // CraftBukkit end + - private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); + // Purpur start - Barrels and enderchests 6 rows + private NonNullList items = NonNullList.withSize(switch (org.purpurmc.purpur.PurpurConfig.barrelRows) { @@ -16163,7 +16156,7 @@ index 0f808855f58281578c2758513787f0f7330c9291..9f6063089f0aa3a68d26ae7cfe393791 public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { @Override protected void onOpen(Level level, BlockPos pos, BlockState state) { -@@ -107,7 +117,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -108,7 +118,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @Override public int getContainerSize() { @@ -16181,7 +16174,7 @@ index 0f808855f58281578c2758513787f0f7330c9291..9f6063089f0aa3a68d26ae7cfe393791 } @Override -@@ -127,7 +146,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -128,7 +147,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @Override protected AbstractContainerMenu createMenu(int id, Inventory player) { @@ -16200,10 +16193,10 @@ index 0f808855f58281578c2758513787f0f7330c9291..9f6063089f0aa3a68d26ae7cfe393791 @Override diff --git a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index deef33d96db188cb297f04b581ab29e77e3716a9..80b0feac68813f11dc5cadc5faf413a59ad73e5b 100644 +index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bc7b9d6faded66e95c38cfc5571b09c05af30deb 100644 --- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -139,6 +139,16 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -142,6 +142,16 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name public double getEffectRange() { if (this.effectRange < 0) { @@ -16220,7 +16213,7 @@ index deef33d96db188cb297f04b581ab29e77e3716a9..80b0feac68813f11dc5cadc5faf413a5 return this.levels * 10 + 10; } else { return effectRange; -@@ -168,6 +178,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -171,6 +181,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name int y = pos.getY(); int z = pos.getZ(); BlockPos blockPos; @@ -16228,15 +16221,15 @@ index deef33d96db188cb297f04b581ab29e77e3716a9..80b0feac68813f11dc5cadc5faf413a5 if (blockEntity.lastCheckY < y) { blockPos = pos; blockEntity.checkingBeamSections = Lists.newArrayList(); -@@ -197,6 +208,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -200,6 +211,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name } } } else { + if (level.purpurConfig.beaconAllowEffectsWithTintedGlass && blockState.getBlock().equals(Blocks.TINTED_GLASS)) {isTintedGlass = true;} // Purpur - allow beacon effects when covered by tinted glass - if (beaconBeamSection == null || blockState.getLightBlock() >= 15 && !blockState.is(Blocks.BEDROCK)) { + if (section == null || blockState.getLightBlock() >= 15 && !blockState.is(Blocks.BEDROCK)) { blockEntity.checkingBeamSections.clear(); blockEntity.lastCheckY = height; -@@ -216,7 +228,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -219,7 +231,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name blockEntity.levels = updateBase(level, x, y, z); } @@ -16246,10 +16239,10 @@ index deef33d96db188cb297f04b581ab29e77e3716a9..80b0feac68813f11dc5cadc5faf413a5 playSound(level, pos, SoundEvents.BEACON_AMBIENT); } diff --git a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index fbde2680b405b9fa7ed2fe70046b77e971b53e48..91d135e6b8cd0bbe0ffa6242d36c2d95e8f3fbab 100644 +index 331eb5416307378162e39e20192ba06a047b70ea..129e63c18e8c641ad2413111632c8a54b1385d1d 100644 --- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -76,7 +76,7 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -72,7 +72,7 @@ public class BeehiveBlockEntity extends BlockEntity { "leash", "UUID" ); @@ -16258,7 +16251,7 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..91d135e6b8cd0bbe0ffa6242d36c2d95 private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400; private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400; public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600; -@@ -154,11 +154,33 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -147,11 +147,33 @@ public class BeehiveBlockEntity extends BlockEntity { return list; } @@ -16292,7 +16285,7 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..91d135e6b8cd0bbe0ffa6242d36c2d95 // Paper start - Add EntityBlockStorage clearEntities public void clearBees() { this.stored.clear(); -@@ -408,8 +430,8 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -389,8 +411,8 @@ public class BeehiveBlockEntity extends BlockEntity { return this.stored.stream().map(BeehiveBlockEntity.BeeData::toOccupant).toList(); } @@ -16304,44 +16297,38 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..91d135e6b8cd0bbe0ffa6242d36c2d95 private int ticksInHive; diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java -index 77618757c0e678532dbab814aceed83f7f1cd892..3fd0f42618e5c2c683335d1d3e0bb74c6d32ef66 100644 +index a1075c26d55cc01219acd94d0138f81aa9d34c48..d7a08a4ecac2bb4f5626fb53e27f8d50b6936f1c 100644 --- a/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -84,6 +84,14 @@ public abstract class BlockEntity { +@@ -105,6 +105,10 @@ public abstract class BlockEntity { this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); } // Paper end - read persistent data container + -+ // Purpur start - Persistent BlockEntity Lore and DisplayName -+ if (tag.contains("Purpur.persistentLore")) { -+ net.minecraft.world.item.component.ItemLore.CODEC.decode(net.minecraft.nbt.NbtOps.INSTANCE, tag.getCompound("Purpur.persistentLore")).result() -+ .ifPresent(tag1 -> this.persistentLore = tag1.getFirst()); -+ } -+ // Purpur end - Persistent BlockEntity Lore and DisplayName ++ ++ this.persistentLore = tag.read("Purpur.persistentLore", net.minecraft.world.item.component.ItemLore.CODEC).orElse(null); // Purpur - Persistent BlockEntity Lore and DisplayName + } public final void loadWithComponents(CompoundTag tag, HolderLookup.Provider registries) { -@@ -98,6 +106,15 @@ public abstract class BlockEntity { - this.loadAdditional(tag, registries); +@@ -118,6 +122,12 @@ public abstract class BlockEntity { } -+ // Purpur start - Persistent BlockEntity Lore and DisplayName -+ protected void saveAdditional(CompoundTag nbt) { -+ if (this.persistentLore != null) { -+ net.minecraft.world.item.component.ItemLore.CODEC.encodeStart(net.minecraft.nbt.NbtOps.INSTANCE, this.persistentLore).result() -+ .ifPresent(tag -> nbt.put("Purpur.persistentLore", tag)); -+ } -+ } -+ // Purpur end - Persistent BlockEntity Lore and DisplayName -+ protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { ++ // Purpur start - Persistent BlockEntity Lore and DisplayName ++ if (this.persistentLore != null) { ++ net.minecraft.resources.RegistryOps registryOps = registries.createSerializationContext(NbtOps.INSTANCE); ++ tag.store("Purpur.persistentLore", net.minecraft.world.item.component.ItemLore.CODEC, registryOps, this.persistentLore); ++ } ++ // Purpur end - Persistent BlockEntity Lore and DisplayName } -@@ -378,4 +395,16 @@ public abstract class BlockEntity { - - T getOrDefault(DataComponentType component, T defaultValue); + public final CompoundTag saveWithFullMetadata(HolderLookup.Provider registries) { +@@ -379,4 +389,17 @@ public abstract class BlockEntity { + private ComponentHelper() { + } } ++ + // Purpur start - Persistent BlockEntity Lore and DisplayName + @Nullable + private net.minecraft.world.item.component.ItemLore persistentLore = null; @@ -16356,10 +16343,10 @@ index 77618757c0e678532dbab814aceed83f7f1cd892..3fd0f42618e5c2c683335d1d3e0bb74c + // Purpur end - Persistent BlockEntity Lore and DisplayName } diff --git a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -index 9d80625fc95e4968cf80492dc7ecf1fd27e585b8..00b2d069c6eb26742f0fd74ac1103e428873248a 100644 +index 2f07a23a6151a4dfb28ddc0ab38ec2abefcdd27c..aeb10f21cd9dab3b134d1d8478083453dc37e3f2 100644 --- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -@@ -155,7 +155,7 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -151,7 +151,7 @@ public class ConduitBlockEntity extends BlockEntity { BlockPos blockPos1 = pos.offset(i, i1, i2x); BlockState blockState = level.getBlockState(blockPos1); @@ -16368,7 +16355,7 @@ index 9d80625fc95e4968cf80492dc7ecf1fd27e585b8..00b2d069c6eb26742f0fd74ac1103e42 if (blockState.is(block)) { positions.add(blockPos1); } -@@ -170,13 +170,13 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -166,13 +166,13 @@ public class ConduitBlockEntity extends BlockEntity { private static void applyEffects(Level level, BlockPos pos, List positions) { // CraftBukkit start @@ -16385,7 +16372,7 @@ index 9d80625fc95e4968cf80492dc7ecf1fd27e585b8..00b2d069c6eb26742f0fd74ac1103e42 // CraftBukkit start return i; } -@@ -213,17 +213,17 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -209,17 +209,17 @@ public class ConduitBlockEntity extends BlockEntity { blockEntity.destroyTargetUUID = null; } else if (blockEntity.destroyTarget == null) { List entitiesOfClass = level.getEntitiesOfClass( @@ -16406,7 +16393,7 @@ index 9d80625fc95e4968cf80492dc7ecf1fd27e585b8..00b2d069c6eb26742f0fd74ac1103e42 level.playSound( null, blockEntity.destroyTarget.getX(), -@@ -253,16 +253,22 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -249,16 +249,22 @@ public class ConduitBlockEntity extends BlockEntity { } public static AABB getDestroyRangeAABB(BlockPos pos) { @@ -16432,10 +16419,10 @@ index 9d80625fc95e4968cf80492dc7ecf1fd27e585b8..00b2d069c6eb26742f0fd74ac1103e42 return entitiesOfClass.size() == 1 ? entitiesOfClass.get(0) : null; } diff --git a/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java b/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java -index 337bbef7e89a46bc4e7d6763db6d1e9ffe5a8c2e..5ced128ad3b9ce5e32a15fd996ef4bd07c72da97 100644 +index 4b2462ece4eb5abb76ea9259b3e6a77f8a8e4e07..d35d04823e5d0de4487310caadd013f7dab1f419 100644 --- a/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java +++ b/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java -@@ -28,6 +28,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable +@@ -31,6 +31,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable private static final RandomSource RANDOM = RandomSource.create(); @Nullable private Component name; @@ -16443,23 +16430,22 @@ index 337bbef7e89a46bc4e7d6763db6d1e9ffe5a8c2e..5ced128ad3b9ce5e32a15fd996ef4bd0 public EnchantingTableBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.ENCHANTING_TABLE, pos, state); -@@ -39,6 +40,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable +@@ -42,12 +43,14 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable if (this.hasCustomName()) { - tag.putString("CustomName", Component.Serializer.toJson(this.name, registries)); + tag.store("CustomName", ComponentSerialization.CODEC, registries.createSerializationContext(NbtOps.INSTANCE), this.name); } + tag.putInt("Purpur.Lapis", this.lapis); // Purpur - Enchantment Table Persists Lapis } @Override -@@ -47,6 +49,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable - if (tag.contains("CustomName", 8)) { - this.name = parseCustomNameSafe(tag.getString("CustomName"), registries); - } -+ this.lapis = tag.getInt("Purpur.Lapis"); // Purpur - Enchantment Table Persists Lapis + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + this.name = parseCustomNameSafe(tag.get("CustomName"), registries); ++ this.lapis = tag.getIntOr("Purpur.Lapis", 0); // Purpur - Enchantment Table Persists Lapis } public static void bookAnimationTick(Level level, BlockPos pos, BlockState state, EnchantingTableBlockEntity enchantingTable) { -@@ -138,4 +141,14 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable +@@ -139,4 +142,14 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable public void removeComponentsFromTag(CompoundTag tag) { tag.remove("CustomName"); } @@ -16475,10 +16461,10 @@ index 337bbef7e89a46bc4e7d6763db6d1e9ffe5a8c2e..5ced128ad3b9ce5e32a15fd996ef4bd0 + // Purpur end - Enchantment Table Persists Lapis } diff --git a/net/minecraft/world/level/block/entity/SignBlockEntity.java b/net/minecraft/world/level/block/entity/SignBlockEntity.java -index a1a537fc373b92b84f003844e3ea328bb91b9a4a..662f53ca5826fb5b68eb4d426f1d9c5d83906eaf 100644 +index 8f87248a77c2083541105cfd1da1bc87bd122ba4..c5184985867b40daf2d86ed8b354f8d0fc960329 100644 --- a/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -163,16 +163,32 @@ public class SignBlockEntity extends BlockEntity { +@@ -151,16 +151,32 @@ public class SignBlockEntity extends BlockEntity { return this.setText(updater.apply(text), isFrontText); } @@ -16513,7 +16499,7 @@ index a1a537fc373b92b84f003844e3ea328bb91b9a4a..662f53ca5826fb5b68eb4d426f1d9c5d ); } } -@@ -311,6 +327,28 @@ public class SignBlockEntity extends BlockEntity { +@@ -298,6 +314,26 @@ public class SignBlockEntity extends BlockEntity { return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player); // Paper - Fix commands from signs not firing command events } @@ -16528,10 +16514,8 @@ index a1a537fc373b92b84f003844e3ea328bb91b9a4a..662f53ca5826fb5b68eb4d426f1d9c5d + final String line = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(component); + final var text = net.kyori.adventure.text.Component.text(line); + final String json = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(text); -+ if (!nbt.contains(side)) nbt.put(side, new CompoundTag()); -+ final CompoundTag sideNbt = nbt.getCompound(side); -+ if (!sideNbt.contains("messages")) sideNbt.put("messages", new net.minecraft.nbt.ListTag()); -+ final net.minecraft.nbt.ListTag messagesNbt = sideNbt.getList("messages", Tag.TAG_STRING); ++ final CompoundTag sideNbt = nbt.getCompoundOrEmpty(side); ++ final net.minecraft.nbt.ListTag messagesNbt = sideNbt.getListOrEmpty("messages"); + messagesNbt.set(i, net.minecraft.nbt.StringTag.valueOf(json)); + } + nbt.putString("PurpurEditor", "true"); @@ -16574,10 +16558,10 @@ index ad143a92569f5b420ccaa2089758b2fb3b4ab7c5..5a3660e02bc805e9a35a81b8a61f07b3 } diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java -index 2856206eafddfcbcc1b65408deda40357f43a6f8..dee0c4ac773c47fb87258b6126854d802ab26db8 100644 +index f9fb1380be9cbe960127c208c65c19f770e50b6d..17315201b8d3546058e2440b8fb8a5bb465f1259 100644 --- a/net/minecraft/world/level/chunk/storage/EntityStorage.java +++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java -@@ -106,6 +106,7 @@ public class EntityStorage implements EntityPersistentStorage { +@@ -100,6 +100,7 @@ public class EntityStorage implements EntityPersistentStorage { } // Paper end - Entity load/save limit per chunk CompoundTag compoundTag1 = new CompoundTag(); @@ -16586,41 +16570,37 @@ index 2856206eafddfcbcc1b65408deda40357f43a6f8..dee0c4ac773c47fb87258b6126854d80 listTag.add(compoundTag1); } diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java -index c792483860d31ce663e7de34e9f79ff46de75b8c..b9fdd5518ee1fe743485abb3557a21101846041f 100644 +index 1ec7abf2c82a5371fe1dacd57d90386fdae67f56..d9fca70ff61f20401643fe95833d3f7fbf3117e0 100644 --- a/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java -@@ -43,7 +43,7 @@ public class PhantomSpawner implements CustomSpawner { - int spawnAttemptMaxSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds; - this.nextTick += (spawnAttemptMinSeconds + randomSource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20; - // Paper end - Ability to control player's insomnia and phantoms -- if (level.getSkyDarken() < 5 && level.dimensionType().hasSkyLight()) { -+ if (level.getSkyDarken() < level.purpurConfig.phantomSpawnMinSkyDarkness && level.dimensionType().hasSkyLight()) { // Purpur - Add phantom spawning options - return 0; - } else { - int i = 0; -@@ -51,9 +51,9 @@ public class PhantomSpawner implements CustomSpawner { - for (ServerPlayer serverPlayer : level.players()) { - if (!serverPlayer.isSpectator() && (!level.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !serverPlayer.isCreative())) { // Paper - Add phantom creative and insomniac controls - BlockPos blockPos = serverPlayer.blockPosition(); -- if (!level.dimensionType().hasSkyLight() || blockPos.getY() >= level.getSeaLevel() && level.canSeeSky(blockPos)) { -+ if (!level.dimensionType().hasSkyLight() || (!level.purpurConfig.phantomSpawnOnlyAboveSeaLevel || blockPos.getY() >= level.getSeaLevel()) && (!level.purpurConfig.phantomSpawnOnlyWithVisibleSky || level.canSeeSky(blockPos))) { // Purpur - Add phantom spawning options - DifficultyInstance currentDifficultyAt = level.getCurrentDifficultyAt(blockPos); -- if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * 3.0F)) { -+ if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * (float) level.purpurConfig.phantomSpawnLocalDifficultyChance)) { // Purpur - Add phantom spawning options - ServerStatsCounter stats = serverPlayer.getStats(); - int i1 = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); - int i2 = 24000; -@@ -73,7 +73,7 @@ public class PhantomSpawner implements CustomSpawner { - FluidState fluidState = level.getFluidState(blockPos1); - if (NaturalSpawner.isValidEmptySpawnBlock(level, blockPos1, blockState, fluidState, EntityType.PHANTOM)) { - SpawnGroupData spawnGroupData = null; -- int i3 = 1 + randomSource.nextInt(currentDifficultyAt.getDifficulty().getId() + 1); -+ int i3 = level.purpurConfig.phantomSpawnMinPerAttempt + level.random.nextInt((level.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? currentDifficultyAt.getDifficulty().getId() : level.purpurConfig.phantomSpawnMaxPerAttempt - level.purpurConfig.phantomSpawnMinPerAttempt) + 1); // Purpur - Add phantom spawning options +@@ -38,13 +38,13 @@ public class PhantomSpawner implements CustomSpawner { + int spawnAttemptMaxSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds; + this.nextTick += (spawnAttemptMinSeconds + randomSource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20; + // Paper end - Ability to control player's insomnia and phantoms +- if (level.getSkyDarken() >= 5 || !level.dimensionType().hasSkyLight()) { ++ if (level.getSkyDarken() >= level.purpurConfig.phantomSpawnMinSkyDarkness || !level.dimensionType().hasSkyLight()) { // Purpur - Add phantom spawning options + for (ServerPlayer serverPlayer : level.players()) { + if (!serverPlayer.isSpectator() && (!level.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !serverPlayer.isCreative())) { // Paper - Add phantom creative and insomniac controls + BlockPos blockPos = serverPlayer.blockPosition(); +- if (!level.dimensionType().hasSkyLight() || blockPos.getY() >= level.getSeaLevel() && level.canSeeSky(blockPos)) { ++ if (!level.dimensionType().hasSkyLight() || (!level.purpurConfig.phantomSpawnOnlyAboveSeaLevel || blockPos.getY() >= level.getSeaLevel()) && (!level.purpurConfig.phantomSpawnOnlyWithVisibleSky || level.canSeeSky(blockPos))) { // Purpur - Add phantom spawning options + DifficultyInstance currentDifficultyAt = level.getCurrentDifficultyAt(blockPos); +- if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * 3.0F)) { ++ if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * (float) level.purpurConfig.phantomSpawnLocalDifficultyChance)) { // Purpur - Add phantom spawning options + ServerStatsCounter stats = serverPlayer.getStats(); + int i = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); + int i1 = 24000; +@@ -64,7 +64,7 @@ public class PhantomSpawner implements CustomSpawner { + FluidState fluidState = level.getFluidState(blockPos1); + if (NaturalSpawner.isValidEmptySpawnBlock(level, blockPos1, blockState, fluidState, EntityType.PHANTOM)) { + SpawnGroupData spawnGroupData = null; +- int i2 = 1 + randomSource.nextInt(currentDifficultyAt.getDifficulty().getId() + 1); ++ int i2 = level.purpurConfig.phantomSpawnMinPerAttempt + randomSource.nextInt((level.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? currentDifficultyAt.getDifficulty().getId() : level.purpurConfig.phantomSpawnMaxPerAttempt - level.purpurConfig.phantomSpawnMinPerAttempt) + 1); // Purpur - Add phantom spawning options - for (int i4 = 0; i4 < i3; i4++) { - // Paper start - PhantomPreSpawnEvent + for (int i3 = 0; i3 < i2; i3++) { + // Paper start - PhantomPreSpawnEvent diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java -index e9e93a6b0866c816609ff0620d242c31f064d18b..738defb8cbd9c63dc85c479911ebe2f795d0a815 100644 +index 91567d45fd809f2fee7ab9abbd27f43869b71016..2a2883b4c38b8ac6e014dab66da0c141f6ac2a64 100644 --- a/net/minecraft/world/level/material/FlowingFluid.java +++ b/net/minecraft/world/level/material/FlowingFluid.java @@ -232,7 +232,7 @@ public abstract class FlowingFluid extends Fluid { @@ -16646,10 +16626,10 @@ index e9e93a6b0866c816609ff0620d242c31f064d18b..738defb8cbd9c63dc85c479911ebe2f7 if (blockState.getBlock() instanceof LiquidBlockContainer liquidBlockContainer) { liquidBlockContainer.placeLiquid(level, pos, blockState, fluidState); diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java -index 6f135caffb7638c6156f00341aeac12b50cea99d..85629a43f5469a89dd6078d879f475e8212438ec 100644 +index 033f252248b671e35135269dd2df6e7ca4585604..43cdc2f8fdfdeb1426e386e0084087779ef62754 100644 --- a/net/minecraft/world/level/material/LavaFluid.java +++ b/net/minecraft/world/level/material/LavaFluid.java -@@ -177,7 +177,7 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -189,7 +189,7 @@ public abstract class LavaFluid extends FlowingFluid { @Override public int getTickDelay(LevelReader level) { @@ -16658,7 +16638,7 @@ index 6f135caffb7638c6156f00341aeac12b50cea99d..85629a43f5469a89dd6078d879f475e8 } @Override -@@ -199,6 +199,13 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -211,6 +211,13 @@ public abstract class LavaFluid extends FlowingFluid { level.levelEvent(1501, pos, 0); } @@ -16673,19 +16653,20 @@ index 6f135caffb7638c6156f00341aeac12b50cea99d..85629a43f5469a89dd6078d879f475e8 protected boolean canConvertToSource(ServerLevel level) { return level.getGameRules().getBoolean(GameRules.RULE_LAVA_SOURCE_CONVERSION); diff --git a/net/minecraft/world/level/material/WaterFluid.java b/net/minecraft/world/level/material/WaterFluid.java -index 56781b47aeddf0c84d64ddf8b1aad7b26730b68c..2e4fed7c27910b6c886f710f33b0841c2a175837 100644 +index 10e3c644e31650b0e1aad6349a83a763cf744ec8..b248fe1d66940c05d56fc322df61c52ece72e77f 100644 --- a/net/minecraft/world/level/material/WaterFluid.java +++ b/net/minecraft/world/level/material/WaterFluid.java -@@ -74,6 +74,12 @@ public abstract class WaterFluid extends FlowingFluid { - protected boolean canConvertToSource(ServerLevel level) { +@@ -78,6 +78,13 @@ public abstract class WaterFluid extends FlowingFluid { return level.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION); } + + // Purpur start - Implement infinite liquids + @Override + protected int getRequiredSources(Level level) { + return level.purpurConfig.waterInfiniteRequiredSources; + } + // Purpur end - Implement infinite liquids ++ // Paper start - Add BlockBreakBlockEvent @Override protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state, BlockPos source) { @@ -16712,7 +16693,7 @@ index 9e6b2bbc1f83d32d0332f036be4f1a0e18b826bf..db6baaa698fe93aba3fbd595158b568b } else if (blockState.is(Blocks.HONEY_BLOCK)) { return PathType.STICKY_HONEY; diff --git a/net/minecraft/world/level/portal/PortalShape.java b/net/minecraft/world/level/portal/PortalShape.java -index 710f4570bb45a25f20cf914c640539cfa9c9d31b..19ee66cc966cbd124d8c59bc55586237c2ca5deb 100644 +index b0a4511b7de2002257e81c52742faf0ec94cc688..c4b8725aa3177114bdcae25fca3c85aaf8277352 100644 --- a/net/minecraft/world/level/portal/PortalShape.java +++ b/net/minecraft/world/level/portal/PortalShape.java @@ -28,7 +28,7 @@ public class PortalShape { @@ -16725,10 +16706,10 @@ index 710f4570bb45a25f20cf914c640539cfa9c9d31b..19ee66cc966cbd124d8c59bc55586237 private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0; private final Direction.Axis axis; diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 3c1c89aade5ff092b880ba1bf1de83f54d3d62cc..681dec447486138088fe5f705ef4fadab531139f 100644 +index eb05d3974ad1e139600810c90f7ced34a2324537..3ae69b17fec1cdb2bee2b5a795026a875f197c30 100644 --- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -68,6 +68,7 @@ public class MapItemSavedData extends SavedData { +@@ -81,6 +81,7 @@ public class MapItemSavedData extends SavedData { public final Map decorations = Maps.newLinkedHashMap(); private final Map frameMarkers = Maps.newHashMap(); private int trackedDecorationCount; @@ -16737,7 +16718,7 @@ index 3c1c89aade5ff092b880ba1bf1de83f54d3d62cc..681dec447486138088fe5f705ef4fada // CraftBukkit start public final org.bukkit.craftbukkit.map.CraftMapView mapView; diff --git a/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java b/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java -index c3d3dd9d3be4b824ccfc114243812ef31b46f4dc..b7636b7dcd2cbec3f08029733bb03e4bd0282b9e 100644 +index c4f29da30d63deb3f9eabafcf62a946ff148b6b7..f3083702286dfb7932f08e0b811eded7988cbab4 100644 --- a/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java +++ b/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java @@ -66,6 +66,11 @@ public class EnchantedCountIncreaseFunction extends LootItemConditionalFunction @@ -16753,12 +16734,12 @@ index c3d3dd9d3be4b824ccfc114243812ef31b46f4dc..b7636b7dcd2cbec3f08029733bb03e4b return stack; } diff --git a/net/minecraft/world/phys/AABB.java b/net/minecraft/world/phys/AABB.java -index 85148858db1fd5e9da8bbdde4b0d84110d80e373..c9c6e4e460ad8435f12761704bb9b0284d6aa708 100644 +index c22acc8889fbb3c9ee698624189c195ee4b5eefb..5767fbfd7f33c5276fb4335ce473b2e1baca411c 100644 --- a/net/minecraft/world/phys/AABB.java +++ b/net/minecraft/world/phys/AABB.java -@@ -442,4 +442,10 @@ public class AABB { - center.x - xSize / 2.0, center.y - ySize / 2.0, center.z - zSize / 2.0, center.x + xSize / 2.0, center.y + ySize / 2.0, center.z + zSize / 2.0 - ); +@@ -465,4 +465,10 @@ public class AABB { + return new AABB(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); + } } + + // Purpur start - Stop squids floating on top of water - tuinity added method @@ -16769,7 +16750,7 @@ index 85148858db1fd5e9da8bbdde4b0d84110d80e373..c9c6e4e460ad8435f12761704bb9b028 } diff --git a/org/purpurmc/purpur/PurpurConfig.java b/org/purpurmc/purpur/PurpurConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..bbfd05509dfc2ee453f847d299b3d261324b6fa9 +index 0000000000000000000000000000000000000000..c03f80f20761384f08ab2c07d9999297c3c96a3b --- /dev/null +++ b/org/purpurmc/purpur/PurpurConfig.java @@ -0,0 +1,581 @@ @@ -16849,8 +16830,8 @@ index 0000000000000000000000000000000000000000..bbfd05509dfc2ee453f847d299b3d261 + commands = new HashMap<>(); + commands.put("purpur", new PurpurCommand("purpur")); + -+ version = getInt("config-version", 41); -+ set("config-version", 41); ++ version = getInt("config-version", 42); ++ set("config-version", 42); + + readConfig(PurpurConfig.class, null); + @@ -17356,10 +17337,10 @@ index 0000000000000000000000000000000000000000..bbfd05509dfc2ee453f847d299b3d261 +} diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..b3fca75c66b16e35f6841c3b7df9103d68f1308e +index 0000000000000000000000000000000000000000..ed5bbc49da258f8db249b1387f51ed1b22a29053 --- /dev/null +++ b/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -0,0 +1,3468 @@ +@@ -0,0 +1,3471 @@ +package org.purpurmc.purpur; + +import java.util.ArrayList; @@ -20759,7 +20740,7 @@ index 0000000000000000000000000000000000000000..b3fca75c66b16e35f6841c3b7df9103d + public boolean zombifiedPiglinJockeyOnlyBaby = true; + public double zombifiedPiglinJockeyChance = 0.05D; + public boolean zombifiedPiglinJockeyTryExistingChickens = true; -+ public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = true; ++ public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = false; + public boolean zombifiedPiglinTakeDamageFromWater = false; + public boolean zombifiedPiglinAlwaysDropExp = false; + private void zombifiedPiglinSettings() { @@ -20771,6 +20752,9 @@ index 0000000000000000000000000000000000000000..b3fca75c66b16e35f6841c3b7df9103d + set("mobs.zombified_piglin.attributes.max-health", null); + set("mobs.zombified_piglin.attributes.max_health", oldValue); + } ++ if (PurpurConfig.version < 42) { ++ set("mobs.zombified_piglin.count-as-player-kill-when-angry", false); ++ } + zombifiedPiglinMaxHealth = getDouble("mobs.zombified_piglin.attributes.max_health", zombifiedPiglinMaxHealth); + zombifiedPiglinScale = Mth.clamp(getDouble("mobs.zombified_piglin.attributes.scale", zombifiedPiglinScale), 0.0625D, 16.0D); + zombifiedPiglinSpawnReinforcements = getDouble("mobs.zombified_piglin.attributes.spawn_reinforcements", zombifiedPiglinSpawnReinforcements); @@ -21646,20 +21630,19 @@ index 0000000000000000000000000000000000000000..922e48799c43ca322a8f550c98a26e1e +} diff --git a/org/purpurmc/purpur/entity/PurpurStoredBee.java b/org/purpurmc/purpur/entity/PurpurStoredBee.java new file mode 100644 -index 0000000000000000000000000000000000000000..7608bf0981fa0d37031e51e57e4086cb5ec4c88b +index 0000000000000000000000000000000000000000..1cd79edbe87d9109bc132e64f6840981aaaab110 --- /dev/null +++ b/org/purpurmc/purpur/entity/PurpurStoredBee.java -@@ -0,0 +1,106 @@ +@@ -0,0 +1,104 @@ +package org.purpurmc.purpur.entity; + +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.Component; +import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.Tag; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.block.entity.BeehiveBlockEntity; ++import net.minecraft.world.level.block.entity.BlockEntity; +import org.bukkit.block.EntityBlockStorage; ++import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; +import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; +import org.bukkit.entity.Bee; @@ -21684,12 +21667,11 @@ index 0000000000000000000000000000000000000000..7608bf0981fa0d37031e51e57e4086cb + this.blockStorage = blockStorage; + + CompoundTag customData = handle.occupant.entityData().copyTag(); -+ this.customName = customData.contains("CustomName") -+ ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(customData.getString("CustomName"), MinecraftServer.getDefaultRegistryAccess())) -+ : null; ++ net.minecraft.network.chat.Component customNameMinecraft = BlockEntity.parseCustomNameSafe(customData.get("CustomName"), ((CraftWorld) blockStorage.getWorld()).getHandle().registryAccess()); ++ this.customName = customNameMinecraft == null ? null : PaperAdventure.asAdventure(customNameMinecraft); + -+ if(customData.contains("BukkitValues", Tag.TAG_COMPOUND)) { -+ this.persistentDataContainer.putAll(customData.getCompound("BukkitValues")); ++ if (customData.get("BukkitValues") instanceof CompoundTag compoundTag) { ++ this.persistentDataContainer.putAll(compoundTag); + } + } + @@ -21752,7 +21734,7 @@ index 0000000000000000000000000000000000000000..7608bf0981fa0d37031e51e57e4086cb + if(customName == null) { + handle.occupant.entityData().copyTag().remove("CustomName"); + } else { -+ handle.occupant.entityData().copyTag().putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName), MinecraftServer.getDefaultRegistryAccess())); ++ handle.occupant.entityData().copyTag().putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName), ((CraftWorld) blockStorage.getWorld()).getHandle().registryAccess())); + } + } +} @@ -22038,7 +22020,7 @@ index 0000000000000000000000000000000000000000..e489b16983b8eea75726baf6323b41af +} diff --git a/org/purpurmc/purpur/entity/projectile/PhantomFlames.java b/org/purpurmc/purpur/entity/projectile/PhantomFlames.java new file mode 100644 -index 0000000000000000000000000000000000000000..bac5eee2d101fa286285747170ba3365c47c87c3 +index 0000000000000000000000000000000000000000..b3fe215e163373641a11c0ab2f5fd5e666434055 --- /dev/null +++ b/org/purpurmc/purpur/entity/projectile/PhantomFlames.java @@ -0,0 +1,127 @@ @@ -22114,7 +22096,7 @@ index 0000000000000000000000000000000000000000..bac5eee2d101fa286285747170ba3365 + this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); + } else if (this.level().getBlockStates(this.getBoundingBox()).noneMatch(BlockBehaviour.BlockStateBase::isAir)) { + this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); -+ } else if (this.isInWaterOrBubble()) { ++ } else if (this.isInWater()) { + this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); + } else { + this.setDeltaMovement(mot.scale(0.99D)); @@ -22356,12 +22338,13 @@ index 0000000000000000000000000000000000000000..b257f35caa13b660854cf17f41fd8fba +} diff --git a/org/purpurmc/purpur/item/SpawnerItem.java b/org/purpurmc/purpur/item/SpawnerItem.java new file mode 100644 -index 0000000000000000000000000000000000000000..ed50cb2115401c9039df4136caf5a087a5f5991c +index 0000000000000000000000000000000000000000..f7de0c7d50382fb1a46534bfab91d70e309fa57d --- /dev/null +++ b/org/purpurmc/purpur/item/SpawnerItem.java -@@ -0,0 +1,40 @@ +@@ -0,0 +1,41 @@ +package org.purpurmc.purpur.item; + ++import java.util.Optional; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; @@ -22389,11 +22372,11 @@ index 0000000000000000000000000000000000000000..ed50cb2115401c9039df4136caf5a087 + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof SpawnerBlockEntity spawner) { + CompoundTag customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); -+ if (customData.contains("Purpur.mob_type")) { -+ EntityType.byString(customData.getString("Purpur.mob_type")).ifPresent(type -> spawner.getSpawner().setEntityId(type, level, level.random, pos)); ++ Optional mobTypeStringOptional = customData.getString("Purpur.mob_type"); ++ if (mobTypeStringOptional.isPresent()) { ++ EntityType.byString(mobTypeStringOptional.get()).ifPresent(type -> spawner.getSpawner().setEntityId(type, level, level.random, pos)); + } else if (customData.contains("Purpur.SpawnData")) { -+ net.minecraft.world.level.SpawnData.CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, customData.getCompound("Purpur.SpawnData")).result() -+ .ifPresent(spawnData -> spawner.getSpawner().nextSpawnData = spawnData); ++ customData.read("SpawnData", net.minecraft.world.level.SpawnData.CODEC).ifPresent(spawnData -> spawner.getSpawner().nextSpawnData = spawnData); + } + } + } diff --git a/leaf-server/minecraft-patches/features/0099-Purpur-Configurable-server-mod-name.patch b/leaf-server/minecraft-patches/features/0100-Purpur-Configurable-server-mod-name.patch similarity index 84% rename from leaf-server/minecraft-patches/features/0099-Purpur-Configurable-server-mod-name.patch rename to leaf-server/minecraft-patches/features/0100-Purpur-Configurable-server-mod-name.patch index 4e1670ca..2b3b190a 100644 --- a/leaf-server/minecraft-patches/features/0099-Purpur-Configurable-server-mod-name.patch +++ b/leaf-server/minecraft-patches/features/0100-Purpur-Configurable-server-mod-name.patch @@ -7,10 +7,10 @@ Original license: MIT Original project: https://github.com/PurpurMC/Purpur diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index af17193fde9d4c13e84fb7952521430299f2cfec..4b163dbc99cbfcef4d7bae97055af844e400d87a 100644 +index 91fa7f0bac5681413cd8d66fe1ebf2029713408f..626ce084ace620bd3883fb3f542b0bd77dfb5f8e 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1802,7 +1802,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 1.18.x that updated by Mojang. By removing this check, it gives ability for hackers to use some modules of hack clients. diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 7142de40a5ff9d1009bb06e73172877e8bf80962..6314831d7ecefa14be1386eced3ee50510ebe769 100644 +index 4b59db324e71846d233e43bafcdae658bcc70328..eba90724a6e5e8a93d775d3e0703a0b37a77e7e5 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1923,8 +1923,13 @@ public class ServerGamePacketListenerImpl +@@ -2003,8 +2003,13 @@ public class ServerGamePacketListenerImpl BlockPos blockPos = hitResult.getBlockPos(); if (this.player.canInteractWithBlock(blockPos, 1.0)) { Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos)); diff --git a/leaf-server/minecraft-patches/features/0104-Remove-change-non-editable-sign-warning.patch b/leaf-server/minecraft-patches/features/0105-Remove-change-non-editable-sign-warning.patch similarity index 93% rename from leaf-server/minecraft-patches/features/0104-Remove-change-non-editable-sign-warning.patch rename to leaf-server/minecraft-patches/features/0105-Remove-change-non-editable-sign-warning.patch index 502b6fe1..d47285c3 100644 --- a/leaf-server/minecraft-patches/features/0104-Remove-change-non-editable-sign-warning.patch +++ b/leaf-server/minecraft-patches/features/0105-Remove-change-non-editable-sign-warning.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Remove change non-editable sign warning diff --git a/net/minecraft/world/level/block/entity/SignBlockEntity.java b/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 8f87248a77c2083541105cfd1da1bc87bd122ba4..93a349efd64859b9183aa7054ddd48a0cb489a0c 100644 +index c5184985867b40daf2d86ed8b354f8d0fc960329..d77f165730df7eb1ee5bcfbfb41acbbda9311fe7 100644 --- a/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java @@ -140,7 +140,7 @@ public class SignBlockEntity extends BlockEntity { diff --git a/leaf-server/minecraft-patches/features/0105-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch b/leaf-server/minecraft-patches/features/0106-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch similarity index 87% rename from leaf-server/minecraft-patches/features/0105-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch rename to leaf-server/minecraft-patches/features/0106-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch index 9620bc31..b066fd11 100644 --- a/leaf-server/minecraft-patches/features/0105-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch +++ b/leaf-server/minecraft-patches/features/0106-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch @@ -7,10 +7,10 @@ Original license: MIT Original project: https://github.com/KeYiMC/KeYi diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index bf2f81232ac40218c6d0241b7a0a26cb2272e06b..6d01f8f8d95573cc545a0c1058cea87f40a39f05 100644 +index 883a053d025e74f73556a0affa2340e42365df59..8aab412c8e70b6f9d8e05a26cefac330dd7a2ea1 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -316,7 +316,7 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -322,7 +322,7 @@ public class ItemEntity extends Entity implements TraceableEntity { ItemStack item = this.getItem(); ItemStack item1 = itemEntity.getItem(); if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { diff --git a/leaf-server/minecraft-patches/features/0106-Carpet-Fixes-Optimized-getBiome-method.patch b/leaf-server/minecraft-patches/features/0107-Carpet-Fixes-Optimized-getBiome-method.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0106-Carpet-Fixes-Optimized-getBiome-method.patch rename to leaf-server/minecraft-patches/features/0107-Carpet-Fixes-Optimized-getBiome-method.patch diff --git a/leaf-server/minecraft-patches/features/0107-Carpet-Fixes-Use-optimized-RecipeManager.patch b/leaf-server/minecraft-patches/features/0108-Carpet-Fixes-Use-optimized-RecipeManager.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0107-Carpet-Fixes-Use-optimized-RecipeManager.patch rename to leaf-server/minecraft-patches/features/0108-Carpet-Fixes-Use-optimized-RecipeManager.patch diff --git a/leaf-server/minecraft-patches/features/0108-Akarin-Save-Json-list-asynchronously.patch b/leaf-server/minecraft-patches/features/0109-Akarin-Save-Json-list-asynchronously.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0108-Akarin-Save-Json-list-asynchronously.patch rename to leaf-server/minecraft-patches/features/0109-Akarin-Save-Json-list-asynchronously.patch diff --git a/leaf-server/minecraft-patches/features/0109-Slice-Smooth-Teleports.patch b/leaf-server/minecraft-patches/features/0110-Slice-Smooth-Teleports.patch similarity index 79% rename from leaf-server/minecraft-patches/features/0109-Slice-Smooth-Teleports.patch rename to leaf-server/minecraft-patches/features/0110-Slice-Smooth-Teleports.patch index 7878c76f..80982ce9 100644 --- a/leaf-server/minecraft-patches/features/0109-Slice-Smooth-Teleports.patch +++ b/leaf-server/minecraft-patches/features/0110-Slice-Smooth-Teleports.patch @@ -9,22 +9,22 @@ Original project: https://github.com/Cryptite/Slice Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 9d5051a65dcbd87b7d29db4643fa2b070717845b..d32acdf38a35d569669b272560c72651240178db 100644 +index 57d301a9528a16c0fcdb9e45ae957629c2363457..fe2710ee9b8a4452ff339a0b15ccf357a7c25336 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -427,6 +427,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - public @Nullable com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent - public @Nullable String clientBrandName = null; // Paper - Brand support - public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event +@@ -431,6 +431,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + private boolean tpsBar = false; // Purpur - Implement TPSBar + private boolean compassBar = false; // Purpur - Add compass command + private boolean ramBar = false; // Purpur - Implement rambar commands + public boolean smoothWorldTeleport; // Slice // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 11015e8c0f2b5f8bd2eb083d8e093beb72c43cf0..8bbf8d660a68c8c74204e101ec3ec0b775883090 100644 +index 800f773ca2cee6310a86d3f8043d57bd078a2dfd..51c1dfe30fddaae0c71b4b809b33c650394b878b 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -795,11 +795,11 @@ public abstract class PlayerList { +@@ -797,11 +797,11 @@ public abstract class PlayerList { byte b = (byte)(keepInventory ? 1 : 0); ServerLevel serverLevel = serverPlayer.serverLevel(); LevelData levelData = serverLevel.getLevelData(); @@ -38,7 +38,7 @@ index 11015e8c0f2b5f8bd2eb083d8e093beb72c43cf0..8bbf8d660a68c8c74204e101ec3ec0b7 serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); serverPlayer.connection -@@ -876,6 +876,8 @@ public abstract class PlayerList { +@@ -878,6 +878,8 @@ public abstract class PlayerList { return serverPlayer; } diff --git a/leaf-server/minecraft-patches/features/0110-Parchment-Make-FixLight-use-action-bar.patch b/leaf-server/minecraft-patches/features/0111-Parchment-Make-FixLight-use-action-bar.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0110-Parchment-Make-FixLight-use-action-bar.patch rename to leaf-server/minecraft-patches/features/0111-Parchment-Make-FixLight-use-action-bar.patch diff --git a/leaf-server/minecraft-patches/features/0111-Petal-Async-Pathfinding.patch b/leaf-server/minecraft-patches/features/0112-Petal-Async-Pathfinding.patch similarity index 97% rename from leaf-server/minecraft-patches/features/0111-Petal-Async-Pathfinding.patch rename to leaf-server/minecraft-patches/features/0112-Petal-Async-Pathfinding.patch index 4b701522..1989bdc1 100644 --- a/leaf-server/minecraft-patches/features/0111-Petal-Async-Pathfinding.patch +++ b/leaf-server/minecraft-patches/features/0112-Petal-Async-Pathfinding.patch @@ -19,10 +19,10 @@ This patch was ported downstream from the Petal fork. Makes most pathfinding-related work happen asynchronously diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index 92ebc61aa7f6f70292a384b56bd8ef77a15e485c..a1ecb7c5ee0e1fe1164e277d8991d6d990035f76 100644 +index ba2f9ab55e52e25788b38c81e1070ae953b66371..86d07d8f7c171a8930990ab02360e79066cad7d5 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -242,6 +242,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -243,6 +243,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Nullable @Override public LivingEntity getTarget() { @@ -31,7 +31,7 @@ index 92ebc61aa7f6f70292a384b56bd8ef77a15e485c..a1ecb7c5ee0e1fe1164e277d8991d6d9 } diff --git a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java -index 751e91a922b20c96f27885c3eb085ec4ae39091b..455662f0718365f466bc52bdaa228954e42d7216 100644 +index 7f0975f8bd6d5f8ca28f503f93c8cb5c42557420..698d7a690f012da87295f0d9035dc0e5f0626fcc 100644 --- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java @@ -102,21 +102,20 @@ public class AcquirePoi { @@ -514,13 +514,13 @@ index 2979846853898d78a2df19df2287da16dbe4ae71..1289a6e85f3fdb9187323343b6c20e17 } diff --git a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java -index 066faa704338c573472381e1ebd063e0d52aaaa4..8629b89401e4cb06dd8a658d1d3f189178c544d8 100644 +index 1f96fd5085bacb4c584576c7cb9f51e7898e9b03..03b6c8c8dcd42e864751e68be9d35d2045468655 100644 --- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java +++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java @@ -57,17 +57,32 @@ public class NearestBedSensor extends Sensor { java.util.List, BlockPos>> poiposes = new java.util.ArrayList<>(); // don't ask me why it's unbounded. ask mojang. - io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); + io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), level.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); // Purpur - Configurable villager search radius - Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes)); // Paper end - optimise POI access - if (path != null && path.canReach()) { @@ -560,10 +560,10 @@ index 066faa704338c573472381e1ebd063e0d52aaaa4..8629b89401e4cb06dd8a658d1d3f1891 + // Leaf end - Kaiiju - await on async path processing } diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java -index edca2fa21e600fa1e7ef91af673adaae7d4c86c4..6eb3a46ea67a30b7c88961a0c2168fc030cc14ad 100644 +index e9dfff7e3726cd2229f89bb39fa1ca4815d99a6d..654ecd20ef4a43f7ffc447c15434ce46ab89efe9 100644 --- a/net/minecraft/world/entity/animal/Bee.java +++ b/net/minecraft/world/entity/animal/Bee.java -@@ -856,7 +856,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -936,7 +936,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { } else { Bee.this.pathfindRandomlyTowards(Bee.this.hivePos); } @@ -572,7 +572,7 @@ index edca2fa21e600fa1e7ef91af673adaae7d4c86c4..6eb3a46ea67a30b7c88961a0c2168fc0 boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos); if (!flag) { this.dropAndBlacklistHive(); -@@ -910,7 +910,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -990,7 +990,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { return true; } else { Path path = Bee.this.navigation.getPath(); @@ -582,10 +582,10 @@ index edca2fa21e600fa1e7ef91af673adaae7d4c86c4..6eb3a46ea67a30b7c88961a0c2168fc0 } } diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java -index bd80e58179fe577693fa419a77989b0db39abb04..ba215c4ebefe3b49b77cc94ee5855debe7f60c84 100644 +index 89fa6a785ff73b30effd58dde4fbcbf99fdad168..5e0f34a929ddad69807db2edcf473a6c00392926 100644 --- a/net/minecraft/world/entity/animal/frog/Frog.java +++ b/net/minecraft/world/entity/animal/frog/Frog.java -@@ -431,9 +431,25 @@ public class Frog extends Animal { +@@ -489,9 +489,25 @@ public class Frog extends Animal { return pathType != PathType.WATER_BORDER && super.canCutCorner(pathType); } @@ -612,10 +612,10 @@ index bd80e58179fe577693fa419a77989b0db39abb04..ba215c4ebefe3b49b77cc94ee5855deb } } diff --git a/net/minecraft/world/entity/monster/Drowned.java b/net/minecraft/world/entity/monster/Drowned.java -index 4978cd2a7a84130fc0de1cc481b39d61f388c812..8b39391015f76d6fc9c740385f4ac683b85eebe1 100644 +index b85d1e196d2bf61ac4896205afb08eba89c4397e..c22f7054e0f78dcce3e3f9765e2ee9b63ca195ff 100644 --- a/net/minecraft/world/entity/monster/Drowned.java +++ b/net/minecraft/world/entity/monster/Drowned.java -@@ -239,7 +239,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -313,7 +313,7 @@ public class Drowned extends Zombie implements RangedAttackMob { protected boolean closeToNextPos() { Path path = this.getNavigation().getPath(); @@ -625,10 +625,10 @@ index 4978cd2a7a84130fc0de1cc481b39d61f388c812..8b39391015f76d6fc9c740385f4ac683 if (target != null) { double d = this.distanceToSqr(target.getX(), target.getY(), target.getZ()); diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java -index afa584e2aba6bebfb2dd343215b043c983281853..ed86080491c982c81306319e3730bfbd115d06aa 100644 +index fe31c4a45afd61be8b74efe9d0858ccd0aced075..e1717b5c854aa81fdd7b7e715d7c3498d9f86072 100644 --- a/net/minecraft/world/entity/monster/Strider.java +++ b/net/minecraft/world/entity/monster/Strider.java -@@ -507,9 +507,25 @@ public class Strider extends Animal implements ItemSteerable { +@@ -560,9 +560,25 @@ public class Strider extends Animal implements ItemSteerable { super(strider, level); } @@ -655,10 +655,10 @@ index afa584e2aba6bebfb2dd343215b043c983281853..ed86080491c982c81306319e3730bfbd } diff --git a/net/minecraft/world/entity/monster/warden/Warden.java b/net/minecraft/world/entity/monster/warden/Warden.java -index 42ca4243d86ef4a14a9ce70da4b79f6c8eeb3a7d..ce66ded89ed851264affc075d65aa1c5abe84dc8 100644 +index 497ea5d5aad1641d5876f23f05db82ab649c0785..e5193d7320ea17e86b776c705ec45010019493d6 100644 --- a/net/minecraft/world/entity/monster/warden/Warden.java +++ b/net/minecraft/world/entity/monster/warden/Warden.java -@@ -555,6 +555,16 @@ public class Warden extends Monster implements VibrationSystem { +@@ -580,6 +580,16 @@ public class Warden extends Monster implements VibrationSystem { @Override protected PathFinder createPathFinder(int maxVisitedNodes) { this.nodeEvaluator = new WalkNodeEvaluator(); diff --git a/leaf-server/minecraft-patches/features/0112-Petal-reduce-work-done-by-game-event-system.patch b/leaf-server/minecraft-patches/features/0113-Petal-reduce-work-done-by-game-event-system.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0112-Petal-reduce-work-done-by-game-event-system.patch rename to leaf-server/minecraft-patches/features/0113-Petal-reduce-work-done-by-game-event-system.patch diff --git a/leaf-server/minecraft-patches/features/0113-Reduce-canSee-work.patch b/leaf-server/minecraft-patches/features/0114-Reduce-canSee-work.patch similarity index 92% rename from leaf-server/minecraft-patches/features/0113-Reduce-canSee-work.patch rename to leaf-server/minecraft-patches/features/0114-Reduce-canSee-work.patch index d2e8f966..bbd9e85d 100644 --- a/leaf-server/minecraft-patches/features/0113-Reduce-canSee-work.patch +++ b/leaf-server/minecraft-patches/features/0114-Reduce-canSee-work.patch @@ -7,10 +7,10 @@ Co-authored by: Martijn Muijsers Co-authored by: MachineBreaker diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 20403c3e2582caf3541cd9b051fb5ebff52eb555..d56283aaf6726a5d71fb89f2c059db76c211d402 100644 +index 3b814983b91165ecee1a15d24cc0352247316a9f..453d4babc78f5676cb9534a5d80967a6f8c5a263 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -942,17 +942,19 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -987,17 +987,19 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl for (int i = 0, len = entities.size(); i < len; ++i) { Entity entity = entities.get(i); diff --git a/leaf-server/minecraft-patches/features/0114-Fix-sprint-glitch.patch b/leaf-server/minecraft-patches/features/0115-Fix-sprint-glitch.patch similarity index 83% rename from leaf-server/minecraft-patches/features/0114-Fix-sprint-glitch.patch rename to leaf-server/minecraft-patches/features/0115-Fix-sprint-glitch.patch index e3329c76..9c9deabe 100644 --- a/leaf-server/minecraft-patches/features/0114-Fix-sprint-glitch.patch +++ b/leaf-server/minecraft-patches/features/0115-Fix-sprint-glitch.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix sprint glitch diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 08c2021a43f626ae142d38d0d0492bffeb1b346b..e65914c2623197031d50508af5c45a4db6b98836 100644 +index dfca015796b87059b19db55b4911bd0de2580798..6cb9b8be0bd5d9fb225472f8eefd50233d3bbdb2 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -1358,7 +1358,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1387,7 +1387,8 @@ public abstract class LivingEntity extends Entity implements Attackable { player.setRealHealth(health); } diff --git a/leaf-server/minecraft-patches/features/0115-Faster-sequencing-of-futures-for-chunk-structure-gen.patch b/leaf-server/minecraft-patches/features/0116-Faster-sequencing-of-futures-for-chunk-structure-gen.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0115-Faster-sequencing-of-futures-for-chunk-structure-gen.patch rename to leaf-server/minecraft-patches/features/0116-Faster-sequencing-of-futures-for-chunk-structure-gen.patch diff --git a/leaf-server/minecraft-patches/features/0116-Reduce-active-items-finding-hopper-nearby-check.patch b/leaf-server/minecraft-patches/features/0117-Reduce-active-items-finding-hopper-nearby-check.patch similarity index 90% rename from leaf-server/minecraft-patches/features/0116-Reduce-active-items-finding-hopper-nearby-check.patch rename to leaf-server/minecraft-patches/features/0117-Reduce-active-items-finding-hopper-nearby-check.patch index f911917a..6adee127 100644 --- a/leaf-server/minecraft-patches/features/0116-Reduce-active-items-finding-hopper-nearby-check.patch +++ b/leaf-server/minecraft-patches/features/0117-Reduce-active-items-finding-hopper-nearby-check.patch @@ -9,10 +9,10 @@ But still recommend to turn-off `checkForMinecartNearItemWhileActive` Since `Reduce-hopper-item-checks.patch` will cause lag under massive dropped items diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index 6d01f8f8d95573cc545a0c1058cea87f40a39f05..8773952bb271158ca5387a2e8813c16116d8ee64 100644 +index 8aab412c8e70b6f9d8e05a26cefac330dd7a2ea1..ecec91d28d1b71d549f48185af5f1ef3286768be 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -242,7 +242,11 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -248,7 +248,11 @@ public class ItemEntity extends Entity implements TraceableEntity { this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause return; // Gale - EMC - reduce hopper item checks } diff --git a/leaf-server/minecraft-patches/features/0117-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch b/leaf-server/minecraft-patches/features/0118-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0117-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch rename to leaf-server/minecraft-patches/features/0118-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch diff --git a/leaf-server/minecraft-patches/features/0118-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch b/leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch similarity index 92% rename from leaf-server/minecraft-patches/features/0118-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch rename to leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch index 0aecbec0..abd6869d 100644 --- a/leaf-server/minecraft-patches/features/0118-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch +++ b/leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch @@ -11,10 +11,10 @@ Optimizes "image in map" maps, without requiring the map to be locked, which som This has the disadvantage that the vanilla map data will never be updated while the CraftMapRenderer is not present, but that's not a huuuge problem for u diff --git a/net/minecraft/world/item/MapItem.java b/net/minecraft/world/item/MapItem.java -index ba0b254d43651bca1f29b5272af05d068fc37ba8..9bb0ce86d2b7af4c468588de50a26a0b8615eb04 100644 +index 780793750c99185e8139a1cd0ad52bc7b80899a9..dd20922e25710fe79fb4d37d04dd5cb59cb896fe 100644 --- a/net/minecraft/world/item/MapItem.java +++ b/net/minecraft/world/item/MapItem.java -@@ -274,7 +274,18 @@ public class MapItem extends Item { +@@ -275,7 +275,18 @@ public class MapItem extends Item { savedData.tickCarriedBy(player, stack); } diff --git a/leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch b/leaf-server/minecraft-patches/features/0120-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch similarity index 87% rename from leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch rename to leaf-server/minecraft-patches/features/0120-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch index 3f03517b..d74f13c5 100644 --- a/leaf-server/minecraft-patches/features/0119-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch +++ b/leaf-server/minecraft-patches/features/0120-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch @@ -13,18 +13,18 @@ To avoid the hefty ArrayDeque's size() call, we check if we *really* need to exe Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay). diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 4b163dbc99cbfcef4d7bae97055af844e400d87a..18083f96f95eb4436cefe5a99fd0fe25d102bae7 100644 +index 626ce084ace620bd3883fb3f542b0bd77dfb5f8e..9b61d82b59715f7de484dca663113cc2cf9be3b2 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping - public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation +@@ -289,6 +289,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) public static S spin(Function threadFunction) { AtomicReference atomicReference = new AtomicReference<>(); -@@ -1628,6 +1629,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { for (final net.minecraft.world.entity.Entity entity : level.getEntities().getAll()) { if (entity.isRemoved()) { -@@ -1639,6 +1656,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 0 ? entity.level().purpurConfig.snowballDamage : entity instanceof Blaze ? 3 : 0; // Purpur - Add configurable snowball damage entity.hurt(this.damageSources().thrown(this, this.getOwner()), i); + // Leaf start - Polpot - Make snowball can knockback player + if (org.dreeam.leaf.config.modules.gameplay.Knockback.snowballCanKnockback && entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { @@ -20,7 +20,7 @@ index 677b4b681f9c2c09a8ae3cfdec72102265547a7b..3f9767a84e9faf1f010358d9c2137bb2 + // Leaf end - Polpot - Make snowball can knockback player } - @Override + // Purpur start - options to extinguish fire blocks with snowballs - borrowed and modified code from ThrownPotion#onHitBlock and ThrownPotion#dowseFire diff --git a/net/minecraft/world/entity/projectile/ThrownEgg.java b/net/minecraft/world/entity/projectile/ThrownEgg.java index 73ec34b43f3fb2aa3edc3f1cb48a923d1fa32036..2433724db23e35f5de3ff46b2801914e6bc2a112 100644 --- a/net/minecraft/world/entity/projectile/ThrownEgg.java diff --git a/leaf-server/minecraft-patches/features/0123-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch b/leaf-server/minecraft-patches/features/0124-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0123-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch rename to leaf-server/minecraft-patches/features/0124-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch diff --git a/leaf-server/minecraft-patches/features/0124-Remove-useless-creating-stats-json-bases-on-player-n.patch b/leaf-server/minecraft-patches/features/0125-Remove-useless-creating-stats-json-bases-on-player-n.patch similarity index 85% rename from leaf-server/minecraft-patches/features/0124-Remove-useless-creating-stats-json-bases-on-player-n.patch rename to leaf-server/minecraft-patches/features/0125-Remove-useless-creating-stats-json-bases-on-player-n.patch index ecb871ce..bd416c8d 100644 --- a/leaf-server/minecraft-patches/features/0124-Remove-useless-creating-stats-json-bases-on-player-n.patch +++ b/leaf-server/minecraft-patches/features/0125-Remove-useless-creating-stats-json-bases-on-player-n.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove useless creating stats json bases on player name logic diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 8bbf8d660a68c8c74204e101ec3ec0b775883090..68d8bb239c2e48e5b3e280676274067e1f597620 100644 +index 51c1dfe30fddaae0c71b4b809b33c650394b878b..82117c8619b184017bb4448bf2e30f817abd368a 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1377,6 +1377,8 @@ public abstract class PlayerList { +@@ -1415,6 +1415,8 @@ public abstract class PlayerList { if (serverStatsCounter == null) { File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); File file1 = new File(file, uuid + ".json"); @@ -17,7 +17,7 @@ index 8bbf8d660a68c8c74204e101ec3ec0b775883090..68d8bb239c2e48e5b3e280676274067e if (!file1.exists()) { File file2 = new File(file, displayName + ".json"); // CraftBukkit Path path = file2.toPath(); -@@ -1384,6 +1386,8 @@ public abstract class PlayerList { +@@ -1422,6 +1424,8 @@ public abstract class PlayerList { file2.renameTo(file1); } } diff --git a/leaf-server/minecraft-patches/features/0125-Virtual-thread-for-chat-executor.patch b/leaf-server/minecraft-patches/features/0126-Virtual-thread-for-chat-executor.patch similarity index 90% rename from leaf-server/minecraft-patches/features/0125-Virtual-thread-for-chat-executor.patch rename to leaf-server/minecraft-patches/features/0126-Virtual-thread-for-chat-executor.patch index 33c10376..00277598 100644 --- a/leaf-server/minecraft-patches/features/0125-Virtual-thread-for-chat-executor.patch +++ b/leaf-server/minecraft-patches/features/0126-Virtual-thread-for-chat-executor.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Virtual thread for chat executor diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 18083f96f95eb4436cefe5a99fd0fe25d102bae7..301b255d43a160b462e546ab894378cc38ae18e6 100644 +index 9b61d82b59715f7de484dca663113cc2cf9be3b2..18a0150536a847f9617a736245086d590bf80b74 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -2625,7 +2625,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop packet) { @@ -138,10 +138,10 @@ index 8c3255661221f8afbccb661bec3afb47e4059403..0450c85bf7c7af1c863514f7c13b5fe1 if (packet == null || this.processedDisconnect) { // Spigot return; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 68d8bb239c2e48e5b3e280676274067e1f597620..a6340714eab6d7eafae639c6aeb2aeb75a0e6c07 100644 +index 82117c8619b184017bb4448bf2e30f817abd368a..f5cdd332292dbf3367eff99efa6c52f00267be52 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1336,7 +1336,7 @@ public abstract class PlayerList { +@@ -1374,7 +1374,7 @@ public abstract class PlayerList { public void broadcastChatMessage(PlayerChatMessage message, Predicate shouldFilterMessageTo, @Nullable ServerPlayer sender, ChatType.Bound boundChatType, @Nullable Function unsignedFunction) { // Paper end boolean flag = this.verifyChatTrusted(message); @@ -150,7 +150,7 @@ index 68d8bb239c2e48e5b3e280676274067e1f597620..a6340714eab6d7eafae639c6aeb2aeb7 OutgoingChatMessage outgoingChatMessage = OutgoingChatMessage.create(message); boolean flag1 = false; -@@ -1361,6 +1361,7 @@ public abstract class PlayerList { +@@ -1399,6 +1399,7 @@ public abstract class PlayerList { } public boolean verifyChatTrusted(PlayerChatMessage message) { diff --git a/leaf-server/minecraft-patches/features/0128-Cache-player-profileResult.patch b/leaf-server/minecraft-patches/features/0129-Cache-player-profileResult.patch similarity index 97% rename from leaf-server/minecraft-patches/features/0128-Cache-player-profileResult.patch rename to leaf-server/minecraft-patches/features/0129-Cache-player-profileResult.patch index a04dc465..ac7be181 100644 --- a/leaf-server/minecraft-patches/features/0128-Cache-player-profileResult.patch +++ b/leaf-server/minecraft-patches/features/0129-Cache-player-profileResult.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Cache player profileResult diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 451a8b9f4deda749b0cb08adb4b5408c2e3ffd93..0aa72ed879e9f7199b75defca884bf8242caae99 100644 +index 9dce1d22c7de3a3dd0e0e8f117cfbb54d1b15042..c4d0372feb6299b785a7e569314cc91f07870036 100644 --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -70,6 +70,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, diff --git a/leaf-server/minecraft-patches/features/0129-Matter-Secure-Seed.patch b/leaf-server/minecraft-patches/features/0130-Matter-Secure-Seed.patch similarity index 98% rename from leaf-server/minecraft-patches/features/0129-Matter-Secure-Seed.patch rename to leaf-server/minecraft-patches/features/0130-Matter-Secure-Seed.patch index 9488654c..503af0fc 100644 --- a/leaf-server/minecraft-patches/features/0129-Matter-Secure-Seed.patch +++ b/leaf-server/minecraft-patches/features/0130-Matter-Secure-Seed.patch @@ -13,10 +13,10 @@ Co-authored-by: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> diff --git a/net/minecraft/server/dedicated/DedicatedServerProperties.java b/net/minecraft/server/dedicated/DedicatedServerProperties.java -index f6518e29f805018c72222f5aaa7b662071665b65..1bf57875cb363e08734222ed59f3b77a2d0dfba5 100644 +index 5748658abf0b90812005ae9d426df92daf5532f0..4a0eed7d7645ed539857592d233214e9a74499f1 100644 --- a/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -113,7 +113,17 @@ public class DedicatedServerProperties extends Settings, AutoCl @@ -122,15 +122,15 @@ index d56283aaf6726a5d71fb89f2c059db76c211d402..6b7efd6466d16276c37abfa1fd64df84 @Deprecated private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); private final Holder dimensionTypeRegistration; -@@ -168,7 +168,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -169,7 +169,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl private int tileTickPosition; public final Map explosionDensityCache = new java.util.HashMap<>(); // Paper - Optimize explosions public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here - public final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // Gale - Pufferfish - move random tick random + public final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = org.dreeam.leaf.config.modules.opt.FastRNG.enabled ? new org.dreeam.leaf.util.math.random.FasterRandomSource(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()) : new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // Gale - Pufferfish - move random tick random // Leaf - Faster random generator - public CraftWorld getWorld() { - return this.world; + // Purpur start - Add adjustable breeding cooldown to config + private com.google.common.cache.Cache playerBreedingCooldowns; diff --git a/net/minecraft/world/level/biome/Biome.java b/net/minecraft/world/level/biome/Biome.java index bad1a03167f7586e5279592adcb43350c9b528cd..336d42d4e85716843633030ba1aa21b7901ca601 100644 --- a/net/minecraft/world/level/biome/Biome.java diff --git a/leaf-server/minecraft-patches/features/0132-Don-t-save-primed-tnt-entity.patch b/leaf-server/minecraft-patches/features/0133-Don-t-save-primed-tnt-entity.patch similarity index 68% rename from leaf-server/minecraft-patches/features/0132-Don-t-save-primed-tnt-entity.patch rename to leaf-server/minecraft-patches/features/0133-Don-t-save-primed-tnt-entity.patch index 8276fce8..8060b7c7 100644 --- a/leaf-server/minecraft-patches/features/0132-Don-t-save-primed-tnt-entity.patch +++ b/leaf-server/minecraft-patches/features/0133-Don-t-save-primed-tnt-entity.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Don't save primed tnt entity diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index 5d23d8754b304d5e2fd54400cc81c7fe5c14a804..edc003e4f0cc4280c90fda9c42a3faacc0f5c94d 100644 +index 9a00aead39e194de076ee651d2f75b29673cad1e..36e3937c9e09852937c94c268c877a15337835c5 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java -@@ -253,4 +253,11 @@ public class PrimedTnt extends Entity implements TraceableEntity { - return !this.level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid(); +@@ -281,4 +281,11 @@ public class PrimedTnt extends Entity implements TraceableEntity { + return super.interact(player, hand); } - // Paper end - Option to prevent TNT from moving in water + // Purpur end - Shears can defuse TNT + + // Leaf start - PMC - Don't save primed tnt entity + @Override diff --git a/leaf-server/minecraft-patches/features/0133-Don-t-save-falling-block-entity.patch b/leaf-server/minecraft-patches/features/0134-Don-t-save-falling-block-entity.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0133-Don-t-save-falling-block-entity.patch rename to leaf-server/minecraft-patches/features/0134-Don-t-save-falling-block-entity.patch diff --git a/leaf-server/minecraft-patches/features/0134-Configurable-connection-message.patch b/leaf-server/minecraft-patches/features/0135-Configurable-connection-message.patch similarity index 95% rename from leaf-server/minecraft-patches/features/0134-Configurable-connection-message.patch rename to leaf-server/minecraft-patches/features/0135-Configurable-connection-message.patch index 7ea410e9..8db9173e 100644 --- a/leaf-server/minecraft-patches/features/0134-Configurable-connection-message.patch +++ b/leaf-server/minecraft-patches/features/0135-Configurable-connection-message.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Configurable connection message diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index a6340714eab6d7eafae639c6aeb2aeb75a0e6c07..0bc3908c8ab41fa11c8698dd8d87c1b52c6767da 100644 +index f5cdd332292dbf3367eff99efa6c52f00267be52..4bc7e2c569223779d3c8c556a62d81c092481f70 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -336,7 +336,7 @@ public abstract class PlayerList { @@ -26,7 +26,7 @@ index a6340714eab6d7eafae639c6aeb2aeb75a0e6c07..0bc3908c8ab41fa11c8698dd8d87c1b5 joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure } -@@ -530,7 +530,7 @@ public abstract class PlayerList { +@@ -532,7 +532,7 @@ public abstract class PlayerList { player.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - Inventory close reason } @@ -35,7 +35,7 @@ index a6340714eab6d7eafae639c6aeb2aeb75a0e6c07..0bc3908c8ab41fa11c8698dd8d87c1b5 this.cserver.getPluginManager().callEvent(playerQuitEvent); player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); -@@ -1488,4 +1488,34 @@ public abstract class PlayerList { +@@ -1526,4 +1526,34 @@ public abstract class PlayerList { public boolean isAllowCommandsForAllPlayers() { return this.allowCommandsForAllPlayers; } diff --git a/leaf-server/minecraft-patches/features/0135-Configurable-unknown-command-message.patch b/leaf-server/minecraft-patches/features/0136-Configurable-unknown-command-message.patch similarity index 97% rename from leaf-server/minecraft-patches/features/0135-Configurable-unknown-command-message.patch rename to leaf-server/minecraft-patches/features/0136-Configurable-unknown-command-message.patch index a467beb3..5bdcee6b 100644 --- a/leaf-server/minecraft-patches/features/0135-Configurable-unknown-command-message.patch +++ b/leaf-server/minecraft-patches/features/0136-Configurable-unknown-command-message.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable unknown command message diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java -index 287edc8caecfd1ebb399d52789161f4d57d0801c..2d3a0d7735983065a41212b202bcb010ba0bf014 100644 +index bcecf48b43eef377354e32695d4258ea8020f73d..71b1b28dbb310e7525fac78a81e15f30665de737 100644 --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java -@@ -394,31 +394,8 @@ public class Commands { +@@ -402,31 +402,8 @@ public class Commands { // Paper start - Add UnknownCommandEvent final net.kyori.adventure.text.TextComponent.Builder builder = net.kyori.adventure.text.Component.text(); // source.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage())); @@ -41,7 +41,7 @@ index 287edc8caecfd1ebb399d52789161f4d57d0801c..2d3a0d7735983065a41212b202bcb010 org.bukkit.Bukkit.getServer().getPluginManager().callEvent(event); if (event.message() != null) { source.sendFailure(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false); -@@ -668,6 +645,86 @@ public class Commands { +@@ -676,6 +653,86 @@ public class Commands { }; } diff --git a/leaf-server/minecraft-patches/features/0136-Remove-stream-in-BlockBehaviour-cache-blockstate.patch b/leaf-server/minecraft-patches/features/0137-Remove-stream-in-BlockBehaviour-cache-blockstate.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0136-Remove-stream-in-BlockBehaviour-cache-blockstate.patch rename to leaf-server/minecraft-patches/features/0137-Remove-stream-in-BlockBehaviour-cache-blockstate.patch diff --git a/leaf-server/minecraft-patches/features/0137-Remove-stream-in-entity-visible-effects-filter.patch b/leaf-server/minecraft-patches/features/0138-Remove-stream-in-entity-visible-effects-filter.patch similarity index 89% rename from leaf-server/minecraft-patches/features/0137-Remove-stream-in-entity-visible-effects-filter.patch rename to leaf-server/minecraft-patches/features/0138-Remove-stream-in-entity-visible-effects-filter.patch index 22c6d681..c30f55c8 100644 --- a/leaf-server/minecraft-patches/features/0137-Remove-stream-in-entity-visible-effects-filter.patch +++ b/leaf-server/minecraft-patches/features/0138-Remove-stream-in-entity-visible-effects-filter.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove stream in entity visible effects filter diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index e65914c2623197031d50508af5c45a4db6b98836..4fd0a728bcc3a7063cefe4d163329f07db06176f 100644 +index 6cb9b8be0bd5d9fb225472f8eefd50233d3bbdb2..19c1dca135ada485e5aab78a0c0622ee9856e1e9 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -975,12 +975,15 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -988,12 +988,15 @@ public abstract class LivingEntity extends Entity implements Attackable { } private void updateSynchronizedMobEffectParticles() { diff --git a/leaf-server/minecraft-patches/features/0138-Remove-stream-and-double-iteration-in-enough-deep-sl.patch b/leaf-server/minecraft-patches/features/0139-Remove-stream-and-double-iteration-in-enough-deep-sl.patch similarity index 87% rename from leaf-server/minecraft-patches/features/0138-Remove-stream-and-double-iteration-in-enough-deep-sl.patch rename to leaf-server/minecraft-patches/features/0139-Remove-stream-and-double-iteration-in-enough-deep-sl.patch index a1f13784..f180fce3 100644 --- a/leaf-server/minecraft-patches/features/0138-Remove-stream-and-double-iteration-in-enough-deep-sl.patch +++ b/leaf-server/minecraft-patches/features/0139-Remove-stream-and-double-iteration-in-enough-deep-sl.patch @@ -6,14 +6,14 @@ Subject: [PATCH] Remove stream and double iteration in enough deep sleeping diff --git a/net/minecraft/server/players/SleepStatus.java b/net/minecraft/server/players/SleepStatus.java -index 2a7ae521654ad5c9f392baa5562e64bb71b13097..2d0033b18f46fb05df12536d68b4bce455abfeed 100644 +index 3a3e6992563236141db687084aeec9684437a7db..e6827e90b685f88d945010f2c8c5aead52b0856e 100644 --- a/net/minecraft/server/players/SleepStatus.java +++ b/net/minecraft/server/players/SleepStatus.java @@ -15,9 +15,24 @@ public class SleepStatus { public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List sleepingPlayers) { // CraftBukkit start -- int i = (int) sleepingPlayers.stream().filter(player -> player.isSleepingLongEnough() || player.fauxSleeping).count(); +- int i = (int) sleepingPlayers.stream().filter(player -> player.isSleepingLongEnough() || player.fauxSleeping || (player.level().purpurConfig.idleTimeoutCountAsSleeping && player.isAfk())).count(); // Purpur - AFK API - boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough); - return anyDeepSleep && i >= this.sleepersNeeded(requiredSleepPercentage); + // Leaf start - Remove stream and double iteration in enough deep sleeping player check diff --git a/leaf-server/minecraft-patches/features/0139-Remove-stream-in-trial-spawner-ticking.patch b/leaf-server/minecraft-patches/features/0140-Remove-stream-in-trial-spawner-ticking.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0139-Remove-stream-in-trial-spawner-ticking.patch rename to leaf-server/minecraft-patches/features/0140-Remove-stream-in-trial-spawner-ticking.patch diff --git a/leaf-server/minecraft-patches/features/0140-Remove-stream-in-Brain.patch b/leaf-server/minecraft-patches/features/0141-Remove-stream-in-Brain.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0140-Remove-stream-in-Brain.patch rename to leaf-server/minecraft-patches/features/0141-Remove-stream-in-Brain.patch diff --git a/leaf-server/minecraft-patches/features/0141-Remove-stream-in-BehaviorUtils.patch b/leaf-server/minecraft-patches/features/0142-Remove-stream-in-BehaviorUtils.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0141-Remove-stream-in-BehaviorUtils.patch rename to leaf-server/minecraft-patches/features/0142-Remove-stream-in-BehaviorUtils.patch diff --git a/leaf-server/minecraft-patches/features/0142-Remove-stream-in-YieldJobSite.patch b/leaf-server/minecraft-patches/features/0143-Remove-stream-in-YieldJobSite.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0142-Remove-stream-in-YieldJobSite.patch rename to leaf-server/minecraft-patches/features/0143-Remove-stream-in-YieldJobSite.patch diff --git a/leaf-server/minecraft-patches/features/0143-Remove-stream-in-PlayerSensor.patch b/leaf-server/minecraft-patches/features/0144-Remove-stream-in-PlayerSensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0143-Remove-stream-in-PlayerSensor.patch rename to leaf-server/minecraft-patches/features/0144-Remove-stream-in-PlayerSensor.patch diff --git a/leaf-server/minecraft-patches/features/0144-Remove-stream-in-GolemSensor.patch b/leaf-server/minecraft-patches/features/0145-Remove-stream-in-GolemSensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0144-Remove-stream-in-GolemSensor.patch rename to leaf-server/minecraft-patches/features/0145-Remove-stream-in-GolemSensor.patch diff --git a/leaf-server/minecraft-patches/features/0145-Remove-stream-in-GateBehavior.patch b/leaf-server/minecraft-patches/features/0146-Remove-stream-in-GateBehavior.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0145-Remove-stream-in-GateBehavior.patch rename to leaf-server/minecraft-patches/features/0146-Remove-stream-in-GateBehavior.patch diff --git a/leaf-server/minecraft-patches/features/0146-Remove-stream-in-updateFluidOnEyes.patch b/leaf-server/minecraft-patches/features/0147-Remove-stream-in-updateFluidOnEyes.patch similarity index 95% rename from leaf-server/minecraft-patches/features/0146-Remove-stream-in-updateFluidOnEyes.patch rename to leaf-server/minecraft-patches/features/0147-Remove-stream-in-updateFluidOnEyes.patch index 515a900d..d5cd6263 100644 --- a/leaf-server/minecraft-patches/features/0146-Remove-stream-in-updateFluidOnEyes.patch +++ b/leaf-server/minecraft-patches/features/0147-Remove-stream-in-updateFluidOnEyes.patch @@ -46,10 +46,10 @@ index 6c7edbbf3935c40ccb78bee680ea75431718b9bd..a1b4dc70d555cce5e06c0298736d8b89 public String toString() { return "Reference{" + this.key + "=" + this.value + "}"; diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 8ac90cc10625f395dba660e2358bbac79431b0cf..f71ab3764aa3bb8b2c48bcae8c7331b4d821e4b1 100644 +index f764c8d108f8ce8d7a901907eb41c9ee4c441d68..8120d78a3175b47b1e6db2f568d79f084f4db044 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1930,7 +1930,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1963,7 +1963,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess FluidState fluidState = this.level().getFluidState(blockPos); double d = blockPos.getY() + fluidState.getHeight(this.level(), blockPos); if (d > eyeY) { diff --git a/leaf-server/minecraft-patches/features/0147-Remove-stream-in-matchingSlot.patch b/leaf-server/minecraft-patches/features/0148-Remove-stream-in-matchingSlot.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0147-Remove-stream-in-matchingSlot.patch rename to leaf-server/minecraft-patches/features/0148-Remove-stream-in-matchingSlot.patch diff --git a/leaf-server/minecraft-patches/features/0148-Remove-stream-in-entity-mountedOrDismounted-changes-.patch b/leaf-server/minecraft-patches/features/0149-Remove-stream-in-entity-mountedOrDismounted-changes-.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0148-Remove-stream-in-entity-mountedOrDismounted-changes-.patch rename to leaf-server/minecraft-patches/features/0149-Remove-stream-in-entity-mountedOrDismounted-changes-.patch diff --git a/leaf-server/minecraft-patches/features/0149-Replace-Entity-active-effects-map-with-optimized-col.patch b/leaf-server/minecraft-patches/features/0150-Replace-Entity-active-effects-map-with-optimized-col.patch similarity index 94% rename from leaf-server/minecraft-patches/features/0149-Replace-Entity-active-effects-map-with-optimized-col.patch rename to leaf-server/minecraft-patches/features/0150-Replace-Entity-active-effects-map-with-optimized-col.patch index 5c4c22e6..8d1aac50 100644 --- a/leaf-server/minecraft-patches/features/0149-Replace-Entity-active-effects-map-with-optimized-col.patch +++ b/leaf-server/minecraft-patches/features/0150-Replace-Entity-active-effects-map-with-optimized-col.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Replace Entity active effects map with optimized collection Dreeam TODO: check this diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 4fd0a728bcc3a7063cefe4d163329f07db06176f..0e1fb766570b5ff0e3c4a0f04c4ef3c589417322 100644 +index 19c1dca135ada485e5aab78a0c0622ee9856e1e9..534dd27d27395f9c98c62ea7014bb3a8df8caa2e 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -196,6 +196,10 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -20,7 +20,7 @@ index 4fd0a728bcc3a7063cefe4d163329f07db06176f..0e1fb766570b5ff0e3c4a0f04c4ef3c5 public final Map, MobEffectInstance> activeEffects = Maps.newHashMap(); private final Map lastEquipmentItems = Util.makeEnumMap(EquipmentSlot.class, slot -> ItemStack.EMPTY); public boolean swinging; -@@ -977,15 +981,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -990,15 +994,16 @@ public abstract class LivingEntity extends Entity implements Attackable { private void updateSynchronizedMobEffectParticles() { // Leaf start - Remove stream in entity visible effects filter List list = new java.util.ArrayList<>(); diff --git a/leaf-server/minecraft-patches/features/0150-Replace-criterion-map-with-optimized-collection.patch b/leaf-server/minecraft-patches/features/0151-Replace-criterion-map-with-optimized-collection.patch similarity index 93% rename from leaf-server/minecraft-patches/features/0150-Replace-criterion-map-with-optimized-collection.patch rename to leaf-server/minecraft-patches/features/0151-Replace-criterion-map-with-optimized-collection.patch index 141ab0f4..6be18088 100644 --- a/leaf-server/minecraft-patches/features/0150-Replace-criterion-map-with-optimized-collection.patch +++ b/leaf-server/minecraft-patches/features/0151-Replace-criterion-map-with-optimized-collection.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Replace criterion map with optimized collection diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java -index 741894ed6df81fce41d9f906d6198d038aab44a8..83ed64b9253f1fcde58267a510256cc18dfd8f8d 100644 +index edf115439c630a4471460db02109bbce7868de81..6dc728625de0f323322c34104e1c55b17aa0b712 100644 --- a/net/minecraft/server/PlayerAdvancements.java +++ b/net/minecraft/server/PlayerAdvancements.java @@ -60,7 +60,7 @@ public class PlayerAdvancements { diff --git a/leaf-server/minecraft-patches/features/0151-Replace-brain-maps-with-optimized-collection.patch b/leaf-server/minecraft-patches/features/0152-Replace-brain-maps-with-optimized-collection.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0151-Replace-brain-maps-with-optimized-collection.patch rename to leaf-server/minecraft-patches/features/0152-Replace-brain-maps-with-optimized-collection.patch diff --git a/leaf-server/minecraft-patches/features/0152-Reduce-worldgen-allocations.patch b/leaf-server/minecraft-patches/features/0153-Reduce-worldgen-allocations.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0152-Reduce-worldgen-allocations.patch rename to leaf-server/minecraft-patches/features/0153-Reduce-worldgen-allocations.patch diff --git a/leaf-server/minecraft-patches/features/0153-Fix-MC-65198.patch b/leaf-server/minecraft-patches/features/0154-Fix-MC-65198.patch similarity index 90% rename from leaf-server/minecraft-patches/features/0153-Fix-MC-65198.patch rename to leaf-server/minecraft-patches/features/0154-Fix-MC-65198.patch index db5497f1..7c1019d6 100644 --- a/leaf-server/minecraft-patches/features/0153-Fix-MC-65198.patch +++ b/leaf-server/minecraft-patches/features/0154-Fix-MC-65198.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix MC-65198 Mojang issues: https://bugs.mojang.com/browse/MC/issues/MC-65198 diff --git a/net/minecraft/world/inventory/ItemCombinerMenu.java b/net/minecraft/world/inventory/ItemCombinerMenu.java -index 34d52c941395645e77de810855b14012c259cf02..7ad3edf0e65c688408bf48305028468e2731cf75 100644 +index c605bd700fd9f5a6596a2bf9648492786306b025..77c0b0b6c63d0a2955fcf3a479581f09067f3e62 100644 --- a/net/minecraft/world/inventory/ItemCombinerMenu.java +++ b/net/minecraft/world/inventory/ItemCombinerMenu.java @@ -120,6 +120,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { @@ -17,15 +17,15 @@ index 34d52c941395645e77de810855b14012c259cf02..7ad3edf0e65c688408bf48305028468e int inventorySlotStart = this.getInventorySlotStart(); int useRowEnd = this.getUseRowEnd(); if (index == this.getResultSlot()) { -@@ -156,7 +157,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { - return ItemStack.EMPTY; +@@ -157,7 +158,7 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { } + this.activeQuickItem = itemStack; // Purpur - Anvil API - slot.onTake(player, item); + slot.onTake(player, itemStack2); // Leaf - Fix MC-65198 + this.activeQuickItem = null; // Purpur - Anvil API } - return itemStack; diff --git a/net/minecraft/world/inventory/ResultSlot.java b/net/minecraft/world/inventory/ResultSlot.java index e4cba45c327d96550a92cd5f9a30b1e5bd212747..ba237017e21d66b4eb3b47b4c7160015993da348 100644 --- a/net/minecraft/world/inventory/ResultSlot.java diff --git a/leaf-server/minecraft-patches/features/0154-Fix-MC-200418.patch b/leaf-server/minecraft-patches/features/0155-Fix-MC-200418.patch similarity index 88% rename from leaf-server/minecraft-patches/features/0154-Fix-MC-200418.patch rename to leaf-server/minecraft-patches/features/0155-Fix-MC-200418.patch index 4682b5d4..db1f4b84 100644 --- a/leaf-server/minecraft-patches/features/0154-Fix-MC-200418.patch +++ b/leaf-server/minecraft-patches/features/0155-Fix-MC-200418.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix MC-200418 Related MC issue: https://bugs.mojang.com/browse/MC/issues/MC-200418 diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java -index a8cd7103e636b57be1270d0f3549c709330b5536..33369d4faf80d36cee5dd3317a8778da5edd060a 100644 +index ae5939c940bdd93977fa882360fc31e46479554f..48042c85676ca8a8ff074f5b23f0857a0a96af0e 100644 --- a/net/minecraft/world/entity/monster/ZombieVillager.java +++ b/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -233,6 +233,11 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -293,6 +293,11 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { if (!this.isSilent()) { level.levelEvent(null, 1027, this.blockPosition(), 0); } diff --git a/leaf-server/minecraft-patches/features/0155-Fix-MC-119417.patch b/leaf-server/minecraft-patches/features/0156-Fix-MC-119417.patch similarity index 85% rename from leaf-server/minecraft-patches/features/0155-Fix-MC-119417.patch rename to leaf-server/minecraft-patches/features/0156-Fix-MC-119417.patch index 62f57d62..e1cd7ce3 100644 --- a/leaf-server/minecraft-patches/features/0155-Fix-MC-119417.patch +++ b/leaf-server/minecraft-patches/features/0156-Fix-MC-119417.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix MC-119417 Related MC issue: https://bugs.mojang.com/browse/MC/issues/MC-119417 diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index d32acdf38a35d569669b272560c72651240178db..637e595c99bf0580d59913dff579868dbf01491b 100644 +index fe2710ee9b8a4452ff339a0b15ccf357a7c25336..291d1ca6df397bba0c85480ab678c481fa59914d 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -2123,6 +2123,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2190,6 +2190,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, gameMode.getId())); if (gameMode == GameType.SPECTATOR) { this.removeEntitiesOnShoulder(); diff --git a/leaf-server/minecraft-patches/features/0156-Fix-MC-223153.patch b/leaf-server/minecraft-patches/features/0157-Fix-MC-223153.patch similarity index 84% rename from leaf-server/minecraft-patches/features/0156-Fix-MC-223153.patch rename to leaf-server/minecraft-patches/features/0157-Fix-MC-223153.patch index 4f52890f..903f4fe8 100644 --- a/leaf-server/minecraft-patches/features/0156-Fix-MC-223153.patch +++ b/leaf-server/minecraft-patches/features/0157-Fix-MC-223153.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix MC-223153 Related MC issue: https://bugs.mojang.com/browse/MC/issues/MC-223153 diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java -index cea1e405c940cd51cf830f28bfc6ce72c0c36a12..01b1495dfd8619ae29591ed4cadce9a0330b85bc 100644 +index 4941bf9df0c8ed6316572920323f7c5f6791b002..303bd27d44e4acfee49334235a6704724e3fd616 100644 --- a/net/minecraft/world/level/block/Blocks.java +++ b/net/minecraft/world/level/block/Blocks.java -@@ -6742,6 +6742,7 @@ public class Blocks { +@@ -6744,6 +6744,7 @@ public class Blocks { .mapColor(MapColor.COLOR_ORANGE) .instrument(NoteBlockInstrument.BASEDRUM) .requiresCorrectToolForDrops() diff --git a/leaf-server/minecraft-patches/features/0157-Configurable-player-knockback-zombie.patch b/leaf-server/minecraft-patches/features/0158-Configurable-player-knockback-zombie.patch similarity index 89% rename from leaf-server/minecraft-patches/features/0157-Configurable-player-knockback-zombie.patch rename to leaf-server/minecraft-patches/features/0158-Configurable-player-knockback-zombie.patch index 6e3f27c0..ccdbc86f 100644 --- a/leaf-server/minecraft-patches/features/0157-Configurable-player-knockback-zombie.patch +++ b/leaf-server/minecraft-patches/features/0158-Configurable-player-knockback-zombie.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable player knockback zombie diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 0e1fb766570b5ff0e3c4a0f04c4ef3c589417322..4b3de5d5a1c29f8f2c62ef059e90614d0791d88b 100644 +index 534dd27d27395f9c98c62ea7014bb3a8df8caa2e..be774fafac70360ea9872ba74dd766619a98c00b 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -2018,6 +2018,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2079,6 +2079,8 @@ public abstract class LivingEntity extends Entity implements Attackable { } public void knockback(double strength, double x, double z, @Nullable Entity attacker, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause eventCause) { // Paper - knockback events @@ -17,7 +17,7 @@ index 0e1fb766570b5ff0e3c4a0f04c4ef3c589417322..4b3de5d5a1c29f8f2c62ef059e90614d strength *= 1.0 - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); if (true || !(strength <= 0.0)) { // CraftBukkit - Call event even when force is 0 // this.hasImpulse = true; // CraftBukkit - Move down -@@ -2048,6 +2050,20 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2109,6 +2111,20 @@ public abstract class LivingEntity extends Entity implements Attackable { } } diff --git a/leaf-server/minecraft-patches/features/0158-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch b/leaf-server/minecraft-patches/features/0159-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch similarity index 87% rename from leaf-server/minecraft-patches/features/0158-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch rename to leaf-server/minecraft-patches/features/0159-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch index 5f3ee49e..2304c2b5 100644 --- a/leaf-server/minecraft-patches/features/0158-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch +++ b/leaf-server/minecraft-patches/features/0159-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch @@ -8,10 +8,10 @@ Original project: https://github.com/PaperMC/Paper Paper pull request: https://github.com/PaperMC/Paper/pull/10990 diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index a1ecb7c5ee0e1fe1164e277d8991d6d990035f76..c3f659396fd7d01140f8038ea0acc4b4f10bded6 100644 +index 86d07d8f7c171a8930990ab02360e79066cad7d5..f138ce7c55bb5241b0c27874151183bfef983cce 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -206,6 +206,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -207,6 +207,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Override public void inactiveTick() { super.inactiveTick(); @@ -24,10 +24,10 @@ index a1ecb7c5ee0e1fe1164e277d8991d6d990035f76..c3f659396fd7d01140f8038ea0acc4b4 if (this.goalSelector.inactiveTick(this.activatedPriority, true) && !isThrottled) { // Pufferfish - pass activated priroity // Pufferfish - throttle inactive goal selector ticking this.goalSelector.tick(); diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index cb9c722251e01cbbd827af9aff5f5942c62d2011..8b96a2695d6cb62e8d38e429769bd7964241c002 100644 +index 530a7873a0796bb5e8e25b91586d6c4cfa00a08c..48384d7a9cb41506e0b5024baf806e56497e9d62 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -275,7 +275,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -374,7 +374,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler if (this.getUnhappyCounter() > 0) { this.setUnhappyCounter(this.getUnhappyCounter() - 1); } diff --git a/leaf-server/minecraft-patches/features/0159-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch b/leaf-server/minecraft-patches/features/0160-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch similarity index 92% rename from leaf-server/minecraft-patches/features/0159-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch rename to leaf-server/minecraft-patches/features/0160-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch index e4ecb525..73965a57 100644 --- a/leaf-server/minecraft-patches/features/0159-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch +++ b/leaf-server/minecraft-patches/features/0160-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch @@ -12,10 +12,10 @@ before spawning, it checks isSpawnPositionOk() for the position which loads the This patch ensures the chunk at the random location is loaded before trying to spawn the reinforcement zombie in it. diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index 39b65970a48568c95ff482b9636e7391f300ffa8..4395947fc8c719864ac2afde5e6bbb53da5129c2 100644 +index 783f8b9a05939b9f42fc77065f6347e3c6ddf8f5..1f32b1549cf9ab84fc338a86ee9eb1f0c014f879 100644 --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -353,6 +353,13 @@ public class Zombie extends Monster { +@@ -400,6 +400,13 @@ public class Zombie extends Monster { int i2 = floor1 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); int i3 = floor2 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); BlockPos blockPos = new BlockPos(i1, i2, i3); diff --git a/leaf-server/minecraft-patches/features/0160-PaperPR-Fix-some-beacon-event-issues.patch b/leaf-server/minecraft-patches/features/0161-PaperPR-Fix-some-beacon-event-issues.patch similarity index 92% rename from leaf-server/minecraft-patches/features/0160-PaperPR-Fix-some-beacon-event-issues.patch rename to leaf-server/minecraft-patches/features/0161-PaperPR-Fix-some-beacon-event-issues.patch index 318f32aa..d0fe3f5f 100644 --- a/leaf-server/minecraft-patches/features/0160-PaperPR-Fix-some-beacon-event-issues.patch +++ b/leaf-server/minecraft-patches/features/0161-PaperPR-Fix-some-beacon-event-issues.patch @@ -33,10 +33,10 @@ index 66eee067b4ffdd72393ca813de995062be5b7a90..52b24df965202a80e409d60484cff1a2 + // Paper end } diff --git a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bdf120291f52642ffa4266ac786bb2975b40bf10 100644 +index bc7b9d6faded66e95c38cfc5571b09c05af30deb..dc5e21981394c5607dabbc8afaa8f6097f94d90f 100644 --- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -@@ -162,6 +162,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -172,6 +172,8 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name return VALID_EFFECTS.contains(effect) ? effect : null; } @@ -45,7 +45,7 @@ index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bdf120291f52642ffa4266ac786bb297 public BeaconBlockEntity(BlockPos pos, BlockState blockState) { super(BlockEntityType.BEACON, pos, blockState); } -@@ -225,10 +227,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -237,10 +239,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name } } // Paper start - beacon activation/deactivation events @@ -63,7 +63,7 @@ index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bdf120291f52642ffa4266ac786bb297 org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); } -@@ -236,10 +243,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -248,10 +255,10 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name if (blockEntity.lastCheckY >= height) { blockEntity.lastCheckY = level.getMinY() - 1; @@ -76,7 +76,7 @@ index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bdf120291f52642ffa4266ac786bb297 if (!flag && flag1) { playSound(level, pos, SoundEvents.BEACON_ACTIVATE); -@@ -283,10 +290,6 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -295,10 +302,6 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @Override public void setRemoved() { @@ -87,7 +87,7 @@ index b77cdbf3e8cf0e9d66c9e5288ebae38c79dae1fe..bdf120291f52642ffa4266ac786bb297 // Paper start - fix MC-153086 if (this.levels > 0 && !this.beamSections.isEmpty()) { playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE); -@@ -414,6 +417,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name +@@ -426,6 +429,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name this.primaryPower = loadEffect(tag, "primary_effect"); this.secondaryPower = loadEffect(tag, "secondary_effect"); this.levels = tag.getIntOr("Levels", 0); // CraftBukkit - SPIGOT-5053, use where available diff --git a/leaf-server/minecraft-patches/features/0161-Dont-send-useless-entity-packets.patch b/leaf-server/minecraft-patches/features/0162-Dont-send-useless-entity-packets.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0161-Dont-send-useless-entity-packets.patch rename to leaf-server/minecraft-patches/features/0162-Dont-send-useless-entity-packets.patch diff --git a/leaf-server/minecraft-patches/features/0162-Multithreaded-Tracker.patch b/leaf-server/minecraft-patches/features/0163-Multithreaded-Tracker.patch similarity index 97% rename from leaf-server/minecraft-patches/features/0162-Multithreaded-Tracker.patch rename to leaf-server/minecraft-patches/features/0163-Multithreaded-Tracker.patch index f9525e16..e3e575e1 100644 --- a/leaf-server/minecraft-patches/features/0162-Multithreaded-Tracker.patch +++ b/leaf-server/minecraft-patches/features/0163-Multithreaded-Tracker.patch @@ -199,10 +199,10 @@ index 209a2b6a30d334fc4f6d0b1c02682db7f0b5e435..1489ecc2754901c6f30ec1b5ff0f324b attributesToSync.clear(); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 2c65987f7dda5b46a232a69e46b91090801fc246..0d73baebab6bdde6e279cc0da9c0ef8a275537ee 100644 +index d23ed8dbda5132337c8c96c67cf924e438ea9f4b..889b7e8752129dd3b5ba196c4b29449615499515 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2407,7 +2407,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2477,7 +2477,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public LevelEntityGetter getEntities() { @@ -212,10 +212,10 @@ index 2c65987f7dda5b46a232a69e46b91090801fc246..0d73baebab6bdde6e279cc0da9c0ef8a } diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6314831d7ecefa14be1386eced3ee50510ebe769..f1cdeb9c1f8eeb69870d17d5453a311358740625 100644 +index eba90724a6e5e8a93d775d3e0703a0b37a77e7e5..1692d243a147e927c910890bd168f2fc5b166e29 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1731,7 +1731,7 @@ public class ServerGamePacketListenerImpl +@@ -1811,7 +1811,7 @@ public class ServerGamePacketListenerImpl } public void internalTeleport(PositionMoveRotation posMoveRotation, Set relatives) { @@ -243,7 +243,7 @@ index 3ac9f36eae87369354e992a1d9b5c5b2d87d17cb..d99bbf299af2b2d3a61761c5c3c33c4d private boolean dirty = true; private double cachedValue; diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index 93a079df455e371a0ca7ada253dc8b7e16b0146f..fce4fa42dbec302b5c49c954d3286deea6f81d45 100644 +index 701025715e0aca3c1f920a66f9b3d03ec08eaf02..2b8b335cf5779d1b6eb639935d1b92d82aa85d7f 100644 --- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java +++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java @@ -14,11 +14,14 @@ import net.minecraft.nbt.ListTag; @@ -263,4 +263,4 @@ index 93a079df455e371a0ca7ada253dc8b7e16b0146f..fce4fa42dbec302b5c49c954d3286dee + // Leaf end - Multithreaded tracker private final AttributeSupplier supplier; private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations - + private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables diff --git a/leaf-server/minecraft-patches/features/0163-Nitori-Async-playerdata-Save.patch b/leaf-server/minecraft-patches/features/0164-Nitori-Async-playerdata-Save.patch similarity index 98% rename from leaf-server/minecraft-patches/features/0163-Nitori-Async-playerdata-Save.patch rename to leaf-server/minecraft-patches/features/0164-Nitori-Async-playerdata-Save.patch index 00575e3f..9eacd393 100644 --- a/leaf-server/minecraft-patches/features/0163-Nitori-Async-playerdata-Save.patch +++ b/leaf-server/minecraft-patches/features/0164-Nitori-Async-playerdata-Save.patch @@ -7,10 +7,10 @@ Original license: GPL v3 Original project: https://github.com/Gensokyo-Reimagined/Nitori diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 301b255d43a160b462e546ab894378cc38ae18e6..b74b58f6d110100c647ca4ffb9fbc8eb5c637dd9 100644 +index 18a0150536a847f9617a736245086d590bf80b74..10084fa3c0b8e1e6eaefc4fd733fc74ff295d588 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1055,6 +1055,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop PLAYER_AFFECTS_SPAWNING = (entity) -> { - return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning; @@ -20,10 +20,10 @@ index bfd58eb04eee606ac0a8071de9bf75f46c35decb..6ee502128da76a22bfc6e9bae813cd4c // Paper end - Affects Spawning API diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index 4395947fc8c719864ac2afde5e6bbb53da5129c2..a326483505245f6106b8ea72574bc2ab23f5402f 100644 +index 1f32b1549cf9ab84fc338a86ee9eb1f0c014f879..4c78db1ab0a588b57c31f23bcba01775e5008d1e 100644 --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -363,7 +363,7 @@ public class Zombie extends Monster { +@@ -410,7 +410,7 @@ public class Zombie extends Monster { if (SpawnPlacements.isSpawnPositionOk(type, level, blockPos) && SpawnPlacements.checkSpawnRules(type, level, EntitySpawnReason.REINFORCEMENT, blockPos, level.random)) { zombie.setPos(i1, i2, i3); @@ -33,20 +33,20 @@ index 4395947fc8c719864ac2afde5e6bbb53da5129c2..a326483505245f6106b8ea72574bc2ab && level.noCollision(zombie) && (zombie.canSpawnInLiquids() || !level.containsAnyLiquid(zombie.getBoundingBox()))) { diff --git a/net/minecraft/world/level/BaseSpawner.java b/net/minecraft/world/level/BaseSpawner.java -index 650ebce14d618076cec2066d134d2ae51a87076a..4137115888eeede519e10b87e520539b92eb75a8 100644 +index 0babc951d9fed6d32d3dba549cc5ced4dc6b0588..9fa9d84033c28071120e8a1c796ace4f9a45d4c5 100644 --- a/net/minecraft/world/level/BaseSpawner.java +++ b/net/minecraft/world/level/BaseSpawner.java -@@ -54,7 +54,7 @@ public abstract class BaseSpawner { - } +@@ -55,7 +55,7 @@ public abstract class BaseSpawner { public boolean isNearPlayer(Level level, BlockPos pos) { + if (level.purpurConfig.spawnerDeactivateByRedstone && level.hasNeighborSignal(pos)) return false; // Purpur - Redstone deactivates spawners - return level.hasNearbyAlivePlayerThatAffectsSpawning(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, this.requiredPlayerRange); // Paper - Affects Spawning API + return level.hasNearbyAlivePlayerThatAffectsSpawningForSpawner(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, this.requiredPlayerRange); // Paper - Affects Spawning API // Leaf - Optimize nearby alive players for spawning } public void clientTick(Level level, BlockPos pos) { diff --git a/net/minecraft/world/level/EntityGetter.java b/net/minecraft/world/level/EntityGetter.java -index 892a7c1eb1b321ca6d5ca709142e7feae1220815..3e3592e40950d54fd4b730442764b1de877ec9df 100644 +index 7719bc8ff1fbbc67cdf15e1fec28dc9233cea207..670860df81a3abfc1b8b53be505fce0ee32ee2c4 100644 --- a/net/minecraft/world/level/EntityGetter.java +++ b/net/minecraft/world/level/EntityGetter.java @@ -112,6 +112,89 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst diff --git a/leaf-server/minecraft-patches/features/0165-Cache-blockstate-cache-array.patch b/leaf-server/minecraft-patches/features/0166-Cache-blockstate-cache-array.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0165-Cache-blockstate-cache-array.patch rename to leaf-server/minecraft-patches/features/0166-Cache-blockstate-cache-array.patch