Update patches to handle vineflower decompiler (#10406)

* Update patches to handle vineflower decompiler

* update patches again to handle inlined simple lambdas

* update vf again and re-apply/rebuild patches

* update patches after removal of verify-merges flag

* fix compile issue

* remove maven local

* fix some issues

* address more issues

* fix collision patch

* use paperweight release

* more fixes

* update fineflower and fix patches again

* add missing comment descriptor

---------

Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
This commit is contained in:
Jake Potrebic 2024-04-12 12:14:06 -07:00
parent 99625a6d53
commit 89528bff42
128 changed files with 1079 additions and 1150 deletions

View File

@ -11,7 +11,7 @@ plugins {
java
`maven-publish`
id("com.github.johnrengelman.shadow") version "8.1.1" apply false
id("io.papermc.paperweight.core") version "1.5.13"
id("io.papermc.paperweight.core") version "1.5.15"
}
allprojects {
@ -69,7 +69,7 @@ repositories {
dependencies {
paramMappings("net.fabricmc:yarn:1.20.4+build.1:mergedv2")
remapper("net.fabricmc:tiny-remapper:0.10.1:fat")
decompiler("net.minecraftforge:forgeflower:2.0.627.2")
decompiler("org.vineflower:vineflower:1.11.0-20240412.144930-14")
spigotDecompiler("io.papermc:patched-spigot-fernflower:0.1+build.6")
paperclip("io.papermc:paperclip:3.0.3")
}
@ -80,7 +80,7 @@ paperweight {
paramMappingsRepo = paperMavenPublicUrl
remapRepo = paperMavenPublicUrl
decompileRepo = paperMavenPublicUrl
decompileRepo = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
craftBukkit {
fernFlowerJar = layout.file(spigotDecompiler.elements.map { it.single().asFile })

View File

@ -513,9 +513,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - actually optimise explosions
float f = explosion.radius() * 2.0F;
Vec3 vec3 = explosion.center();
double d = Math.sqrt(entity.distanceToSqr(vec3)) / (double)f;
- double e = (1.0D - d) * (double)Explosion.getSeenPercent(vec3, entity);
+ double e = (1.0D - d) * seenPercent; // Paper - actually optimise explosions
return (float)((e * e + e) / 2.0D * 7.0D * (double)f + 1.0D);
double d = Math.sqrt(entity.distanceToSqr(vec3)) / f;
- double e = (1.0 - d) * Explosion.getSeenPercent(vec3, entity);
+ double e = (1.0 - d) * seenPercent; // Paper - actually optimise explosions
return (float)((e * e + e) / 2.0 * 7.0 * f + 1.0);
}
}

View File

@ -36,12 +36,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
- this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob)null);
- this.finalizeSpawnChildFromBreeding(world, other, null);
+ // Paper start - Add EntityFertilizeEggEvent event
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
+ if (result.isCancelled()) return;
+
+ this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob)null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
+ this.finalizeSpawnChildFromBreeding(world, other, null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
+ // Paper end - Add EntityFertilizeEggEvent event
this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
}

View File

@ -265,7 +265,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
entity.makeStuckInBlock(state, new Vec3(0.25D, (double)0.05F, 0.25D));
entity.makeStuckInBlock(state, new Vec3(0.25, 0.05F, 0.25));
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java

View File

@ -89,25 +89,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java
@@ -0,0 +0,0 @@ public class RamTarget extends Behavior<Goat> {
float f = 0.25F * (float)(i - j);
float f = 0.25F * (i - j);
float g = Mth.clamp(entity.getSpeed() * 1.65F, 0.2F, 3.0F) + f;
float h = livingEntity.isDamageSourceBlocked(world.damageSources().mobAttack(entity)) ? 0.5F : 1.0F;
- livingEntity.knockback((double)(h * g) * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z());
+ livingEntity.knockback((double)(h * g) * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z(), entity, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
- livingEntity.knockback(h * g * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z());
+ livingEntity.knockback(h * g * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z(), entity, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
this.finishRam(world, entity);
world.playSound((Player)null, entity, this.getImpactSound.apply(entity), SoundSource.NEUTRAL, 1.0F, 1.0F);
world.playSound(null, entity, this.getImpactSound.apply(entity), SoundSource.NEUTRAL, 1.0F, 1.0F);
} else if (this.hasRammedHornBreakingBlock(world, entity)) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java b/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java
@@ -0,0 +0,0 @@ public class SonicBoom extends Behavior<Warden> {
target.hurt(world.damageSources().sonicBoom(entity), 10.0F);
double d = 0.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double e = 2.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
- target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e);
+ target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e, entity); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
});
target.hurt(world.damageSources().sonicBoom(entity), 10.0F);
double d = 0.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double e = 2.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
- target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e);
+ target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e, entity); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
});
}
}
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@ -170,9 +170,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java
@@ -0,0 +0,0 @@ public interface HoglinBase {
double j = f * (double)(attacker.level().random.nextFloat() * 0.5F + 0.2F);
Vec3 vec3 = (new Vec3(g, 0.0D, h)).normalize().scale(j).yRot(i);
double k = f * (double)attacker.level().random.nextFloat() * 0.5D;
double j = f * (attacker.level().random.nextFloat() * 0.5F + 0.2F);
Vec3 vec3 = new Vec3(g, 0.0, h).normalize().scale(j).yRot(i);
double k = f * attacker.level().random.nextFloat() * 0.5;
- target.push(vec3.x, k, vec3.z);
+ target.push(vec3.x, k, vec3.z, attacker); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
target.hurtMarked = true;

View File

@ -25,7 +25,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Add Listing API for Player
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
@ -54,21 +55,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
public ClientboundPlayerInfoUpdatePacket(FriendlyByteBuf buf) {
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
this.entries = buf.readList((buf2) -> {
this.entries = buf.readList(buf2 -> {
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
public static record Entry(UUID profileId, @Nullable GameProfile profile, boolean listed, int latency, GameType gameMode, @Nullable Component displayName, @Nullable RemoteChatSession.Data chatSession) {
@Nullable RemoteChatSession.Data chatSession
) {
Entry(ServerPlayer player) {
- this(player.getUUID(), player.getGameProfile(), true, player.connection.latency(), player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData));
+ // Paper start - Add Listing API for Player
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
+ this(player.getUUID(), player.getGameProfile(), listed, player.connection.latency(), player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData));
+ }
this(
player.getUUID(),
player.getGameProfile(),
- true,
+ listed,
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.getTabListDisplayName(),
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
);
}
+ Entry(UUID profileId, boolean listed) {
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, null);
}
+ }
+ // Paper end - Add Listing API for Player
}

View File

@ -22,13 +22,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.out_of_order_chat"), true, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
} else {
this.lastTimeStamp = body.timeStamp();
PlayerChatMessage playerChatMessage = new PlayerChatMessage(signedMessageLink, signature, body, (Component)null, FilterMask.PASS_THROUGH);
PlayerChatMessage playerChatMessage = new PlayerChatMessage(signedMessageLink, signature, body, null, FilterMask.PASS_THROUGH);
if (!playerChatMessage.verify(signatureValidator)) {
- throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.unsigned_chat"), true);
+ throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.unsigned_chat"), true, org.bukkit.event.player.PlayerKickEvent.Cause.UNSIGNED_CHAT); // Paper - kick event causes
} else {
if (playerChatMessage.hasExpiredServer(Instant.now())) {
LOGGER.warn("Received expired chat: '{}'. Is the client/server system time unsynchronized?", (Object)body.content());
LOGGER.warn("Received expired chat: '{}'. Is the client/server system time unsynchronized?", body.content());
@@ -0,0 +0,0 @@ public class SignedMessageChain {
public static class DecodeException extends ThrowingComponent {
@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class BanIpCommands {
}
for(ServerPlayer serverPlayer : list) {
for (ServerPlayer serverPlayer : list) {
- serverPlayer.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"));
+ serverPlayer.connection.disconnect(Component.translatable("multiplayer.disconnect.ip_banned"), org.bukkit.event.player.PlayerKickEvent.Cause.IP_BANNED); // Paper - kick event cause
}
@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/commands/BanPlayerCommands.java
+++ b/src/main/java/net/minecraft/server/commands/BanPlayerCommands.java
@@ -0,0 +0,0 @@ public class BanPlayerCommands {
}, true);
);
ServerPlayer serverPlayer = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
if (serverPlayer != null) {
- serverPlayer.connection.disconnect(Component.translatable("multiplayer.disconnect.banned"));
@ -92,13 +92,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/commands/KickCommand.java
@@ -0,0 +0,0 @@ public class KickCommand {
for(ServerPlayer serverPlayer : targets) {
for (ServerPlayer serverPlayer : targets) {
if (!source.getServer().isSingleplayerOwner(serverPlayer.getGameProfile())) {
- serverPlayer.connection.disconnect(reason);
+ serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause
source.sendSuccess(() -> {
return Component.translatable("commands.kick.success", serverPlayer.getDisplayName(), reason);
}, true);
source.sendSuccess(() -> Component.translatable("commands.kick.success", serverPlayer.getDisplayName(), reason), true);
i++;
}
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java

View File

@ -55,16 +55,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Add PlayerShearBlockEvent
Direction direction = hit.getDirection();
Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction;
world.playSound((Player)null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.playSound(null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11);
- ItemEntity itemEntity = new ItemEntity(world, (double)pos.getX() + 0.5D + (double)direction2.getStepX() * 0.65D, (double)pos.getY() + 0.1D, (double)pos.getZ() + 0.5D + (double)direction2.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4));
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) {
+ ItemEntity itemEntity = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) direction2.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) direction2.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item));
+ // Paper end - Add PlayerShearBlockEvent
itemEntity.setDeltaMovement(0.05D * (double)direction2.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02D);
+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { // Paper - Add PlayerShearBlockEvent
ItemEntity itemEntity = new ItemEntity(
world,
pos.getX() + 0.5 + direction2.getStepX() * 0.65,
pos.getY() + 0.1,
pos.getZ() + 0.5 + direction2.getStepZ() * 0.65,
- new ItemStack(Items.PUMPKIN_SEEDS, 4)
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item) // Paper - Add PlayerShearBlockEvent
);
itemEntity.setDeltaMovement(
0.05 * direction2.getStepX() + world.random.nextDouble() * 0.02, 0.05, 0.05 * direction2.getStepZ() + world.random.nextDouble() * 0.02
);
world.addFreshEntity(itemEntity);
+ } // Paper - Add PlayerShearBlockEvent
itemStack.hurtAndBreak(1, player, (playerx) -> {
playerx.broadcastBreakEvent(hand);
});
itemStack.hurtAndBreak(1, player, playerx -> playerx.broadcastBreakEvent(hand));
world.gameEvent(player, GameEvent.SHEAR, pos);
player.awardStat(Stats.ITEM_USED.get(Items.SHEARS));

View File

@ -16,9 +16,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ private static void awardTargetHitCriteria(Projectile projectile, BlockHitResult hit, int i) {
+ // Paper end - Add TargetHitEvent
Entity entity = projectile.getOwner();
if (entity instanceof ServerPlayer serverPlayer) {
if (projectile.getOwner() instanceof ServerPlayer serverPlayer) {
serverPlayer.awardStat(Stats.TARGET_HIT);
CriteriaTriggers.TARGET_BLOCK_HIT.trigger(serverPlayer, projectile, hit.getLocation(), i);
@@ -0,0 +0,0 @@ public class TargetBlock extends Block {
private static int updateRedstoneOutput(LevelAccessor world, BlockState state, BlockHitResult hitResult, Entity entity) {
int i = getRedstoneStrength(hitResult, hitResult.getLocation());

View File

@ -9,14 +9,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java
+++ b/src/main/java/net/minecraft/world/entity/monster/warden/AngerManagement.java
@@ -0,0 +0,0 @@ public class AngerManagement {
public int increaseAnger(Entity entity, int amount) {
boolean bl = !this.angerBySuspect.containsKey(entity);
int i = this.angerBySuspect.computeInt(entity, (suspect, anger) -> {
- return Math.min(150, (anger == null ? 0 : anger) + amount);
+ return Math.min(150, (anger == null ? 0 : anger) + amount); // Paper - diff on change (Warden#increaseAngerAt WardenAngerChangeEvent)
});
- int i = this.angerBySuspect.computeInt(entity, (suspect, anger) -> Math.min(150, (anger == null ? 0 : anger) + amount));
+ int i = this.angerBySuspect.computeInt(entity, (suspect, anger) -> Math.min(150, (anger == null ? 0 : anger) + amount)); // Paper - diff on change (Warden#increaseAngerAt WardenAngerChangeEvent)
if (bl) {
int j = this.angerByUuid.removeInt(entity.getUUID());
i += j;
diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java

View File

@ -13,9 +13,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (!world.paperConfig().environment.frostedIce.enabled) return; // Paper - Frosted ice options
if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock(world, pos) && this.slightlyMelt(state, world, pos)) {
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4))
&& world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock(world, pos)
&& this.slightlyMelt(state, world, pos)) {
@@ -0,0 +0,0 @@ public class FrostedIceBlock extends IceBlock {
mutableBlockPos.setWithOffset(pos, direction);
BlockState blockState = world.getBlockState(mutableBlockPos);
@ -24,7 +24,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - Frosted ice options
}
}
} else {
- world.scheduleTick(pos, this, Mth.nextInt(random, 20, 40));
+ world.scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - Frosted ice options

View File

@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - Call BlockFadeEvent
this.destroyBlock(world, pos);
world.playSound((Player)null, pos, SoundEvents.FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
world.playSound(null, pos, SoundEvents.FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
this.spawnTadpoles(world, pos, random);
diff --git a/src/main/java/net/minecraft/world/level/block/ScaffoldingBlock.java b/src/main/java/net/minecraft/world/level/block/ScaffoldingBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -57,15 +57,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!this.isReadyToHatch(state)) {
world.playSound((Player)null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
} else {
+ // Paper start - Call BlockFadeEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {
+ rescheduleTick(world, pos);
+ this.rescheduleTick(world, pos);
+ return;
+ }
+ // Paper end - Call BlockFadeEvent
world.playSound((Player)null, pos, SoundEvents.SNIFFER_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.destroyBlock(pos, false);
Sniffer sniffer = EntityType.SNIFFER.create(world);

View File

@ -16,8 +16,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
entity.spawnAtLocation(itemStack, 0.5F);
+ entity.forceDrops = false; // Paper - Add missing forceDrop toggles
}
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java

View File

@ -170,13 +170,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ // Paper end - Add missing structure set seed configs
if (!this.isPlacementChunk(calculator, chunkX, chunkZ)) {
return false;
- } else if (this.frequency < 1.0F && !this.frequencyReductionMethod.shouldGenerate(calculator.getLevelSeed(), this.salt, chunkX, chunkZ, this.frequency)) {
+ } else if (this.frequency < 1.0F && !this.frequencyReductionMethod.shouldGenerate(calculator.getLevelSeed(), this.salt, chunkX, chunkZ, this.frequency, saltOverride)) { // Paper - Add missing structure set seed configs
return false;
} else {
return !this.exclusionZone.isPresent() || !this.exclusionZone.get().isPlacementForbidden(calculator, chunkX, chunkZ);
return this.isPlacementChunk(calculator, chunkX, chunkZ)
- && (!(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(calculator.getLevelSeed(), this.salt, chunkX, chunkZ, this.frequency))
+ && (!(this.frequency < 1.0F) || this.frequencyReductionMethod.shouldGenerate(calculator.getLevelSeed(), this.salt, chunkX, chunkZ, this.frequency, saltOverride)) // Paper - Add missing structure set seed configs
&& (!this.exclusionZone.isPresent() || !this.exclusionZone.get().isPlacementForbidden(calculator, chunkX, chunkZ));
}
@@ -0,0 +0,0 @@ public abstract class StructurePlacement {
public abstract StructurePlacementType<?> type();
@ -198,7 +197,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride);
+ }
+ // Paper end - Add missing structure set seed configs
return worldgenRandom.nextDouble() < (double)frequency;
return worldgenRandom.nextDouble() < frequency;
}
- private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) {

View File

@ -93,8 +93,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private float y;
+ 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<ResourceLocation> background, AdvancementType frame, boolean showToast, boolean announceToChat, boolean hidden) {
this.title = title;
public DisplayInfo(
ItemStack icon,
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancement.java

View File

@ -14,7 +14,7 @@ diff --git a/src/main/java/net/minecraft/advancements/critereon/LocationPredicat
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/advancements/critereon/LocationPredicate.java
+++ b/src/main/java/net/minecraft/advancements/critereon/LocationPredicate.java
@@ -0,0 +0,0 @@ public record LocationPredicate(Optional<LocationPredicate.PositionPredicate> po
@@ -0,0 +0,0 @@ public record LocationPredicate(
public boolean matches(ServerLevel world, double x, double y, double z) {
if (this.position.isPresent() && !this.position.get().matches(x, y, z)) {
return false;

View File

@ -51,27 +51,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
BlockGetter blockGetter = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState().setValue(DOWN, Boolean.valueOf(!blockGetter.getBlockState(blockPos.below()).is(this))).setValue(UP, Boolean.valueOf(!blockGetter.getBlockState(blockPos.above()).is(this))).setValue(NORTH, Boolean.valueOf(!blockGetter.getBlockState(blockPos.north()).is(this))).setValue(EAST, Boolean.valueOf(!blockGetter.getBlockState(blockPos.east()).is(this))).setValue(SOUTH, Boolean.valueOf(!blockGetter.getBlockState(blockPos.south()).is(this))).setValue(WEST, Boolean.valueOf(!blockGetter.getBlockState(blockPos.west()).is(this)));
return this.defaultBlockState()
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return neighborState.is(this) ? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false)) : super.updateShape(state, direction, neighborState, world, pos, neighborPos);
}
return neighborState.is(this)
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false))
: super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
public BlockState rotate(BlockState state, Rotation rotation) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.NORTH)), state.getValue(NORTH)).setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.SOUTH)), state.getValue(SOUTH)).setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.EAST)), state.getValue(EAST)).setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.WEST)), state.getValue(WEST)).setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.UP)), state.getValue(UP)).setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.DOWN)), state.getValue(DOWN));
}
return state.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.EAST)), state.getValue(EAST))
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
public BlockState mirror(BlockState state, Mirror mirror) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.NORTH)), state.getValue(NORTH)).setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.SOUTH)), state.getValue(SOUTH)).setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.EAST)), state.getValue(EAST)).setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.WEST)), state.getValue(WEST)).setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.UP)), state.getValue(UP)).setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.DOWN)), state.getValue(DOWN));
}
return state.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.EAST)), state.getValue(EAST))
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java

View File

@ -2139,11 +2139,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
MinecraftServer minecraftServer = source.getServer();
CompletableFuture<FilteredText> completableFuture = filterPlainText(source, message);
- Component component = minecraftServer.getChatDecorator().decorate(source.getPlayer(), message.decoratedContent());
- source.getChatMessageChainer().append(completableFuture, (filtered) -> {
- source.getChatMessageChainer().append(completableFuture, filtered -> {
- PlayerChatMessage playerChatMessage2 = message.withUnsignedContent(component).filter(filtered.mask());
+ // Paper start - support asynchronous chat decoration
+ CompletableFuture<ChatDecorator.Result> componentFuture = minecraftServer.getChatDecorator().decorate(source.getPlayer(), source, message.decoratedContent());
+ source.getChatMessageChainer().append(CompletableFuture.allOf(completableFuture, componentFuture), (filtered) -> {
+ source.getChatMessageChainer().append(CompletableFuture.allOf(completableFuture, componentFuture), filtered -> {
+ PlayerChatMessage playerChatMessage2 = message.withUnsignedContent(componentFuture.join().component()).filter(completableFuture.join().mask());
+ // Paper end - support asynchronous chat decoration
callback.accept(playerChatMessage2);
@ -2248,10 +2248,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@FunctionalInterface
public interface ChatDecorator {
ChatDecorator PLAIN = (sender, message) -> {
- return message;
+ return CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events
};
- ChatDecorator PLAIN = (sender, message) -> message;
+ ChatDecorator PLAIN = (sender, message) -> CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events;
- Component decorate(@Nullable ServerPlayer sender, Component message);
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - adventure; support chat decoration events
@ -2342,11 +2340,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ private static Codec<Component> createCodec(Codec<Component> selfCodec, @javax.annotation.Nullable java.util.Locale locale) {
+ // Paper end - adventure; create separate codec for each locale
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE};
MapCodec<ComponentContents> mapCodec = createLegacyComponentMatcher(types, ComponentContents.Type::codec, ComponentContents::type, "type");
Codec<Component> codec = RecordCodecBuilder.create((instance) -> {
return instance.group(mapCodec.forGetter(Component::getContents), ExtraCodecs.strictOptionalField(ExtraCodecs.nonEmptyList(selfCodec.listOf()), "extra", List.of()).forGetter(Component::getSiblings), Style.Serializer.MAP_CODEC.forGetter(Component::getStyle)).apply(instance, MutableComponent::new);
});
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{
PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
};
@@ -0,0 +0,0 @@ public class ComponentSerialization {
)
.apply(instance, MutableComponent::new)
);
+ // Paper start - adventure; create separate codec for each locale
+ final Codec<Component> origCodec = codec;
+ codec = new Codec<>() {
@ -2375,9 +2375,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ };
+ // Paper end - adventure; create separate codec for each locale
return Codec.either(Codec.either(Codec.STRING, ExtraCodecs.nonEmptyList(selfCodec.listOf())), codec).xmap((either) -> {
return either.map((either2) -> {
return either2.map(Component::literal, ComponentSerialization::createFromList);
return Codec.either(Codec.either(Codec.STRING, ExtraCodecs.nonEmptyList(selfCodec.listOf())), codec)
.xmap(either -> either.map(either2 -> either2.map(Component::literal, ComponentSerialization::createFromList), text -> (Component)text), text -> {
String string = text.tryCollapseToString();
diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java
@ -2393,7 +2393,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - adventure; pass actual vanilla component
MutableComponent mutableComponent = text.getContents().resolve(source, sender, depth + 1);
for(Component component : text.getSiblings()) {
for (Component component : text.getSiblings()) {
diff --git a/src/main/java/net/minecraft/network/chat/MessageSignature.java b/src/main/java/net/minecraft/network/chat/MessageSignature.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/chat/MessageSignature.java
@ -2406,12 +2406,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static final Codec<MessageSignature> CODEC = ExtraCodecs.BASE64_STRING.xmap(MessageSignature::new, MessageSignature::bytes);
public static final int BYTES = 256;
public MessageSignature {
- Preconditions.checkState(bs.length == 256, "Invalid message signature size");
+ Preconditions.checkState(bytes.length == 256, "Invalid message signature size"); // Paper - decompile fix
}
public static MessageSignature read(FriendlyByteBuf buf) {
diff --git a/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java b/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java
@ -2427,10 +2421,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
+
static OutgoingChatMessage create(PlayerChatMessage message) {
return (OutgoingChatMessage)(message.isSystem() ? new OutgoingChatMessage.Disguised(message.decoratedContent()) : new OutgoingChatMessage.Player(message));
}
return (OutgoingChatMessage)(message.isSystem()
? new OutgoingChatMessage.Disguised(message.decoratedContent())
@@ -0,0 +0,0 @@ public interface OutgoingChatMessage {
public static record Disguised(Component content) implements OutgoingChatMessage {
public static record Disguised(@Override Component content) implements OutgoingChatMessage {
@Override
public void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params) {
- sender.connection.sendDisguisedChatMessage(this.content, params);
@ -2461,13 +2455,14 @@ diff --git a/src/main/java/net/minecraft/network/chat/PlayerChatMessage.java b/s
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/chat/PlayerChatMessage.java
+++ b/src/main/java/net/minecraft/network/chat/PlayerChatMessage.java
@@ -0,0 +0,0 @@ import net.minecraft.Util;
import net.minecraft.util.SignatureUpdater;
@@ -0,0 +0,0 @@ import net.minecraft.util.SignatureUpdater;
import net.minecraft.util.SignatureValidator;
-public record PlayerChatMessage(SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask) {
+// Paper start - adventure; support signed messages
+public record PlayerChatMessage(SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask, @Nullable net.minecraft.network.chat.ChatDecorator.Result result) {
public record PlayerChatMessage(
- SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask
+ SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask, @Nullable net.minecraft.network.chat.ChatDecorator.Result result // Paper - adventure; support signed messages
) {
+ // Paper start - adventure; support signed messages
+ public PlayerChatMessage(SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask) {
+ this(link, signature, signedBody, unsignedContent, filterMask, null);
+ }
@ -2513,10 +2508,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return new AdventureView();
+ }
+ // Paper end - adventure; support signed messages
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec((instance) -> {
return instance.group(SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link), MessageSignature.CODEC.optionalFieldOf("signature").forGetter((message) -> {
return Optional.ofNullable(message.signature);
@@ -0,0 +0,0 @@ public record PlayerChatMessage(SignedMessageLink link, @Nullable MessageSignatu
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
@@ -0,0 +0,0 @@ public record PlayerChatMessage(
}
public PlayerChatMessage withUnsignedContent(Component unsignedContent) {

View File

@ -62,11 +62,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonDeathPhase.java
@@ -0,0 +0,0 @@ public class DragonDeathPhase extends AbstractDragonPhaseInstance {
public void doServerTick() {
++this.time;
if (this.targetLocation == null) {
- BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
BlockPos blockPos = this.dragon
.level()
- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
this.targetLocation = Vec3.atBottomCenterOf(blockPos);
}
@ -75,11 +75,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonHoldingPatternPhase.java
@@ -0,0 +0,0 @@ public class DragonHoldingPatternPhase extends AbstractDragonPhaseInstance {
private void findNewTarget() {
if (this.currentPath != null && this.currentPath.isDone()) {
- BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(EndPodiumFeature.getLocation(this.dragon.getFightOrigin())));
+ BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
BlockPos blockPos = this.dragon
.level()
- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(EndPodiumFeature.getLocation(this.dragon.getFightOrigin())));
+ .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(this.dragon.getPodium())); // Paper - Allow changing the EnderDragon podium
int i = this.dragon.getDragonFight() == null ? 0 : this.dragon.getDragonFight().getCrystalsAlive();
if (this.dragon.getRandom().nextInt(i + 3) == 0) {
this.dragon.getPhaseManager().setPhase(EnderDragonPhase.LANDING_APPROACH);
@ -88,12 +88,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingApproachPhase.java
@@ -0,0 +0,0 @@ public class DragonLandingApproachPhase extends AbstractDragonPhaseInstance {
private void findNewTarget() {
if (this.currentPath == null || this.currentPath.isDone()) {
int i = this.dragon.findClosestNode();
- BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
Player player = this.dragon.level().getNearestPlayer(NEAR_EGG_TARGETING, this.dragon, (double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ());
BlockPos blockPos = this.dragon
.level()
- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
Player player = this.dragon.level().getNearestPlayer(NEAR_EGG_TARGETING, this.dragon, blockPos.getX(), blockPos.getY(), blockPos.getZ());
int j;
if (player != null) {
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
@ -101,25 +101,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonLandingPhase.java
@@ -0,0 +0,0 @@ public class DragonLandingPhase extends AbstractDragonPhaseInstance {
@Override
public void doServerTick() {
if (this.targetLocation == null) {
- this.targetLocation = Vec3.atBottomCenterOf(this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin())));
+ this.targetLocation = Vec3.atBottomCenterOf(this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium())); // Paper - Allow changing the EnderDragon podium
this.targetLocation = Vec3.atBottomCenterOf(
- this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()))
+ this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()) // Paper - Allow changing the EnderDragon podium
);
}
if (this.targetLocation.distanceToSqr(this.dragon.getX(), this.dragon.getY(), this.dragon.getZ()) < 1.0D) {
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonTakeoffPhase.java
@@ -0,0 +0,0 @@ public class DragonTakeoffPhase extends AbstractDragonPhaseInstance {
@Override
public void doServerTick() {
if (!this.firstTick && this.currentPath != null) {
- BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ BlockPos blockPos = this.dragon.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
if (!blockPos.closerToCenterThan(this.dragon.position(), 10.0D)) {
BlockPos blockPos = this.dragon
.level()
- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.dragon.getFightOrigin()));
+ .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, this.dragon.getPodium()); // Paper - Allow changing the EnderDragon podium
if (!blockPos.closerToCenterThan(this.dragon.position(), 10.0)) {
this.dragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java

View File

@ -1009,13 +1009,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static void extractChunkData(FriendlyByteBuf buf, LevelChunk chunk) {
+ int chunkSectionIndex = 0; // Paper - Anti-Xray
for(LevelChunkSection levelChunkSection : chunk.getSections()) {
for (LevelChunkSection levelChunkSection : chunk.getSections()) {
- levelChunkSection.getBiomes().write(buf);
+ levelChunkSection.getBiomes().write(buf, null, chunkSectionIndex); // Paper - Anti-Xray
+ chunkSectionIndex++; // Paper - Anti-Xray
}
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@ -1031,7 +1031,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
this.heightmaps = new CompoundTag();
for(Map.Entry<Heightmap.Types, Heightmap> entry : chunk.getHeightmaps()) {
for (Entry<Heightmap.Types, Heightmap> entry : chunk.getHeightmaps()) {
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacketData {
}
@ -1047,7 +1047,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
this.blockEntitiesData = Lists.newArrayList();
for(Map.Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
for (Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacketData {
return byteBuf;
}
@ -1058,14 +1058,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static void extractChunkData(FriendlyByteBuf buf, LevelChunk chunk, com.destroystokyo.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+ int chunkSectionIndex = 0;
+
for(LevelChunkSection levelChunkSection : chunk.getSections()) {
for (LevelChunkSection levelChunkSection : chunk.getSections()) {
- levelChunkSection.write(buf);
+ levelChunkSection.write(buf, chunkPacketInfo, chunkSectionIndex);
+ chunkSectionIndex++;
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
@ -1146,10 +1146,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { // Paper - rewrite chunk loader - public
handler.player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(chunk.getPos().toLong()).addPlayer(handler.player);
- handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null));
- handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), null, null));
+ // Paper start - Anti-Xray
+ final boolean shouldModify = world.chunkPacketBlockController.shouldModify(handler.player, chunk);
+ handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null, shouldModify));
+ handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), null, null, shouldModify));
+ // Paper end - Anti-Xray
// Paper start - PlayerChunkLoadEvent
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
@ -1284,8 +1284,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -0,0 +0,0 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return 0;
};
private static final int MIN_PALETTE_BITS = 0;
private final PaletteResize<T> dummyPaletteResize = (newSize, added) -> 0;
public final IdMap<T> registry;
+ private final T @org.jetbrains.annotations.Nullable [] presetValues; // Paper - Anti-Xray - Add preset values
private volatile PalettedContainer.Data<T> data;
@ -1308,20 +1308,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static <T> Codec<PalettedContainerRO<T>> codecRO(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy paletteProvider, T defaultValue) {
PalettedContainerRO.Unpacker<T, PalettedContainerRO<T>> unpacker = (idListx, paletteProviderx, serialized) -> {
- return unpack(idListx, paletteProviderx, serialized).map((result) -> {
+ return unpack(idListx, paletteProviderx, serialized, defaultValue, null).map((result) -> { // Paper - Anti-Xray - Add preset values
return result;
});
};
PalettedContainerRO.Unpacker<T, PalettedContainerRO<T>> unpacker = (idListx, paletteProviderx, serialized) -> unpack(
- idListx, paletteProviderx, serialized
+ idListx, paletteProviderx, serialized, defaultValue, null // Paper - Anti-Xray - Add preset values
)
.map(result -> (PalettedContainerRO<T>)result);
return codec(idList, entryCodec, paletteProvider, defaultValue, unpacker);
@@ -0,0 +0,0 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
});
);
}
- public PalettedContainer(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainer.Configuration<T> dataProvider, BitStorage storage, List<T> paletteEntries) {
+ // Paper start - Anti-Xray - Add preset values
+ @Deprecated @io.papermc.paper.annotation.DoNotUse public PalettedContainer(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainer.Configuration<T> dataProvider, BitStorage storage, List<T> paletteEntries) { this(idList, paletteProvider, dataProvider, storage, paletteEntries, null, null); }
+ public PalettedContainer(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainer.Configuration<T> dataProvider, BitStorage storage, List<T> paletteEntries, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues) {
public PalettedContainer(
IdMap<T> idList,
PalettedContainer.Strategy paletteProvider,
PalettedContainer.Configuration<T> dataProvider,
BitStorage storage,
- List<T> paletteEntries
+ List<T> paletteEntries, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues
) {
+ this.presetValues = presetValues;
this.registry = idList;
this.strategy = paletteProvider;
@ -1369,7 +1375,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
this.strategy = paletteProvider;
this.registry = idList;
this.data = this.createOrReuseData((PalettedContainer.Data<T>)null, 0);
this.data = this.createOrReuseData(null, 0);
@@ -0,0 +0,0 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@Override
public synchronized int onResize(int newBits, T object) { // Paper - synchronize
@ -1413,7 +1419,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} finally {
this.release();
}
}
+ // Paper start - Anti-Xray; Add chunk packet info
@ -1435,14 +1440,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} finally {
this.release();
}
}
- private static <T> DataResult<PalettedContainer<T>> unpack(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainerRO.PackedData<T> serialized) {
+ private static <T> DataResult<PalettedContainer<T>> unpack(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainerRO.PackedData<T> serialized, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues) { // Paper - Anti-Xray - Add preset values
private static <T> DataResult<PalettedContainer<T>> unpack(
- IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainerRO.PackedData<T> serialized
+ IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainerRO.PackedData<T> serialized, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues // Paper - Anti-Xray - Add preset values
) {
List<T> list = serialized.paletteEntries();
int i = paletteProvider.size();
int j = paletteProvider.calculateBitsForSerialization(idList, list.size());
@@ -0,0 +0,0 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
}
}

View File

@ -772,6 +772,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public class RegionFileVersion {
- private static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>();
+ public static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>(); // Paper - private -> public
public static final RegionFileVersion VERSION_GZIP = register(new RegionFileVersion(1, (stream) -> {
return new FastBufferedInputStream(new GZIPInputStream(stream));
}, (stream) -> {
public static final RegionFileVersion VERSION_GZIP = register(
new RegionFileVersion(
1, stream -> new FastBufferedInputStream(new GZIPInputStream(stream)), stream -> new BufferedOutputStream(new GZIPOutputStream(stream))

View File

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/com/mojang/math/OctahedralGroup.java
@@ -0,0 +0,0 @@ public enum OctahedralGroup implements StringRepresentable {
this.permutation = axisTransformation;
this.transformation = (new Matrix3f()).scaling(flipX ? -1.0F : 1.0F, flipY ? -1.0F : 1.0F, flipZ ? -1.0F : 1.0F);
this.transformation = new Matrix3f().scaling(flipX ? -1.0F : 1.0F, flipY ? -1.0F : 1.0F, flipZ ? -1.0F : 1.0F);
this.transformation.mul(axisTransformation.transformation());
+ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
}

View File

@ -102,14 +102,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java
+++ b/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java
@@ -0,0 +0,0 @@ public class ServerPacksSource extends BuiltInPackSource {
@VisibleForTesting
public static VanillaPackResources createVanillaPackSource() {
- return (new VanillaPackResourcesBuilder()).setMetadata(BUILT_IN_METADATA).exposeNamespace("minecraft").applyDevelopmentConfig().pushJarResources().build();
+ return (new VanillaPackResourcesBuilder()).setMetadata(BUILT_IN_METADATA).exposeNamespace("minecraft", ResourceLocation.PAPER_NAMESPACE).applyDevelopmentConfig().pushJarResources().build(); // Paper
}
@Override
return new VanillaPackResourcesBuilder()
.setMetadata(BUILT_IN_METADATA)
- .exposeNamespace("minecraft")
+ .exposeNamespace("minecraft", ResourceLocation.PAPER_NAMESPACE) // Paper
.applyDevelopmentConfig()
.pushJarResources()
.build();
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java

View File

@ -65,14 +65,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final RandomState randomState;
private final LevelHeightAccessor heightAccessor;
@@ -0,0 +0,0 @@ public class StructureCheck {
private final Long2ObjectMap<Object2IntMap<Structure>> loadedChunks = new Long2ObjectOpenHashMap<>();
private final Map<Structure, Long2BooleanMap> featureChecks = new HashMap<>();
- public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureTemplateManager structureTemplateManager, ResourceKey<Level> worldKey, ChunkGenerator chunkGenerator, RandomState noiseConfig, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) {
+ public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureTemplateManager structureTemplateManager, ResourceKey<net.minecraft.world.level.dimension.LevelStem> worldKey, ChunkGenerator chunkGenerator, RandomState noiseConfig, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) { // Paper - fix missing CB diff
this.storageAccess = chunkIoWorker;
this.registryAccess = registryManager;
this.structureTemplateManager = structureTemplateManager;
ChunkScanAccess chunkIoWorker,
RegistryAccess registryManager,
StructureTemplateManager structureTemplateManager,
- ResourceKey<Level> worldKey,
+ ResourceKey<net.minecraft.world.level.dimension.LevelStem> worldKey, // Paper - fix missing CB diff
ChunkGenerator chunkGenerator,
RandomState noiseConfig,
LevelHeightAccessor world,
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java

View File

@ -28,11 +28,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!this.isReadyToHatch(state)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2)) {
+ rescheduleTick(world, pos);
+ this.rescheduleTick(world, pos);
+ return;
+ }
+ // Paper end
world.playSound((Player)null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- world.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
} else {
// Paper start - Call BlockFadeEvent

View File

@ -28,5 +28,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - Call BlockPhysicsEvent
if (this.idx < NeighborUpdater.UPDATE_ORDER.length && NeighborUpdater.UPDATE_ORDER[this.idx] == this.skipDirection) {
++this.idx;
this.idx++;
}

View File

@ -99,5 +99,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.name = Component.Serializer.fromJson(nbt.getString("CustomName"));
+ this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
}
}

View File

@ -2470,14 +2470,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
@@ -0,0 +0,0 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
- if (!this.box.intersects((double)i, (double)j, (double)k, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)) {
+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(this.box, (double)i, (double)j, (double)k, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)) { // Paper - keep vanilla behavior for voxelshape intersection - See comment in CollisionUtil
continue;
}
// Paper end
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
- if (this.box.intersects(i, j, k, i + 1.0, j + 1.0, k + 1.0)) {
+ if (io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(this.box, i, j, k, i + 1.0, j + 1.0, k + 1.0)) { // Paper - keep vanilla behavior for voxelshape intersection - See comment in CollisionUtil
return this.resultProvider.apply(this.pos, voxelShape.move(i, j, k));
}
} else {
diff --git a/src/main/java/net/minecraft/world/level/ClipContext.java b/src/main/java/net/minecraft/world/level/ClipContext.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/ClipContext.java
@ -2508,7 +2508,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - optimise collisions
+
default boolean noCollision(AABB box) {
return this.noCollision((Entity)null, box);
return this.noCollision(null, box);
}
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -2522,8 +2522,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (shape.isEmpty()) {
- return true;
- } else {
- for(Entity entity : this.getEntities(except, shape.bounds())) {
- if (!entity.isRemoved() && entity.blocksBuilding && (except == null || !entity.isPassengerOfSameVehicle(except)) && Shapes.joinIsNotEmpty(shape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) {
- for (Entity entity : this.getEntities(except, shape.bounds())) {
- if (!entity.isRemoved()
- && entity.blocksBuilding
- && (except == null || !entity.isPassengerOfSameVehicle(except))
- && Shapes.joinIsNotEmpty(shape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) {
- return false;
+ return false;
+ }
@ -2561,7 +2564,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
default List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AABB box) {
- if (box.getSize() < 1.0E-7D) {
- if (box.getSize() < 1.0E-7) {
- return List.of();
+ // Paper start - optimise collisions
+ // first behavior change is to correctly check for empty AABB
@ -2580,21 +2583,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ entities = this.getEntities(entity, box, null);
} else {
- Predicate<Entity> predicate = entity == null ? EntitySelector.CAN_BE_COLLIDED_WITH : EntitySelector.NO_SPECTATORS.and(entity::canCollideWith);
- List<Entity> list = this.getEntities(entity, box.inflate(1.0E-7D), predicate);
- List<Entity> list = this.getEntities(entity, box.inflate(1.0E-7), predicate);
- if (list.isEmpty()) {
- return List.of();
- } else {
- ImmutableList.Builder<VoxelShape> builder = ImmutableList.builderWithExpectedSize(list.size());
- Builder<VoxelShape> builder = ImmutableList.builderWithExpectedSize(list.size());
-
- for(Entity entity2 : list) {
- for (Entity entity2 : list) {
- builder.add(Shapes.create(entity2.getBoundingBox()));
- }
+ entities = this.getHardCollidingEntities(entity, box, null);
+ }
+
+ final List<VoxelShape> ret = new java.util.ArrayList<>(Math.min(25, entities.size()));
- return builder.build();
+ final List<VoxelShape> ret = new java.util.ArrayList<>(Math.min(25, entities.size()));
+
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ final Entity otherEntity = entities.get(i);
+
@ -3234,23 +3237,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
+
public AABB(BlockPos pos) {
this((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 1), (double)(pos.getZ() + 1));
this(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
}
@@ -0,0 +0,0 @@ public class AABB {
}
@Nullable
- private static Direction getDirection(AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ) {
+ public static Direction getDirection(AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ) { // Paper - optimise collisions - public
if (deltaX > 1.0E-7D) {
approachDirection = clipPoint(traceDistanceResult, approachDirection, deltaX, deltaY, deltaZ, box.minX, box.minY, box.maxY, box.minZ, box.maxZ, Direction.WEST, intersectingVector.x, intersectingVector.y, intersectingVector.z);
} else if (deltaX < -1.0E-7D) {
- private static Direction getDirection(
+ public static Direction getDirection( // Paper - optimise collisions - public
AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ
) {
if (deltaX > 1.0E-7) {
diff --git a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
@@ -0,0 +0,0 @@ public class ArrayVoxelShape extends VoxelShape {
this(shape, (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(xPoints, shape.getXSize() + 1)), (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(yPoints, shape.getYSize() + 1)), (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(zPoints, shape.getZSize() + 1)));
);
}
- ArrayVoxelShape(DiscreteVoxelShape shape, DoubleList xPoints, DoubleList yPoints, DoubleList zPoints) {
@ -3259,8 +3262,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
int i = shape.getXSize() + 1;
int j = shape.getYSize() + 1;
@@ -0,0 +0,0 @@ public class ArrayVoxelShape extends VoxelShape {
} else {
throw (IllegalArgumentException)Util.pauseInIde(new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape."));
new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape.")
);
}
+ this.initCache(); // Paper - optimise collisions
}
@ -3305,11 +3308,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start - optimise collisions
+ // called with the shape of a VoxelShape, so we can expect the cache to exist
+ final io.papermc.paper.util.collisions.CachedShapeData cache = voxelSet.getOrCreateCachedShapeData();
+
- for (int i = 0; i < bitSetDiscreteVoxelShape.ySize; i++) {
- for (int j = 0; j < bitSetDiscreteVoxelShape.xSize; j++) {
- int k = -1;
+ final int sizeX = cache.sizeX();
+ final int sizeY = cache.sizeY();
+ final int sizeZ = cache.sizeZ();
+
- for (int l = 0; l <= bitSetDiscreteVoxelShape.zSize; l++) {
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
- if (coalesce) {
- if (k == -1) {
- k = l;
- }
- } else {
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
+ int indexX;
+ int indexY = 0;
+ int indexZ;
@ -3339,21 +3353,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else {
+ // same notes about loop order as the above
+ // this branch is actually important to optimise, as it affects uncached toAabbs() (which affects optimize())
- for(int i = 0; i < bitSetDiscreteVoxelShape.ySize; ++i) {
- for(int j = 0; j < bitSetDiscreteVoxelShape.xSize; ++j) {
- int k = -1;
+
+ // only clone when we may write to it
+ bitset = bitset.clone();
- for(int l = 0; l <= bitSetDiscreteVoxelShape.zSize; ++l) {
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
- if (coalesce) {
- if (k == -1) {
- k = l;
- }
- } else {
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
+
+ for (int y = 0; y < sizeY; ++y, indexY += incY) {
+ indexX = indexY;
+ for (int x = 0; x < sizeX; ++x, indexX += incX) {
@ -3368,17 +3371,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- int n = i;
- bitSetDiscreteVoxelShape.clearZStrip(k, l, j, i);
-
- while(bitSetDiscreteVoxelShape.isZStripFull(k, l, m + 1, i)) {
- while (bitSetDiscreteVoxelShape.isZStripFull(k, l, m + 1, i)) {
- bitSetDiscreteVoxelShape.clearZStrip(k, l, m + 1, i);
- ++m;
- m++;
+
+ int lastSetZ = io.papermc.paper.util.collisions.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
+ if (lastSetZ == -1) {
+ lastSetZ = endIndex;
}
- while(bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
- for(int o = j; o <= m; ++o) {
- while (bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
- for (int o = j; o <= m; o++) {
- bitSetDiscreteVoxelShape.clearZStrip(k, l, o, n + 1);
+ io.papermc.paper.util.collisions.FlatBitsetUtil.clearRange(bitset, firstSetZ, lastSetZ);
+
@ -3408,7 +3411,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
}
- ++n;
- n++;
+ ++endY;
+
+ // passed, so we can clear it
@ -3426,7 +3429,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
}
-
+ // Paper end - optimise collisions
}
@ -3539,8 +3541,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
@@ -0,0 +0,0 @@ public final class Shapes {
public static final double EPSILON = 1.0E-7D;
public static final double BIG_EPSILON = 1.0E-6D;
public static final double EPSILON = 1.0E-7;
public static final double BIG_EPSILON = 1.0E-6;
private static final VoxelShape BLOCK = Util.make(() -> {
- DiscreteVoxelShape discreteVoxelShape = new BitSetDiscreteVoxelShape(1, 1, 1);
- discreteVoxelShape.fill(0, 0, 0);
@ -3555,8 +3557,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ );
+ // Paper end - optimise collisions - force arrayvoxelshape
});
public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})));
public static final VoxelShape INFINITY = box(
Double.NEGATIVE_INFINITY,
@@ -0,0 +0,0 @@ public final class Shapes {
new DoubleArrayList(new double[]{0.0})
);
+ // Paper start - optimise collisions - force arrayvoxelshape
+ private static final DoubleArrayList[] PARTS_BY_BITS = new DoubleArrayList[] {
@ -3588,13 +3593,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public final class Shapes {
public static VoxelShape create(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
if (!(maxX - minX < 1.0E-7D) && !(maxY - minY < 1.0E-7D) && !(maxZ - minZ < 1.0E-7D)) {
if (!(maxX - minX < 1.0E-7) && !(maxY - minY < 1.0E-7) && !(maxZ - minZ < 1.0E-7)) {
- int i = findBits(minX, maxX);
- int j = findBits(minY, maxY);
- int k = findBits(minZ, maxZ);
- if (i >= 0 && j >= 0 && k >= 0) {
- if (i == 0 && j == 0 && k == 0) {
- return block();
- if (i < 0 || j < 0 || k < 0) {
- return new ArrayVoxelShape(
- BLOCK.shape,
- DoubleArrayList.wrap(new double[]{minX, maxX}),
- DoubleArrayList.wrap(new double[]{minY, maxY}),
- DoubleArrayList.wrap(new double[]{minZ, maxZ})
- );
- } else if (i == 0 && j == 0 && k == 0) {
- return block();
+ // Paper start - optimise collisions
+ // force ArrayVoxelShape in every case
+ final int bitsX = findBits(minX, maxX);
@ -3603,12 +3614,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (bitsX >= 0 && bitsY >= 0 && bitsZ >= 0) {
+ if (bitsX == 0 && bitsY == 0 && bitsZ == 0) {
+ return BLOCK;
} else {
- int l = 1 << i;
- int m = 1 << j;
- int n = 1 << k;
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.withFilledBounds(l, m, n, (int)Math.round(minX * (double)l), (int)Math.round(minY * (double)m), (int)Math.round(minZ * (double)n), (int)Math.round(maxX * (double)l), (int)Math.round(maxY * (double)m), (int)Math.round(maxZ * (double)n));
- return new CubeVoxelShape(bitSetDiscreteVoxelShape);
+ } else {
+ final int sizeX = 1 << bitsX;
+ final int sizeY = 1 << bitsY;
+ final int sizeZ = 1 << bitsZ;
@ -3623,15 +3629,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ PARTS_BY_BITS[bitsY],
+ PARTS_BY_BITS[bitsZ]
+ );
}
+ }
} else {
- return new ArrayVoxelShape(BLOCK.shape, (DoubleList)DoubleArrayList.wrap(new double[]{minX, maxX}), (DoubleList)DoubleArrayList.wrap(new double[]{minY, maxY}), (DoubleList)DoubleArrayList.wrap(new double[]{minZ, maxZ}));
- int l = 1 << i;
- int m = 1 << j;
- int n = 1 << k;
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.withFilledBounds(
- l,
- m,
- n,
- (int)Math.round(minX * l),
- (int)Math.round(minY * m),
- (int)Math.round(minZ * n),
- (int)Math.round(maxX * l),
- (int)Math.round(maxY * m),
- (int)Math.round(maxZ * n)
+ return new ArrayVoxelShape(
+ BLOCK.shape,
+ minX == 0.0 && maxX == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minX, maxX }),
+ minY == 0.0 && maxY == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minY, maxY }),
+ minZ == 0.0 && maxZ == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minZ, maxZ })
+ );
);
- return new CubeVoxelShape(bitSetDiscreteVoxelShape);
}
+ // Paper end - optimise collisions
} else {
@ -3699,9 +3718,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- } else {
- IndexMerger indexMerger = createIndexMerger(1, one.getCoords(Direction.Axis.X), two.getCoords(Direction.Axis.X), bl, bl2);
- IndexMerger indexMerger2 = createIndexMerger(indexMerger.size() - 1, one.getCoords(Direction.Axis.Y), two.getCoords(Direction.Axis.Y), bl, bl2);
- IndexMerger indexMerger3 = createIndexMerger((indexMerger.size() - 1) * (indexMerger2.size() - 1), one.getCoords(Direction.Axis.Z), two.getCoords(Direction.Axis.Z), bl, bl2);
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.join(one.shape, two.shape, indexMerger, indexMerger2, indexMerger3, function);
- return (VoxelShape)(indexMerger instanceof DiscreteCubeMerger && indexMerger2 instanceof DiscreteCubeMerger && indexMerger3 instanceof DiscreteCubeMerger ? new CubeVoxelShape(bitSetDiscreteVoxelShape) : new ArrayVoxelShape(bitSetDiscreteVoxelShape, indexMerger.getList(), indexMerger2.getList(), indexMerger3.getList()));
- IndexMerger indexMerger3 = createIndexMerger(
- (indexMerger.size() - 1) * (indexMerger2.size() - 1), one.getCoords(Direction.Axis.Z), two.getCoords(Direction.Axis.Z), bl, bl2
- );
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.join(
- one.shape, two.shape, indexMerger, indexMerger2, indexMerger3, function
- );
- return (VoxelShape)(indexMerger instanceof DiscreteCubeMerger
- && indexMerger2 instanceof DiscreteCubeMerger
- && indexMerger3 instanceof DiscreteCubeMerger
- ? new CubeVoxelShape(bitSetDiscreteVoxelShape)
- : new ArrayVoxelShape(bitSetDiscreteVoxelShape, indexMerger.getList(), indexMerger2.getList(), indexMerger3.getList()));
- }
- }
+ return io.papermc.paper.util.CollisionUtil.joinUnoptimized(one, two, function); // Paper - optimise collisions
@ -3720,19 +3747,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- boolean bl3 = predicate.apply(true, false);
- boolean bl4 = predicate.apply(false, true);
-
- for(Direction.Axis axis : AxisCycle.AXIS_VALUES) {
- if (shape1.max(axis) < shape2.min(axis) - 1.0E-7D) {
- for (Direction.Axis axis : AxisCycle.AXIS_VALUES) {
- if (shape1.max(axis) < shape2.min(axis) - 1.0E-7) {
- return bl3 || bl4;
- }
-
- if (shape2.max(axis) < shape1.min(axis) - 1.0E-7D) {
- if (shape2.max(axis) < shape1.min(axis) - 1.0E-7) {
- return bl3 || bl4;
- }
- }
-
- IndexMerger indexMerger = createIndexMerger(1, shape1.getCoords(Direction.Axis.X), shape2.getCoords(Direction.Axis.X), bl3, bl4);
- IndexMerger indexMerger2 = createIndexMerger(indexMerger.size() - 1, shape1.getCoords(Direction.Axis.Y), shape2.getCoords(Direction.Axis.Y), bl3, bl4);
- IndexMerger indexMerger3 = createIndexMerger((indexMerger.size() - 1) * (indexMerger2.size() - 1), shape1.getCoords(Direction.Axis.Z), shape2.getCoords(Direction.Axis.Z), bl3, bl4);
- IndexMerger indexMerger2 = createIndexMerger(
- indexMerger.size() - 1, shape1.getCoords(Direction.Axis.Y), shape2.getCoords(Direction.Axis.Y), bl3, bl4
- );
- IndexMerger indexMerger3 = createIndexMerger(
- (indexMerger.size() - 1) * (indexMerger2.size() - 1), shape1.getCoords(Direction.Axis.Z), shape2.getCoords(Direction.Axis.Z), bl3, bl4
- );
- return joinIsNotEmpty(indexMerger, indexMerger2, indexMerger3, shape1.shape, shape2.shape, predicate);
- }
- } else {
@ -3742,7 +3773,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return io.papermc.paper.util.CollisionUtil.isJoinNonEmpty(shape1, shape2, predicate); // Paper - optimise collisions
}
private static boolean joinIsNotEmpty(IndexMerger mergedX, IndexMerger mergedY, IndexMerger mergedZ, DiscreteVoxelShape shape1, DiscreteVoxelShape shape2, BooleanOp predicate) {
private static boolean joinIsNotEmpty(
@@ -0,0 +0,0 @@ public final class Shapes {
}
@ -3758,6 +3789,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ if (shape.isEmpty() | neighbor.isEmpty()) {
+ return false;
+ }
+
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
+ final VoxelShape newFirst = shape.getFaceShapeClamped(direction);
+ if (newFirst.isEmpty()) {
return false;
- } else {
- Direction.Axis axis = direction.getAxis();
@ -3765,15 +3803,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? shape : neighbor;
- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? neighbor : shape;
- BooleanOp booleanOp = axisDirection == Direction.AxisDirection.POSITIVE ? BooleanOp.ONLY_FIRST : BooleanOp.ONLY_SECOND;
- return DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0D, 1.0E-7D) && DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0D, 1.0E-7D) && !joinIsNotEmpty(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), booleanOp);
- return DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)
- && DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)
- && !joinIsNotEmpty(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), booleanOp);
}
+
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
+ final VoxelShape newFirst = shape.getFaceShapeClamped(direction);
+ if (newFirst.isEmpty()) {
+ return false;
+ }
+ final VoxelShape newSecond = neighbor.getFaceShapeClamped(direction.getOpposite());
+ if (newSecond.isEmpty()) {
+ return false;
@ -3791,10 +3824,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- boolean bl;
- int i;
- if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
- bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0D, 1.0E-7D);
- bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0, 1.0E-7);
- i = shape.shape.getSize(axis) - 1;
- } else {
- bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0D, 1.0E-7D);
- bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0, 1.0E-7);
- i = 0;
- }
+ return shape.getFaceShapeClamped(direction); // Paper - optimise collisions
@ -3828,7 +3861,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- Direction.AxisDirection axisDirection = direction.getAxisDirection();
- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? one : two;
- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? two : one;
- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0D, 1.0E-7D)) {
- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)) {
- voxelShape = empty();
- }
+ // Paper start - optimise collisions
@ -3837,14 +3870,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return true;
+ }
- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0D, 1.0E-7D)) {
- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)) {
- voxelShape2 = empty();
- }
+ if (one.isEmpty() & two.isEmpty()) {
+ return false;
+ }
- return !joinIsNotEmpty(block(), joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR), BooleanOp.ONLY_FIRST);
- return !joinIsNotEmpty(
- block(),
- joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR),
- BooleanOp.ONLY_FIRST
- );
- } else {
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
@ -3876,17 +3913,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static boolean faceShapeOccludes(VoxelShape one, VoxelShape two) {
- if (one != block() && two != block()) {
- if (one.isEmpty() && two.isEmpty()) {
- return false;
- } else {
- return !joinIsNotEmpty(block(), joinUnoptimized(one, two, BooleanOp.OR), BooleanOp.ONLY_FIRST);
- }
- } else {
- return one == block()
- || two == block()
- || (!one.isEmpty() || !two.isEmpty()) && !joinIsNotEmpty(block(), joinUnoptimized(one, two, BooleanOp.OR), BooleanOp.ONLY_FIRST);
+ // Paper start - optimise collisions
+ if (one.occludesFullBlockIfCached() || two.occludesFullBlockIfCached()) {
return true;
}
+ return true;
+ }
+
+ final boolean s1Empty = one.isEmpty();
+ final boolean s2Empty = two.isEmpty();
@ -3937,7 +3970,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private double offsetX;
+ private double offsetY;
+ private double offsetZ;
+ private AABB singleAABBRepresentation;
+ @Nullable private AABB singleAABBRepresentation;
+ private double[] rootCoordinatesX;
+ private double[] rootCoordinatesY;
+ private double[] rootCoordinatesZ;
@ -4335,15 +4368,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (this.isEmpty()) {
- throw (UnsupportedOperationException)Util.pauseInIde(new UnsupportedOperationException("No bounds for empty shape."));
- } else {
- return new AABB(this.min(Direction.Axis.X), this.min(Direction.Axis.Y), this.min(Direction.Axis.Z), this.max(Direction.Axis.X), this.max(Direction.Axis.Y), this.max(Direction.Axis.Z));
- return new AABB(
- this.min(Direction.Axis.X),
- this.min(Direction.Axis.Y),
- this.min(Direction.Axis.Z),
- this.max(Direction.Axis.X),
- this.max(Direction.Axis.Y),
- this.max(Direction.Axis.Z)
- );
+ // Paper start - optimise collisions
+ if (this.isEmpty) {
+ throw Util.pauseInIde(new UnsupportedOperationException("No bounds for empty shape."));
}
+ }
+ AABB cached = this.cachedBounds;
+ if (cached != null) {
+ return cached;
+ }
}
+
+ final io.papermc.paper.util.collisions.CachedShapeData shapeData = this.cachedShapeData;
+
@ -4378,26 +4418,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean isEmpty() {
- return this.shape.isEmpty();
+ return this.isEmpty; // Paper - optimise collisions
}
+ }
+
+ // Paper start - optimise collisions
+ private static DoubleList offsetList(final DoubleList src, final double by) {
+ if (src instanceof OffsetDoubleList offsetDoubleList) {
+ return new OffsetDoubleList(offsetDoubleList.delegate, by + offsetDoubleList.offset);
+ }
+ return new OffsetDoubleList(src, by);
+ }
}
+ // Paper end - optimise collisions
+
public VoxelShape move(double x, double y, double z) {
- return (VoxelShape)(this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.X), x)), (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y)), (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))));
- return (VoxelShape)(this.isEmpty()
- ? Shapes.empty()
- : new ArrayVoxelShape(
+ // Paper start - optimise collisions
+ if (this.isEmpty) {
+ return Shapes.empty();
+ }
+
+ final ArrayVoxelShape ret = new ArrayVoxelShape(
+ this.shape,
this.shape,
- new OffsetDoubleList(this.getCoords(Direction.Axis.X), x),
- new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y),
- new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z)
- ));
+ offsetList(this.getCoords(Direction.Axis.X), x),
+ offsetList(this.getCoords(Direction.Axis.Y), y),
+ offsetList(this.getCoords(Direction.Axis.Z), z)
@ -4414,9 +4460,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public VoxelShape optimize() {
- VoxelShape[] voxelShapes = new VoxelShape[]{Shapes.empty()};
- this.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> {
- voxelShapes[0] = Shapes.joinUnoptimized(voxelShapes[0], Shapes.box(minX, minY, minZ, maxX, maxY, maxZ), BooleanOp.OR);
- });
- this.forAllBoxes(
- (minX, minY, minZ, maxX, maxY, maxZ) -> voxelShapes[0] = Shapes.joinUnoptimized(
- voxelShapes[0], Shapes.box(minX, minY, minZ, maxX, maxY, maxZ), BooleanOp.OR
- )
- );
- return voxelShapes[0];
+ // Paper start - optimise collisions
+ // Optimise merge strategy to increase the number of simple joins, and additionally forward the toAabbs cache
@ -4487,7 +4535,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void forAllEdges(Shapes.DoubleLineConsumer consumer) {
@@ -0,0 +0,0 @@ public abstract class VoxelShape {
}, true);
);
}
+ // Paper start - optimise collisions
@ -4510,9 +4558,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
public List<AABB> toAabbs() {
- List<AABB> list = Lists.newArrayList();
- this.forAllBoxes((x1, y1, z1, x2, y2, z2) -> {
- list.add(new AABB(x1, y1, z1, x2, y2, z2));
- });
- this.forAllBoxes((x1, y1, z1, x2, y2, z2) -> list.add(new AABB(x1, y1, z1, x2, y2, z2)));
- return list;
+ // Paper start - optimise collisions
+ io.papermc.paper.util.collisions.CachedToAABBs cachedToAABBs = this.cachedToAABBs;
@ -4536,7 +4582,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public double min(Direction.Axis axis, double from, double to) {
@@ -0,0 +0,0 @@ public abstract class VoxelShape {
}) - 1;
return Mth.binarySearch(0, this.shape.getSize(axis) + 1, i -> coord < this.get(axis, i)) - 1;
}
+ // Paper start - optimise collisions
@ -4568,11 +4614,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return null;
- } else {
- Vec3 vec3 = end.subtract(start);
- if (vec3.lengthSqr() < 1.0E-7D) {
- if (vec3.lengthSqr() < 1.0E-7) {
- return null;
- } else {
- Vec3 vec32 = start.add(vec3.scale(0.001D));
- return this.shape.isFullWide(this.findIndex(Direction.Axis.X, vec32.x - (double)pos.getX()), this.findIndex(Direction.Axis.Y, vec32.y - (double)pos.getY()), this.findIndex(Direction.Axis.Z, vec32.z - (double)pos.getZ())) ? new BlockHitResult(vec32, Direction.getNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true) : AABB.clip(this.toAabbs(), start, end, pos);
- Vec3 vec32 = start.add(vec3.scale(0.001));
- return this.shape
- .isFullWide(
- this.findIndex(Direction.Axis.X, vec32.x - pos.getX()),
- this.findIndex(Direction.Axis.Y, vec32.y - pos.getY()),
- this.findIndex(Direction.Axis.Z, vec32.z - pos.getZ())
- )
- ? new BlockHitResult(vec32, Direction.getNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true)
- : AABB.clip(this.toAabbs(), start, end, pos);
+ }
+
+ final Vec3 directionOpposite = end.subtract(start);
@ -4615,10 +4668,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (vec3s[0] == null || target.distanceToSqr(d, e, f) < target.distanceToSqr(vec3s[0])) {
- vec3s[0] = new Vec3(d, e, f);
- }
+ }
- });
- return Optional.of(vec3s[0]);
}
+
+ Vec3 ret = null;
+ double retDistance = Double.MAX_VALUE;
+
@ -4634,7 +4687,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ret = new Vec3(x, y, z);
+ retDistance = dist;
+ }
}
+ }
+
+ return Optional.ofNullable(ret);
+ // Paper end - optimise collisions

View File

@ -30,7 +30,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
Vec3 vec3 = context.getParamOrNull(LootContextParams.ORIGIN);
if (vec3 != null) {
ServerLevel serverLevel = context.getLevel();
- BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, BlockPos.containing(vec3), this.searchRadius, this.skipKnownStructures);
+ // Paper start - Configurable cartographer treasure maps
+ if (!serverLevel.paperConfig().environment.treasureMaps.enabled) {
+ /*
@ -39,8 +38,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ */
+ return stack;
+ }
+ BlockPos blockPos = serverLevel.findNearestMapStructure(this.destination, BlockPos.containing(vec3), this.searchRadius, !serverLevel.paperConfig().environment.treasureMaps.findAlreadyDiscoveredLootTable.or(!this.skipKnownStructures));
+ // Paper end - Configurable cartographer treasure maps
BlockPos blockPos = serverLevel.findNearestMapStructure(
- this.destination, BlockPos.containing(vec3), this.searchRadius, this.skipKnownStructures
+ this.destination, BlockPos.containing(vec3), this.searchRadius, !serverLevel.paperConfig().environment.treasureMaps.findAlreadyDiscoveredLootTable.or(!this.skipKnownStructures) // Paper - Configurable cartographer treasure maps
);
if (blockPos != null) {
ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), this.zoom, true, true);
MapItem.renderBiomePreviewMap(serverLevel, itemStack);

View File

@ -43,7 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected abstract class EntryBase implements LootPoolEntry {
@Override
public int getWeight(float luck) {
- return Math.max(Mth.floor((float)LootPoolSingletonContainer.this.weight + (float)LootPoolSingletonContainer.this.quality * luck), 0);
- return Math.max(Mth.floor(LootPoolSingletonContainer.this.weight + LootPoolSingletonContainer.this.quality * luck), 0);
+ // Paper start - Configurable LootPool luck formula
+ // SEE: https://luckformula.emc.gs for details and data
+ if (LootPoolSingletonContainer.this.lastLuck != null && LootPoolSingletonContainer.this.lastLuck == luck) {

View File

@ -22,9 +22,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
@@ -0,0 +0,0 @@ public class RegionFileVersion {
}, (stream) -> {
return stream;
}));
)
);
public static final RegionFileVersion VERSION_NONE = register(new RegionFileVersion(3, stream -> stream, stream -> stream));
+
+ // Paper start - Configurable region compression format
+ public static RegionFileVersion getCompressionFormat() {

View File

@ -44,8 +44,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected SculkSensorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@@ -0,0 +0,0 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
this.vibrationData = listener;
});
.resultOrPartial(LOGGER::error)
.ifPresent(listener -> this.vibrationData = listener);
}
+ // Paper start - Configurable sculk sensor listener range
+ if (nbt.contains(PAPER_LISTENER_RANGE_NBT_KEY)) {
@ -54,7 +54,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.rangeOverride = null;
+ }
+ // Paper end - Configurable sculk sensor listener range
}
+ protected static final String PAPER_LISTENER_RANGE_NBT_KEY = "Paper.ListenerRange"; // Paper - Configurable sculk sensor listener range
@ -62,9 +61,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void saveAdditional(CompoundTag nbt) {
super.saveAdditional(nbt);
@@ -0,0 +0,0 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList
VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData).resultOrPartial(LOGGER::error).ifPresent((listenerNbt) -> {
nbt.put("listener", listenerNbt);
});
.encodeStart(NbtOps.INSTANCE, this.vibrationData)
.resultOrPartial(LOGGER::error)
.ifPresent(listenerNbt -> nbt.put("listener", listenerNbt));
+ this.saveRangeOverride(nbt); // Paper - Configurable sculk sensor listener range
+ }
+ // Paper start - Configurable sculk sensor listener range

View File

@ -66,8 +66,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final List<PotionBrewing.Mix<Item>> CONTAINER_MIXES = Lists.newArrayList();
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<org.bukkit.NamespacedKey, io.papermc.paper.potion.PaperPotionMix> CUSTOM_MIXES = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Paper - Custom Potion Mixes
private static final List<Ingredient> ALLOWED_CONTAINERS = Lists.newArrayList();
private static final Predicate<ItemStack> ALLOWED_CONTAINER = (stack) -> {
for(Ingredient ingredient : ALLOWED_CONTAINERS) {
private static final Predicate<ItemStack> ALLOWED_CONTAINER = stack -> {
for (Ingredient ingredient : ALLOWED_CONTAINERS) {
@@ -0,0 +0,0 @@ public class PotionBrewing {
};
@ -86,9 +86,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return true;
+ }
+ // Paper end - Custom Potion Mixes
if (!ALLOWED_CONTAINER.test(input)) {
return false;
} else {
return ALLOWED_CONTAINER.test(input) && (hasContainerMix(input, ingredient) || hasPotionMix(input, ingredient));
}
@@ -0,0 +0,0 @@ public class PotionBrewing {
public static ItemStack mix(ItemStack ingredient, ItemStack input) {

View File

@ -284,17 +284,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
super(name, type);
this.values = ImmutableSet.copyOf(values);
@@ -0,0 +0,0 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
this.names.put(string, enum_);
}
+ // Paper start - optimise iblockdata state lookup
+ // Paper start - optimise BlockState lookup
+ int id = 0;
+ this.idLookupTable = new int[type.getEnumConstants().length];
+ java.util.Arrays.fill(this.idLookupTable, -1);
+ for (final T value : this.getPossibleValues()) {
+ this.idLookupTable[value.ordinal()] = id++;
+ }
+ // Paper end - optimise iblockdata state lookup
+ // Paper end - optimise BlockState lookup
}
@Override
@ -324,7 +324,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
@@ -0,0 +0,0 @@ public abstract class Property<T extends Comparable<T>> {
}, this::getName);
);
private final Codec<Property.Value<T>> valueCodec = this.codec.xmap(this::value, Property.Value::value);
+ // Paper start - optimise iblockdata state lookup

View File

@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator {
for(int n = -1; n <= 1; ++n) {
for (int n = -1; n <= 1; n++) {
if (l != 0 || n != 0) {
pos.set(i + l, j + m, k + n);
- BlockState blockState = world.getBlockState(pos);

View File

@ -29,4 +29,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Don't load Chunks from Hoppers and other things
if (blockState.is(state.getBlock())) {
DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState);
if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE && blockType != blockType2 && blockState.getValue(directionProperty) == state.getValue(directionProperty)) {
if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE

View File

@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ScoreboardSaveData extends SavedData {
ListTag listTag = new ListTag();
for(PlayerTeam playerTeam : this.scoreboard.getPlayerTeams()) {
for (PlayerTeam playerTeam : this.scoreboard.getPlayerTeams()) {
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().scoreboards.saveEmptyScoreboardTeams && playerTeam.getPlayers().isEmpty()) continue; // Paper - Don't save empty scoreboard teams to scoreboard.dat
CompoundTag compoundTag = new CompoundTag();
compoundTag.putString("Name", playerTeam.getName());

View File

@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ else dragonFireball.discard(null); // Paper - EnderDragon Events
this.fireballCharge = 0;
if (this.currentPath != null) {
while(!this.currentPath.isDone()) {
while (!this.currentPath.isDone()) {
diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java

View File

@ -195,7 +195,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public GoalSelector(Supplier<ProfilerFiller> profiler) {
this.profiler = profiler;
@@ -0,0 +0,0 @@ public class GoalSelector {
});
this.availableGoals.removeIf(goal -> predicate.test(goal.getGoal()));
}
+ // Paper start
@ -213,8 +213,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end
public void removeGoal(Goal goal) {
this.availableGoals.stream().filter((wrappedGoal) -> {
return wrappedGoal.getGoal() == goal;
this.availableGoals.stream().filter(wrappedGoal -> wrappedGoal.getGoal() == goal).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop);
this.availableGoals.removeIf(wrappedGoal -> wrappedGoal.getGoal() == goal);
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
@ -310,9 +310,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.setEnabled(bl);
}
+ this.immunize(); // Paper
}
public boolean isEnabled() {
@@ -0,0 +0,0 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
public boolean suckInItems() {
@ -320,7 +320,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.immunize(); // Paper
return true;
} else {
for(ItemEntity itemEntity : this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.25D, 0.0D, 0.25D), EntitySelector.ENTITY_STILL_ALIVE)) {
for (ItemEntity itemEntity : this.level()
.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.25, 0.0, 0.25), EntitySelector.ENTITY_STILL_ALIVE)) {
if (HopperBlockEntity.addItem(this, itemEntity)) {
+ this.immunize(); // Paper
return true;

View File

@ -124,14 +124,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
@@ -0,0 +0,0 @@ public class SculkShriekerBlockEntity extends BlockEntity implements GameEventLi
}
private boolean trySummonWarden(ServerLevel world) {
- return this.warningLevel < 4 ? false : SpawnUtil.trySpawnMob(EntityType.WARDEN, MobSpawnType.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER).isPresent();
+ return this.warningLevel < 4 ? false : SpawnUtil.trySpawnMob(EntityType.WARDEN, MobSpawnType.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, null).isPresent(); // Paper - Entity#getEntitySpawnReason
return this.warningLevel >= 4
- && SpawnUtil.trySpawnMob(EntityType.WARDEN, MobSpawnType.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER)
+ && SpawnUtil.trySpawnMob(EntityType.WARDEN, MobSpawnType.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, null) // Paper - Entity#getEntitySpawnReason
.isPresent();
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java

View File

@ -28,9 +28,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
- public Path createPath(BlockPos target, int distance) {
+ public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent
LevelChunk levelChunk = this.level.getChunkSource().getChunkNow(SectionPos.blockToSectionCoord(target.getX()), SectionPos.blockToSectionCoord(target.getZ()));
if (levelChunk == null) {
return null;
LevelChunk levelChunk = this.level
.getChunkSource()
.getChunkNow(SectionPos.blockToSectionCoord(target.getX()), SectionPos.blockToSectionCoord(target.getZ()));
@@ -0,0 +0,0 @@ public class GroundPathNavigation extends PathNavigation {
}
@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return super.createPath(blockPos.above(), entity, distance); // Paper - EntityPathfindEvent
}
while(blockPos.getY() < this.level.getMaxBuildHeight() && levelChunk.getBlockState(blockPos).isAir()) {
while (blockPos.getY() < this.level.getMaxBuildHeight() && levelChunk.getBlockState(blockPos).isAir()) {
@@ -0,0 +0,0 @@ public class GroundPathNavigation extends PathNavigation {
}
@ -47,8 +47,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- return super.createPath(target, distance);
+ return super.createPath(target, entity, distance); // Paper - EntityPathfindEvent
} else {
BlockPos blockPos2;
for(blockPos2 = target.above(); blockPos2.getY() < this.level.getMaxBuildHeight() && levelChunk.getBlockState(blockPos2).isSolid(); blockPos2 = blockPos2.above()) {
BlockPos blockPos2 = target.above();
@@ -0,0 +0,0 @@ public class GroundPathNavigation extends PathNavigation {
blockPos2 = blockPos2.above();
}
- return super.createPath(blockPos2, distance);
@ -109,7 +111,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - EntityPathfindEvent
if (positions.isEmpty()) {
return null;
} else if (this.mob.getY() < (double)this.level.getMinBuildHeight()) {
} else if (this.mob.getY() < this.level.getMinBuildHeight()) {
@@ -0,0 +0,0 @@ public abstract class PathNavigation {
} else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) {
return this.path;
@ -133,7 +135,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - EntityPathfindEvent
this.level.getProfiler().push("pathfind");
BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition();
int i = (int)(followRange + (float)range);
int i = (int)(followRange + range);
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/WallClimberNavigation.java

View File

@ -11,16 +11,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class DefaultGameModeCommands {
GameType gameType = minecraftServer.getForcedGameType();
if (gameType != null) {
for(ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
for (ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
- if (serverPlayer.setGameMode(gameType)) {
- ++i;
- i++;
+ // Paper start - Expand PlayerGameModeChangeEvent
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty());
+ if (event != null && event.isCancelled()) {
+ source.sendSuccess(() -> io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false);
}
+ // Paper end - Expand PlayerGameModeChangeEvent
+ ++i;
+ i++;
}
}
@ -31,13 +31,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class GameModeCommand {
int i = 0;
for(ServerPlayer serverPlayer : targets) {
for (ServerPlayer serverPlayer : targets) {
- if (serverPlayer.setGameMode(gameMode)) {
+ // Paper start - Expand PlayerGameModeChangeEvent
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty());
+ if (event != null && !event.isCancelled()) {
logGamemodeChange(context.getSource(), serverPlayer, gameMode);
++i;
i++;
+ } else if (event != null && event.cancelMessage() != null) {
+ context.getSource().sendSuccess(() -> io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true);
+ // Paper end - Expand PlayerGameModeChangeEvent

View File

@ -116,7 +116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/item/HoneycombItem.java
+++ b/src/main/java/net/minecraft/world/item/HoneycombItem.java
@@ -0,0 +0,0 @@ public class HoneycombItem extends Item implements SignApplicator {
return getWaxed(blockState).map((state) -> {
return getWaxed(blockState).map(state -> {
Player player = context.getPlayer();
ItemStack itemStack = context.getItemInHand();
+ // Paper start - EntityChangeBlockEvent
@ -163,7 +163,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
+ afterAction = () -> { // Paper
if (!level.isClientSide()) {
level.levelEvent((Player)null, 1009, blockPos, 0);
level.levelEvent(null, 1009, blockPos, 0);
}
CampfireBlock.dowse(context.getPlayer(), level, blockPos, blockState);

View File

@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ networkDataOutputStream.writeString(queryResponse.getHostname());
+ // Paper end
this.sendTo(networkDataOutputStream.toByteArray(), packet);
LOGGER.debug("Status [{}]", (Object)socketAddress);
LOGGER.debug("Status [{}]", socketAddress);
}
@@ -0,0 +0,0 @@ public class QueryThreadGs4 extends GenericThread {
this.rulesResponse.writeString("splitnum");
@ -112,13 +112,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.rulesResponse.writeString(this.worldName);
+ this.rulesResponse.writeString(queryResponse.getMap());
this.rulesResponse.writeString("numplayers");
- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount());
- this.rulesResponse.writeString(this.serverInterface.getPlayerCount() + "");
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getCurrentPlayers()));
this.rulesResponse.writeString("maxplayers");
- this.rulesResponse.writeString("" + this.maxPlayers);
- this.rulesResponse.writeString(this.maxPlayers + "");
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getMaxPlayers()));
this.rulesResponse.writeString("hostport");
- this.rulesResponse.writeString("" + this.serverPort);
- this.rulesResponse.writeString(this.serverPort + "");
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getPort()));
this.rulesResponse.writeString("hostip");
- this.rulesResponse.writeString(this.hostIp);
@ -130,5 +130,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- String[] strings = this.serverInterface.getPlayerNames();
+ String[] strings = queryResponse.getPlayers().toArray(String[]::new);
for(String string : strings) {
for (String string : strings) {
this.rulesResponse.writeString(string);

View File

@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public int lifetime;
@Nullable
public LivingEntity attachedToEntity;
+ public java.util.UUID spawningEntity; // Paper
+ @Nullable public java.util.UUID spawningEntity; // Paper
public FireworkRocketEntity(EntityType<? extends FireworkRocketEntity> type, Level world) {
super(type, world);
@ -60,9 +60,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
@@ -0,0 +0,0 @@ public class FireworkRocketItem extends Item {
Vec3 vec3 = context.getClickLocation();
Direction direction = context.getClickedFace();
FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack);
vec3.z + direction.getStepZ() * 0.15,
itemStack
);
+ fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper
level.addFreshEntity(fireworkRocketEntity);
itemStack.shrink(1);

View File

@ -21,10 +21,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener<T> conditions) {
- this.players.computeIfAbsent(manager, (managerx) -> {
+ manager.criterionData.computeIfAbsent(this, (managerx) -> { // Paper - fix AdvancementDataPlayer leak
return Sets.newHashSet();
}).add(conditions);
- this.players.computeIfAbsent(manager, managerx -> Sets.newHashSet()).add(conditions);
+ manager.criterionData.computeIfAbsent(this, managerx -> Sets.newHashSet()).add(conditions); // Paper - fix AdvancementDataPlayer leak
}
@Override
@ -38,8 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ manager.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak
}
}
@@ -0,0 +0,0 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
}
@Override
public final void removePlayerListeners(PlayerAdvancements tracker) {

View File

@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private final ShufflingList<BehaviorControl<? super E>> behaviors = new ShufflingList<>(false); // Paper - Fix Concurrency issue in ShufflingList during worldgen
private Behavior.Status status = Behavior.Status.STOPPED;
public GateBehavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState, Set<MemoryModuleType<?>> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List<Pair<? extends BehaviorControl<? super E>, Integer>> tasks) {
public GateBehavior(
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java
@ -53,9 +53,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public ShufflingList<U> shuffle() {
- this.entries.forEach((entry) -> {
- entry.setRandom(this.random.nextFloat());
- });
- this.entries.forEach(entry -> entry.setRandom(this.random.nextFloat()));
- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight));
- return this;
+ // Paper start - Fix Concurrency issue in ShufflingList during worldgen

View File

@ -14,11 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
@@ -0,0 +0,0 @@ public class VillagerGoalPackages {
private static final float STROLL_SPEED_MODIFIER = 0.4F;
public static ImmutableList<Pair<Integer, ? extends BehaviorControl<? super Villager>>> getCorePackage(VillagerProfession profession, float speed) {
- return ImmutableList.of(Pair.of(0, new Swim(0.8F)), Pair.of(0, InteractWithDoor.create()), Pair.of(0, new LookAtTargetSink(45, 90)), Pair.of(0, new VillagerPanicTrigger()), Pair.of(0, WakeUp.create()), Pair.of(0, ReactToBell.create()), Pair.of(0, SetRaidStatus.create()), Pair.of(0, ValidateNearbyPoi.create(profession.heldJobSite(), MemoryModuleType.JOB_SITE)), Pair.of(0, ValidateNearbyPoi.create(profession.acquirableJobSite(), MemoryModuleType.POTENTIAL_JOB_SITE)), Pair.of(1, new MoveToTargetSink()), Pair.of(2, PoiCompetitorScan.create()), Pair.of(3, new LookAndFollowTradingPlayerSink(speed)), Pair.of(5, GoToWantedItem.create(speed, false, 4)), Pair.of(6, AcquirePoi.create(profession.acquirableJobSite(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())), Pair.of(7, new GoToPotentialJobSite(speed)), Pair.of(8, YieldJobSite.create(speed)), Pair.of(10, AcquirePoi.create((poiType) -> {
+ return ImmutableList.of(Pair.of(0, new Swim(0.8F)), Pair.of(0, InteractWithDoor.create()), Pair.of(0, new LookAtTargetSink(45, 90)), Pair.of(0, new VillagerPanicTrigger()), Pair.of(0, WakeUp.create()), Pair.of(0, ReactToBell.create()), Pair.of(0, SetRaidStatus.create()), Pair.of(0, ValidateNearbyPoi.create(profession.heldJobSite(), MemoryModuleType.JOB_SITE)), Pair.of(0, ValidateNearbyPoi.create(profession.acquirableJobSite(), MemoryModuleType.POTENTIAL_JOB_SITE)), Pair.of(1, new MoveToTargetSink()), Pair.of(2, PoiCompetitorScan.create()), Pair.of(3, new LookAndFollowTradingPlayerSink(speed)), Pair.of(5, GoToWantedItem.create(villager -> !villager.isSleeping(), speed, false, 4)), Pair.of(6, AcquirePoi.create(profession.acquirableJobSite(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())), Pair.of(7, new GoToPotentialJobSite(speed)), Pair.of(8, YieldJobSite.create(speed)), Pair.of(10, AcquirePoi.create((poiType) -> { // Paper - Fix MC-157464
return poiType.is(PoiTypes.HOME);
}, MemoryModuleType.HOME, false, Optional.of((byte)14))), Pair.of(10, AcquirePoi.create((poiType) -> {
return poiType.is(PoiTypes.MEETING);
Pair.of(1, new MoveToTargetSink()),
Pair.of(2, PoiCompetitorScan.create()),
Pair.of(3, new LookAndFollowTradingPlayerSink(speed)),
- Pair.of(5, GoToWantedItem.create(speed, false, 4)),
+ Pair.of(5, GoToWantedItem.create(villager -> !villager.isSleeping(), speed, false, 4)), // Paper - Fix MC-157464
Pair.of(
6, AcquirePoi.create(profession.acquirableJobSite(), MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, true, Optional.empty())
),

View File

@ -32,7 +32,7 @@ diff --git a/src/main/java/net/minecraft/server/Services.java b/src/main/java/ne
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Services.java
+++ b/src/main/java/net/minecraft/server/Services.java
@@ -0,0 +0,0 @@ public record Services(MinecraftSessionService sessionService, ServicesKeySet se
@@ -0,0 +0,0 @@ public record Services(
return java.util.Objects.requireNonNull(this.paperConfigurations);
}
// Paper end - add paper configuration files

View File

@ -87,7 +87,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0F * 7))) { // Paper - Fix Spigot growth modifiers
this.advanceTree(world, pos, state, random);
}
} else {
diff --git a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java

View File

@ -91,27 +91,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/commands/DeOpCommands.java
+++ b/src/main/java/net/minecraft/server/commands/DeOpCommands.java
@@ -0,0 +0,0 @@ public class DeOpCommands {
if (playerList.isOp(gameProfile)) {
playerList.deop(gameProfile);
++i;
source.sendSuccess(() -> {
- return Component.translatable("commands.deop.success", targets.iterator().next().getName());
+ return Component.translatable("commands.deop.success", gameProfile.getName()); // Paper - fixes MC-253721
}, true);
i++;
- source.sendSuccess(() -> Component.translatable("commands.deop.success", targets.iterator().next().getName()), true);
+ source.sendSuccess(() -> Component.translatable("commands.deop.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}
diff --git a/src/main/java/net/minecraft/server/commands/OpCommand.java b/src/main/java/net/minecraft/server/commands/OpCommand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/commands/OpCommand.java
+++ b/src/main/java/net/minecraft/server/commands/OpCommand.java
@@ -0,0 +0,0 @@ public class OpCommand {
if (!playerList.isOp(gameProfile)) {
playerList.op(gameProfile);
++i;
source.sendSuccess(() -> {
- return Component.translatable("commands.op.success", targets.iterator().next().getName());
+ return Component.translatable("commands.op.success", gameProfile.getName()); // Paper - fixes MC-253721
}, true);
i++;
- source.sendSuccess(() -> Component.translatable("commands.op.success", targets.iterator().next().getName()), true);
+ source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
@ -211,7 +211,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/BegGoal.java
@@ -0,0 +0,0 @@ public class BegGoal extends Goal {
private boolean playerHoldingInteresting(Player player) {
for(InteractionHand interactionHand : InteractionHand.values()) {
for (InteractionHand interactionHand : InteractionHand.values()) {
ItemStack itemStack = player.getItemInHand(interactionHand);
- if (this.wolf.isTame() && itemStack.is(Items.BONE)) {
+ if (!this.wolf.isTame() && itemStack.is(Items.BONE)) { // Paper - Fix MC-84789
@ -268,7 +268,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -0,0 +0,0 @@ public class SwellGoal extends Goal {
return this.creeper.getSwellDir() > 0 || livingEntity != null && this.creeper.distanceToSqr(livingEntity) < 9.0D;
return this.creeper.getSwellDir() > 0 || livingEntity != null && this.creeper.distanceToSqr(livingEntity) < 9.0;
}
+ // Paper start - Fix MC-179072
@ -344,7 +344,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return 0;
} else {
+ cat.moveTo(pos, 0.0F, 0.0F); // Paper - move up - Fix MC-147659
cat.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.NATURAL, (SpawnGroupData)null, (CompoundTag)null);
cat.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.NATURAL, null, null);
- cat.moveTo(pos, 0.0F, 0.0F);
world.addFreshEntityWithPassengers(cat);
return 1;
@ -392,7 +392,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/item/BundleItem.java
+++ b/src/main/java/net/minecraft/world/item/BundleItem.java
@@ -0,0 +0,0 @@ public class BundleItem extends Item {
});
removeOne(stack).ifPresent(removedStack -> add(stack, slot.safeInsert(removedStack)));
} else if (itemStack.getItem().canFitInsideContainerItems()) {
int i = (64 - getContentWeight(stack)) / getWeight(itemStack);
- int j = add(stack, slot.safeTake(itemStack.getCount(), i, player));
@ -414,14 +414,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/item/SaddleItem.java
+++ b/src/main/java/net/minecraft/world/item/SaddleItem.java
@@ -0,0 +0,0 @@ public class SaddleItem extends Item {
if (entity instanceof Saddleable saddleable) {
if (entity.isAlive() && !saddleable.isSaddled() && saddleable.isSaddleable()) {
if (!user.level().isClientSide) {
- saddleable.equipSaddle(SoundSource.NEUTRAL);
+ saddleable.equipSaddle(SoundSource.NEUTRAL, stack.copyWithCount(1)); // Paper - Fix saddles losing nbt data - MC-191591
entity.level().gameEvent(entity, GameEvent.EQUIP, entity.position());
stack.shrink(1);
}
public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) {
if (entity instanceof Saddleable saddleable && entity.isAlive() && !saddleable.isSaddled() && saddleable.isSaddleable()) {
if (!user.level().isClientSide) {
- saddleable.equipSaddle(SoundSource.NEUTRAL);
+ saddleable.equipSaddle(SoundSource.NEUTRAL, stack.copyWithCount(1)); // Paper - Fix saddles losing nbt data - MC-191591
entity.level().gameEvent(entity, GameEvent.EQUIP, entity.position());
stack.shrink(1);
}
diff --git a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java

View File

@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/resources/RegistryOps.java
@@ -0,0 +0,0 @@ public class RegistryOps<T> extends DelegatingOps<T> {
private static RegistryOps.RegistryInfoLookup memoizeLookup(final RegistryOps.RegistryInfoLookup registryInfoGetter) {
private static RegistryOps.RegistryInfoLookup memoizeLookup(RegistryOps.RegistryInfoLookup registryInfoGetter) {
return new RegistryOps.RegistryInfoLookup() {
- private final Map<ResourceKey<? extends Registry<?>>, Optional<? extends RegistryOps.RegistryInfo<?>>> lookups = new HashMap<>();
+ // The concurrent access occurs on the Netty IO threads when serializing packets.
@ -26,8 +26,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryRef) {
- return this.lookups.computeIfAbsent(registryRef, registryInfoGetter::lookup);
+ return (Optional<RegistryOps.RegistryInfo<T>>)this.lookups.computeIfAbsent(registryRef, registryInfoGetter::lookup); // Paper - fix concurrent access to lookups field
}
};
}

View File

@ -122,9 +122,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
+++ b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
@@ -0,0 +0,0 @@ public class EntitySelectorOptions {
public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType((entity) -> {
return Component.translatableEscape("argument.entity.options.type.invalid", entity);
});
public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType(
entity -> Component.translatableEscape("argument.entity.options.type.invalid", entity)
);
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
+ public static final DynamicCommandExceptionType ERROR_ENTITY_TAG_INVALID = new DynamicCommandExceptionType((object) -> {
+ return io.papermc.paper.adventure.PaperAdventure
@ -143,14 +143,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
OPTIONS.put(id, new EntitySelectorOptions.Option(handler, condition, description));
@@ -0,0 +0,0 @@ public class EntitySelectorOptions {
if (reader.isTag()) {
TagKey<EntityType<?>> tagKey = TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.read(reader.getReader()));
+ // Paper start - tell clients to ask server for suggestions for EntityArguments; throw error if invalid entity tag (only on suggestions to keep cmd success behavior)
+ if (reader.parsingEntityArgumentSuggestions && io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getTag(tagKey).isEmpty()) {
+ reader.getReader().setCursor(i);
+ throw ERROR_ENTITY_TAG_INVALID.createWithContext(reader.getReader(), tagKey);
+ }
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
reader.addPredicate((entity) -> {
return entity.getType().is(tagKey) != bl;
});
if (reader.isTag()) {
TagKey<EntityType<?>> tagKey = TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.read(reader.getReader()));
+ // Paper start - tell clients to ask server for suggestions for EntityArguments; throw error if invalid entity tag (only on suggestions to keep cmd success behavior)
+ if (reader.parsingEntityArgumentSuggestions && io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getTag(tagKey).isEmpty()) {
+ reader.getReader().setCursor(i);
+ throw ERROR_ENTITY_TAG_INVALID.createWithContext(reader.getReader(), tagKey);
+ }
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
reader.addPredicate(entity -> entity.getType().is(tagKey) != bl);
} else {
ResourceLocation resourceLocation = ResourceLocation.read(reader.getReader());

View File

@ -58,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class SpikeFeature extends Feature<SpikeConfiguration> {
endCrystal.setBeamTarget(config.getCrystalBeamTarget());
endCrystal.setInvulnerable(config.isCrystalInvulnerable());
endCrystal.moveTo((double)spike.getCenterX() + 0.5D, (double)(spike.getHeight() + 1), (double)spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F);
endCrystal.moveTo(spike.getCenterX() + 0.5, spike.getHeight() + 1, spike.getCenterZ() + 0.5, random.nextFloat() * 360.0F, 0.0F);
+ endCrystal.generatedByDragonFight = true; // Paper - Fix invulnerable end crystals
world.addFreshEntity(endCrystal);
BlockPos blockPos2 = endCrystal.blockPosition();

View File

@ -38,9 +38,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.timeInOverworld = 0;
+ }
+ // Paper end - Fix issues with mob conversion
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java

View File

@ -22,8 +22,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
int j = z / 2;
int k = x % 2;
int l = z % 2;
- float f = 100.0F - Mth.sqrt((float)(x * x + z * z)) * 8.0F;
- float f = 100.0F - Mth.sqrt(x * x + z * z) * 8.0F;
+ float f = 100.0F - Mth.sqrt((long) x * (long) x + (long) z * (long) z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
f = Mth.clamp(f, -100.0F, 80.0F);
for(int m = -12; m <= 12; ++m) {
for (int m = -12; m <= 12; m++) {

View File

@ -22,6 +22,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
level.scheduleTick(tick.pos(), fluid, tick.delay(), tick.priority());
});
+ UpgradeData.BlockFixers.values(); // Paper - force the class init so that we don't access CHUNKY_FIXERS before all BlockFixers are initialised
CHUNKY_FIXERS.forEach((logic) -> {
logic.processChunk(level);
});
CHUNKY_FIXERS.forEach(logic -> logic.processChunk(level));
}

View File

@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - Fix some rails connecting improperly
for(int i = 0; i < this.connections.size(); ++i) {
for (int i = 0; i < this.connections.size(); i++) {
RailState railState = this.getRail(this.connections.get(i));
- if (railState != null) {
+ if (railState != null && railState.isValid()) { // Paper - Fix some rails connecting improperly

View File

@ -37,9 +37,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public List<StructureStart> startsForStructure(ChunkPos pos, Predicate<Structure> predicate, @Nullable ServerLevelAccessor levelAccessor) {
+ Map<Structure, LongSet> map = (levelAccessor == null ? this.level : levelAccessor).getChunk(pos.x, pos.z, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
+ // Paper end - Fix swamp hut cat generation deadlock
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
Builder<StructureStart> builder = ImmutableList.builder();
for(Map.Entry<Structure, LongSet> entry : map.entrySet()) {
for (Entry<Structure, LongSet> entry : map.entrySet()) {
@@ -0,0 +0,0 @@ public class StructureManager {
}
@ -51,12 +51,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Fix swamp hut cat generation deadlock
Registry<Structure> registry = this.registryAccess().registryOrThrow(Registries.STRUCTURE);
for(StructureStart structureStart : this.startsForStructure(new ChunkPos(pos), (structure) -> {
return registry.getHolder(registry.getId(structure)).map((reference) -> {
return reference.is(structureTag);
}).orElse(false);
- })) {
+ }, levelAccessor)) { // Paper - Fix swamp hut cat generation deadlock
for (StructureStart structureStart : this.startsForStructure(
- new ChunkPos(pos), structure -> registry.getHolder(registry.getId(structure)).map(reference -> reference.is(structureTag)).orElse(false)
+ new ChunkPos(pos), structure -> registry.getHolder(registry.getId(structure)).map(reference -> reference.is(structureTag)).orElse(false), levelAccessor // Paper - Fix swamp hut cat generation deadlock
)) {
if (this.structureHasPieceAt(pos, structureStart)) {
return structureStart;
}

View File

@ -9,11 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/Display.java
+++ b/src/main/java/net/minecraft/world/entity/Display.java
@@ -0,0 +0,0 @@ public abstract class Display extends Entity {
byte b = loadFlag((byte)0, nbt, "shadow", (byte)1);
b = loadFlag(b, nbt, "see_through", (byte)2);
b = loadFlag(b, nbt, "default_background", (byte)4);
- Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error)).map(Pair::getFirst);
+ Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).result().map(Pair::getFirst); // Paper - Hide text display error on spawn
Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC
.decode(NbtOps.INSTANCE, nbt.get("alignment"))
- .resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error))
+ .result() // Paper - Hide text display error on spawn
.map(Pair::getFirst);
if (optional.isPresent()) {
byte var10000;
switch ((Display.TextDisplay.Align)optional.get()) {
b = switch ((Display.TextDisplay.Align)optional.get()) {

View File

@ -39,13 +39,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
@@ -0,0 +0,0 @@ public class FrogspawnBlock extends Block {
int k = random.nextInt(1, 361);
tadpole.moveTo(d, (double)pos.getY() - 0.5D, e, (float)k, 0.0F);
tadpole.moveTo(d, pos.getY() - 0.5, e, k, 0.0F);
tadpole.setPersistenceRequired();
- world.addFreshEntity(tadpole);
+ world.addFreshEntity(tadpole, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason
}
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
@ -57,5 +57,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- world.addFreshEntity(sniffer);
+ world.addFreshEntity(sniffer, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason
}
}
}

View File

@ -172,12 +172,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java
@@ -0,0 +0,0 @@ public class CarvingContext extends WorldGenerationContext {
private final RandomState randomState;
private final SurfaceRules.RuleSource surfaceRule;
- public CarvingContext(NoiseBasedChunkGenerator noiseChunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler, RandomState noiseConfig, SurfaceRules.RuleSource materialRule) {
LevelHeightAccessor heightLimitView,
NoiseChunk chunkNoiseSampler,
RandomState noiseConfig,
- SurfaceRules.RuleSource materialRule
+ SurfaceRules.RuleSource materialRule, @javax.annotation.Nullable net.minecraft.world.level.Level level // Paper - Flat bedrock generator settings
) {
- super(noiseChunkGenerator, heightLimitView);
+ public CarvingContext(NoiseBasedChunkGenerator noiseChunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler, RandomState noiseConfig, SurfaceRules.RuleSource materialRule, @javax.annotation.Nullable net.minecraft.world.level.Level level) { // Paper - Flat bedrock generator settings
+ super(noiseChunkGenerator, heightLimitView, level); // Paper - Flat bedrock generator settings
this.registryAccess = registryManager;
this.noiseChunk = chunkNoiseSampler;

View File

@ -58,7 +58,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Handle large packets disconnecting client
ProtocolSwapHandler.swapProtocolIfNeeded(attribute, packet);
}
}
}
}

View File

@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.blockEntitiesData = Lists.newArrayList();
+ int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
for(Map.Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
for (Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
+ // Paper start - Handle oversized block entities in chunks
+ if (++totalTileEntities > TE_LIMIT) {
+ var packet = entry2.getValue().getUpdatePacket();
@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Handle oversized block entities in chunks
this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entry2.getValue()));
}
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java

View File

@ -30,10 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
- public boolean equals(Object object) {
+ public final boolean equals(Object object) { // Paper - Perf: Final for inline
if (this == object) {
return true;
} else if (!(object instanceof Vec3i)) {
@@ -0,0 +0,0 @@ public class Vec3i implements Comparable<Vec3i> {
return this == object || object instanceof Vec3i vec3i && this.getX() == vec3i.getX() && this.getY() == vec3i.getY() && this.getZ() == vec3i.getZ();
}
@Override

View File

@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
executorService = MoreExecutors.newDirectExecutorService();
} else {
- AtomicInteger atomicInteger = new AtomicInteger(1);
- executorService = new ForkJoinPool(i, (pool) -> {
- executorService = new ForkJoinPool(i, pool -> {
- ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(pool) {
+ executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<>(), target -> new io.papermc.paper.util.ServerWorkerThread(target, s, priorityModifier));
+ }

View File

@ -73,10 +73,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ tpsAvg[g] = format( tps[g] );
+ }
this.msgs[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)";
this.msgs[1] = "Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / (double)TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms";
this.msgs[1] = "Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms";
+ this.msgs[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg);
+ // Paper end - Improve ServerGUI
this.values[this.vp++ & 255] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
this.values[this.vp++ & 0xFF] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
this.repaint();
}
@@ -0,0 +0,0 @@ public class StatsComponent extends JComponent {

View File

@ -9,11 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -0,0 +0,0 @@ public class Util {
}).findFirst().orElseThrow(() -> {
return new IllegalStateException("No jar file system provider found");
});
.filter(fileSystemProvider -> fileSystemProvider.getScheme().equalsIgnoreCase("jar"))
.findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
+ public static final double COLLISION_EPSILON = 1.0E-7; // Paper - Improve boat collision performance
private static Consumer<String> thePauser = (message) -> {
private static Consumer<String> thePauser = message -> {
};
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java

View File

@ -326,23 +326,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.spawnAtLocation(Blocks.CHEST);
}
- this.setChest(false);
+ //this.setCarryingChest(false); // Paper - moved to post death logic
}
}
+ //this.setChest(false); // Paper - moved to post death logic
+ }
+ }
+
+ // Paper start
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {
+ if (this.hasChest() && (event == null || !event.isCancelled())) {
+ this.setChest(false);
+ }
+ }
this.setChest(false);
}
}
+ // Paper end
+
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java

View File

@ -153,11 +153,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.stackedContents.initialize(recipe.value()); // Paper - Improve exact choice recipe ingredients
entity.getInventory().fillStackedContents(this.stackedContents);
this.menu.fillCraftSlotsStackedContents(this.stackedContents);
if (this.stackedContents.canCraft(recipe.value(), (IntList)null)) {
if (this.stackedContents.canCraft((Recipe<?>)recipe.value(), null)) {
@@ -0,0 +0,0 @@ public class ServerPlaceRecipe<C extends Container> implements PlaceRecipe<Integ
int l = k;
for(int m : intList) {
for (int m : intList) {
- int n = StackedContents.fromStackingIndex(m).getMaxStackSize();
+ int n = StackedContents.maxStackSizeFromStackingIndex(m, this.stackedContents); // Paper - Improve exact choice recipe ingredients
if (n < l) {
@ -181,12 +181,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - Improve exact choice recipe ingredients
if (!itemStack.isEmpty()) {
for(int i = 0; i < amount; ++i) {
for (int i = 0; i < amount; i++) {
- this.moveItemToGrid(slot2, itemStack);
+ this.moveItemToGrid(slot2, itemStack, isExact); // Paper - Improve exact choice recipe ingredients
}
}
}
@@ -0,0 +0,0 @@ public class ServerPlaceRecipe<C extends Container> implements PlaceRecipe<Integ
return i;
}
@ -225,7 +225,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (this.extrasMap != null && stack.hasTag() && this.extrasMap.accountStack(stack, j)) return; // Paper - Improve exact choice recipe ingredients; if an exact ingredient, don't include it
this.put(i, j);
}
}
@@ -0,0 +0,0 @@ public class StackedContents {
return itemId == 0 ? ItemStack.EMPTY : new ItemStack(Item.byId(itemId));
}
@ -253,27 +253,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class StackedContents {
this.data = new BitSet(this.ingredientCount + this.itemCount + this.ingredientCount + this.ingredientCount * this.itemCount);
for(int i = 0; i < this.ingredients.size(); ++i) {
for (int i = 0; i < this.ingredients.size(); i++) {
- IntList intList = this.ingredients.get(i).getStackingIds();
+ IntList intList = this.getStackingIds(this.ingredients.get(i)); // Paper - Improve exact choice recipe ingredients
for(int j = 0; j < this.itemCount; ++j) {
for (int j = 0; j < this.itemCount; j++) {
if (intList.contains(this.items[j])) {
@@ -0,0 +0,0 @@ public class StackedContents {
IntCollection intCollection = new IntAVLTreeSet();
for(Ingredient ingredient : this.ingredients) {
for (Ingredient ingredient : this.ingredients) {
- intCollection.addAll(ingredient.getStackingIds());
+ intCollection.addAll(this.getStackingIds(ingredient)); // Paper - Improve exact choice recipe ingredients
}
IntIterator intIterator = intCollection.iterator();
@@ -0,0 +0,0 @@ public class StackedContents {
for(Ingredient ingredient : this.ingredients) {
for (Ingredient ingredient : this.ingredients) {
int j = 0;
- for(int k : ingredient.getStackingIds()) {
+ for(int k : this.getStackingIds(ingredient)) { // Paper - Improve exact choice recipe ingredients
- for (int k : ingredient.getStackingIds()) {
+ for (int k : this.getStackingIds(ingredient)) { // Paper - Improve exact choice recipe ingredients
j = Math.max(j, StackedContents.this.contents.get(k));
}

View File

@ -70,7 +70,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/packs/PathPackResources.java
@@ -0,0 +0,0 @@ public class PathPackResources extends AbstractPackResources {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
for(Path path2 : directoryStream) {
for (Path path2 : directoryStream) {
String string = path2.getFileName().toString();
+ // Paper start - Improve logging and errors
+ if (!Files.isDirectory(path2)) {

View File

@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level());
+ NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level(), this.craftSlots.getCurrentRecipe() != null ? this.craftSlots.getCurrentRecipe().id() : null); // Paper - Perf: Improve mass crafting; check last recipe used first
for(int i = 0; i < nonNullList.size(); ++i) {
for (int i = 0; i < nonNullList.size(); i++) {
ItemStack itemStack = this.craftSlots.getItem(i);
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View File

@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private int depth; // Paper
public static CompoundTag parseTag(String string) throws CommandSyntaxException {
return (new TagParser(new StringReader(string))).readSingleStruct();
return new TagParser(new StringReader(string)).readSingleStruct();
@@ -0,0 +0,0 @@ public class TagParser {
public CompoundTag readStruct() throws CommandSyntaxException {
@ -97,21 +97,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return listTag;
}
}
@@ -0,0 +0,0 @@ public class TagParser {
}
if (typeReader == ByteTag.TYPE) {
- list.add((T)((NumericTag)tag).getAsByte());
+ list.add((T)((NumericTag)tag).getAsNumber()); // Paper - decompile fix
} else if (typeReader == LongTag.TYPE) {
- list.add((T)((NumericTag)tag).getAsLong());
+ list.add((T)((NumericTag)tag).getAsNumber()); // Paper - decompile fix
} else {
- list.add((T)((NumericTag)tag).getAsInt());
+ list.add((T)((NumericTag)tag).getAsNumber()); // Paper - decompile fix
}
if (this.hasElementSeparator()) {
@@ -0,0 +0,0 @@ public class TagParser {
this.reader.skipWhitespace();
this.reader.expect(c);
@ -143,7 +128,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Count visited parts
this.decompose();
for(FormattedText formattedText : this.decomposedParts) {
for (FormattedText formattedText : this.decomposedParts) {
@@ -0,0 +0,0 @@ public class TranslatableContents implements ComponentContents {
return Optional.empty();

View File

@ -289,7 +289,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (var3.getCause() instanceof ThreadDeath) throw var3; // Paper
LOGGER.error(LogUtils.FATAL_MARKER, "Error executing task on {}", this.name(), var3);
}
}
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

View File

@ -11,17 +11,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/core/Direction.java
+++ b/src/main/java/net/minecraft/core/Direction.java
@@ -0,0 +0,0 @@ public enum Direction implements StringRepresentable {
})).toArray((i) -> {
return new Direction[i];
});
.sorted(Comparator.comparingInt(direction -> direction.data2d))
.toArray(Direction[]::new);
+ // Paper start - Perf: Inline shift direction fields
+ private final int adjX;
+ private final int adjY;
+ private final int adjZ;
+ // Paper end - Perf: Inline shift direction fields
+
private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) {
this.data3d = id;
this.data2d = idHorizontal;
@@ -0,0 +0,0 @@ public enum Direction implements StringRepresentable {
this.axis = axis;
this.axisDirection = direction;

View File

@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - Perf: lazily create LootContext for criterions
List<CriterionTrigger.Listener<T>> list = null;
for(CriterionTrigger.Listener<T> listener : set) {
for (CriterionTrigger.Listener<T> listener : set) {
T simpleInstance = listener.trigger();
if (predicate.test(simpleInstance)) {
Optional<ContextAwarePredicate> optional = simpleInstance.player();

View File

@ -606,7 +606,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- } else {
- ContainerHelper.saveAllItems(nbt, this.getItemStacks());
}
+ ContainerHelper.saveAllItems(nbt, this.getItemStacks()); // Paper - always save the items, table may still remain
}
@ -618,7 +617,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- } else {
- ContainerHelper.loadAllItems(nbt, this.getItemStacks());
}
+ ContainerHelper.loadAllItems(nbt, this.getItemStacks()); // Paper - always load the items, table may still remain
}
@ -634,14 +632,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, this.getLootTable());
}
- this.setLootTable((ResourceLocation)null);
- this.setLootTable(null);
+ this.getLootableData().processRefill(player); // Paper
LootParams.Builder builder = (new LootParams.Builder((ServerLevel)this.level())).withParameter(LootContextParams.ORIGIN, this.position());
LootParams.Builder builder = new LootParams.Builder((ServerLevel)this.level()).withParameter(LootContextParams.ORIGIN, this.position());
if (player != null) {
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
@@ -0,0 +0,0 @@ public interface ContainerEntity extends Container, MenuProvider {
default boolean isChestVehicleStillValid(Player player) {
return !this.isRemoved() && this.position().closerThan(player.position(), 8.0D);
return !this.isRemoved() && this.position().closerThan(player.position(), 8.0);
}
+ // Paper start
+ default Entity getEntity() {
@ -717,7 +715,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
@Override
public boolean isEmpty() {
this.unpackLootTable((Player)null);
this.unpackLootTable(null);
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java

View File

@ -22,10 +22,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
@@ -0,0 +0,0 @@ public class TargetingConditions {
if (this.range > 0.0D) {
double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
- double e = Math.max(this.range * d, 2.0D);
+ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper - Fix MC-145656
if (this.range > 0.0) {
double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0;
- double e = Math.max(this.range * d, 2.0);
+ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0); // Paper - Fix MC-145656
double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
if (f > e * e) {
return false;

View File

@ -16,14 +16,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@VisibleForTesting
static long encode(double value) {
- return Math.round(value * 4096.0D);
+ return Math.round(value * 4096.0D); // Paper - Fix MC-4; diff on change
- return Math.round(value * 4096.0);
+ return Math.round(value * 4096.0); // Paper - Fix MC-4; diff on change
}
@VisibleForTesting
static double decode(long value) {
- return (double)value / 4096.0D;
+ return (double)value / 4096.0D; // Paper - Fix MC-4; diff on change
- return value / 4096.0;
+ return value / 4096.0; // Paper - Fix MC-4; diff on change
}
public Vec3 decode(long x, long y, long z) {
@ -39,9 +39,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (this instanceof ItemEntity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) {
+ // encode/decode from ClientboundMoveEntityPacket
+ x = Mth.lfloor(x * 4096.0D) * (1 / 4096.0D);
+ y = Mth.lfloor(y * 4096.0D) * (1 / 4096.0D);
+ z = Mth.lfloor(z * 4096.0D) * (1 / 4096.0D);
+ x = Mth.lfloor(x * 4096.0) * (1 / 4096.0);
+ y = Mth.lfloor(y * 4096.0) * (1 / 4096.0);
+ z = Mth.lfloor(z * 4096.0) * (1 / 4096.0);
+ }
+ }
+ // Paper end - Fix MC-4

File diff suppressed because one or more lines are too long

View File

@ -7040,8 +7040,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
@@ -0,0 +0,0 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
runnable.run();
}
}
+ // Paper start
+ public void scheduleOnMain(Runnable r0) {
@ -7360,9 +7360,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading)
+ @Nullable default ChunkAccess getChunkIfLoadedImmediately(BlockPos pos) { return this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);}
+
/** @deprecated */
@Deprecated
boolean hasChunk(int chunkX, int chunkZ);
diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java

View File

@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
@@ -0,0 +0,0 @@ public abstract class WaterAnimal extends PathfinderMob {
public static boolean checkSurfaceWaterAnimalSpawnRules(EntityType<? extends WaterAnimal> type, LevelAccessor world, MobSpawnType reason, BlockPos pos, RandomSource random) {
) {
int i = world.getSeaLevel();
int j = i - 13;
+ // Paper start - Make water animal spawn height configurable

View File

@ -49,8 +49,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/core/Vec3i.java
+++ b/src/main/java/net/minecraft/core/Vec3i.java
@@ -0,0 +0,0 @@ public class Vec3i implements Comparable<Vec3i> {
return IntStream.of(vec.getX(), vec.getY(), vec.getZ());
});
vec -> IntStream.of(vec.getX(), vec.getY(), vec.getZ())
);
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
- private int x;
- private int y;
@ -60,4 +60,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ protected int z; // Paper - Perf: Manually inline methods in BlockPosition; protected
public static Codec<Vec3i> offsetCodec(int maxAbsValue) {
return ExtraCodecs.validate(CODEC, (vec) -> {
return ExtraCodecs.validate(

View File

@ -35,11 +35,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java
+++ b/src/main/java/net/minecraft/world/item/SuspiciousStewItem.java
@@ -0,0 +0,0 @@ public class SuspiciousStewItem extends Item {
@Override
public ItemStack finishUsingItem(ItemStack stack, Level world, LivingEntity user) {
ItemStack itemStack = super.finishUsingItem(stack, world, user);
listPotionEffects(itemStack, (effect) -> {
- user.addEffect(effect.createEffectInstance());
+ user.addEffect(effect.createEffectInstance(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // Paper - Add missing effect cause
});
- listPotionEffects(itemStack, effect -> user.addEffect(effect.createEffectInstance()));
+ listPotionEffects(itemStack, effect -> user.addEffect(effect.createEffectInstance(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD)); // Paper - Add missing effect cause
return user instanceof Player && ((Player)user).getAbilities().instabuild ? itemStack : new ItemStack(Items.BOWL);
}
}

View File

@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
@@ -0,0 +0,0 @@ public class ClientboundSetPlayerTeamPacket implements Packet<ClientGamePacketLi
return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), ImmutableList.of(playerName));
);
}
+ // Paper start - Multiple Entries with Scoreboards

View File

@ -58,14 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public boolean equals(Object object) {
- if (this == object) {
- return true;
- } else if (!(object instanceof Property)) {
- return false;
- } else {
- Property<?> property = (Property)object;
- return this.clazz.equals(property.clazz) && this.name.equals(property.name);
- }
- return this == object || object instanceof Property<?> property && this.clazz.equals(property.clazz) && this.name.equals(property.name);
+ return this == object; // Paper - Perf: Optimize hashCode/equals
}

View File

@ -845,18 +845,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -0,0 +0,0 @@ public class AcquirePoi {
return true;
}
};
- Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllClosestFirstWithType(poiPredicate, predicate2, entity.blockPosition(), 48, PoiManager.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet());
+ // Paper start - optimise POI access
+ java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
+ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes);
+ Set<Pair<Holder<PoiType>, BlockPos>> set = new java.util.HashSet<>(poiposes);
+ // Paper end - optimise POI access
Path path = findPathToPois(entity, set);
if (path != null && path.canReach()) {
BlockPos blockPos = path.getTarget();
return true;
}
};
- Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllClosestFirstWithType(
- poiPredicate, predicate2, entity.blockPosition(), 48, PoiManager.Occupancy.HAS_SPACE
- )
- .limit(5L)
- .collect(Collectors.toSet());
+ // Paper start - optimise POI access
+ java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
+ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes);
+ Set<Pair<Holder<PoiType>, BlockPos>> set = new java.util.HashSet<>(poiposes);
+ // Paper end - optimise POI access
Path path = findPathToPois(entity, set);
if (path != null && path.canReach()) {
BlockPos blockPos = path.getTarget();
diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
@ -865,9 +869,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return true;
}
};
- Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllWithType((holder) -> {
- return holder.is(PoiTypes.HOME);
- }, predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY).collect(Collectors.toSet());
- Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllWithType(
- holder -> holder.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY
- )
- .collect(Collectors.toSet());
- Path path = AcquirePoi.findPathToPois(entity, set);
+ // Paper start - optimise POI access
+ java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
@ -883,9 +888,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage<PoiSection> {
}
public Optional<BlockPos> find(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
public Optional<BlockPos> find(
Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus
) {
- return this.findAll(typePredicate, posPredicate, pos, radius, occupationStatus).findFirst();
+ // Paper start - re-route to faster logic
+ BlockPos ret = io.papermc.paper.util.PoiAccess.findAnyPoiPosition(this, typePredicate, posPredicate, pos, radius, occupationStatus, false);
@ -894,21 +899,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public Optional<BlockPos> findClosest(Predicate<Holder<PoiType>> typePredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus).map(PoiRecord::getPos).min(Comparator.comparingDouble((blockPos2) -> {
- return blockPos2.distSqr(pos);
- }));
- return this.getInRange(typePredicate, pos, radius, occupationStatus)
- .map(PoiRecord::getPos)
- .min(Comparator.comparingDouble(blockPos2 -> blockPos2.distSqr(pos)));
+ // Paper start - re-route to faster logic
+ BlockPos ret = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, null, pos, radius, radius * radius, occupationStatus, false);
+ return Optional.ofNullable(ret);
+ // Paper end - re-route to faster logic
}
public Optional<Pair<Holder<PoiType>, BlockPos>> findClosestWithType(Predicate<Holder<PoiType>> typePredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus).min(Comparator.comparingDouble((poi) -> {
- return poi.getPos().distSqr(pos);
- })).map((poi) -> {
- return Pair.of(poi.getPoiType(), poi.getPos());
- });
public Optional<Pair<Holder<PoiType>, BlockPos>> findClosestWithType(
Predicate<Holder<PoiType>> typePredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus
) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus)
- .min(Comparator.comparingDouble(poi -> poi.getPos().distSqr(pos)))
- .map(poi -> Pair.of(poi.getPoiType(), poi.getPos()));
+ // Paper start - re-route to faster logic
+ return Optional.ofNullable(io.papermc.paper.util.PoiAccess.findClosestPoiDataTypeAndPosition(
+ this, typePredicate, null, pos, radius, radius * radius, occupationStatus, false
@ -916,10 +921,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - re-route to faster logic
}
public Optional<BlockPos> findClosest(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus).map(PoiRecord::getPos).filter(posPredicate).min(Comparator.comparingDouble((blockPos2) -> {
- return blockPos2.distSqr(pos);
- }));
public Optional<BlockPos> findClosest(
Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus
) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus)
- .map(PoiRecord::getPos)
- .filter(posPredicate)
- .min(Comparator.comparingDouble(blockPos2 -> blockPos2.distSqr(pos)));
+ // Paper start - re-route to faster logic
+ BlockPos ret = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, posPredicate, pos, radius, radius * radius, occupationStatus, false);
+ return Optional.ofNullable(ret);
@ -927,25 +935,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public Optional<BlockPos> take(Predicate<Holder<PoiType>> typePredicate, BiPredicate<Holder<PoiType>, BlockPos> biPredicate, BlockPos pos, int radius) {
- return this.getInRange(typePredicate, pos, radius, PoiManager.Occupancy.HAS_SPACE).filter((poi) -> {
- return biPredicate.test(poi.getPoiType(), poi.getPos());
- }).findFirst().map((poi) -> {
- return this.getInRange(typePredicate, pos, radius, PoiManager.Occupancy.HAS_SPACE)
- .filter(poi -> biPredicate.test(poi.getPoiType(), poi.getPos()))
- .findFirst()
+ // Paper start - re-route to faster logic
+ final @javax.annotation.Nullable PoiRecord closest = io.papermc.paper.util.PoiAccess.findClosestPoiDataRecord(
+ this, typePredicate, biPredicate, pos, radius, radius * radius, Occupancy.HAS_SPACE, false
+ );
+ return Optional.ofNullable(closest).map(poi -> {
+ return Optional.ofNullable(closest)
+ // Paper end - re-route to faster logic
poi.acquireTicket();
return poi.getPos();
});
}
public Optional<BlockPos> getRandom(Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> positionPredicate, PoiManager.Occupancy occupationStatus, BlockPos pos, int radius, RandomSource random) {
.map(poi -> {
poi.acquireTicket();
return poi.getPos();
@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage<PoiSection> {
int radius,
RandomSource random
) {
- List<PoiRecord> list = Util.toShuffledList(this.getInRange(typePredicate, pos, radius, occupationStatus), random);
- return list.stream().filter((poi) -> {
- return positionPredicate.test(poi.getPos());
- }).findFirst().map(PoiRecord::getPos);
- return list.stream().filter(poi -> positionPredicate.test(poi.getPos())).findFirst().map(PoiRecord::getPos);
+ // Paper start - re-route to faster logic
+ List<PoiRecord> list = new java.util.ArrayList<>();
+ io.papermc.paper.util.PoiAccess.findAnyPoiRecords(

View File

@ -135,9 +135,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
protected void doTick(ServerLevel world, LivingEntity entity) {
- List<Player> list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((player) -> {
- return entity.closerThan(player, 16.0D);
- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList());
- List<Player> list = world.players()
- .stream()
- .filter(EntitySelector.NO_SPECTATORS)
- .filter(player -> entity.closerThan(player, 16.0))
- .sorted(Comparator.comparingDouble(entity::distanceToSqr))
- .collect(Collectors.toList());
+ // Paper start - Perf: optimise nearby player retrieval & remove streams from hot code
+ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = world.chunkSource.chunkMap.getNearbyPlayers();
+ net.minecraft.world.phys.Vec3 entityPos = entity.position();
@ -164,13 +167,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ players.sort(Comparator.comparingDouble(entity::distanceToSqr));
Brain<?> brain = entity.getBrain();
- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list);
- List<Player> list2 = list.stream().filter((player) -> {
- return isEntityTargetable(entity, player);
- }).collect(Collectors.toList());
- List<Player> list2 = list.stream().filter(player -> isEntityTargetable(entity, player)).collect(Collectors.toList());
- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0));
- Optional<Player> optional = list2.stream().filter((player) -> {
- return isEntityAttackable(entity, player);
- }).findFirst();
- Optional<Player> optional = list2.stream().filter(player -> isEntityAttackable(entity, player)).findFirst();
- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional);
+
+ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players);
@ -200,10 +199,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
@@ -0,0 +0,0 @@ public class TargetingConditions {
public static final TargetingConditions DEFAULT = forCombat();
private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0D;
private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0;
private final boolean isCombat;
- private double range = -1.0D;
+ public double range = -1.0D; // Paper - public
- private double range = -1.0;
+ public double range = -1.0; // Paper - public
private boolean checkLineOfSight = true;
private boolean testInvisible = true;
@Nullable
@ -214,15 +213,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public interface EntityGetter {
T livingEntity = null;
for(T livingEntity2 : entityList) {
for (T livingEntity2 : entityList) {
+ // Paper start - optimise nearby player retrieval; move up
+ // don't check entities outside closest range
+ double e = livingEntity2.distanceToSqr(x, y, z);
+ if (d == -1.0D || e < d) {
+ if (d == -1.0 || e < d) {
+ // Paper end - move up
if (targetPredicate.test(entity, livingEntity2)) {
- double e = livingEntity2.distanceToSqr(x, y, z);
- if (d == -1.0D || e < d) {
- if (d == -1.0 || e < d) {
+ // Paper - optimise nearby player retrieval; move up
d = e;
livingEntity = livingEntity2;

View File

@ -309,7 +309,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
@Override
public void getAll(IntConsumer action) {
for(int i = 0; i < this.size; ++i) {
for (int i = 0; i < this.size; i++) {
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java

View File

@ -13,7 +13,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static class Builder {
- private final Map<MobCategory, List<MobSpawnSettings.SpawnerData>> spawners = Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((mobCategory) -> {
+ // Paper start - Perf: keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it
+ public static class MobList extends java.util.ArrayList<MobSpawnSettings.SpawnerData> {
+ java.util.Set<MobSpawnSettings.SpawnerData> biomes = new java.util.HashSet<>();
@ -45,12 +44,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ // use toImmutableEnumMap collector
+ private final Map<MobCategory, List<MobSpawnSettings.SpawnerData>> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((mobCategory) -> {
return mobCategory;
}, (mobCategory) -> {
- return Lists.newArrayList();
+ return new MobList(); // Use MobList instead of ArrayList
}));
private final Map<MobCategory, List<MobSpawnSettings.SpawnerData>> spawners = Stream.of(MobCategory.values())
- .collect(ImmutableMap.toImmutableMap(mobCategory -> (MobCategory)mobCategory, mobCategory -> Lists.newArrayList()));
+ .collect(Maps.toImmutableEnumMap(mobCategory -> (MobCategory)mobCategory, mobCategory -> new MobList())); // Use MobList instead of ArrayList
+ // Paper end - Perf: keep track of data in a pair set to give O(1) contains calls
private final Map<EntityType<?>, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap();
private float creatureGenerationProbability = 0.1F;

View File

@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
}).stable();
.stable();
private static final Logger LOGGER = LogUtils.getLogger();
public static final BlockPos ZERO = new BlockPos(0, 0, 0);
- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000));
@ -76,9 +76,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static long asLong(int x, int y, int z) {
- long l = 0L;
- l |= ((long)x & PACKED_X_MASK) << X_OFFSET;
- l |= ((long)y & PACKED_Y_MASK) << 0;
- return l | ((long)z & PACKED_Z_MASK) << Z_OFFSET;
- l |= (x & PACKED_X_MASK) << X_OFFSET;
- l |= (y & PACKED_Y_MASK) << 0;
- return l | (z & PACKED_Z_MASK) << Z_OFFSET;
+ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify
}
@ -180,9 +180,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
public static long asLong(int x, int y, int z) {
- long l = 0L;
- l |= ((long)x & 4194303L) << 42;
- l |= ((long)y & 1048575L) << 0;
- return l | ((long)z & 4194303L) << 20;
- l |= (x & 4194303L) << 42;
- l |= (y & 1048575L) << 0;
- return l | (z & 4194303L) << 20;
+ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count
}
@ -210,4 +210,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline
}
public static Stream<SectionPos> betweenClosedStream(final int minX, final int minY, final int minZ, final int maxX, final int maxY, final int maxZ) {
public static Stream<SectionPos> betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {

View File

@ -42,55 +42,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
@@ -0,0 +0,0 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
@Override
protected T computeNext() {
while(true) {
if (this.cursor.advance()) {
- int i = this.cursor.nextX();
- int j = this.cursor.nextY();
- int k = this.cursor.nextZ();
+ int i = this.cursor.nextX(); final int x = i; // Paper
+ int j = this.cursor.nextY(); final int y = j; // Paper
+ int k = this.cursor.nextZ(); final int z = k; // Paper
int l = this.cursor.getNextType();
if (l == 3) {
continue;
}
+ // Paper start - ensure we don't load chunks
+ final @Nullable Entity source = this.context instanceof net.minecraft.world.phys.shapes.EntityCollisionContext entityContext ? entityContext.getEntity() : null;
+ boolean far = source != null && io.papermc.paper.util.MCUtil.distanceSq(source.getX(), y, source.getZ(), x, y, z) > 14;
+ this.pos.set(x, y, z);
while (this.cursor.advance()) {
- int i = this.cursor.nextX();
- int j = this.cursor.nextY();
- int k = this.cursor.nextZ();
+ int i = this.cursor.nextX(); final int x = i; // Paper - OBFHELPER
+ int j = this.cursor.nextY(); final int y = j; // Paper - OBFHELPER
+ int k = this.cursor.nextZ(); final int z = k; // Paper - OBFHELPER
int l = this.cursor.getNextType();
if (l != 3) {
- BlockGetter blockGetter = this.getChunk(i, k);
- if (blockGetter == null) {
+ BlockState blockState;
+ if (this.collisionGetter instanceof net.minecraft.server.level.WorldGenRegion) {
+ BlockGetter blockGetter = this.getChunk(x, z);
+ if (blockGetter == null) {
+ continue;
- if (blockGetter != null) {
- this.pos.set(i, j, k);
- BlockState blockState = blockGetter.getBlockState(this.pos);
- if ((!this.onlySuffocatingBlocks || blockState.isSuffocating(blockGetter, this.pos))
- && (l != 1 || blockState.hasLargeCollisionShape())
- && (l != 2 || blockState.is(Blocks.MOVING_PISTON))) {
+ // Paper start - ensure we don't load chunks
+ // BlockGetter blockGetter = this.getChunk(i, k);
+ if (true) {
+ final @Nullable Entity source = this.context instanceof net.minecraft.world.phys.shapes.EntityCollisionContext entityContext ? entityContext.getEntity() : null;
+ boolean far = source != null && io.papermc.paper.util.MCUtil.distanceSq(source.getX(), y, source.getZ(), x, y, z) > 14;
+ this.pos.set(x, y, z);
+ BlockState blockState;
+ if (this.collisionGetter instanceof net.minecraft.server.level.WorldGenRegion) {
+ BlockGetter blockGetter = this.getChunk(x, z);
+ if (blockGetter == null) {
+ continue;
+ }
+ blockState = blockGetter.getBlockState(this.pos);
+ } else if ((!far && source instanceof net.minecraft.server.level.ServerPlayer) || (source != null && source.collisionLoadChunks)) {
+ blockState = this.collisionGetter.getBlockState(this.pos);
+ } else {
+ blockState = this.collisionGetter.getBlockStateIfLoaded(this.pos);
+ }
+ blockState = blockGetter.getBlockState(this.pos);
+ } else if ((!far && source instanceof net.minecraft.server.level.ServerPlayer) || (source != null && source.collisionLoadChunks)) {
+ blockState = this.collisionGetter.getBlockState(this.pos);
+ } else {
+ blockState = this.collisionGetter.getBlockStateIfLoaded(this.pos);
+ }
+
+ if (blockState == null) {
+ if (!(source instanceof net.minecraft.server.level.ServerPlayer) || source.level().paperConfig().chunks.preventMovingIntoUnloadedChunks) {
+ return this.resultProvider.apply(new BlockPos.MutableBlockPos(x, y, z), Shapes.create(far ? source.getBoundingBox() : new AABB(new BlockPos(x, y, z))));
+ if (blockState == null) {
+ if (!(source instanceof net.minecraft.server.level.ServerPlayer) || source.level().paperConfig().chunks.preventMovingIntoUnloadedChunks) {
+ return this.resultProvider.apply(new BlockPos.MutableBlockPos(x, y, z), Shapes.create(far ? source.getBoundingBox() : new AABB(new BlockPos(x, y, z))));
+ }
+ continue;
+ }
+ // Paper end
continue;
}
- this.pos.set(i, j, k);
- BlockState blockState = blockGetter.getBlockState(this.pos);
- if (this.onlySuffocatingBlocks && !blockState.isSuffocating(blockGetter, this.pos) || l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) {
+ // Paper - moved up
+ if (/*this.onlySuffocatingBlocks && (!blockState.isSuffocating(blockGetter, this.pos)) ||*/ l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) { // Paper - onlySuffocatingBlocks is only true on the client, so we don't care about it here
continue;
}
+ if (/*(!this.onlySuffocatingBlocks || blockState.isSuffocating(blockGetter, this.pos)) &&*/ (l != 1 || blockState.hasLargeCollisionShape()) && (l != 2 || blockState.is(Blocks.MOVING_PISTON))) { // Paper - onlySuffocatingBlocks is only true on the client, so we don't care about it here
+ // Paper end
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
if (this.box.intersects(i, j, k, i + 1.0, j + 1.0, k + 1.0)) {
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java
@ -100,7 +98,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
default boolean noCollision(@Nullable Entity entity, AABB box) {
+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper
for(VoxelShape voxelShape : this.getBlockCollisions(entity, box)) {
for (VoxelShape voxelShape : this.getBlockCollisions(entity, box)) {
if (!voxelShape.isEmpty()) {
return false;
}

View File

@ -42,10 +42,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private int cellIndex(int index) {
- long l = Integer.toUnsignedLong(this.divideMul);
- long m = Integer.toUnsignedLong(this.divideAdd);
- return (int)((long)index * l + m >> 32 >> this.divideShift);
- return (int)(index * l + m >> 32 >> this.divideShift);
+ //long l = Integer.toUnsignedLong(this.divideMul); // Paper - Perf: Optimize SimpleBitStorage
+ //long m = Integer.toUnsignedLong(this.divideAdd); // Paper - Perf: Optimize SimpleBitStorage
+ return (int) ((long) index * this.divideMulUnsigned + this.divideAddUnsigned >> 32 >> this.divideShift); // Paper - Perf: Optimize SimpleBitStorage
+ return (int) (index * this.divideMulUnsigned + this.divideAddUnsigned >> 32 >> this.divideShift); // Paper - Perf: Optimize SimpleBitStorage
}
@Override

View File

@ -79,16 +79,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
// Paper end
public void removeGoal(Goal goal) {
- this.availableGoals.stream().filter((wrappedGoal) -> {
- return wrappedGoal.getGoal() == goal;
- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop);
- this.availableGoals.removeIf((wrappedGoal) -> {
- return wrappedGoal.getGoal() == goal;
- });
- this.availableGoals.stream().filter(wrappedGoal -> wrappedGoal.getGoal() == goal).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop);
- this.availableGoals.removeIf(wrappedGoal -> wrappedGoal.getGoal() == goal);
- }
-
- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> controls) {
- for(Goal.Flag flag : goal.getFlags()) {
- for (Goal.Flag flag : goal.getFlags()) {
- if (controls.contains(flag)) {
- return true;
+ // Paper start - remove streams from pathfindergoalselector
@ -111,7 +107,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> goalsByControl) {
- for(Goal.Flag flag : goal.getFlags()) {
- for (Goal.Flag flag : goal.getFlags()) {
+ // Paper start
+ long flagIterator = goal.getFlags().getBackingSet();
+ int wrappedGoalSize = goal.getFlags().size();
@ -125,18 +121,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class GoalSelector {
profilerFiller.push("goalCleanup");
for(WrappedGoal wrappedGoal : this.availableGoals) {
for (WrappedGoal wrappedGoal : this.availableGoals) {
- if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.disabledFlags) || !wrappedGoal.canContinueToUse())) {
+ if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) {
+ if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams
wrappedGoal.stop();
}
}
@@ -0,0 +0,0 @@ public class GoalSelector {
profilerFiller.push("goalUpdate");
for(WrappedGoal wrappedGoal2 : this.availableGoals) {
- if (!wrappedGoal2.isRunning() && !goalContainsAnyFlags(wrappedGoal2, this.disabledFlags) && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags) && wrappedGoal2.canUse()) {
- for(Goal.Flag flag : wrappedGoal2.getFlags()) {
for (WrappedGoal wrappedGoal2 : this.availableGoals) {
- if (!wrappedGoal2.isRunning()
- && !goalContainsAnyFlags(wrappedGoal2, this.disabledFlags)
- && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags)
- && wrappedGoal2.canUse()) {
- for (Goal.Flag flag : wrappedGoal2.getFlags()) {
+ // Paper start
+ if (!wrappedGoal2.isRunning() && !goalContainsAnyFlags(wrappedGoal2, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags) && wrappedGoal2.canUse()) {
+ long flagIterator = wrappedGoal2.getFlags().getBackingSet();

View File

@ -729,7 +729,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@Override
public boolean isEmpty() {
this.unpackLootTable((Player)null);
this.unpackLootTable(null);
- return this.getItems().stream().allMatch(ItemStack::isEmpty);
+ // Paper start - Perf: Optimize Hoppers
+ for (final ItemStack itemStack : this.getItems()) {
@ -743,8 +743,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public ItemStack getItem(int slot) {
- this.unpackLootTable((Player)null);
+ if (slot == 0) this.unpackLootTable((Player) null); // Paper - Perf: Optimize Hoppers
- this.unpackLootTable(null);
+ if (slot == 0) this.unpackLootTable(null); // Paper - Perf: Optimize Hoppers
return this.getItems().get(slot);
}

View File

@ -15,14 +15,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final Logger LOGGER = LogUtils.getLogger();
final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
- private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(), (map) -> {
+ private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(2048), (map) -> { // Paper - Perf: Use bigger expected size to reduce collisions
map.defaultReturnValue(-1);
});
- private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(), map -> map.defaultReturnValue(-1));
- private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>();
- private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>();
- private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>();
- private final Map<T, Lifecycle> lifecycles = new IdentityHashMap<>();
+ private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(2048), map -> map.defaultReturnValue(-1)); // Paper - Perf: Use bigger expected size to reduce collisions
+ private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
+ private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
+ private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions

View File

@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public Packet<?> createPacket(int id, FriendlyByteBuf buf) {
+ if (id < 0 || id >= this.idToDeserializer.size()) return null; // Paper - Perf: Optimize exception handling
Function<FriendlyByteBuf, ? extends Packet<? super T>> function = this.idToDeserializer.get(id);
return function != null ? function.apply(buf) : null;
return (Packet<?>)(function != null ? function.apply(buf) : null);
}
diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View File

@ -23,9 +23,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (node == null) {
return null;
} else {
- Map<Target, BlockPos> map = positions.stream().collect(Collectors.toMap((pos) -> {
- return this.nodeEvaluator.getGoal((double)pos.getX(), (double)pos.getY(), (double)pos.getZ());
- }, Function.identity()));
- Map<Target, BlockPos> map = positions.stream()
- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), Function.identity()));
+ // Paper start - Perf: remove streams and optimize collection
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
+ for (BlockPos pos : positions) {
@ -57,19 +56,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
int i = 0;
- Set<Target> set3 = Sets.newHashSetWithExpectedSize(set.size());
+ List<Map.Entry<Target, BlockPos>> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection
int j = (int)((float)this.maxVisitedNodes * rangeMultiplier);
int j = (int)(this.maxVisitedNodes * rangeMultiplier);
while(!this.openSet.isEmpty()) {
while (!this.openSet.isEmpty()) {
@@ -0,0 +0,0 @@ public class PathFinder {
Node node = this.openSet.pop();
node.closed = true;
- for(Target target : set) {
- for (Target target : set) {
+ // Paper start - optimize collection
+ for(int i1 = 0; i1 < positions.size(); i1++) {
+ for (int i1 = 0; i1 < positions.size(); i1++) {
+ final Map.Entry<Target, BlockPos> entry = positions.get(i1);
+ Target target = entry.getKey();
if (node.distanceManhattan(target) <= (float)distance) {
if (node.distanceManhattan(target) <= distance) {
target.setReached();
- set3.add(target);
+ entryList.add(entry);
@ -95,11 +94,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
- Optional<Path> optional = !set3.isEmpty() ? set3.stream().map((node) -> {
- return this.reconstructPath(node.getBestNode(), positions.get(node), true);
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), false);
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
- Optional<Path> optional = !set3.isEmpty()
- ? set3.stream().map(node -> this.reconstructPath(node.getBestNode(), positions.get(node), true)).min(Comparator.comparingInt(Path::getNodeCount))
- : set.stream()
- .map(targetx -> this.reconstructPath(targetx.getBestNode(), positions.get(targetx), false))
- .min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
+ // Paper start - Perf: remove streams and optimize collection
+ Path best = null;
+ boolean entryListIsEmpty = entryList.isEmpty();
@ -124,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private float getBestH(Node node, List<Map.Entry<Target, BlockPos>> targets) { // Paper - Perf: remove streams and optimize collection; Set<Target> -> List<Map.Entry<Target, BlockPos>>
float f = Float.MAX_VALUE;
- for(Target target : targets) {
- for (Target target : targets) {
+ // Paper start - Perf: remove streams and optimize collection
+ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) {
+ final Target target = targets.get(i).getKey();

View File

@ -24,8 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ VARINT_EXACT_BYTE_LENGTHS[32] = 1; // Special case for the number 0.
+ }
+ public static int getByteSizeOld(int i) {
+ //Paper end - Optimize VarInts
for(int j = 1; j < 5; ++j) {
+ // Paper end - Optimize VarInts
for (int j = 1; j < 5; j++) {
if ((i & -1 << j * 7) == 0) {
return j;
@@ -0,0 +0,0 @@ public class VarInt {
@ -47,6 +47,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ public static ByteBuf writeOld(ByteBuf buf, int i) {
+ // Paper end - Optimize VarInts
while((i & -128) != 0) {
while ((i & -128) != 0) {
buf.writeByte(i & 127 | 128);
i >>>= 7;

View File

@ -93,12 +93,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper note - Rewrite below as optimized order if instead of nasty ternary
if (first instanceof CubePointRange && second instanceof CubePointRange) {
long l = lcm(i, j);
if ((long)size * l <= 256L) {
if (size * l <= 256L) {
@@ -0,0 +0,0 @@ public final class Shapes {
}
}
- if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) {
- if (first.getDouble(i) < second.getDouble(0) - 1.0E-7) {
+ // Paper start - Identical happens more often than Disjoint
+ if (i == j && Objects.equals(first, second)) {
+ if (first instanceof IdenticalMerger) {
@ -107,12 +107,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return (IndexMerger) second;
+ }
+ return new IdenticalMerger(first);
+ } else if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) {
+ } else if (first.getDouble(i) < second.getDouble(0) - 1.0E-7) {
return new NonOverlappingMerger(first, second, false);
} else if (second.getDouble(j) < first.getDouble(0) - 1.0E-7D) {
} else if (second.getDouble(j) < first.getDouble(0) - 1.0E-7) {
return new NonOverlappingMerger(second, first, true);
} else {
- return (IndexMerger)(i == j && Objects.equals(first, second) ? new IdenticalMerger(first) : new IndirectMerger(first, second, includeFirst, includeSecond));
- return (IndexMerger)(i == j && Objects.equals(first, second)
- ? new IdenticalMerger(first)
- : new IndirectMerger(first, second, includeFirst, includeSecond));
+ return new IndirectMerger(first, second, includeFirst, includeSecond);
}
+ // Paper end

Some files were not shown because too many files have changed in this diff Show More