9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-28 19:39:17 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0170-optimize-attribute.patch
hayanesuru f2682d84a6 optimize attribute and cleanup entity tracker (#548)
* optimize attribute

* compile fix

* redo async tracker

* rename id

* refactor

* fix comment

* reduce call

* fix entity removal

* rename

* fix

* fix ctx

* unnecessary

* rebuild patches

* fix immediately remove

closes: #555

* wrap
2025-12-10 17:00:14 -05:00

274 lines
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
Date: Thu, 14 Aug 2025 14:12:38 +0900
Subject: [PATCH] optimize attribute
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 61a9d3012eb7a8bfdd3867606cd1b144f6170de2..85c811666b5cc4a01ccb97cef0cf350570bc12c6 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -463,7 +463,7 @@ public class ServerEntity {
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
}
- attributesToSync.clear();
+ // attributesToSync.clear(); // Leaf - optimize attribute
}
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 500f62505d56c51ea6a21280152852db02c086b8..36859e17275a38d7acc82fcad8762bfc642811a1 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -370,7 +370,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
.add(Attributes.CAMERA_DISTANCE)
.add(Attributes.WAYPOINT_TRANSMIT_RANGE);
}
- public boolean shouldSendAttribute(Attribute attribute) { return true; } // Purpur - Ridables
+ public boolean shouldSendAttribute(Attribute attribute) { return true; } // Purpur - Ridables // Leaf - optimize attribute - diff on change
@Override
protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) {
@@ -1345,13 +1345,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
private void refreshDirtyAttributes() {
- Set<AttributeInstance> attributesToUpdate = this.getAttributes().getAttributesToUpdate();
+ // Leaf start - optimize attribute
+ int[] attributesToUpdate = this.getAttributes().getAttributesToUpdateIds();
- for (AttributeInstance attributeInstance : attributesToUpdate) {
- this.onAttributeUpdated(attributeInstance.getAttribute());
+ for (int attribute : attributesToUpdate) {
+ this.onAttributeUpdated(org.dreeam.leaf.util.RegistryTypeManager.ATTRIBUTE[attribute]);
}
-
- attributesToUpdate.clear();
+ // Leaf end - optimize attribute
}
protected void onAttributeUpdated(Holder<Attribute> attribute) {
diff --git a/net/minecraft/world/entity/ai/attributes/Attribute.java b/net/minecraft/world/entity/ai/attributes/Attribute.java
index 18563961e9dba1a11265c6ea708881d4e46846ff..ad3fee2adde07055e1ce69a069fd4201020a47ea 100644
--- a/net/minecraft/world/entity/ai/attributes/Attribute.java
+++ b/net/minecraft/world/entity/ai/attributes/Attribute.java
@@ -16,10 +16,15 @@ public class Attribute {
private boolean syncable;
private final String descriptionId;
public Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE;
+ // Leaf start - optimize attribute
+ public final int id;
+ private static int size = 0;
+ // Leaf end - optimize attribute
protected Attribute(String descriptionId, double defaultValue) {
this.defaultValue = defaultValue;
this.descriptionId = descriptionId;
+ this.id = size++; // Leaf - optimize attribute
}
public double getDefaultValue() {
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
index 42ad600c6a5cb20e1d820f169f6a1a17ef3a5195..df5f51f6a2921a7c1f1b2d17938a704c61102ba3 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
@@ -52,16 +52,19 @@ public class AttributeInstance {
@VisibleForTesting
Map<ResourceLocation, AttributeModifier> getModifiers(AttributeModifier.Operation operation) {
- return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> new Object2ObjectOpenHashMap<>());
+ return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> new Object2ObjectArrayMap<>()); // Leaf - optimize attribute
}
+ // Leaf start - optimize attribute
+ private static final AttributeModifier[] EMPTY_ATTRIBUTE_MODIFIER_ARRAY = {};
public Set<AttributeModifier> getModifiers() {
- return ImmutableSet.copyOf(this.modifierById.values());
+ return this.modifierById.isEmpty() ? Set.of() : it.unimi.dsi.fastutil.objects.ObjectArraySet.ofUnchecked(this.modifierById.values().toArray(EMPTY_ATTRIBUTE_MODIFIER_ARRAY));
}
public Set<AttributeModifier> getPermanentModifiers() {
- return ImmutableSet.copyOf(this.permanentModifiers.values());
+ return this.permanentModifiers.isEmpty() ? Set.of() : it.unimi.dsi.fastutil.objects.ObjectArraySet.ofUnchecked(this.permanentModifiers.values().toArray(EMPTY_ATTRIBUTE_MODIFIER_ARRAY));
}
+ // Leaf end - optimize attribute
@Nullable
public AttributeModifier getModifier(ResourceLocation id) {
@@ -139,12 +142,15 @@ public class AttributeInstance {
}
public double getValue() {
- if (this.dirty) {
- this.cachedValue = this.calculateValue();
- this.dirty = false;
+ // Leaf start - optimize attribute
+ if (!this.dirty) {
+ return this.cachedValue;
}
-
- return this.cachedValue;
+ double value = this.calculateValue();
+ this.cachedValue = value;
+ this.dirty = false;
+ return value;
+ // Leaf end - optimize attribute
}
private double calculateValue() {
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index a65ba1712d55d23abdbb192f13ffb972be308e84..4395afb167217c92213d646dc2cd42d786798843 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -13,12 +13,12 @@ import javax.annotation.Nullable;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
-public class AttributeMap {
- // Gale start - Lithium - replace AI attributes with optimized collections
- public final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
- private final Set<AttributeInstance> attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
- private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
- // Gale end - Lithium - replace AI attributes with optimized collections
+public class AttributeMap implements java.util.function.Consumer<AttributeInstance> { // Leaf - optimize attribute
+ // Leaf start - optimize attribute
+ public final Map<Holder<Attribute>, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap();
+ private final Set<AttributeInstance> attributesToSync = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
+ private final Set<AttributeInstance> attributesToUpdate = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
+ // Leaf end - optimize attribute
private final AttributeSupplier supplier;
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
@@ -27,34 +27,109 @@ public class AttributeMap {
this(supplier, null);
}
public AttributeMap(AttributeSupplier defaultAttributes, net.minecraft.world.entity.LivingEntity entity) {
- this.entity = entity;
+ this.entity = entity instanceof net.minecraft.world.entity.ambient.Bat ? entity : null; // Leaf - optimize attribute - only check bat
// Purpur end - Ridables
this.supplier = defaultAttributes;
}
private void onAttributeModified(AttributeInstance instance) {
- this.attributesToUpdate.add(instance);
- if (instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur - Ridables
- this.attributesToSync.add(instance);
+ // Leaf start - optimize attribute
+ Attribute attribute = instance.getAttribute().value();
+ ((org.dreeam.leaf.util.map.AttributeInstanceSet)this.attributesToUpdate).addAttribute(attribute);
+ if (attribute.isClientSyncable() && (entity == null || entity.shouldSendAttribute(attribute))) { // Purpur - Ridables
+ ((org.dreeam.leaf.util.map.AttributeInstanceSet)this.attributesToSync).addAttribute(attribute);
}
+ // Leaf end - optimize attribute
}
+ // Leaf start - optimize attribute
+ @Override
+ public void accept(AttributeInstance instance) {
+ this.onAttributeModified(instance);
+ }
+
+ private static final AttributeInstance[] EMPTY_ATTRIBUTE_INSTANCE = new AttributeInstance[0];
+ @Deprecated
public Set<AttributeInstance> getAttributesToSync() {
- return this.attributesToSync;
+ if (attributesToSync.isEmpty()) {
+ return Set.of();
+ }
+ it.unimi.dsi.fastutil.objects.ReferenceArraySet<AttributeInstance> clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToSync.toArray(EMPTY_ATTRIBUTE_INSTANCE));
+ this.attributesToSync.clear();
+ return clone;
}
+ @Deprecated
public Set<AttributeInstance> getAttributesToUpdate() {
- return this.attributesToUpdate;
+ if (attributesToUpdate.isEmpty()) {
+ return Set.of();
+ }
+ it.unimi.dsi.fastutil.objects.ReferenceArraySet<AttributeInstance> clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToUpdate.toArray(EMPTY_ATTRIBUTE_INSTANCE));
+ this.attributesToUpdate.clear();
+ return clone;
+ }
+
+ public boolean attributeDirty() {
+ return !attributesToSync.isEmpty();
+ }
+
+ public int[] getAttributesToUpdateIds() {
+ int[] clone = ((org.dreeam.leaf.util.map.AttributeInstanceSet)attributesToUpdate).inner.toIntArray();
+ this.attributesToUpdate.clear();
+ return clone;
+ }
+
+ public int[] getAttributesToSyncIds() {
+ int[] clone = ((org.dreeam.leaf.util.map.AttributeInstanceSet)attributesToSync).inner.toIntArray();
+ this.attributesToSync.clear();
+ return clone;
}
public Collection<AttributeInstance> getSyncableAttributes() {
- return this.attributes.values().stream().filter(instance -> instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))).collect(Collectors.toList()); // Purpur - Ridables
+ List<AttributeInstance> list = new ArrayList<>(this.attributes.size());
+ for (AttributeInstance instance : this.attributes.values()) {
+ if (instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur - Ridables
+ list.add(instance);
+ }
+ }
+ return list;
+ }
+
+ public List<net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot> getSyncableAttributesPacket() {
+ List<net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot> list = new ArrayList<>(attributes.size());
+ if (attributes instanceof org.dreeam.leaf.util.map.AttributeInstanceArrayMap map) {
+ for (AttributeInstance instance : map.elements()) {
+ if (instance != null && instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur - Ridables
+ list.add(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot(
+ instance.getAttribute(), instance.getBaseValue(), instance.getModifiers()
+ ));
+ }
+ }
+ } else {
+ for (AttributeInstance instance : attributes.values()) {
+ if (instance != null && instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur - Ridables
+ list.add(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket.AttributeSnapshot(
+ instance.getAttribute(), instance.getBaseValue(), instance.getModifiers()
+ ));
+ }
+ }
+ }
+ return list;
}
@Nullable
public AttributeInstance getInstance(Holder<Attribute> attribute) {
- return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>)holder));
+ AttributeInstance v;
+ if ((v = this.attributes.get(attribute)) == null) {
+ AttributeInstance newValue;
+ if ((newValue = this.supplier.createInstance(this, attribute)) != null) {
+ attributes.put(attribute, newValue);
+ return newValue;
+ }
+ }
+ return v;
}
+ // Leaf end - optimize attribute
public boolean hasAttribute(Holder<Attribute> attribute) {
return this.attributes.get(attribute) != null || this.supplier.hasAttribute(attribute);
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
index 24710041ccbc70e5506d8d89ae34f0141977f209..a428848f7ada657e171c8ed78c52935cef53aadf 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
@@ -11,7 +11,7 @@ public class AttributeSupplier {
private final Map<Holder<Attribute>, AttributeInstance> instances;
AttributeSupplier(Map<Holder<Attribute>, AttributeInstance> instances) {
- this.instances = instances;
+ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - optimize attribute
}
public AttributeInstance getAttributeInstance(Holder<Attribute> attribute) {