|
| 1 | +--- a/net/minecraft/world/level/LocalMobCapCalculator.java |
| 2 | ++++ b/net/minecraft/world/level/LocalMobCapCalculator.java |
| 3 | +@@ -1,19 +_,22 @@ |
| 4 | + package net.minecraft.world.level; |
| 5 | + |
| 6 | + import com.google.common.collect.Maps; |
| 7 | ++import io.multipaper.shreddedpaper.util.SimpleStampedLock; |
| 8 | + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; |
| 9 | + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; |
| 10 | + import it.unimi.dsi.fastutil.objects.Object2IntMap; |
| 11 | + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; |
| 12 | + import java.util.List; |
| 13 | + import java.util.Map; |
| 14 | ++import java.util.concurrent.ConcurrentHashMap; |
| 15 | + import net.minecraft.server.level.ChunkMap; |
| 16 | + import net.minecraft.server.level.ServerPlayer; |
| 17 | + import net.minecraft.world.entity.MobCategory; |
| 18 | + |
| 19 | + public class LocalMobCapCalculator { |
| 20 | +- private final Long2ObjectMap<List<ServerPlayer>> playersNearChunk = new Long2ObjectOpenHashMap<>(); |
| 21 | ++ private final Map<Long, List<ServerPlayer>> playersNearChunk = new ConcurrentHashMap<>(); // ShreddedPaper - thread safety (playersNearChunk is mostly writes) |
| 22 | + private final Map<ServerPlayer, LocalMobCapCalculator.MobCounts> playerMobCounts = Maps.newHashMap(); |
| 23 | ++ private final SimpleStampedLock playerMobCountsLock = new SimpleStampedLock(); // ShreddedPaper - thread safety (playerMobCounts is mostly reads) |
| 24 | + private final ChunkMap chunkMap; |
| 25 | + |
| 26 | + public LocalMobCapCalculator(ChunkMap chunkMap) { |
| 27 | +@@ -26,13 +_,17 @@ |
| 28 | + |
| 29 | + public void addMob(ChunkPos pos, MobCategory category) { |
| 30 | + for (ServerPlayer serverPlayer : this.getPlayersNear(pos)) { |
| 31 | +- this.playerMobCounts.computeIfAbsent(serverPlayer, key -> new LocalMobCapCalculator.MobCounts()).add(category); |
| 32 | ++ // ShreddedPaper start - thread safety |
| 33 | ++ LocalMobCapCalculator.MobCounts playerMobCount = this.playerMobCountsLock.optimisticRead(() -> this.playerMobCounts.get(serverPlayer)); |
| 34 | ++ if (playerMobCount == null) playerMobCount = this.playerMobCountsLock.write(() -> this.playerMobCounts.computeIfAbsent(serverPlayer, key -> new LocalMobCapCalculator.MobCounts())); |
| 35 | ++ playerMobCount.add(category); |
| 36 | ++ // ShreddedPaper end - thread safety |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + public boolean canSpawn(MobCategory category, ChunkPos pos) { |
| 41 | + for (ServerPlayer serverPlayer : this.getPlayersNear(pos)) { |
| 42 | +- LocalMobCapCalculator.MobCounts mobCounts = this.playerMobCounts.get(serverPlayer); |
| 43 | ++ LocalMobCapCalculator.MobCounts mobCounts = this.playerMobCountsLock.optimisticRead(() -> this.playerMobCounts.get(serverPlayer)); // ShreddedPaper - thread safety |
| 44 | + if (mobCounts == null || mobCounts.canSpawn(category)) { |
| 45 | + return true; |
| 46 | + } |
0 commit comments