-
-
Notifications
You must be signed in to change notification settings - Fork 63
Lithium Equipment Tracking #736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MC-XiaoHei
wants to merge
4
commits into
master
Choose a base branch
from
dev/equipment-tracking
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
267 changes: 267 additions & 0 deletions
267
leaves-server/minecraft-patches/features/0140-Lithium-Equipment-Tracking.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: MC_XiaoHei <xor7xiaohei@gmail.com> | ||
Date: Tue, 9 Nov 2077 00:00:00 +0800 | ||
Subject: [PATCH] Lithium Equipment Tracking | ||
|
||
Origin patch author: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> | ||
Origin patch link: https://github.com/Winds-Studio/Leaf/blob/ver/1.21.8/leaf-server/minecraft-patches/features/0268-Lithium-equipment-tracking.patch | ||
|
||
Should have special treatment to ArmorStand, since Paper introduced the configurable | ||
ArmorStand no-tick, and still gives it ability to update equipment changes. | ||
Thus added a bypass condition in LivingEntity#collectEquipmentChanges, always send | ||
ArmorStand equipment changes even if the ArmorStand is no-tick | ||
|
||
This patch is based on the following mixins: | ||
* "net/caffeinemc/mods/lithium/mixin/util/item_component_and_count_tracking/PatchedDataComponentMapMixin.java" | ||
* "net/caffeinemc/mods/lithium/mixin/util/item_component_and_count_tracking/ItemStackMixin.java" | ||
* "net/caffeinemc/mods/lithium/mixin/entity/equipment_tracking/enchantment_ticking/LivingEntityMixin.java" | ||
* "net/caffeinemc/mods/lithium/mixin/entity/equipment_tracking/equipment_changes/LivingEntityMixin.java" | ||
* "net/caffeinemc/mods/lithium/mixin/entity/equipment_tracking/EntityEquipmentMixin.java" | ||
* "net/caffeinemc/mods/lithium/common/util/change_tracking/ChangePublisher.java" | ||
* "net/caffeinemc/mods/lithium/common/util/change_tracking/ChangeSubscriber.java" | ||
By: 2No2Name <2No2Name@web.de> | ||
As part of: Lithium (https://github.com/CaffeineMC/lithium) | ||
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html) | ||
|
||
diff --git a/net/minecraft/world/entity/EntityEquipment.java b/net/minecraft/world/entity/EntityEquipment.java | ||
index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e09906e343 100644 | ||
--- a/net/minecraft/world/entity/EntityEquipment.java | ||
+++ b/net/minecraft/world/entity/EntityEquipment.java | ||
@@ -7,7 +7,7 @@ import java.util.Objects; | ||
import java.util.Map.Entry; | ||
import net.minecraft.world.item.ItemStack; | ||
|
||
-public class EntityEquipment { | ||
+public class EntityEquipment implements org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber.CountChangeSubscriber<ItemStack> { // Leaves - Lithium - equipment tracking | ||
public static final Codec<EntityEquipment> CODEC = Codec.unboundedMap(EquipmentSlot.CODEC, ItemStack.CODEC).xmap(map -> { | ||
EnumMap<EquipmentSlot, ItemStack> map1 = new EnumMap<>(EquipmentSlot.class); | ||
map1.putAll((Map<? extends EquipmentSlot, ? extends ItemStack>)map); | ||
@@ -18,6 +18,11 @@ public class EntityEquipment { | ||
return map; | ||
}); | ||
private final EnumMap<EquipmentSlot, ItemStack> items; | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ boolean shouldTickEnchantments = false; | ||
+ ItemStack recheckEnchantmentForStack = null; | ||
+ boolean hasUnsentEquipmentChanges = true; | ||
+ // Leaves end - Lithium - equipment tracking | ||
|
||
private EntityEquipment(EnumMap<EquipmentSlot, ItemStack> items) { | ||
this.items = items; | ||
@@ -29,7 +34,13 @@ public class EntityEquipment { | ||
|
||
public ItemStack set(EquipmentSlot slot, ItemStack stack) { | ||
stack.getItem().verifyComponentsAfterLoad(stack); | ||
- return Objects.requireNonNullElse(this.items.put(slot, stack), ItemStack.EMPTY); | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ ItemStack oldStack = Objects.requireNonNullElse(this.items.put(slot, stack), ItemStack.EMPTY); | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) { | ||
+ this.onEquipmentReplaced(oldStack, stack); | ||
+ } | ||
+ return oldStack; | ||
+ // Leaves end - Lithium - equipment tracking | ||
} | ||
|
||
public ItemStack get(EquipmentSlot slot) { | ||
@@ -56,8 +67,23 @@ public class EntityEquipment { | ||
} | ||
|
||
public void setAll(EntityEquipment equipment) { | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) this.onClear(); // Leaves - Lithium - equipment tracking | ||
this.items.clear(); | ||
this.items.putAll(equipment.items); | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) { | ||
+ for (net.minecraft.world.item.ItemStack newStack : this.items.values()) { | ||
+ if (!newStack.isEmpty()) { | ||
+ if (!this.shouldTickEnchantments) { | ||
+ this.shouldTickEnchantments = stackHasTickableEnchantment(newStack); | ||
+ } | ||
+ if (!newStack.isEmpty()) { | ||
+ newStack.lithium$subscribe(this, 0); | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ // Leaves end - Lithium - equipment tracking | ||
} | ||
|
||
public void dropAll(LivingEntity entity) { | ||
@@ -70,6 +96,7 @@ public class EntityEquipment { | ||
|
||
public void clear() { | ||
this.items.replaceAll((equipmentSlot, itemStack) -> ItemStack.EMPTY); | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) this.onClear(); // Leaves - Lithium - equipment tracking | ||
} | ||
|
||
// Paper start - EntityDeathEvent | ||
@@ -78,4 +105,98 @@ public class EntityEquipment { | ||
return this.items.containsKey(slot); | ||
} | ||
// Paper end - EntityDeathEvent | ||
+ | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ public boolean lithium$shouldTickEnchantments() { | ||
+ this.processScheduledEnchantmentCheck(null); | ||
+ return this.shouldTickEnchantments; | ||
+ } | ||
+ | ||
+ public boolean lithium$hasUnsentEquipmentChanges() { | ||
+ return this.hasUnsentEquipmentChanges; | ||
+ } | ||
+ | ||
+ public void lithium$onEquipmentChangesSent() { | ||
+ this.hasUnsentEquipmentChanges = false; | ||
+ } | ||
+ | ||
+ private void onClear() { | ||
+ this.shouldTickEnchantments = false; | ||
+ this.recheckEnchantmentForStack = null; | ||
+ this.hasUnsentEquipmentChanges = true; | ||
+ | ||
+ for (ItemStack oldStack : this.items.values()) { | ||
+ if (!oldStack.isEmpty()) { | ||
+ oldStack.lithium$unsubscribeWithData(this, 0); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ private void onEquipmentReplaced(ItemStack oldStack, ItemStack newStack) { | ||
+ if (!this.shouldTickEnchantments) { | ||
+ if (this.recheckEnchantmentForStack == oldStack) { | ||
+ this.recheckEnchantmentForStack = null; | ||
+ } | ||
+ this.shouldTickEnchantments = stackHasTickableEnchantment(newStack); | ||
+ } | ||
+ | ||
+ this.hasUnsentEquipmentChanges = true; | ||
+ | ||
+ if (!oldStack.isEmpty()) { | ||
+ oldStack.lithium$unsubscribeWithData(this, 0); | ||
+ } | ||
+ if (!newStack.isEmpty()) { | ||
+ newStack.lithium$subscribe(this, 0); | ||
+ } | ||
+ } | ||
+ | ||
+ private static boolean stackHasTickableEnchantment(ItemStack stack) { | ||
+ if (!stack.isEmpty()) { | ||
+ net.minecraft.world.item.enchantment.ItemEnchantments enchantments = stack.get(net.minecraft.core.component.DataComponents.ENCHANTMENTS); | ||
+ if (enchantments != null && !enchantments.isEmpty()) { | ||
+ for (net.minecraft.core.Holder<net.minecraft.world.item.enchantment.Enchantment> enchantmentEntry : enchantments.keySet()) { | ||
+ if (!enchantmentEntry.value().getEffects(net.minecraft.world.item.enchantment.EnchantmentEffectComponents.TICK).isEmpty()) { | ||
+ return true; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ return false; | ||
+ } | ||
+ | ||
+ @Override | ||
+ public void lithium$notify(@org.jetbrains.annotations.Nullable ItemStack publisher, int zero) { | ||
+ this.hasUnsentEquipmentChanges = true; | ||
+ | ||
+ if (!this.shouldTickEnchantments) { | ||
+ this.processScheduledEnchantmentCheck(publisher); | ||
+ this.scheduleEnchantmentCheck(publisher); | ||
+ } | ||
+ } | ||
+ | ||
+ private void scheduleEnchantmentCheck(@org.jetbrains.annotations.Nullable ItemStack toCheck) { | ||
+ this.recheckEnchantmentForStack = toCheck; | ||
+ } | ||
+ | ||
+ private void processScheduledEnchantmentCheck(@org.jetbrains.annotations.Nullable ItemStack ignoredStack) { | ||
+ if (this.recheckEnchantmentForStack != null && this.recheckEnchantmentForStack != ignoredStack) { | ||
+ this.shouldTickEnchantments = stackHasTickableEnchantment(this.recheckEnchantmentForStack); | ||
+ this.recheckEnchantmentForStack = null; | ||
+ } | ||
+ } | ||
+ | ||
+ @Override | ||
+ public void lithium$notifyCount(ItemStack publisher, int zero, int newCount) { | ||
+ if (newCount == 0) { | ||
+ publisher.lithium$unsubscribeWithData(this, zero); | ||
+ } | ||
+ | ||
+ this.onEquipmentReplaced(publisher, ItemStack.EMPTY); | ||
+ } | ||
+ | ||
+ @Override | ||
+ public void lithium$forceUnsubscribe(ItemStack publisher, int zero) { | ||
+ throw new UnsupportedOperationException(); | ||
+ } | ||
MC-XiaoHei marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ // Leaves end - Lithium - equipment tracking | ||
} | ||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java | ||
index 951300caeca0421cabda44496ed2f09fc2258dd0..eb1a6644670c126c03ef871c8ac4bc2d0e389872 100644 | ||
--- a/net/minecraft/world/entity/LivingEntity.java | ||
+++ b/net/minecraft/world/entity/LivingEntity.java | ||
@@ -425,9 +425,17 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
this.getSleepingPos().ifPresent(this::setPosToBed); | ||
} | ||
|
||
- if (this.level() instanceof ServerLevel serverLevel) { | ||
- EnchantmentHelper.tickEffects(serverLevel, this); | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) { | ||
+ if ((this instanceof Player || this.equipment.lithium$shouldTickEnchantments()) && this.level() instanceof ServerLevel serverLevel) { | ||
+ EnchantmentHelper.tickEffects(serverLevel, this); | ||
+ } | ||
+ } else { | ||
+ if (this.level() instanceof ServerLevel serverLevel) { | ||
+ EnchantmentHelper.tickEffects(serverLevel, this); | ||
+ } | ||
} | ||
+ // Leaves end - Lithium - equipment tracking | ||
|
||
super.baseTick(); | ||
ProfilerFiller profilerFiller = Profiler.get(); | ||
@@ -3348,6 +3356,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
public void detectEquipmentUpdates() { | ||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges(); | ||
if (map != null) { | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking && !(this instanceof net.minecraft.world.entity.player.Player)) this.equipment.lithium$onEquipmentChangesSent(); // Leaves - Lithium - equipment tracking | ||
this.handleHandSwap(map); | ||
if (!map.isEmpty()) { | ||
this.handleEquipmentChanges(map); | ||
@@ -3357,6 +3366,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
|
||
@Nullable | ||
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() { | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) { | ||
+ final boolean isArmorStandUpdateNoTick = this instanceof net.minecraft.world.entity.decoration.ArmorStand stand && !stand.canTick && stand.noTickEquipmentDirty; | ||
+ if (!isArmorStandUpdateNoTick && !this.equipment.lithium$hasUnsentEquipmentChanges()) { | ||
+ return null; | ||
+ } | ||
+ } | ||
+ // Leaves end - Lithium - equipment tracking | ||
Map<EquipmentSlot, ItemStack> map = null; | ||
// Paper start - EntityEquipmentChangedEvent | ||
record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange { | ||
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java | ||
index d7725b5ca689e3d5b512baab04e113be77c0b2ee..abe5d681f81f60facc019660a6eae833e5742cef 100644 | ||
--- a/net/minecraft/world/entity/decoration/ArmorStand.java | ||
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java | ||
@@ -89,7 +89,7 @@ public class ArmorStand extends LivingEntity { | ||
// Paper start - Allow ArmorStands not to tick | ||
public boolean canTick = true; | ||
public boolean canTickSetByAPI = false; | ||
- private boolean noTickEquipmentDirty = false; | ||
+ public boolean noTickEquipmentDirty = false; // Leaves - private -> public | ||
// Paper end - Allow ArmorStands not to tick | ||
|
||
public ArmorStand(EntityType<? extends ArmorStand> entityType, Level level) { | ||
@@ -530,8 +530,9 @@ public class ArmorStand extends LivingEntity { | ||
public void tick() { | ||
if (!this.canTick) { | ||
if (this.noTickEquipmentDirty) { | ||
- this.noTickEquipmentDirty = false; | ||
+ if (!org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) this.noTickEquipmentDirty = false; // Leaves - Lithium - equipment tracking - move down when enable | ||
this.detectEquipmentUpdates(); | ||
+ if (org.leavesmc.leaves.LeavesConfig.performance.equipmentTracking) this.noTickEquipmentDirty = false; // Leaves - Lithium - equipment tracking | ||
} | ||
|
||
return; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.