9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-22 08:29:28 +00:00
Files
Leaf/patches/server/0041-Hearse-Async-entity-ai.patch
2023-01-04 19:27:51 -05:00

688 lines
35 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BuildTools <unconfigured@null.spigotmc.org>
Date: Wed, 4 Jan 2023 11:37:44 +0800
Subject: [PATCH] Hearse: Async entity ai
Original license:
Original project: https://github.com/NaturalCodeClub/Hearse
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..fe4d76875462ac9d408c972b968647af78f2ed14 100644
--- a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
+++ b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
@@ -94,7 +94,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return 1.0 - ((double)this.indexMap.size() / (double)this.listSize);
}
- public int createRawIterator() {
+ public synchronized int createRawIterator() {
if (this.allowSafeIteration()) {
++this.iteratorCount;
}
@@ -105,7 +105,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
- public int advanceRawIterator(final int index) {
+ public synchronized int advanceRawIterator(final int index) {
final E[] elements = this.listElements;
int ret = index + 1;
for (int len = this.listSize; ret < len; ++ret) {
@@ -117,7 +117,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return -1;
}
- public void finishRawIterator() {
+ public synchronized void finishRawIterator() {
if (this.allowSafeIteration() && --this.iteratorCount == 0) {
if (this.getFragFactor() >= this.maxFragFactor) {
this.defrag();
@@ -125,7 +125,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
- public boolean remove(final E element) {
+ public synchronized boolean remove(final E element) {
final int index = this.indexMap.removeInt(element);
if (index >= 0) {
if (this.firstInvalidIndex < 0 || index < this.firstInvalidIndex) {
@@ -144,11 +144,11 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return false;
}
- public boolean contains(final E element) {
+ public synchronized boolean contains(final E element) {
return this.indexMap.containsKey(element);
}
- public boolean add(final E element) {
+ public synchronized boolean add(final E element) {
final int listSize = this.listSize;
final int previous = this.indexMap.putIfAbsent(element, listSize);
@@ -223,30 +223,30 @@ public final class IteratorSafeOrderedReferenceSet<E> {
//this.check();
}
- public E rawGet(final int index) {
+ public synchronized E rawGet(final int index) {
return this.listElements[index];
}
- public int size() {
+ public synchronized int size() {
// always returns the correct amount - listSize can be different
return this.indexMap.size();
}
- public IteratorSafeOrderedReferenceSet.Iterator<E> iterator() {
+ public synchronized IteratorSafeOrderedReferenceSet.Iterator<E> iterator() {
return this.iterator(0);
}
- public IteratorSafeOrderedReferenceSet.Iterator<E> iterator(final int flags) {
+ public synchronized IteratorSafeOrderedReferenceSet.Iterator<E> iterator(final int flags) {
if (this.allowSafeIteration()) {
++this.iteratorCount;
}
return new BaseIterator<>(this, true, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize);
}
- public java.util.Iterator<E> unsafeIterator() {
+ public synchronized java.util.Iterator<E> unsafeIterator() {
return this.unsafeIterator(0);
}
- public java.util.Iterator<E> unsafeIterator(final int flags) {
+ public synchronized java.util.Iterator<E> unsafeIterator(final int flags) {
return new BaseIterator<>(this, false, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize);
}
@@ -273,7 +273,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public boolean hasNext() {
+ public synchronized boolean hasNext() {
if (this.finished) {
return false;
}
@@ -297,7 +297,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public E next() {
+ public synchronized E next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
}
@@ -310,7 +310,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public void remove() {
+ public synchronized void remove() {
final E lastReturned = this.lastReturned;
if (lastReturned == null) {
throw new IllegalStateException();
@@ -320,7 +320,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public void finishedIterating() {
+ public synchronized void finishedIterating() {
if (this.finished || !this.canFinish) {
throw new IllegalStateException();
}
diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
index f597d65d56964297eeeed6c7e77703764178fee0..b3bcafc8bafe1e4a1a2b690499b91e5316a604f1 100644
--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
+++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
@@ -4,6 +4,7 @@ import com.destroystokyo.paper.util.maplist.EntityList;
import io.papermc.paper.chunk.system.entity.EntityLookup;
import io.papermc.paper.util.TickThread;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ChunkHolder;
@@ -34,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 Reference2ObjectMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
protected final EntityList entities = new EntityList();
public ChunkHolder.FullChunkStatus status;
@@ -61,7 +62,7 @@ public final class ChunkEntitySlices {
this.allEntities = new EntityCollectionBySection(this);
this.hardCollidingEntities = new EntityCollectionBySection(this);
- this.entitiesByClass = new Reference2ObjectOpenHashMap<>();
+ this.entitiesByClass = Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>());
this.status = status;
}
@@ -209,7 +210,7 @@ public final class ChunkEntitySlices {
}
for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
if (entry.getKey().isInstance(entity)) {
@@ -234,7 +235,7 @@ public final class ChunkEntitySlices {
}
for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
if (entry.getKey().isInstance(entity)) {
@@ -312,11 +313,11 @@ public final class ChunkEntitySlices {
this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
}
- public boolean isEmpty() {
+ public synchronized boolean isEmpty() {
return this.size == 0;
}
- public int size() {
+ public synchronized int size() {
return this.size;
}
@@ -328,7 +329,7 @@ public final class ChunkEntitySlices {
}
}
- public void add(final E entity) {
+ public synchronized void add(final E entity) {
final int idx = this.size++;
if (idx >= this.storage.length) {
this.resize();
@@ -338,7 +339,7 @@ public final class ChunkEntitySlices {
}
}
- public int indexOf(final E entity) {
+ public synchronized int indexOf(final E entity) {
final E[] storage = this.storage;
for (int i = 0, len = Math.min(this.storage.length, this.size); i < len; ++i) {
@@ -350,7 +351,7 @@ public final class ChunkEntitySlices {
return -1;
}
- public boolean remove(final E entity) {
+ public synchronized boolean remove(final E entity) {
final int idx = this.indexOf(entity);
if (idx == -1) {
return false;
@@ -367,7 +368,7 @@ public final class ChunkEntitySlices {
return true;
}
- public boolean has(final E entity) {
+ public synchronized boolean has(final E entity) {
return this.indexOf(entity) != -1;
}
}
@@ -388,7 +389,7 @@ public final class ChunkEntitySlices {
this.entitiesBySection = new BasicEntityList[sectionCount];
}
- public void addEntity(final Entity entity, final int sectionIndex) {
+ public synchronized void addEntity(final Entity entity, final int sectionIndex) {
BasicEntityList<Entity> list = this.entitiesBySection[sectionIndex];
if (list != null && list.has(entity)) {
@@ -404,7 +405,7 @@ public final class ChunkEntitySlices {
++this.count;
}
- public void removeEntity(final Entity entity, final int sectionIndex) {
+ public synchronized void removeEntity(final Entity entity, final int sectionIndex) {
final BasicEntityList<Entity> list = this.entitiesBySection[sectionIndex];
if (list == null || !list.remove(entity)) {
@@ -419,7 +420,7 @@ public final class ChunkEntitySlices {
}
}
- public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
+ public synchronized void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
if (this.count == 0) {
return;
}
@@ -457,7 +458,7 @@ public final class ChunkEntitySlices {
}
}
- public void getEntitiesWithEnderDragonParts(final Entity except, final AABB box, final List<Entity> into,
+ public synchronized void getEntitiesWithEnderDragonParts(final Entity except, final AABB box, final List<Entity> into,
final Predicate<? super Entity> predicate) {
if (this.count == 0) {
return;
@@ -508,7 +509,7 @@ public final class ChunkEntitySlices {
}
}
- public void getEntitiesWithEnderDragonParts(final Entity except, final Class<?> clazz, final AABB box, final List<Entity> into,
+ public synchronized void getEntitiesWithEnderDragonParts(final Entity except, final Class<?> clazz, final AABB box, final List<Entity> into,
final Predicate<? super Entity> predicate) {
if (this.count == 0) {
return;
@@ -559,7 +560,7 @@ public final class ChunkEntitySlices {
}
}
- public <T extends Entity> void getEntities(final EntityType<?> type, final AABB box, final List<? super T> into,
+ public synchronized <T extends Entity> void getEntities(final EntityType<?> type, final AABB box, final List<? super T> into,
final Predicate<? super T> predicate) {
if (this.count == 0) {
return;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index beb7c22cb63021f26c06f91050361e1b25fcc72d..7c3716ff453f0705a67e5cd81776cf84de46ee2a 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -15,6 +15,7 @@ import com.mojang.logging.LogUtils;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ByteMap;
import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
@@ -25,8 +26,8 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
-import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-import it.unimi.dsi.fastutil.objects.ObjectIterator;
+import it.unimi.dsi.fastutil.objects.*;
+
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
@@ -52,6 +53,7 @@ import java.util.function.IntSupplier;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
+
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
@@ -113,7 +115,6 @@ import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
import org.bukkit.entity.Player;
// CraftBukkit end
-import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
@@ -153,7 +154,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private final Queue<Runnable> unloadQueue;
int viewDistance;
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
- public final ReferenceOpenHashSet<ChunkHolder> needsChangeBroadcasting = new ReferenceOpenHashSet<>();
+ public final ReferenceSet<ChunkHolder> needsChangeBroadcasting = ReferenceSets.synchronize(new ReferenceOpenHashSet<>());
// Paper - rewrite chunk system
// Paper start - optimise checkDespawn
@@ -295,7 +296,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper - rewrite chunk system
this.tickingGenerated = new AtomicInteger();
this.playerMap = new PlayerMap();
- this.entityMap = new Int2ObjectOpenHashMap();
+ this.entityMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap());
this.chunkTypeCache = new Long2ByteOpenHashMap();
this.chunkSaveCooldowns = new Long2LongOpenHashMap();
this.unloadQueue = Queues.newConcurrentLinkedQueue();
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 0ae45cf5a084fd412305e8b2f5dabe608b4eb1c1..686852f5cb6303381c45a673a0daf79a2d3a9dfe 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -6,12 +6,7 @@ import com.mojang.datafixers.DataFixer;
import com.mojang.datafixers.util.Either;
import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BooleanSupplier;
@@ -803,7 +798,7 @@ public class ServerChunkCache extends ChunkSource {
//gameprofilerfiller.popPush("broadcast"); // Purpur
//this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing // Purpur
if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) {
- ReferenceOpenHashSet<ChunkHolder> copy = this.chunkMap.needsChangeBroadcasting.clone();
+ List<ChunkHolder> copy = new ArrayList<>(this.chunkMap.needsChangeBroadcasting);
this.chunkMap.needsChangeBroadcasting.clear();
for (ChunkHolder holder : copy) {
holder.broadcastChanges(holder.getFullChunkNowUnchecked()); // LevelChunks are NEVER unloaded
diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
index 50a9f33aa31e9273c7c52d4bb2b02f0f884f7ba5..6d94aa3c175345f701ec67175fad3fcde4481041 100644
--- a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
+++ b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
@@ -10,12 +10,14 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Collector;
import java.util.stream.Collectors;
public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
- private final Map<Class<?>, List<T>> byClass = Maps.newHashMap();
+ private final Map<Class<?>, List<T>> byClass = Maps.newConcurrentMap();
private final Class<T> baseClass;
- private final List<T> allInstances = Lists.newArrayList();
+ private final List<T> allInstances = Lists.newCopyOnWriteArrayList();
public ClassInstanceMultiMap(Class<T> elementType) {
this.baseClass = elementType;
@@ -58,22 +60,24 @@ public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
if (!this.baseClass.isAssignableFrom(type)) {
throw new IllegalArgumentException("Don't know how to search for " + type);
} else {
- List<? extends T> list = this.byClass.computeIfAbsent(type, (typeClass) -> {
- return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList());
- });
- return Collections.unmodifiableCollection(list);
+ List<? extends T> list = this.byClass.computeIfAbsent(type, (typeClass) -> this.allInstances.stream().filter(typeClass::isInstance).collect(toList()));
+ return (Collection<S>) Collections.unmodifiableCollection(list);
}
}
@Override
public Iterator<T> iterator() {
- return (Iterator<T>)(this.allInstances.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.allInstances.iterator()));
+ return this.allInstances.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.allInstances.iterator());
}
public List<T> getAllInstances() {
return ImmutableList.copyOf(this.allInstances);
}
+ public static <T> Collector<T, ?, List<T>> toList() {
+ return Collectors.toCollection(CopyOnWriteArrayList::new);
+ }
+
@Override
public int size() {
return this.allInstances.size();
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 29fa9ad2223de668c15a5e5b433704b2c4765610..a49247b9007d859928aab21ed05cfa86ad1a13cf 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -23,6 +23,7 @@ import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
@@ -216,12 +217,14 @@ public abstract class Mob extends LivingEntity {
public void inactiveTick() {
super.inactiveTick();
boolean isThrottled = gg.pufferfish.pufferfish.PufferfishConfig.throttleInactiveGoalSelectorTick && _pufferfish_inactiveTickDisableCounter++ % 20 != 0; // Pufferfish - throttle inactive goal selector ticking
- if (this.goalSelector.inactiveTick(this.activatedPriority, true) && !isThrottled) { // Pufferfish - pass activated priroity // Pufferfish - throttle inactive goal selector ticking
- this.goalSelector.tick();
- }
- if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priority
- this.targetSelector.tick();
- }
+ MinecraftServer.getServer().asyncExecutor.executeWithCallBack(()->{
+ if (this.goalSelector.inactiveTick(this.activatedPriority, true) && !isThrottled) { // Pufferfish - pass activated priroity // Pufferfish - throttle inactive goal selector ticking
+ this.goalSelector.tick();
+ }
+ if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priority
+ this.targetSelector.tick();
+ }
+ },()->{});
}
// Paper end
@@ -877,43 +880,32 @@ public abstract class Mob extends LivingEntity {
//this.level.getProfiler().push("sensing"); // Purpur
if (i % 10 == 0) this.sensing.tick(); // petal - only refresh line of sight cache every half second
//this.level.getProfiler().pop(); // Purpur
-
- if (i % 2 != 0 && this.tickCount > 1) {
- //this.level.getProfiler().push("targetSelector"); // Purpur
- if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.targetSelector.tickRunningGoals(false);
- //this.level.getProfiler().pop(); // Purpur
- //this.level.getProfiler().push("goalSelector"); // Purpur
- if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.goalSelector.tickRunningGoals(false);
- //this.level.getProfiler().pop(); // Purpur
- } else {
- //this.level.getProfiler().push("targetSelector"); // Purpur
- if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.targetSelector.tick();
- //this.level.getProfiler().pop(); // Purpur
- //this.level.getProfiler().push("goalSelector"); // Purpur
- if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.goalSelector.tick();
- //this.level.getProfiler().pop(); // Purpur
- }
-
- //this.level.getProfiler().push("navigation"); // Purpur
- this.navigation.tick();
- //this.level.getProfiler().pop(); // Purpur
- //this.level.getProfiler().push("mob tick"); // Purpur
- this.customServerAiStep();
- //this.level.getProfiler().pop(); // Purpur
- //this.level.getProfiler().push("controls"); // Purpur
- //this.level.getProfiler().push("move"); // Purpur
- this.moveControl.tick();
- //this.level.getProfiler().popPush("look"); // Purpur
- this.lookControl.tick();
- //this.level.getProfiler().popPush("jump"); // Purpur
- this.jumpControl.tick();
- //this.level.getProfiler().pop(); // Purpur
- //this.level.getProfiler().pop(); // Purpur
- this.sendDebugPackets();
+ MinecraftServer.getServer().asyncExecutor.executeWithCallBack(() -> {
+ if (i % 2 != 0 && this.tickCount > 1) {
+ //this.level.getProfiler().push("targetSelector"); // Purpur
+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
+ this.targetSelector.tickRunningGoals(false);
+ //this.level.getProfiler().pop(); // Purpur
+ //this.level.getProfiler().push("goalSelector"); // Purpur
+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
+ this.goalSelector.tickRunningGoals(false);
+ //this.level.getProfiler().pop(); // Purpur
+ } else {
+ //this.level.getProfiler().push("targetSelector"); // Purpur
+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
+ this.targetSelector.tick();
+ //this.level.getProfiler().pop(); // Purpur
+ //this.level.getProfiler().push("goalSelector"); // Purpur
+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
+ this.goalSelector.tick();
+ //this.level.getProfiler().pop(); // Purpur
+ }
+ this.navigation.tick();
+ this.customServerAiStep();
+ this.moveControl.tick();
+ this.lookControl.tick();
+ this.jumpControl.tick();
+ }, this::sendDebugPackets);
}
protected void sendDebugPackets() {
diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
index 097007c1c25ba55d9916fc820dd1d1149d81f6f4..16eec12db529dd513e0971289a9326652369de58 100644
--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java
@@ -30,11 +30,11 @@ import org.slf4j.Logger;
public class GossipContainer {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int DISCARD_THRESHOLD = 2;
- public final Map<UUID, GossipContainer.EntityGossips> gossips = Maps.newHashMap();
+ public final Map<UUID, GossipContainer.EntityGossips> gossips = Maps.newConcurrentMap();
@VisibleForDebug
public Map<UUID, Object2IntMap<GossipType>> getGossipEntries() {
- Map<UUID, Object2IntMap<GossipType>> map = Maps.newHashMap();
+ Map<UUID, Object2IntMap<GossipType>> map = Maps.newConcurrentMap();
this.gossips.keySet().forEach((uuid) -> {
GossipContainer.EntityGossips entityGossips = this.gossips.get(uuid);
map.put(uuid, entityGossips.entries);
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 2d222e383d48a1a32eebdb722d770b4fc6c0aca7..eb5257fabef397566e784247922fb27e61f96313 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -274,16 +274,18 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
if (this.getUnhappyCounter() > 0) {
this.setUnhappyCounter(this.getUnhappyCounter() - 1);
}
- if (this.isEffectiveAi()) {
- if (level.spigotConfig.tickInactiveVillagers) {
- this.customServerAiStep();
- } else {
- this.mobTick(true);
+ MinecraftServer.getServer().asyncExecutor.executeWithCallBack(()->{
+ if (this.isEffectiveAi()) {
+ if (level.spigotConfig.tickInactiveVillagers) {
+ this.customServerAiStep();
+ } else {
+ this.mobTick(true);
+ }
}
- }
- maybeDecayGossip();
+ },()->{
+ maybeDecayGossip();
+ });
// Paper end
-
super.inactiveTick();
}
// Spigot End
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
index d45d832232be5017dde53816191c2b1830a0da32..f73f78e2f7c6e3eae66f7608a92854b3246e153d 100644
--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
+++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
@@ -8,13 +8,15 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
+
+import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import net.minecraft.util.AbortableIterationConsumer;
import org.slf4j.Logger;
public class EntityLookup<T extends EntityAccess> {
private static final Logger LOGGER = LogUtils.getLogger();
- private final Int2ObjectMap<T> byId = new Int2ObjectLinkedOpenHashMap<>();
- private final Map<UUID, T> byUuid = Maps.newHashMap();
+ private final Int2ObjectMap<T> byId = Int2ObjectMaps.synchronize(new Int2ObjectLinkedOpenHashMap<>());
+ private final Map<UUID, T> byUuid = Maps.newConcurrentMap();
public <U extends T> void getEntities(EntityTypeTest<T, U> filter, AbortableIterationConsumer<U> consumer) {
for(T entityAccess : this.byId.values()) {
diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
index a77985b2dd7137d8eea03909403fc08e89376d73..6bcbbbfc39432076a3d7714ecc2d05d9112d405c 100644
--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
+++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -4,12 +4,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
-import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.*;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
-import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
-import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -39,15 +35,15 @@ import org.bukkit.craftbukkit.event.CraftEventFactory;
public class PersistentEntitySectionManager<T extends EntityAccess> implements AutoCloseable {
static final Logger LOGGER = LogUtils.getLogger();
- final Set<UUID> knownUuids = Sets.newHashSet();
+ final Set<UUID> knownUuids = Sets.newConcurrentHashSet();
final LevelCallback<T> callbacks;
public final EntityPersistentStorage<T> permanentStorage;
private final EntityLookup<T> visibleEntityStorage = new EntityLookup<>();
final EntitySectionStorage<T> sectionStorage;
private final LevelEntityGetter<T> entityGetter;
- private final Long2ObjectMap<Visibility> chunkVisibility = new Long2ObjectOpenHashMap();
- private final Long2ObjectMap<PersistentEntitySectionManager.ChunkLoadStatus> chunkLoadStatuses = new Long2ObjectOpenHashMap();
- private final LongSet chunksToUnload = new LongOpenHashSet();
+ private final Long2ObjectMap<Visibility> chunkVisibility = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap());
+ private final Long2ObjectMap<PersistentEntitySectionManager.ChunkLoadStatus> chunkLoadStatuses = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap());
+ private final LongSet chunksToUnload = LongSets.synchronize(new LongOpenHashSet());
private final Queue<ChunkEntities<T>> loadingInbox = Queues.newConcurrentLinkedQueue();
public PersistentEntitySectionManager(Class<T> entityClass, LevelCallback<T> handler, EntityPersistentStorage<T> dataAccess) {
diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
index b1c594dc6a6b8a6c737b99272acab9e7dbd0ed63..4aedee56077159aaf613033b688d2be6833f1ad1 100644
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
+++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
@@ -3,7 +3,10 @@ package net.minecraft.world.level.redstone;
import com.mojang.logging.LogUtils;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Deque;
import java.util.List;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -16,8 +19,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
private static final Logger LOGGER = LogUtils.getLogger();
private final Level level;
private final int maxChainedNeighborUpdates;
- private final ArrayDeque<CollectingNeighborUpdater.NeighborUpdates> stack = new ArrayDeque<>();
- private final List<CollectingNeighborUpdater.NeighborUpdates> addedThisLayer = new ArrayList<>();
+ private final Deque<NeighborUpdates> stack = new ConcurrentLinkedDeque<>();
+ private final List<CollectingNeighborUpdater.NeighborUpdates> addedThisLayer = new CopyOnWriteArrayList<>();
private int count = 0;
public CollectingNeighborUpdater(Level world, int maxChainDepth) {
@@ -26,22 +29,22 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
}
@Override
- public void shapeUpdate(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) {
+ public synchronized void shapeUpdate(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) {
this.addAndRun(pos, new CollectingNeighborUpdater.ShapeUpdate(direction, neighborState, pos.immutable(), neighborPos.immutable(), flags));
}
@Override
- public void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos sourcePos) {
+ public synchronized void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos sourcePos) {
this.addAndRun(pos, new CollectingNeighborUpdater.SimpleNeighborUpdate(pos, sourceBlock, sourcePos.immutable()));
}
@Override
- public void neighborChanged(BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
+ public synchronized void neighborChanged(BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
this.addAndRun(pos, new CollectingNeighborUpdater.FullNeighborUpdate(state, pos.immutable(), sourceBlock, sourcePos.immutable(), notify));
}
@Override
- public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block sourceBlock, @Nullable Direction except) {
+ public synchronized void updateNeighborsAtExceptFromFacing(BlockPos pos, Block sourceBlock, @Nullable Direction except) {
this.addAndRun(pos, new CollectingNeighborUpdater.MultiNeighborUpdate(pos.immutable(), sourceBlock, except));
}