-
-
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.
+270
−0
Open
Changes from 1 commit
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
240 changes: 240 additions & 0 deletions
240
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,240 @@ | ||
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..e21968703dfee71946f64b1262cb35d9b3904b6c 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 net.caffeinemc.mods.lithium.common.entity.EquipmentInfo, 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,11 @@ 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); | ||
+ this.onEquipmentReplaced(oldStack, stack); | ||
+ return oldStack; | ||
+ // Leaves end - Lithium - equipment tracking | ||
} | ||
|
||
public ItemStack get(EquipmentSlot slot) { | ||
@@ -56,8 +65,21 @@ public class EntityEquipment { | ||
} | ||
|
||
public void setAll(EntityEquipment equipment) { | ||
+ this.onClear(); // Leaves - Lithium - equipment tracking | ||
this.items.clear(); | ||
this.items.putAll(equipment.items); | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ for (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 +92,7 @@ public class EntityEquipment { | ||
|
||
public void clear() { | ||
this.items.replaceAll((equipmentSlot, itemStack) -> ItemStack.EMPTY); | ||
+ this.onClear(); // Leaves - Lithium - equipment tracking | ||
} | ||
|
||
// Paper start - EntityDeathEvent | ||
@@ -78,4 +101,99 @@ public class EntityEquipment { | ||
return this.items.containsKey(slot); | ||
} | ||
// Paper end - EntityDeathEvent | ||
+ | ||
+ @Override | ||
+ public boolean lithium$shouldTickEnchantments() { | ||
+ this.processScheduledEnchantmentCheck(null); | ||
+ return this.shouldTickEnchantments; | ||
+ } | ||
+ | ||
+ @Override | ||
+ public boolean lithium$hasUnsentEquipmentChanges() { | ||
+ return this.hasUnsentEquipmentChanges; | ||
+ } | ||
+ | ||
+ @Override | ||
+ 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
|
||
} | ||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java | ||
index 951300caeca0421cabda44496ed2f09fc2258dd0..94d3ad59dbf105e827c69bac2fce67edbe3ea4ba 100644 | ||
--- a/net/minecraft/world/entity/LivingEntity.java | ||
+++ b/net/minecraft/world/entity/LivingEntity.java | ||
@@ -425,7 +425,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
this.getSleepingPos().ifPresent(this::setPosToBed); | ||
} | ||
|
||
- if (this.level() instanceof ServerLevel serverLevel) { | ||
+ if ((this instanceof Player || this.equipment.lithium$shouldTickEnchantments()) && this.level() instanceof ServerLevel serverLevel) { // Leaves - Lithium - equipment tracking | ||
EnchantmentHelper.tickEffects(serverLevel, this); | ||
} | ||
|
||
@@ -3348,6 +3348,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
public void detectEquipmentUpdates() { | ||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges(); | ||
if (map != null) { | ||
+ if (!(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 +3358,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin | ||
|
||
@Nullable | ||
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() { | ||
+ // Leaves start - Lithium - equipment tracking | ||
+ 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..e20c90c6db23ce82f19526cfd384d52d4af06afc 100644 | ||
--- a/net/minecraft/world/entity/decoration/ArmorStand.java | ||
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java | ||
@@ -530,8 +530,9 @@ public class ArmorStand extends LivingEntity { | ||
public void tick() { | ||
if (!this.canTick) { | ||
if (this.noTickEquipmentDirty) { | ||
- this.noTickEquipmentDirty = false; | ||
+ //this.noTickEquipmentDirty = false; // Leaves - Lithium - equipment tracking - move down | ||
this.detectEquipmentUpdates(); | ||
+ this.noTickEquipmentDirty = false; // Leaves - Lithium - equipment tracking | ||
} | ||
|
||
return; |
Oops, something went wrong.
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.