Compare commits

...
7 Commits
Author SHA1 Message Date
NotAlexNoyle 026cc872ed Exclude CODEOWNERS from language statistics 2026-11-01 10:10:01 -05:00
NotAlexNoyle 77b7b8a9a6 Add CODEOWNERS (one staff approval) 2026-11-01 10:10:01 -05:00
Tamion 6ea42025a4 Send all attributes on respawn (#12274) 2025-03-13 12:41:03 +01:00
Nassim Jahnke 310f52293b Add unsupported config option and internal API to simplify remote item matching
This is important for 1.21.5 servers/clients and non-Vanilla clients that may not be able to match 1.21.5 data hashes anymore
2025-03-13 12:32:50 +01:00
Nassim Jahnke c37b890c8b More deferred requireNonNull message creation 2025-03-13 12:27:12 +01:00
Pedro f0388e2f38 Call EntityPushedByEntityAttackEvent for Mace AoE (#12257) 2025-03-12 11:13:47 +01:00
Tamion 102c8bbc54 Add config for updating equipment on player actions (#12275) 2025-03-12 11:09:27 +01:00
18 changed files with 125 additions and 38 deletions

No files matched your search

+1
View File
@@ -5,3 +5,4 @@ gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -0,0 +1,3 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
@@ -83,14 +83,12 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
* @see #NamespacedKey(Plugin, String)
*/
public NamespacedKey(@NotNull String namespace, @NotNull String key) {
Preconditions.checkArgument(namespace != null && isValidNamespace(namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
Preconditions.checkArgument(key != null && isValidKey(key), "Invalid key. Must be [a-z0-9/._-]: %s", key);
Preconditions.checkArgument(namespace != null, "Namespace cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
this.namespace = namespace;
this.key = key;
String string = toString();
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
this.validate();
}
/**
@@ -108,16 +106,17 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
public NamespacedKey(@NotNull Plugin plugin, @NotNull String key) {
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
this.key = key.toLowerCase(Locale.ROOT);
// Check validity after normalization
this.validate();
}
private void validate() {
Preconditions.checkArgument(this.namespace.length() + 1 + this.key.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters");
Preconditions.checkArgument(isValidNamespace(this.namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
String string = toString();
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
}
@NotNull
@@ -64,7 +64,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
@SuppressWarnings("removal")
@Deprecated(forRemoval = true, since = "1.21.4")
private static <A extends Keyed> Registry<A> legacyRegistryFor(final Class<A> clazz) {
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), () -> "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
}
/**
@@ -57,7 +57,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
*/
@org.jetbrains.annotations.Contract(value = "_, _ -> new", pure = true)
public static @NotNull ItemStack of(final @NotNull Material type, final int amount) {
Preconditions.checkArgument(type.asItemType() != null, type + " isn't an item");
Preconditions.checkArgument(type.asItemType() != null, "%s isn't an item", type);
Preconditions.checkArgument(amount > 0, "amount must be greater than 0");
return java.util.Objects.requireNonNull(type.asItemType(), type + " is not an item").createItemStack(amount); // Paper - delegate
}
@@ -23751,7 +23751,7 @@ index 841a41485af62470d833aba578069b19a0bd1e8d..409c1134327bfcc338c3ac5e658a83cc
// CraftBukkit start
public boolean isDebugging() {
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index f8c81d795b19e73d56d6e0196c75e441ab4c2bef..97a294d2f5c1ddf0af7ffec3e1425eb329c5751b 100644
index ac7bc193f7ea63cbbba73df49f54a17ef7cdec40..d2db6e3a4af13984b0a790fb38e83c253914a973 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -433,7 +433,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -26735,7 +26735,7 @@ index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7d
if (!passengers.equals(this.lastPassengers)) {
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 400b56657414177cd76a7b94c426dc7c886aa957..a275b17d0852d9d9bc850614713244e580ae81f1 100644
index d1f235ebd835f58cf0c703c3a64d29825d98e183..080091efc19bc768bb9a660f366c42e831225505 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -170,7 +170,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
@@ -27976,10 +27976,10 @@ index 4eb040006f5d41b47e5ac9df5d9f19c4315d6343..7fa41dea184b01891f45d8e404bc1cba
this.generatingStep = generatingStep;
this.cache = cache;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 5d88b2790710a885957ffcffc02fb99c917123c5..7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4 100644
index 7eebb494e38b57e81b4f92f0a96d3a4c610d86df..065f4c810439dde464529b54ae300ecfcb1c2c31 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1312,7 +1312,7 @@ public abstract class PlayerList {
@@ -1317,7 +1317,7 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
@@ -27988,7 +27988,7 @@ index 5d88b2790710a885957ffcffc02fb99c917123c5..7d1d4abfb04829d8c4722e326c6c6b8f
for (ServerLevel serverLevel : this.server.getAllLevels()) {
if (serverLevel != null) {
@@ -1323,7 +1323,7 @@ public abstract class PlayerList {
@@ -1328,7 +1328,7 @@ public abstract class PlayerList {
public void setSimulationDistance(int simulationDistance) {
this.simulationDistance = simulationDistance;
@@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 994791a83ca6712db3e74ca9aba4bfcd95a0ec6d..1b54cf07616a10d93e9336dbd299ba5f09678a28 100644
index 9b3b770f6986dd132da78fdc3626d334166ec52a..b2b61203438bb1fad1ee807729781718d2467155 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -10,7 +10,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -258,6 +_,13 @@
@@ -258,6 +_,20 @@
}
}
@@ -20,6 +20,13 @@
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ }
+ // Paper end - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ @Override
+ public ServerPlayer player() {
+ return ServerPlayer.this;
+ }
+ // Paper end - add flag to simplify remote matching logic
+
@Override
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
@@ -577,7 +577,7 @@
this.player.connection.send(new ClientboundSetHeldSlotPacket(inventory.selected));
this.player.inventoryMenu.broadcastChanges();
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
}
@@ -1103,7 +1103,7 @@
+ }
+ // CraftBukkit end
this.player.stopUsingItem();
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
return;
@@ -1125,21 +1125,21 @@
+ }
+ // CraftBukkit end
this.player.drop(false);
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
return;
case DROP_ALL_ITEMS:
if (!this.player.isSpectator()) {
this.player.drop(true);
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
return;
case RELEASE_USE_ITEM:
- this.player.releaseUsingItem();
+ if (this.player.getUseItem() == this.player.getItemInHand(this.player.getUsedItemHand())) this.player.releaseUsingItem(); // Paper - validate use item before processing release
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
return;
case START_DESTROY_BLOCK:
case ABORT_DESTROY_BLOCK:
@@ -1172,7 +1172,7 @@
+ }
+ }
+ // Paper end - Send block entities after destroy prediction
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
return;
default:
throw new IllegalArgumentException("Invalid player action");
@@ -1247,7 +1247,7 @@
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos));
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction)));
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
} else {
LOGGER.warn(
"Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.",
@@ -1397,7 +1397,7 @@
this.player.getInventory().selected = packet.getSlot();
this.player.resetLastActionTime();
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
} else {
LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
+ this.disconnect(Component.literal("Invalid hotbar selection (Hacking?)"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause
@@ -2004,7 +2004,7 @@
+ });
+ }
+ // Paper end - PlayerUseUnknownEntityEvent
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
}
@@ -2410,7 +2410,7 @@
} else {
this.player.containerMenu.broadcastChanges();
}
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
}
}
@@ -2487,7 +2487,7 @@
if (flag) {
this.player.containerMenu.broadcastChanges();
}
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
}
}
}
@@ -2536,7 +2536,7 @@
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
this.player.inventoryMenu.broadcastChanges();
+ this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
} else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) {
this.dropSpamThrottler.increment();
@@ -931,13 +931,18 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -671,8 +_,16 @@
@@ -671,8 +_,21 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
- player.resetSentInfo();
+ // entityplayer.resetSentInfo();
+ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
+ // Paper start - send all attributes
+ // needs to be done because the ServerPlayer instance is being reused on respawn instead of getting replaced like on vanilla
+ java.util.Collection<net.minecraft.world.entity.ai.attributes.AttributeInstance> syncableAttributes = player.getAttributes().getSyncableAttributes();
+ player.getBukkitEntity().injectScaledMaxHealth(syncableAttributes, true);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket(player.getId(), syncableAttributes));
+ // Paper end - send all attributes
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
+ // CraftBukkit start - from GameRules
@@ -72,6 +72,41 @@
}
}
}
@@ -243,7 +_,7 @@
private void synchronizeSlotToRemote(int slotIndex, ItemStack stack, Supplier<ItemStack> supplier) {
if (!this.suppressRemoteUpdates) {
ItemStack itemStack = this.remoteSlots.get(slotIndex);
- if (!ItemStack.matches(itemStack, stack)) {
+ if (!this.matchesRemote(itemStack, stack)) { // Paper - add flag to simplify remote matching logic
ItemStack itemStack1 = supplier.get();
this.remoteSlots.set(slotIndex, itemStack1);
if (this.synchronizer != null) {
@@ -267,7 +_,7 @@
private void synchronizeCarriedToRemote() {
if (!this.suppressRemoteUpdates) {
- if (!ItemStack.matches(this.getCarried(), this.remoteCarried)) {
+ if (!this.matchesRemote(this.getCarried(), this.remoteCarried)) { // Paper - add flag to simplify remote matching logic
this.remoteCarried = this.getCarried().copy();
if (this.synchronizer != null) {
this.synchronizer.sendCarriedChange(this, this.remoteCarried);
@@ -276,6 +_,16 @@
}
}
+ // Paper start - add flag to simplify remote matching logic
+ private boolean matchesRemote(final ItemStack stack, final ItemStack other) {
+ if (this.synchronizer != null && this.synchronizer.player() != null && this.synchronizer.player().getBukkitEntity().simplifyContainerDesyncCheck()) {
+ // Only check the item type and count
+ return stack == other || (stack.getCount() == other.getCount() && ItemStack.isSameItem(stack, other));
+ }
+ return ItemStack.matches(stack, other);
+ }
+ // Paper end - add flag to simplify remote matching logic
+
public void setRemoteSlot(int slot, ItemStack stack) {
this.remoteSlots.set(slot, stack.copy());
}
@@ -343,6 +_,7 @@
this.resetQuickCraft();
}
@@ -1,9 +1,15 @@
--- a/net/minecraft/world/inventory/ContainerSynchronizer.java
+++ b/net/minecraft/world/inventory/ContainerSynchronizer.java
@@ -11,4 +_,6 @@
@@ -11,4 +_,12 @@
void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack);
void sendDataChange(AbstractContainerMenu container, int id, int value);
+
+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ default net.minecraft.server.level.@org.jspecify.annotations.Nullable ServerPlayer player() {
+ return null;
+ }
+ // Paper end - add flag to simplify remote matching logic
}
@@ -15,3 +15,12 @@
ServerLevel serverLevel = (ServerLevel)attacker.level();
attacker.setDeltaMovement(attacker.getDeltaMovement().with(Direction.Axis.Y, 0.01F));
if (attacker instanceof ServerPlayer serverPlayer) {
@@ -139,7 +_,7 @@
double knockbackPower = getKnockbackPower(attacker, livingEntity, vec3);
Vec3 vec31 = vec3.normalize().scale(knockbackPower);
if (knockbackPower > 0.0) {
- livingEntity.push(vec31.x, 0.7F, vec31.z);
+ livingEntity.push(vec31.x, 0.7F, vec31.z, attacker); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
if (livingEntity instanceof ServerPlayer serverPlayer) {
serverPlayer.connection.send(new ClientboundSetEntityMotionPacket(serverPlayer));
}
@@ -30,6 +30,6 @@ public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameev
@Override
public @NotNull Set<GameEvent> getValues() {
return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), () -> nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
}
}
@@ -184,6 +184,10 @@ public class GlobalConfiguration extends ConfigurationPart {
public boolean skipVanillaDamageTickWhenShieldBlocked = false;
@Comment("This setting controls what compression format is used for region files.")
public CompressionFormat compressionFormat = CompressionFormat.ZLIB;
@Comment("This setting controls if equipment should be updated when handling certain player actions.")
public boolean updateEquipmentOnPlayerActions = true;
@Comment("Only checks an item's amount and type instead of its full data during inventory desync checks.")
public boolean simplifyRemoteItemMatching = false;
public enum CompressionFormat {
GZIP,
@@ -153,12 +153,12 @@ public final class PaperRegistries {
@SuppressWarnings("unchecked")
public static <M, T> RegistryKey<T> registryFromNms(final ResourceKey<? extends Registry<M>> registryResourceKey) {
return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), registryResourceKey + " doesn't have an api RegistryKey").apiKey();
return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), () -> registryResourceKey + " doesn't have an api RegistryKey").apiKey();
}
@SuppressWarnings("unchecked")
public static <M, T> ResourceKey<? extends Registry<M>> registryToNms(final RegistryKey<T> registryKey) {
return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), registryKey + " doesn't have an mc registry ResourceKey").mcKey();
return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), () -> registryKey + " doesn't have an mc registry ResourceKey").mcKey();
}
public static <M, T> TypedKey<T> fromNms(final ResourceKey<M> resourceKey) {
@@ -60,7 +60,7 @@ public sealed interface RegistryEntryMeta<M, A extends Keyed> permits RegistryEn
) implements ServerSide<M, A> { // TODO remove Keyed
public Craft {
Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), classToPreload + " should not be in the net.minecraft package as the class-to-preload");
Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), "%s should not be in the net.minecraft package as the class-to-preload", classToPreload);
}
}
@@ -34,7 +34,7 @@ public final class RegistryEventMap {
@SuppressWarnings("unchecked")
public <T, E extends LifecycleEvent> LifecycleEventType<BootstrapContext, E, ?> getEventType(final RegistryKey<T> registryKey) {
return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.eventTypes.get(registryKey), "No hook for " + registryKey);
return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.eventTypes.get(registryKey), () -> "No hook for " + registryKey);
}
public boolean hasHandlers(final RegistryKey<?> registryKey) {
@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Pair;
import io.netty.buffer.Unpooled;
import io.papermc.paper.FeatureHooks;
import io.papermc.paper.configuration.GlobalConfiguration;
import io.papermc.paper.entity.LookAnchor;
import io.papermc.paper.entity.PaperPlayerGiveResult;
import io.papermc.paper.entity.PlayerGiveResult;
@@ -225,6 +226,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private BorderChangeListener clientWorldBorderListener = this.createWorldBorderListener();
public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; // Paper - more resource pack API
private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit
private boolean simplifyContainerDesyncCheck = GlobalConfiguration.get().unsupportedSettings.simplifyRemoteItemMatching;
private long lastSaveTime; // Paper - getLastPlayed replacement API
public CraftPlayer(CraftServer server, ServerPlayer entity) {
@@ -3606,4 +3608,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void setDeathScreenScore(final int score) {
getHandle().setScore(score);
}
/**
* Returns whether container desync checks should skip the full item comparison of remote carried and changed slots
* and should instead only check their type and amount.
* <p>
* This is useful if the client is not able to produce the same item stack (or as of 1.21.5, its data hashes) as the server.
*
* @return whether to simplify container desync checks
*/
public boolean simplifyContainerDesyncCheck() {
return simplifyContainerDesyncCheck;
}
public void setSimplifyContainerDesyncCheck(final boolean simplifyContainerDesyncCheck) {
this.simplifyContainerDesyncCheck = simplifyContainerDesyncCheck;
}
}