From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Helvetica Volubi Date: Sun, 8 Mar 2026 23:56:06 +0800 Subject: [PATCH] Leaves: Creative fly no clip Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com> As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/da12a58e8d3bd3cd13b52a60676d5a1e03acd30a/leaves-server/minecraft-patches/features/0049-Creative-fly-no-clip.patch) Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java index 700c9c0d40dee1df6c97f7c63ad731f16bc5f3e7..b95c56e0699fbe16e65efcf010cd514f0ac0962f 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java @@ -204,7 +204,7 @@ public class ExperienceOrb extends Entity { Player prevTarget = this.followingPlayer; // CraftBukkit - store old target if (this.followingPlayer == null || this.followingPlayer.isSpectator() || this.followingPlayer.distanceToSqr(this) > 64.0) { Player nearestPlayer = this.level().getNearestPlayer(this, 8.0); - if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) { + if (nearestPlayer != null && !nearestPlayer.isCreativeFlyOrSpectator() && !nearestPlayer.isDeadOrDying()) { // Leaves - creative no clip this.followingPlayer = nearestPlayer; } else { this.followingPlayer = null; diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java index 3f4cf6e0ddce45ca169a5fdfc54b25f609eba44b..8709dabd6d3574e53210543321ca88c778594afc 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -284,8 +284,8 @@ public abstract class Player extends Avatar implements ContainerUser { if (this.cullTask != null) this.cullTask.requestCullSignal(); // Luminol - Ray tracing entity tracker // Luminol end - this.noPhysics = this.isSpectator(); - if (this.isSpectator() || this.isPassenger()) { + this.noPhysics = this.isCreativeFlyOrSpectator(); // Leaves - creative no clip + if (this.isCreativeFlyOrSpectator() || this.isPassenger()) { // Leaves - creative no clip this.setOnGround(false); } @@ -411,7 +411,7 @@ public abstract class Player extends Avatar implements ContainerUser { if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) { Pose desiredPose = this.getDesiredPose(); Pose actualPose; - if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) { + if (this.isCreativeFlyOrSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) { // Leaves - creative no clip actualPose = desiredPose; } else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) { actualPose = Pose.CROUCHING; @@ -540,7 +540,7 @@ public abstract class Player extends Avatar implements ContainerUser { this.updateSwingTime(); this.yHeadRot = this.getYRot(); this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED)); - if (this.getHealth() > 0.0F && !this.isSpectator()) { + if (this.getHealth() > 0.0F && !this.isCreativeFlyOrSpectator()) { // Leaves - creative no clip AABB pickupArea; if (this.isPassenger() && !this.getVehicle().isRemoved()) { pickupArea = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0); @@ -1872,6 +1872,26 @@ public abstract class Player extends Avatar implements ContainerUser { return this.gameMode() == GameType.SPECTATOR; } + // Leaves start - creative no clip + public boolean isCreativeFlyOrSpectator() { + return isSpectator() || (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && isCreative() && getAbilities().flying); + } + + public boolean canSpectatingPlace(final net.minecraft.world.level.LevelReader world, final BlockState state, final BlockPos pos, final net.minecraft.world.phys.shapes.CollisionContext context) { + if (this.isCreativeFlyOrSpectator()) { + net.minecraft.world.phys.shapes.VoxelShape voxelShape = state.getCollisionShape(world, pos, context); + return voxelShape.isEmpty() || world.isUnobstructed(this, voxelShape.move(pos.getX(), pos.getY(), pos.getZ())); + } else { + return world.isUnobstructed(state, pos, context); + } + } + + @Override + public boolean isCollidable(final boolean ignoreClimbing) { + return !isCreativeFlyOrSpectator() && super.isCollidable(ignoreClimbing); + } + // Leaves end - creative no clip + @Override public boolean isPickable() { return !this.isSpectator() && super.isPickable(); diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java index 0f4ac8eeb8f5f866b22a81f255f7169754437bfc..3b5aa0c45647c694e908aaae2a027db02b4f8385 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java @@ -162,8 +162,9 @@ public class BlockItem extends Item { Player player = context.getPlayer(); // CraftBukkit start Level world = context.getLevel(); // Paper - Cancel hit for vanished players + CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.placementContext(player); // Leaves - creative no clip boolean canBuild = (!this.mustSurvive() || stateForPlacement.canSurvive(world, context.getClickedPos())) - && world.checkEntityCollision(stateForPlacement, player, CollisionContext.placementContext(player), context.getClickedPos(), true); // Paper - Cancel hit for vanished players + && ((fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, stateForPlacement, context.getClickedPos(), collisionContext) : world.checkEntityCollision(stateForPlacement, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip org.bukkit.entity.Player bukkitPlayer = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent( diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java index 1f17f966882320b3a2ced50b3f73925cd0dfa14c..5a75df997c9026bcc740823d7039c8e426ea345a 100644 --- a/net/minecraft/world/item/StandingAndWallBlockItem.java +++ b/net/minecraft/world/item/StandingAndWallBlockItem.java @@ -44,7 +44,7 @@ public class StandingAndWallBlockItem extends BlockItem { // return stateForPlacement != null && level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()) ? stateForPlacement : null; // CraftBukkit start if (stateForPlacement != null) { - boolean defaultReturn = level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); + boolean defaultReturn = (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(level, stateForPlacement, pos, CollisionContext.empty()) : level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); // Leaves - creative no clip org.bukkit.entity.Player player = (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer serverPlayer) ? serverPlayer.getBukkitEntity() : null; org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), pos), player, stateForPlacement.asBlockData(), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java index 8025fec49e6b9550d6154d6e735c6a39a2352f24..2c27de099c203b51b0fb317a8160402b3189e41c 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java @@ -153,7 +153,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl List entities = level.getEntities(null, aabb); if (!entities.isEmpty()) { for (Entity entity : entities) { - if (entity.getPistonPushReaction() != PushReaction.IGNORE) { + if (entity.getPistonPushReaction() != PushReaction.IGNORE && !(entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator())) { // Leaves - creative no clip entity.move( MoverType.SHULKER_BOX, new Vec3( diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java index 15605dacaec3860e476a70dbdd3743e4197f67a6..199f23547fded9b7d311b9cf21484d863748fd1c 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java @@ -168,7 +168,7 @@ public class PistonMovingBlockEntity extends BlockEntity { dz = movement.getStepZ(); } - entity.setDeltaMovement(dx, dy, dz); + if (!(entity instanceof net.minecraft.world.entity.player.Player player) || !player.isCreativeFlyOrSpectator()) entity.setDeltaMovement(dx, dy, dz); // Leaves - creative no clip // Paper - EAR items stuck in slime pushed by a piston entity.activatedTick = Math.max(entity.activatedTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 10); // Folia - region threading entity.activatedImmunityTick = Math.max(entity.activatedImmunityTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 10); // Folia - region threading @@ -204,6 +204,7 @@ public class PistonMovingBlockEntity extends BlockEntity { } private static void moveEntityByPiston(final Direction pistonDirection, final Entity entity, final double delta, final Direction movement) { + if (entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator()) return; // Leaves - creative no clip NOCLIP.set(pistonDirection); Vec3 previousPos = entity.position(); entity.move(MoverType.PISTON, new Vec3(delta * movement.getStepX(), delta * movement.getStepY(), delta * movement.getStepZ()));