diff --git a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch index 7c2a37e7c7..347b99d45a 100644 --- a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch +++ b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType); + return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror(); + } -+ // Paper end ++ // Paper end - old getSpawnEgg API } diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Add-Raw-Byte-Entity-Serialization.patch b/patches/server/Add-Raw-Byte-Entity-Serialization.patch index 6091477f4c..d733ea533d 100644 --- a/patches/server/Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/server/Add-Raw-Byte-Entity-Serialization.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.passengers = ImmutableList.copyOf(pass); + return result; + } -+ // Paper end ++ // Paper end - Entity serialization api public boolean save(CompoundTag nbt) { return this.isPassenger() ? false : this.saveAsPassenger(nbt); } diff --git a/patches/server/Add-back-EntityPortalExitEvent.patch b/patches/server/Add-back-EntityPortalExitEvent.patch index 0b46d5061a..f79fd54d6a 100644 --- a/patches/server/Add-back-EntityPortalExitEvent.patch +++ b/patches/server/Add-back-EntityPortalExitEvent.patch @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + pitch = event.getTo().getPitch(); + velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter()); + } -+ // Paper end ++ // Paper end - Call EntityPortalExitEvent if (worldserver == this.level) { // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in this.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); @@ -43,8 +43,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 entity.restoreFrom(this); - entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); - entity.setDeltaMovement(shapedetectorshape.speed); -+ entity.moveTo(position.x, position.y, position.z, yaw, pitch); // Paper - use EntityPortalExitEvent values -+ entity.setDeltaMovement(velocity); // Paper - use EntityPortalExitEvent values ++ entity.moveTo(position.x, position.y, position.z, yaw, pitch); // Paper - EntityPortalExitEvent ++ entity.setDeltaMovement(velocity); // Paper - EntityPortalExitEvent // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned if (this.inWorld) { worldserver.addDuringTeleport(entity); diff --git a/patches/server/Add-critical-damage-API.patch b/patches/server/Add-critical-damage-API.patch index 695f942bf7..6f126a2a3f 100644 --- a/patches/server/Add-critical-damage-API.patch +++ b/patches/server/Add-critical-damage-API.patch @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.critical = critical; + return this; + } -+ // Paper end ++ // Paper end - add critical damage API } diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; -+ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API - conflict on change ++ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API; diff on change flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper flag2 = flag2 && !this.isSprinting(); diff --git a/patches/server/Add-methods-to-find-targets-for-lightning-strikes.patch b/patches/server/Add-methods-to-find-targets-for-lightning-strikes.patch index 38dd03945d..3c84f33228 100644 --- a/patches/server/Add-methods-to-find-targets-for-lightning-strikes.patch +++ b/patches/server/Add-methods-to-find-targets-for-lightning-strikes.patch @@ -14,11 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } protected BlockPos findLightningTargetAround(BlockPos pos) { -+ // Paper start ++ // Paper start - Add methods to find targets for lightning strikes + return this.findLightningTargetAround(pos, false); + } + public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) { -+ // Paper end ++ // Paper end - Add methods to find targets for lightning strikes BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos); Optional optional = this.findLightningRod(blockposition1); @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!list.isEmpty()) { return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition(); } else { -+ if (returnNullWhenNoTarget) return null; // Paper ++ if (returnNullWhenNoTarget) return null; // Paper - Add methods to find targets for lightning strikes if (blockposition1.getY() == this.getMinBuildHeight() - 1) { blockposition1 = blockposition1.above(2); } @@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return (LightningStrike) lightning.getBukkitEntity(); } -+ // Paper start ++ // Paper start - Add methods to find targets for lightning strikes + @Override + public Location findLightningRod(Location location) { + return this.world.findLightningRod(io.papermc.paper.util.MCUtil.toBlockPosition(location)) @@ -53,7 +53,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final BlockPos pos = this.world.findLightningTargetAround(io.papermc.paper.util.MCUtil.toBlockPosition(location), true); + return pos == null ? null : io.papermc.paper.util.MCUtil.toLocation(this.world, pos); + } -+ // Paper end ++ // Paper end - Add methods to find targets for lightning strikes + @Override public boolean generateTree(Location loc, TreeType type) { diff --git a/patches/server/Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch b/patches/server/Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch index b2bb16996a..8797bfff39 100644 --- a/patches/server/Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch +++ b/patches/server/Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public final class CraftServer implements Server { @Override public int getSpawnLimit(SpawnCategory spawnCategory) { - // Paper start + // Paper start - Add mobcaps commands + Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); + Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory." + spawnCategory + " does not have a spawn limit."); return this.getSpawnLimitUnsafe(spawnCategory); diff --git a/patches/server/Add-more-advancement-API.patch b/patches/server/Add-more-advancement-API.patch index 5ee1886c32..47911d1564 100644 --- a/patches/server/Add-more-advancement-API.patch +++ b/patches/server/Add-more-advancement-API.patch @@ -91,7 +91,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final boolean hidden; private float x; private float y; -+ public final io.papermc.paper.advancement.AdvancementDisplay paper = new io.papermc.paper.advancement.PaperAdvancementDisplay(this); // Paper ++ public final io.papermc.paper.advancement.AdvancementDisplay paper = new io.papermc.paper.advancement.PaperAdvancementDisplay(this); // Paper - Add more advancement API public DisplayInfo(ItemStack icon, Component title, Component description, Optional background, AdvancementType frame, boolean showToast, boolean announceToChat, boolean hidden) { this.title = title; @@ -103,7 +103,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return Collections.unmodifiableCollection(this.handle.value().criteria().keySet()); } -+ // Paper start ++ // Paper start - Add more advancement API @Override - public AdvancementDisplay getDisplay() { - if (this.handle.value().display().isEmpty()) { @@ -149,7 +149,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final net.minecraft.advancements.AdvancementNode advancementNode = net.minecraft.server.MinecraftServer.getServer().getAdvancements().tree().get(this.handle); + return java.util.Objects.requireNonNull(advancementNode, "could not find internal advancement node for advancement " + this.handle.id()).root().holder().toBukkit(); } -+ // Paper end ++ // Paper end - Add more advancement API } diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch index dba30578d1..56f3f3be59 100644 --- a/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch +++ b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch @@ -264,7 +264,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 world.getProfiler().pop(); } -+ // Paper start ++ // Paper start - Add mobcaps commands + public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) { + final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category)); + if (categoryLimit < 1) { @@ -272,7 +272,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return categoryLimit * spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; + } -+ // Paper end ++ // Paper end - Add mobcaps commands + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { // Paper start - add parameters and int ret type @@ -285,11 +285,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public int getSpawnLimit(SpawnCategory spawnCategory) { -+ // Paper start ++ // Paper start - Add mobcaps commands + return this.getSpawnLimitUnsafe(spawnCategory); + } + public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) { -+ // Paper end ++ // Paper end - Add mobcaps commands return this.spawnCategoryLimit.getOrDefault(spawnCategory, -1); } @@ -301,7 +301,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -+ // Paper start ++ // Paper start - Add mobcaps commands + return this.getSpawnLimitUnsafe(spawnCategory); + } + public final int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) { @@ -309,7 +309,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (limit < 0) { - limit = this.server.getSpawnLimit(spawnCategory); + limit = this.server.getSpawnLimitUnsafe(spawnCategory); -+ // Paper end ++ // Paper end - Add mobcaps commands } return limit; } diff --git a/patches/server/Add-root-admin-user-detection.patch b/patches/server/Add-root-admin-user-detection.patch index c07fa8ea3f..c22a83f66a 100644 --- a/patches/server/Add-root-admin-user-detection.patch +++ b/patches/server/Add-root-admin-user-detection.patch @@ -72,7 +72,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + DedicatedServer.LOGGER.warn("FOR MORE INFORMATION, SEE https://madelinemiller.dev/blog/root-minecraft-server/"); + DedicatedServer.LOGGER.warn("****************************"); + } -+ // Paper end ++ // Paper end - detect running as root + DedicatedServer.LOGGER.info("Loading properties"); DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties(); diff --git a/patches/server/Add-support-for-Proxy-Protocol.patch b/patches/server/Add-support-for-Proxy-Protocol.patch index 840540e9f9..9ce365d16b 100644 --- a/patches/server/Add-support-for-Proxy-Protocol.patch +++ b/patches/server/Add-support-for-Proxy-Protocol.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java @@ -0,0 +0,0 @@ public class ServerConnectionListener { ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); - // Paper end + // Paper end - Use Velocity cipher + // Paper start - Add support for proxy protocol + if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.proxyProtocol) { diff --git a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index 816b86f218..62acc818e8 100644 --- a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import org.slf4j.Logger; public class ChunkSerializer { -+ // Paper start ++ // Paper start - Attempt to recalculate regionfile header if it is corrupt + // TODO: Check on update + public static long getLastWorldSaveTime(CompoundTag chunkData) { + final int dataVersion = ChunkStorage.getVersion(chunkData); @@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return chunkData.getLong("LastUpdate"); + } + } -+ // Paper end ++ // Paper end - Attempt to recalculate regionfile header if it is corrupt public static final Codec> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null); // Paper - Anti-Xray - Add preset block states private static final Logger LOGGER = LogUtils.getLogger(); @@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start - async chunk io // remove IO worker - this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker -+ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - nuke IOWorker // Paper ++ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - nuke IOWorker // Paper - Attempt to recalculate regionfile header if it is corrupt // Paper end - async chunk io } @@ -62,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public class RegionBitmap { private final BitSet used = new BitSet(); -+ // Paper start ++ // Paper start - Attempt to recalculate regionfile header if it is corrupt + public final void copyFrom(RegionBitmap other) { + BitSet thisBitset = this.used; + BitSet otherBitset = other.used; @@ -81,7 +81,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + bitset.set(from, from + length); + return true; + } -+ // Paper end ++ // Paper end - Attempt to recalculate regionfile header if it is corrupt + public void force(int start, int size) { this.used.set(start, start + size); @@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper public final Path regionFile; // Paper -+ // Paper start - try to recover from RegionFile header corruption ++ // Paper start - Attempt to recalculate regionfile header if it is corrupt + private static long roundToSectors(long bytes) { + long sectors = bytes >>> 12; // 4096 = 2^12 + long remainingBytes = bytes & 4095; @@ -441,7 +441,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + final boolean canRecalcHeader; // final forces compile fail on new constructor -+ // Paper end ++ // 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]; diff --git a/patches/server/Check-requirement-before-suggesting-root-nodes.patch b/patches/server/Check-requirement-before-suggesting-root-nodes.patch index b607a78939..dd71c9ea50 100644 --- a/patches/server/Check-requirement-before-suggesting-root-nodes.patch +++ b/patches/server/Check-requirement-before-suggesting-root-nodes.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } catch (final CommandSyntaxException ignored) { } + } -+ // Paper end ++ // Paper end - Don't suggest if the requirement isn't met futures[i++] = future; } diff --git a/patches/server/Configurable-feature-seeds.patch b/patches/server/Configurable-feature-seeds.patch index 75151bd30b..c1990b98d1 100644 --- a/patches/server/Configurable-feature-seeds.patch +++ b/patches/server/Configurable-feature-seeds.patch @@ -27,14 +27,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 }; - seededrandom.setFeatureSeed(i, l1, l); -+ // Paper start - change populationSeed used in random ++ // Paper start - Configurable feature seeds; change populationSeed used in random + long featurePopulationSeed = i; + final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig().featureSeeds.features.getLong(placedfeature.feature()); + if (configFeatureSeed != -1) { + featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above + } + seededrandom.setFeatureSeed(featurePopulationSeed, l1, l); -+ // Paper end ++ // Paper end - Configurable feature seeds try { generatoraccessseed.setCurrentlyGenerating(supplier1); diff --git a/patches/server/Do-not-run-close-logic-for-inventories-on-chunk-unlo.patch b/patches/server/Do-not-run-close-logic-for-inventories-on-chunk-unlo.patch index b2567950ac..caf279afbd 100644 --- a/patches/server/Do-not-run-close-logic-for-inventories-on-chunk-unlo.patch +++ b/patches/server/Do-not-run-close-logic-for-inventories-on-chunk-unlo.patch @@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + ((org.bukkit.craftbukkit.entity.CraftHumanEntity)h).getHandle().closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper } -+ // Paper end ++ // Paper end - this area looks like it can load chunks, change the behavior } } // Spigot End diff --git a/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch b/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch index f01e20cd03..db53abdddf 100644 --- a/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch +++ b/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start private boolean check(ServerChunkCache cps, int x, int z) { -+ if (true) return true; // Paper - this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full" ++ if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full" ChunkPos pos = new ChunkPos(x, z); if (cps != null) { //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe diff --git a/patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server/Ensure-Entity-position-and-AABB-are-never-invalid.patch similarity index 57% rename from patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch rename to patches/server/Ensure-Entity-position-and-AABB-are-never-invalid.patch index fd1190643f..4bde5c4148 100644 --- a/patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch +++ b/patches/server/Ensure-Entity-position-and-AABB-are-never-invalid.patch @@ -1,8 +1,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid +Subject: [PATCH] Ensure Entity position and AABB are never invalid +Co-authored-by: Spottedleaf diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -14,20 +15,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void setPos(double x, double y, double z) { - this.setPosRaw(x, y, z); - this.setBoundingBox(this.makeBoundingBox()); -+ this.setPosRaw(x, y, z, true); // Paper - force bounding box update -+ // this.setBoundingBox(this.makeBoundingBox()); // Paper - move into setPositionRaw ++ this.setPosRaw(x, y, z, true); // Paper - Block invalid positions and bounding box; force update ++ // this.setBoundingBox(this.makeBoundingBox()); // Paper - Block invalid positions and bounding box; move into setPosRaw } protected AABB makeBoundingBox() { @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * widthScale); } ++ // Paper start - Block invalid positions and bounding box ++ public static boolean checkPosition(Entity entity, double newX, double newY, double newZ) { ++ if (Double.isFinite(newX) && Double.isFinite(newY) && Double.isFinite(newZ)) { ++ return true; ++ } ++ ++ String entityInfo; ++ try { ++ entityInfo = entity.toString(); ++ } catch (Exception ex) { ++ entityInfo = "[Entity info unavailable] "; ++ } ++ LOGGER.error("New entity position is invalid! Tried to set invalid position ({},{},{}) for entity {} located at {}, entity info: {}", newX, newY, newZ, entity.getClass().getName(), entity.position, entityInfo, new Throwable()); ++ return false; ++ } public final void setPosRaw(double x, double y, double z) { -+ // Paper start + this.setPosRaw(x, y, z, false); + } + public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { -+ // Paper end ++ if (!checkPosition(this, x, y, z)) { ++ return; ++ } ++ // Paper end - Block invalid positions and bounding box // Paper start - rewrite chunk system if (this.updatingSectionStatus) { LOGGER.error("Refusing to update position for entity " + this + " to position " + new Vec3(x, y, z) + " since it is processing a section status update", new Throwable()); @@ -35,12 +54,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.levelCallback.onMove(); } -+ // Paper start - never allow AABB to become desynced from position ++ // Paper start - Block invalid positions and bounding box; don't allow desync of pos and AABB + // hanging has its own special logic + if (!(this instanceof net.minecraft.world.entity.decoration.HangingEntity) && (forceBoundingBoxUpdate || this.position.x != x || this.position.y != y || this.position.z != z)) { + this.setBoundingBox(this.makeBoundingBox()); + } -+ // Paper end ++ // Paper end - Block invalid positions and bounding box } public void checkDespawn() {} diff --git a/patches/server/Ensure-valid-vehicle-status.patch b/patches/server/Ensure-valid-vehicle-status.patch index 8ddfb224da..66a8610ccf 100644 --- a/patches/server/Ensure-valid-vehicle-status.patch +++ b/patches/server/Ensure-valid-vehicle-status.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { -+ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper - Ensure valid vehicle status // CraftBukkit end CompoundTag nbttagcompound2 = new CompoundTag(); CompoundTag nbttagcompound3 = new CompoundTag(); diff --git a/patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch b/patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch index c23593a552..dc1f620729 100644 --- a/patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch +++ b/patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void place(TreeDecorator.Context generator) { -+ if (generator.logs().isEmpty()) return; // Paper ++ if (generator.logs().isEmpty()) return; // Paper - Fix crash when trying to generate without logs RandomSource randomSource = generator.random(); if (!(randomSource.nextFloat() >= this.probability)) { List list = generator.logs(); diff --git a/patches/server/Fix-GameProfileCache-concurrency.patch b/patches/server/Fix-GameProfileCache-concurrency.patch index 66e2ff69e6..29dc8cf15e 100644 --- a/patches/server/Fix-GameProfileCache-concurrency.patch +++ b/patches/server/Fix-GameProfileCache-concurrency.patch @@ -14,10 +14,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Nullable private Executor executor; -+ // Paper start ++ // Paper start - Fix GameProfileCache concurrency + protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock(); + protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock(); -+ // Paper end ++ // Paper end - Fix GameProfileCache concurrency + public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) { this.profileRepository = profileRepository; @@ -26,13 +26,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } private void safeAdd(GameProfileCache.GameProfileInfo entry) { -+ try { this.stateLock.lock(); // Paper - allow better concurrency ++ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency GameProfile gameprofile = entry.getProfile(); entry.setLastAccess(this.getNextOperation()); this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), entry); this.profilesByUUID.put(gameprofile.getId(), entry); -+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency ++ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency } private static Optional lookupGameProfile(GameProfileRepository repository, String name) { @@ -40,20 +40,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start public @Nullable GameProfile getProfileIfCached(String name) { -+ try { this.stateLock.lock(); // Paper - allow better concurrency ++ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); if (entry == null) { return null; } entry.setLastAccess(this.getNextOperation()); return entry.getProfile(); -+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency ++ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency } // Paper end public Optional get(String name) { String s1 = name.toLowerCase(Locale.ROOT); -+ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - allow better concurrency ++ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); boolean flag = false; @@ -61,12 +61,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (usercache_usercacheentry != null) { usercache_usercacheentry.setLastAccess(this.getNextOperation()); optional = Optional.of(usercache_usercacheentry.getProfile()); -+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency ++ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency } else { -+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency -+ try { this.lookupLock.lock(); // Paper - allow better concurrency ++ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency ++ try { this.lookupLock.lock(); // Paper - Fix GameProfileCache concurrency optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // CraftBukkit - use correct case for offline players -+ } finally { this.lookupLock.unlock(); } // Paper - allow better concurrency ++ } finally { this.lookupLock.unlock(); } // Paper - Fix GameProfileCache concurrency if (optional.isPresent()) { this.add((GameProfile) optional.get()); flag = false; @@ -74,7 +74,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } return optional; -+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - allow better concurrency ++ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - Fix GameProfileCache concurrency } public CompletableFuture> getAsync(String username) { @@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public Optional get(UUID uuid) { -+ try { this.stateLock.lock(); // Paper - allow better concurrency ++ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); if (usercache_usercacheentry == null) { @@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 usercache_usercacheentry.setLastAccess(this.getNextOperation()); return Optional.of(usercache_usercacheentry.getProfile()); } -+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency ++ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency } public void setExecutor(Executor executor) { @@ -99,7 +99,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 DateFormat dateformat = GameProfileCache.createDateFormat(); - this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot -+ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - allow better concurrency ++ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - Fix GameProfileCache concurrency jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat)); }); String s = this.gson.toJson(jsonarray); @@ -108,7 +108,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private Stream getTopMRUProfiles(int limit) { - return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); -+ // Paper start - allow better concurrency ++ // Paper start - Fix GameProfileCache concurrency + return this.listTopMRUProfiles(limit).stream(); + } + @@ -120,7 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.stateLock.unlock(); + } } -+ // Paper end ++ // Paper end - Fix GameProfileCache concurrency private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) { JsonObject jsonobject = new JsonObject(); diff --git a/patches/server/Fix-issues-with-mob-conversion.patch b/patches/server/Fix-issues-with-mob-conversion.patch index 506b425df0..e7ab5b664e 100644 --- a/patches/server/Fix-issues-with-mob-conversion.patch +++ b/patches/server/Fix-issues-with-mob-conversion.patch @@ -13,15 +13,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected void doFreezeConversion() { - this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons -+ Stray stray = this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons // Paper - track result of conversion ++ Stray stray = this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons // Paper - Fix issues with mob conversion if (!this.isSilent()) { this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); } -+ // Paper start - reset conversion time to prevent event spam ++ // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam + if (stray == null) { + this.conversionTime = 300; + } -+ // Paper end ++ // Paper end - Fix issues with mob conversion } @@ -33,11 +33,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (zoglin != null) { zoglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); } -+ // Paper start - reset to prevent event spam ++ // Paper start - Fix issues with mob conversion; reset to prevent event spam + else { + this.timeInOverworld = 0; + } -+ // Paper end ++ // Paper end - Fix issues with mob conversion } @@ -49,11 +49,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (entitypigzombie != null) { entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); } -+ // Paper start - reset to prevent event spam ++ // Paper start - Fix issues with mob conversion; reset to prevent event spam + else { + this.timeInOverworld = 0; + } -+ // Paper end ++ // Paper end - Fix issues with mob conversion } diff --git a/patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch b/patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch index e6cc5f9609..0fe4c4438f 100644 --- a/patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch +++ b/patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch @@ -12,11 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Spigot end // 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 ++ // Paper start - Fix merchant inventory not closing on entity removal + if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { + merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); + } -+ // Paper end ++ // Paper end - Fix merchant inventory not closing on entity removal for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper } diff --git a/patches/server/Goat-ram-API.patch b/patches/server/Goat-ram-API.patch index 468b0c467c..23189cb506 100644 --- a/patches/server/Goat-ram-API.patch +++ b/patches/server/Goat-ram-API.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM); + } -+ // Paper end ++ // Paper end - Goat ram API } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Guard-against-invalid-entity-positions.patch b/patches/server/Guard-against-invalid-entity-positions.patch deleted file mode 100644 index fdf3e66034..0000000000 --- a/patches/server/Guard-against-invalid-entity-positions.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 31 Mar 2022 05:18:28 -0700 -Subject: [PATCH] Guard against invalid entity positions - -Anything not finite should be blocked and logged - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * widthScale); - } - -+ // Paper start - block invalid positions -+ public static boolean checkPosition(Entity entity, double newX, double newY, double newZ) { -+ if (Double.isFinite(newX) && Double.isFinite(newY) && Double.isFinite(newZ)) { -+ return true; -+ } -+ -+ String entityInfo = null; -+ try { -+ entityInfo = entity.toString(); -+ } catch (Exception ex) { -+ entityInfo = "[Entity info unavailable] "; -+ } -+ LOGGER.error("New entity position is invalid! Tried to set invalid position (" + newX + "," + newY + "," + newZ + ") for entity " + entity.getClass().getName() + " located at " + entity.position + ", entity info: " + entityInfo, new Throwable()); -+ return false; -+ } -+ // Paper end - block invalid positions -+ - public final void setPosRaw(double x, double y, double z) { - // Paper start - this.setPosRaw(x, y, z, false); - } - public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { -+ // Paper start - block invalid positions -+ if (!checkPosition(this, x, y, z)) { -+ return; -+ } -+ // Paper end - block invalid positions - // Paper end - // Paper start - rewrite chunk system - if (this.updatingSectionStatus) { diff --git a/patches/server/Implement-enchantWithLevels-API.patch b/patches/server/Implement-enchantWithLevels-API.patch index 5e3984d3ac..29e535a83f 100644 --- a/patches/server/Implement-enchantWithLevels-API.patch +++ b/patches/server/Implement-enchantWithLevels-API.patch @@ -11,8 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror(); } - // Paper end -+ + // Paper end - old getSpawnEgg API + // Paper start - enchantWithLevels API + @Override + public ItemStack enchantWithLevels(ItemStack itemStack, int levels, boolean allowTreasure, java.util.Random random) { diff --git a/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch index 648b17b3d3..1fb5cc91f6 100644 --- a/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -9,11 +9,14 @@ type and we are not using its capabilities. Set thread priorities so main thread has above normal priority over server threads -Allow usage of a single thread executor by not using ForkJoin so single core CPU's. +Allow usage of a single thread executor by not using ForkJoin so single core CPU's +and reduce worldgen thread worker count for low core count CPUs. == AT == public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V +Co-authored-by: Spottedleaf + diff --git a/src/main/java/io/papermc/paper/util/ServerWorkerThread.java b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -54,11 +57,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - private static ExecutorService makeExecutor(String name) { - int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads()); + private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority -+ // Paper start - use simpler thread pool that allows 1 thread -+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); ++ // Paper start - use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs ++ int cpus = Runtime.getRuntime().availableProcessors() / 2; ++ int i; ++ if (cpus <= 4) { ++ i = cpus <= 2 ? 1 : 2; ++ } else if (cpus <= 8) { ++ // [5, 8] ++ i = Math.max(3, cpus - 2); ++ } else { ++ i = cpus * 2 / 3; ++ } ++ i = Math.min(8, i); + i = Integer.getInteger("Paper.WorkerThreadCount", i); ExecutorService executorService; -+ if (i <= 0) { executorService = MoreExecutors.newDirectExecutorService(); } else { diff --git a/patches/server/Make-sure-inlined-getChunkAt-has-inlined-logic-for-l.patch b/patches/server/Make-sure-inlined-getChunkAt-has-inlined-logic-for-l.patch index acf5ee6f17..e23224896b 100644 --- a/patches/server/Make-sure-inlined-getChunkAt-has-inlined-logic-for-l.patch +++ b/patches/server/Make-sure-inlined-getChunkAt-has-inlined-logic-for-l.patch @@ -9,9 +9,6 @@ previous getChunkAt method which had inlined logic for loaded chunks did get inlined, but the standard CPS.getChunkAt method was not inlined. -Paper recently reverted this optimisation, so it's been reintroduced -here. - diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/Level.java @@ -20,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline -+ // Paper start - make sure loaded chunks get the inlined variant of this function ++ // Paper start - Perf: make sure loaded chunks get the inlined variant of this function + net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource(); + if (cps.mainThread == Thread.currentThread()) { + LevelChunk ifLoaded = cps.getChunkAtIfLoadedMainThread(chunkX, chunkZ); @@ -28,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return ifLoaded; + } + } -+ // Paper end - make sure loaded chunks get the inlined variant of this function ++ // Paper end - Perf: make sure loaded chunks get the inlined variant of this function return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump } diff --git a/patches/server/Manually-inline-methods-in-BlockPosition.patch b/patches/server/Manually-inline-methods-in-BlockPosition.patch index 6b512cea73..724eccc78f 100644 --- a/patches/server/Manually-inline-methods-in-BlockPosition.patch +++ b/patches/server/Manually-inline-methods-in-BlockPosition.patch @@ -26,21 +26,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public BlockPos.MutableBlockPos setX(int i) { - super.setX(i); -+ this.x = i; // Paper ++ this.x = i; // Paper - force line return this; } @Override public BlockPos.MutableBlockPos setY(int i) { - super.setY(i); -+ this.y = i; // Paper ++ this.y = i; // Paper - force line return this; } @Override public BlockPos.MutableBlockPos setZ(int i) { - super.setZ(i); -+ this.z = i; // Paper ++ this.z = i; // Paper - force line return this; } @@ -55,9 +55,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - private int x; - private int y; - private int z; -+ protected int x; // Paper - protected -+ protected int y; // Paper - protected -+ protected int z; // Paper - protected ++ protected int x; // Paper - force line; protected ++ protected int y; // Paper - force line; protected ++ protected int z; // Paper - force line; protected public static Codec offsetCodec(int maxAbsValue) { return ExtraCodecs.validate(CODEC, (vec) -> { diff --git a/patches/server/Name-craft-scheduler-threads-according-to-the-plugin.patch b/patches/server/Name-craft-scheduler-threads-according-to-the-plugin.patch index 276cebb045..8b7695be51 100644 --- a/patches/server/Name-craft-scheduler-threads-according-to-the-plugin.patch +++ b/patches/server/Name-craft-scheduler-threads-according-to-the-plugin.patch @@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } } -+ } finally { thread.setName(nameBefore); } // Paper - name worker thread according ++ } finally { thread.setName(nameBefore); } // Paper - name threads according to running plugin } LinkedList getWorkers() { diff --git a/patches/server/Oprimise-map-impl-for-tracked-players.patch b/patches/server/Oprimise-map-impl-for-tracked-players.patch index 54d79475e5..898970cd56 100644 --- a/patches/server/Oprimise-map-impl-for-tracked-players.patch +++ b/patches/server/Oprimise-map-impl-for-tracked-players.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final int range; SectionPos lastSectionPos; - public final Set seenBy = Sets.newIdentityHashSet(); -+ public final Set seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - optimise map impl ++ public final Set seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl public TrackedEntity(Entity entity, int i, int j, boolean flag) { this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit diff --git a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch index 7f10504b90..cc705e2a34 100644 --- a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch +++ b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - do { - if (!iterator.hasNext()) { - return false; -+ // Paper start - remove abstract block iteration ++ // Paper start - Perf: remove abstract block iteration + int xOff = pos.getX(); + int yOff = pos.getY(); + int zOff = pos.getZ(); @@ -46,6 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - return true; + return false; ++ // Paper end - Perf: remove abstract block iteration } @Override diff --git a/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch b/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch index cad0450994..6dcdc0fa84 100644 --- a/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch +++ b/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch @@ -12,10 +12,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; } -+ protected long lastJumpTime = 0L; // Paper ++ protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits protected void jumpFromGround() { Vec3 vec3d = this.getDeltaMovement(); -+ // Paper start ++ // Paper start - Prevent excessive velocity through repeated crits + long time = System.nanoTime(); + boolean canCrit = true; + if (this instanceof net.minecraft.world.entity.player.Player) { @@ -25,13 +25,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + canCrit = true; + } + } -+ // Paper end ++ // Paper end - Prevent excessive velocity through repeated crits this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); if (this.isSprinting()) { float f = this.getYRot() * 0.017453292F; -+ if (canCrit) // Paper ++ if (canCrit) // Paper - Prevent excessive velocity through repeated crits this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F))); } diff --git a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch index 8b7ddcfd05..5ef25d768d 100644 --- a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch +++ b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) { + this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1); + } -+ // Paper end ++ // Paper end - Prevent "softlocked" exit portal generation if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) { int i = Mth.positiveCeilDiv(4, 16); diff --git a/patches/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch b/patches/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch deleted file mode 100644 index 1cc2a630ed..0000000000 --- a/patches/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 30 Aug 2021 04:26:40 -0700 -Subject: [PATCH] Reduce worldgen thread worker count for low core count CPUs - - -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -0,0 +0,0 @@ public class Util { - - private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority - // Paper start - use simpler thread pool that allows 1 thread -- int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); -+ // Paper start - also try to avoid suffocating the system with the worldgen workers -+ int cpus = Runtime.getRuntime().availableProcessors() / 2; -+ int i; -+ if (cpus <= 4) { -+ i = cpus <= 2 ? 1 : 2; -+ } else if (cpus <= 8) { -+ // [5, 8] -+ i = Math.max(3, cpus - 2); -+ } else { -+ i = cpus * 2 / 3; -+ } -+ i = Math.min(8, i); -+ // Paper end - also try to avoid suffocating the system with the worldgen workers - i = Integer.getInteger("Paper.WorkerThreadCount", i); - ExecutorService executorService; - diff --git a/patches/server/Sanitize-ResourceLocation-error-logging.patch b/patches/server/Sanitize-ResourceLocation-error-logging.patch index 5a7142abe8..f2863e33ec 100644 --- a/patches/server/Sanitize-ResourceLocation-error-logging.patch +++ b/patches/server/Sanitize-ResourceLocation-error-logging.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static String assertValidNamespace(String namespace, String path) { if (!isValidNamespace(namespace)) { - throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + namespace + ":" + path); -+ throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper ++ throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging } else { return namespace; } @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static String assertValidPath(String namespace, String path) { if (!isValidPath(path)) { - throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + path); -+ throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper ++ throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging } else { return path; } diff --git a/patches/server/Use-Velocity-compression-and-cipher-natives.patch b/patches/server/Use-Velocity-compression-and-cipher-natives.patch index 19f0cbfb84..da2a629e20 100644 --- a/patches/server/Use-Velocity-compression-and-cipher-natives.patch +++ b/patches/server/Use-Velocity-compression-and-cipher-natives.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") { + isTransitive = false + } -+ // Paper end ++ // Paper end - Use Velocity cipher runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6") runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") @@ -29,17 +29,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public class CipherDecoder extends MessageToMessageDecoder { - private final CipherBase cipher; -+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper ++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper - Use Velocity cipher - public CipherDecoder(Cipher cipher) { - this.cipher = new CipherBase(cipher); -+ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper -+ this.cipher = cipher; // Paper ++ public CipherDecoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper - Use Velocity cipher ++ this.cipher = cipher; // Paper - Use Velocity cipher } protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - list.add(this.cipher.decipher(channelHandlerContext, byteBuf)); -+ // Paper start ++ // Paper start - Use Velocity cipher + ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf); + try { + cipher.process(compatible); @@ -48,15 +48,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + compatible.release(); // compatible will never be used if we throw an exception + throw e; + } -+ // Paper end ++ // Paper end - Use Velocity cipher } + -+ // Paper start ++ // Paper start - Use Velocity cipher + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + cipher.close(); + } -+ // Paper end ++ // Paper end - Use Velocity cipher } diff --git a/src/main/java/net/minecraft/network/CipherEncoder.java b/src/main/java/net/minecraft/network/CipherEncoder.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -70,19 +70,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 -public class CipherEncoder extends MessageToByteEncoder { - private final CipherBase cipher; -+public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder { // Paper - change superclass -+ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper ++public class CipherEncoder extends io.netty.handler.codec.MessageToMessageEncoder { // Paper - Use Velocity cipher; change superclass ++ private final com.velocitypowered.natives.encryption.VelocityCipher cipher; // Paper - Use Velocity cipher - public CipherEncoder(Cipher cipher) { - this.cipher = new CipherBase(cipher); -+ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper -+ this.cipher = cipher; // Paper ++ public CipherEncoder(com.velocitypowered.natives.encryption.VelocityCipher cipher) { // Paper - Use Velocity cipher ++ this.cipher = cipher; // Paper - Use Velocity cipher } - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { - this.cipher.encipher(byteBuf, byteBuf2); + protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { -+ // Paper start ++ // Paper start - Use Velocity cipher + ByteBuf compatible = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), cipher, byteBuf); + try { + cipher.process(compatible); @@ -91,15 +91,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + compatible.release(); // compatible will never be used if we throw an exception + throw e; + } -+ // Paper end ++ // Paper end - Use Velocity cipher } + -+ // Paper start ++ // Paper start - Use Velocity cipher + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + cipher.close(); + } -+ // Paper end ++ // Paper end - Use Velocity cipher } diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -109,11 +109,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152; public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608; private final Inflater inflater; -+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper ++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher private int threshold; private boolean validateDecompressed; -+ // Paper start ++ // Paper start - Use Velocity cipher public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) { + this(null, compressionThreshold, rejectsBadPackets); + } @@ -123,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.inflater = new Inflater(); + this.inflater = compressor == null ? new Inflater() : null; + this.compressor = compressor; -+ // Paper end ++ // Paper end - Use Velocity cipher } protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { @@ -131,15 +131,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -+ if (inflater != null) { // Paper - use velocity compression - fallback to vanilla inflater ++ if (inflater != null) { // Paper - Use Velocity cipher; fallback to vanilla inflater this.setupInflaterInput(byteBuf); ByteBuf byteBuf2 = this.inflate(channelHandlerContext, i); this.inflater.reset(); list.add(byteBuf2); -+ return; // Paper - use velocity compression ++ return; // Paper - Use Velocity cipher + } // Paper - use velocity compression + -+ // Paper start - use velocity compression ++ // Paper start - Use Velocity cipher + int claimedUncompressedSize = i; // OBFHELPER + ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf); + ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(channelHandlerContext.alloc(), this.compressor, claimedUncompressedSize); @@ -153,19 +153,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } finally { + compatibleIn.release(); + } -+ // Paper end - use velocity compression ++ // Paper end - Use Velocity cipher } } } -+ // Paper start ++ // Paper start - Use Velocity cipher + @Override + public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { + if (this.compressor != null) { + this.compressor.close(); + } + } -+ // Paper end ++ // Paper end - Use Velocity cipher + private void setupInflaterInput(ByteBuf buf) { ByteBuffer byteBuffer; @@ -179,12 +179,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public class CompressionEncoder extends MessageToByteEncoder { - private final byte[] encodeBuf = new byte[8192]; -+ private final byte[] encodeBuf; // Paper ++ private final byte[] encodeBuf; // Paper - Use Velocity cipher private final Deflater deflater; -+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper ++ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher private int threshold; -+ // Paper start ++ // Paper start - Use Velocity cipher public CompressionEncoder(int compressionThreshold) { + this(null, compressionThreshold); + } @@ -199,17 +199,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.deflater = null; + } + this.compressor = compressor; -+ // Paper end ++ // Paper end - Use Velocity cipher } - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) { -+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper ++ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper - Use Velocity cipher int i = byteBuf.readableBytes(); if (i < this.threshold) { VarInt.write(byteBuf2, 0); byteBuf2.writeBytes(byteBuf); } else { -+ // Paper start ++ // Paper start - Use Velocity cipher + if (this.deflater != null) { byte[] bs = new byte[i]; byteBuf.readBytes(bs); @@ -228,12 +228,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } finally { + compatibleIn.release(); + } -+ // Paper end ++ // Paper end - Use Velocity cipher } } -+ // Paper start ++ // Paper start - Use Velocity cipher + @Override + protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{ + if (this.compressor != null) { @@ -258,7 +258,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.compressor.close(); + } + } -+ // Paper end ++ // Paper end - Use Velocity cipher + public int getThreshold() { return this.threshold; @@ -275,7 +275,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.encrypted = true; - this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher)); - this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptionCipher)); -+ // Paper start ++ // Paper start - Use Velocity cipher +// public void setEncryptionKey(Cipher decryptionCipher, Cipher encryptionCipher) { +// this.encrypted = true; +// this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptionCipher)); @@ -296,7 +296,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } } -+ // Paper end ++ // Paper end - Use Velocity cipher public boolean isEncrypted() { return this.encrypted; @@ -304,19 +304,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) { if (compressionThreshold >= 0) { -+ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper ++ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper - Use Velocity cipher if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets); } else { - this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets)); -+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper ++ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper - Use Velocity cipher } if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold); } else { - this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold)); -+ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper ++ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper - Use Velocity cipher } this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper } else { @@ -328,10 +328,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ServerConnectionListener.LOGGER.info("Using default channel type"); } -+ // Paper start - indicate Velocity natives in use ++ // Paper start - Use Velocity cipher + ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity."); + ServerConnectionListener.LOGGER.info("Paper: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity."); -+ // Paper end ++ // Paper end - Use Velocity cipher + this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { protected void initChannel(Channel channel) { @@ -346,15 +346,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 SecretKey secretkey = packet.getSecretKey(privatekey); - Cipher cipher = Crypt.getCipher(2, secretkey); - Cipher cipher1 = Crypt.getCipher(1, secretkey); -+ // Paper start ++ // Paper start - Use Velocity cipher +// Cipher cipher = Crypt.getCipher(2, secretkey); +// Cipher cipher1 = Crypt.getCipher(1, secretkey); -+ // Paper end ++ // Paper end - Use Velocity cipher s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16); this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING; - this.connection.setEncryptionKey(cipher, cipher1); -+ this.connection.setupEncryption(secretkey); // Paper ++ this.connection.setupEncryption(secretkey); // Paper - Use Velocity cipher } catch (CryptException cryptographyexception) { throw new IllegalStateException("Protocol error", cryptographyexception); } diff --git a/patches/server/Vanilla-command-permission-fixes.patch b/patches/server/Vanilla-command-permission-fixes.patch index da133efe99..9e67cb63a6 100644 --- a/patches/server/Vanilla-command-permission-fixes.patch +++ b/patches/server/Vanilla-command-permission-fixes.patch @@ -17,18 +17,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import java.util.function.Predicate; public abstract class ArgumentBuilder> { -+ // Paper start ++ // Paper start - Vanilla command permission fixes + private static final Predicate DEFAULT_REQUIREMENT = s -> true; + + @SuppressWarnings("unchecked") + public static Predicate defaultRequirement() { + return (Predicate) DEFAULT_REQUIREMENT; + } -+ // Paper end ++ // Paper end - Vanilla command permission fixes private final RootCommandNode arguments = new RootCommandNode<>(); private Command command; - private Predicate requirement = s -> true; -+ private Predicate requirement = defaultRequirement(); // Paper ++ private Predicate requirement = defaultRequirement(); // Paper - Vanilla command permission fixes private CommandNode target; private RedirectModifier modifier = null; private boolean forks; @@ -40,13 +40,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } this.vanillaCommandNodes.addAll(this.dispatcher.getRoot().getChildren()); // Paper -+ // Paper start ++ // Paper start - Vanilla command permission fixes + for (final CommandNode node : this.dispatcher.getRoot().getChildren()) { + if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.defaultRequirement()) { + node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node)); + } + } -+ // Paper end ++ // Paper end - Vanilla command permission fixes // CraftBukkit start } @@ -59,7 +59,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static String getPermission(CommandNode vanillaCommand) { - return "minecraft.command." + ((vanillaCommand.getRedirect() == null) ? vanillaCommand.getName() : vanillaCommand.getRedirect().getName()); -+ // Paper start ++ // Paper start - Vanilla command permission fixes + final String commandName; + if (vanillaCommand.getRedirect() == null) { + commandName = vanillaCommand.getName(); @@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return maybeNamespaced.substring(prefix.length()); + } + return maybeNamespaced; -+ // Paper end ++ // Paper end - Vanilla command permission fixes } private String toDispatcher(String[] args, String name) { diff --git a/patches/server/fix-various-menus-with-empty-level-accesses.patch b/patches/server/fix-various-menus-with-empty-level-accesses.patch index 642dfc1eee..14fd5c8f0c 100644 --- a/patches/server/fix-various-menus-with-empty-level-accesses.patch +++ b/patches/server/fix-various-menus-with-empty-level-accesses.patch @@ -12,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public Optional evaluate(BiFunction getter) { return Optional.empty(); } -+ // Paper start ++ // Paper start - fix menus with empty level accesses + @Override + public org.bukkit.Location getLocation() { + return null; + } -+ // Paper end ++ // Paper end - fix menus with empty level accesses }; static ContainerLevelAccess create(final Level world, final BlockPos pos) { diff --git a/patches/server/prevent-unintended-light-block-manipulation.patch b/patches/server/prevent-unintended-light-block-manipulation.patch index e4e3c41a36..81e096e589 100644 --- a/patches/server/prevent-unintended-light-block-manipulation.patch +++ b/patches/server/prevent-unintended-light-block-manipulation.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!world.isClientSide && player.canUseGameMasterBlocks()) { -+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper ++ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return InteractionResult.FAIL; } // Paper - Prevent unintended light block manipulation world.setBlock(pos, state.cycle(LEVEL), 2); return InteractionResult.SUCCESS; } else {