Removed unstable patches from petal

This commit is contained in:
nostalgic853
2022-10-26 15:48:09 +08:00
parent cef3cbb0a1
commit 47cb3884ed
5 changed files with 0 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,363 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: peaches94 <peachescu94@gmail.com>
Date: Sat, 2 Jul 2022 00:35:56 -0500
Subject: [PATCH] Multithreaded tracker
Original code by Bloom-host, licensed under GNU General Public License v3.0
You can find the original code on https://github.com/Bloom-host/Petal
Co-authored-by: Paul Sauve <paul@technove.co>
Co-authored-by: Kevin Raneri <kevin.raneri@gmail.com>
based off the airplane multithreaded tracker this patch properly handles
concurrent accesses everywhere, as well as being much simpler to maintain
some things are too unsafe to run off the main thread so we don't attempt to do
that. this multithreaded tracker remains accurate, non-breaking and fast
we also learned from pufferfish core that changes have to be sent ordered
now we do that in an optimized way
diff --git a/src/main/java/host/bloom/tracker/MultithreadedTracker.java b/src/main/java/host/bloom/tracker/MultithreadedTracker.java
new file mode 100644
index 0000000000000000000000000000000000000000..d27b7224ed2bcc63386dc46c33bfb8b272d91f92
--- /dev/null
+++ b/src/main/java/host/bloom/tracker/MultithreadedTracker.java
@@ -0,0 +1,154 @@
+package host.bloom.tracker;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet;
+import io.papermc.paper.world.ChunkEntitySlices;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ChunkMap;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.level.chunk.LevelChunk;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MultithreadedTracker {
+
+ private enum TrackerStage {
+ UPDATE_PLAYERS,
+ SEND_CHANGES
+ }
+
+ private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors());
+ private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder()
+ .setNameFormat("petal-tracker-%d")
+ .setPriority(Thread.NORM_PRIORITY - 2)
+ .build());
+
+ private final IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks;
+ private final AtomicInteger taskIndex = new AtomicInteger();
+
+ private final ConcurrentLinkedQueue<Runnable> mainThreadTasks;
+ private final AtomicInteger finishedTasks = new AtomicInteger();
+
+ public MultithreadedTracker(IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks, ConcurrentLinkedQueue<Runnable> mainThreadTasks) {
+ this.entityTickingChunks = entityTickingChunks;
+ this.mainThreadTasks = mainThreadTasks;
+ }
+
+ public void tick() {
+ int iterator = this.entityTickingChunks.createRawIterator();
+
+ if (iterator == -1) {
+ return;
+ }
+
+ // start with updating players
+ try {
+ this.taskIndex.set(iterator);
+ this.finishedTasks.set(0);
+
+ for (int i = 0; i < parallelism; i++) {
+ trackerExecutor.execute(this::runUpdatePlayers);
+ }
+
+ while (this.taskIndex.get() < this.entityTickingChunks.getListSize()) {
+ this.runMainThreadTasks();
+ this.handleChunkUpdates(5); // assist
+ }
+
+ while (this.finishedTasks.get() != parallelism) {
+ this.runMainThreadTasks();
+ }
+
+ this.runMainThreadTasks(); // finish any remaining tasks
+ } finally {
+ this.entityTickingChunks.finishRawIterator();
+ }
+
+ // then send changes
+ iterator = this.entityTickingChunks.createRawIterator();
+
+ if (iterator == -1) {
+ return;
+ }
+
+ try {
+ do {
+ LevelChunk chunk = this.entityTickingChunks.rawGet(iterator);
+
+ if (chunk != null) {
+ this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES);
+ }
+ } while (++iterator < this.entityTickingChunks.getListSize());
+ } finally {
+ this.entityTickingChunks.finishRawIterator();
+ }
+ }
+
+ private void runMainThreadTasks() {
+ try {
+ Runnable task;
+ while ((task = this.mainThreadTasks.poll()) != null) {
+ task.run();
+ }
+ } catch (Throwable throwable) {
+ MinecraftServer.LOGGER.warn("Tasks failed while ticking track queue", throwable);
+ }
+ }
+
+ private void runUpdatePlayers() {
+ try {
+ while (handleChunkUpdates(10));
+ } finally {
+ this.finishedTasks.incrementAndGet();
+ }
+ }
+
+ private boolean handleChunkUpdates(int tasks) {
+ int index;
+ while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.getListSize()) {
+ for (int i = index; i < index + tasks && i < this.entityTickingChunks.getListSize(); i++) {
+ LevelChunk chunk = this.entityTickingChunks.rawGet(i);
+ if (chunk != null) {
+ try {
+ this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS);
+ } catch (Throwable throwable) {
+ MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable);
+ }
+
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) {
+ final ChunkEntitySlices entitySlices = chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ);
+ if (entitySlices == null) {
+ return;
+ }
+
+ final Entity[] rawEntities = entitySlices.entities.getRawData();
+ final ChunkMap chunkMap = chunk.level.chunkSource.chunkMap;
+
+ for (int i = 0; i < rawEntities.length; i++) {
+ Entity entity = rawEntities[i];
+ if (entity != null) {
+ ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId());
+ if (entityTracker != null) {
+ if (trackerStage == TrackerStage.SEND_CHANGES) {
+ entityTracker.serverEntity.sendChanges();
+ } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) {
+ entityTracker.updatePlayers(entityTracker.entity.getPlayersInTrackRange());
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
index 0fd814f1d65c111266a2b20f86561839a4cef755..169ac3ad1b1e8e3e1874ada2471e478233c6ada7 100644
--- a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
+++ b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
@@ -15,7 +15,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
/* list impl */
protected E[] listElements;
- protected int listSize;
+ protected int listSize; public int getListSize() { return this.listSize; } // petal - expose listSize
protected final double maxFragFactor;
diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
index f597d65d56964297eeeed6c7e77703764178fee0..665c377e2d0d342f4dcc89c4cbdfcc9e4b96e95c 100644
--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
+++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
@@ -35,7 +35,7 @@ public final class ChunkEntitySlices {
protected final EntityCollectionBySection allEntities;
protected final EntityCollectionBySection hardCollidingEntities;
protected final Reference2ObjectOpenHashMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
- protected final EntityList entities = new EntityList();
+ public final EntityList entities = new EntityList();
public ChunkHolder.FullChunkStatus status;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 9976630fad886392057f642e84f919f0b95cc040..c4284894258df0b0bcc2d86c5a6da0047b994191 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1236,9 +1236,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
entity.tracker = null; // Paper - We're no longer tracked
}
+ // petal start - multithreaded tracker
+ private @Nullable host.bloom.tracker.MultithreadedTracker multithreadedTracker;
+ private final java.util.concurrent.ConcurrentLinkedQueue<Runnable> trackerMainThreadTasks = new java.util.concurrent.ConcurrentLinkedQueue<>();
+ private boolean tracking = false;
+
+ public void runOnTrackerMainThread(final Runnable runnable) {
+ if (this.tracking) {
+ this.trackerMainThreadTasks.add(runnable);
+ } else {
+ runnable.run();
+ }
+ }
+
// Paper start - optimised tracker
private final void processTrackQueue() {
+ if (true) {
+ if (this.multithreadedTracker == null) {
+ this.multithreadedTracker = new host.bloom.tracker.MultithreadedTracker(this.level.chunkSource.entityTickingChunks, this.trackerMainThreadTasks);
+ }
+
+ this.tracking = true;
+ try {
+ this.multithreadedTracker.tick();
+ } finally {
+ this.tracking = false;
+ }
+ return;
+ }
+ // petal end
+
this.level.timings.tracker1.startTiming();
+ //this.level.timings.tracker1.startTiming(); // Purpur
try {
for (TrackedEntity tracker : this.entityMap.values()) {
// update tracker entry
@@ -1461,11 +1490,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public class TrackedEntity {
- final ServerEntity serverEntity;
- final Entity entity;
+ public final ServerEntity serverEntity; // petal -> public
+ public final Entity entity; // petal -> public
private final int range;
SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = new ReferenceOpenHashSet<>(); // Paper - optimise map impl
+ public final Set<ServerPlayerConnection> seenBy = it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Paper - optimise map impl // petal - sync
public TrackedEntity(Entity entity, int i, int j, boolean flag) {
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
@@ -1477,7 +1506,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start - use distance map to optimise tracker
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> lastTrackerCandidates;
- final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates) {
+ public final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newTrackerCandidates) { // petal -> public
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> oldTrackerCandidates = this.lastTrackerCandidates;
this.lastTrackerCandidates = newTrackerCandidates;
@@ -1549,7 +1578,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void removePlayer(ServerPlayer player) {
- org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
+ //org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot // petal - we can remove async too
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
@@ -1557,7 +1586,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void updatePlayer(ServerPlayer player) {
- org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
+ //org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot // petal - we can update async
if (player != this.entity) {
// Paper start - remove allocation of Vec3D here
// Vec3 vec3d = player.position().subtract(this.entity.position());
diff --git a/src/main/java/net/minecraft/server/level/ServerBossEvent.java b/src/main/java/net/minecraft/server/level/ServerBossEvent.java
index ca42c2642a729b90d22b968af7258f3aee72e14b..40261b80d947a6be43465013fae5532197cfe721 100644
--- a/src/main/java/net/minecraft/server/level/ServerBossEvent.java
+++ b/src/main/java/net/minecraft/server/level/ServerBossEvent.java
@@ -13,7 +13,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.BossEvent;
public class ServerBossEvent extends BossEvent {
- private final Set<ServerPlayer> players = Sets.newHashSet();
+ private final Set<ServerPlayer> players = Sets.newConcurrentHashSet(); // petal - players can be removed in async tracking
private final Set<ServerPlayer> unmodifiablePlayers = Collections.unmodifiableSet(this.players);
public boolean visible = true;
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 3441339e1ba5efb0e25c16fa13cb65d2fbdafc42..555336cf6700566e8a99e0f0cd6f0cc41b6c5ba0 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -249,14 +249,18 @@ public class ServerEntity {
public void removePairing(ServerPlayer player) {
this.entity.stopSeenByPlayer(player);
- player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()}));
+ // petal start - ensure main thread
+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() ->
+ player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()}))
+ );
+ // petal end
}
public void addPairing(ServerPlayer player) {
ServerGamePacketListenerImpl playerconnection = player.connection;
Objects.requireNonNull(player.connection);
- this.sendPairingData(playerconnection::send, player); // CraftBukkit - add player
+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> this.sendPairingData(playerconnection::send, player)); // CraftBukkit - add player // petal - main thread
this.entity.startSeenByPlayer(player);
}
@@ -362,19 +366,30 @@ public class ServerEntity {
SynchedEntityData datawatcher = this.entity.getEntityData();
if (datawatcher.isDirty()) {
- this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false));
+ // Petal start - sync
+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() ->
+ this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false))
+ );
+ // Petal end
}
if (this.entity instanceof LivingEntity) {
Set<AttributeInstance> set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes();
if (!set.isEmpty()) {
+ // Petal start - sync
+ final var copy = Lists.newArrayList(set);
+ ((ServerLevel) this.entity.level).chunkSource.chunkMap.runOnTrackerMainThread(() -> {
+
// CraftBukkit start - Send scaled max health
if (this.entity instanceof ServerPlayer) {
- ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false);
+ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(copy, false);
}
// CraftBukkit end
- this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set));
+ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy));
+
+ });
+ // Petal end
}
set.clear();

View File

@@ -1,204 +0,0 @@
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] Reduce work done by game event system
Original code by Bloom-host, licensed under GNU General Public License v3.0
You can find the original code on https://github.com/Bloom-host/Petal
1. going into game event dispatching can be expensive so run the checks before dispatching
2. euclideangameeventdispatcher is not used concurrently so we ban that usage for improved performance with allays
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 26316eae266a0e19b3cacc39ed1c9263f1cd58ea..446a08355cfcb380280b102ae0b367ffa7334005 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1705,6 +1705,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (chunk != null) {
for (int j2 = k; j2 <= j1; ++j2) {
flag |= chunk.getEventDispatcher(j2).walkListeners(event, emitterPos, emitter, (gameeventlistener, vec3d1) -> {
+ if (!gameeventlistener.listensToEvent(event, emitter)) return; // petal - if they don't listen, ignore
(gameeventlistener.handleEventsImmediately() ? list : this.gameEventMessages).add(new GameEvent.Message(event, emitterPos, emitter, gameeventlistener, vec3d1));
});
}
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 22c309343299e60ed8028229b7f134109001ff35..d5947d29295ddc93ba8ac1c0fc61f7badad582c4 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
@@ -85,6 +85,13 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
}
}
+ // petal start
+ @Override
+ public boolean listensToEvent(GameEvent gameEvent, GameEvent.Context context) {
+ return !this.isRemoved() && gameEvent == GameEvent.ENTITY_DIE && context.sourceEntity() instanceof LivingEntity;
+ }
+ // petal end
+
public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) {
org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep.
blockEntity.sculkSpreader.updateCursors(world, pos, world.getRandom(), true);
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 b89dad36bf09fdab340efc83d09992b707cd321a..71e84572fff4d78e3872b3ccc4767d973bfb9a6e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -84,7 +84,18 @@ public class LevelChunk extends ChunkAccess {
private Supplier<ChunkHolder.FullChunkStatus> fullStatus;
@Nullable
private LevelChunk.PostLoadProcessor postLoad;
- private final Int2ObjectMap<GameEventDispatcher> gameEventDispatcherSections;
+ // petal start
+ private final GameEventDispatcher[] gameEventDispatcherSections;
+ 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;
@@ -113,7 +124,7 @@ public class LevelChunk extends ChunkAccess {
this.tickersInLevel = Maps.newHashMap();
this.clientLightReady = false;
this.level = (ServerLevel) world; // CraftBukkit - type
- this.gameEventDispatcherSections = new Int2ObjectOpenHashMap();
+ this.gameEventDispatcherSections = new GameEventDispatcher[getGameEventSectionLength(this.getSectionsCount())]; // petal
Heightmap.Types[] aheightmap_type = Heightmap.Types.values();
int j = aheightmap_type.length;
@@ -446,9 +457,23 @@ public class LevelChunk extends ChunkAccess {
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
- return (GameEventDispatcher) this.gameEventDispatcherSections.computeIfAbsent(ySectionCoord, (j) -> {
- return new EuclideanGameEventDispatcher(worldserver);
- });
+ // 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.gameEventDispatcherSections.length) {
+ return GameEventDispatcher.NOOP;
+ }
+
+ var dispatcher = this.gameEventDispatcherSections[sectionIndex];
+
+ if (dispatcher == null) {
+ dispatcher = this.gameEventDispatcherSections[sectionIndex] = new EuclideanGameEventDispatcher(worldserver);
+ }
+
+ return dispatcher;
+ // petal end
} else {
return super.getEventDispatcher(ySectionCoord);
}
@@ -812,7 +837,7 @@ public class LevelChunk extends ChunkAccess {
gameeventdispatcher.unregister(gameeventlistener);
if (gameeventdispatcher.isEmpty()) {
- this.gameEventDispatcherSections.remove(i);
+ this.gameEventDispatcherSections[getGameEventSectionIndex(this.getSectionIndexFromSectionY(i))] = null; // petal
}
}
}
diff --git a/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventDispatcher.java b/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventDispatcher.java
index 0dd708ebe81f73710de51215529c05ec61837dd3..f5b402efa86f824c460db8cac20c1c2b090f82d0 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventDispatcher.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/EuclideanGameEventDispatcher.java
@@ -13,8 +13,8 @@ import net.minecraft.world.phys.Vec3;
public class EuclideanGameEventDispatcher implements GameEventDispatcher {
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;
@@ -30,7 +30,7 @@ public class EuclideanGameEventDispatcher implements GameEventDispatcher {
@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);
}
@@ -41,7 +41,7 @@ public class EuclideanGameEventDispatcher implements GameEventDispatcher {
@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);
}
@@ -58,7 +58,7 @@ public class EuclideanGameEventDispatcher implements GameEventDispatcher {
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);
@@ -72,6 +72,8 @@ public class EuclideanGameEventDispatcher implements GameEventDispatcher {
this.processing = false;
}
+ // petal start
+ /*
if (!this.listenersToAdd.isEmpty()) {
this.listeners.addAll(this.listenersToAdd);
this.listenersToAdd.clear();
@@ -81,6 +83,8 @@ public class EuclideanGameEventDispatcher implements GameEventDispatcher {
this.listeners.removeAll(this.listenersToRemove);
this.listenersToRemove.clear();
}
+ */
+ // petal end
return bl;
}
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 e5601afe8b739da518f36ae306f5e0cb252238f0..bc8f04424c5e8c416d6988f0e06d8cadbb400ca7 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/GameEventListener.java
@@ -12,4 +12,10 @@ public interface GameEventListener {
int getListenerRadius();
boolean handleGameEvent(ServerLevel world, GameEvent.Message event);
+
+ // petal start - add check for seeing if this listener cares about an event
+ default boolean listensToEvent(net.minecraft.world.level.gameevent.GameEvent gameEvent, net.minecraft.world.level.gameevent.GameEvent.Context context) {
+ return true;
+ }
+ // petal end
}
diff --git a/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationListener.java b/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationListener.java
index e45f54534bbf054eaf0008546ff459d4c11ddd50..e49d0d1c2a539fcd7e75262c4010475193964287 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationListener.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/vibrations/VibrationListener.java
@@ -162,6 +162,13 @@ public class VibrationListener implements GameEventListener {
return true;
}
+ // petal start
+ @Override
+ public boolean listensToEvent(GameEvent gameEvent, GameEvent.Context context) {
+ return this.receivingEvent == null && gameEvent.is(this.config.getListenableEvents());
+ }
+ // petal end
+
public interface VibrationListenerConfig {
default TagKey<GameEvent> getListenableEvents() {

View File

@@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: peaches94 <peachescu94@gmail.com>
Date: Sun, 10 Jul 2022 15:44:38 -0500
Subject: [PATCH] Reduce sensor work
Original code by Bloom-host, licensed under GNU General Public License v3.0
You can find the original code on https://github.com/Bloom-host/Petal
this patch is focused around the sensors used for ai
delete the line of sight cache less often and use a faster nearby comparison
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 87655d7c3dfbbd6bf348d693445c71d5601ed9c3..149d3db91b546a8428271e22d91036f8b8f9f639 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1011,20 +1011,22 @@ public abstract class LivingEntity extends Entity {
}
if (entity != null) {
- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
+ // petal start - only do itemstack lookup if we need to
+ //ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
EntityType<?> entitytypes = entity.getType();
// Purpur start
- if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL)) {
+ if (entitytypes == EntityType.SKELETON && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.SKELETON_SKULL)) {
d0 *= entity.level.purpurConfig.skeletonHeadVisibilityPercent;
}
- else if (entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD)) {
+ else if (entitytypes == EntityType.ZOMBIE && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.ZOMBIE_HEAD)) {
d0 *= entity.level.purpurConfig.zombieHeadVisibilityPercent;
}
- else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) {
+ else if (entitytypes == EntityType.CREEPER && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.CREEPER_HEAD)) {
d0 *= entity.level.purpurConfig.creeperHeadVisibilityPercent;
}
// Purpur end
+ // petal end
// Purpur start
if (entity instanceof LivingEntity entityliving) {
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index d5e3bd662da349fc2ee58c7800d79c60300f33b3..0981873ee37fc839035b8398bac03d15adecb301 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -884,10 +884,10 @@ public abstract class Mob extends LivingEntity {
return;
}
// Paper end
+ int i = this.level.getServer().getTickCount() + this.getId(); // petal - move up
//this.level.getProfiler().push("sensing"); // Purpur
- this.sensing.tick();
+ if (i % 10 == 0) this.sensing.tick(); // petal - only refresh line of sight cache every half second
//this.level.getProfiler().pop(); // Purpur
- int i = this.level.getServer().getTickCount() + this.getId();
if (i % 2 != 0 && this.tickCount > 1) {
//this.level.getProfiler().push("targetSelector"); // Purpur