From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Bacteriawa Date: Sun, 22 Mar 2026 01:39:15 +0800 Subject: [PATCH] Carpet features diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java index 64c9f1d36ac9f02f0dd574ffb995e56a08631bfc..cb68671e513fc812723b2abbdd21e8d6e18cf808 100644 --- a/io/papermc/paper/threadedregions/RegionizedServer.java +++ b/io/papermc/paper/threadedregions/RegionizedServer.java @@ -337,6 +337,7 @@ public final class RegionizedServer { } this.randomWalk(); */ + final long tickStartNanos = System.nanoTime(); // Lophine - Carpet features ++this.tickCount; // Luminol start - Add a config to enable tick command if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) { @@ -379,6 +380,10 @@ public final class RegionizedServer { } // Lophine end - Add a config to enable tick command + // Lophine start - Carpet features + fun.bm.lophine.protocol.tiscm.TISCMProtocol.broadcastMsptSample(this.tickCount, System.nanoTime() - tickStartNanos); + + // Lophine end - Carpet features // tick connections this.tickConnections(); diff --git a/net/minecraft/commands/arguments/blocks/BlockInput.java b/net/minecraft/commands/arguments/blocks/BlockInput.java index 29dcaa5b33e4f6c649b0918721cfaafe9c74eb01..c7e4f2345c8d48b263eeb537d5fcce3ac43bb59e 100644 --- a/net/minecraft/commands/arguments/blocks/BlockInput.java +++ b/net/minecraft/commands/arguments/blocks/BlockInput.java @@ -65,7 +65,11 @@ public class BlockInput implements Predicate { } public boolean place(final ServerLevel level, final BlockPos pos, final @Block.UpdateFlags int update) { - BlockState state = (update & Block.UPDATE_KNOWN_SHAPE) != 0 ? this.state : Block.updateFromNeighbourShapes(this.state, level, pos); + // Lophine start - Carpet features + BlockState state = (update & Block.UPDATE_KNOWN_SHAPE) != 0 || fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates() + ? this.state + : Block.updateFromNeighbourShapes(this.state, level, pos); + // Lophine end - Carpet features if (state.isAir()) { state = this.state; } diff --git a/net/minecraft/core/Direction.java b/net/minecraft/core/Direction.java index 46547155b817a89a8afe2f8d1a30bf881efc07bc..c9a766f14fd2ad7f42af252b702e8ecd9956cb64 100644 --- a/net/minecraft/core/Direction.java +++ b/net/minecraft/core/Direction.java @@ -136,7 +136,7 @@ public enum Direction implements StringRepresentable, ca.spottedleaf.moonrise.pa public static Direction[] orderedByNearest(final Entity entity) { float pitch = entity.getViewXRot(1.0F) * Mth.DEG_TO_RAD; - float yaw = -entity.getViewYRot(1.0F) * Mth.DEG_TO_RAD; + float yaw = -(fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.placementRotationFix ? entity.getYRot(1.0F) : entity.getViewYRot(1.0F)) * Mth.DEG_TO_RAD; // Lophine - Carpet features float pitchSin = Mth.sin(pitch); float pitchCos = Mth.cos(pitch); float yawSin = Mth.sin(yaw); diff --git a/net/minecraft/network/chat/SignedMessageValidator.java b/net/minecraft/network/chat/SignedMessageValidator.java index a28958b8ab09b3ffdcedba19e0063af07f177080..c37a985102198add61f7d70e33e21d585fb2b399 100644 --- a/net/minecraft/network/chat/SignedMessageValidator.java +++ b/net/minecraft/network/chat/SignedMessageValidator.java @@ -31,7 +31,11 @@ public interface SignedMessageValidator { private boolean validateChain(final PlayerChatMessage message) { if (message.equals(this.lastMessage)) { return true; - } else if (this.lastMessage != null && !message.link().isDescendantOf(this.lastMessage.link())) { + // Lophine start - Carpet features + } else if (this.lastMessage != null + && !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.yeetOutOfOrderChatKick + && !message.link().isDescendantOf(this.lastMessage.link())) { + // Lophine end - Carpet features LOGGER.error( "Received out-of-order chat message from {}: expected index > {} for session {}, but was {} for session {}", message.sender(), diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java index 4421658e4061299dea2ff72a77506214cc9045d8..53bda989ce23d9eb144f1dc3d54fbe2a91cd1e17 100644 --- a/net/minecraft/server/commands/TickCommand.java +++ b/net/minecraft/server/commands/TickCommand.java @@ -21,7 +21,7 @@ public class TickCommand { public static void register(final CommandDispatcher dispatcher) { dispatcher.register( Commands.literal("tick") - .requires(Commands.hasPermission(Commands.LEVEL_ADMINS)) + .requires(Commands.hasPermission(tickCommandPermissionCheck())) // Lophine - Carpet features .then(Commands.literal("query").executes(c -> tickQuery(c.getSource()))) .then( // Lophine - Add tick rate support Commands.literal("rate") @@ -107,8 +107,14 @@ public class TickCommand { return Command.SINGLE_SUCCESS; } - private static int setFreeze(final CommandSourceStack source, final boolean freeze) { + private static int setFreeze(final CommandSourceStack source, boolean freeze) { // Lophine - Carpet features ServerTickRateManager manager = source.getServer().tickRateManager(); + // Lophine start - Carpet features + if (freeze && fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tickFreezeCommandToggleable && manager.isFrozen()) { + freeze = false; + } + + // Lophine end - Carpet features if (freeze) { if (manager.isSprinting()) { manager.stopSprinting(); @@ -164,4 +170,10 @@ public class TickCommand { return 0; } } + // Lophine start - Carpet features + + private static net.minecraft.server.permissions.PermissionCheck tickCommandPermissionCheck() { + return new net.minecraft.server.permissions.PermissionCheck.Require(new net.minecraft.server.permissions.Permission.HasCommandLevel(net.minecraft.server.permissions.PermissionLevel.byId(fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.normalizedTickCommandPermission()))); + } + // Lophine end - Carpet features } diff --git a/net/minecraft/server/dedicated/DedicatedPlayerList.java b/net/minecraft/server/dedicated/DedicatedPlayerList.java index 8cc4fe9feb57902a4b9a6a26e6175ac00a2cef65..9ab1a812e43145120859734075e2ac995d0357c2 100644 --- a/net/minecraft/server/dedicated/DedicatedPlayerList.java +++ b/net/minecraft/server/dedicated/DedicatedPlayerList.java @@ -14,7 +14,7 @@ public class DedicatedPlayerList extends PlayerList { public DedicatedPlayerList(final DedicatedServer server, final LayeredRegistryAccess registries, final PlayerDataStorage playerDataStorage) { super(server, registries, playerDataStorage, server.notificationManager()); - this.setViewDistance(server.viewDistance()); + this.setViewDistance(Math.max(2, fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.viewDistance)); // Lophine - Carpet features this.setSimulationDistance(server.simulationDistance()); // Paper start - fix converting txt to json file; moved from constructor } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java index 4a22a07cd0e0d81cf7b12a91e75ec78d7d7b9836..82a9143d43425943d6b730c8a43446881061ac2c 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -260,6 +260,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private int requestedViewDistance = 2; public String language = null; // Paper - default to null public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + private @Nullable ClientInformation lastKnownClientInformation; // Lophine - Carpet features private @Nullable Vec3 startingToFallPosition; private @Nullable Vec3 enteredNetherPosition; private @Nullable Vec3 enteredLavaOnVehiclePosition; @@ -2805,6 +2806,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.setShoulderEntityRight(oldPlayer.getShoulderEntityRight()); this.setLastDeathLocation(oldPlayer.getLastDeathLocation()); this.waypointIcon().copyFrom(oldPlayer.waypointIcon()); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.clientSettingsLostOnRespawnFix && oldPlayer.lastKnownClientInformation != null) { + this.updateOptions(oldPlayer.lastKnownClientInformation); + } + // Lophine end - Carpet features } private void transferInventoryXpAndScore(final Player oldPlayer) { @@ -3084,6 +3090,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.particleStatus = information.particleStatus(); this.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, (byte)information.modelCustomisation()); this.getEntityData().set(DATA_PLAYER_MAIN_HAND, information.mainHand()); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.clientSettingsLostOnRespawnFix) { + this.lastKnownClientInformation = information; + } + // Lophine end - Carpet features } public ClientInformation clientInformation() { diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java index b5e19220cd137c91ee992aa011593d625f741222..d94111b1171e83822885f616db4cd6fccc39298d 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -2073,7 +2073,15 @@ public class ServerGamePacketListenerImpl this.player.gameMode.capturedBlockEntity = false; this.player.gameMode.captureSentBlockEntities = true; // Paper end - Send block entities after destroy prediction - this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence()); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.interactionUpdates) { + this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence()); + } else { + fun.bm.lophine.carpet.InteractionUpdateCompatHelper.runWithSuppressedUpdates( + () -> this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence()) + ); + } + // Lophine end - Carpet features this.ackBlockChangesUpTo(packet.getSequence()); // Paper start - Send block entities after destroy prediction this.player.gameMode.captureSentBlockEntities = false; @@ -2176,7 +2184,9 @@ public class ServerGamePacketListenerImpl if (!me.earthme.luminol.config.modules.fixes.ItemMultitaskConfig.enabled) { // Luminol - Add item multitask config this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 } // Luminol - Add item multitask config - InteractionResult interactionResult = this.player.gameMode.useItemOn(this.player, level, itemStack, hand, blockHit); + InteractionResult interactionResult = this.runInteractionWithConfiguredUpdates( + () -> this.player.gameMode.useItemOn(this.player, level, itemStack, hand, blockHit) + ); if (interactionResult.consumesAction()) { CriteriaTriggers.ANY_BLOCK_USE.trigger(this.player, blockHit.getBlockPos(), itemStack); } @@ -2281,7 +2291,10 @@ public class ServerGamePacketListenerImpl } // CraftBukkit end - if (this.player.gameMode.useItem(this.player, level, itemStack, hand) instanceof InteractionResult.Success success + // Lophine start - Carpet features + ItemStack itemStackToUse = itemStack; + if (this.runInteractionWithConfiguredUpdates(() -> this.player.gameMode.useItem(this.player, level, itemStackToUse, hand)) instanceof InteractionResult.Success success + // Lophine end - Carpet features && success.swingSource() == InteractionResult.SwingSource.SERVER) { this.player.swing(hand, true); } @@ -2289,6 +2302,16 @@ public class ServerGamePacketListenerImpl } } + // Lophine start - Carpet features + private T runInteractionWithConfiguredUpdates(final java.util.function.Supplier action) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.interactionUpdates) { + return action.get(); + } + + return fun.bm.lophine.carpet.InteractionUpdateCompatHelper.supplyWithSuppressedUpdates(action); + } + + // Lophine end - Carpet features @Override public void handleTeleportToEntityPacket(final ServerboundTeleportToEntityPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); @@ -2669,6 +2692,10 @@ public class ServerGamePacketListenerImpl if (true) throw new UnsupportedOperationException(); // Folia - region threading final String conversationInput = rawMessage; this.server.processQueue.add(() -> ServerGamePacketListenerImpl.this.getCraftPlayer().acceptConversationInput(conversationInput)); + // Lophine start - Carpet features + } else if (fun.bm.lophine.carpet.CarpetCalculatorCompatHelper.handleChat(this.player, rawMessage)) { + return; + // Lophine end - Carpet features } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false)); } else { @@ -2681,6 +2708,9 @@ public class ServerGamePacketListenerImpl // Spigot start - spam exclusions private void detectRateSpam(final TickThrottler throttler, final String message) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.antiSpamDisabled) { + return; + } if (me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable) return; // Leaves - disable // CraftBukkit start - replaced with thread safe throttle if (org.spigotmc.SpigotConfig.enableSpamExclusions) { @@ -3627,8 +3657,10 @@ public class ServerGamePacketListenerImpl if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - item over-stack util - force send carried item if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. } else if (drop && validData) { - if (this.dropSpamThrottler.isUnderThreshold()) { - this.dropSpamThrottler.increment(); + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.antiSpamDisabled || this.dropSpamThrottler.isUnderThreshold()) { + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.antiSpamDisabled) { + this.dropSpamThrottler.increment(); + } this.player.drop(itemStack, true); } else { LOGGER.warn("Player {} was dropping items too fast in creative mode, ignoring.", this.player.getPlainTextName()); diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java index b95c56e0699fbe16e65efcf010cd514f0ac0962f..0125d59551accd9005aa33a5c7cc8ec288fb7757 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java @@ -356,8 +356,27 @@ public class ExperienceOrb extends Entity { @Override public void playerTouch(final Player player) { if (player instanceof ServerPlayer serverPlayer) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.xpNoCooldown) { + player.takeXpDelay = 0; + } + + // Lophine end - Carpet features if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent - player.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(player, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entity.takeXpDelay = 2; + // Lophine start - Carpet features + int newCooldown = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(player, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entity.takeXpDelay = 2; + player.takeXpDelay = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.xpNoCooldown ? 0 : newCooldown; + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.xpNoCooldown) { + while (this.count > 1) { + int remaining = this.repairPlayerItems(serverPlayer, this.getValue()); + if (remaining > 0) { + player.giveExperiencePoints(org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerExpChangeEvent(player, this, remaining).getAmount()); // CraftBukkit - remaining -> event.getAmount() // Paper - supply experience orb + } + this.count--; + } + } + + // Lophine end - Carpet features player.take(this, 1); int remaining = this.repairPlayerItems(serverPlayer, this.getValue()); if (remaining > 0) { @@ -373,6 +392,12 @@ public class ExperienceOrb extends Entity { } private int repairPlayerItems(final ServerPlayer player, final int amount) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.powerfulExpMending) { + return this.repairAllPlayerItems(player, amount); + } + + // Lophine end - Carpet features Optional selected = EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged); if (selected.isPresent()) { ItemStack itemStack = selected.get().itemStack(); @@ -402,6 +427,78 @@ public class ExperienceOrb extends Entity { } } + // Lophine start - Carpet features + private int repairAllPlayerItems(ServerPlayer player, int value) { + List candidates = new java.util.ArrayList<>(); + net.minecraft.world.entity.player.Inventory inventory = player.getInventory(); + + for (int slotIndex = 0; slotIndex < inventory.getNonEquipmentItems().size(); slotIndex++) { + ItemStack stack = inventory.getNonEquipmentItems().get(slotIndex); + EquipmentSlot slot = slotIndex == inventory.getSelectedSlot() ? EquipmentSlot.MAINHAND : null; + candidates.add(new MendingCandidate(stack, slot)); + } + + candidates.add(new MendingCandidate(player.getItemBySlot(EquipmentSlot.HEAD), EquipmentSlot.HEAD)); + candidates.add(new MendingCandidate(player.getItemBySlot(EquipmentSlot.CHEST), EquipmentSlot.CHEST)); + candidates.add(new MendingCandidate(player.getItemBySlot(EquipmentSlot.LEGS), EquipmentSlot.LEGS)); + candidates.add(new MendingCandidate(player.getItemBySlot(EquipmentSlot.FEET), EquipmentSlot.FEET)); + candidates.add(new MendingCandidate(player.getItemBySlot(EquipmentSlot.OFFHAND), EquipmentSlot.OFFHAND)); + + java.util.Collections.shuffle(candidates, new java.util.Random(player.getRandom().nextLong())); + + int remaining = value; + for (MendingCandidate candidate : candidates) { + if (remaining <= 0) { + break; + } + + ItemStack stack = candidate.stack(); + if (!this.canRepairWithXp(player, stack)) { + continue; + } + + int durabilityToRepair = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), stack, remaining); + int repairedAmount = Math.min(durabilityToRepair, stack.getDamageValue()); + if (repairedAmount <= 0) { + continue; + } + + org.bukkit.event.player.PlayerItemMendEvent event = candidate.slot() != null + ? org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent( + player, this, stack, candidate.slot(), repairedAmount, repairedAmount * remaining / durabilityToRepair + ) + : this.callInventoryItemMendEvent(player, stack, repairedAmount); + repairedAmount = event.getRepairAmount(); + if (event.isCancelled() || repairedAmount <= 0) { + continue; + } + + stack.setDamageValue(stack.getDamageValue() - repairedAmount); + remaining -= repairedAmount * remaining / durabilityToRepair; + } + + return remaining; + } + + private boolean canRepairWithXp(ServerPlayer player, ItemStack stack) { + return !stack.isEmpty() && stack.isDamaged() && EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), stack, 1) > 1; + } + + private org.bukkit.event.player.PlayerItemMendEvent callInventoryItemMendEvent(ServerPlayer player, ItemStack stack, int repairAmount) { + org.bukkit.event.player.PlayerItemMendEvent event = new org.bukkit.event.player.PlayerItemMendEvent( + player.getBukkitEntity(), + org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), + (org.bukkit.entity.ExperienceOrb)this.getBukkitEntity(), + repairAmount + ); + player.level().getCraftServer().getPluginManager().callEvent(event); + return event; + } + + private record MendingCandidate(ItemStack stack, @Nullable EquipmentSlot slot) { + } + + // Lophine end - Carpet features public int getValue() { return this.entityData.get(DATA_VALUE); } diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java index 1fe317cf3251bff7bb3e0335452a5714d4d31017..14a79e8ef5a98b1eef2f2d3e0c63f21cb5bb4dbf 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -623,7 +623,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin public boolean broadcastedDeath = false; // Folia - region threading protected void tickDeath() { this.deathTime++; - if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) { + // Lophine start - Carpet features + int removalDelay = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.entityInstantDeathRemoval ? 1 : 20; + if (this.deathTime >= removalDelay && !this.level().isClientSide() && !this.isRemoved()) { + // Lophine end - Carpet features this.level().broadcastEntityEvent(this, EntityEvent.POOF); this.broadcastedDeath = true; // Folia - region threading - death has been broadcasted if (!(this instanceof ServerPlayer)) this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause // Folia - region threading - don't remove, we want the tick scheduler to be running if ((this instanceof ServerPlayer)) this.unRide(); // Folia - region threading - unmount player when dead diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java index 4e8385b340686531297324983754fab4150e41b8..34018a6f7a8c97c489a938222df189e8790d015d 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java @@ -73,8 +73,14 @@ public class PrimedTnt extends Entity implements TraceableEntity { this(EntityTypes.TNT, level); this.setPos(x, y, z); double rot = this.getRandom().nextDouble() * (float) (Math.PI * 2); // Paper - Don't use level random in entity constructors - this.setDeltaMovement(-Math.sin(rot) * 0.02, 0.2F, -Math.cos(rot) * 0.02); - this.setFuse(80); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tntPrimerMomentumRemoved) { + this.setDeltaMovement(0.0, 0.20000000298023224, 0.0); + } else { + this.setDeltaMovement(-Math.sin(rot) * 0.02, 0.2F, -Math.cos(rot) * 0.02); + } + this.setFuse(getConfiguredFuseTime()); + // Lophine end - Carpet features this.xo = x; this.yo = y; this.zo = z; @@ -83,7 +89,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { @Override protected void defineSynchedData(final SynchedEntityData.Builder entityData) { - entityData.define(DATA_FUSE_ID, 80); + entityData.define(DATA_FUSE_ID, getConfiguredFuseTime()); // Lophine - Carpet features entityData.define(DATA_BLOCK_STATE_ID, DEFAULT_BLOCK_STATE); } @@ -180,7 +186,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { @Override protected void readAdditionalSaveData(final ValueInput input) { - this.setFuse(input.getShortOr("fuse", (short)80)); + this.setFuse(input.getShortOr("fuse", (short)getConfiguredFuseTime())); // Lophine - Carpet features this.setBlockState(input.read("block_state", BlockState.CODEC).orElse(DEFAULT_BLOCK_STATE)); this.explosionPower = Mth.clamp(input.getFloatOr("explosion_power", 4.0F), 0.0F, 128.0F); this.owner = EntityReference.read(input, "owner"); @@ -203,6 +209,12 @@ public class PrimedTnt extends Entity implements TraceableEntity { this.entityData.set(DATA_FUSE_ID, time); } + // Lophine start - Carpet features + private static int getConfiguredFuseTime() { + return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.normalizedTntFuseDuration(); + } + + // Lophine end - Carpet features public int getFuse() { return this.entityData.get(DATA_FUSE_ID); } diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java index d2ac2a0c5bb18c2bca18e5166ed65afd01166e04..6b3adf1af870c3d710494d34d2f25850126516eb 100644 --- a/net/minecraft/world/entity/monster/EnderMan.java +++ b/net/minecraft/world/entity/monster/EnderMan.java @@ -643,7 +643,7 @@ public class EnderMan extends Monster implements NeutralMob { Vec3 to = new Vec3(xt + 0.5, yt + 0.5, zt + 0.5); BlockHitResult result = level.clip(new ClipContext(from, to, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); boolean reachable = result.getBlockPos().equals(pos); - if (blockState.is(BlockTags.ENDERMAN_HOLDABLE) && reachable) { + if (canPickupBlock(blockState) && reachable) { // Lophine - Carpet features if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.enderman, pos, blockState.getFluidState().createLegacyBlock())) { // Paper - Place event level.removeBlock(pos, false); level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(this.enderman, blockState)); @@ -651,5 +651,15 @@ public class EnderMan extends Monster implements NeutralMob { } // CraftBukkit } } + // Lophine start - Carpet features + + private static boolean canPickupBlock(BlockState state) { + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.sensibleEnderman) { + return state.is(BlockTags.ENDERMAN_HOLDABLE); + } + + return state.is(Blocks.MELON) || state.is(Blocks.PUMPKIN); + } + // Lophine end - Carpet features } } diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java index d46abbea2153cac2d939416fafeac7f905fe0e02..e224c1b8977cd97f2868f7db56c1df22a6820918 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -560,7 +560,15 @@ public abstract class Player extends Avatar implements ContainerUser { } if (!orbs.isEmpty()) { - this.touch(Util.getRandom(orbs, this.random)); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.xpNoCooldown) { + for (Entity orb : orbs) { + this.touch(orb); + } + } else { + this.touch(Util.getRandom(orbs, this.random)); + } + // Lophine end - Carpet features } } @@ -1078,6 +1086,28 @@ public abstract class Player extends Avatar implements ContainerUser { if (playerAttackEntityEvent.callEvent() && willAttack) { // Logic moved to willAttack local variable. // Paper end - PlayerAttackEntityEvent + // Lophine start - Carpet features + if (this.level() instanceof ServerLevel serverLevel + && fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeOneHitKill + && this.isCreative() + && net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity)) { + if (this.isShiftKeyDown()) { + for (Entity nearbyEntity : this.level().getEntities( + this, + entity.getBoundingBox().inflate(2.0, 0.5, 2.0), + candidate -> candidate.isAttackable() && net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(candidate) + )) { + this.creativeInstantKill(serverLevel, nearbyEntity); + } + this.playServerSideSound(SoundEvents.PLAYER_ATTACK_SWEEP); + } else { + this.creativeInstantKill(serverLevel, entity); + this.playServerSideSound(SoundEvents.PLAYER_ATTACK_CRIT); + } + return; + } + + // Lophine end - Carpet features float baseDamage = this.isAutoSpinAttack() ? this.autoSpinAttackDmg : (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ItemStack attackingItemStack = this.getWeaponItem(); DamageSource damageSource = this.createAttackSource(attackingItemStack); final DamageSource dmgSourceFinal = damageSource; // Paper - damage events @@ -1137,6 +1167,18 @@ public abstract class Player extends Avatar implements ContainerUser { } } + // Lophine start - Carpet features + private void creativeInstantKill(final ServerLevel level, final Entity target) { + if (target instanceof EnderDragonPart enderDragonPart) { + java.util.Arrays.stream(enderDragonPart.parentMob.getSubEntities()).forEach(part -> part.kill(level)); + enderDragonPart.parentMob.kill(level); + return; + } + + target.kill(level); + } + + // Lophine end - Carpet features private void playServerSideSound(final SoundEvent sound) { sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility } diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java index 02b8f4aa4aefea0391ab4ce6d634f3a050c80f5a..af3abbc1b24d0d68cd71f14af2419df52ec5da90 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java @@ -149,8 +149,12 @@ public class BlockItem extends Item { // 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 ignoreEntityCollision = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.blockPlacementIgnoreEntity && player != null && player.isCreative(); boolean canBuild = (!this.mustSurvive() || stateForPlacement.canSurvive(world, context.getClickedPos())) - && ((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 + && (ignoreEntityCollision + || ((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/ServerItemCooldowns.java b/net/minecraft/world/item/ServerItemCooldowns.java index ca548c006dfde82bef3f8855e275df63a42b8e09..c447a5ccce7c859ed61ab42e25d683262df9e062 100644 --- a/net/minecraft/world/item/ServerItemCooldowns.java +++ b/net/minecraft/world/item/ServerItemCooldowns.java @@ -14,6 +14,11 @@ public class ServerItemCooldowns extends ItemCooldowns { // Paper start - Add PlayerItemCooldownEvent @Override public void addCooldown(ItemStack item, int duration) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoItemCooldown && this.player.isCreative()) { + return; + } + // Lophine end - Carpet features final Identifier cooldownGroup = this.getCooldownGroup(item); final io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent( this.player.getBukkitEntity(), diff --git a/net/minecraft/world/item/crafting/RecipeManager.java b/net/minecraft/world/item/crafting/RecipeManager.java index 6812ade4d9de26d507234b8357b109ec7e5cbb50..071d2cd7e0c2e5bba0732590ba804a5cb5db3f5e 100644 --- a/net/minecraft/world/item/crafting/RecipeManager.java +++ b/net/minecraft/world/item/crafting/RecipeManager.java @@ -55,6 +55,11 @@ public class RecipeManager extends SimplePreparableReloadListener imp forSingleInput(RecipeType.CAMPFIRE_COOKING) ); private static final FileToIdConverter RECIPE_LISTER = FileToIdConverter.registry(Registries.RECIPE); + // Lophine start - Carpet features + private static final ResourceKey> BETTER_CRAFTABLE_BONE_BLOCK_RECIPE = compatRecipeKey("better_craftable_bone_block"); + private static final ResourceKey> BETTER_CRAFTABLE_DISPENSER_SHAPED_RECIPE = compatRecipeKey("better_craftable_dispenser_shaped"); + private static final ResourceKey> BETTER_CRAFTABLE_DISPENSER_SHAPELESS_RECIPE = compatRecipeKey("better_craftable_dispenser_shapeless"); + // Lophine end - Carpet features private final HolderLookup.Provider registries; public RecipeMap recipes = RecipeMap.EMPTY; private Map, RecipePropertySet> propertySets = Map.of(); @@ -83,10 +88,75 @@ public class RecipeManager extends SimplePreparableReloadListener imp @Override protected void apply(final RecipeMap recipes, final ResourceManager manager, final ProfilerFiller profiler) { + this.injectCompatRecipes(recipes); // Lophine - Carpet features this.recipes = recipes; LOGGER.info("Loaded {} recipes", recipes.values().size()); } + // Lophine start - Carpet features + private void injectCompatRecipes(final RecipeMap recipeMap) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.betterCraftableBoneBlock) { + addCompatRecipe(recipeMap, createBetterCraftableBoneBlockRecipe()); + } + + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.betterCraftableDispenser) { + addCompatRecipe(recipeMap, createBetterCraftableDispenserShapedRecipe()); + addCompatRecipe(recipeMap, createBetterCraftableDispenserShapelessRecipe()); + } + } + + private static void addCompatRecipe(final RecipeMap recipeMap, final RecipeHolder recipeHolder) { + if (recipeMap.byKey(recipeHolder.id()) == null) { + recipeMap.addRecipe(recipeHolder); + } + } + + private static RecipeHolder createBetterCraftableBoneBlockRecipe() { + return new RecipeHolder<>( + BETTER_CRAFTABLE_BONE_BLOCK_RECIPE, + new ShapedRecipe( + new Recipe.CommonInfo(true), + new CraftingRecipe.CraftingBookInfo(CraftingBookCategory.BUILDING, "carpet_ams_better_bone_block"), + ShapedRecipePattern.of(Map.of('#', Ingredient.of(net.minecraft.world.item.Items.BONE)), "###", "###", "###"), + new net.minecraft.world.item.ItemStackTemplate(net.minecraft.world.item.Items.BONE_BLOCK, 3) + ) + ); + } + + private static RecipeHolder createBetterCraftableDispenserShapedRecipe() { + return new RecipeHolder<>( + BETTER_CRAFTABLE_DISPENSER_SHAPED_RECIPE, + new ShapedRecipe( + new Recipe.CommonInfo(true), + new CraftingRecipe.CraftingBookInfo(CraftingBookCategory.REDSTONE, "carpet_ams_better_dispenser"), + ShapedRecipePattern.of( + Map.of('S', Ingredient.of(net.minecraft.world.item.Items.STICK), 'D', Ingredient.of(net.minecraft.world.item.Items.DROPPER), 'X', Ingredient.of(net.minecraft.world.item.Items.STRING)), + " SX", + "SDX", + " SX" + ), + new net.minecraft.world.item.ItemStackTemplate(net.minecraft.world.item.Items.DISPENSER) + ) + ); + } + + private static RecipeHolder createBetterCraftableDispenserShapelessRecipe() { + return new RecipeHolder<>( + BETTER_CRAFTABLE_DISPENSER_SHAPELESS_RECIPE, + new ShapelessRecipe( + new Recipe.CommonInfo(true), + new CraftingRecipe.CraftingBookInfo(CraftingBookCategory.REDSTONE, "carpet_ams_better_dispenser"), + new net.minecraft.world.item.ItemStackTemplate(net.minecraft.world.item.Items.DISPENSER), + List.of(Ingredient.of(net.minecraft.world.item.Items.BOW), Ingredient.of(net.minecraft.world.item.Items.DROPPER)) + ) + ); + } + + private static ResourceKey> compatRecipeKey(final String path) { + return ResourceKey.create(Registries.RECIPE, Identifier.fromNamespaceAndPath("lophine", path)); + } + + // Lophine end - Carpet features // CraftBukkit start public void addRecipe(RecipeHolder holder) { org.spigotmc.AsyncCatcher.catchOp("Recipe Add"); // Spigot diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java index fb368e4c09b44744ba634c22934b27ea804ea00e..6d3a5d648f4d04945a64e76995c0f4b5f81af779 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -1179,7 +1179,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // CraftBukkit start - Split off from above in order to directly send client and physic updates public void notifyAndUpdatePhysics(BlockPos pos, LevelChunk chunk, BlockState oldState, BlockState blockState, BlockState newState, @Block.UpdateFlags int updateFlags, int updateLimit) { if (newState == blockState) { - if (oldState != newState) { + // Lophine start - Carpet features + boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates(); + if (skipInteractionUpdates) { + updateFlags &= ~Block.UPDATE_NEIGHBORS; + } + // Lophine end - Carpet features + if (oldState != newState) { this.setBlocksDirty(pos, oldState, newState); } @@ -1194,7 +1200,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } } - if ((updateFlags & Block.UPDATE_KNOWN_SHAPE) == 0 && updateLimit > 0) { + if (!skipInteractionUpdates && (updateFlags & Block.UPDATE_KNOWN_SHAPE) == 0 && updateLimit > 0) { // Lophine - Carpet features int neighbourUpdateFlags = updateFlags & ~(Block.UPDATE_SUPPRESS_DROPS | Block.UPDATE_NEIGHBORS); // CraftBukkit start diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926649b097f 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java @@ -289,6 +289,12 @@ public final class NaturalSpawner { Player nearestPlayer = level.getNearestPlayer(xx, yStart, zz, -1.0, false); if (nearestPlayer != null) { double nearestPlayerDistanceSqr = nearestPlayer.distanceToSqr(xx, yStart, zz); + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) { + nearestPlayerDistanceSqr = fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.limitDistanceSq(mobCategory, nearestPlayerDistanceSqr); + } + + // Lophine end - Carpet features if (level.isLoadedAndInBounds(pos) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, pos, nearestPlayerDistanceSqr)) { // Paper - don't load chunks for mob spawn if (currentSpawnData == null) { Optional nextSpawnData = getRandomSpawnMobAt( @@ -329,6 +335,12 @@ public final class NaturalSpawner { // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. level.addFreshEntityWithPassengers(mob, (mob instanceof net.minecraft.world.entity.animal.feline.Ocelot && !((org.bukkit.entity.Ageable) mob.getBukkitEntity()).isAdult()) ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.OCELOT_BABY : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); if (!mob.isRemoved()) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) { + fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.markSpawned(level, mob.getType()); + } + + // Lophine end - Carpet features clusterSize++; groupSize++; spawnCallback.run(mob, chunk); @@ -408,11 +420,24 @@ public final class NaturalSpawner { && canSpawnMobAt(level, structureManager, generator, mobCategory, currentSpawnData, pos) && SpawnPlacements.isSpawnPositionOk(type, level, pos) && SpawnPlacements.checkSpawnRules(type, level, EntitySpawnReason.NATURAL, pos, level.random) - && level.noCollision(type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5)); + // Lophine start - Carpet features + && (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning + ? fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.hasNoCollision(level, type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5)) + : level.noCollision(type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5))); + // Lophine end - Carpet features return success ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent } private static @Nullable Mob getMobForSpawn(final ServerLevel level, final EntityType type) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) { + Mob cachedMob = fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.getOrCreateMob(level, type); + if (cachedMob != null) { + return cachedMob; + } + } + + // Lophine end - Carpet features try { if (type.create(level, EntitySpawnReason.NATURAL) instanceof Mob mob) { return mob; @@ -533,7 +558,11 @@ public final class NaturalSpawner { float width = spawnerData.type().getWidth(); double fx = Mth.clamp(x, (double)xo + width, xo + 16.0 - width); double fz = Mth.clamp(z, (double)zo + width, zo + 16.0 - width); - if (!level.noCollision(spawnerData.type().getSpawnAABB(fx, pos.getY(), fz)) + // Lophine start - Carpet features + if (!(fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning + ? fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.hasNoCollision(level.getLevel(), spawnerData.type().getSpawnAABB(fx, pos.getY(), fz)) + : level.noCollision(spawnerData.type().getSpawnAABB(fx, pos.getY(), fz))) + // Lophine end - Carpet features || !SpawnPlacements.checkSpawnRules( spawnerData.type(), level, @@ -565,6 +594,11 @@ public final class NaturalSpawner { level, level.getCurrentDifficultyAt(mob.blockPosition()), EntitySpawnReason.CHUNK_GENERATION, groupSpawnData ); level.addFreshEntityWithPassengers(mob, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) { + fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.markSpawned(level.getLevel(), mob.getType()); + } + // Lophine end - Carpet features success = true; } } diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java index b90077b44ce81d5d60f9d0ad2414f0b7c6b1e720..4f4512d30717e5e41bd98703574485c0e2b866fb 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java @@ -371,6 +371,12 @@ public class ServerExplosion implements Explosion { } private List calculateExplodedPositions() { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.explosionNoBlockDamage) { + return List.of(); + } + + // Lophine end - Carpet features // Paper start - collision optimisations final ObjectArrayList ret = new ObjectArrayList<>(); diff --git a/net/minecraft/world/level/block/CarvedPumpkinBlock.java b/net/minecraft/world/level/block/CarvedPumpkinBlock.java index 4ed03c9bb81a903c6ec68efe72845f20b083f3ac..003c19d8cad2ae5af770923a76735e4944b24c28 100644 --- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java +++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java @@ -59,7 +59,10 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { public boolean canSpawnGolem(final LevelReader level, final BlockPos topPos) { return this.getOrCreateSnowGolemBase().find(level, topPos) != null || this.getOrCreateIronGolemBase().find(level, topPos) != null - || this.getOrCreateCopperGolemBase().find(level, topPos) != null; + // Lophine start - Carpet features + || this.getOrCreateCopperGolemBase().find(level, topPos) != null + || this.canSpawnShulkerGolem(level, topPos); + // Lophine end - Carpet features } private void trySpawnGolem(final Level level, final BlockPos topPos) { @@ -92,6 +95,10 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { copperGolem.spawn(this.getWeatherStateFromPattern(copperGolemMatch)); } } + // Lophine start - Carpet features + + this.trySpawnShulkerGolem(level, topPos); + // Lophine end - Carpet features } private WeatheringCopper.WeatherState getWeatherStateFromPattern(final BlockPattern.BlockPatternMatch copperGolemMatch) { @@ -159,6 +166,44 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { builder.add(FACING); } + // Lophine start - Carpet features + private boolean canSpawnShulkerGolem(LevelReader level, BlockPos pos) { + return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.shulkerGolem + && PUMPKINS_PREDICATE.test(level.getBlockState(pos)) + && level.getBlockState(pos.below()).is(BlockTags.SHULKER_BOXES); + } + + private void trySpawnShulkerGolem(Level level, BlockPos pos) { + if (!this.canSpawnShulkerGolem(level, pos)) { + return; + } + + net.minecraft.world.entity.monster.Shulker shulker = EntityTypes.SHULKER.create(level, EntitySpawnReason.TRIGGERED); + if (shulker == null) { + return; + } + + BlockPos bodyPos = pos.below(); + BlockState headState = level.getBlockState(pos); + BlockState bodyState = level.getBlockState(bodyPos); + shulker.snapTo(bodyPos.getX() + 0.5, bodyPos.getY(), bodyPos.getZ() + 0.5, 0.0F, 0.0F); + if (!level.addFreshEntity(shulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM)) { + return; + } + + level.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS); + level.setBlock(bodyPos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS); + level.levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, pos, Block.getId(headState)); + level.levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, bodyPos, Block.getId(bodyState)); + level.updateNeighborsAt(pos, Blocks.AIR); + level.updateNeighborsAt(bodyPos, Blocks.AIR); + + for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, shulker.getBoundingBox().inflate(5.0))) { + CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, shulker); + } + } + + // Lophine end - Carpet features private BlockPattern getOrCreateSnowGolemBase() { if (this.snowGolemBase == null) { this.snowGolemBase = BlockPatternBuilder.start() diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java index 70a0d30552d42d91778e0524bb89f6619c1fd0b0..ff4f28446759a5d5968286323675a7cdbf75e92b 100644 --- a/net/minecraft/world/level/block/ChestBlock.java +++ b/net/minecraft/world/level/block/ChestBlock.java @@ -272,7 +272,10 @@ public class ChestBlock extends AbstractChestBlock implements final BlockState state, final Level level, final BlockPos pos, final Player player, final BlockHitResult hitResult ) { if (level instanceof ServerLevel serverLevel) { - MenuProvider menuProvider = this.getMenuProvider(state, level, pos); + // Lophine start - Carpet features + boolean ignoreObstructions = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeOpenContainerForcibly && player.isCreative(); + MenuProvider menuProvider = this.getMenuProvider(state, level, pos, ignoreObstructions); + // Lophine end - Carpet features if (menuProvider != null && player.openMenu(menuProvider).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation player.awardStat(this.getOpenChestStat()); PiglinAi.angerNearbyPiglins(serverLevel, player, true); diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java index bfc34508937befc0f7610176ebe625563f7a4fe0..b96afc074191d91e21d13c28c88f26f4e1881ee0 100644 --- a/net/minecraft/world/level/block/EnderChestBlock.java +++ b/net/minecraft/world/level/block/EnderChestBlock.java @@ -83,7 +83,10 @@ public class EnderChestBlock extends AbstractChestBlock i PlayerEnderChestContainer container = player.getEnderChestInventory(); if (container != null && level.getBlockEntity(pos) instanceof EnderChestBlockEntity enderChest) { BlockPos above = pos.above(); - if (level.getBlockState(above).isRedstoneConductor(level, above)) { // Paper - diff on change; make sure that EnderChest#isBlocked uses the same logic + // Lophine start - Carpet features + boolean canOpenForcibly = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeOpenContainerForcibly && player.isCreative(); + if (!canOpenForcibly && level.getBlockState(above).isRedstoneConductor(level, above)) { // Paper - diff on change; make sure that EnderChest#isBlocked uses the same logic + // Lophine end - Carpet features return InteractionResult.SUCCESS; } diff --git a/net/minecraft/world/level/block/FarmlandBlock.java b/net/minecraft/world/level/block/FarmlandBlock.java index ef55faf83e39c8dfd6bbe33c4943ed88bc473715..f91a8608ba4948217fce4a62affe1e4e6cfb7bf2 100644 --- a/net/minecraft/world/level/block/FarmlandBlock.java +++ b/net/minecraft/world/level/block/FarmlandBlock.java @@ -132,7 +132,11 @@ public class FarmlandBlock extends Block { return; } // CraftBukkit end - turnToDirt(entity, state, level, pos); + // Lophine start - Carpet features + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.farmlandTrampledDisabled) { + turnToDirt(entity, state, level, pos); + } + // Lophine end - Carpet features } // super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved up diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java index 1d68ebf02f4e83a69fc30f36e0b9f688799210c3..505c3b1a99394ec89ea0589e0cad1af44c48959a 100644 --- a/net/minecraft/world/level/block/ObserverBlock.java +++ b/net/minecraft/world/level/block/ObserverBlock.java @@ -89,6 +89,12 @@ public class ObserverBlock extends DirectionalBlock { } private void startSignal(final LevelReader level, final ScheduledTickAccess ticks, final BlockPos pos) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.observerNoDetection) { + return; + } + + // Lophine end - Carpet features if (!level.isClientSide() && !ticks.getBlockTicks().hasScheduledTick(pos, this)) { ticks.scheduleTick(pos, this, 2); } diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java index 1ccacb7ffa7e8b9c3fdd37910d3e8bded86a4d3a..239258ad543571a5213d1b06aa9e4e9f44261a14 100644 --- a/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -292,7 +292,10 @@ public class RedStoneWireBlock extends Block { * Note: Added 'source' argument so as to help determine direction of information flow */ private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, @Nullable Orientation orientation, boolean blockAdded) { - if (worldIn.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.EIGENCRAFT) { + // Lophine start - Carpet features + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.fastRedstoneDust + && worldIn.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.EIGENCRAFT) { + // Lophine end - Carpet features // since 24w33a the source pos is no longer given, but instead an Orientation parameter // when this is not null, it can be used to find the source pos, which the turbo uses // to find the direction of information flow @@ -367,7 +370,8 @@ public class RedStoneWireBlock extends Block { protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) { if (!oldState.is(state.getBlock()) && !level.isClientSide()) { // Paper start - optimize redstone - replace call to updatePowerStrength - if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.fastRedstoneDust + || level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { level.getWireHandler().onWireAdded(pos, state); // Alternate Current } else { this.updateSurroundingRedstone(level, pos, state, null, true); // Vanilla/Eigencraft @@ -392,7 +396,8 @@ public class RedStoneWireBlock extends Block { } // Paper start - optimize redstone - replace call to updatePowerStrength - if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.fastRedstoneDust + || level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { level.getWireHandler().onWireRemoved(pos, state); // Alternate Current } else { this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft @@ -412,7 +417,8 @@ public class RedStoneWireBlock extends Block { } // Paper start - optimize redstone - replace call to updatePowerStrength - if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.fastRedstoneDust + || level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { level.getWireHandler().onWireRemoved(pos, state); // Alternate Current } else { this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft @@ -444,7 +450,8 @@ public class RedStoneWireBlock extends Block { if (!level.isClientSide()) { // Paper start - optimize redstone (Alternate Current) // Alternate Current handles breaking of redstone wires in the WireHandler. - if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.fastRedstoneDust + || level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { level.getWireHandler().onWireUpdated(pos, state, orientation); } else // Paper end - optimize redstone (Alternate Current) diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java index a80535ebb7b4fcc3a6c7b84eb08e275461c7ae36..c470631eba2495e6363ea29aad7515d65dd46f4b 100644 --- a/net/minecraft/world/level/block/ShulkerBoxBlock.java +++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java @@ -76,9 +76,10 @@ public class ShulkerBoxBlock extends BaseEntityBlock { protected InteractionResult useWithoutItem( final BlockState state, final Level level, final BlockPos pos, final Player player, final BlockHitResult hitResult ) { + boolean canOpenForcibly = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeOpenContainerForcibly && player.isCreative(); // Lophine - Carpet features if (level instanceof ServerLevel serverLevel && level.getBlockEntity(pos) instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity - && canOpen(state, level, pos, shulkerBoxBlockEntity) // Paper - Fix InventoryOpenEvent cancellation - expand if for belows check + && (canOpen(state, level, pos, shulkerBoxBlockEntity) || canOpenForcibly) // Paper - Fix InventoryOpenEvent cancellation - expand if for belows check && player.openMenu(shulkerBoxBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation player.awardStat(Stats.OPEN_SHULKER_BOX); PiglinAi.angerNearbyPiglins(serverLevel, player, true); diff --git a/net/minecraft/world/level/block/TntBlock.java b/net/minecraft/world/level/block/TntBlock.java index c27fc92d6ff9dd7e07a61513601ef73ff16cf842..e5915893a06e332992c34b8ac511595534f48cdf 100644 --- a/net/minecraft/world/level/block/TntBlock.java +++ b/net/minecraft/world/level/block/TntBlock.java @@ -47,7 +47,10 @@ public class TntBlock extends Block { @Override protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) { if (!oldState.is(state.getBlock())) { - if (level.hasNeighborSignal(pos) && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent + // Lophine start - Carpet features + if (shouldPrimeFromRedstone(level, pos) + && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent + // Lophine end - Carpet features level.removeBlock(pos, false); } } @@ -57,7 +60,11 @@ public class TntBlock extends Block { protected void neighborChanged( final BlockState state, final Level level, final BlockPos pos, final Block block, final @Nullable Orientation orientation, final boolean movedByPiston ) { - if (level.hasNeighborSignal(pos) && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent + // Lophine start - Carpet features + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tntIgnoreRedstoneSignal + && level.hasNeighborSignal(pos) + && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent + // Lophine end - Carpet features level.removeBlock(pos, false); } } @@ -154,4 +161,12 @@ public class TntBlock extends Block { protected void createBlockStateDefinition(final StateDefinition.Builder builder) { builder.add(UNSTABLE); } + // Lophine start - Carpet features + + private static boolean shouldPrimeFromRedstone(final Level level, final BlockPos pos) { + return !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tntDoNotUpdate + && !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tntIgnoreRedstoneSignal + && level.hasNeighborSignal(pos); + } + // Lophine end - Carpet features } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java index 569f96a1b0b8a03b6a70775f4b7f58a66feed939..c23976cd72d7556ef96e04a7009031fc07b7a4fd 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -296,6 +296,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen private static boolean hopperPush(final Level level, final Container destination, final Direction direction, final HopperBlockEntity hopper) { io.papermc.paper.threadedregions.RegionizedWorldData worldData = level.getCurrentWorldData(); // Folia - region threading worldData.skipPushModeEventFire = worldData.skipHopperEvents; // Folia - region threading + // Lophine start - Carpet features + boolean noItemCost = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.hopperNoItemCost + && org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, hopper.getBlockPos().above()) != null; + // Lophine end - Carpet features boolean foundItem = false; for (int i = 0; i < hopper.getContainerSize(); ++i) { final ItemStack item = hopper.getItem(i); @@ -321,6 +325,15 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen final ItemStack remainingItem = addItem(hopper, destination, movedItem, direction); final int remainingItemCount = remainingItem.getCount(); if (remainingItemCount != movedItemCount) { + // Lophine start - Carpet features + if (noItemCost) { + origItemStack.setCount(originalItemCount); + hopper.setItem(i, origItemStack); + destination.setChanged(); + return true; + } + + // Lophine end - Carpet features origItemStack = origItemStack.copy(true); origItemStack.setCount(originalItemCount); if (!origItemStack.isEmpty()) { diff --git a/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/net/minecraft/world/level/block/piston/PistonBaseBlock.java index b4f5d462e4012451328210018c24de5a1d9e8c2e..e8f7944220d76d5c9111c6552e7904751aa26018 100644 --- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java @@ -387,7 +387,7 @@ public class PistonBaseBlock extends DirectionalBlock { for (int i = toPush.size() - 1; i >= 0; i--) { // Paper start - fix a variety of piston desync dupes - boolean allowDesync = io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPistonDuplication; + boolean allowDesync = !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.tntDupingFix; BlockPos oldPos = toPush.get(i); BlockPos pos = oldPos; BlockState blockState = allowDesync ? level.getBlockState(oldPos) : null; diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java index 972b953a579120c1c05f2dc9bfc2b408d6071d26..a60bb8af6b6aa356193befa9d7e9cdfc7cf38f39 100644 --- a/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java @@ -859,6 +859,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea } public Vec3 getOffset(final BlockPos pos) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.bambooModelNoOffset && (this.getBlock() == Blocks.BAMBOO || this.getBlock() == Blocks.BAMBOO_SAPLING)) { + return Vec3.ZERO; + } + + // Lophine end - Carpet features BlockBehaviour.OffsetFunction function = this.offsetFunction; return function != null ? function.evaluate(this.asState(), pos) : Vec3.ZERO; } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java index c3b32f9c4c2fa17bef629453e3315c12387f5a92..62e760dcf3f499822800e243103cdc27a25b8cbe 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java @@ -425,10 +425,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot boolean blockChanged = !oldState.is(newBlock); boolean movedByPiston = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0; boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0; - // Leaves start - behaviour 1.21.1- + boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates(); // Lophine - Carpet features// Leaves start - behaviour 1.21.1- if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) { if (blockChanged && oldState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(oldState)) { - if (!this.level.isClientSide() && sideEffects) { + if (!this.level.isClientSide() && sideEffects&& !skipInteractionUpdates) { BlockEntity blockEntity = this.level.getBlockEntity(pos); if (blockEntity != null) { blockEntity.preRemoveSideEffects(pos, oldState); @@ -440,7 +440,8 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot if ((blockChanged || newBlock instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel - && ((flags & Block.UPDATE_NEIGHBORS) != 0 || movedByPiston)) { + && !skipInteractionUpdates + && ((flags & Block.UPDATE_NEIGHBORS) != 0 || movedByPiston)) { oldState.affectNeighborsAfterRemoval(serverLevel, pos, movedByPiston); } } else { @@ -452,7 +453,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot return null; } - if (!this.level.isClientSide() && (flags & Block.UPDATE_SKIP_ON_PLACE) == 0 && (!this.level.getCurrentWorldData().captureBlockStates || newBlock instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. // Folia - region threading + if (!this.level.isClientSide() + && !skipInteractionUpdates + && (flags & Block.UPDATE_SKIP_ON_PLACE) == 0 + && (!this.level.getCurrentWorldData().captureBlockStates || newBlock instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. // Folia - region threading state.onPlace(this.level, pos, oldState, movedByPiston); } diff --git a/net/minecraft/world/level/dimension/end/DragonRespawnStage.java b/net/minecraft/world/level/dimension/end/DragonRespawnStage.java index 8d33e8888980f57d4f6d502b4f6912a5f56eff06..f90eb5768b1af9ca07bf6abdea7dbb2509ceb358 100644 --- a/net/minecraft/world/level/dimension/end/DragonRespawnStage.java +++ b/net/minecraft/world/level/dimension/end/DragonRespawnStage.java @@ -55,16 +55,19 @@ public enum DragonRespawnStage implements StringRepresentable { respawnCrystal.setBeamTarget(new BlockPos(spike.getCenterX(), spike.getHeight() + 1, spike.getCenterZ())); } } else { - int radius = 10; + // Lophine start - Carpet features + if (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.preventEndSpikeRespawn) { + for (BlockPos pos : BlockPos.betweenClosed( + new BlockPos(spike.getCenterX() - 10, spike.getHeight() - 10, spike.getCenterZ() - 10), + new BlockPos(spike.getCenterX() + 10, spike.getHeight() + 10, spike.getCenterZ() + 10) + )) { + level.removeBlock(pos, false); + } + // Lophine end - Carpet features - for (BlockPos pos : BlockPos.betweenClosed( - new BlockPos(spike.getCenterX() - 10, spike.getHeight() - 10, spike.getCenterZ() - 10), - new BlockPos(spike.getCenterX() + 10, spike.getHeight() + 10, spike.getCenterZ() + 10) - )) { - level.removeBlock(pos, false); + level.explode(null, spike.getCenterX() + 0.5F, spike.getHeight(), spike.getCenterZ() + 0.5F, 5.0F, Level.ExplosionInteraction.BLOCK); // Lophine - Carpet features } - level.explode(null, spike.getCenterX() + 0.5F, spike.getHeight(), spike.getCenterZ() + 0.5F, 5.0F, Level.ExplosionInteraction.BLOCK); EndSpikeConfiguration configuration = new EndSpikeConfiguration(true, ImmutableList.of(spike), new BlockPos(0, 128, 0)); Feature.END_SPIKE .place( diff --git a/net/minecraft/world/level/levelgen/feature/EndSpikeFeature.java b/net/minecraft/world/level/levelgen/feature/EndSpikeFeature.java index f18523cc88dad77b4c7f2174f7db6ca13a199c7c..2e09964a0b3ae755d4b79cfdfe2ae52bd14f37bb 100644 --- a/net/minecraft/world/level/levelgen/feature/EndSpikeFeature.java +++ b/net/minecraft/world/level/levelgen/feature/EndSpikeFeature.java @@ -68,6 +68,12 @@ public class EndSpikeFeature extends Feature { private void placeSpike( final ServerLevelAccessor level, final RandomSource random, final EndSpikeConfiguration config, final EndSpikeFeature.EndSpike spike ) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.preventEndSpikeRespawn && config.getCrystalBeamTarget() != null) { + return; + } + + // Lophine end - Carpet features int radius = spike.getRadius(); for (BlockPos pos : BlockPos.betweenClosed( diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java index 90145a3ea384b568897ee665b80b24cccba1b6c5..4556860c8a8c728e8c64b6b3081fdc7f8608df98 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/net/minecraft/world/level/redstone/NeighborUpdater.java @@ -42,6 +42,12 @@ public interface NeighborUpdater { final @Block.UpdateFlags int updateFlags, final int updateLimit ) { + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.totallyNoBlockUpdate) { + return; + } + + // Lophine end - Carpet features BlockState currentState = level.getBlockState(pos); if ((updateFlags & Block.UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE) == 0 || !currentState.is(Blocks.REDSTONE_WIRE)) { try { @@ -72,6 +78,12 @@ public interface NeighborUpdater { static void executeUpdate(Level level, BlockState state, BlockPos pos, Block changedBlock, @Nullable Orientation orientation, boolean movedByPiston, BlockPos sourcePos) { // Paper end - Add source block to BlockPhysicsEvent + // Lophine start - Carpet features + if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.totallyNoBlockUpdate) { + return; + } + + // Lophine end - Carpet features try { // CraftBukkit start org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), state.asBlockData(), org.bukkit.craftbukkit.block.CraftBlock.at(level, sourcePos)); // Paper - Add source block to BlockPhysicsEvent