Compare commits

...
Author SHA1 Message Date
Bjarne Koll 8043efd4d0 Correctly read per-world gamerule for command blocks (#13411) 2026-01-04 21:00:08 +00:00
Bjarne Koll 2f7f139762 [ci skip] Rebuild patches 2025-12-20 23:17:03 +00:00
niho2 3e25649471 Fix allowEnteringNetherUsingPortals gamerule not being respected (#13263) 2025-12-19 23:32:27 +00:00
TraksandBjarne Koll 14a10f43ec Fix isInteractable for copper chests (#13325)
Co-authored-by: Bjarne Koll <git@lynxplay.dev>
2025-12-19 22:53:01 +00:00
xSnowyk 92ee2c2574 Fix inverted logic in SwellGoal (MC-179072) (#13396) 2025-12-17 21:32:42 +00:00
Warrior 275118e5d1 Do not save entity fire override if it's unset (#13320) 2025-12-17 21:28:28 +00:00
Camden Cove 6530053d74 update connection hostname after player handshake event (#13386) 2025-12-17 21:25:39 +00:00
Lulu13022002 c2e533d8be Fix inverted check in Rotations (#13399) 2025-12-17 21:14:35 +00:00
MiniDigger | Martin 659e965c06 chore: bump fill to fix publishing 2025-12-17 13:57:48 +01:00
Max Lee ad1450c5c1 Use per-world difficulty and gamerules for monster spawn check (#13395) 2025-12-15 17:06:01 +00:00
sovdee 1c257ebf5b Prevent NaN velocity and crash for 0 powered explosion (#13366)
Prevents a 0 explosion_power explosion at the exact location of an entity from producing a NaN delta
due to dividing 0 by 0.
Such velocities lead to faulty client state and server crashes.
2025-12-10 23:02:40 +00:00
brickmonster 92ed3f00b1 Fix wrong translation key in /give command (#13364)
See: MC-151857
Backport-Of: ffce96cf3e
2025-12-03 17:50:54 +00:00
19 changed files with 169 additions and 70 deletions

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ plugins {
`maven-publish`
idea
id("io.papermc.paperweight.core")
id("io.papermc.fill.gradle") version "1.0.9"
id("io.papermc.fill.gradle") version "1.0.10"
}
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
@@ -23067,7 +23067,7 @@ index 13424bce076493f146bdc5fd0b1f2e09805bd5e7..2de7072c8ccc005e514673bba494b64d
thread1 -> {
DedicatedServer dedicatedServer1 = new DedicatedServer(
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index ab95014e66a7e217024ad9845669cc77fbbb13c2..40730d5775ed81bd715960b2c7dd710ca11dcb0e 100644
index 09272efcb581a849e093a368be2fa40eec53088c..f7d1237343833e2cf8af388acbfd49304258fae4 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -177,7 +177,7 @@ import net.minecraft.world.phys.Vec2;
@@ -23315,7 +23315,7 @@ index ab95014e66a7e217024ad9845669cc77fbbb13c2..40730d5775ed81bd715960b2c7dd710c
return true;
} else {
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
@@ -2574,6 +2690,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2579,6 +2695,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -26253,7 +26253,7 @@ index 9dbb7c744030fb8d6891780a0928c8cca2a2b68d..f019f1330f9f1e6aa98ef3f914833769
if (!passengers.equals(this.lastPassengers)) {
this.synchronizer
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 704733ff5e558a12f2f9dde924ab4c507745595d..5e305c9a64e856de70ed787901c01d09e68aa979 100644
index 436e1c7ead4dd815fc7d5f8114b6b9bff3e9d4c7..168c29e3f251ec85cc1b25682f6588f39fdd7958 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -175,7 +175,7 @@ import net.minecraft.world.ticks.LevelTicks;
@@ -26970,7 +26970,7 @@ index 704733ff5e558a12f2f9dde924ab4c507745595d..5e305c9a64e856de70ed787901c01d09
for (ChunkPos chunkPos1 : list) {
if (!this.areEntitiesLoaded(chunkPos1.toLong())) {
@@ -2208,28 +2527,38 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2212,28 +2531,38 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public void close() throws IOException {
super.close();
@@ -27015,7 +27015,7 @@ index 704733ff5e558a12f2f9dde924ab4c507745595d..5e305c9a64e856de70ed787901c01d09
}
public boolean anyPlayerCloseEnoughForSpawning(BlockPos pos) {
@@ -2241,7 +2570,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2245,7 +2574,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
public boolean canSpawnEntitiesInChunk(ChunkPos chunkPos) {
@@ -27027,7 +27027,7 @@ index 704733ff5e558a12f2f9dde924ab4c507745595d..5e305c9a64e856de70ed787901c01d09
}
@Override
@@ -2296,7 +2628,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2300,7 +2632,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
@@ -28135,7 +28135,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf4b672617 100644
index 020870daf433be3ac7074d4c577abdc71f2aa1b9..43c87b319ea84f912b41e1432d616f74be723a35 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -149,7 +149,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
@@ -28488,7 +28488,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
}
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2696,21 +2844,110 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -2698,21 +2846,110 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
public boolean isInWall() {
@@ -28610,7 +28610,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
}
public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4298,15 +4535,17 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4300,15 +4537,17 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
public Iterable<Entity> getIndirectPassengers() {
@@ -28636,7 +28636,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
}
public int countPlayerPassengers() {
@@ -4449,77 +4688,126 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4451,77 +4690,126 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
return Mth.lerp(partialTick, this.yRotO, this.yRot);
}
@@ -28821,7 +28821,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4675,6 +4963,15 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4677,6 +4965,15 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -28837,7 +28837,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
if (!checkPosition(this, x, y, z)) {
return;
}
@@ -4826,6 +5123,12 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4828,6 +5125,12 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@Override
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
@@ -28850,7 +28850,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) {
@@ -4836,7 +5139,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4838,7 +5141,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
this.stopRiding();
}
@@ -28859,7 +28859,7 @@ index a91d8e7d26cea116b0f58d84c84854bbd8cee05c..d5a38c3464539b05453ead3dfd77f4cf
this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason);
// Paper start - Folia schedulers
@@ -4870,7 +5173,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -4872,7 +5175,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
public boolean shouldBeSaved() {
return (this.removalReason == null || this.removalReason.shouldSave())
&& !this.isPassenger()
@@ -29257,7 +29257,7 @@ index 300f3ed58109219d97846082941b860585f66fed..9175a7e4e6076626cb46144c5858c2f2
// Paper start - Affects Spawning API
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 2a25f07c536890cf73dfce01bf043c5ec36480c3..39947ac2fae9a088d1fbc5c72d6ac520bfb97cf3 100644
index 1a2755fe70e970fd3da2ca74191bf8b83a5b6e3c..7a249a82c884e52304bb35d92fff87109a7d9aa3 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -82,6 +82,7 @@ import net.minecraft.world.level.storage.LevelData;
@@ -30173,7 +30173,7 @@ index 93110c815abe7baef61b1eaacfe28ebb1fc821f7..564c5064ec105a4f59476f2d21d3664b
ChunkAccess getChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk);
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index c132a3bfff7cf020e7fe4be616daa763b83e4b25..1c521f9f32340cf75310686c90777e521ac3ae5c 100644
index d0286d25ea641ceb7642213067bc737175ea9d29..222ae660d2a74f708f13ba1e715bc810f433f48f 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -62,6 +62,249 @@ public class ServerExplosion implements Explosion {
@@ -30576,7 +30576,7 @@ index c132a3bfff7cf020e7fe4be616daa763b83e4b25..1c521f9f32340cf75310686c90777e52
}
private void hurtEntities() {
@@ -346,6 +628,14 @@ public class ServerExplosion implements Explosion {
@@ -347,6 +629,14 @@ public class ServerExplosion implements Explosion {
}
public int explode() {
@@ -30591,7 +30591,7 @@ index c132a3bfff7cf020e7fe4be616daa763b83e4b25..1c521f9f32340cf75310686c90777e52
this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
this.hurtEntities();
@@ -360,6 +650,13 @@ public class ServerExplosion implements Explosion {
@@ -361,6 +651,13 @@ public class ServerExplosion implements Explosion {
this.createFire(list);
}
@@ -30605,7 +30605,7 @@ index c132a3bfff7cf020e7fe4be616daa763b83e4b25..1c521f9f32340cf75310686c90777e52
return list.size();
}
@@ -449,12 +746,12 @@ public class ServerExplosion implements Explosion {
@@ -450,12 +747,12 @@ public class ServerExplosion implements Explosion {
// Paper start - Optimize explosions
private float getBlockDensity(Vec3 vec3d, Entity entity) {
if (!this.level.paperConfig().environment.optimizeExplosions) {
@@ -2326,7 +2326,7 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
+ }
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index ce6f83c83b0235d59b4cadd248ff218985978ab5..71de8d8920eb33d15a18653dcef370c8e1a43712 100644
index e5365cad2b8476b6054f89ff3a0ba0d51431590d..c4aed8a8c4d4a02a960478882c8d670075011a73 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -221,6 +221,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2337,7 +2337,7 @@ index ce6f83c83b0235d59b4cadd248ff218985978ab5..71de8d8920eb33d15a18653dcef370c8
@Override
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
@@ -2660,6 +2661,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2664,6 +2665,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.debugSynchronizers;
}
@@ -2352,13 +2352,14 @@ index ce6f83c83b0235d59b4cadd248ff218985978ab5..71de8d8920eb33d15a18653dcef370c8
@Override
public void onCreated(Entity entity) {
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 439abba4f371343dfd8e5ede7c20050ca049fcd2..96fa7390a4bcfa7bdf2cf5346f2de895ac085203 100644
index 7ba08b317b0ac7ed15ecbc477f2402a2dbe526d5..b75c6ae764d88640ddd520c1345634b0365fff60 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -2078,6 +2078,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
return this.palettedContainerFactory;
}
@@ -2082,6 +2082,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public abstract boolean isCommandBlockEnabled();
public abstract boolean isSpawnerBlockEnabled();
// Paper end - per level game rules
+
+ // Paper start - optimize redstone (Alternate Current)
+ public alternate.current.wire.WireHandler getWireHandler() {
+ // This method is overridden in ServerLevel.
@@ -2369,10 +2370,9 @@ index 439abba4f371343dfd8e5ede7c20050ca049fcd2..96fa7390a4bcfa7bdf2cf5346f2de895
+ return null;
+ }
+ // Paper end - optimize redstone (Alternate Current)
+
public static enum ExplosionInteraction implements StringRepresentable {
NONE("none"),
BLOCK("block"),
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 07d2b9b7ebea9827ef7a535c090b311a3c27d5c6..a07d9237d227fe6d419d8a9bc44fc623b244ad3e 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -67,10 +67,10 @@ index ff6fc300e9e7d1dbf4b0fa1e59bffe94e1f51259..d58ee455467b2c8307ea20f8a9d88f0f
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue(this.tickCount); // Paper
profilerFiller.push("commandFunctions");
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 7ab250350027543adc3926632b0d68a2254c6ad3..2e3e038874757049445a91bf590d5a1a427a3f6d 100644
index e2905425313a814cd05ce7fa37679edbd249f1ca..46d7cd841aeeddac765ca1568dc8db2d5abdafef 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -5190,6 +5190,11 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -5192,6 +5192,11 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
this.getBukkitEntity().taskScheduler.retire();
}
// Paper end - Folia schedulers
@@ -4,7 +4,7 @@
buffer.writeFloat(value.z);
}
};
+ // Paper start - add internal method for skipping validation for plugins
+ // Paper start - add internal method for skipping validation for plugins using userdev
+ private static boolean SKIP_VALIDATION = false;
+ public static Rotations createWithoutValidityChecks(float x, float y, float z) {
+ SKIP_VALIDATION = true;
@@ -12,14 +12,14 @@
+ SKIP_VALIDATION = false;
+ return rotations;
+ }
+ // Paper end - add internal method for skipping validation for plugins
+ // Paper end - add internal method for skipping validation for plugins using userdev
public Rotations(float x, float y, float z) {
+ if (SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins
+ if (!SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins using userdev
x = !Float.isInfinite(x) && !Float.isNaN(x) ? x % 360.0F : 0.0F;
y = !Float.isInfinite(y) && !Float.isNaN(y) ? y % 360.0F : 0.0F;
z = !Float.isInfinite(z) && !Float.isNaN(z) ? z % 360.0F : 0.0F;
+ } // Paper - add internal method for skipping validation for plugins
+ } // Paper - add internal method for skipping validation for plugins using userdev
this.x = x;
this.y = y;
this.z = z;
@@ -1138,6 +1138,21 @@
this.effectiveRespawnData = serverLevel.getWorldBorderAdjustedRespawnData(respawnData);
}
@@ -1195,9 +_,12 @@
profilerFiller.pop();
}
- public boolean isAllowedToEnterPortal(Level level) {
- return level.dimension() != Level.NETHER || this.getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER);
+ // Paper start - Fix allowEnteringNetherUsingPortals gamerule - check from source level
+ public boolean isAllowedToEnterPortal(Level sourceLevel, Level destinationLevel) {
+ return destinationLevel.dimension() != Level.NETHER ||
+ (sourceLevel instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER));
}
+ // Paper end - Fix allowEnteringNetherUsingPortals gamerule
public void addTickable(Runnable tickable) {
this.tickables.add(tickable);
@@ -1224,6 +_,22 @@
return this.levels.get(dimension);
}
@@ -1210,7 +1225,19 @@
public boolean isPvpAllowed() {
return this.getGameRules().getBoolean(GameRules.RULE_PVP);
}
@@ -1415,10 +_,20 @@
@@ -1405,20 +_,32 @@
return true;
}
+ @io.papermc.paper.annotation.DoNotUse // Paper - do not use server wide gamerule, instead use server level specific one
public boolean isCommandBlockEnabled() {
return this.getGameRules().getBoolean(GameRules.RULE_COMMAND_BLOCKS_ENABLED);
}
+ @io.papermc.paper.annotation.DoNotUse // Paper - do not use server wide gamerule, instead use server level specific one
public boolean isSpawnerBlockEnabled() {
return this.getGameRules().getBoolean(GameRules.RULE_SPAWNER_BLOCKS_ENABLED);
}
@Override
public String getMotd() {
@@ -36,7 +36,7 @@
);
} else {
- source.sendSuccess(() -> Component.translatable("commands.give.success.single", count, itemStack.getDisplayName(), targets.size()), true);
+ source.sendSuccess(() -> Component.translatable("commands.give.success.single", count, displayName, targets.size()), true); // Paper - use cached display name
+ source.sendSuccess(() -> Component.translatable("commands.give.success.multiple", count, displayName, targets.size()), true); // Paper - use cached display name // Paper - MC-151857 - correct translation key
}
return targets.size();
@@ -1027,6 +1027,19 @@
return this.entityManager.getEntityGetter();
}
@@ -1703,7 +_,11 @@
}
public boolean isSpawningMonsters() {
- return this.server.isSpawningMonsters();
+ // Paper start - per world difficulty and game rules
+ return this.getDifficulty() != net.minecraft.world.Difficulty.PEACEFUL
+ && this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)
+ && this.getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS);
+ // Paper end - per world difficulty and game rules
}
@Override
@@ -1772,6 +_,28 @@
return this.serverLevelData.getGameRules();
}
@@ -1177,7 +1190,7 @@
}
@Override
@@ -1892,4 +_,24 @@
@@ -1892,4 +_,34 @@
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
@@ -1201,4 +1214,14 @@
+ this.lagCompensationTick = (System.nanoTime() - MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
+ }
+ // Paper end - lag compensation
+
+ // Paper start - per level game rules
+ public boolean isCommandBlockEnabled() {
+ return this.getGameRules().getBoolean(GameRules.RULE_COMMAND_BLOCKS_ENABLED);
+ }
+
+ public boolean isSpawnerBlockEnabled() {
+ return this.getGameRules().getBoolean(GameRules.RULE_SPAWNER_BLOCKS_ENABLED);
+ }
+ // Paper end - per level game rules
}
@@ -519,18 +519,24 @@
}
);
}
@@ -596,7 +_,7 @@
@@ -594,9 +_,9 @@
@Override
public void handleSetCommandBlock(ServerboundSetCommandBlockPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (!this.server.isCommandBlockEnabled()) {
- if (!this.server.isCommandBlockEnabled()) {
+ if (!player.level().isCommandBlockEnabled()) { // Paper - per level game rules - enabled command blocks
this.player.sendSystemMessage(Component.translatable("advMode.notEnabled"));
- } else if (!this.player.canUseGameMasterBlocks()) {
+ } else if (!this.player.canUseGameMasterBlocks() && (!this.player.isCreative() || !this.player.getBukkitEntity().hasPermission("minecraft.commandblock"))) { // Paper - command block permission
this.player.sendSystemMessage(Component.translatable("advMode.notAllowed"));
} else {
BaseCommandBlock baseCommandBlock = null;
@@ -651,7 +_,7 @@
@@ -649,9 +_,9 @@
@Override
public void handleSetCommandMinecart(ServerboundSetCommandMinecartPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (!this.server.isCommandBlockEnabled()) {
- if (!this.server.isCommandBlockEnabled()) {
+ if (!this.player.level().isCommandBlockEnabled()) { // Paper - per level game rules - enabled command blocks
this.player.sendSystemMessage(Component.translatable("advMode.notEnabled"));
- } else if (!this.player.canUseGameMasterBlocks()) {
+ } else if (!this.player.canUseGameMasterBlocks() && (!this.player.isCreative() || !this.player.getBukkitEntity().hasPermission("minecraft.commandblock"))) { // Paper - command block permission
@@ -29,7 +29,7 @@
switch (packet.intention()) {
case LOGIN:
this.beginLogin(packet, false);
@@ -50,22 +_,118 @@
@@ -50,22 +_,119 @@
default:
throw new UnsupportedOperationException("Invalid intention " + packet.intention());
}
@@ -115,6 +115,7 @@
+ packet.port(),
+ packet.intention()
+ );
+ this.connection.hostname = event.getServerHostname();
+ }
+ if (event.getSocketAddressHostname() != null) this.connection.address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0);
+ this.connection.spoofedUUID = event.getUniqueId();
@@ -212,7 +212,7 @@
}
}
@@ -224,18 +_,113 @@
@@ -224,18 +_,123 @@
? ((InetSocketAddress)remoteAddress).getAddress()
: null;
}
@@ -278,6 +278,16 @@
@Override
public void handleCustomQueryPacket(ServerboundCustomQueryAnswerPacket packet) {
+ // Paper start - Add Velocity IP Forwarding Support
+ try {
+ this.handleCustomQueryPacket0(packet);
+ } finally {
+ ServerboundCustomQueryAnswerPacket.QueryAnswerPayload payload = (ServerboundCustomQueryAnswerPacket.QueryAnswerPayload) packet.payload();
+ if (payload != null) {
+ payload.buffer.release();
+ }
+ }
+ }
+ private void handleCustomQueryPacket0(ServerboundCustomQueryAnswerPacket packet) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled && packet.transactionId() == this.velocityLoginMessageId) {
+ ServerboundCustomQueryAnswerPacket.QueryAnswerPayload payload = (ServerboundCustomQueryAnswerPacket.QueryAnswerPayload)packet.payload();
+ if (payload == null) {
@@ -760,17 +760,20 @@
output.storeNullable("CustomName", ComponentSerialization.CODEC, this.getCustomName());
if (this.isCustomNameVisible()) {
output.putBoolean("CustomNameVisible", this.isCustomNameVisible());
@@ -1976,9 +_,12 @@
@@ -1976,9 +_,14 @@
output.putInt("TicksFrozen", this.getTicksFrozen());
}
- if (this.hasVisualFire) {
- output.putBoolean("HasVisualFire", this.hasVisualFire);
- }
+ // Paper start - improve visual fire API
+ if (this.visualFire.equals(net.kyori.adventure.util.TriState.TRUE)) {
+ output.putBoolean("HasVisualFire", true);
}
+ output.putString("Paper.FireOverride", visualFire.name());
+ }
+ if (this.visualFire != net.kyori.adventure.util.TriState.NOT_SET) {
+ output.putString("Paper.FireOverride", visualFire.name());
+ }
+ // Paper end
if (!this.tags.isEmpty()) {
@@ -1270,17 +1273,15 @@
}
protected boolean canAddPassenger(Entity passenger) {
@@ -2505,8 +_,8 @@
@@ -2505,7 +_,7 @@
TeleportTransition portalDestination = this.portalProcess.getPortalDestination(serverLevel, this);
if (portalDestination != null) {
ServerLevel level = portalDestination.newLevel();
- if (serverLevel.getServer().isAllowedToEnterPortal(level)
- && (level.dimension() == serverLevel.dimension() || this.canTeleport(serverLevel, level))) {
+ if (this instanceof ServerPlayer // CraftBukkit - always call event for players
+ || (level != null && (level.dimension() == serverLevel.dimension() || this.canTeleport(serverLevel, level)))) { // CraftBukkit
+ if (serverLevel.getServer().isAllowedToEnterPortal(serverLevel, level) // Paper - Pass source and destination levels
&& (level.dimension() == serverLevel.dimension() || this.canTeleport(serverLevel, level))) {
this.teleport(portalDestination);
}
}
@@ -2587,7 +_,7 @@
}
@@ -1,17 +1,19 @@
--- a/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -21,6 +_,14 @@
@@ -21,6 +_,7 @@
return this.creeper.getSwellDir() > 0 || target != null && this.creeper.distanceToSqr(target) < 9.0;
}
+ // Paper start - Fix MC-179072
+ @Override
+ public boolean canContinueToUse() {
+ return !net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(this.creeper.getTarget()) && this.canUse();
+ }
+ // Paper end
+
+
@Override
public void start() {
this.creeper.getNavigation().stop();
@@ -41,7 +_,7 @@
public void tick() {
if (this.target == null) {
this.creeper.setSwellDir(-1);
- } else if (this.creeper.distanceToSqr(this.target) > 49.0) {
+ } else if (this.creeper.distanceToSqr(this.target) > 49.0 || !net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(this.target)) { // Paper - Fix MC-179072 - consider creative / spectator players as out of reach
this.creeper.setSwellDir(-1);
} else if (!this.creeper.getSensing().hasLineOfSight(this.target)) {
this.creeper.setSwellDir(-1);
@@ -1,6 +1,14 @@
--- a/net/minecraft/world/item/SpawnEggItem.java
+++ b/net/minecraft/world/item/SpawnEggItem.java
@@ -68,6 +_,7 @@
@@ -61,13 +_,14 @@
EntityType<?> type = this.getType(itemInHand);
if (type == null) {
return InteractionResult.FAIL;
- } else if (!serverLevel.getServer().isSpawnerBlockEnabled()) {
+ } else if (!serverLevel.isSpawnerBlockEnabled()) { // Paper - per level game rules - spawner block enabled
if (context.getPlayer() instanceof ServerPlayer serverPlayer) {
serverPlayer.sendSystemMessage(Component.translatable("advMode.notEnabled.spawner"));
}
return InteractionResult.FAIL;
} else {
@@ -10,6 +10,15 @@
public int getSuccessCount() {
return this.successCount;
@@ -101,7 +_,7 @@
} else {
this.successCount = 0;
MinecraftServer server = this.getLevel().getServer();
- if (server.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) {
+ if (level.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { // Paper - per level game rules - enabled command blocks
try {
this.lastOutput = null;
@@ -112,7 +_,13 @@
this.successCount++;
}
@@ -21,14 +21,15 @@
}
public void serverTick(ServerLevel level, BlockPos pos) {
- if (this.isNearPlayer(level, pos) && level.getServer().isSpawnerBlockEnabled()) {
- if (this.spawnDelay == -1) {
+ if (spawnCount <= 0 || maxNearbyEntities <= 0) return; // Paper - Ignore impossible spawn tick
+ // Paper start - Configurable mob spawner tick rate
+ if (spawnDelay > 0 && --tickDelay > 0) return;
+ tickDelay = level.paperConfig().tickRates.mobSpawner;
+ if (tickDelay == -1) { return; } // If disabled
+ // Paper end - Configurable mob spawner tick rate
if (this.isNearPlayer(level, pos) && level.getServer().isSpawnerBlockEnabled()) {
- if (this.spawnDelay == -1) {
+ if (this.isNearPlayer(level, pos) && level.isSpawnerBlockEnabled()) { // Paper - per level game rules - spawner block enabled
+ if (this.spawnDelay < -tickDelay) { // Paper - Configurable mob spawner tick rate
this.delay(level, pos);
}
@@ -518,7 +518,17 @@
this.getChunkAt(blockPos).addAndRegisterBlockEntity(blockEntity);
}
}
@@ -1039,7 +_,8 @@
@@ -1034,12 +_,18 @@
return this.palettedContainerFactory;
}
+ // Paper start - per level game rules
+ public abstract boolean isCommandBlockEnabled();
+ public abstract boolean isSpawnerBlockEnabled();
+ // Paper end - per level game rules
+
public static enum ExplosionInteraction implements StringRepresentable {
NONE("none"),
BLOCK("block"),
MOB("mob"),
TNT("tnt"),
@@ -64,7 +64,7 @@
}
d3 += d * 0.3F;
@@ -176,8 +_,8 @@
@@ -176,27 +_,64 @@
int floor3 = Mth.floor(this.center.y + f + 1.0);
int floor4 = Mth.floor(this.center.z - f - 1.0);
int floor5 = Mth.floor(this.center.z + f + 1.0);
@@ -74,8 +74,9 @@
+ for (Entity entity : list) { // Paper - used in loop
if (!entity.ignoreExplosion(this)) {
double d = Math.sqrt(entity.distanceToSqr(this.center)) / f;
+ if (Double.isNaN(d)) d = Double.POSITIVE_INFINITY; // Paper - avoid infinite damage/velocity when distance and radius are 0 - +inf is chosen as 0+h / 0 is evaluated to +inf for all positive h, which distanceSqrt complies with
if (!(d > 1.0)) {
@@ -185,18 +_,54 @@
Vec3 vec3 = entity instanceof PrimedTnt ? entity.position() : entity.getEyePosition();
Vec3 vec31 = vec3.subtract(this.center).normalize();
boolean shouldDamageEntity = this.damageCalculator.shouldDamageEntity(this, entity);
float knockbackMultiplier = this.damageCalculator.getKnockbackMultiplier(entity);
@@ -82,12 +82,12 @@ public class CraftBlockType<B extends @NonNull BlockData> extends HolderableBase
private static boolean isInteractable(Block block) {
Class<?> clazz = block.getClass();
boolean hasMethod = CraftBlockType.hasMethod(clazz, CraftBlockType.USE_WITHOUT_ITEM_ARGS) || CraftBlockType.hasMethod(clazz, CraftBlockType.USE_ITEM_ON_ARGS);
if (!hasMethod && clazz.getSuperclass() != BlockBehaviour.class) {
clazz = clazz.getSuperclass();
boolean hasMethod = false;
while (!hasMethod && clazz != BlockBehaviour.class && clazz != null) {
hasMethod = CraftBlockType.hasMethod(clazz, CraftBlockType.USE_WITHOUT_ITEM_ARGS) || CraftBlockType.hasMethod(clazz, CraftBlockType.USE_ITEM_ON_ARGS);
clazz = clazz.getSuperclass();
}
return hasMethod;