9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-30 20:39:21 +00:00

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
This commit is contained in:
hayanesuru
2025-12-11 07:00:14 +09:00
committed by GitHub
parent 1144cbce27
commit f2682d84a6
42 changed files with 1023 additions and 860 deletions

View File

@@ -13,18 +13,18 @@ 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/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index 7dd8c1c8e27410854ce1ee90defc607c2710b5a2..0ac398b8b10aae5e67a797b2991c66874003f282 100644
index be0fceea10755bb1a0a0cea4749f45e122bfa771..a65ba1712d55d23abdbb192f13ffb972be308e84 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -14,9 +14,11 @@ import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
public class AttributeMap {
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new Object2ObjectOpenHashMap<>();
- public final Map<Holder<Attribute>, AttributeInstance> attributes = new Object2ObjectOpenHashMap<>();
- private final Set<AttributeInstance> attributesToSync = new ObjectOpenHashSet<>();
- private final Set<AttributeInstance> attributesToUpdate = new ObjectOpenHashSet<>();
+ // Gale start - Lithium - replace AI attributes with optimized collections
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
+ 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

View File

@@ -9,19 +9,33 @@ Original license: MIT
Original project: https://github.com/PurpurMC/Purpur
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index d605c4da4475fdc47a6d0c90fbca2713fc9d8fef..0dee18df07c979da6125a4e7a955343e44d67ac2 100644
index db16e1e66807a3dbbff8200d93734c9b38140e6f..61a9d3012eb7a8bfdd3867606cd1b144f6170de2 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -225,6 +225,8 @@ public class ServerEntity {
@@ -195,11 +195,12 @@ public class ServerEntity {
long l1 = this.positionCodec.encodeY(vec3);
long l2 = this.positionCodec.encodeZ(vec3);
boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L;
+ boolean onGroundChanged = this.wasOnGround != this.entity.onGround(); // Purpur - Dont send useless entity packets
if (this.forceStateResync || this.entity.getRequiresPrecisePosition() // Paper - fix desync when a player is added to the tracker
|| flag5
|| this.teleportDelay > 400
|| this.wasRiding
- || this.wasOnGround != this.entity.onGround()) {
+ || onGroundChanged) { // Purpur - Dont send useless entity packets
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
@@ -225,6 +226,8 @@ public class ServerEntity {
}
// Gale end - Airplane - better checking for useless move packets
+ if (org.dreeam.leaf.config.modules.opt.ReduceUselessPackets.reduceUselessEntityMovePackets && isUselessMoveEntityPacket(packet)) packet = null; // Purpur - Dont send useless entity packets
+ if (org.dreeam.leaf.config.modules.opt.ReduceUselessPackets.reduceUselessEntityMovePackets && !onGroundChanged && isUselessMoveEntityPacket(packet)) packet = null; // Purpur - Dont send useless entity packets
+
if (this.entity.hasImpulse || this.trackDelta || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) {
Vec3 deltaMovement = this.entity.getDeltaMovement();
if (deltaMovement != this.lastSentMovement) { // SparklyPaper start - skip distanceToSqr call in ServerEntity#sendChanges if the delta movement hasn't changed
@@ -308,6 +310,21 @@ public class ServerEntity {
@@ -308,6 +311,21 @@ public class ServerEntity {
);
}

View File

@@ -0,0 +1,273 @@
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) {

View File

@@ -12,7 +12,7 @@ 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/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 6055beca9a3c24a8af06824662d3040d0c017ad4..3d782ffd7170b0ff0b9ca5d7987e92026921426b 100644
index 787c2ef42d7b067900d56d5bf5876fe0f4c9e20b..30704985f33a04010f47e20214235857b03a3910 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2828,6 +2828,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -9,7 +9,7 @@ This patch didn't cahce SectionPos or BlockPos to chunkKey, since they are mutab
The JMH benchmark of this patch can be found in SunBox's `CacheChunkKey`
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 356ec20eff799aa12ed6b4f9e54e8721c50a0068..499cad369242f9ad724b3251538d62d8dc8d2ec8 100644
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..288a3eb57f3431dd624ad8a4b08684563abbc5ad 100644
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
@@ -127,7 +127,7 @@ public final class NearbyPlayers {
@@ -119,10 +119,10 @@ index 50bc5b940812432bc472e5b272582efb8bbfc7a7..d55677f66ec7e2d4f2a96556f874e719
// Paper end - rewrite chunk system
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index d43e2d207e143f35536626c0f3de16dd295b5866..175c4ab639f1516de06e3a16e89e779c59754e1c 100644
index c73d4ca35ad35b21a9df283a18928d7738c172d0..08a6a3c3eb6e270ec3d02e31b26d5fa547bb66b2 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -508,7 +508,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -507,7 +507,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public final void moonrise$markChunkForPlayerTicking(final LevelChunk chunk) {
final ChunkPos pos = chunk.getPos();
@@ -131,7 +131,7 @@ index d43e2d207e143f35536626c0f3de16dd295b5866..175c4ab639f1516de06e3a16e89e779c
return;
}
@@ -2652,7 +2652,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2650,7 +2650,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public boolean areEntitiesActuallyLoadedAndTicking(ChunkPos chunkPos) {
// Paper start - rewrite chunk system
@@ -140,7 +140,7 @@ index d43e2d207e143f35536626c0f3de16dd295b5866..175c4ab639f1516de06e3a16e89e779c
return chunkHolder != null && chunkHolder.isEntityTickingReady();
// Paper end - rewrite chunk system
}
@@ -2667,7 +2667,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2665,7 +2665,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public boolean canSpawnEntitiesInChunk(ChunkPos chunkPos) {
// Paper start - rewrite chunk system

View File

@@ -6,7 +6,7 @@ Subject: [PATCH] Only player pushable
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
index 3d782ffd7170b0ff0b9ca5d7987e92026921426b..f69512541e1f72c6234ab29cb42cccddc95538eb 100644
index 30704985f33a04010f47e20214235857b03a3910..58f6fe72999bd6255e1ca815ad66a98e9358e306 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3696,7 +3696,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] optimize mob despawn
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 175c4ab639f1516de06e3a16e89e779c59754e1c..073dec29d48b5ab8dd379a1e66a0de6ef101ca1f 100644
index 3a4c9f215354b5ce96e301a17dd2d9ca0d4d1e91..cf9231c8b266dcb11a5b31db99a3a98b42423a65 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -797,13 +797,19 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -796,13 +796,19 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
@@ -29,7 +29,7 @@ index 175c4ab639f1516de06e3a16e89e779c59754e1c..073dec29d48b5ab8dd379a1e66a0de6e
if (true) { // Paper - rewrite chunk system
Entity vehicle = entity.getVehicle();
if (vehicle != null) {
@@ -945,6 +951,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -943,6 +949,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Async chunk sending
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
index f34b8012d48ce1b69c1a1529d7ae46b624785ffa..525f29f3ecd7eb12e3d7447898005d3a6d62c093 100644
index bdc1200ef5317fdaf58973bf580b0a672aee800f..112ef27a64da2f1538a2223704cd4da20ce45ffd 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -448,7 +448,15 @@ public final class RegionizedPlayerChunkLoader {
@@ -440,7 +440,15 @@ public final class RegionizedPlayerChunkLoader {
// Note: drop isAlive() check so that chunks properly unload client-side when the player dies
((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
.getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$removeReceivedChunk(this.player);

View File

@@ -112,7 +112,7 @@ index 582e012222123e5001c34153f2ee1ab1d08935fd..e90201f4d878874e380d12d82220fc6c
List<org.bukkit.block.BlockState> states = new java.util.ArrayList<>(level.capturedBlockStates.values());
level.capturedBlockStates.clear();
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f8dd55a4a5a93788e0690b1a6a6b87d12cf26571..51efe9aadb377c35d6ed2b7eadead3c9e1c745f8 100644
index 0baed29caff0e523676e499ff63db7925a947a0a..96a5887da3697f0729cce2819dbb8690ee7eda78 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -290,6 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -271,11 +271,11 @@ index f8dd55a4a5a93788e0690b1a6a6b87d12cf26571..51efe9aadb377c35d6ed2b7eadead3c9
+ // Leaf end - SparklyPaper - parallel world ticking
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) { org.dreeam.leaf.async.tracker.AsyncTracker.onTickEnd(this); } // Leaf - Multithreaded tracker
@@ -1817,6 +1868,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
level.trackerTask = null;
}
// Leaf end - Multithreaded tracker
this.tickConnection();
@@ -1811,6 +1862,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
newLevels.remove(level.dimension());
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) level.tickExecutor.shutdown(); // Leaf - SparklyPaper - parallel world ticking (We remove it in here instead of ServerLevel.close() because ServerLevel.close() is never called!)
this.levels = Collections.unmodifiableMap(newLevels);
}
@@ -379,7 +379,7 @@ index eaaa66c4d86d4ebda0acf8f1dbe8ecb55aa28285..908cd08e33fed1c4cd4bd34c3e63cbbe
continue;
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064304f7c7d 100644
index cf9231c8b266dcb11a5b31db99a3a98b42423a65..15976e209ac24abf7f9aac5009dfd85a6b03fd2f 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -180,7 +180,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -403,7 +403,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
// CraftBukkit start
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
@@ -680,7 +685,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -679,7 +684,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.sleepStatus = new SleepStatus();
this.gameEventDispatcher = new GameEventDispatcher(this);
this.randomSequences = Objects.requireNonNullElseGet(randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.TYPE));
@@ -412,7 +412,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
// Paper start - rewrite chunk system
this.moonrise$setEntityLookup(new ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup((ServerLevel)(Object)this, ((ServerLevel)(Object)this).new EntityCallbacks()));
this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this);
@@ -698,6 +703,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -697,6 +702,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
this.realPlayers = Lists.newArrayList(); // Leaves - skip
@@ -428,7 +428,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
}
// Paper start
@@ -730,8 +744,127 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -729,8 +743,127 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.structureManager;
}
@@ -556,7 +556,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
TickRateManager tickRateManager = this.tickRateManager();
boolean runsNormally = tickRateManager.runsNormally();
if (runsNormally) {
@@ -739,6 +872,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -738,6 +871,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.advanceWeatherCycle();
}
@@ -569,7 +569,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) { // Purpur - Config for skipping night
// Paper start - create time skip event - move up calculations
@@ -831,6 +970,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -830,6 +969,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
// Paper end - Prevent block entity and entity crashes
}
@@ -577,7 +577,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
this.moonrise$midTickTasks(); // Paper - rewrite chunk system
// Gale end - Airplane - remove lambda from ticking guard - copied from guardEntityTick
}
@@ -1311,7 +1451,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1309,7 +1449,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
fluidState.tick(this, pos, blockState);
}
// Paper start - rewrite chunk system
@@ -589,7 +589,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks();
}
// Paper end - rewrite chunk system
@@ -1324,7 +1467,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1322,7 +1465,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
blockState.tick(this, pos, this.random);
}
// Paper start - rewrite chunk system
@@ -601,7 +601,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks();
}
// Paper end - rewrite chunk system
@@ -1591,6 +1737,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1589,6 +1735,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
private void addPlayer(ServerPlayer player) {
@@ -609,7 +609,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
Entity entity = this.getEntity(player.getUUID());
if (entity != null) {
LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID());
@@ -1603,7 +1750,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1601,7 +1748,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// CraftBukkit start
private boolean addEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {

View File

@@ -6,7 +6,7 @@ Subject: [PATCH] SparklyPaper: Track each world MSPT
Original project: https://github.com/SparklyPower/SparklyPaper
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 51efe9aadb377c35d6ed2b7eadead3c9e1c745f8..d3c6f7f78d895cca4abe1da79abb595c51449afc 100644
index 96a5887da3697f0729cce2819dbb8690ee7eda78..e01c5b8a20e5e852021ec7db72a690145fcad86c 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1686,7 +1686,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -27,10 +27,10 @@ index 51efe9aadb377c35d6ed2b7eadead3c9e1c745f8..d3c6f7f78d895cca4abe1da79abb595c
CrashReport crashReport = CrashReport.forThrowable(levelTickingException, "Exception ticking world");
serverLevel.fillReportDetails(crashReport);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index e0bd79a371e2c2d370518ae1b9c31064304f7c7d..8866cf1a431a8fc2188d05b3e1365ad6e21af52f 100644
index fdeadc168caa4bedd11927e361b900cfc6312e53..6b63ffcb6344ed2d7aaf02d1026bbf27eff384e5 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -573,6 +573,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -572,6 +572,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
// Paper end - chunk tick iteration

View File

@@ -9,10 +9,10 @@ Leaf: ~48ms (-36%)
This should help drastically on the farms that use actively changing fluids.
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 8866cf1a431a8fc2188d05b3e1365ad6e21af52f..e49cef515a605311ba6afca4101ef75e5c8378eb 100644
index 229cd5a61ed3668e0991ae0c4657d7ea578fedef..c43cd28c0d0870f812d136cfeba884bea89b277f 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1450,6 +1450,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1448,6 +1448,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.emptyTime = 0;
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Micro optimizations for random tick
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index e49cef515a605311ba6afca4101ef75e5c8378eb..29158e9cb73aa6670c6a0fa494cc8011b7dfaa95 100644
index c43cd28c0d0870f812d136cfeba884bea89b277f..bec2b39c1975da51302f6a395aa03269773e3007 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1048,7 +1048,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1046,7 +1046,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper start - optimise random ticking
private void optimiseRandomTick(final LevelChunk chunk, final int tickSpeed) {
final LevelChunkSection[] sections = chunk.getSections();
@@ -17,7 +17,7 @@ index e49cef515a605311ba6afca4101ef75e5c8378eb..29158e9cb73aa6670c6a0fa494cc8011
final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Leaf - Faster random generator - upcasting
final boolean doubleTickFluids = !ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC224294();
@@ -1057,41 +1057,41 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1055,41 +1055,41 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
final int offsetZ = cpos.z << 4;
for (int sectionIndex = 0, sectionsLen = sections.length; sectionIndex < sectionsLen; sectionIndex++) {

View File

@@ -22,10 +22,10 @@ index 56fd1ed7ccaf96e7eedea60fbdbf7f934939d563..d2f522ea6d0a209496848af073c9af1c
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d3c6f7f78d895cca4abe1da79abb595c51449afc..7306a3273adf5bfa8ebdec42b7aedf3656fb5850 100644
index e01c5b8a20e5e852021ec7db72a690145fcad86c..4fbffd06d23860df912ff216446699e0ab5eb00b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1802,6 +1802,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1801,6 +1801,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(tickCount); // Leaves - protocol

View File

@@ -18,7 +18,7 @@ index b7e5c7b681b2775367f707825b132ce6e00e570a..9f4bed1c2211f58ceda837385facf361
}
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index f69512541e1f72c6234ab29cb42cccddc95538eb..4476a43011d1f8e7be6fc62410fef80c3e4f945a 100644
index 58f6fe72999bd6255e1ca815ad66a98e9358e306..4ff228b64e39e8b0f6406e2d069f20d7b45d98df 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -4169,9 +4169,9 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -100,7 +100,7 @@ index 66ae0b340c7e9ebccfeaee786577e27916ace38c..b7cd9b286e7392c3fd619c7ba9e04907
} else if (!flag) {
this.applyGravity();
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 4476a43011d1f8e7be6fc62410fef80c3e4f945a..de22fce4f98a600a26d1d78f3bbc1c5f5a8b5bfa 100644
index 4ff228b64e39e8b0f6406e2d069f20d7b45d98df..463bc12b25c2beb9a31959c92d5c85edaf963771 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -463,7 +463,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -18,7 +18,7 @@ Generally faster than the non-async approach
iterate over all entities, get their chunk, and increment the count
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 5c369b3d94e369c3f240821ad90b9d96223f24ca..9803c395fce103cb7bc746f43a017ff9ed99728c 100644
index 5c8a603e5800e1cc282d899e2a3d6b556295e13c..2dca1ceb886537ff96d0834844429e1c7b97bd79 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -278,6 +278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -188,10 +188,10 @@ index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e3
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 29158e9cb73aa6670c6a0fa494cc8011b7dfaa95..4a21cafb1895236744693cf924843fa82428ce41 100644
index bec2b39c1975da51302f6a395aa03269773e3007..eac2b9eb713d8a0a0b1682986745ae722262547e 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1098,6 +1098,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1096,6 +1096,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking
public final org.dreeam.leaf.world.DespawnMap despawnMap = new org.dreeam.leaf.world.DespawnMap(paperConfig()); // Leaf - optimize despawn

View File

@@ -24,10 +24,10 @@ index f5b58c181726536bedabd4b6f64769e312ef4257..2847aa24cca82b1c66b69600ddcb5dbd
this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies);
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 4a21cafb1895236744693cf924843fa82428ce41..25a86714b7c15ba3a0b4cd0290a1dae84a030947 100644
index eac2b9eb713d8a0a0b1682986745ae722262547e..147ff83b0fd851f57a8ad4e79487b8eef0196970 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1099,6 +1099,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1097,6 +1097,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final org.dreeam.leaf.world.DespawnMap despawnMap = new org.dreeam.leaf.world.DespawnMap(paperConfig()); // Leaf - optimize despawn
public final org.dreeam.leaf.world.NatureSpawnChunkMap natureSpawnChunkMap = new org.dreeam.leaf.world.NatureSpawnChunkMap(); // Leaf - optimize mob spawning

View File

@@ -117,10 +117,10 @@ index 2847aa24cca82b1c66b69600ddcb5dbdadec5b9d..bd4c98e9ec41a2bd608e2e2245c503be
if (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 25a86714b7c15ba3a0b4cd0290a1dae84a030947..39d082abfd1ea4351a3d2ef1a703b720948cc418 100644
index 147ff83b0fd851f57a8ad4e79487b8eef0196970..de61388b0bf8b1fcb33cec5564922be29224d075 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1502,13 +1502,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1500,13 +1500,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - log detailed entity tick information
public void tickNonPassenger(Entity entity) {
@@ -134,7 +134,7 @@ index 25a86714b7c15ba3a0b4cd0290a1dae84a030947..39d082abfd1ea4351a3d2ef1a703b720
entity.setOldPosAndRot();
entity.tickCount++;
entity.totalEntityAge++; // Paper - age-like counter for all entities
@@ -1521,13 +1515,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1519,13 +1513,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
for (Entity entity1 : entity.getPassengers()) {
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
}

View File

@@ -6,7 +6,7 @@ Subject: [PATCH] Fix Paper config fixClimbingBypassingCrammingRule
Waiting for Paper#12793
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index de22fce4f98a600a26d1d78f3bbc1c5f5a8b5bfa..f62898ec36cea977d67da087bf741fb508b1f88d 100644
index 463bc12b25c2beb9a31959c92d5c85edaf963771..7389635bcd6b1d854341bb17176d42a43d539fdc 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3846,7 +3846,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -86,7 +86,7 @@ index 7f508c50e451a0689218cd36e6ac993f87092c04..a6c1f450f32fa688b102140963fd5bfb
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index f62898ec36cea977d67da087bf741fb508b1f88d..a267b5bcf03b1186465adf56d49d5ea2423652f7 100644
index 7389635bcd6b1d854341bb17176d42a43d539fdc..8223c0e33f58247b892f70e6bb33a56a57e94e8b 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2279,7 +2279,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -8,7 +8,7 @@ Related MC issue: https://bugs.mojang.com/browse/MC/issues/MC-298464
Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index a267b5bcf03b1186465adf56d49d5ea2423652f7..04b9b2d744242e76cc390c2c31e01310419ed356 100644
index 8223c0e33f58247b892f70e6bb33a56a57e94e8b..46f8049b463802133f1ee537404a1d3ab63b2b85 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -750,6 +750,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -241,7 +241,7 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..94c7ae9535a235abb8fddf0ca6578dfa
+ }
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 04b9b2d744242e76cc390c2c31e01310419ed356..dc21247dbf62a192c622fe35ba8255c2c4af5062 100644
index 46f8049b463802133f1ee537404a1d3ab63b2b85..cbe9949a2b3223a74ae4141b5148badf65502bde 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -431,7 +431,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -18,7 +18,7 @@ index 86a694b94045b47f6e98c480645f75738b8a052c..bb9554463a6983ab98323f4dd665c7c1
// Purpur end - Configurable entity base attributes
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index dc21247dbf62a192c622fe35ba8255c2c4af5062..904de921ac626bf2f6a82069b02620e899f19d0a 100644
index cbe9949a2b3223a74ae4141b5148badf65502bde..27fc48b3d0ed62587bdc540bf32fa72f6c6c10ef 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2857,6 +2857,16 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -28,10 +28,10 @@ index 340d5487fa778277b9560250271c5143d80d9987..99543330da85ddecd91c954c8aa386c8
public boolean isCommandBlockEnabled() {
return true;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 7306a3273adf5bfa8ebdec42b7aedf3656fb5850..540a1af9f4e0cf69ff987105a34d92a35e669fb0 100644
index 4fbffd06d23860df912ff216446699e0ab5eb00b..8fc7e0d3ae4a3056c0e9e5e19af4261cfe4adfb0 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2061,6 +2061,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2055,6 +2055,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public abstract boolean isEpollEnabled();

View File

@@ -117,10 +117,10 @@ index 0000000000000000000000000000000000000000..5f5cdfc538ba9aa6666c019df6706015
+ }
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 39d082abfd1ea4351a3d2ef1a703b720948cc418..e7cf5f336245821db444597424341789c7a6a50a 100644
index 907650b743d556d50c59004d2fd0b5f7f6576045..288ede03a3ae4c5c99250d4ef1a3cf6bdc0a354d 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -942,6 +942,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -941,6 +941,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
@@ -128,7 +128,7 @@ index 39d082abfd1ea4351a3d2ef1a703b720948cc418..e7cf5f336245821db444597424341789
if (org.dreeam.leaf.config.modules.opt.OptimizeDespawn.enabled && tickRateManager.runsNormally()) { despawnMap.tick(this, this.entityTickList); } // Leaf - optimize despawn
this.entityTickList
@@ -3085,4 +3086,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -3083,4 +3084,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.lagCompensationTick = (System.nanoTime() - MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
}
// Paper end - lag compensation

View File

@@ -70,10 +70,10 @@ index 5f5cdfc538ba9aa6666c019df6706015234d7bae..2dfec8f6d0fe833e5f06cf2165ae14bf
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index e7cf5f336245821db444597424341789c7a6a50a..f7a716404f5e694d4a9331073f8349ff3f3f67ad 100644
index 373ccb50eee5aa2985fd96f731e7f8b930ce0586..03986a9b496a0cd14b6d80ef58f8bfbe3440cd19 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -942,7 +942,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -941,7 +941,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR

View File

@@ -19,7 +19,7 @@ index ea137958c70f80349041cd27d1503f7b8def2a69..e8cd433ca5792b87a1763ccb14777115
return this.inBlockState;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 904de921ac626bf2f6a82069b02620e899f19d0a..b35ef147ee813778721816e89b95b7a43e6c310e 100644
index 27fc48b3d0ed62587bdc540bf32fa72f6c6c10ef..b6a1f45d27c2639018667ccee36a7beaf9f002e8 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2221,10 +2221,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -113,7 +113,7 @@ index 841d63333f55701357ed4dfd0d1be3faa5eeb3b1..ecfd852e64ffdb9e5eaebe7b1eeef4e9
boolean flag = dimensions.width() <= 4.0F && dimensions.height() <= 4.0F;
if (!this.level.isClientSide
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index b35ef147ee813778721816e89b95b7a43e6c310e..4277c798ceee0ca329d332f8d1354dde312f0c29 100644
index b6a1f45d27c2639018667ccee36a7beaf9f002e8..1928293100abba5d3765842755c8e9e812dc64bf 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -464,7 +464,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -42,7 +42,7 @@ index ecfd852e64ffdb9e5eaebe7b1eeef4e99dda3b15..4689764a580d7dca468cdfa2b0fef7e7
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 4277c798ceee0ca329d332f8d1354dde312f0c29..efbad651cd6fa1ea73265761f8e91f84c07316d5 100644
index 1928293100abba5d3765842755c8e9e812dc64bf..9082d41be5f390c9bd4d7afe4079e1309cd2a7c3 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3091,7 +3091,11 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] cache collision list
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index f7a716404f5e694d4a9331073f8349ff3f3f67ad..f846498b87ba751dbd4024424c0dd4f8496309b7 100644
index 03986a9b496a0cd14b6d80ef58f8bfbe3440cd19..b0192fe9359ff61d9f29d65768b1af9eeee91bde 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1101,6 +1101,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1099,6 +1099,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final org.dreeam.leaf.world.DespawnMap despawnMap = new org.dreeam.leaf.world.DespawnMap(paperConfig()); // Leaf - optimize despawn
public final org.dreeam.leaf.world.NatureSpawnChunkMap natureSpawnChunkMap = new org.dreeam.leaf.world.NatureSpawnChunkMap(); // Leaf - optimize mob spawning
public final org.dreeam.leaf.world.RandomTickSystem randomTickSystem = new org.dreeam.leaf.world.RandomTickSystem(); // Leaf - optimize random tick

View File

@@ -6,10 +6,10 @@ Subject: [PATCH] fast bit radix sort
Co-authored-by: Taiyou06 <kaandindar21@gmail.com>
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index f846498b87ba751dbd4024424c0dd4f8496309b7..e2799c3731d2c92e9ba9e87af36cbea944efe169 100644
index b0192fe9359ff61d9f29d65768b1af9eeee91bde..99f3589d5d051ca613c325ac566d52d30a813271 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1102,6 +1102,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1100,6 +1100,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final org.dreeam.leaf.world.NatureSpawnChunkMap natureSpawnChunkMap = new org.dreeam.leaf.world.NatureSpawnChunkMap(); // Leaf - optimize mob spawning
public final org.dreeam.leaf.world.RandomTickSystem randomTickSystem = new org.dreeam.leaf.world.RandomTickSystem(); // Leaf - optimize random tick
public final org.dreeam.leaf.world.EntityCollisionCache entityCollisionCache = new org.dreeam.leaf.world.EntityCollisionCache(); // Leaf - cache collision list

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] optimize tickEffects
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index efbad651cd6fa1ea73265761f8e91f84c07316d5..dc5cbabe8909cedf79e915a6129bfe414d69d106 100644
index 9082d41be5f390c9bd4d7afe4079e1309cd2a7c3..94fec2456206d0d5ec868ce220631c7ff4325218 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -951,6 +951,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -35,10 +35,10 @@ index 45093451fb25ae3bb1e57d2e53c49a1ae666e31e..c228135032b5f74fd1ec96a2cf52aa3e
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index e2799c3731d2c92e9ba9e87af36cbea944efe169..a59ecf85da0df09256d0951266d979206e713e01 100644
index 99f3589d5d051ca613c325ac566d52d30a813271..898c3b4522c306ba2c42d70a6281b130ce5d9678 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1185,7 +1185,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1183,7 +1183,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// We only need to check blocks that are taller than the minimum step height
if (org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep > 0 && layersValue >= org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep) {
int layersValueMin = layersValue - org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep;

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Only update frozen ticks if changed
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index dc5cbabe8909cedf79e915a6129bfe414d69d106..67c70e8d1e44c8b9ee010f89c527fff2c5cff1f6 100644
index 94fec2456206d0d5ec868ce220631c7ff4325218..a2102e3739b19b99da81cc7a99ed2c8f01c46927 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3709,7 +3709,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin

View File

@@ -1,11 +1,14 @@
package org.dreeam.leaf.async.tracker;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.dreeam.leaf.async.FixedThreadExecutor;
@@ -26,7 +29,11 @@ public final class AsyncTracker {
THREAD_NAME
) : null;
private AsyncTracker() {
private Future<TrackerCtx>[] fut;
private final TrackerCtx local;
public AsyncTracker(ServerLevel world) {
this.local = new TrackerCtx(world);
}
public static void init() {
@@ -35,7 +42,11 @@ public final class AsyncTracker {
}
}
public static void tick(ServerLevel world) {
public TrackerCtx ctx() {
return this.local;
}
public void tick(ServerLevel world) {
handlePlayerVelocity(world);
ServerEntityLookup entityLookup = (ServerEntityLookup) world.moonrise$getEntityLookup();
ca.spottedleaf.moonrise.common.list.ReferenceList<Entity> trackerEntities = entityLookup.trackerEntities;
@@ -54,7 +65,7 @@ public final class AsyncTracker {
futures[i] = TRACKER_EXECUTOR.submitOrRun(new TrackerTask(world, slices[i]));
}
TRACKER_EXECUTOR.unpack();
world.trackerTask = futures;
this.fut = futures;
}
private static void handlePlayerVelocity(ServerLevel world) {
@@ -85,8 +96,9 @@ public final class AsyncTracker {
}
}
public static void onEntitiesTickEnd(ServerLevel world) {
Future<TrackerCtx>[] task = world.trackerTask;
public void onEntitiesTickEnd() {
Future<TrackerCtx>[] task = this.fut;
TrackerCtx local = this.local;
if (task == null) {
return;
}
@@ -95,26 +107,36 @@ public final class AsyncTracker {
return;
}
}
handle(world, task, false);
this.fut = null;
handle(task, local);
local.reset();
// for (ServerPlayer player : world.players()) {
// player.connection.connection.flushChannel();
// }
}
public static void onTickEnd(MinecraftServer server) {
for (ServerLevel world : server.getAllLevels()) {
Future<TrackerCtx>[] task = world.trackerTask;
if (task != null) {
handle(world, task, false);
}
}
public void onTickEnd() {
Future<TrackerCtx>[] task = this.fut;
TrackerCtx local = this.local;
this.fut = null;
handle(task, local);
local.reset();
}
private static void handle(ServerLevel world, Future<TrackerCtx>[] futures, boolean flush) {
private static void handle(Future<TrackerCtx>[] futures, TrackerCtx local) {
try {
TrackerCtx ctx = futures[0].get();
for (int i = 1; i < futures.length; i++) {
ctx.join(futures[i].get());
if (futures == null) {
local.handle(new Object2ObjectOpenHashMap[0]);
} else {
TrackerCtx ctx = futures[0].get();
@SuppressWarnings("unchecked")
Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>>[] packets = new Object2ObjectOpenHashMap[futures.length];
packets[futures.length - 1] = ctx.join(local);
for (int i = 1; i < futures.length; i++) {
packets[i - 1] = ctx.join(futures[i].get());
}
ctx.handle(packets);
}
world.trackerTask = null;
ctx.handle(flush);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {

View File

@@ -1,64 +1,82 @@
package org.dreeam.leaf.async.tracker;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import io.papermc.paper.event.player.PlayerTrackEntityEvent;
import io.papermc.paper.event.player.PlayerUntrackEntityEvent;
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import net.minecraft.core.Holder;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBundlePacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeMap;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.MapItem;
import net.minecraft.world.level.saveddata.maps.MapId;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.dreeam.leaf.util.map.AttributeInstanceArrayMap;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public final class TrackerCtx {
private final Reference2ReferenceOpenHashMap<ServerPlayerConnection, ReferenceArrayList<Packet<? super ClientGamePacketListener>>> packets;
@SuppressWarnings("unchecked")
private static final Object2ObjectFunction<ServerPlayerConnection, ObjectArrayList<Packet<?>>> INIT_PACKET_LIST = x -> ObjectArrayList.wrap(new Packet[16], 0);
private final Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> packets = new Object2ObjectOpenHashMap<>();
private final ServerLevel world;
private final ObjectArrayList<ItemFrame> bukkitItemFrames = new ObjectArrayList<>();
private final ObjectArrayList<ItemFrame> itemFrames = new ObjectArrayList<>();
private final ObjectArrayList<BossEvent> witherBosses = new ObjectArrayList<>();
private final ObjectArrayList<PaperStopSeen> paperStopSeen = new ObjectArrayList<>();
private final ObjectArrayList<PaperStartSeen> paperStartSeen = new ObjectArrayList<>();
private final ObjectArrayList<Entity> pluginEntity = new ObjectArrayList<>();
private final ObjectArrayList<StopSeen> stopSeen = new ObjectArrayList<>();
private final ObjectArrayList<StartSeen> startSeen = new ObjectArrayList<>();
private final ObjectArrayList<ChunkMap.TrackedEntity> resync = new ObjectArrayList<>();
private final ObjectArrayList<ChunkMap.TrackedEntity> pluginEntity = new ObjectArrayList<>();
private final ObjectArrayList<ChunkMap.TrackedEntity> syncAttributes = new ObjectArrayList<>();
private record BossEvent(WitherBoss witherBoss, ObjectArrayList<ServerPlayer> add, ObjectArrayList<ServerPlayer> remove) {}
private record PaperStopSeen(Entity e, ObjectArrayList<ServerPlayerConnection> q) {}
private record PaperStartSeen(Entity e, ObjectArrayList<ServerPlayerConnection> q) {}
private record BossEvent(WitherBoss witherBoss,
ObjectArrayList<ServerPlayer> add,
ObjectArrayList<ServerPlayer> remove) {
}
private record StopSeen(Entity e, ObjectArrayList<ServerPlayer> q) {
}
private record StartSeen(Entity e,
ObjectArrayList<ServerPlayerConnection> q) {
}
public TrackerCtx(ServerLevel world) {
this.packets = new Reference2ReferenceOpenHashMap<>();
this.world = world;
}
public void stopSeenByPlayer(ServerPlayerConnection connection, Entity entity) {
if (PlayerUntrackEntityEvent.getHandlerList().getRegisteredListeners().length != 0) {
if (paperStopSeen.isEmpty()) {
paperStopSeen.add(new PaperStopSeen(entity, new ObjectArrayList<>()));
}
if (!paperStopSeen.getLast().e.equals(entity)) {
paperStopSeen.add(new PaperStopSeen(entity, new ObjectArrayList<>()));
}
paperStopSeen.getLast().q.add(connection);
if (stopSeen.isEmpty() || !stopSeen.getLast().e.equals(entity)) {
stopSeen.add(new StopSeen(entity, new ObjectArrayList<>()));
}
ObjectArrayList<ServerPlayer> players = stopSeen.getLast().q;
if (players.isEmpty() || players.getLast() != connection.getPlayer()) {
players.add(connection.getPlayer());
}
if (entity instanceof WitherBoss witherBoss) {
if (witherBosses.isEmpty()) {
witherBosses.add(new BossEvent(witherBoss, new ObjectArrayList<>(), new ObjectArrayList<>()));
}
if (!witherBosses.getLast().witherBoss.equals(witherBoss)) {
if (witherBosses.isEmpty() || !witherBosses.getLast().witherBoss.equals(witherBoss)) {
witherBosses.add(new BossEvent(witherBoss, new ObjectArrayList<>(), new ObjectArrayList<>()));
}
witherBosses.getLast().remove.add(connection.getPlayer());
@@ -66,165 +84,284 @@ public final class TrackerCtx {
}
public void startSeenByPlayer(ServerPlayerConnection connection, Entity entity) {
if (PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length != 0) {
if (paperStartSeen.isEmpty()) {
paperStartSeen.add(new PaperStartSeen(entity, new ObjectArrayList<>()));
}
if (!paperStartSeen.getLast().e.equals(entity)) {
paperStartSeen.add(new PaperStartSeen(entity, new ObjectArrayList<>()));
}
paperStartSeen.getLast().q.add(connection);
if (startSeen.isEmpty() || !startSeen.getLast().e.equals(entity)) {
startSeen.add(new StartSeen(entity, new ObjectArrayList<>()));
}
startSeen.getLast().q.add(connection);
if (entity instanceof WitherBoss witherBoss) {
if (witherBosses.isEmpty()) {
witherBosses.add(new BossEvent(witherBoss, new ObjectArrayList<>(), new ObjectArrayList<>()));
}
if (!witherBosses.getLast().witherBoss.equals(witherBoss)) {
if (witherBosses.isEmpty() || !witherBosses.getLast().witherBoss.equals(witherBoss)) {
witherBosses.add(new BossEvent(witherBoss, new ObjectArrayList<>(), new ObjectArrayList<>()));
}
witherBosses.getLast().add.add(connection.getPlayer());
}
}
public void updateItemFrame(ItemFrame itemFrame) {
bukkitItemFrames.add(itemFrame);
public void forceResync(ChunkMap.TrackedEntity entity) {
resync.add(entity);
}
public void citizensEntity(Entity entity) {
public void updateItemFrame(ItemFrame itemFrame) {
itemFrames.add(itemFrame);
}
public void citizensEntity(ChunkMap.TrackedEntity entity) {
pluginEntity.add(entity);
}
public void send(ServerPlayerConnection connection, Packet<? super ClientGamePacketListener> packet) {
packets.computeIfAbsent(connection, x -> ReferenceArrayList.wrap(new Packet[16], 0)).add(packet);
public void send(ServerPlayerConnection connection, Packet<?> packet) {
packets.computeIfAbsent(connection, INIT_PACKET_LIST).add(packet);
}
void join(TrackerCtx other) {
bukkitItemFrames.addAll(other.bukkitItemFrames);
paperStopSeen.addAll(other.paperStopSeen);
paperStartSeen.addAll(other.paperStartSeen);
pluginEntity.addAll(other.pluginEntity);
if (other.packets.isEmpty()) {
return;
}
var iterator = other.packets.reference2ReferenceEntrySet().fastIterator();
while (iterator.hasNext()) {
var entry = iterator.next();
packets.computeIfAbsent(entry.getKey(), x -> ReferenceArrayList.wrap(new Packet[0])).addAll(entry.getValue());
public void broadcast(ChunkMap.TrackedEntity entity, Packet<?> packet) {
for (ServerPlayerConnection serverPlayerConnection : entity.seenBy()) {
send(serverPlayerConnection, packet);
}
}
void handle(boolean flush) {
if (!pluginEntity.isEmpty()) {
for (final Entity entity : pluginEntity) {
final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity();
if (tracker == null) {
continue;
}
ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData chunk = ((ChunkSystemEntity) entity).moonrise$getChunkData();
if (chunk == null) {
continue;
}
tracker.moonrise$tick(chunk.nearbyPlayers);
boolean flag = false;
if (tracker.moonrise$hasPlayers()) {
flag = true;
} else {
FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus();
if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
flag = true;
}
}
if (flag) {
tracker.serverEntity.sendChanges();
}
public void broadcastIgnorePlayers(ChunkMap.TrackedEntity entity, Packet<?> packet, List<UUID> ignoredPlayers) {
for (ServerPlayerConnection conn : entity.seenBy()) {
if (!ignoredPlayers.contains(conn.getPlayer().getUUID())) {
send(conn, packet);
}
}
}
public void broadcastAndSend(ChunkMap.TrackedEntity entity, Packet<? super net.minecraft.network.protocol.game.ClientGamePacketListener> packet) {
broadcast(entity, packet);
if (entity.serverEntity.entity instanceof ServerPlayer serverPlayer) {
send(serverPlayer.connection, packet);
}
}
Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> join(TrackerCtx other) {
itemFrames.addAll(other.itemFrames);
witherBosses.addAll(other.witherBosses);
stopSeen.addAll(other.stopSeen);
startSeen.addAll(other.startSeen);
pluginEntity.addAll(other.pluginEntity);
resync.addAll(other.resync);
syncAttributes.addAll(other.syncAttributes);
return other.packets;
}
void reset() {
itemFrames.clear();
witherBosses.clear();
stopSeen.clear();
startSeen.clear();
pluginEntity.clear();
resync.clear();
syncAttributes.clear();
packets.clear();
}
void handle(Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>>[] other) {
if (!pluginEntity.isEmpty()) {
for (ChunkMap.TrackedEntity tracker : pluginEntity) {
handlePlugin(tracker);
}
pluginEntity.clear();
}
handlePackets(world, packets, flush);
if (!bukkitItemFrames.isEmpty()) {
for (ItemFrame itemFrame : bukkitItemFrames) {
MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData savedData = MapItem.getSavedData(mapId, world);
if (savedData != null) {
ChunkMap.TrackedEntity trackedEntity = itemFrame.moonrise$getTrackedEntity();
if (trackedEntity != null) {
ItemStack item = itemFrame.getItem();
for (final net.minecraft.server.network.ServerPlayerConnection connection : trackedEntity.seenBy()) {
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
savedData.tickCarriedBy(serverPlayer, item);
Packet<? super ClientGamePacketListener> updatePacket = (Packet<? super ClientGamePacketListener>) savedData.getUpdatePacket(mapId, serverPlayer);
if (updatePacket != null) {
send(serverPlayer.connection, updatePacket);
}
Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> prior = new Object2ObjectOpenHashMap<>();
if (!startSeen.isEmpty()) {
boolean callEvent = PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length != 0;
for (StartSeen startSeen : startSeen) {
handleStartTrack(startSeen, prior, callEvent);
}
}
flush(world, prior);
for (Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> otherPackets : other) {
flush(world, otherPackets);
}
if (!resync.isEmpty()) {
for (ChunkMap.TrackedEntity tracker : resync) {
tracker.serverEntity.leaf$sendChanges(this, tracker, true);
}
}
if (!syncAttributes.isEmpty()) {
for (ChunkMap.TrackedEntity tracker : syncAttributes) {
handleSyncAttribute(tracker);
}
}
flush(world, this.packets);
if (!stopSeen.isEmpty()) {
boolean callEvent = PlayerUntrackEntityEvent.getHandlerList().getRegisteredListeners().length != 0;
for (StopSeen untrack : stopSeen) {
for (ServerPlayer player : untrack.q) {
if (world == player.level()) {
if (callEvent) {
new PlayerUntrackEntityEvent(
player.getBukkitEntity(),
untrack.e.getBukkitEntity()
).callEvent();
}
ChunkMap.TrackedEntity tracker = untrack.e.moonrise$getTrackedEntity();
if (tracker == null || !tracker.seenBy.contains(player.connection)) {
send(player.connection, new ClientboundRemoveEntitiesPacket(untrack.e.getId()));
}
}
}
}
bukkitItemFrames.clear();
}
if (!itemFrames.isEmpty()) {
for (ItemFrame itemFrame : itemFrames) {
handleItemFrame(itemFrame);
}
}
if (!witherBosses.isEmpty()) {
for (BossEvent witherBoss : witherBosses) {
for (ServerPlayer player : witherBoss.add) {
if (!world.equals(player.level())) {
continue;
}
witherBoss.witherBoss.bossEvent.leafAddPlayer(this, player);
}
for (ServerPlayer player : witherBoss.remove) {
witherBoss.witherBoss.bossEvent.leafRemovePlayer(this, player);
}
handleBossEvent(witherBoss);
}
witherBosses.clear();
}
if (!paperStartSeen.isEmpty()) {
for (PaperStartSeen startSeen : paperStartSeen) {
for (ServerPlayerConnection connection : startSeen.q) {
if (!new PlayerTrackEntityEvent(
connection.getPlayer().getBukkitEntity(),
startSeen.e.getBukkitEntity()
).callEvent()) {
send(connection, new ClientboundRemoveEntitiesPacket(startSeen.e.getId()));
}
}
}
paperStartSeen.clear();
}
if (!paperStopSeen.isEmpty()) {
for (PaperStopSeen stopSeen : paperStopSeen) {
for (ServerPlayerConnection connection : stopSeen.q) {
new PlayerUntrackEntityEvent(
connection.getPlayer().getBukkitEntity(),
stopSeen.e.getBukkitEntity()
).callEvent();
}
}
paperStopSeen.clear();
}
handlePackets(world, packets, flush);
flush(world, this.packets);
}
private static void handlePackets(ServerLevel world, Reference2ReferenceOpenHashMap<ServerPlayerConnection, ReferenceArrayList<Packet<? super ClientGamePacketListener>>> packets, boolean flush) {
private void handleBossEvent(BossEvent witherBoss) {
for (ServerPlayer player : witherBoss.add) {
if (world == player.level()) {
witherBoss.witherBoss.bossEvent.leaf$addPlayer(this, player);
}
}
for (ServerPlayer player : witherBoss.remove) {
witherBoss.witherBoss.bossEvent.leaf$removePlayer(this, player);
}
}
private static void handlePlugin(ChunkMap.TrackedEntity tracker) {
ChunkSystemEntity entity = tracker.serverEntity.entity;
ChunkData chunk = entity.moonrise$getChunkData();
tracker.moonrise$tick(chunk == null ? null : chunk.nearbyPlayers);
boolean flag = tracker.moonrise$hasPlayers();
if (!flag) {
FullChunkStatus status = entity.moonrise$getChunkStatus();
flag = status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING);
}
if (flag) {
tracker.serverEntity.sendChanges();
}
}
private void handleItemFrame(ItemFrame itemFrame) {
MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData savedData = MapItem.getSavedData(mapId, world);
if (savedData == null) {
return;
}
ChunkMap.TrackedEntity tracker = itemFrame.moonrise$getTrackedEntity();
if (tracker == null) {
return;
}
ItemStack item = itemFrame.getItem();
for (ServerPlayerConnection connection : tracker.seenBy()) {
ServerPlayer serverPlayer = connection.getPlayer(); // Paper
savedData.tickCarriedBy(serverPlayer, item);
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
if (updatePacket != null) {
send(serverPlayer.connection, updatePacket);
}
}
}
private void handleStartTrack(StartSeen startSeen, Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> prior, boolean callEvent) {
ChunkMap.TrackedEntity tracker = startSeen.e.moonrise$getTrackedEntity();
ObjectArrayList<Packet<? super ClientGamePacketListener>> list = new ObjectArrayList<>(4);
if (tracker == null) {
return;
}
list.add(startSeen.e.getAddEntityPacket(tracker.serverEntity));
boolean flag = tracker.serverEntity.leaf$sendPairingData(list);
ClientboundBundlePacket packet = new ClientboundBundlePacket(list);
for (ServerPlayerConnection connection : startSeen.q) {
if (callEvent
&& !new PlayerTrackEntityEvent(
connection.getPlayer().getBukkitEntity(),
startSeen.e.getBukkitEntity()
).callEvent()) {
send(connection, new ClientboundRemoveEntitiesPacket(startSeen.e.getId()));
} else if (flag && connection.getPlayer() == startSeen.e) {
var copy = new ObjectArrayList<>(list);
copy.add(new ClientboundUpdateAttributesPacket(startSeen.e.getId(), List.of(connection.getPlayer().getBukkitEntity().getScaledMaxHealth())));
var modified = new ClientboundBundlePacket(copy);
prior.computeIfAbsent(connection, INIT_PACKET_LIST).add(modified);
} else {
prior.computeIfAbsent(connection, INIT_PACKET_LIST).add(packet);
}
}
}
public void sendDirtyEntityData(ChunkMap.TrackedEntity tracker) {
Entity entity = tracker.serverEntity.entity;
SynchedEntityData entityData = entity.getEntityData();
List<SynchedEntityData.DataValue<?>> list = entityData.packDirty();
if (list != null) {
tracker.serverEntity.trackedDataValues = entityData.getNonDefaultValues();
ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entity.getId(), list);
broadcastAndSend(tracker, packet);
}
if (entity instanceof LivingEntity livingEntity && livingEntity.getAttributes().attributeDirty()) {
syncAttributes.add(tracker);
}
}
private void handleSyncAttribute(ChunkMap.TrackedEntity tracker) {
LivingEntity e = tracker.serverEntity.entity instanceof LivingEntity livingEntity? livingEntity : null;
if (e == null) {
return;
}
ObjectArrayList<ClientboundUpdateAttributesPacket.AttributeSnapshot> attributes;
AttributeMap attributeMap = e.getAttributes();
ServerPlayer p = e instanceof ServerPlayer serverPlayer ? serverPlayer : null;
if (attributeMap.attributes instanceof AttributeInstanceArrayMap map) {
int[] ids = attributeMap.getAttributesToSyncIds();
attributes = new ObjectArrayList<>(ids.length);
for (int attributeIdx : ids) {
AttributeInstance attributeInstance = map.getInstance(attributeIdx);
if (attributeInstance == null) continue;
Holder<Attribute> attribute = attributeInstance.getAttribute();
if (p != null && attribute == Attributes.MAX_HEALTH) {
attributeInstance = p.getBukkitEntity().getScaledMaxHealth();
}
attributes.add(new ClientboundUpdateAttributesPacket.AttributeSnapshot(attribute, attributeInstance.getBaseValue(), attributeInstance.getModifiers()));
}
} else {
Set<AttributeInstance> toSync = attributeMap.getAttributesToSync();
attributes = new ObjectArrayList<>(toSync.size());
for (AttributeInstance attributeInstance : toSync) {
if (attributeInstance == null) continue;
Holder<Attribute> attribute = attributeInstance.getAttribute();
if (p != null && attribute == Attributes.MAX_HEALTH) {
attributeInstance = p.getBukkitEntity().getScaledMaxHealth();
}
attributes.add(new ClientboundUpdateAttributesPacket.AttributeSnapshot(attribute, attributeInstance.getBaseValue(), attributeInstance.getModifiers()));
}
}
broadcastAndSend(tracker, new ClientboundUpdateAttributesPacket(e.getId(), attributes));
}
private static void flush(ServerLevel world, Object2ObjectOpenHashMap<ServerPlayerConnection, ObjectArrayList<Packet<?>>> packets) {
if (packets.isEmpty()) {
return;
}
var iter = packets.reference2ReferenceEntrySet().fastIterator();
while (iter.hasNext()) {
var entry = iter.next();
packets.object2ObjectEntrySet().fastForEach(entry -> {
ServerPlayerConnection connection = entry.getKey();
ReferenceArrayList<Packet<? super ClientGamePacketListener>> list = entry.getValue();
if (!world.equals(connection.getPlayer().level())) {
continue;
ObjectArrayList<Packet<?>> list = entry.getValue();
if (world == connection.getPlayer().level()) {
Packet<?>[] packetsRaw = list.elements();
for (int i = 0, size = list.size(); i < size; i++) {
connection.send(packetsRaw[i]);
}
}
Packet[] packetsRaw = list.elements();
for (int i = 0, size = list.size(); i < size; i++) {
connection.send(packetsRaw[i]);
}
if (flush && connection instanceof ServerGamePacketListenerImpl playerConnection) {
playerConnection.connection.flushChannel();
}
}
});
packets.clear();
}
}

View File

@@ -25,27 +25,18 @@ public record TrackerTask(ServerLevel world, EntitySlice entities) implements Ca
continue;
}
if (tracker.getClass() != ChunkMap.TrackedEntity.class) {
ctx.citizensEntity(entity);
ctx.citizensEntity(tracker);
continue;
}
ChunkData chunkData = ((ChunkSystemEntity) entity).moonrise$getChunkData();
// removed in world if null
if (chunkData == null) {
continue;
}
tracker.leafTick(ctx, chunkData.nearbyPlayers);
boolean flag = false;
if (tracker.moonrise$hasPlayers()) {
flag = true;
} else {
boolean flag = tracker.leaf$tick(ctx, chunkData == null ? null : chunkData.nearbyPlayers);
if (!flag) {
FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus();
// removed in world if null
if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
flag = true;
}
flag = status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING);
}
if (flag) {
tracker.serverEntity.leafSendChanges(ctx, tracker);
tracker.serverEntity.leaf$sendChanges(ctx, tracker, false);
}
}
return ctx;

View File

@@ -27,7 +27,7 @@ public final class RegistryTypeManager {
ATTRIBUTE = new Holder[ATTRIBUTE_SIZE];
for (int i = 0; i < ATTRIBUTE_SIZE; i++) {
ATTRIBUTE[i] = BuiltInRegistries.ATTRIBUTE.get(i).orElseThrow();
if (ATTRIBUTE[i].value().uid != i) {
if (ATTRIBUTE[i].value().id != i) {
throw new ExceptionInInitializerError();
}
}

View File

@@ -53,20 +53,20 @@ public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, A
@Override
public boolean containsKey(Object key) {
if (key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute) {
int uid = attribute.uid;
return uid >= 0 && uid < a.length && a[uid] != null;
int id = attribute.id;
return id >= 0 && id < a.length && a[id] != null;
}
return false;
}
@Override
public boolean containsValue(Object value) {
return value instanceof AttributeInstance val && Objects.equals(getInstance(val.getAttribute().value().uid), val);
return value instanceof AttributeInstance val && Objects.equals(getInstance(val.getAttribute().value().id), val);
}
@Override
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.id] : null;
}
@Nullable
@@ -76,18 +76,18 @@ public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, A
@Override
public AttributeInstance put(@NotNull Holder<Attribute> key, AttributeInstance value) {
int uid = key.value().uid;
AttributeInstance prev = a[uid];
setByIndex(uid, value);
int id = key.value().id;
AttributeInstance prev = a[id];
setByIndex(id, value);
return prev;
}
@Override
public AttributeInstance remove(Object key) {
if (!(key instanceof Holder<?> holder) || !(holder.value() instanceof Attribute attribute)) return null;
int uid = attribute.uid;
AttributeInstance prev = a[uid];
setByIndex(uid, null);
int id = attribute.id;
AttributeInstance prev = a[id];
setByIndex(id, null);
return prev;
}
@@ -95,7 +95,7 @@ public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, A
public void putAll(@NotNull Map<? extends Holder<Attribute>, ? extends AttributeInstance> m) {
for (AttributeInstance e : m.values()) {
if (e != null) {
setByIndex(e.getAttribute().value().uid, e);
setByIndex(e.getAttribute().value().id, e);
}
}
}

View File

@@ -19,16 +19,16 @@ public final class AttributeInstanceSet extends AbstractCollection<AttributeInst
@Override
public boolean add(AttributeInstance instance) {
return inner.add(instance.getAttribute().value().uid);
return inner.add(instance.getAttribute().value().id);
}
public boolean addAttribute(Attribute attribute) {
return inner.add(attribute.uid);
return inner.add(attribute.id);
}
@Override
public boolean remove(Object o) {
return o instanceof AttributeInstance instance && inner.remove(instance.getAttribute().value().uid);
return o instanceof AttributeInstance instance && inner.remove(instance.getAttribute().value().id);
}
@Override
@@ -54,7 +54,7 @@ public final class AttributeInstanceSet extends AbstractCollection<AttributeInst
@Override
public boolean contains(Object o) {
if (o instanceof AttributeInstance instance) {
return inner.contains(instance.getAttribute().value().uid);
return inner.contains(instance.getAttribute().value().id);
}
return false;
}