9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-23 17:09:29 +00:00
Files
Leaf/patches/unapplied/server/0019-Petal-reduce-work-done-by-game-event-system.patch
2023-06-16 12:52:26 +08:00

187 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: peaches94 <peachescu94@gmail.com>
Date: Sun, 10 Jul 2022 13:29:20 -0500
Subject: [PATCH] Petal: reduce work done by game event system
Original license: GPL v3
Original project: https://github.com/Bloom-host/Petal
1. going into game event dispatching can be expensive so run the checks before dispatching
2. EuclideanGameEventListenerRegistry is not used concurrently so we ban that usage for improved performance with allays
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
index a606aed406551f4d3cc0bf09d6e231d87fe00f53..01babdf2c82d019589c38b73a10ad7afeebd32d2 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
@@ -126,6 +126,13 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
world.playSound((Player) null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F);
}
+ // petal start
+ @Override
+ public boolean listensToEvent(GameEvent gameEvent, GameEvent.Context context) {
+ return !this.isRemoved() && gameEvent == GameEvent.ENTITY_DIE && context.sourceEntity() instanceof LivingEntity;
+ }
+ // petal end
+
private void tryAwardItSpreadsAdvancement(Level world, LivingEntity deadEntity) {
LivingEntity entityliving1 = deadEntity.getLastHurtByMob();
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 901938201c1abee1c88e217d2c1ba1a2d147420e..e0a90ee2c28dc67e33db8f3b599cfb9cef294553 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -80,7 +80,18 @@ public class LevelChunk extends ChunkAccess {
private Supplier<FullChunkStatus> fullStatus;
@Nullable
private LevelChunk.PostLoadProcessor postLoad;
- private final Int2ObjectMap<GameEventListenerRegistry> gameEventListenerRegistrySections;
+ // petal start
+ private final GameEventListenerRegistry[] gameEventListenerRegistrySections;
+ private static final int GAME_EVENT_DISPATCHER_RADIUS = 2;
+
+ private static int getGameEventSectionIndex(int sectionIndex) {
+ return sectionIndex + GAME_EVENT_DISPATCHER_RADIUS;
+ }
+
+ private static int getGameEventSectionLength(int sectionCount) {
+ return sectionCount + (GAME_EVENT_DISPATCHER_RADIUS * 2);
+ }
+ // petal end
private final LevelChunkTicks<Block> blockTicks;
private final LevelChunkTicks<Fluid> fluidTicks;
@@ -108,7 +119,7 @@ public class LevelChunk extends ChunkAccess {
// Paper end - rewrite light engine
this.tickersInLevel = Maps.newHashMap();
this.level = (ServerLevel) world; // CraftBukkit - type
- this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap();
+ this.gameEventListenerRegistrySections = new GameEventListenerRegistry[getGameEventSectionLength(this.getSectionsCount())]; // petal
Heightmap.Types[] aheightmap_type = Heightmap.Types.values();
int j = aheightmap_type.length;
@@ -398,9 +409,23 @@ public class LevelChunk extends ChunkAccess {
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
- return (GameEventListenerRegistry) this.gameEventListenerRegistrySections.computeIfAbsent(ySectionCoord, (j) -> {
- return new EuclideanGameEventListenerRegistry(worldserver, ySectionCoord, this::removeGameEventListenerRegistry);
- });
+ // petal start
+ int sectionIndex = getGameEventSectionIndex(this.getSectionIndexFromSectionY(ySectionCoord));
+
+ // drop game events that are too far away (32 blocks) from loaded sections
+ // this matches the highest radius of game events in the game
+ if (sectionIndex < 0 || sectionIndex >= this.gameEventListenerRegistrySections.length) {
+ return GameEventListenerRegistry.NOOP;
+ }
+
+ var dispatcher = this.gameEventListenerRegistrySections[sectionIndex];
+
+ if (dispatcher == null) {
+ dispatcher = this.gameEventListenerRegistrySections[sectionIndex] = new EuclideanGameEventListenerRegistry(worldserver, ySectionCoord, this::removeGameEventListenerRegistry);
+ }
+
+ return dispatcher;
+ // petal end
} else {
return super.getListenerRegistry(ySectionCoord);
}
@@ -774,7 +799,7 @@ public class LevelChunk extends ChunkAccess {
}
private void removeGameEventListenerRegistry(int ySectionCoord) {
- this.gameEventListenerRegistrySections.remove(ySectionCoord);
+ this.gameEventListenerRegistrySections[getGameEventSectionIndex(this.getSectionIndexFromSectionY(ySectionCoord))] = null; // petal
}
private void removeBlockEntityTicker(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventListenerRegistry.java b/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventListenerRegistry.java
index 48132c44ddc147eea0f751c1fc568388730104c5..9307fbf34e7794c1786e08a2045b1356421f554c 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventListenerRegistry.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventListenerRegistry.java
@@ -12,8 +12,8 @@ import net.minecraft.world.phys.Vec3;
public class EuclideanGameEventListenerRegistry implements GameEventListenerRegistry {
private final List<GameEventListener> listeners = Lists.newArrayList();
- private final Set<GameEventListener> listenersToRemove = Sets.newHashSet();
- private final List<GameEventListener> listenersToAdd = Lists.newArrayList();
+ //private final Set<GameEventListener> listenersToRemove = Sets.newHashSet(); // petal - not necessary
+ //private final List<GameEventListener> listenersToAdd = Lists.newArrayList(); // petal
private boolean processing;
private final ServerLevel level;
private final int sectionY;
@@ -33,7 +33,7 @@ public class EuclideanGameEventListenerRegistry implements GameEventListenerRegi
@Override
public void register(GameEventListener listener) {
if (this.processing) {
- this.listenersToAdd.add(listener);
+ throw new java.util.ConcurrentModificationException(); // petal - disallow concurrent modification
} else {
this.listeners.add(listener);
}
@@ -44,7 +44,7 @@ public class EuclideanGameEventListenerRegistry implements GameEventListenerRegi
@Override
public void unregister(GameEventListener listener) {
if (this.processing) {
- this.listenersToRemove.add(listener);
+ throw new java.util.ConcurrentModificationException(); // petal - disallow concurrent modification
} else {
this.listeners.remove(listener);
}
@@ -65,7 +65,7 @@ public class EuclideanGameEventListenerRegistry implements GameEventListenerRegi
while(iterator.hasNext()) {
GameEventListener gameEventListener = iterator.next();
- if (this.listenersToRemove.remove(gameEventListener)) {
+ if (false) { // petal - disallow concurrent modification
iterator.remove();
} else {
Optional<Vec3> optional = getPostableListenerPosition(this.level, pos, gameEventListener);
@@ -79,6 +79,8 @@ public class EuclideanGameEventListenerRegistry implements GameEventListenerRegi
this.processing = false;
}
+ // petal start
+ /*
if (!this.listenersToAdd.isEmpty()) {
this.listeners.addAll(this.listenersToAdd);
this.listenersToAdd.clear();
@@ -88,6 +90,8 @@ public class EuclideanGameEventListenerRegistry implements GameEventListenerRegi
this.listeners.removeAll(this.listenersToRemove);
this.listenersToRemove.clear();
}
+ */
+ // petal end
return bl;
}
diff --git a/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java b/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java
index f2d10d58617644a589ecec3e17358c1277795e5d..ea7b3485e81cd1cb8158a1811b78691bb19635fd 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java
@@ -45,6 +45,7 @@ public class GameEventDispatcher {
int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i);
List<GameEvent.ListenerInfo> list = new ArrayList();
GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_a = (gameeventlistener, vec3d1) -> {
+ if (!gameeventlistener.listensToEvent(event, emitter)) return; // petal - if they don't listen, ignore
if (gameeventlistener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) {
list.add(new GameEvent.ListenerInfo(event, emitterPos, emitter, gameeventlistener, vec3d1));
} else {
diff --git a/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java b/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java
index a4148dd326b10b0eb2bc7884691d79dcda60e010..5859d7af9052a150f5d115bb0e2cbd102374f162 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java
@@ -22,4 +22,10 @@ public interface GameEventListener {
public interface Holder<T extends GameEventListener> {
T getListener();
}
+
+ // petal start - add check for seeing if this listener cares about an event
+ default boolean listensToEvent(GameEvent gameEvent, GameEvent.Context context) {
+ return true;
+ }
+ // petal end
}