1234 lines
78 KiB
Diff
1234 lines
78 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Bacteriawa <A3167717663@hotmail.com>
|
|
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<BlockInWorld> {
|
|
}
|
|
|
|
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<CommandSourceStack> 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<RegistryLayer> 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 2ada9d75ee70754a3992a32660d125c4328ff264..91eb538fe3f7134573f3974728ffc527cae5bfae 100644
|
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -2078,7 +2078,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;
|
|
@@ -2181,7 +2189,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);
|
|
}
|
|
@@ -2286,7 +2296,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);
|
|
}
|
|
@@ -2294,6 +2307,16 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
}
|
|
|
|
+ // Lophine start - Carpet features
|
|
+ private <T> T runInteractionWithConfiguredUpdates(final java.util.function.Supplier<T> 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());
|
|
@@ -2674,6 +2697,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 {
|
|
@@ -2686,6 +2713,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) {
|
|
@@ -3632,8 +3662,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<EnchantedItemInUse> 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<MendingCandidate> 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<RecipeMap> imp
|
|
forSingleInput(RecipeType.CAMPFIRE_COOKING)
|
|
);
|
|
private static final FileToIdConverter RECIPE_LISTER = FileToIdConverter.registry(Registries.RECIPE);
|
|
+ // Lophine start - Carpet features
|
|
+ private static final ResourceKey<Recipe<?>> BETTER_CRAFTABLE_BONE_BLOCK_RECIPE = compatRecipeKey("better_craftable_bone_block");
|
|
+ private static final ResourceKey<Recipe<?>> BETTER_CRAFTABLE_DISPENSER_SHAPED_RECIPE = compatRecipeKey("better_craftable_dispenser_shaped");
|
|
+ private static final ResourceKey<Recipe<?>> 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<ResourceKey<RecipePropertySet>, RecipePropertySet> propertySets = Map.of();
|
|
@@ -83,10 +88,75 @@ public class RecipeManager extends SimplePreparableReloadListener<RecipeMap> 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<Recipe<?>> 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 bfc8e50a9e0d1ec13092cdd4bee0efba94a24da7..9691985eff543ad71174c2be3033ed7901390413 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<MobSpawnSettings.SpawnerData> 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<BlockPos> 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<BlockPos> 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<ChestBlockEntity> 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<EnderChestBlockEntity> 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<Block, BlockState> 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<EndSpikeConfiguration> {
|
|
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
|