From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: BuildTools 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 { 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 { } } - 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 { 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 { } } - 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 { 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 { //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 iterator() { + public synchronized IteratorSafeOrderedReferenceSet.Iterator iterator() { return this.iterator(0); } - public IteratorSafeOrderedReferenceSet.Iterator iterator(final int flags) { + public synchronized IteratorSafeOrderedReferenceSet.Iterator 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 unsafeIterator() { + public synchronized java.util.Iterator unsafeIterator() { return this.unsafeIterator(0); } - public java.util.Iterator unsafeIterator(final int flags) { + public synchronized java.util.Iterator 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 { } @Override - public boolean hasNext() { + public synchronized boolean hasNext() { if (this.finished) { return false; } @@ -297,7 +297,7 @@ public final class IteratorSafeOrderedReferenceSet { } @Override - public E next() { + public synchronized E next() { if (!this.hasNext()) { throw new NoSuchElementException(); } @@ -310,7 +310,7 @@ public final class IteratorSafeOrderedReferenceSet { } @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 { } @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, EntityCollectionBySection> entitiesByClass; + protected final Reference2ObjectMap, 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, EntityCollectionBySection>> iterator = - this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) { + this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) { final Reference2ObjectMap.Entry, EntityCollectionBySection> entry = iterator.next(); if (entry.getKey().isInstance(entity)) { @@ -234,7 +235,7 @@ public final class ChunkEntitySlices { } for (final Iterator, EntityCollectionBySection>> iterator = - this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) { + this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) { final Reference2ObjectMap.Entry, 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 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 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 into, final Predicate predicate) { + public synchronized void getEntities(final Entity except, final AABB box, final List into, final Predicate 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 into, + public synchronized void getEntitiesWithEnderDragonParts(final Entity except, final AABB box, final List into, final Predicate 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 into, + public synchronized void getEntitiesWithEnderDragonParts(final Entity except, final Class clazz, final AABB box, final List into, final Predicate predicate) { if (this.count == 0) { return; @@ -559,7 +560,7 @@ public final class ChunkEntitySlices { } } - public void getEntities(final EntityType type, final AABB box, final List into, + public synchronized void getEntities(final EntityType type, final AABB box, final List into, final Predicate 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 unloadQueue; int viewDistance; public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper - public final ReferenceOpenHashSet needsChangeBroadcasting = new ReferenceOpenHashSet<>(); + public final ReferenceSet 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 copy = this.chunkMap.needsChangeBroadcasting.clone(); + List 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 extends AbstractCollection { - private final Map, List> byClass = Maps.newHashMap(); + private final Map, List> byClass = Maps.newConcurrentMap(); private final Class baseClass; - private final List allInstances = Lists.newArrayList(); + private final List allInstances = Lists.newCopyOnWriteArrayList(); public ClassInstanceMultiMap(Class elementType) { this.baseClass = elementType; @@ -58,22 +60,24 @@ public class ClassInstanceMultiMap extends AbstractCollection { if (!this.baseClass.isAssignableFrom(type)) { throw new IllegalArgumentException("Don't know how to search for " + type); } else { - List list = this.byClass.computeIfAbsent(type, (typeClass) -> { - return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList()); - }); - return Collections.unmodifiableCollection(list); + List list = this.byClass.computeIfAbsent(type, (typeClass) -> this.allInstances.stream().filter(typeClass::isInstance).collect(toList())); + return (Collection) Collections.unmodifiableCollection(list); } } @Override public Iterator iterator() { - return (Iterator)(this.allInstances.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.allInstances.iterator())); + return this.allInstances.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.allInstances.iterator()); } public List getAllInstances() { return ImmutableList.copyOf(this.allInstances); } + public static Collector> 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 gossips = Maps.newHashMap(); + public final Map gossips = Maps.newConcurrentMap(); @VisibleForDebug public Map> getGossipEntries() { - Map> map = Maps.newHashMap(); + Map> 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 { private static final Logger LOGGER = LogUtils.getLogger(); - private final Int2ObjectMap byId = new Int2ObjectLinkedOpenHashMap<>(); - private final Map byUuid = Maps.newHashMap(); + private final Int2ObjectMap byId = Int2ObjectMaps.synchronize(new Int2ObjectLinkedOpenHashMap<>()); + private final Map byUuid = Maps.newConcurrentMap(); public void getEntities(EntityTypeTest filter, AbortableIterationConsumer 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 implements AutoCloseable { static final Logger LOGGER = LogUtils.getLogger(); - final Set knownUuids = Sets.newHashSet(); + final Set knownUuids = Sets.newConcurrentHashSet(); final LevelCallback callbacks; public final EntityPersistentStorage permanentStorage; private final EntityLookup visibleEntityStorage = new EntityLookup<>(); final EntitySectionStorage sectionStorage; private final LevelEntityGetter entityGetter; - private final Long2ObjectMap chunkVisibility = new Long2ObjectOpenHashMap(); - private final Long2ObjectMap chunkLoadStatuses = new Long2ObjectOpenHashMap(); - private final LongSet chunksToUnload = new LongOpenHashSet(); + private final Long2ObjectMap chunkVisibility = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); + private final Long2ObjectMap chunkLoadStatuses = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); + private final LongSet chunksToUnload = LongSets.synchronize(new LongOpenHashSet()); private final Queue> loadingInbox = Queues.newConcurrentLinkedQueue(); public PersistentEntitySectionManager(Class entityClass, LevelCallback handler, EntityPersistentStorage 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 stack = new ArrayDeque<>(); - private final List addedThisLayer = new ArrayList<>(); + private final Deque stack = new ConcurrentLinkedDeque<>(); + private final List 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)); }