diff --git a/patches/server/Add-predicate-for-blocks-when-raytracing.patch b/patches/server/Add-predicate-for-blocks-when-raytracing.patch index 5d310d368c..e5b6e3308c 100644 --- a/patches/server/Add-predicate-for-blocks-when-raytracing.patch +++ b/patches/server/Add-predicate-for-blocks-when-raytracing.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 BlockState iblockdata = this.getBlockStateIfLoaded(blockposition); if (iblockdata == null) { @@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor { - return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + return BlockHitResult.miss(raytrace1.getTo(), Direction.getApproximateNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); } // Paper end - Prevent raytrace from loading chunks - if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases diff --git a/patches/server/Add-various-missing-EntityDropItemEvent-calls.patch b/patches/server/Add-various-missing-EntityDropItemEvent-calls.patch index d2e2b82cf6..7271c8c7d9 100644 --- a/patches/server/Add-various-missing-EntityDropItemEvent-calls.patch +++ b/patches/server/Add-various-missing-EntityDropItemEvent-calls.patch @@ -13,11 +13,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 entityitem.setDefaultPickUpDelay(); + // Paper start - Call EntityDropItemEvent -+ return this.spawnAtLocation(entityitem); ++ return this.spawnAtLocation(world, entityitem); + } + } + @Nullable -+ public ItemEntity spawnAtLocation(ItemEntity entityitem) { ++ public ItemEntity spawnAtLocation(ServerLevel world, ItemEntity entityitem) { + { + // Paper end - Call EntityDropItemEvent // CraftBukkit start diff --git a/patches/server/Don-t-lookup-fluid-state-when-raytracing-skip-air-bl.patch b/patches/server/Don-t-lookup-fluid-state-when-raytracing-skip-air-bl.patch index 8f0158784e..3dd17d2f04 100644 --- a/patches/server/Don-t-lookup-fluid-state-when-raytracing-skip-air-bl.patch +++ b/patches/server/Don-t-lookup-fluid-state-when-raytracing-skip-air-bl.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/BlockGetter.java +++ b/src/main/java/net/minecraft/world/level/BlockGetter.java @@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor { - return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + return BlockHitResult.miss(raytrace1.getTo(), Direction.getApproximateNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); } // Paper end - Prevent raytrace from loading chunks - FluidState fluid = this.getFluidState(blockposition); diff --git a/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch index 3d07807e84..689633d71a 100644 --- a/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch +++ b/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch @@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ int i = worldserver.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); + if (i <= 0 && this.level().paperConfig().collisions.maxEntityCollisions <= 0) { + return; + } diff --git a/patches/server/Fix-item-duplication-and-teleport-issues.patch b/patches/server/Fix-item-duplication-and-teleport-issues.patch index ba0f38abbb..147862446e 100644 --- a/patches/server/Fix-item-duplication-and-teleport-issues.patch +++ b/patches/server/Fix-item-duplication-and-teleport-issues.patch @@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - Fix item duplication and teleport issues + if (!this.isAlive() || !this.valid) { -+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + teleportTarget.newLevel() + ":" + teleportTarget.pos(), new Throwable()); ++ LOGGER.warn("Illegal Entity Teleport " + this + " to " + teleportTarget.newLevel() + ":" + teleportTarget.position(), new Throwable()); + return null; + } + // Paper end - Fix item duplication and teleport issues diff --git a/patches/server/Fix-missing-map-initialize-event-call.patch b/patches/server/Fix-missing-map-initialize-event-call.patch index 0f518827c5..f381913044 100644 --- a/patches/server/Fix-missing-map-initialize-event-call.patch +++ b/patches/server/Fix-missing-map-initialize-event-call.patch @@ -21,22 +21,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - Call missing map initialize event and set id + final DimensionDataStorage storage = this.getServer().overworld().getDataStorage(); + -+ final net.minecraft.world.level.saveddata.SavedData existing = storage.cache.get(id.key()); -+ if (existing == null && !storage.cache.containsKey(id.key())) { -+ final MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key()); -+ storage.cache.put(id.key(), worldmap); -+ if (worldmap != null) { ++ final Optional cacheEntry = storage.cache.get(id.key()); ++ if (cacheEntry == null) { // Cache did not contain, try to load and may init ++ final MapItemSavedData worldmap = storage.get(MapItemSavedData.factory(), id.key()); // get populates the cache ++ if (worldmap != null) { // map was read, init it and return + worldmap.id = id; + new MapInitializeEvent(worldmap.mapView).callEvent(); + return worldmap; + } -+ } else if (existing instanceof MapItemSavedData mapItemSavedData) { -+ mapItemSavedData.id = id; ++ ++ return null; // Map does not exist, reading failed. } - return worldmap; - // CraftBukkit end + -+ return existing instanceof MapItemSavedData data ? data : null; ++ // Cache entry exists, update it with the id ref and return. ++ if (cacheEntry.orElse(null) instanceof final MapItemSavedData mapItemSavedData) { ++ mapItemSavedData.id = id; ++ return mapItemSavedData; ++ } ++ ++ return null; + // Paper end - Call missing map initialize event and set id } diff --git a/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch index 61e38264c6..11b55680e0 100644 --- a/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch +++ b/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper start - remove player from map on drop -+ if (itemstack.getItem() == Items.FILLED_MAP) { ++ if (itemstack.getItem() == net.minecraft.world.item.Items.FILLED_MAP) { + net.minecraft.world.level.saveddata.maps.MapItemSavedData worldmap = net.minecraft.world.item.MapItem.getSavedData(itemstack, this.level()); + if (worldmap != null) { + worldmap.tickCarriedBy(this, itemstack); diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch index 99d892a1c0..2ddc0869d7 100644 --- a/patches/server/MC-Utils.patch +++ b/patches/server/MC-Utils.patch @@ -4991,7 +4991,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void scheduleOnMain(Runnable runnable) { + // postToMainThread does not work the same as older versions of mc + // This method is actually used to create a TickTask, which can then be posted onto main -+ this.tell(this.wrapRunnable(runnable)); ++ this.schedule(this.wrapRunnable(runnable)); + } + // Paper end diff --git a/patches/server/More-Teleport-API.patch b/patches/server/More-Teleport-API.patch index c4ce1b2cb8..23712d79ce 100644 --- a/patches/server/More-Teleport-API.patch +++ b/patches/server/More-Teleport-API.patch @@ -162,23 +162,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }; + } + -+ public static net.minecraft.world.entity.RelativeMovement toNmsRelativeFlag(io.papermc.paper.entity.TeleportFlag.Relative apiFlag) { ++ public static net.minecraft.world.entity.Relative toNmsRelativeFlag(io.papermc.paper.entity.TeleportFlag.Relative apiFlag) { + return switch (apiFlag) { -+ case X -> net.minecraft.world.entity.RelativeMovement.X; -+ case Y -> net.minecraft.world.entity.RelativeMovement.Y; -+ case Z -> net.minecraft.world.entity.RelativeMovement.Z; -+ case PITCH -> net.minecraft.world.entity.RelativeMovement.X_ROT; -+ case YAW -> net.minecraft.world.entity.RelativeMovement.Y_ROT; ++ case X -> net.minecraft.world.entity.Relative.X; ++ case Y -> net.minecraft.world.entity.Relative.Y; ++ case Z -> net.minecraft.world.entity.Relative.Z; ++ case PITCH -> net.minecraft.world.entity.Relative.X_ROT; ++ case YAW -> net.minecraft.world.entity.Relative.Y_ROT; + }; + } + -+ public static io.papermc.paper.entity.TeleportFlag.Relative toApiRelativeFlag(net.minecraft.world.entity.RelativeMovement nmsFlag) { ++ public static io.papermc.paper.entity.TeleportFlag.Relative toApiRelativeFlag(net.minecraft.world.entity.Relative nmsFlag) { + return switch (nmsFlag) { + case X -> io.papermc.paper.entity.TeleportFlag.Relative.X; + case Y -> io.papermc.paper.entity.TeleportFlag.Relative.Y; + case Z -> io.papermc.paper.entity.TeleportFlag.Relative.Z; + case X_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.PITCH; + case Y_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.YAW; ++ default -> throw new RuntimeException("not yet"); // TODO figure out what to do with new flags + }; + } + @@ -258,7 +259,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (fromWorld == toWorld) { - entity.connection.teleport(to); + // Paper start - Teleport API -+ final Set nms = java.util.EnumSet.noneOf(net.minecraft.world.entity.RelativeMovement.class); ++ final Set nms = java.util.EnumSet.noneOf(net.minecraft.world.entity.Relative.class); + for (final io.papermc.paper.entity.TeleportFlag.Relative bukkit : relativeArguments) { + nms.add(toNmsRelativeFlag(bukkit)); + } diff --git a/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch b/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch index 65b35a5ac8..41eaa05582 100644 --- a/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch +++ b/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch @@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); + // Paper start - option to use the dimension_type to check if spawners should be added. I imagine mojang will add some datapack-y way of managing this in the future. + final List spawners; -+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.useDimensionTypeForCustomSpawners && this.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).getResourceKey(worlddimension.type().value()).orElseThrow() == net.minecraft.world.level.dimension.BuiltinDimensionTypes.OVERWORLD) { ++ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.useDimensionTypeForCustomSpawners && this.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE).getResourceKey(worlddimension.type().value()).orElseThrow() == net.minecraft.world.level.dimension.BuiltinDimensionTypes.OVERWORLD) { + spawners = list; + } else { + spawners = Collections.emptyList(); diff --git a/patches/server/Prevent-various-interactions-from-causing-chunk-load.patch b/patches/server/Prevent-various-interactions-from-causing-chunk-load.patch index e39a522af9..05f7d54b87 100644 --- a/patches/server/Prevent-various-interactions-from-causing-chunk-load.patch +++ b/patches/server/Prevent-various-interactions-from-causing-chunk-load.patch @@ -91,7 +91,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // copied the last function parameter (listed below) + Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); + -+ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getApproximateNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + } + // Paper end - Prevent raytrace from loading chunks FluidState fluid = this.getFluidState(blockposition); diff --git a/patches/server/Remap-fixes.patch b/patches/server/Remap-fixes.patch index 452337873c..2abac08787 100644 --- a/patches/server/Remap-fixes.patch +++ b/patches/server/Remap-fixes.patch @@ -73,6 +73,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private ContextKeySet paramSet; private Optional randomSequence; +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 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +@@ -0,0 +0,0 @@ public abstract class CraftBoat extends CraftVehicle implements Boat { + throw new EnumConstantNotPresentException(Type.class, boatType.toString()); + } + +- public static Status boatStatusFromNms(net.minecraft.world.entity.vehicle.Boat.EnumStatus enumStatus) { ++ public static Status boatStatusFromNms(net.minecraft.world.entity.vehicle.AbstractBoat.Status enumStatus) { // Paper - remap fixes + return switch (enumStatus) { + default -> throw new EnumConstantNotPresentException(Status.class, enumStatus.name()); + case IN_AIR -> Status.IN_AIR; diff --git a/src/test/java/org/bukkit/DyeColorsTest.java b/src/test/java/org/bukkit/DyeColorsTest.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/DyeColorsTest.java diff --git a/patches/server/Restore-vanilla-entity-drops-behavior.patch b/patches/server/Restore-vanilla-entity-drops-behavior.patch index 94e3f2e739..3f8277df30 100644 --- a/patches/server/Restore-vanilla-entity-drops-behavior.patch +++ b/patches/server/Restore-vanilla-entity-drops-behavior.patch @@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } } - if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false + if (this.shouldDropLoot() && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) this.dropFromLootTable(this.serverLevel(), damageSource, this.lastHurtByPlayerTime > 0); - this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag); @@ -86,7 +86,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - entityitem.setDefaultPickUpDelay(); + entityitem.setDefaultPickUpDelay(); // Paper - diff on change (in dropConsumer) // Paper start - Call EntityDropItemEvent - return this.spawnAtLocation(entityitem); + return this.spawnAtLocation(world, entityitem); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Timings-v2.patch b/patches/server/Timings-v2.patch index 4b4ff32c9a..fbfd090076 100644 --- a/patches/server/Timings-v2.patch +++ b/patches/server/Timings-v2.patch @@ -1076,14 +1076,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } this.level.timings.doChunkUnload.startTiming(); // Spigot -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - gameprofilerfiller.pop(); - this.clearCache(); - } -+ if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper - - private void tickChunks() { - long i = this.level.getGameTime(); @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { LevelChunk chunk = playerchunk.getTickingChunk(); diff --git a/patches/server/fix-player-loottables-running-when-mob-loot-gamerule.patch b/patches/server/fix-player-loottables-running-when-mob-loot-gamerule.patch index ae84af00a7..bc23853543 100644 --- a/patches/server/fix-player-loottables-running-when-mob-loot-gamerule.patch +++ b/patches/server/fix-player-loottables-running-when-mob-loot-gamerule.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } } -+ if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false ++ if (this.shouldDropLoot() && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) this.dropFromLootTable(this.serverLevel(), damageSource, this.lastHurtByPlayerTime > 0); this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag); diff --git a/patches/server/prevent-unintended-light-block-manipulation.patch b/patches/server/prevent-unintended-light-block-manipulation.patch index b4f79ca15d..d3f4082f68 100644 --- a/patches/server/prevent-unintended-light-block-manipulation.patch +++ b/patches/server/prevent-unintended-light-block-manipulation.patch @@ -8,14 +8,24 @@ diff --git a/src/main/java/net/minecraft/world/level/block/LightBlock.java b/src index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/LightBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LightBlock.java +@@ -0,0 +0,0 @@ import java.util.function.ToIntFunction; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.component.DataComponents; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; @@ -0,0 +0,0 @@ public class LightBlock extends Block implements SimpleWaterloggedBlock { builder.add(LEVEL, WATERLOGGED); } + // Paper start - prevent unintended light block manipulation + @Override -+ protected net.minecraft.world.ItemInteractionResult useItemOn(final ItemStack stack, final BlockState state, final Level world, final BlockPos pos, final Player player, final net.minecraft.world.InteractionHand hand, final BlockHitResult hit) { -+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; } // Paper - Prevent unintended light block manipulation ++ protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ if (player.getItemInHand(hand).getItem() != Items.LIGHT || (world instanceof final ServerLevel serverLevel && !player.mayInteract(serverLevel, pos)) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.InteractionResult.PASS; } // Paper - Prevent unintended light block manipulation + return super.useItemOn(stack, state, world, pos, player, hand, hit); + } + // Paper end - prevent unintended light block manipulation