3
0
Mirror von https://github.com/PaperMC/Paper.git synchronisiert 2024-11-15 04:20:04 +01:00
Paper/patches/server/1062-Manually-reset-attribute-map-on-restoring-player-ins.patch
Bjarne Koll ef823cbc25
Do not remove current modifiers
Do not break API modifier expectations of lasting through death.
2024-11-10 01:05:33 +01:00

106 Zeilen
6.3 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 4 Nov 2024 20:23:02 +0000
Subject: [PATCH] Manually reset attribute map on restoring player instance
Spigots reuse of the entity instances causes the server to try to copy
a players existing attributes back onto itself, which causes an error.
We'll manually clear the applicable attribute modifiers, but, in the long run,
we should just revert out of the broken behavior of trying to reuse ServerPlayer
instances.
== AT ==
protected net.minecraft.world.entity.LivingEntity lastHandItemStacks
protected net.minecraft.world.entity.LivingEntity lastArmorItemStacks
protected net.minecraft.world.entity.LivingEntity lastBodyItemStack
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index cffbd3300967e5d80b5973b35a76235bb2aa1b73..88de7566297b0be7d5f7d8868f76a0b5ac42dfcf 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -2285,8 +2285,11 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
this.gameMode.setGameModeForPlayer(oldPlayer.gameMode.getGameModeForPlayer(), oldPlayer.gameMode.getPreviousGameModeForPlayer());
this.onUpdateAbilities();
if (alive) {
- this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
- this.getAttributes().assignPermanentModifiers(oldPlayer.getAttributes());
+ // Paper start - deal with upstream stupidity around attribute modifiers and recycling entity instances.
+ // this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
+ // this.getAttributes().assignPermanentModifiers(oldPlayer.getAttributes());
+ // this.getAttributes().removeAllTransientModifiers(); Currently not implemented as it would loose API added attribute modifiers, awaiting addition of new API
+ // Paper end
this.setHealth(oldPlayer.getHealth());
this.foodData = oldPlayer.foodData;
Iterator iterator = oldPlayer.getActiveEffects().iterator();
@@ -2304,7 +2307,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
this.setScore(oldPlayer.getScore());
this.portalProcess = oldPlayer.portalProcess;
} else {
- this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
+ // Paper start - deal with upstream stupidity around attribute modifiers and recycling entity instances.
+ // this.getAttributes().assignBaseValues(oldPlayer.getAttributes());
+ // this.getAttributes().removeAllModifiers(); // Currently not implemented as it would loose API added attribute modifiers, awaiting addition of new API
+ // Paper end
// this.setHealth(this.getMaxHealth()); // CraftBukkit
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || oldPlayer.isSpectator()) {
this.getInventory().replaceWith(oldPlayer.getInventory());
@@ -2328,6 +2334,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
this.setShoulderEntityLeft(oldPlayer.getShoulderEntityLeft());
this.setShoulderEntityRight(oldPlayer.getShoulderEntityRight());
this.setLastDeathLocation(oldPlayer.getLastDeathLocation());
+ // Paper start - deal with upstream stupidity around attribute modifiers and recycling entity instances.
+ /*
+ Currently not implemented as modifiers are *not* actually removed, deviating from vanilla.
+ this.lastArmorItemStacks.clear();
+ this.lastHandItemStacks.clear();
+ this.lastBodyItemStack = ItemStack.EMPTY;
+ this.skipNextCollectEquipmentEvent = false; // Implement
+ */
+ // Paper end - deal with upstream stupidity around attribute modifiers and recycling entity instances.
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 1a93006d252ebfe5571904d8be1ceb62079db35a..5c40dfbb920cc3d83c27657784f3e2f5f5f9de5d 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3369,6 +3369,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@Nullable
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
+ // Paper start - deal with upstream stupidity around attribute modifiers and recycling entity instances.
+ return collectEquipmentChanges(true);
+ }
+ protected Map<EquipmentSlot, ItemStack> collectEquipmentChanges(boolean fireEvent) {
+ // Paper end - deal with upstream stupidity around attribute modifiers and recycling entity instances.
Map<EquipmentSlot, ItemStack> map = null;
Iterator iterator = EquipmentSlot.VALUES.iterator();
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index 94d04a20f97405e02d7cccaabadc7a7e86e336f7..684392007e6fd1f0a328bc5f59929fcabe1f1a6e 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -156,5 +156,21 @@ public class AttributeMap {
attributes.put(attributeBase, attributeModifiable);
}
// Paper - end - living entity allow attribute registration
+ // Paper start - deal with upstream stupidity around attribute modifiers and recycling entity instances.
+ public void removeAllModifiers() {
+ this.attributes.values().forEach(AttributeInstance::removeModifiers);
+ }
+
+ public void removeAllTransientModifiers() {
+ this.attributes.values().forEach(attributeInstance -> {
+ final Set<AttributeModifier> permanentModifiers = attributeInstance.getPermanentModifiers();
+ attributeInstance.getModifiers().forEach(modifier -> {
+ if (!permanentModifiers.contains(modifier)) {
+ attributeInstance.removeModifier(modifier.id());
+ }
+ });
+ });
+ }
+ // Paper end
}