mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
fix attribute crash server
This commit is contained in:
@@ -58,6 +58,18 @@ index dd2509996bfd08e8c3f9f2be042229eac6d7692d..a35e9fae8f8da0c42f0616c4f78dc396
|
|||||||
|
|
||||||
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
|
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
|
||||||
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
|
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
|
||||||
|
diff --git a/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java b/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
index 9c0c99b936b4a82ebfe924866e53ec71f7bbe9ad..2ccff968cb2065d34fad4d27573f9e3081edb2f2 100644
|
||||||
|
--- a/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
+++ b/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
@@ -32,6 +32,7 @@ public class ClientboundUpdateAttributesPacket implements Packet<ClientGamePacke
|
||||||
|
this.attributes = Lists.newArrayList();
|
||||||
|
|
||||||
|
for (AttributeInstance attributeInstance : attributes) {
|
||||||
|
+ if (attributeInstance == null) continue; // Leaf - Multithreaded tracker
|
||||||
|
this.attributes
|
||||||
|
.add(
|
||||||
|
new ClientboundUpdateAttributesPacket.AttributeSnapshot(
|
||||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||||
index 5d9d233e3a568aa6297ed9c703fa450f98158602..47a7bf7c38600a2ad547bbd2b7fe632e96e9a139 100644
|
index 5d9d233e3a568aa6297ed9c703fa450f98158602..47a7bf7c38600a2ad547bbd2b7fe632e96e9a139 100644
|
||||||
--- a/net/minecraft/server/level/ChunkMap.java
|
--- a/net/minecraft/server/level/ChunkMap.java
|
||||||
@@ -319,7 +331,7 @@ index f106373ef3ac4a8685c2939c9e8361688a285913..51ae390c68e7a3aa193329cc3bc47ca6
|
|||||||
public boolean visible = true;
|
public boolean visible = true;
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||||
index 1dee20436fc29537319ee456756a8e8f7b6fe66a..bcd569e7d12d4f453c64bf12933a72c3ca362329 100644
|
index 1dee20436fc29537319ee456756a8e8f7b6fe66a..5351d373aa0f4450386a6b50f88052c031949f5b 100644
|
||||||
--- a/net/minecraft/server/level/ServerEntity.java
|
--- a/net/minecraft/server/level/ServerEntity.java
|
||||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||||
@@ -110,8 +110,16 @@ public class ServerEntity {
|
@@ -110,8 +110,16 @@ public class ServerEntity {
|
||||||
@@ -350,38 +362,15 @@ index 1dee20436fc29537319ee456756a8e8f7b6fe66a..bcd569e7d12d4f453c64bf12933a72c3
|
|||||||
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
|
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
|
||||||
savedData.tickCarriedBy(serverPlayer, item);
|
savedData.tickCarriedBy(serverPlayer, item);
|
||||||
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
||||||
@@ -433,15 +441,30 @@ public class ServerEntity {
|
@@ -443,7 +451,7 @@ public class ServerEntity {
|
||||||
}
|
|
||||||
|
|
||||||
if (this.entity instanceof LivingEntity) {
|
|
||||||
- Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
|
|
||||||
+ // Leaf start - Multithreaded tracker
|
|
||||||
+ var attributeMap = ((LivingEntity)this.entity).getAttributes();
|
|
||||||
+ Set<AttributeInstance> attributesToSync = attributeMap.getAttributesToSync();
|
|
||||||
if (!attributesToSync.isEmpty()) {
|
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
+ synchronized (attributeMap) {
|
|
||||||
+ // CraftBukkit start - Send scaled max health
|
|
||||||
+ if (this.entity instanceof ServerPlayer serverPlayer) {
|
|
||||||
+ serverPlayer.getBukkitEntity().injectScaledMaxHealth(attributesToSync, false);
|
|
||||||
+ }
|
|
||||||
+ // CraftBukkit end
|
|
||||||
+ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
// CraftBukkit start - Send scaled max health
|
|
||||||
if (this.entity instanceof ServerPlayer serverPlayer) {
|
|
||||||
serverPlayer.getBukkitEntity().injectScaledMaxHealth(attributesToSync, false);
|
|
||||||
}
|
|
||||||
// CraftBukkit end
|
|
||||||
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
|
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
|
||||||
+ }
|
|
||||||
}
|
}
|
||||||
+ // Leaf end - Multithreaded tracker
|
|
||||||
|
|
||||||
attributesToSync.clear();
|
- attributesToSync.clear();
|
||||||
|
+ // attributesToSync.clear(); // Leaf - Multithreaded tracker
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 275b640f4536366152f59acf071dd4eba15696c8..a669a59a42f814480879a52d2da5e04c636720de 100644
|
index 275b640f4536366152f59acf071dd4eba15696c8..a669a59a42f814480879a52d2da5e04c636720de 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -418,39 +407,50 @@ index 327b3bc89920c4ab02c1126dc63bca05ce3abefe..1415043bee5fbbfcf9dab9184a9418d5
|
|||||||
if (this.player.isRemoved()) {
|
if (this.player.isRemoved()) {
|
||||||
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
||||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
index d502325d693539842fd6f5485365e0e9b786b7aa..324f8952a921a3897f4ff48145f0f8645c690318 100644
|
index d502325d693539842fd6f5485365e0e9b786b7aa..a99527409e9aae6c8b321a5ed100b2645151087e 100644
|
||||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
@@ -1311,13 +1311,26 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -1311,13 +1311,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshDirtyAttributes() {
|
private void refreshDirtyAttributes() {
|
||||||
- Set<AttributeInstance> attributesToUpdate = this.getAttributes().getAttributesToUpdate();
|
- Set<AttributeInstance> attributesToUpdate = this.getAttributes().getAttributesToUpdate();
|
||||||
+ // Leaf start - Multithreaded tracker
|
+ // Leaf start - Multithreaded tracker
|
||||||
+ var attributeMap = this.getAttributes();
|
+ int[] attributesToUpdate = this.getAttributes().getAttributesToUpdateIds();
|
||||||
+ Set<AttributeInstance> attributesToUpdate = attributeMap.getAttributesToUpdate();
|
|
||||||
+
|
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
+ synchronized (attributeMap) {
|
|
||||||
+ for (AttributeInstance attributeInstance : attributesToUpdate) {
|
|
||||||
+ this.onAttributeUpdated(attributeInstance.getAttribute());
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ attributesToUpdate.clear();
|
- for (AttributeInstance attributeInstance : attributesToUpdate) {
|
||||||
+ }
|
- this.onAttributeUpdated(attributeInstance.getAttribute());
|
||||||
+ } else {
|
+ for (int attribute : attributesToUpdate) {
|
||||||
for (AttributeInstance attributeInstance : attributesToUpdate) {
|
+ this.onAttributeUpdated(net.minecraft.core.registries.BuiltInRegistries.ATTRIBUTE.get(attribute).orElseThrow());
|
||||||
this.onAttributeUpdated(attributeInstance.getAttribute());
|
|
||||||
}
|
}
|
||||||
|
-
|
||||||
attributesToUpdate.clear();
|
- attributesToUpdate.clear();
|
||||||
+ }
|
|
||||||
+ // Leaf end - Multithreaded tracker
|
+ // Leaf end - Multithreaded tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onAttributeUpdated(Holder<Attribute> 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 f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b161647497f99b 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;
|
||||||
|
private Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE;
|
||||||
|
+ // Leaf start - Optimize AttributeMap
|
||||||
|
+ public final int uid;
|
||||||
|
+ private static final java.util.concurrent.atomic.AtomicInteger SIZE = new java.util.concurrent.atomic.AtomicInteger();
|
||||||
|
+ // Leaf end - Optimize AttributeMap
|
||||||
|
|
||||||
|
protected Attribute(String descriptionId, double defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.descriptionId = descriptionId;
|
||||||
|
+ this.uid = SIZE.getAndAdd(1); // Leaf - Optimize AttributeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDefaultValue() {
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
index 8013594bb4844e7a8abf28123958e7f632d39341..93b375f39f10568f6b222607890a9ce67db0e9bb 100644
|
index 8013594bb4844e7a8abf28123958e7f632d39341..b502c4a0f3695cc5bee8954f937f64584df1584d 100644
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
@@ -24,8 +24,24 @@ public class AttributeInstance {
|
@@ -24,8 +24,24 @@ public class AttributeInstance {
|
||||||
@@ -495,21 +495,21 @@ index 8013594bb4844e7a8abf28123958e7f632d39341..93b375f39f10568f6b222607890a9ce6
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Set<AttributeModifier> getModifiers() {
|
public Set<AttributeModifier> getModifiers() {
|
||||||
@@ -174,6 +196,13 @@ public class AttributeInstance {
|
@@ -142,8 +164,12 @@ public class AttributeInstance {
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceFrom(AttributeInstance instance) {
|
public double getValue() {
|
||||||
+ // Leaf start - Multithreaded tracker
|
if (this.dirty) {
|
||||||
+ synchronized (instance) {
|
- this.cachedValue = this.calculateValue();
|
||||||
+ this.replaceFrom0(instance);
|
+ // Leaf start - Multithreaded tracker
|
||||||
+ }
|
+ double value = this.calculateValue();
|
||||||
+ }
|
+ this.cachedValue = value;
|
||||||
+ public void replaceFrom0(AttributeInstance instance) {
|
this.dirty = false;
|
||||||
+ // Leaf end - Multithreaded tracker
|
+ return value;
|
||||||
this.baseValue = instance.baseValue;
|
+ // Leaf end - Multithreaded tracker
|
||||||
this.modifierById.clear();
|
}
|
||||||
this.modifierById.putAll(instance.modifierById);
|
|
||||||
@@ -195,9 +224,19 @@ public class AttributeInstance {
|
return this.cachedValue;
|
||||||
|
@@ -195,9 +221,19 @@ public class AttributeInstance {
|
||||||
if (!this.permanentModifiers.isEmpty()) {
|
if (!this.permanentModifiers.isEmpty()) {
|
||||||
ListTag listTag = new ListTag();
|
ListTag listTag = new ListTag();
|
||||||
|
|
||||||
@@ -532,65 +532,112 @@ index 8013594bb4844e7a8abf28123958e7f632d39341..93b375f39f10568f6b222607890a9ce6
|
|||||||
compoundTag.put("modifiers", listTag);
|
compoundTag.put("modifiers", listTag);
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..c0a09b615e9b6c4ec72b8b77a78e7da374d4498b 100644
|
index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..0bc846721b1af44904a705f5c4aef897a03824e0 100644
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
@@ -21,8 +21,19 @@ public class AttributeMap {
|
@@ -20,12 +20,14 @@ import org.slf4j.Logger;
|
||||||
|
public class AttributeMap {
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
// Gale start - Lithium - replace AI attributes with optimized collections
|
// Gale start - Lithium - replace AI attributes with optimized collections
|
||||||
private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
- private 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> attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||||
- private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
- private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||||
+ // Leaf start - Multithreaded tracker
|
+ // Leaf start - Multithreaded tracker
|
||||||
+ private final Set<AttributeInstance> attributesToSync;
|
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap();
|
||||||
+ private final Set<AttributeInstance> attributesToUpdate;
|
+ private final org.dreeam.leaf.util.map.AttributeInstanceSet attributesToSync = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
|
||||||
+ {
|
+ private final org.dreeam.leaf.util.map.AttributeInstanceSet attributesToUpdate = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
+ attributesToSync = it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0), this);
|
|
||||||
+ attributesToUpdate = it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0), this);
|
|
||||||
+ } else {
|
|
||||||
+ attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
|
||||||
+ attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Leaf end - Multithreaded tracker
|
+ // Leaf end - Multithreaded tracker
|
||||||
// Gale end - Lithium - replace AI attributes with optimized collections
|
// Gale end - Lithium - replace AI attributes with optimized collections
|
||||||
private final AttributeSupplier supplier;
|
private final AttributeSupplier supplier;
|
||||||
private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations
|
- private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations
|
||||||
@@ -60,7 +71,13 @@ public class AttributeMap {
|
+ //private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
||||||
|
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
|
||||||
|
|
||||||
|
public AttributeMap(AttributeSupplier supplier) {
|
||||||
|
@@ -36,31 +38,54 @@ public class AttributeMap {
|
||||||
|
this.entity = entity;
|
||||||
|
// Purpur end - Ridables
|
||||||
|
this.supplier = defaultAttributes;
|
||||||
|
- this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations
|
||||||
|
+ //this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
- private void onAttributeModified(AttributeInstance instance) {
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ private synchronized 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- public Set<AttributeInstance> getAttributesToSync() {
|
||||||
|
- return this.attributesToSync;
|
||||||
|
+ private static final AttributeInstance[] EMPTY_ATTRIBUTE_INSTANCE = new AttributeInstance[0];
|
||||||
|
+ public synchronized Set<AttributeInstance> getAttributesToSync() {
|
||||||
|
+ var clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToSync.toArray(EMPTY_ATTRIBUTE_INSTANCE));
|
||||||
|
+ this.attributesToSync.clear();
|
||||||
|
+ return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
- public Set<AttributeInstance> getAttributesToUpdate() {
|
||||||
|
- return this.attributesToUpdate;
|
||||||
|
+ public synchronized Set<AttributeInstance> getAttributesToUpdate() {
|
||||||
|
+ var clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToUpdate.toArray(EMPTY_ATTRIBUTE_INSTANCE));
|
||||||
|
+ this.attributesToUpdate.clear();
|
||||||
|
+ return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public synchronized int[] getAttributesToUpdateIds() {
|
||||||
|
+ int[] clone = attributesToUpdate.inner.toIntArray();
|
||||||
|
+ this.attributesToUpdate.clear();
|
||||||
|
+ return clone;
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
+
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public AttributeInstance getInstance(Holder<Attribute> attribute) {
|
public AttributeInstance getInstance(Holder<Attribute> attribute) {
|
||||||
- return this.attributes.computeIfAbsent(attribute, this.createInstance); // Gale - Airplane - reduce entity allocations - cache lambda, as for some reason java allocates it anyways
|
- return this.attributes.computeIfAbsent(attribute, this.createInstance); // Gale - Airplane - reduce entity allocations - cache lambda, as for some reason java allocates it anyways
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
+ // Leaf start - Multithreaded tracker
|
||||||
+ synchronized (this) {
|
+ AttributeInstance v;
|
||||||
+ return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>) holder));
|
+ if ((v = this.attributes.get(attribute)) == null) {
|
||||||
|
+ AttributeInstance newValue;
|
||||||
|
+ if ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
|
||||||
|
+ attributes.put(attribute, newValue);
|
||||||
|
+ return newValue;
|
||||||
+ }
|
+ }
|
||||||
+ } else {
|
|
||||||
+ return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>) holder));
|
|
||||||
+ }
|
+ }
|
||||||
|
+ return v;
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAttribute(Holder<Attribute> attribute) {
|
public boolean hasAttribute(Holder<Attribute> attribute) {
|
||||||
@@ -176,8 +193,17 @@ public class AttributeMap {
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
||||||
|
index 24710041ccbc70e5506d8d89ae34f0141977f209..05de8a77b389691dd6986f36b4cb8cc0935e21e4 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;
|
||||||
|
|
||||||
// Paper - start - living entity allow attribute registration
|
AttributeSupplier(Map<Holder<Attribute>, AttributeInstance> instances) {
|
||||||
public void registerAttribute(Holder<Attribute> attributeBase) {
|
- this.instances = instances;
|
||||||
+ // Leaf start - Multithreaded tracker
|
+ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - Optimize AttributeMap
|
||||||
AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute);
|
|
||||||
- attributes.put(attributeBase, attributeModifiable);
|
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
+ synchronized (this) {
|
|
||||||
+ attributes.put(attributeBase, attributeModifiable);
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ attributes.put(attributeBase, attributeModifiable);
|
|
||||||
+ }
|
|
||||||
+ // Leaf end - Multithreaded tracker
|
|
||||||
}
|
}
|
||||||
// Paper - end - living entity allow attribute registration
|
|
||||||
|
|
||||||
|
public AttributeInstance getAttributeInstance(Holder<Attribute> attribute) {
|
||||||
|
@@ -41,7 +41,7 @@ public class AttributeSupplier {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
- public AttributeInstance createInstance(Consumer<AttributeInstance> onDirty, Holder<Attribute> attribute) {
|
||||||
|
+ public AttributeInstance createInstance(Consumer<AttributeInstance> onDirty, Holder<Attribute> attribute) { // Leaf - Multithreaded tracker
|
||||||
|
AttributeInstance attributeInstance = this.instances.get(attribute);
|
||||||
|
if (attributeInstance == null) {
|
||||||
|
return null;
|
||||||
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
|
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
|
||||||
index c96f458994818392857642282ec3d492124885da..d345afd14ef6fe2f0a584df5dfa080fd7ab3f47e 100644
|
index c96f458994818392857642282ec3d492124885da..d345afd14ef6fe2f0a584df5dfa080fd7ab3f47e 100644
|
||||||
--- a/net/minecraft/world/entity/item/PrimedTnt.java
|
--- a/net/minecraft/world/entity/item/PrimedTnt.java
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ As part of: Lithium (https://github.com/CaffeineMC/lithium-fabric)
|
|||||||
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
index 324f8952a921a3897f4ff48145f0f8645c690318..3e3fdcff3725841c8b04047a91733c8b98187e0b 100644
|
index 0ac8b7bd9d899daf61aeb58f80bdcebe87974d51..eb79e6984810410c646d7b1910694d7df75dccba 100644
|
||||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
@@ -2752,6 +2752,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -2739,6 +2739,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateSwingTime() {
|
protected void updateSwingTime() {
|
||||||
@@ -23,7 +23,7 @@ index 324f8952a921a3897f4ff48145f0f8645c690318..3e3fdcff3725841c8b04047a91733c8b
|
|||||||
int currentSwingDuration = this.getCurrentSwingDuration();
|
int currentSwingDuration = this.getCurrentSwingDuration();
|
||||||
if (this.swinging) {
|
if (this.swinging) {
|
||||||
this.swingTime++;
|
this.swingTime++;
|
||||||
@@ -3703,6 +3704,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -3690,6 +3691,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
protected void updateFallFlying() {
|
protected void updateFallFlying() {
|
||||||
this.checkSlowFallDistance();
|
this.checkSlowFallDistance();
|
||||||
if (!this.level().isClientSide) {
|
if (!this.level().isClientSide) {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ index a8c6549f772208cd543607224fef2c2389b14f24..709631db548a16a969a373e26ebbcd69
|
|||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
return this == other
|
return this == other
|
||||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
index 3e3fdcff3725841c8b04047a91733c8b98187e0b..ffae6778b471628639c41b1d5f3af08b6b72a86c 100644
|
index eb79e6984810410c646d7b1910694d7df75dccba..69e91a732a497b2ffa906088a636947ce9a9ec36 100644
|
||||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
@@ -159,7 +159,7 @@ import org.bukkit.event.entity.EntityTeleportEvent;
|
@@ -159,7 +159,7 @@ import org.bukkit.event.entity.EntityTeleportEvent;
|
||||||
@@ -116,7 +116,7 @@ index 3e3fdcff3725841c8b04047a91733c8b98187e0b..ffae6778b471628639c41b1d5f3af08b
|
|||||||
Equippable equippable = newItem.get(DataComponents.EQUIPPABLE);
|
Equippable equippable = newItem.get(DataComponents.EQUIPPABLE);
|
||||||
if (!this.isSilent() && equippable != null && slot == equippable.slot() && !silent) { // CraftBukkit
|
if (!this.isSilent() && equippable != null && slot == equippable.slot() && !silent) { // CraftBukkit
|
||||||
this.level()
|
this.level()
|
||||||
@@ -3368,6 +3373,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -3355,6 +3360,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
public void detectEquipmentUpdatesPublic() { // CraftBukkit
|
public void detectEquipmentUpdatesPublic() { // CraftBukkit
|
||||||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
|
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
@@ -124,7 +124,7 @@ index 3e3fdcff3725841c8b04047a91733c8b98187e0b..ffae6778b471628639c41b1d5f3af08b
|
|||||||
this.handleHandSwap(map);
|
this.handleHandSwap(map);
|
||||||
if (!map.isEmpty()) {
|
if (!map.isEmpty()) {
|
||||||
this.handleEquipmentChanges(map);
|
this.handleEquipmentChanges(map);
|
||||||
@@ -3377,6 +3383,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -3364,6 +3370,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
|
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
|
||||||
@@ -135,7 +135,7 @@ index 3e3fdcff3725841c8b04047a91733c8b98187e0b..ffae6778b471628639c41b1d5f3af08b
|
|||||||
Map<EquipmentSlot, ItemStack> map = null;
|
Map<EquipmentSlot, ItemStack> map = null;
|
||||||
// Paper start - EntityEquipmentChangedEvent
|
// Paper start - EntityEquipmentChangedEvent
|
||||||
record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange {
|
record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange {
|
||||||
@@ -4736,6 +4746,81 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -4723,6 +4733,81 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
return this.lastHurtByPlayerTime;
|
return this.lastHurtByPlayerTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ Subject: [PATCH] Only player pushable
|
|||||||
Useful for extreme cases like massive entities collide together in a small area
|
Useful for extreme cases like massive entities collide together in a small area
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
index ffae6778b471628639c41b1d5f3af08b6b72a86c..32039b50946b23e4f55498aa09ea33cfa77b517c 100644
|
index 69e91a732a497b2ffa906088a636947ce9a9ec36..d455406df1f3a4c3d1bd016d50d1d7025366ae80 100644
|
||||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
@@ -3644,7 +3644,7 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
@@ -3631,7 +3631,7 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
||||||
this.checkAutoSpinAttack(boundingBox, this.getBoundingBox());
|
this.checkAutoSpinAttack(boundingBox, this.getBoundingBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ index ffae6778b471628639c41b1d5f3af08b6b72a86c..32039b50946b23e4f55498aa09ea33cf
|
|||||||
// Paper start - Add EntityMoveEvent
|
// Paper start - Add EntityMoveEvent
|
||||||
// Purpur start - Ridables
|
// Purpur start - Ridables
|
||||||
if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
|
if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
|
||||||
@@ -3782,7 +3782,14 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
@@ -3769,7 +3769,14 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Paper end - don't run getEntities if we're not going to use its result
|
// Paper end - don't run getEntities if we're not going to use its result
|
||||||
@@ -34,7 +34,7 @@ index ffae6778b471628639c41b1d5f3af08b6b72a86c..32039b50946b23e4f55498aa09ea33cf
|
|||||||
if (!entities.isEmpty()) {
|
if (!entities.isEmpty()) {
|
||||||
// Paper - don't run getEntities if we're not going to use its result; moved up
|
// Paper - don't run getEntities if we're not going to use its result; moved up
|
||||||
if (_int > 0 && entities.size() > _int - 1 && this.random.nextInt(4) == 0) {
|
if (_int > 0 && entities.size() > _int - 1 && this.random.nextInt(4) == 0) {
|
||||||
@@ -3815,6 +3822,44 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
@@ -3802,6 +3809,44 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Optimize addOrUpdateTransientModifier
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
index 93b375f39f10568f6b222607890a9ce67db0e9bb..69ba880e17e5cff3b2260f539683ca565f34e8dd 100644
|
index ed5077708415a74da171b88fa1fb8b736446666b..62cadad97109247e65a550acc5955424b1f6fc5e 100644
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
@@ -107,8 +107,13 @@ public class AttributeInstance {
|
@@ -107,8 +107,13 @@ public class AttributeInstance {
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: hayanesuru <hayanesuru@outlook.jp>
|
|
||||||
Date: Thu, 15 May 2025 21:11:18 +0900
|
|
||||||
Subject: [PATCH] Optimize AttributeMap
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/Attribute.java b/net/minecraft/world/entity/ai/attributes/Attribute.java
|
|
||||||
index f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b161647497f99b 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;
|
|
||||||
private Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE;
|
|
||||||
+ // Leaf start - Optimize AttributeMap
|
|
||||||
+ public final int uid;
|
|
||||||
+ private static final java.util.concurrent.atomic.AtomicInteger SIZE = new java.util.concurrent.atomic.AtomicInteger();
|
|
||||||
+ // Leaf end - Optimize AttributeMap
|
|
||||||
|
|
||||||
protected Attribute(String descriptionId, double defaultValue) {
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.descriptionId = descriptionId;
|
|
||||||
+ this.uid = SIZE.getAndAdd(1); // Leaf - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDefaultValue() {
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
index c0a09b615e9b6c4ec72b8b77a78e7da374d4498b..a550e6bd9dffa9a46f0d7967c9d73ff5cbfbaa0a 100644
|
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
@@ -20,7 +20,7 @@ import org.slf4j.Logger;
|
|
||||||
public class AttributeMap {
|
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
|
||||||
// Gale start - Lithium - replace AI attributes with optimized collections
|
|
||||||
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
|
||||||
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(); // Leaf - Optimize AttributeMap
|
|
||||||
// Leaf start - Multithreaded tracker
|
|
||||||
private final Set<AttributeInstance> attributesToSync;
|
|
||||||
private final Set<AttributeInstance> attributesToUpdate;
|
|
||||||
@@ -36,7 +36,7 @@ public class AttributeMap {
|
|
||||||
// Leaf end - Multithreaded tracker
|
|
||||||
// Gale end - Lithium - replace AI attributes with optimized collections
|
|
||||||
private final AttributeSupplier supplier;
|
|
||||||
- private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations
|
|
||||||
+ //private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
|
||||||
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
|
|
||||||
|
|
||||||
public AttributeMap(AttributeSupplier supplier) {
|
|
||||||
@@ -47,7 +47,7 @@ public class AttributeMap {
|
|
||||||
this.entity = entity;
|
|
||||||
// Purpur end - Ridables
|
|
||||||
this.supplier = defaultAttributes;
|
|
||||||
- this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations
|
|
||||||
+ //this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onAttributeModified(AttributeInstance instance) {
|
|
||||||
@@ -71,13 +71,24 @@ public class AttributeMap {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public AttributeInstance getInstance(Holder<Attribute> attribute) {
|
|
||||||
- if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
- synchronized (this) {
|
|
||||||
- return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>) holder));
|
|
||||||
+ // Leaf start - Optimize AttributeMap
|
|
||||||
+ AttributeInstance v;
|
|
||||||
+ if ((v = this.attributes.get(attribute)) == null) {
|
|
||||||
+ AttributeInstance newValue;
|
|
||||||
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
|
||||||
+ synchronized (this) {
|
|
||||||
+ if ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
|
|
||||||
+ this.attributes.put(attribute, newValue);
|
|
||||||
+ return newValue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ } else if ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
|
|
||||||
+ this.attributes.put(attribute, newValue);
|
|
||||||
+ return newValue;
|
|
||||||
}
|
|
||||||
- } else {
|
|
||||||
- return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>) holder));
|
|
||||||
}
|
|
||||||
+ return v;
|
|
||||||
+ // Leaf end - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasAttribute(Holder<Attribute> attribute) {
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
|
||||||
index 24710041ccbc70e5506d8d89ae34f0141977f209..09341ef6c651150aba223689badbead490162b2b 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 AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public AttributeInstance getAttributeInstance(Holder<Attribute> attribute) {
|
|
||||||
@@ -71,6 +71,19 @@ index edcd209798740f31cb302f36d7864a0d8ea1d561..e8b80ac3d2a54b9e855cad80c8a78200
|
|||||||
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
|
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
index 8e8630db9f74e5952142dba14ec58917c5745287..f89f6cea94486842a5e9015200a0d648225c8615 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
@@ -2915,7 +2915,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
Iterator<AttributeInstance> iterator = collection.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
AttributeInstance genericInstance = iterator.next();
|
||||||
|
- if (genericInstance.getAttribute() == Attributes.MAX_HEALTH) {
|
||||||
|
+ if (genericInstance != null && genericInstance.getAttribute() == Attributes.MAX_HEALTH) { // Leaf - Multithreaded tracker
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
index e52479f3c888268fd1febeb78e9965af834a8ae9..c2552c3706831f7012b5b449fa43c7d5990056a4 100644
|
index e52479f3c888268fd1febeb78e9965af834a8ae9..c2552c3706831f7012b5b449fa43c7d5990056a4 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.*;
|
|||||||
import java.util.AbstractMap.SimpleEntry;
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
|
|
||||||
// fast array backend map with O(1) get & put & remove
|
// fast array backend map with O(1) get & put & remove
|
||||||
public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, AttributeInstance>, Cloneable {
|
public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, AttributeInstance>, Cloneable {
|
||||||
|
|
||||||
private int size = 0;
|
private int size = 0;
|
||||||
private transient AttributeInstance[] a = new AttributeInstance[32];
|
private transient AttributeInstance[] a = new AttributeInstance[32];
|
||||||
@@ -46,17 +46,17 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int size() {
|
public int size() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return size == 0;
|
return size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean containsKey(Object key) {
|
public boolean containsKey(Object key) {
|
||||||
if (key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute) {
|
if (key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute) {
|
||||||
int uid = attribute.uid;
|
int uid = attribute.uid;
|
||||||
return uid >= 0 && uid < a.length && a[uid] != null;
|
return uid >= 0 && uid < a.length && a[uid] != null;
|
||||||
@@ -65,22 +65,22 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
for (final AttributeInstance instance : a) {
|
return value instanceof AttributeInstance val && Objects.equals(getInstance(val.getAttribute().value().uid), val);
|
||||||
if (Objects.equals(value, instance)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance get(Object key) {
|
public AttributeInstance get(Object key) {
|
||||||
return key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute ? a[attribute.uid] : null;
|
return key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute ? a[attribute.uid] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public AttributeInstance getInstance(int key) {
|
||||||
|
return a[key];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance put(@NotNull Holder<Attribute> key, AttributeInstance value) {
|
public AttributeInstance put(@NotNull Holder<Attribute> key, AttributeInstance value) {
|
||||||
int uid = key.value().uid;
|
int uid = key.value().uid;
|
||||||
AttributeInstance prev = a[uid];
|
AttributeInstance prev = a[uid];
|
||||||
setByIndex(uid, value);
|
setByIndex(uid, value);
|
||||||
@@ -88,7 +88,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance remove(Object key) {
|
public AttributeInstance remove(Object key) {
|
||||||
if (!(key instanceof Holder<?> holder) || !(holder.value() instanceof Attribute attribute)) return null;
|
if (!(key instanceof Holder<?> holder) || !(holder.value() instanceof Attribute attribute)) return null;
|
||||||
int uid = attribute.uid;
|
int uid = attribute.uid;
|
||||||
AttributeInstance prev = a[uid];
|
AttributeInstance prev = a[uid];
|
||||||
@@ -97,7 +97,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void putAll(@NotNull Map<? extends Holder<Attribute>, ? extends AttributeInstance> m) {
|
public void putAll(@NotNull Map<? extends Holder<Attribute>, ? extends AttributeInstance> m) {
|
||||||
for (AttributeInstance e : m.values()) {
|
for (AttributeInstance e : m.values()) {
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
setByIndex(e.getAttribute().value().uid, e);
|
setByIndex(e.getAttribute().value().uid, e);
|
||||||
@@ -106,13 +106,13 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void clear() {
|
public void clear() {
|
||||||
Arrays.fill(a, null);
|
Arrays.fill(a, null);
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Set<Holder<Attribute>> keySet() {
|
public @NotNull Set<Holder<Attribute>> keySet() {
|
||||||
if (keys == null) {
|
if (keys == null) {
|
||||||
keys = new KeySet();
|
keys = new KeySet();
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Collection<AttributeInstance> values() {
|
public @NotNull Collection<AttributeInstance> values() {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
values = new Values();
|
values = new Values();
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Set<Entry<Holder<Attribute>, AttributeInstance>> entrySet() {
|
public @NotNull Set<Entry<Holder<Attribute>, AttributeInstance>> entrySet() {
|
||||||
if (entries == null) {
|
if (entries == null) {
|
||||||
entries = new EntrySet();
|
entries = new EntrySet();
|
||||||
}
|
}
|
||||||
@@ -136,13 +136,23 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof AttributeInstanceArrayMap that)) return false;
|
if (o == this) return true;
|
||||||
return size == that.size && Arrays.equals(a, that.a);
|
if (!(o instanceof Map<?, ?> s)) return false;
|
||||||
|
if (s.size() != size()) return false;
|
||||||
|
if (o instanceof AttributeInstanceArrayMap that) {
|
||||||
|
return Arrays.equals(a, that.a);
|
||||||
|
}
|
||||||
|
for (Entry<?, ?> e : s.entrySet()) {
|
||||||
|
if (!Objects.equals(get(e.getKey()), e.getValue())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public int hashCode() {
|
||||||
return Arrays.hashCode(a);
|
return Arrays.hashCode(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +202,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
if (!hasNext()) throw new NoSuchElementException();
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
currentIndex = nextIndex;
|
currentIndex = nextIndex;
|
||||||
nextIndex = findNextOccupied(nextIndex + 1);
|
nextIndex = findNextOccupied(nextIndex + 1);
|
||||||
return BuiltInRegistries.ATTRIBUTE.asHolderIdMap().byIdOrThrow(currentIndex);
|
return BuiltInRegistries.ATTRIBUTE.get(currentIndex).orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -279,7 +289,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
public Entry<Holder<Attribute>, AttributeInstance> next() {
|
public Entry<Holder<Attribute>, AttributeInstance> next() {
|
||||||
if (!hasNext()) throw new NoSuchElementException();
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
currentIndex = nextIndex;
|
currentIndex = nextIndex;
|
||||||
Holder<Attribute> key = BuiltInRegistries.ATTRIBUTE.asHolderIdMap().byIdOrThrow(nextIndex);
|
Holder<Attribute> key = BuiltInRegistries.ATTRIBUTE.get(nextIndex).orElseThrow();
|
||||||
AttributeInstance value = a[nextIndex];
|
AttributeInstance value = a[nextIndex];
|
||||||
nextIndex = findNextOccupied(nextIndex + 1);
|
nextIndex = findNextOccupied(nextIndex + 1);
|
||||||
return new SimpleEntry<>(key, value) {
|
return new SimpleEntry<>(key, value) {
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package org.dreeam.leaf.util.map;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public final class AttributeInstanceSet extends AbstractCollection<AttributeInstance> implements Set<AttributeInstance> {
|
||||||
|
public final IntSet inner;
|
||||||
|
public final AttributeInstanceArrayMap map;
|
||||||
|
|
||||||
|
public AttributeInstanceSet(AttributeInstanceArrayMap map) {
|
||||||
|
this.map = map;
|
||||||
|
inner = new IntArraySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(AttributeInstance instance) {
|
||||||
|
return inner.add(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return o instanceof AttributeInstance instance && inner.remove(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Iterator<AttributeInstance> iterator() {
|
||||||
|
return new CloneIterator(inner.toIntArray(), map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return inner.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return inner.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
inner.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
if (o instanceof AttributeInstance instance) {
|
||||||
|
return inner.contains(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeInstance @NotNull [] toArray() {
|
||||||
|
int[] innerClone = inner.toIntArray();
|
||||||
|
AttributeInstance[] arr = new AttributeInstance[innerClone.length];
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] = map.getInstance(innerClone[i]);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
@Override
|
||||||
|
public <T> T @NotNull [] toArray(T[] a) {
|
||||||
|
if (a == null || (a.getClass() == AttributeInstance[].class && a.length == 0)) {
|
||||||
|
return (T[]) toArray();
|
||||||
|
}
|
||||||
|
if (a.length < size()) {
|
||||||
|
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size());
|
||||||
|
}
|
||||||
|
System.arraycopy((T[]) toArray(), 0, a, 0, size());
|
||||||
|
if (a.length > size()) {
|
||||||
|
a[size()] = null;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CloneIterator implements Iterator<AttributeInstance> {
|
||||||
|
private final int[] array;
|
||||||
|
private int index = 0;
|
||||||
|
private final AttributeInstanceArrayMap map;
|
||||||
|
|
||||||
|
CloneIterator(int[] array, AttributeInstanceArrayMap map) {
|
||||||
|
this.array = array;
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < array.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeInstance next() {
|
||||||
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
|
return map.getInstance(array[index++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) return true;
|
||||||
|
if (!(o instanceof Set<?> s)) return false;
|
||||||
|
if (s.size() != size()) return false;
|
||||||
|
return containsAll(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user