9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00

MultithreadedTracker add lock to AttributeMap and TrackedChunk

This commit is contained in:
hayanesuru
2025-05-29 12:20:52 +09:00
parent a0457c6ae3
commit df1d62bed9
9 changed files with 286 additions and 99 deletions

View File

@@ -23,6 +23,28 @@ for the case of some NPC plugins which using real entity type, e.g. Citizens.
But it is still recommending to use those packet based, virtual entity
based NPC plugins, e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc.
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..4200d22606c6a3dbdf282792a4007a51df66963b 100644
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
@@ -60,7 +60,16 @@ public final class NearbyPlayers {
private final ServerLevel world;
private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
- private final Long2ReferenceOpenHashMap<TrackedChunk> byChunk = new Long2ReferenceOpenHashMap<>();
+ // Leaf start - Multithreaded tracker
+ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap<TrackedChunk> byChunk;
+ {
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ byChunk = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>());
+ } else {
+ byChunk = new Long2ReferenceOpenHashMap<>();
+ }
+ }
+ // Leaf end - Multithreaded tracker
private final Long2ReferenceOpenHashMap<ReferenceList<ServerPlayer>>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES];
{
for (int i = 0; i < this.directByChunk.length; ++i) {
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
index dd2509996bfd08e8c3f9f2be042229eac6d7692d..a35e9fae8f8da0c42f0616c4f78dc396492673aa 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -37,7 +59,7 @@ index dd2509996bfd08e8c3f9f2be042229eac6d7692d..a35e9fae8f8da0c42f0616c4f78dc396
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eafc8b48d1b 100644
index 5d9d233e3a568aa6297ed9c703fa450f98158602..47a7bf7c38600a2ad547bbd2b7fe632e96e9a139 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -248,6 +248,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -70,14 +92,13 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
// Paper start - optimise entity tracker
if (true) {
this.newTrackerTick();
@@ -1073,7 +1089,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1073,7 +1089,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
final Entity entity;
private final int range;
SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
+ // Leaf start - Multithreaded tracker
+ public static final ServerPlayerConnection[] EMPTY_OBJECT_ARRAY = new ServerPlayerConnection[0];
+ public final Object sync = new Object();
+ public final Set<ServerPlayerConnection> seenBy = org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled ? it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>()) : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
+ private volatile ServerPlayerConnection[] seenByArray = EMPTY_OBJECT_ARRAY;
+ public ServerPlayerConnection[] seenBy() {
@@ -90,7 +111,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
// Paper start - optimise entity tracker
private long lastChunkUpdate = -1L;
@@ -1100,27 +1127,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1100,27 +1126,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.lastTrackedChunk = chunk;
final ServerPlayer[] playersRaw = players.getRawDataUnchecked();
@@ -191,7 +212,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(conn.getPlayer())) {
foundToRemove = true;
break;
@@ -1131,12 +1226,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1131,12 +1225,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return;
}
@@ -207,7 +228,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
}
@Override
@@ -1146,10 +1242,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1146,10 +1241,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (this.seenBy.isEmpty()) {
return;
}
@@ -221,7 +242,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
}
@Override
@@ -1176,7 +1273,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1176,7 +1272,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void broadcast(Packet<?> packet) {
@@ -230,7 +251,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
serverPlayerConnection.send(packet);
}
}
@@ -1189,21 +1286,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1189,21 +1285,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void broadcastRemoved() {
@@ -268,7 +289,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
// Paper start - remove allocation of Vec3D here
// Vec3 vec3 = player.position().subtract(this.entity.position());
double vec3_dx = player.getX() - this.entity.getX();
@@ -1231,6 +1341,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1231,6 +1340,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// CraftBukkit end
if (flag) {
if (this.seenBy.add(player.connection)) {
@@ -276,7 +297,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eaf
// Paper start - entity tracking events
if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
this.serverEntity.addPairing(player);
@@ -1239,6 +1350,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1239,6 +1349,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.serverEntity.onPlayerAdd(); // Paper - fix desync when a player is added to the tracker
}
} else if (this.seenBy.remove(player.connection)) {
@@ -298,18 +319,10 @@ index f106373ef3ac4a8685c2939c9e8361688a285913..51ae390c68e7a3aa193329cc3bc47ca6
public boolean visible = true;
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 1dee20436fc29537319ee456756a8e8f7b6fe66a..1f3e030cea42a0c9e27425cb18c232f482ef8608 100644
index 1dee20436fc29537319ee456756a8e8f7b6fe66a..bcd569e7d12d4f453c64bf12933a72c3ca362329 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -70,6 +70,7 @@ public class ServerEntity {
private boolean wasOnGround;
@Nullable
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
+ public boolean wantSendDirtyEntityData = false; // Leaf - Multithreaded tracker
// CraftBukkit start
private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers;
@@ -110,8 +111,16 @@ public class ServerEntity {
@@ -110,8 +110,16 @@ public class ServerEntity {
.forEach(
removedPassenger -> {
if (removedPassenger instanceof ServerPlayer serverPlayer1) {
@@ -328,7 +341,7 @@ index 1dee20436fc29537319ee456756a8e8f7b6fe66a..1f3e030cea42a0c9e27425cb18c232f4
}
}
);
@@ -124,7 +133,7 @@ public class ServerEntity {
@@ -124,7 +132,7 @@ public class ServerEntity {
MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level);
if (savedData != null) {
@@ -337,19 +350,38 @@ index 1dee20436fc29537319ee456756a8e8f7b6fe66a..1f3e030cea42a0c9e27425cb18c232f4
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
savedData.tickCarriedBy(serverPlayer, item);
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
@@ -425,6 +434,12 @@ public class ServerEntity {
}
@@ -433,15 +441,30 @@ public class ServerEntity {
}
public void sendDirtyEntityData() {
+ // Leaf start - Multithreaded tracker
+ if (Thread.currentThread() instanceof org.dreeam.leaf.async.tracker.MultithreadedTracker.MultithreadedTrackerThread) {
+ wantSendDirtyEntityData = true;
+ return;
+ }
+ // Leaf end - Multithreaded tracker
SynchedEntityData entityData = this.entity.getEntityData();
List<SynchedEntityData.DataValue<?>> list = entityData.packDirty();
if (list != null) {
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));
+ }
}
+ // Leaf end - Multithreaded tracker
attributesToSync.clear();
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 275b640f4536366152f59acf071dd4eba15696c8..a669a59a42f814480879a52d2da5e04c636720de 100644
--- a/net/minecraft/server/level/ServerLevel.java
@@ -385,6 +417,180 @@ index 327b3bc89920c4ab02c1126dc63bca05ce3abefe..1415043bee5fbbfcf9dab9184a9418d5
// Paper start - Prevent teleporting dead entities
if (this.player.isRemoved()) {
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
index d502325d693539842fd6f5485365e0e9b786b7aa..324f8952a921a3897f4ff48145f0f8645c690318 100644
--- a/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 {
}
private void refreshDirtyAttributes() {
- Set<AttributeInstance> attributesToUpdate = this.getAttributes().getAttributesToUpdate();
+ // Leaf start - Multithreaded tracker
+ var attributeMap = this.getAttributes();
+ 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();
+ }
+ } else {
for (AttributeInstance attributeInstance : attributesToUpdate) {
this.onAttributeUpdated(attributeInstance.getAttribute());
}
attributesToUpdate.clear();
+ }
+ // Leaf end - Multithreaded tracker
}
protected void onAttributeUpdated(Holder<Attribute> attribute) {
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
index 8013594bb4844e7a8abf28123958e7f632d39341..93b375f39f10568f6b222607890a9ce67db0e9bb 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
@@ -24,8 +24,24 @@ public class AttributeInstance {
private final Map<AttributeModifier.Operation, Map<ResourceLocation, AttributeModifier>> modifiersByOperation = Maps.newEnumMap(
AttributeModifier.Operation.class
);
- private final Map<ResourceLocation, AttributeModifier> modifierById = new Object2ObjectArrayMap<>();
- private final Map<ResourceLocation, AttributeModifier> permanentModifiers = new Object2ObjectArrayMap<>();
+ // Leaf start - Multithreaded tracker
+ private final Map<ResourceLocation, AttributeModifier> modifierById;
+ {
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ modifierById = it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
+ } else {
+ modifierById = new Object2ObjectArrayMap<>();
+ }
+ }
+ private final Map<ResourceLocation, AttributeModifier> permanentModifiers;
+ {
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ permanentModifiers = it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
+ } else {
+ permanentModifiers = new Object2ObjectArrayMap<>();
+ }
+ }
+ // Leaf end - Multithreaded tracker
private double baseValue;
private boolean dirty = true;
private double cachedValue;
@@ -54,7 +70,13 @@ public class AttributeInstance {
@VisibleForTesting
Map<ResourceLocation, AttributeModifier> getModifiers(AttributeModifier.Operation operation) {
- return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> new Object2ObjectOpenHashMap<>());
+ // Leaf start - Multithreaded tracker
+ return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> {
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled)
+ return it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
+ else return new Object2ObjectArrayMap<>();
+ });
+ // Leaf end - Multithreaded tracker
}
public Set<AttributeModifier> getModifiers() {
@@ -174,6 +196,13 @@ public class AttributeInstance {
}
public void replaceFrom(AttributeInstance instance) {
+ // Leaf start - Multithreaded tracker
+ synchronized (instance) {
+ this.replaceFrom0(instance);
+ }
+ }
+ public void replaceFrom0(AttributeInstance instance) {
+ // Leaf end - Multithreaded tracker
this.baseValue = instance.baseValue;
this.modifierById.clear();
this.modifierById.putAll(instance.modifierById);
@@ -195,9 +224,19 @@ public class AttributeInstance {
if (!this.permanentModifiers.isEmpty()) {
ListTag listTag = new ListTag();
- for (AttributeModifier attributeModifier : this.permanentModifiers.values()) {
- listTag.add(attributeModifier.save());
+ // Leaf start - Multithreaded tracker
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ synchronized (this) {
+ for (AttributeModifier attributeModifier : this.permanentModifiers.values()) {
+ listTag.add(attributeModifier.save());
+ }
+ }
+ } else {
+ for (AttributeModifier attributeModifier : this.permanentModifiers.values()) {
+ listTag.add(attributeModifier.save());
+ }
}
+ // Leaf end - Multithreaded tracker
compoundTag.put("modifiers", listTag);
}
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..c0a09b615e9b6c4ec72b8b77a78e7da374d4498b 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -21,8 +21,19 @@ 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 Set<AttributeInstance> attributesToSync = 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
+ private final Set<AttributeInstance> attributesToSync;
+ private final Set<AttributeInstance> attributesToUpdate;
+ {
+ 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
// 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
@@ -60,7 +71,13 @@ public class AttributeMap {
@Nullable
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
+ 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));
+ }
+ } else {
+ return this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, (Holder<Attribute>) holder));
+ }
}
public boolean hasAttribute(Holder<Attribute> attribute) {
@@ -176,8 +193,17 @@ public class AttributeMap {
// Paper - start - living entity allow attribute registration
public void registerAttribute(Holder<Attribute> attributeBase) {
+ // Leaf start - Multithreaded tracker
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
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
index c96f458994818392857642282ec3d492124885da..d345afd14ef6fe2f0a584df5dfa080fd7ab3f47e 100644
--- a/net/minecraft/world/entity/item/PrimedTnt.java

View File

@@ -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)
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 316242d60db43494300a29b7d0945d0d76ac9987..0138bd4d95a592bfa5ccbb33fa6c1201f289fd2a 100644
index 324f8952a921a3897f4ff48145f0f8645c690318..3e3fdcff3725841c8b04047a91733c8b98187e0b 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2739,6 +2739,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2752,6 +2752,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
protected void updateSwingTime() {
@@ -23,7 +23,7 @@ index 316242d60db43494300a29b7d0945d0d76ac9987..0138bd4d95a592bfa5ccbb33fa6c1201
int currentSwingDuration = this.getCurrentSwingDuration();
if (this.swinging) {
this.swingTime++;
@@ -3690,6 +3691,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3703,6 +3704,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
protected void updateFallFlying() {
this.checkSlowFallDistance();
if (!this.level().isClientSide) {

View File

@@ -76,7 +76,7 @@ index a8c6549f772208cd543607224fef2c2389b14f24..709631db548a16a969a373e26ebbcd69
public boolean equals(Object other) {
return this == other
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 0138bd4d95a592bfa5ccbb33fa6c1201f289fd2a..00233a7066d751821566b43993e8c45e7dad95d0 100644
index 3e3fdcff3725841c8b04047a91733c8b98187e0b..ffae6778b471628639c41b1d5f3af08b6b72a86c 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -159,7 +159,7 @@ import org.bukkit.event.entity.EntityTeleportEvent;
@@ -116,7 +116,7 @@ index 0138bd4d95a592bfa5ccbb33fa6c1201f289fd2a..00233a7066d751821566b43993e8c45e
Equippable equippable = newItem.get(DataComponents.EQUIPPABLE);
if (!this.isSilent() && equippable != null && slot == equippable.slot() && !silent) { // CraftBukkit
this.level()
@@ -3355,6 +3360,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3368,6 +3373,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
public void detectEquipmentUpdatesPublic() { // CraftBukkit
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
if (map != null) {
@@ -124,7 +124,7 @@ index 0138bd4d95a592bfa5ccbb33fa6c1201f289fd2a..00233a7066d751821566b43993e8c45e
this.handleHandSwap(map);
if (!map.isEmpty()) {
this.handleEquipmentChanges(map);
@@ -3364,6 +3370,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3377,6 +3383,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
@Nullable
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
@@ -135,7 +135,7 @@ index 0138bd4d95a592bfa5ccbb33fa6c1201f289fd2a..00233a7066d751821566b43993e8c45e
Map<EquipmentSlot, ItemStack> map = null;
// Paper start - EntityEquipmentChangedEvent
record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange {
@@ -4723,6 +4733,81 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -4736,6 +4746,81 @@ public abstract class LivingEntity extends Entity implements Attackable {
return this.lastHurtByPlayerTime;
}

View File

@@ -9,10 +9,10 @@ This patch didn't cahce SectionPos or BlockPos to chunkKey, since it needs to co
TODO: Cache block pos and section pos, whether need?
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..288a3eb57f3431dd624ad8a4b08684563abbc5ad 100644
index 4200d22606c6a3dbdf282792a4007a51df66963b..4b258f048c73107d0d050a9aa4b4a39788145b17 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 {
@@ -136,7 +136,7 @@ public final class NearbyPlayers {
}
public TrackedChunk getChunk(final ChunkPos pos) {
@@ -21,7 +21,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..288a3eb57f3431dd624ad8a4b0868456
}
public TrackedChunk getChunk(final BlockPos pos) {
@@ -143,7 +143,7 @@ public final class NearbyPlayers {
@@ -152,7 +152,7 @@ public final class NearbyPlayers {
}
public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {
@@ -84,7 +84,7 @@ index 571db5f9bf94745a8afe2cd313e593fb15db5e37..1487b7d8be435b3fbad2aabd05796965
valueInMap = new ServerChunkTasks(
keyInMap, ServerLightQueue.this.lightInterface, ServerLightQueue.this, priority
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 49cbdf014d0626b36eb4c451b6de09508822b7fd..a9e7424bb55266c5e04c56dcf598ce7d149eeb21 100644
index a669a59a42f814480879a52d2da5e04c636720de..61afe93ff7f6f6ac3967e948bf39b0ab559e2808 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

View File

@@ -6,10 +6,10 @@ 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 00233a7066d751821566b43993e8c45e7dad95d0..03c9edad5c2f5e902b7a766c6d0be61bf3c263ae 100644
index ffae6778b471628639c41b1d5f3af08b6b72a86c..32039b50946b23e4f55498aa09ea33cfa77b517c 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3631,7 +3631,7 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
@@ -3644,7 +3644,7 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
this.checkAutoSpinAttack(boundingBox, this.getBoundingBox());
}
@@ -18,7 +18,7 @@ index 00233a7066d751821566b43993e8c45e7dad95d0..03c9edad5c2f5e902b7a766c6d0be61b
// Paper start - Add EntityMoveEvent
// Purpur start - Ridables
if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
@@ -3769,7 +3769,14 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
@@ -3782,7 +3782,14 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
return;
}
// Paper end - don't run getEntities if we're not going to use its result
@@ -34,7 +34,7 @@ index 00233a7066d751821566b43993e8c45e7dad95d0..03c9edad5c2f5e902b7a766c6d0be61b
if (!entities.isEmpty()) {
// 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) {
@@ -3802,6 +3809,44 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
@@ -3815,6 +3822,44 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf
}
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Optimize addOrUpdateTransientModifier
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
index 8013594bb4844e7a8abf28123958e7f632d39341..7505485c8965e5492a9d68288596178cfe0971ee 100644
index 93b375f39f10568f6b222607890a9ce67db0e9bb..69ba880e17e5cff3b2260f539683ca565f34e8dd 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
@@ -85,8 +85,13 @@ public class AttributeInstance {
@@ -107,8 +107,13 @@ public class AttributeInstance {
}
public void addOrUpdateTransientModifier(AttributeModifier modifier) {

View File

@@ -34,10 +34,10 @@ index 98af1ad020a003db66d7319f33d43deec315aec5..9669036e6b7f1830888e48c99acb01d4
for (int i = 0; i < this.tickables.size(); i++) {
this.tickables.get(i).run();
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index e67d87b3043b381d27f75f37e3b7f922e18dcc2d..d64434d808d164ab1201f244058e2964860a590c 100644
index bcd569e7d12d4f453c64bf12933a72c3ca362329..b48032bc878e11518d63c128edeef6bf3770f7d1 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -284,6 +284,7 @@ public class ServerEntity {
@@ -283,6 +283,7 @@ public class ServerEntity {
this.entity.hurtMarked = false;
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
}

View File

@@ -25,17 +25,20 @@ index f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b16164
public double getDefaultValue() {
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..51a5a3a804a1cbb0e1d23be432043552b102d837 100644
index c0a09b615e9b6c4ec72b8b77a78e7da374d4498b..a550e6bd9dffa9a46f0d7967c9d73ff5cbfbaa0a 100644
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -20,12 +20,12 @@ import org.slf4j.Logger;
@@ -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
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);
// 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
@@ -43,7 +46,7 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..51a5a3a804a1cbb0e1d23be432043552
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
public AttributeMap(AttributeSupplier supplier) {
@@ -36,7 +36,7 @@ public class AttributeMap {
@@ -47,7 +47,7 @@ public class AttributeMap {
this.entity = entity;
// Purpur end - Ridables
this.supplier = defaultAttributes;
@@ -52,20 +55,31 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..51a5a3a804a1cbb0e1d23be432043552
}
private void onAttributeModified(AttributeInstance instance) {
@@ -60,7 +60,17 @@ public class AttributeMap {
@@ -71,13 +71,24 @@ public class AttributeMap {
@Nullable
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
- 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 ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
+ 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
}

View File

@@ -32,15 +32,6 @@ public class MultithreadedTracker {
private static long lastWarnMillis = System.currentTimeMillis();
private static ThreadPoolExecutor TRACKER_EXECUTOR = null;
private record SendChanges(ServerEntity[] entities, int size) implements Runnable {
@Override
public void run() {
for (int i = 0; i < size; i++) {
entities[i].sendDirtyEntityData();
}
}
}
private MultithreadedTracker() {
}
@@ -80,7 +71,6 @@ public class MultithreadedTracker {
// Move tracking to off-main
TRACKER_EXECUTOR.execute(() -> {
ReferenceArrayList<ServerEntity> sendDirty = ReferenceArrayList.wrap(new ServerEntity[0]);
for (final Entity entity : trackerEntitiesRaw) {
if (entity == null) continue;
@@ -88,19 +78,12 @@ public class MultithreadedTracker {
if (tracker == null) continue;
// Don't Parallel Tick Tracker of Entity
synchronized (tracker.sync) {
tracker.moonrise$tick(nearbyPlayers.getChunk(entity.chunkPosition()));
synchronized (tracker) {
var trackedChunk = nearbyPlayers.getChunk(entity.chunkPosition());
tracker.moonrise$tick(trackedChunk);
tracker.serverEntity.sendChanges();
if (tracker.serverEntity.wantSendDirtyEntityData) {
tracker.serverEntity.wantSendDirtyEntityData = false;
sendDirty.add(tracker.serverEntity);
}
}
}
if (!sendDirty.isEmpty()) {
level.getServer().execute(new SendChanges(sendDirty.elements(), sendDirty.size()));
}
});
}
@@ -121,7 +104,7 @@ public class MultithreadedTracker {
if (tracker == null) continue;
synchronized (tracker.sync) {
synchronized (tracker) {
tickTask[index] = tracker.leafTickCompact(nearbyPlayers.getChunk(entity.chunkPosition()));
sendChangesTasks[index] = () -> tracker.serverEntity.sendChanges(); // Collect send changes to task array
}
@@ -140,22 +123,6 @@ public class MultithreadedTracker {
sendChanges.run();
}
ReferenceArrayList<ServerEntity> sendDirty = ReferenceArrayList.wrap(new ServerEntity[0]);;
for (final Entity entity : trackerEntitiesRaw) {
if (entity == null) continue;
final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity();
if (tracker == null) continue;
if (tracker.serverEntity.wantSendDirtyEntityData) {
tracker.serverEntity.wantSendDirtyEntityData = false;
sendDirty.add(tracker.serverEntity);
}
}
if (!sendDirty.isEmpty()) {
level.getServer().execute(new SendChanges(sendDirty.elements(), sendDirty.size()));
}
});
}