diff --git a/patches/api/Zombie-API-breaking-doors.patch b/patches/api/Zombie-API-breaking-doors.patch index 43c86121c1..3410e92483 100644 --- a/patches/api/Zombie-API-breaking-doors.patch +++ b/patches/api/Zombie-API-breaking-doors.patch @@ -33,7 +33,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * no effect. + * + * @return true if entity supports breaking doors ++ * @deprecated Since 1.21.2 all zombie types can break doors if instructed as MC-137053 was fixed. + */ ++ @Deprecated(since = "1.21.2", forRemoval = true) + boolean supportsBreakingDoors(); // Paper end } diff --git a/patches/server/API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/server/API-to-get-Material-from-Boats-and-Minecarts.patch index bd516cb2f0..c0f482c7bf 100644 --- a/patches/server/API-to-get-Material-from-Boats-and-Minecarts.patch +++ b/patches/server/API-to-get-Material-from-Boats-and-Minecarts.patch @@ -3,6 +3,8 @@ From: Madeline Miller Date: Thu, 31 Dec 2020 12:48:19 +1000 Subject: [PATCH] API to get Material from Boats and Minecarts +== AT == +public net.minecraft.world.entity.vehicle.AbstractBoat getDropItem()Lnet/minecraft/world/item/Item; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -26,11 +28,8 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/sr index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - +@@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.entity; import net.minecraft.world.entity.vehicle.AbstractMinecart; -+import net.minecraft.world.item.Items; // Paper import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.Material; // Paper @@ -44,16 +43,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override + public Material getMinecartMaterial() { -+ net.minecraft.world.item.Item minecartItem = switch (getHandle().getMinecartType()) { -+ case CHEST -> Items.CHEST_MINECART; -+ case FURNACE -> Items.FURNACE_MINECART; -+ case TNT -> Items.TNT_MINECART; -+ case HOPPER -> Items.HOPPER_MINECART; -+ case COMMAND_BLOCK -> Items.COMMAND_BLOCK_MINECART; -+ case RIDEABLE, SPAWNER -> Items.MINECART; -+ }; ++ return CraftMagicNumbers.getMaterial(minecartEntityTypeToMaterial(this.getHandle().getType())); ++ } + -+ return CraftMagicNumbers.getMaterial(minecartItem); ++ static net.minecraft.world.item.Item minecartEntityTypeToMaterial(final net.minecraft.world.entity.EntityType type) { ++ if (type == net.minecraft.world.entity.EntityType.MINECART) return net.minecraft.world.item.Items.MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.CHEST_MINECART) return net.minecraft.world.item.Items.CHEST_MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.FURNACE_MINECART) return net.minecraft.world.item.Items.FURNACE_MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.SPAWNER_MINECART) return net.minecraft.world.item.Items.MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.COMMAND_BLOCK_MINECART) return net.minecraft.world.item.Items.COMMAND_BLOCK_MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.HOPPER_MINECART) return net.minecraft.world.item.Items.HOPPER_MINECART; ++ else if (type == net.minecraft.world.entity.EntityType.TNT_MINECART) return net.minecraft.world.item.Items.TNT_MINECART; ++ else throw new UnsupportedOperationException("Server implementation is missing minecart material binding for entity type " + type.toShortString()); + } + // Paper end + diff --git a/patches/server/Add-Shearable-API.patch b/patches/server/Add-Shearable-API.patch index cf13d83e87..90aff682c4 100644 --- a/patches/server/Add-Shearable-API.patch +++ b/patches/server/Add-Shearable-API.patch @@ -14,7 +14,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.sound.Sound; ++import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Shearable; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; + +public interface PaperShearable extends io.papermc.paper.entity.Shearable { @@ -28,9 +31,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + default void shear(@NotNull Sound.Source source) { -+ this.getHandle().shear(PaperAdventure.asVanilla(source)); ++ if (!(this.getHandle().level() instanceof final ServerLevel serverLevel)) return; ++ this.getHandle().shear(serverLevel, PaperAdventure.asVanilla(source), new ItemStack(Items.SHEARS)); + } +} +diff --git a/src/main/java/net/minecraft/world/entity/Shearable.java b/src/main/java/net/minecraft/world/entity/Shearable.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Shearable.java ++++ b/src/main/java/net/minecraft/world/entity/Shearable.java +@@ -0,0 +0,0 @@ public interface Shearable { + void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears); + + boolean readyForShearing(); ++ net.minecraft.world.level.Level level(); // Shearable API - expose default level needed for shearing. + } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java diff --git a/patches/server/Add-drops-to-shear-events.patch b/patches/server/Add-drops-to-shear-events.patch index fc3356a780..07752d4eed 100644 --- a/patches/server/Add-drops-to-shear-events.patch +++ b/patches/server/Add-drops-to-shear-events.patch @@ -37,6 +37,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 void shear(ServerLevel world, SoundSource shearedSoundCategory, ItemStack shears); boolean readyForShearing(); + net.minecraft.world.level.Level level(); // Shearable API - expose default level needed for shearing. ++ + // Paper start - custom shear drops; ensure all implementing entities override this + default java.util.List generateDefaultDrops(final ServerLevel serverLevel, final ItemStack shears) { + return java.util.Collections.emptyList(); diff --git a/patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch b/patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch index ca4f3b8051..1e888cc0e2 100644 --- a/patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch +++ b/patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch @@ -15,14 +15,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override + public boolean isFuel(ItemStack stack) { -+ return stack != null && !stack.getType().isEmpty() && AbstractFurnaceBlockEntity.isFuel(CraftItemStack.asNMSCopy(stack)); ++ net.minecraft.server.level.ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld) org.bukkit.Bukkit.getWorlds().get(0)).getHandle(); ++ return stack != null && !stack.getType().isEmpty() && world.fuelValues().isFuel(CraftItemStack.asNMSCopy(stack)); + } + + @Override + public boolean canSmelt(ItemStack stack) { + // data packs are always loaded in the main world + net.minecraft.server.level.ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld) org.bukkit.Bukkit.getWorlds().get(0)).getHandle(); -+ return stack != null && !stack.getType().isEmpty() && world.getRecipeManager().getRecipeFor(((AbstractFurnaceBlockEntity) this.inventory).recipeType, new net.minecraft.world.item.crafting.SingleRecipeInput(CraftItemStack.asNMSCopy(stack)), world).isPresent(); ++ return stack != null && !stack.getType().isEmpty() && world.recipeAccess().getRecipeFor(((AbstractFurnaceBlockEntity) this.inventory).recipeType, new net.minecraft.world.item.crafting.SingleRecipeInput(CraftItemStack.asNMSCopy(stack)), world).isPresent(); + } + // Paper end + diff --git a/patches/server/Fix-NPE-on-Boat-getStatus.patch b/patches/server/Fix-NPE-on-Boat-getStatus.patch index fa701d1ca6..99cec0c66c 100644 --- a/patches/server/Fix-NPE-on-Boat-getStatus.patch +++ b/patches/server/Fix-NPE-on-Boat-getStatus.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix NPE on Boat getStatus Boat status is null until the entity is added to the world and the tick() method is called. == AT == -public net.minecraft.world.entity.vehicle.Boat getStatus()Lnet/minecraft/world/entity/vehicle/Boat$Status; +public net.minecraft.world.entity.vehicle.AbstractBoat getStatus()Lnet/minecraft/world/entity/vehicle/AbstractBoat$Status; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Status getStatus() { + // Paper start - Fix NPE on Boat getStatus -+ final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle(); ++ final net.minecraft.world.entity.vehicle.AbstractBoat handle = this.getHandle(); + if (handle.status == null) { + if (handle.valid) { + // Don't actually set the status because it would skew the old status check in the next tick diff --git a/patches/server/Furnace-RecipesUsed-API.patch b/patches/server/Furnace-RecipesUsed-API.patch index f01e10c040..69eedb4cee 100644 --- a/patches/server/Furnace-RecipesUsed-API.patch +++ b/patches/server/Furnace-RecipesUsed-API.patch @@ -10,34 +10,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java @@ -0,0 +0,0 @@ public abstract class CraftFurnace extends snapshot.cookSpeedMultiplier = multiplier; - snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot.recipeType, snapshot, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier + snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot, snapshot.recipeType, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier } + + @Override + public int getRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) { -+ return this.getSnapshot().getRecipesUsed().getInt(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe)); ++ return this.getSnapshot().recipesUsed.getInt(io.papermc.paper.util.MCUtil.toResourceKey(net.minecraft.core.registries.Registries.RECIPE, furnaceRecipe)); + } + + @Override + public boolean hasRecipeUsedCount(org.bukkit.NamespacedKey furnaceRecipe) { -+ return this.getSnapshot().getRecipesUsed().containsKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe)); ++ return this.getSnapshot().recipesUsed.containsKey(io.papermc.paper.util.MCUtil.toResourceKey(net.minecraft.core.registries.Registries.RECIPE, furnaceRecipe)); + } + + @Override + public void setRecipeUsedCount(org.bukkit.inventory.CookingRecipe furnaceRecipe, int count) { -+ final net.minecraft.resources.ResourceLocation location = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(furnaceRecipe.getKey()); -+ java.util.Optional> nmsRecipe = (this.isPlaced() ? this.world.getHandle().getRecipeManager() : net.minecraft.server.MinecraftServer.getServer().getRecipeManager()).byKey(location); ++ final var location = io.papermc.paper.util.MCUtil.toResourceKey(net.minecraft.core.registries.Registries.RECIPE, furnaceRecipe.getKey()); ++ java.util.Optional> nmsRecipe = (this.isPlaced() ? this.world.getHandle().recipeAccess() : net.minecraft.server.MinecraftServer.getServer().getRecipeManager()).byKey(location); + com.google.common.base.Preconditions.checkArgument(nmsRecipe.isPresent() && nmsRecipe.get().value() instanceof net.minecraft.world.item.crafting.AbstractCookingRecipe, furnaceRecipe.getKey() + " is not recognized as a valid and registered furnace recipe"); + if (count > 0) { -+ this.getSnapshot().getRecipesUsed().put(location, count); ++ this.getSnapshot().recipesUsed.put(location, count); + } else { -+ this.getSnapshot().getRecipesUsed().removeInt(location); ++ this.getSnapshot().recipesUsed.removeInt(location); + } + } + + @Override + public void setRecipesUsed(java.util.Map, Integer> recipesUsed) { -+ this.getSnapshot().getRecipesUsed().clear(); ++ this.getSnapshot().recipesUsed.clear(); + recipesUsed.forEach((recipe, integer) -> { + if (integer != null) { + this.setRecipeUsedCount(recipe, integer); diff --git a/patches/server/Implement-furnace-cook-speed-multiplier-API.patch b/patches/server/Implement-furnace-cook-speed-multiplier-API.patch index 179cc10ef0..8a37c4487f 100644 --- a/patches/server/Implement-furnace-cook-speed-multiplier-API.patch +++ b/patches/server/Implement-furnace-cook-speed-multiplier-API.patch @@ -6,6 +6,9 @@ Subject: [PATCH] Implement furnace cook speed multiplier API Fixed an issue where a furnace's cook-speed multiplier rounds down to the nearest Integer when updating its current cook time. +== AT == +public net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I + Co-authored-by: Eric Su diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java @@ -79,9 +82,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return fuelRegistry.burnDuration(stack); } -- private static int getTotalCookTime(ServerLevel world, AbstractFurnaceBlockEntity furnace) { +- public static int getTotalCookTime(ServerLevel world, AbstractFurnaceBlockEntity furnace) { - if (world == null) return 200; // CraftBukkit - SPIGOT-4302 -+ private static int getTotalCookTime(@Nullable ServerLevel world, AbstractFurnaceBlockEntity furnace, RecipeType recipeType, double cookSpeedMultiplier) { // Paper - cook speed multiplier API ++ public static int getTotalCookTime(@Nullable ServerLevel world, AbstractFurnaceBlockEntity furnace, RecipeType recipeType, double cookSpeedMultiplier) { // Paper - cook speed multiplier API SingleRecipeInput singlerecipeinput = new SingleRecipeInput(furnace.getItem(0)); - return (Integer) furnace.quickCheck.getRecipeFor(singlerecipeinput, world).map((recipeholder) -> { @@ -130,7 +133,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); + T snapshot = this.getSnapshot(); + snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot.recipeType, snapshot, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier ++ snapshot.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.isPlaced() ? this.world.getHandle() : null, snapshot, snapshot.recipeType, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier + } + // Paper end } diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch index cd42279d8b..25073ec42d 100644 --- a/patches/server/MC-Utils.patch +++ b/patches/server/MC-Utils.patch @@ -4098,11 +4098,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.function.Supplier; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; ++import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Waitable; + +public final class MCUtil { @@ -4256,6 +4259,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void scheduleAsyncTask(Runnable run) { + asyncExecutor.execute(run); + } ++ ++ public static ResourceKey toResourceKey( ++ final ResourceKey> registry, ++ final NamespacedKey namespacedKey ++ ) { ++ return ResourceKey.create(registry, CraftNamespacedKey.toMinecraft(namespacedKey)); ++ } ++ ++ public static NamespacedKey fromResourceKey(final ResourceKey key) { ++ return CraftNamespacedKey.fromMinecraft(key.location()); ++ } +} diff --git a/src/main/java/io/papermc/paper/util/StackWalkerUtil.java b/src/main/java/io/papermc/paper/util/StackWalkerUtil.java new file mode 100644 diff --git a/patches/server/More-Projectile-API.patch b/patches/server/More-Projectile-API.patch index 051904e3fd..91bc85e3a1 100644 --- a/patches/server/More-Projectile-API.patch +++ b/patches/server/More-Projectile-API.patch @@ -17,6 +17,7 @@ public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage public net.minecraft.world.entity.projectile.Arrow NO_EFFECT_COLOR public net.minecraft.world.entity.projectile.Projectile hasBeenShot public net.minecraft.world.entity.projectile.Projectile leftOwner +public net.minecraft.world.entity.projectile.Projectile ownerUUID public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z public net.minecraft.world.entity.projectile.FireworkRocketEntity getDefaultItem()Lnet/minecraft/world/item/ItemStack; diff --git a/patches/server/Zombie-API-breaking-doors.patch b/patches/server/Zombie-API-breaking-doors.patch index 66593978ac..40e2aa4203 100644 --- a/patches/server/Zombie-API-breaking-doors.patch +++ b/patches/server/Zombie-API-breaking-doors.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public boolean supportsBreakingDoors() { -+ return getHandle().supportsBreakDoorGoal(); ++ return true; // All zombies are now capable of breaking doors, see https://bugs.mojang.com/browse/MC-137053 + } // Paper end