diff --git a/patches/api/0282-More-Enchantment-API.patch b/patches/api/0282-More-Enchantment-API.patch index bef111a629..e9b05a0fcf 100644 --- a/patches/api/0282-More-Enchantment-API.patch +++ b/patches/api/0282-More-Enchantment-API.patch @@ -7,12 +7,13 @@ Co-authored-by: Luis diff --git a/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java new file mode 100644 -index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14797d05b0 +index 0000000000000000000000000000000000000000..50c49739cc25679c9d241466e3069c9c232a22c4 --- /dev/null +++ b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java -@@ -0,0 +1,24 @@ +@@ -0,0 +1,25 @@ +package io.papermc.paper.enchantments; + ++@Deprecated(forRemoval = true, since = "As of 1.20.5 enchantments do not have a rarity.") +public enum EnchantmentRarity { + + COMMON(10), @@ -36,7 +37,7 @@ index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14 + } +} diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index 3375ce0f9ac50cd3f145291ceb587d4e6f72569c..a72202b653549b4074feb89748849fcb495ba0d4 100644 +index 3375ce0f9ac50cd3f145291ceb587d4e6f72569c..5e192105851436dbfe73a6e47c64bbb10e1ac41a 100644 --- a/src/main/java/org/bukkit/enchantments/Enchantment.java +++ b/src/main/java/org/bukkit/enchantments/Enchantment.java @@ -291,11 +291,7 @@ public abstract class Enchantment implements Keyed, Translatable, net.kyori.adve @@ -51,7 +52,7 @@ index 3375ce0f9ac50cd3f145291ceb587d4e6f72569c..a72202b653549b4074feb89748849fcb public abstract boolean isCursed(); /** -@@ -329,6 +325,84 @@ public abstract class Enchantment implements Keyed, Translatable, net.kyori.adve +@@ -329,6 +325,87 @@ public abstract class Enchantment implements Keyed, Translatable, net.kyori.adve * @return the name of the enchantment with {@code level} applied */ public abstract net.kyori.adventure.text.@NotNull Component displayName(int level); @@ -99,8 +100,11 @@ index 3375ce0f9ac50cd3f145291ceb587d4e6f72569c..a72202b653549b4074feb89748849fcb + * Gets the rarity of this enchantment. + * + * @return the rarity ++ * @deprecated As of 1.20.5 enchantments do not have a rarity. + */ + @NotNull ++ @Deprecated(forRemoval = true, since = "1.20.5") ++ @Contract("-> fail") + public abstract io.papermc.paper.enchantments.EnchantmentRarity getRarity(); + + /** diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index b924660ae0..27a292058c 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -1620,18 +1620,17 @@ index 0000000000000000000000000000000000000000..94a0a5850c97df08019c5b0f5d4e02a9 +} diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java new file mode 100644 -index 0000000000000000000000000000000000000000..0a7764797b0f1f346fb35f09377d5639bc382bff +index 0000000000000000000000000000000000000000..c7da1c8395244803872601bb95de95ad91c93e29 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -@@ -0,0 +1,39 @@ +@@ -0,0 +1,30 @@ +package io.papermc.paper.adventure; + +import com.mojang.datafixers.util.Pair; -+import java.util.function.Function; ++import com.mojang.serialization.JavaOps; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.ComponentSerializer; +import net.minecraft.network.chat.ComponentSerialization; -+import net.minecraft.util.JavaOps; + +final class WrapperAwareSerializer implements ComponentSerializer { + @Override @@ -1640,26 +1639,18 @@ index 0000000000000000000000000000000000000000..0a7764797b0f1f346fb35f09377d5639 + return ((AdventureComponent) input).adventure; + } + final Object obj = ComponentSerialization.CODEC.encodeStart(JavaOps.INSTANCE, input) -+ .get().map(Function.identity(), partial -> { -+ throw new RuntimeException("Failed to encode Minecraft Component: " + input + "; " + partial.message()); -+ }); ++ .getOrThrow(s -> new RuntimeException("Failed to encode Minecraft Component: " + input + "; " + s)); + final Pair converted = AdventureCodecs.COMPONENT_CODEC.decode(JavaOps.INSTANCE, obj) -+ .get().map(Function.identity(), partial -> { -+ throw new RuntimeException("Failed to decode to adventure Component: " + obj + "; " + partial.message()); -+ }); ++ .getOrThrow(s -> new RuntimeException("Failed to decode to adventure Component: " + obj + "; " + s)); + return converted.getFirst(); + } + + @Override + public net.minecraft.network.chat.Component serialize(final Component component) { + final Object obj = AdventureCodecs.COMPONENT_CODEC.encodeStart(JavaOps.INSTANCE, component) -+ .get().map(Function.identity(), partial -> { -+ throw new RuntimeException("Failed to encode adventure Component: " + component + "; " + partial.message()); -+ }); ++ .getOrThrow(s -> new RuntimeException("Failed to encode adventure Component: " + component + "; " + s)); + final Pair converted = ComponentSerialization.CODEC.decode(JavaOps.INSTANCE, obj) -+ .get().map(Function.identity(), partial -> { -+ throw new RuntimeException("Failed to decode to Minecraft Component: " + obj + "; " + partial.message()); -+ }); ++ .getOrThrow(s -> new RuntimeException("Failed to decode to Minecraft Component: " + obj + "; " + s)); + return converted.getFirst(); + } +} @@ -5598,10 +5589,10 @@ index 0000000000000000000000000000000000000000..3aedd0bbc97edacc1ebf71264b310e55 +} diff --git a/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java b/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..fdf9f95d6c65ba13108352c83d793b3a2126d69b +index 0000000000000000000000000000000000000000..ff9e3013e4f5049c6cfa35803676516dfe8b9af1 --- /dev/null +++ b/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java -@@ -0,0 +1,402 @@ +@@ -0,0 +1,399 @@ +package io.papermc.paper.adventure; + +import com.mojang.datafixers.util.Pair; @@ -5854,10 +5845,7 @@ index 0000000000000000000000000000000000000000..fdf9f95d6c65ba13108352c83d793b3a + } + + static R require(final DataResult result, final Function errorMessage) { -+ return switch (result) { -+ case final DataResult.Error error -> throw new RuntimeException(errorMessage.apply(error.message())); -+ case final DataResult.Success success -> success.value(); -+ }; ++ return result.getOrThrow(s -> new RuntimeException(errorMessage.apply(s))); + } + + static List invalidData() { diff --git a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch index 66e3d00971..6b16874a15 100644 --- a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -592,6 +592,32 @@ index 8390f5b5b957b5435efece26507a89756d0a7b3c..c6e8441e299f477ddb22c1ce26187107 } catch (Exception e) { } } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java +index 7d1c0810181c51ffa64f9a23b251e05c789870b0..09804513265e6db0c1f3501355335551100a36a8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java +@@ -4,14 +4,12 @@ import java.io.IOException; + import java.util.HashSet; + import java.util.List; + import java.util.Set; +-import jline.console.ConsoleReader; +-import jline.console.completer.CompletionHandler; + + /** + * SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it + * e.g. The user needs to press y / n to continue + */ +-public class TerminalCompletionHandler implements CompletionHandler { ++public class TerminalCompletionHandler /* implements CompletionHandler */ { /* Paper - comment out whole class + + private final TerminalConsoleWriterThread writerThread; + private final CompletionHandler delegate; +@@ -50,4 +48,5 @@ public class TerminalCompletionHandler implements CompletionHandler { + + return result; + } ++*/ // Paper end - comment out whole class + } diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java index 2e5101fca081548bb616bc5eaa0134698719b63a..6e4d50a4863d43a2d6a2d574350c74d0819df402 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java diff --git a/patches/server/0458-Add-PlayerShearBlockEvent.patch b/patches/server/0458-Add-PlayerShearBlockEvent.patch index 0f9033b27e..e212c2217b 100644 --- a/patches/server/0458-Add-PlayerShearBlockEvent.patch +++ b/patches/server/0458-Add-PlayerShearBlockEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add PlayerShearBlockEvent diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java -index ce108f1cea8027aa7aab444689f7a29f2e54cc20..7b311f60ceae9942eeee0d2c7a170278e5983f2d 100644 +index ce108f1cea8027aa7aab444689f7a29f2e54cc20..ef804067ee05870e9331237b44ca1ffeb8df99c7 100644 --- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java @@ -127,7 +127,7 @@ public class BeehiveBlock extends BaseEntityBlock { @@ -22,10 +22,10 @@ index ce108f1cea8027aa7aab444689f7a29f2e54cc20..7b311f60ceae9942eeee0d2c7a170278 if (stack.is(Items.SHEARS)) { + // Paper start - Add PlayerShearBlockEvent -+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>()); ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>()); + event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); + if (!event.callEvent()) { -+ return InteractionResult.PASS; ++ return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; + } + // Paper end world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); @@ -39,7 +39,7 @@ index ce108f1cea8027aa7aab444689f7a29f2e54cc20..7b311f60ceae9942eeee0d2c7a170278 flag = true; world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos); diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java -index aa8667f0b14dc8944dd3457b431162e59bf54ada..d52abece78866fb4202e54d21be8105261401d9b 100644 +index aa8667f0b14dc8944dd3457b431162e59bf54ada..3b94888516e4dd1a8e56c31fd71bb21f84b8cfbd 100644 --- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java @@ -40,10 +40,18 @@ public class PumpkinBlock extends Block { @@ -47,10 +47,10 @@ index aa8667f0b14dc8944dd3457b431162e59bf54ada..d52abece78866fb4202e54d21be81052 return ItemInteractionResult.sidedSuccess(world.isClientSide); } else { + // Paper start - Add PlayerShearBlockEvent -+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>()); ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>()); + event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); + if (!event.callEvent()) { -+ return ItemInteractionResult.PASS; ++ return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; + } + // Paper end - Add PlayerShearBlockEvent Direction direction = hit.getDirection(); diff --git a/patches/server/0553-More-Enchantment-API.patch b/patches/server/0553-More-Enchantment-API.patch index fdc9153965..5fa7b54c59 100644 --- a/patches/server/0553-More-Enchantment-API.patch +++ b/patches/server/0553-More-Enchantment-API.patch @@ -4,12 +4,12 @@ Date: Thu, 6 May 2021 19:57:58 -0700 Subject: [PATCH] More Enchantment API == AT == -public net.minecraft.world.item.enchantment.Enchantment slots +public net.minecraft.world.item.enchantment.Enchantment definition Co-authored-by: Luis diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index bb8a3e670924ebcce48669c5dce57e2df03fad77..58a24e149ae9500c9db90693ac9eb6446794535c 100644 +index bb8a3e670924ebcce48669c5dce57e2df03fad77..bb45dde0fd91796d5fd83a5fd20f5f1d5ad63ee7 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java @@ -71,7 +71,7 @@ public class CraftEnchantment extends Enchantment implements Handleable getActiveSlots() { -+ return java.util.stream.Stream.of(handle.slots).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); -+ } -+ -+ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { -+ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; -+ } -+ -+ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); ++ return java.util.stream.Stream.of(handle.definition.slots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); + } // Paper end @Override -diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..03a53ceb0dc3aaff7b5d10ec57f74d71be90ec3a ---- /dev/null -+++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.enchantments; -+ -+import net.minecraft.world.item.enchantment.Enchantment.Rarity; -+import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.junit.jupiter.api.Test; -+ -+import static org.junit.jupiter.api.Assertions.assertNotNull; -+ -+public class EnchantmentRarityTest { -+ -+ @Test -+ public void test() { -+ for (Rarity nmsRarity : Rarity.values()) { -+ // Will throw exception if a bukkit counterpart is not found -+ CraftEnchantment.fromNMSRarity(nmsRarity); -+ } -+ } -+} diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4ee48ef89f0e31a7bda4b04453fca8177874f540 diff --git a/patches/server/0578-Missing-Entity-API.patch b/patches/server/0578-Missing-Entity-API.patch index 5ef76ed856..12cad0f3e9 100644 --- a/patches/server/0578-Missing-Entity-API.patch +++ b/patches/server/0578-Missing-Entity-API.patch @@ -30,6 +30,8 @@ public net.minecraft.world.entity.animal.Rabbit moreCarrotTicks public net.minecraft.world.entity.AreaEffectCloud ownerUUID public net.minecraft.world.entity.animal.MushroomCow stewEffects public net.minecraft.world.entity.Entity FLAG_INVISIBLE +public net.minecraft.world.entity.animal.Cat setRelaxStateOne(Z)V +public net.minecraft.world.entity.animal.Cat isRelaxStateOne()Z Co-authored-by: Nassim Jahnke Co-authored-by: Jake Potrebic diff --git a/patches/server/0701-Fix-swamp-hut-cat-generation-deadlock.patch b/patches/server/0701-Fix-swamp-hut-cat-generation-deadlock.patch index 6bc7d4bda7..1b0f7d0ed5 100644 --- a/patches/server/0701-Fix-swamp-hut-cat-generation-deadlock.patch +++ b/patches/server/0701-Fix-swamp-hut-cat-generation-deadlock.patch @@ -10,7 +10,7 @@ indefinitely. Instead of using the world state, we use the already supplied ServerLevelAccessor which will always have the chunk available. diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index f3b0e5a97ad5d344741dfa3b7c864712c7ba8802..d2e273f58b4c9b65642980d3f47e01ae92166e46 100644 +index 951b7f252e67b29092964019bb3463cb00e497e3..b5f13d1bf1cccb9a15d8956f68c960e25098dc98 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java @@ -367,7 +367,7 @@ public class Cat extends TamableAnimal implements VariantHolder type.is(PoiTypes.NETHER_PORTAL), + (BlockPos pos) -> { -+ net.minecraft.world.level.chunk.ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.ChunkStatus.EMPTY); -+ if (!lowest.getStatus().isOrAfter(net.minecraft.world.level.chunk.ChunkStatus.FULL) -+ && (lowest.getBelowZeroRetrogen() == null || !lowest.getBelowZeroRetrogen().targetStatus().isOrAfter(net.minecraft.world.level.chunk.ChunkStatus.SPAWN))) { ++ net.minecraft.world.level.chunk.ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY); ++ if (!lowest.getStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.FULL) ++ && (lowest.getBelowZeroRetrogen() == null || !lowest.getBelowZeroRetrogen().targetStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN))) { + // why would we generate the chunk? + return false; + } diff --git a/patches/server/1016-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/1016-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index ad9608b3ae..0bc7d78d6a 100644 --- a/patches/server/1016-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/patches/server/1016-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -87,14 +87,13 @@ index a23dc2f8f4475de1ee35bf18a7a8a53233ccac12..226af44fd469053451a0403a95ffb446 this.used.set(start, start + size); } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f16573e58 100644 +index 27d3209275d621a211a82436667ba1a8eae605c7..9fdbea51d96e54b52b63de04f2845c62bfd0117a 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -53,6 +53,356 @@ public class RegionFile implements AutoCloseable { +@@ -52,6 +52,354 @@ public class RegionFile implements AutoCloseable { + @VisibleForTesting protected final RegionBitmap usedSectors; public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper - public final Path regionFile; // Paper -+ + // Paper start - Attempt to recalculate regionfile header if it is corrupt + private static long roundToSectors(long bytes) { + long sectors = bytes >>> 12; // 4096 = 2^12 @@ -153,15 +152,15 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + } + + private void backupRegionFile() { -+ Path backup = this.regionFile.getParent().resolve(this.regionFile.getFileName() + "." + new java.util.Random().nextLong() + ".backup"); ++ Path backup = this.path.getParent().resolve(this.path.getFileName() + "." + new java.util.Random().nextLong() + ".backup"); + this.backupRegionFile(backup); + } + + private void backupRegionFile(Path to) { + try { + this.file.force(true); -+ LOGGER.warn("Backing up regionfile \"" + this.regionFile.toAbsolutePath() + "\" to " + to.toAbsolutePath()); -+ java.nio.file.Files.copy(this.regionFile, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES); ++ LOGGER.warn("Backing up regionfile \"" + this.path.toAbsolutePath() + "\" to " + to.toAbsolutePath()); ++ java.nio.file.Files.copy(this.path, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES); + LOGGER.warn("Backed up the regionfile to " + to.toAbsolutePath()); + } catch (IOException ex) { + LOGGER.error("Failed to backup to " + to.toAbsolutePath(), ex); @@ -177,13 +176,13 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + if (!this.canRecalcHeader) { + return false; + } -+ ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.regionFile); ++ ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.path); + if (ourLowerLeftPosition == null) { -+ LOGGER.error("Unable to get chunk location of regionfile " + this.regionFile.toAbsolutePath() + ", cannot recover header"); ++ LOGGER.error("Unable to get chunk location of regionfile " + this.path.toAbsolutePath() + ", cannot recover header"); + return false; + } + synchronized (this) { -+ LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.regionFile.toAbsolutePath(), new Throwable()); ++ LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.path.toAbsolutePath(), new Throwable()); + + // try to backup file so maybe it could be sent to us for further investigation + @@ -207,7 +206,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + + ChunkPos chunkPos = ChunkSerializer.getChunkCoordinate(compound); + if (!inSameRegionfile(ourLowerLeftPosition, chunkPos)) { -+ LOGGER.error("Ignoring absolute chunk " + chunkPos + " in regionfile as it is not contained in the bounds of the regionfile '" + this.regionFile.toAbsolutePath() + "'. It should be in regionfile (" + (chunkPos.x >> 5) + "," + (chunkPos.z >> 5) + ")"); ++ LOGGER.error("Ignoring absolute chunk " + chunkPos + " in regionfile as it is not contained in the bounds of the regionfile '" + this.path.toAbsolutePath() + "'. It should be in regionfile (" + (chunkPos.x >> 5) + "," + (chunkPos.z >> 5) + ")"); + continue; + } + int location = (chunkPos.x & 31) | ((chunkPos.z & 31) << 5); @@ -229,7 +228,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + isAikarOversized = true; + } + } catch (Exception ex) { -+ LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.regionFile.toAbsolutePath() + ", oversized data for this chunk will be lost", ex); ++ LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.path.toAbsolutePath() + ", oversized data for this chunk will be lost", ex); + // fall through, if we can't read aikar oversized we can't risk corrupting chunk data + } + } @@ -337,7 +336,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + if (newSectorAllocations.tryAllocate(sectorOffset, sectorLength)) { + calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized + } else { -+ LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath() + ", chunk will be regenerated"); ++ LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + ", chunk will be regenerated"); + } + } + } @@ -361,7 +360,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized + } catch (IOException ex) { + newSectorAllocations.free(sectorOffset, sectorLength); -+ LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath() + " will be regenerated"); ++ LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + " will be regenerated"); + } + } + } @@ -383,7 +382,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + try { + this.writeOversizedMeta(); + } catch (Exception ex) { -+ LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.regionFile.toAbsolutePath(), ex); ++ LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.path.toAbsolutePath(), ex); + Files.deleteIfExists(this.getOversizedMetaFile()); + } + } else { @@ -394,7 +393,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + + // before we overwrite the old sectors, print a summary of the chunks that got changed. + -+ LOGGER.info("Starting summary of changes for regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.info("Starting summary of changes for regionfile " + this.path.toAbsolutePath()); + + for (int chunkX = 0; chunkX < 32; ++chunkX) { + for (int chunkZ = 0; chunkZ < 32; ++chunkZ) { @@ -411,16 +410,16 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + + if (oldOffset == 0) { + // found lost data -+ LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath()); + } else if (newOffset == 0) { -+ LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.regionFile.toAbsolutePath() + ", it will be regenerated"); ++ LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.path.toAbsolutePath() + ", it will be regenerated"); + } else { -+ LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.path.toAbsolutePath()); + } + } + } + -+ LOGGER.info("End of change summary for regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.info("End of change summary for regionfile " + this.path.toAbsolutePath()); + + // simply destroy the timestamp header, it's not used + @@ -432,9 +431,9 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + try { + this.flush(); + this.file.force(true); // try to ensure it goes through... -+ LOGGER.info("Successfully wrote new header to disk for regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.info("Successfully wrote new header to disk for regionfile " + this.path.toAbsolutePath()); + } catch (IOException ex) { -+ LOGGER.error("Failed to write new header to disk for regionfile " + this.regionFile.toAbsolutePath(), ex); ++ LOGGER.error("Failed to write new header to disk for regionfile " + this.path.toAbsolutePath(), ex); + } + } + @@ -443,11 +442,10 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + + final boolean canRecalcHeader; // final forces compile fail on new constructor + // Paper end - Attempt to recalculate regionfile header if it is corrupt -+ // Paper start - Cache chunk status - private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32]; + private final net.minecraft.world.level.chunk.status.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.status.ChunkStatus[32 * 32]; -@@ -80,8 +430,18 @@ public class RegionFile implements AutoCloseable { +@@ -79,8 +427,18 @@ public class RegionFile implements AutoCloseable { public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException { this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format } @@ -464,9 +462,9 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + this.canRecalcHeader = canRecalcHeader; + // Paper end - add can recalc flag this.header = ByteBuffer.allocateDirect(8192); - this.regionFile = file; // Paper initOversizedState(); // Paper -@@ -112,14 +472,16 @@ public class RegionFile implements AutoCloseable { + this.usedSectors = new RegionBitmap(); +@@ -110,14 +468,16 @@ public class RegionFile implements AutoCloseable { RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i); } @@ -488,7 +486,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f // Spigot start if (j1 == 255) { // We're maxed out, so we need to read the proper length from the section -@@ -128,21 +490,66 @@ public class RegionFile implements AutoCloseable { +@@ -126,21 +486,66 @@ public class RegionFile implements AutoCloseable { j1 = (realLen.getInt(0) + 4) / 4096 + 1; } // Spigot end @@ -513,12 +511,12 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + // Paper start - recalculate header on header corruption + if (offset < 2 || sectorLength <= 0 || ((long)offset * 4096L) > regionFileSize) { + if (canRecalcHeader) { -+ LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() + "! Recalculating header..."); ++ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() + "! Recalculating header..."); + needsHeaderRecalc = true; + break; + } else { + // location = chunkX | (chunkZ << 5); -+ LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() + ++ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() + + "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); + if (!hasBackedUp) { + hasBackedUp = true; @@ -531,11 +529,11 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + } + boolean failedToAllocate = !this.usedSectors.tryAllocate(offset, sectorLength); + if (failedToAllocate) { -+ LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.regionFile.toAbsolutePath()); ++ LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.path.toAbsolutePath()); } + if (failedToAllocate & !canRecalcHeader) { + // location = chunkX | (chunkZ << 5); -+ LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() + ++ LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() + + "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header"); + if (!hasBackedUp) { + hasBackedUp = true; @@ -552,14 +550,14 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f + // Paper start - recalculate header on header corruption + // we move the recalc here so comparison to old header is correct when logging to console + if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues -+ LOGGER.error("Recalculating regionfile " + this.regionFile.toAbsolutePath() + ", header gave erroneous offsets & locations"); ++ LOGGER.error("Recalculating regionfile " + this.path.toAbsolutePath() + ", header gave erroneous offsets & locations"); + this.recalculateHeader(); + } + // Paper end } } -@@ -153,11 +560,36 @@ public class RegionFile implements AutoCloseable { +@@ -151,11 +556,36 @@ public class RegionFile implements AutoCloseable { } private Path getExternalChunkPath(ChunkPos chunkPos) { @@ -597,7 +595,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f @Nullable public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException { int i = this.getOffset(pos); -@@ -181,6 +613,11 @@ public class RegionFile implements AutoCloseable { +@@ -179,6 +609,11 @@ public class RegionFile implements AutoCloseable { ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error if (bytebuffer.remaining() < 5) { RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{pos, l, bytebuffer.remaining()}); @@ -609,7 +607,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f return null; } else { int i1 = bytebuffer.getInt(); -@@ -188,6 +625,11 @@ public class RegionFile implements AutoCloseable { +@@ -186,6 +621,11 @@ public class RegionFile implements AutoCloseable { if (i1 == 0) { RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", pos); @@ -621,7 +619,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f return null; } else { int j1 = i1 - 1; -@@ -195,18 +637,45 @@ public class RegionFile implements AutoCloseable { +@@ -193,18 +633,45 @@ public class RegionFile implements AutoCloseable { if (RegionFile.isExternalStreamChunk(b0)) { if (j1 != 0) { RegionFile.LOGGER.warn("Chunk has both internal and external streams"); @@ -669,7 +667,7 @@ index 36cdf165334c4d7c1ca28ba42b1006b163e45a95..6e8c488ed05495237e06e44005d3656f } } } -@@ -392,10 +861,15 @@ public class RegionFile implements AutoCloseable { +@@ -390,10 +857,15 @@ public class RegionFile implements AutoCloseable { } private ByteBuffer createExternalStub() { diff --git a/patches/server/1019-Collision-optimisations.patch b/patches/server/1019-Collision-optimisations.patch index da5d66cae5..d017c63f57 100644 --- a/patches/server/1019-Collision-optimisations.patch +++ b/patches/server/1019-Collision-optimisations.patch @@ -105,7 +105,7 @@ index be668387f65a633c6ac497fca632a4767a1bf3a2..e08f4e39db4ee3fed62e37364d17dcc5 } diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java new file mode 100644 -index 0000000000000000000000000000000000000000..ee0331a6bc40cdde08d926fd8eb1dc642630c2e5 +index 0000000000000000000000000000000000000000..ee8e9c0e3690e78f3cc621ddfca89ea4256d4803 --- /dev/null +++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java @@ -0,0 +1,1851 @@ @@ -127,7 +127,7 @@ index 0000000000000000000000000000000000000000..ee0331a6bc40cdde08d926fd8eb1dc64 +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.material.FluidState; diff --git a/patches/server/1023-Add-Alternate-Current-redstone-implementation.patch b/patches/server/1023-Add-Alternate-Current-redstone-implementation.patch index fffcd9e0ed..f2c62489a6 100644 --- a/patches/server/1023-Add-Alternate-Current-redstone-implementation.patch +++ b/patches/server/1023-Add-Alternate-Current-redstone-implementation.patch @@ -22,7 +22,7 @@ Alternate Current's wire handler. diff --git a/src/main/java/alternate/current/wire/LevelHelper.java b/src/main/java/alternate/current/wire/LevelHelper.java new file mode 100644 -index 0000000000000000000000000000000000000000..7d60b8b6dd7f3a2878e75c78f329bc4158c80aec +index 0000000000000000000000000000000000000000..8b4697421d57f81ff1794c6f845258e10df91622 --- /dev/null +++ b/src/main/java/alternate/current/wire/LevelHelper.java @@ -0,0 +1,66 @@ @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..7d60b8b6dd7f3a2878e75c78f329bc41 +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; -+import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.LevelChunkSection; + +public class LevelHelper {