diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch index eb9a50bc6a..2b80fc3b43 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -29,14 +29,24 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { -@@ -110,9 +123,39 @@ +@@ -65,6 +78,8 @@ + protected final ContainerData dataAccess; + public final Reference2IntOpenHashMap>> recipesUsed; + private final RecipeManager.CachedCheck quickCheck; ++ public final RecipeType recipeType; // Paper - cook speed multiplier API ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + + protected AbstractFurnaceBlockEntity(BlockEntityType blockEntityType, BlockPos pos, BlockState state, RecipeType recipeType) { + super(blockEntityType, pos, state); +@@ -110,8 +125,39 @@ } }; this.recipesUsed = new Reference2IntOpenHashMap(); - this.quickCheck = RecipeManager.createCheck(recipeType); + this.quickCheck = RecipeManager.createCheck((RecipeType) recipeType); // CraftBukkit - decompile error // Eclipse fail ++ this.recipeType = recipeType; // Paper - cook speed multiplier API } - ++ + // CraftBukkit start - add fields and methods + private int maxStack = MAX_STACK; + public List transaction = new java.util.ArrayList(); @@ -66,11 +76,30 @@ + this.maxStack = size; + } + // CraftBukkit end -+ + private boolean isLit() { return this.litTimeRemaining > 0; +@@ -135,6 +181,11 @@ + this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(s)), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed multiplier API ++ if (nbt.contains("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = nbt.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end - cook speed multiplier API } -@@ -175,7 +218,7 @@ + + @Override +@@ -144,6 +195,7 @@ + nbt.putShort("cooking_total_time", (short) this.cookingTotalTime); + nbt.putShort("lit_time_remaining", (short) this.litTimeRemaining); + nbt.putShort("lit_total_time", (short) this.litTotalTime); ++ nbt.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerHelper.saveAllItems(nbt, this.items, registries); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -175,7 +227,7 @@ RecipeHolder recipeholder; if (flag2) { @@ -79,7 +108,7 @@ } else { recipeholder = null; } -@@ -183,9 +226,20 @@ +@@ -183,9 +235,20 @@ int i = blockEntity.getMaxStackSize(); if (!blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) { @@ -102,7 +131,7 @@ flag1 = true; if (flag3) { Item item = itemstack.getItem(); -@@ -199,11 +253,23 @@ +@@ -199,11 +262,23 @@ } if (blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) { @@ -111,7 +140,7 @@ + CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0)); + CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); + -+ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, pos), source, recipe); ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, pos), source, recipe, AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity, blockEntity.recipeType, blockEntity.cookSpeedMultiplier)); // Paper - cook speed multiplier API + world.getCraftServer().getPluginManager().callEvent(event); + + blockEntity.cookingTotalTime = event.getTotalCookTime(); @@ -119,15 +148,17 @@ + // CraftBukkit end + ++blockEntity.cookingTimer; - if (blockEntity.cookingTimer == blockEntity.cookingTotalTime) { +- if (blockEntity.cookingTimer == blockEntity.cookingTotalTime) { ++ if (blockEntity.cookingTimer >= blockEntity.cookingTotalTime) { // Paper - cook speed multiplier API blockEntity.cookingTimer = 0; - blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity); +- blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity); - if (AbstractFurnaceBlockEntity.burn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) { ++ blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity, blockEntity.recipeType, blockEntity.cookSpeedMultiplier); // Paper - cook speed multiplier API + if (AbstractFurnaceBlockEntity.burn(blockEntity.level, blockEntity.worldPosition, world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) { // CraftBukkit blockEntity.setRecipeUsed(recipeholder); } -@@ -242,20 +308,47 @@ +@@ -242,20 +317,47 @@ } } @@ -183,15 +214,40 @@ } itemstack.shrink(1); -@@ -270,6 +363,7 @@ +@@ -269,12 +371,14 @@ + return fuelRegistry.burnDuration(stack); } - public static int getTotalCookTime(ServerLevel world, AbstractFurnaceBlockEntity furnace) { -+ if (world == null) return 200; // CraftBukkit - SPIGOT-4302 +- public static int getTotalCookTime(ServerLevel world, AbstractFurnaceBlockEntity furnace) { ++ 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) -> { -@@ -358,19 +452,19 @@ +- return (Integer) furnace.quickCheck.getRecipeFor(singlerecipeinput, world).map((recipeholder) -> { +- return ((AbstractCookingRecipe) recipeholder.value()).cookingTime(); +- }).orElse(200); ++ // Paper start - cook speed multiplier API ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = world != null ? furnace.quickCheck.getRecipeFor(singlerecipeinput, world).map(holder -> holder.value().cookingTime()).orElse(200) : (net.minecraft.server.MinecraftServer.getServer().getRecipeManager().getRecipeFor(recipeType, singlerecipeinput, world /* passing a null level here is safe. world is only used for map extending recipes which won't happen here */).map(holder -> holder.value().cookingTime()).orElse(200)); ++ return (int) Math.ceil (cookTime / cookSpeedMultiplier); ++ // Paper end - cook speed multiplier API + } + + @Override +@@ -320,12 +424,11 @@ + if (world instanceof ServerLevel) { + ServerLevel worldserver = (ServerLevel) world; + +- this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(worldserver, this); ++ this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(worldserver, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API + this.cookingTimer = 0; + this.setChanged(); + } + } +- + } + + @Override +@@ -358,19 +461,19 @@ } @Override @@ -216,7 +272,7 @@ } } -@@ -378,30 +472,47 @@ +@@ -378,30 +481,47 @@ } public List> getRecipesToAwardAndPopExperience(ServerLevel world, Vec3 pos) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java index 7a642b1b95..fd2f28ee78 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java @@ -88,4 +88,20 @@ public abstract class CraftFurnace extends @Override public abstract CraftFurnace copy(Location location); + + // Paper start - cook speed multiplier API + @Override + public double getCookSpeedMultiplier() { + return this.getSnapshot().cookSpeedMultiplier; + } + + @Override + public void setCookSpeedMultiplier(double multiplier) { + com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); + 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, snapshot.recipeType, snapshot.cookSpeedMultiplier); // Update the snapshot's current total cook time to scale with the newly set multiplier + } + // Paper end }