mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-28 19:39:17 +00:00
* 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
274 lines
14 KiB
Diff
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) {
|