diff options
author | Bjarne Koll <[email protected]> | 2024-09-19 16:36:07 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2024-09-19 16:36:07 +0200 |
commit | c5a10665b8b80af650500b9263036f778f06d500 (patch) | |
tree | fedc133f0dbc101067951e1fccd9d577c312fdb8 /patches/server/0968-Fix-equipment-slot-and-group-API.patch | |
parent | 5c829557332f21b34bc81e6ad1a73e511faef8f6 (diff) | |
download | Paper-c5a10665b8b80af650500b9263036f778f06d500.tar.gz Paper-c5a10665b8b80af650500b9263036f778f06d500.zip |
Remove wall-time / unused skip tick protection (#11412)
Spigot still maintains some partial implementation of "tick skipping", a
practice in which the MinecraftServer.currentTick field is updated not
by an increment of one per actual tick, but instead set to
System.currentTimeMillis() / 50. This behaviour means that the tracked
tick may "skip" a tick value in case a previous tick took more than the
expected 50ms.
To compensate for this in important paths, spigot/craftbukkit
implements "wall-time". Instead of incrementing/decrementing ticks on
block entities/entities by one for each call to their tick() method,
they instead increment/decrement important values, like
an ItemEntity's age or pickupDelay, by the difference of
`currentTick - lastTick`, where `lastTick` is the value of
`currentTick` during the last tick() call.
These "fixes" however do not play nicely with minecraft's simulation
distance as entities/block entities implementing the above behaviour
would "catch up" their values when moving from a non-ticking chunk to a
ticking one as their `lastTick` value remains stuck on the last tick in
a ticking chunk and hence lead to a large "catch up" once ticked again.
Paper completely removes the "tick skipping" behaviour (See patch
"Further-improve-server-tick-loop"), making the above precautions
completely unnecessary, which also rids paper of the previous described
incompatibility with non-ticking chunks.
Diffstat (limited to 'patches/server/0968-Fix-equipment-slot-and-group-API.patch')
-rw-r--r-- | patches/server/0968-Fix-equipment-slot-and-group-API.patch | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/patches/server/0968-Fix-equipment-slot-and-group-API.patch b/patches/server/0968-Fix-equipment-slot-and-group-API.patch new file mode 100644 index 0000000000..e84bebe105 --- /dev/null +++ b/patches/server/0968-Fix-equipment-slot-and-group-API.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +Date: Wed, 22 May 2024 10:01:19 -0700 +Subject: [PATCH] Fix equipment slot and group API + +Adds the following: +- Add test for EquipmentSlotGroup +- Expose LivingEntity#canUseSlot + +Co-authored-by: SoSeDiK <[email protected]> + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 6c44aaef8f09b2a10183dba751557ac5c6233a87..a54cf98661cc678277855f21735e98fafd018ded 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1187,4 +1187,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + this.getHandle().setYBodyRot(bodyYaw); + } + // Paper end - body yaw API ++ ++ // Paper start - Expose canUseSlot ++ @Override ++ public boolean canUseEquipmentSlot(org.bukkit.inventory.EquipmentSlot slot) { ++ return this.getHandle().canUseSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ } ++ // Paper end - Expose canUseSlot + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +index 9d74577af071954e1e37201a96368c1360076209..eafa54c870c3e2aef30c3f9f96f516607a7cae24 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +@@ -135,6 +135,10 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + case HEAD: + this.setHelmet(item); + break; ++ // Paper start ++ case BODY: ++ throw new IllegalArgumentException("BODY is not valid for players!"); ++ // Paper end + default: + throw new IllegalArgumentException("Not implemented. This is a bug"); + } +@@ -162,6 +166,10 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i + return java.util.Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull + case HEAD: + return java.util.Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull ++ // Paper start ++ case BODY: ++ throw new IllegalArgumentException("BODY is not valid for players!"); ++ // Paper end + default: + throw new IllegalArgumentException("Not implemented. This is a bug"); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +index beeed762e5ba49c317c5f214af17c44174b0c943..042bfdd14c9ff4cc8ed3421f73565f0f03b11bcb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +@@ -1448,7 +1448,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components + SetMultimap<Attribute, AttributeModifier> result = LinkedHashMultimap.create(); + for (Map.Entry<Attribute, AttributeModifier> entry : this.attributeModifiers.entries()) { +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { ++ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group + result.put(entry.getKey(), entry.getValue()); + } + } +@@ -1522,9 +1522,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + + while (iter.hasNext()) { + Map.Entry<Attribute, AttributeModifier> entry = iter.next(); +- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - +- // set slot are active in any slot. +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { ++ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group + iter.remove(); + ++removed; + } +diff --git a/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee0bfe4edb134d7ea3a3b97f5102a7f3122c3b99 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.inventory.item; ++ ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.world.entity.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.inventory.EquipmentSlotGroup; ++import org.junit.jupiter.params.ParameterizedTest; ++import org.junit.jupiter.params.provider.EnumSource; ++import org.junit.jupiter.params.provider.MethodSource; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; ++import static org.junit.jupiter.api.Assertions.assertNotNull; ++ ++class EquipmentSlotGroupTest { ++ ++ static List<EquipmentSlotGroup> apiValues() throws ReflectiveOperationException { ++ final List<EquipmentSlotGroup> apiValues = new ArrayList<>(); ++ for (final Field field : EquipmentSlotGroup.class.getDeclaredFields()) { ++ if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || !field.getType().equals(EquipmentSlotGroup.class)) { ++ continue; ++ } ++ apiValues.add((EquipmentSlotGroup) field.get(null)); ++ } ++ if (apiValues.isEmpty()) { ++ throw new RuntimeException("Didn't find any api " + EquipmentSlotGroup.class.getSimpleName()); ++ } ++ return apiValues; ++ } ++ ++ @ParameterizedTest ++ @MethodSource("apiValues") ++ void testBukkitToNms(final EquipmentSlotGroup slotGroup) { ++ final net.minecraft.world.entity.EquipmentSlotGroup nmsGroup = CraftEquipmentSlot.getNMSGroup(slotGroup); ++ assertNotNull(nmsGroup, "No nms slot group found for " + slotGroup); ++ assertEquals(nmsGroup.getSerializedName(), slotGroup.toString(), "slot group name mismatch"); ++ for (final EquipmentSlot slot : EquipmentSlot.values()) { ++ assertEquals(nmsGroup.test(slot), slotGroup.test(CraftEquipmentSlot.getSlot(slot))); ++ } ++ } ++ ++ @ParameterizedTest ++ @EnumSource(net.minecraft.world.entity.EquipmentSlotGroup.class) ++ void testNmsToBukkit(final net.minecraft.world.entity.EquipmentSlotGroup slotGroup) { ++ final EquipmentSlotGroup apiGroup = CraftEquipmentSlot.getSlot(slotGroup); ++ assertNotNull(apiGroup, "No api slot group found for " + slotGroup); ++ assertEquals(apiGroup.toString(), slotGroup.getSerializedName(), "slot group name mismatch"); ++ } ++} |