mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-23 08:59:23 +00:00
1048 lines
50 KiB
Diff
1048 lines
50 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: wangxyper <wangxyper@163.com>
|
|
Date: Sun, 8 Jan 2023 21:48:49 +0800
|
|
Subject: [PATCH] Hearse: MC code changes
|
|
|
|
Original license: MIT
|
|
Original project: https://github.com/NaturalCodeClub/HearseRewrite
|
|
|
|
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
|
index 24c677e80af652952263253409c050641e72e3b5..c6f9fb3efb92de0879eab6389fabd531bb4cfcb2 100644
|
|
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
|
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
|
@@ -1,7 +1,8 @@
|
|
package net.minecraft.network.protocol.game;
|
|
|
|
-import it.unimi.dsi.fastutil.shorts.ShortIterator;
|
|
import it.unimi.dsi.fastutil.shorts.ShortSet;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
import java.util.function.BiConsumer;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.SectionPos;
|
|
@@ -22,14 +23,16 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet<ClientGamePa
|
|
public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section, boolean noLightingUpdates) {
|
|
this.sectionPos = sectionPos;
|
|
this.suppressLightUpdates = noLightingUpdates;
|
|
- int i = positions.size();
|
|
+ final List<Short> copy = new ArrayList<>(positions);
|
|
+ this.positions = new short[copy.size()];
|
|
+ this.states = new BlockState[copy.size()];
|
|
+ for (int i = 0; i < copy.size(); i++) {
|
|
+ this.positions[i] = copy.get(i);
|
|
+ }
|
|
|
|
- this.positions = new short[i];
|
|
- this.states = new BlockState[i];
|
|
- int j = 0;
|
|
|
|
- for (ShortIterator shortiterator = positions.iterator(); shortiterator.hasNext(); ++j) {
|
|
- short short0 = (Short) shortiterator.next();
|
|
+ for (int j = 0;j < this.positions.length;j++) {
|
|
+ short short0 = this.positions[j];
|
|
|
|
this.positions[j] = short0;
|
|
this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
index bc46479fd0622a90fd98ac88f92b2840a22a2d04..e642b4a83687d03e55feb340452d608c53ae7cce 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
@@ -2,19 +2,9 @@ package net.minecraft.server.level;
|
|
|
|
import com.mojang.datafixers.util.Either;
|
|
import com.mojang.datafixers.util.Pair;
|
|
-import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet;
|
|
+import it.unimi.dsi.fastutil.shorts.ShortArraySet;
|
|
import it.unimi.dsi.fastutil.shorts.ShortSet;
|
|
-import java.util.ArrayList;
|
|
-import java.util.BitSet;
|
|
-import java.util.List;
|
|
-import java.util.Optional;
|
|
-import java.util.concurrent.CompletableFuture;
|
|
-import java.util.concurrent.Executor;
|
|
-import java.util.concurrent.atomic.AtomicReferenceArray;
|
|
-import java.util.function.IntConsumer;
|
|
-import java.util.function.IntSupplier;
|
|
-import javax.annotation.Nullable;
|
|
-import net.minecraft.Util;
|
|
+import it.unimi.dsi.fastutil.shorts.ShortSets;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.network.protocol.Packet;
|
|
@@ -29,15 +19,14 @@ import net.minecraft.world.level.LevelHeightAccessor;
|
|
import net.minecraft.world.level.LightLayer;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
-import net.minecraft.world.level.chunk.ChunkAccess;
|
|
-import net.minecraft.world.level.chunk.ChunkStatus;
|
|
-import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
|
-import net.minecraft.world.level.chunk.LevelChunk;
|
|
-import net.minecraft.world.level.chunk.LevelChunkSection;
|
|
-import net.minecraft.world.level.chunk.ProtoChunk;
|
|
+import net.minecraft.world.level.chunk.*;
|
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
-// CraftBukkit start
|
|
-import net.minecraft.server.MinecraftServer;
|
|
+import javax.annotation.Nullable;
|
|
+import java.util.BitSet;
|
|
+import java.util.List;
|
|
+import java.util.concurrent.CompletableFuture;
|
|
+import java.util.function.IntConsumer;
|
|
+import java.util.function.IntSupplier;
|
|
// CraftBukkit end
|
|
|
|
public class ChunkHolder {
|
|
@@ -233,7 +222,7 @@ public class ChunkHolder {
|
|
if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
|
if (this.changedBlocksPerSection[i] == null) {
|
|
this.hasChangedSections = true; this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
|
- this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
|
+ this.changedBlocksPerSection[i] = ShortSets.synchronize(new ShortArraySet());
|
|
}
|
|
|
|
this.changedBlocksPerSection[i].add(SectionPos.sectionRelativePos(pos));
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index beb7c22cb63021f26c06f91050361e1b25fcc72d..10c7d776ca0d959541d3110c75ceb45a340278ac 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -1,57 +1,25 @@
|
|
package net.minecraft.server.level;
|
|
|
|
-import co.aikar.timings.Timing; // Paper
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableList.Builder;
|
|
import com.google.common.collect.Iterables;
|
|
-import com.google.common.collect.ComparisonChain; // Paper
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Queues;
|
|
-import com.google.common.collect.Sets;
|
|
import com.google.gson.JsonElement;
|
|
import com.mojang.datafixers.DataFixer;
|
|
import com.mojang.datafixers.util.Either;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.serialization.DataResult;
|
|
import com.mojang.serialization.JsonOps;
|
|
+import io.papermc.paper.util.MCUtil;
|
|
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;
|
|
-import it.unimi.dsi.fastutil.longs.Long2LongMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
|
-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.longs.*;
|
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
-import java.io.IOException;
|
|
-import java.io.Writer;
|
|
-import java.nio.file.Path;
|
|
-import java.util.ArrayList;
|
|
-import java.util.BitSet;
|
|
-import java.util.Iterator;
|
|
-import java.util.List;
|
|
-import java.util.Locale;
|
|
-import java.util.Objects;
|
|
-import java.util.Optional;
|
|
-import java.util.Queue;
|
|
-import java.util.Set;
|
|
-import java.util.concurrent.CancellationException;
|
|
-import java.util.concurrent.CompletableFuture;
|
|
-import java.util.concurrent.CompletionException;
|
|
-import java.util.concurrent.CompletionStage;
|
|
-import java.util.concurrent.Executor;
|
|
-import java.util.concurrent.atomic.AtomicInteger;
|
|
-import java.util.function.BooleanSupplier;
|
|
-import java.util.function.Consumer;
|
|
-import java.util.function.IntFunction;
|
|
-import java.util.function.IntSupplier;
|
|
-import java.util.function.Supplier;
|
|
-import java.util.stream.Collectors;
|
|
-import javax.annotation.Nullable;
|
|
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
|
+import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
|
+import it.unimi.dsi.fastutil.objects.ReferenceSets;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.ReportedException;
|
|
@@ -63,36 +31,19 @@ import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
|
-import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket;
|
|
-import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
|
|
-import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
|
import net.minecraft.network.protocol.game.DebugPackets;
|
|
-import io.papermc.paper.util.MCUtil;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
|
import net.minecraft.server.network.ServerPlayerConnection;
|
|
-import net.minecraft.util.CsvOutput;
|
|
import net.minecraft.util.Mth;
|
|
-import net.minecraft.util.profiling.ProfilerFiller;
|
|
import net.minecraft.util.thread.BlockableEventLoop;
|
|
-import net.minecraft.util.thread.ProcessorHandle;
|
|
-import net.minecraft.util.thread.ProcessorMailbox;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityType;
|
|
-import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
|
import net.minecraft.world.entity.boss.EnderDragonPart;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
import net.minecraft.world.level.GameRules;
|
|
-import net.minecraft.world.level.chunk.ChunkAccess;
|
|
-import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
-import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
|
-import net.minecraft.world.level.chunk.ChunkStatus;
|
|
-import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
|
-import net.minecraft.world.level.chunk.LevelChunk;
|
|
-import net.minecraft.world.level.chunk.LightChunkGetter;
|
|
-import net.minecraft.world.level.chunk.ProtoChunk;
|
|
-import net.minecraft.world.level.chunk.UpgradeData;
|
|
+import net.minecraft.world.level.chunk.*;
|
|
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
|
import net.minecraft.world.level.chunk.storage.ChunkStorage;
|
|
import net.minecraft.world.level.entity.ChunkStatusUpdateListener;
|
|
@@ -101,19 +52,24 @@ import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
|
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
|
import net.minecraft.world.level.levelgen.RandomState;
|
|
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
|
-import net.minecraft.world.level.levelgen.structure.StructureStart;
|
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
|
import net.minecraft.world.level.storage.DimensionDataStorage;
|
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
|
-import net.minecraft.world.phys.Vec3;
|
|
-import org.apache.commons.lang3.mutable.MutableBoolean;
|
|
import org.apache.commons.lang3.mutable.MutableObject;
|
|
-import org.slf4j.Logger;
|
|
import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
|
|
-import org.bukkit.entity.Player;
|
|
-// CraftBukkit end
|
|
+import org.slf4j.Logger;
|
|
|
|
-import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
|
|
+import javax.annotation.Nullable;
|
|
+import java.io.IOException;
|
|
+import java.io.Writer;
|
|
+import java.nio.file.Path;
|
|
+import java.util.*;
|
|
+import java.util.concurrent.CancellationException;
|
|
+import java.util.concurrent.CompletableFuture;
|
|
+import java.util.concurrent.CompletionException;
|
|
+import java.util.concurrent.Executor;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+import java.util.function.*;
|
|
|
|
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
|
|
|
|
@@ -153,7 +109,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,9 +251,9 @@ 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.chunkTypeCache = new Long2ByteOpenHashMap();
|
|
- this.chunkSaveCooldowns = new Long2LongOpenHashMap();
|
|
+ this.entityMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap());
|
|
+ this.chunkTypeCache = Long2ByteMaps.synchronize(new Long2ByteOpenHashMap());
|
|
+ this.chunkSaveCooldowns = Long2LongMaps.synchronize(new Long2LongOpenHashMap());
|
|
this.unloadQueue = Queues.newConcurrentLinkedQueue();
|
|
this.structureTemplateManager = structureTemplateManager;
|
|
Path path = session.getDimensionPath(world.dimension());
|
|
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
index 52cba8f68d274cce106304aef1249a95474d3238..a9ba8adc5f290f6e2820632bdae8e50165595706 100644
|
|
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
@@ -1,42 +1,20 @@
|
|
package net.minecraft.server.level;
|
|
|
|
-import com.google.common.annotations.VisibleForTesting;
|
|
-import com.google.common.collect.ImmutableList;
|
|
-import com.google.common.collect.ImmutableSet;
|
|
-import com.google.common.collect.Sets;
|
|
-import com.mojang.datafixers.util.Either;
|
|
import com.mojang.logging.LogUtils;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ByteMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2IntMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2IntMaps;
|
|
-import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
|
-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.longs.*;
|
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
-import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
|
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
-import java.io.File;
|
|
-import java.io.FileOutputStream;
|
|
-import java.io.IOException;
|
|
-import java.nio.charset.StandardCharsets;
|
|
-import java.util.Iterator;
|
|
-import java.util.Objects;
|
|
-import java.util.Set;
|
|
-import java.util.concurrent.CompletableFuture;
|
|
-import java.util.concurrent.Executor;
|
|
-import javax.annotation.Nullable;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.util.SortedArraySet;
|
|
-import net.minecraft.util.thread.ProcessorHandle;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
-import net.minecraft.world.level.chunk.LevelChunk;
|
|
import org.slf4j.Logger;
|
|
+import javax.annotation.Nullable;
|
|
+import java.io.File;
|
|
+import java.io.FileOutputStream;
|
|
+import java.io.IOException;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+import java.util.concurrent.Executor;
|
|
|
|
public abstract class DistanceManager {
|
|
|
|
@@ -52,7 +30,7 @@ public abstract class DistanceManager {
|
|
private static final int INITIAL_TICKET_LIST_CAPACITY = 4;
|
|
private static final int ENTITY_TICKING_LEVEL_THRESHOLD = 32;
|
|
private static final int BLOCK_TICKING_LEVEL_THRESHOLD = 33;
|
|
- final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
|
|
+ final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap());
|
|
// Paper - rewrite chunk system
|
|
public static final int MOB_SPAWN_RANGE = 8; // private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); // Paper - no longer used
|
|
//private final TickingTracker tickingTicketsTracker = new TickingTracker(); // Paper - no longer used
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index 0ae45cf5a084fd412305e8b2f5dabe608b4eb1c1..a2935994edc279d880ff26dd5cc4e33f1105acc8 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -4,43 +4,19 @@ import com.google.common.annotations.VisibleForTesting;
|
|
import com.google.common.collect.Lists;
|
|
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.concurrent.CompletableFuture;
|
|
-import java.util.concurrent.Executor;
|
|
-import java.util.function.BooleanSupplier;
|
|
-import java.util.function.Consumer;
|
|
-import java.util.function.Supplier;
|
|
-import javax.annotation.Nullable;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
|
import net.minecraft.util.VisibleForDebug;
|
|
-import net.minecraft.util.profiling.ProfilerFiller;
|
|
import net.minecraft.util.thread.BlockableEventLoop;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
|
-import net.minecraft.world.level.BlockGetter;
|
|
-import net.minecraft.world.level.ChunkPos;
|
|
-import net.minecraft.world.level.GameRules;
|
|
-import net.minecraft.world.level.Level;
|
|
-import net.minecraft.world.level.LightLayer;
|
|
-import net.minecraft.world.level.LocalMobCapCalculator;
|
|
-import net.minecraft.world.level.NaturalSpawner;
|
|
-import net.minecraft.world.level.chunk.ChunkAccess;
|
|
-import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
-import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
|
-import net.minecraft.world.level.chunk.ChunkSource;
|
|
-import net.minecraft.world.level.chunk.ChunkStatus;
|
|
-import net.minecraft.world.level.chunk.LevelChunk;
|
|
+import net.minecraft.world.level.*;
|
|
+import net.minecraft.world.level.chunk.*;
|
|
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
|
import net.minecraft.world.level.entity.ChunkStatusUpdateListener;
|
|
import net.minecraft.world.level.levelgen.RandomState;
|
|
@@ -48,7 +24,16 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|
import net.minecraft.world.level.storage.DimensionDataStorage;
|
|
import net.minecraft.world.level.storage.LevelData;
|
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
|
-import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
|
|
+
|
|
+import javax.annotation.Nullable;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.util.*;
|
|
+import java.util.concurrent.CompletableFuture;
|
|
+import java.util.concurrent.Executor;
|
|
+import java.util.function.BooleanSupplier;
|
|
+import java.util.function.Consumer;
|
|
+import java.util.function.Supplier;
|
|
|
|
public class ServerChunkCache extends ChunkSource {
|
|
|
|
@@ -803,7 +788,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();
|
|
+ ObjectSet<ChunkHolder> copy = new ObjectArraySet<>(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/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
|
|
index 660693c6dc0ef86f4013df980b6d0c11c03e46cd..1ea9699ce1f77a551a45fc06dad55df4cc1a4f4d 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
|
|
@@ -1,14 +1,9 @@
|
|
package net.minecraft.server.level;
|
|
|
|
-import com.mojang.datafixers.util.Pair;
|
|
+import ca.spottedleaf.starlight.common.light.StarLightEngine;
|
|
import com.mojang.logging.LogUtils;
|
|
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
-import it.unimi.dsi.fastutil.objects.ObjectList;
|
|
-import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
-import java.util.concurrent.CompletableFuture;
|
|
-import java.util.concurrent.atomic.AtomicBoolean;
|
|
-import java.util.function.IntSupplier;
|
|
-import javax.annotation.Nullable;
|
|
+import io.papermc.paper.util.CoordinateUtils;
|
|
+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.SectionPos;
|
|
@@ -17,21 +12,17 @@ import net.minecraft.util.thread.ProcessorMailbox;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
import net.minecraft.world.level.LightLayer;
|
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
|
+import net.minecraft.world.level.chunk.ChunkStatus;
|
|
import net.minecraft.world.level.chunk.DataLayer;
|
|
-import net.minecraft.world.level.chunk.LevelChunkSection;
|
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
|
+import net.minecraft.world.level.lighting.LayerLightEventListener;
|
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
import org.slf4j.Logger;
|
|
|
|
-// Paper start
|
|
-import ca.spottedleaf.starlight.common.light.StarLightEngine;
|
|
-import io.papermc.paper.util.CoordinateUtils;
|
|
+import javax.annotation.Nullable;
|
|
+import java.util.concurrent.CompletableFuture;
|
|
+import java.util.function.IntSupplier;
|
|
import java.util.function.Supplier;
|
|
-import net.minecraft.world.level.lighting.LayerLightEventListener;
|
|
-import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
-import it.unimi.dsi.fastutil.longs.LongIterator;
|
|
-import net.minecraft.world.level.chunk.ChunkStatus;
|
|
// Paper end
|
|
|
|
public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable {
|
|
@@ -145,20 +136,30 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
|
|
return;
|
|
}
|
|
|
|
- final int references = this.chunksBeingWorkedOn.addTo(key, 1);
|
|
+ int references;
|
|
+ synchronized (this.chunksBeingWorkedOn){
|
|
+ references = this.chunksBeingWorkedOn.addTo(key, 1);
|
|
+ }
|
|
if (references == 0) {
|
|
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
|
world.getChunkSource().addRegionTicket(ca.spottedleaf.starlight.common.light.StarLightInterface.CHUNK_WORK_TICKET, pos, 0, pos);
|
|
}
|
|
|
|
updateFuture.thenAcceptAsync((final Void ignore) -> {
|
|
- final int newReferences = this.chunksBeingWorkedOn.get(key);
|
|
+ int newReferences;
|
|
+ synchronized (this.chunksBeingWorkedOn){
|
|
+ newReferences = this.chunksBeingWorkedOn.get(key);
|
|
+ }
|
|
if (newReferences == 1) {
|
|
- this.chunksBeingWorkedOn.remove(key);
|
|
+ synchronized (this.chunksBeingWorkedOn){
|
|
+ this.chunksBeingWorkedOn.remove(key);
|
|
+ }
|
|
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
|
world.getChunkSource().removeRegionTicket(ca.spottedleaf.starlight.common.light.StarLightInterface.CHUNK_WORK_TICKET, pos, 0, pos);
|
|
} else {
|
|
- this.chunksBeingWorkedOn.put(key, newReferences - 1);
|
|
+ synchronized (this.chunksBeingWorkedOn){
|
|
+ this.chunksBeingWorkedOn.put(key, newReferences - 1);
|
|
+ }
|
|
}
|
|
}, world.getChunkSource().chunkMap.mainThreadExecutor).whenComplete((final Void ignore, final Throwable thr) -> {
|
|
if (thr != null) {
|
|
diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
|
|
index 50a9f33aa31e9273c7c52d4bb2b02f0f884f7ba5..d5802cfe08f92b55ff1fd41648abda9ef2b7dd20 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;
|
|
@@ -59,12 +61,16 @@ public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
|
|
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 this.allInstances.stream().filter(typeClass::isInstance).collect(toList());
|
|
});
|
|
- return Collections.unmodifiableCollection(list);
|
|
+ return (Collection<S>) Collections.unmodifiableCollection(list);
|
|
}
|
|
}
|
|
|
|
+ public static <T> Collector<T, ?, List<T>> toList() {
|
|
+ return Collectors.toCollection(CopyOnWriteArrayList::new);
|
|
+ }
|
|
+
|
|
@Override
|
|
public Iterator<T> iterator() {
|
|
return (Iterator<T>)(this.allInstances.isEmpty() ? Collections.emptyIterator() : Iterators.unmodifiableIterator(this.allInstances.iterator()));
|
|
diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
index 83701fbfaa56a232593ee8f11a3afb8941238bfa..0c70810edace99bb5037d927388e055a514fcbde 100644
|
|
--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
@@ -8,6 +8,7 @@ import java.util.Queue;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.locks.LockSupport;
|
|
+import java.util.concurrent.locks.StampedLock;
|
|
import java.util.function.BooleanSupplier;
|
|
import java.util.function.Supplier;
|
|
import net.minecraft.util.profiling.metrics.MetricCategory;
|
|
@@ -20,6 +21,7 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
private final String name;
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final Queue<R> pendingRunnables = Queues.newConcurrentLinkedQueue();
|
|
+ private final StampedLock lock = new StampedLock();
|
|
private int blockingCount;
|
|
|
|
protected BlockableEventLoop(String name) {
|
|
@@ -42,7 +44,12 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
}
|
|
|
|
public int getPendingTasksCount() {
|
|
- return this.pendingRunnables.size();
|
|
+ final long id = this.lock.readLock();
|
|
+ try{
|
|
+ return this.pendingRunnables.size();
|
|
+ }finally {
|
|
+ this.lock.unlockRead(id);
|
|
+ }
|
|
}
|
|
|
|
@Override
|
|
@@ -88,7 +95,12 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
|
|
@Override
|
|
public void tell(R runnable) {
|
|
- this.pendingRunnables.add(runnable);
|
|
+ final long id = this.lock.writeLock();
|
|
+ try {
|
|
+ this.pendingRunnables.add(runnable);
|
|
+ }finally {
|
|
+ this.lock.unlockWrite(id);
|
|
+ }
|
|
LockSupport.unpark(this.getRunningThread());
|
|
}
|
|
|
|
@@ -107,7 +119,12 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
}
|
|
|
|
protected void dropAllTasks() {
|
|
- this.pendingRunnables.clear();
|
|
+ final long id = this.lock.writeLock();
|
|
+ try {
|
|
+ this.pendingRunnables.clear();
|
|
+ }finally {
|
|
+ this.lock.unlockWrite(id);
|
|
+ }
|
|
}
|
|
|
|
protected void runAllTasks() {
|
|
@@ -117,14 +134,19 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
}
|
|
|
|
public boolean pollTask() {
|
|
- R runnable = this.pendingRunnables.peek();
|
|
- if (runnable == null) {
|
|
- return false;
|
|
- } else if (this.blockingCount == 0 && !this.shouldRun(runnable)) {
|
|
- return false;
|
|
- } else {
|
|
- this.doRunTask(this.pendingRunnables.remove());
|
|
- return true;
|
|
+ final long id = this.lock.writeLock();
|
|
+ try {
|
|
+ R runnable = this.pendingRunnables.peek();
|
|
+ if (runnable == null) {
|
|
+ return false;
|
|
+ } else if (this.blockingCount == 0 && !this.shouldRun(runnable)) {
|
|
+ return false;
|
|
+ } else {
|
|
+ this.doRunTask(this.pendingRunnables.remove());
|
|
+ return true;
|
|
+ }
|
|
+ }finally {
|
|
+ this.lock.unlockWrite(id);
|
|
}
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index 99912ae883227e1c0a0adc1edbb4c4baee4fe2bc..f33476a35706d7a236fe3bb178d166d568c07674 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -164,76 +164,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
}
|
|
|
|
// Paper start
|
|
- public static RandomSource SHARED_RANDOM = new RandomRandomSource();
|
|
- private static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource {
|
|
- private boolean locked = false;
|
|
-
|
|
- @Override
|
|
- public synchronized void setSeed(long seed) {
|
|
- if (locked) {
|
|
- LOGGER.error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable());
|
|
- } else {
|
|
- super.setSeed(seed);
|
|
- locked = true;
|
|
- }
|
|
- }
|
|
-
|
|
- @Override
|
|
- public RandomSource fork() {
|
|
- return new net.minecraft.world.level.levelgen.LegacyRandomSource(this.nextLong());
|
|
- }
|
|
-
|
|
- @Override
|
|
- public net.minecraft.world.level.levelgen.PositionalRandomFactory forkPositional() {
|
|
- return new net.minecraft.world.level.levelgen.LegacyRandomSource.LegacyPositionalRandomFactory(this.nextLong());
|
|
- }
|
|
-
|
|
- // these below are added to fix reobf issues that I don't wanna deal with right now
|
|
- @Override
|
|
- public int next(int bits) {
|
|
- return super.next(bits);
|
|
- }
|
|
-
|
|
- @Override
|
|
- public int nextInt(int origin, int bound) {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt(origin, bound);
|
|
- }
|
|
-
|
|
- @Override
|
|
- public long nextLong() {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextLong();
|
|
- }
|
|
-
|
|
- @Override
|
|
- public int nextInt() {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt();
|
|
- }
|
|
-
|
|
- @Override
|
|
- public int nextInt(int bound) {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextInt(bound);
|
|
- }
|
|
-
|
|
- @Override
|
|
- public boolean nextBoolean() {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextBoolean();
|
|
- }
|
|
-
|
|
- @Override
|
|
- public float nextFloat() {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextFloat();
|
|
- }
|
|
-
|
|
- @Override
|
|
- public double nextDouble() {
|
|
- return net.minecraft.world.level.levelgen.BitRandomSource.super.nextDouble();
|
|
- }
|
|
-
|
|
- @Override
|
|
- public double nextGaussian() {
|
|
- return super.nextGaussian();
|
|
- }
|
|
- }
|
|
+ public static RandomSource SHARED_RANDOM = RandomSource.create();
|
|
// Paper end
|
|
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper
|
|
|
|
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/EntityTickList.java b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
|
|
index 57fcf3910f45ce371ac2e237b277b1034caaac4e..00f7b58db5948f4d7c7f07736d8fcf1972009c77 100644
|
|
--- a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
|
|
@@ -1,29 +1,22 @@
|
|
package net.minecraft.world.level.entity;
|
|
|
|
-import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
-import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
|
+import java.util.Iterator;
|
|
+import java.util.Set;
|
|
import java.util.function.Consumer;
|
|
-import javax.annotation.Nullable;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
import net.minecraft.world.entity.Entity;
|
|
|
|
public class EntityTickList {
|
|
- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<Entity> entities = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(true); // Paper - rewrite this, always keep this updated - why would we EVER tick an entity that's not ticking? // Pufferfish - private->public
|
|
-
|
|
- private void ensureActiveIsNotIterated() {
|
|
- // Paper - replace with better logic, do not delay removals
|
|
-
|
|
- }
|
|
+ public final Set<Entity> entities = ObjectSets.synchronize(new ObjectArraySet<>());
|
|
|
|
public void add(Entity entity) {
|
|
io.papermc.paper.util.TickThread.ensureTickThread("Asynchronous entity ticklist addition"); // Paper
|
|
- this.ensureActiveIsNotIterated();
|
|
this.entities.add(entity); // Paper - replace with better logic, do not delay removals/additions
|
|
}
|
|
|
|
public void remove(Entity entity) {
|
|
io.papermc.paper.util.TickThread.ensureTickThread("Asynchronous entity ticklist removal"); // Paper
|
|
- this.ensureActiveIsNotIterated();
|
|
this.entities.remove(entity); // Paper - replace with better logic, do not delay removals/additions
|
|
}
|
|
|
|
@@ -33,16 +26,8 @@ public class EntityTickList {
|
|
|
|
public void forEach(Consumer<Entity> action) {
|
|
io.papermc.paper.util.TickThread.ensureTickThread("Asynchronous entity ticklist iteration"); // Paper
|
|
- // Paper start - replace with better logic, do not delay removals/additions
|
|
- // To ensure nothing weird happens with dimension travelling, do not iterate over new entries...
|
|
- // (by dfl iterator() is configured to not iterate over new entries)
|
|
- io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<Entity> iterator = this.entities.iterator();
|
|
- try {
|
|
- while (iterator.hasNext()) {
|
|
- action.accept(iterator.next());
|
|
- }
|
|
- } finally {
|
|
- iterator.finishedIterating();
|
|
+ for (Entity entity : this.entities) {
|
|
+ action.accept(entity);
|
|
}
|
|
// Paper end - replace with better logic, do not delay removals/additions
|
|
}
|
|
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/levelgen/LegacyRandomSource.java b/src/main/java/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
|
index daa03360dd7044f10b20f36023b305dc7e0bb7df..35de9e9a9d211b16a8b945bc512c128709ec6bfc 100644
|
|
--- a/src/main/java/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
|
+++ b/src/main/java/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
|
@@ -19,17 +19,17 @@ public class LegacyRandomSource implements BitRandomSource {
|
|
}
|
|
|
|
@Override
|
|
- public RandomSource fork() {
|
|
+ public synchronized RandomSource fork() {
|
|
return new LegacyRandomSource(this.nextLong());
|
|
}
|
|
|
|
@Override
|
|
- public PositionalRandomFactory forkPositional() {
|
|
+ public synchronized PositionalRandomFactory forkPositional() {
|
|
return new LegacyRandomSource.LegacyPositionalRandomFactory(this.nextLong());
|
|
}
|
|
|
|
@Override
|
|
- public void setSeed(long seed) {
|
|
+ public synchronized void setSeed(long seed) {
|
|
if (!this.seed.compareAndSet(this.seed.get(), (seed ^ 25214903917L) & 281474976710655L)) {
|
|
throw ThreadingDetector.makeThreadingException("LegacyRandomSource", (Thread)null);
|
|
} else {
|
|
@@ -38,7 +38,7 @@ public class LegacyRandomSource implements BitRandomSource {
|
|
}
|
|
|
|
@Override
|
|
- public int next(int bits) {
|
|
+ public synchronized int next(int bits) {
|
|
long l = this.seed.get();
|
|
long m = l * 25214903917L + 11L & 281474976710655L;
|
|
if (!this.seed.compareAndSet(l, m)) {
|
|
@@ -49,7 +49,7 @@ public class LegacyRandomSource implements BitRandomSource {
|
|
}
|
|
|
|
@Override
|
|
- public double nextGaussian() {
|
|
+ public synchronized double nextGaussian() {
|
|
return this.gaussianSource.nextGaussian();
|
|
}
|
|
|
|
@@ -61,21 +61,21 @@ public class LegacyRandomSource implements BitRandomSource {
|
|
}
|
|
|
|
@Override
|
|
- public RandomSource at(int x, int y, int z) {
|
|
+ public synchronized RandomSource at(int x, int y, int z) {
|
|
long l = Mth.getSeed(x, y, z);
|
|
long m = l ^ this.seed;
|
|
return new LegacyRandomSource(m);
|
|
}
|
|
|
|
@Override
|
|
- public RandomSource fromHashOf(String seed) {
|
|
+ public synchronized RandomSource fromHashOf(String seed) {
|
|
int i = seed.hashCode();
|
|
return new LegacyRandomSource((long)i ^ this.seed);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
@Override
|
|
- public void parityConfigString(StringBuilder info) {
|
|
+ public synchronized void parityConfigString(StringBuilder info) {
|
|
info.append("LegacyPositionalRandomFactory{").append(this.seed).append("}");
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/lighting/DynamicGraphMinFixedPoint.java b/src/main/java/net/minecraft/world/level/lighting/DynamicGraphMinFixedPoint.java
|
|
index 3d5ce92c77bc107e2ec2f54dc849b99c3abf9718..88d78f77740ee436fedd5159f8bafe91c1eb5ec1 100644
|
|
--- a/src/main/java/net/minecraft/world/level/lighting/DynamicGraphMinFixedPoint.java
|
|
+++ b/src/main/java/net/minecraft/world/level/lighting/DynamicGraphMinFixedPoint.java
|
|
@@ -1,17 +1,16 @@
|
|
package net.minecraft.world.level.lighting;
|
|
|
|
-import it.unimi.dsi.fastutil.longs.Long2ByteMap;
|
|
-import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
|
|
-import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
-import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
|
|
-import it.unimi.dsi.fastutil.longs.LongList;
|
|
+import it.unimi.dsi.fastutil.longs.*;
|
|
+
|
|
+import java.util.Deque;
|
|
+import java.util.concurrent.ConcurrentLinkedDeque;
|
|
import java.util.function.LongPredicate;
|
|
import net.minecraft.util.Mth;
|
|
|
|
public abstract class DynamicGraphMinFixedPoint {
|
|
private static final int NO_COMPUTED_LEVEL = 255;
|
|
private final int levelCount;
|
|
- private final LongLinkedOpenHashSet[] queues;
|
|
+ private final Deque<Long>[] queues;
|
|
private final Long2ByteMap computedLevels;
|
|
private int firstQueuedLevel;
|
|
private volatile boolean hasWork;
|
|
@@ -21,17 +20,10 @@ public abstract class DynamicGraphMinFixedPoint {
|
|
throw new IllegalArgumentException("Level count must be < 254.");
|
|
} else {
|
|
this.levelCount = levelCount;
|
|
- this.queues = new LongLinkedOpenHashSet[levelCount];
|
|
+ this.queues = new Deque[levelCount];
|
|
|
|
for(int i = 0; i < levelCount; ++i) {
|
|
- this.queues[i] = new LongLinkedOpenHashSet(expectedLevelSize, 0.5F) {
|
|
- protected void rehash(int i) {
|
|
- if (i > expectedLevelSize) {
|
|
- super.rehash(i);
|
|
- }
|
|
-
|
|
- }
|
|
- };
|
|
+ this.queues[i] = new ConcurrentLinkedDeque();
|
|
}
|
|
|
|
this.computedLevels = new Long2ByteOpenHashMap(expectedTotalSize, 0.5F) {
|
|
@@ -191,8 +183,8 @@ public abstract class DynamicGraphMinFixedPoint {
|
|
} else {
|
|
while(this.firstQueuedLevel < this.levelCount && maxSteps > 0) {
|
|
--maxSteps;
|
|
- LongLinkedOpenHashSet longLinkedOpenHashSet = this.queues[this.firstQueuedLevel];
|
|
- long l = longLinkedOpenHashSet.removeFirstLong();
|
|
+ Deque<Long> longLinkedOpenHashSet = this.queues[this.firstQueuedLevel];
|
|
+ long l = longLinkedOpenHashSet.removeFirst();
|
|
int i = Mth.clamp(this.getLevel(l), 0, this.levelCount - 1);
|
|
if (longLinkedOpenHashSet.isEmpty()) {
|
|
this.checkFirstQueuedLevel(this.levelCount);
|
|
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..a097e00bd62f53630568f68854d3a34300012277 100644
|
|
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
|
+++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
|
@@ -4,6 +4,8 @@ import com.mojang.logging.LogUtils;
|
|
import java.util.ArrayDeque;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
+import java.util.concurrent.CopyOnWriteArrayList;
|
|
+import java.util.concurrent.locks.StampedLock;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
@@ -17,9 +19,11 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
|
|
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 List<CollectingNeighborUpdater.NeighborUpdates> addedThisLayer = new CopyOnWriteArrayList<>();
|
|
private int count = 0;
|
|
|
|
+ private final StampedLock lock = new StampedLock();
|
|
+
|
|
public CollectingNeighborUpdater(Level world, int maxChainDepth) {
|
|
this.level = world;
|
|
this.maxChainedNeighborUpdates = maxChainDepth;
|
|
@@ -49,14 +53,19 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
|
|
boolean bl = this.count > 0;
|
|
boolean bl2 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates;
|
|
++this.count;
|
|
- if (!bl2) {
|
|
- if (bl) {
|
|
- this.addedThisLayer.add(entry);
|
|
- } else {
|
|
- this.stack.push(entry);
|
|
+ final long lockId = this.lock.writeLock();
|
|
+ try {
|
|
+ if (!bl2) {
|
|
+ if (bl) {
|
|
+ this.addedThisLayer.add(entry);
|
|
+ } else {
|
|
+ this.stack.push(entry);
|
|
+ }
|
|
+ } else if (this.count - 1 == this.maxChainedNeighborUpdates) {
|
|
+ LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString());
|
|
}
|
|
- } else if (this.count - 1 == this.maxChainedNeighborUpdates) {
|
|
- LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString());
|
|
+ }finally {
|
|
+ this.lock.unlockWrite(lockId);
|
|
}
|
|
|
|
if (!bl) {
|
|
@@ -66,28 +75,31 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
|
|
}
|
|
|
|
private void runUpdates() {
|
|
+ final long lockid = this.lock.writeLock();
|
|
try {
|
|
- while(!this.stack.isEmpty() || !this.addedThisLayer.isEmpty()) {
|
|
- for(int i = this.addedThisLayer.size() - 1; i >= 0; --i) {
|
|
- this.stack.push(this.addedThisLayer.get(i));
|
|
- }
|
|
-
|
|
- this.addedThisLayer.clear();
|
|
- CollectingNeighborUpdater.NeighborUpdates neighborUpdates = this.stack.peek();
|
|
-
|
|
- while(this.addedThisLayer.isEmpty()) {
|
|
- if (!neighborUpdates.runNext(this.level)) {
|
|
- this.stack.pop();
|
|
- break;
|
|
+ try {
|
|
+ while(!this.stack.isEmpty() || !this.addedThisLayer.isEmpty()) {
|
|
+ for(int i = this.addedThisLayer.size() - 1; i >= 0; --i) {
|
|
+ this.stack.push(this.addedThisLayer.get(i));
|
|
+ }
|
|
+ this.addedThisLayer.clear();
|
|
+ CollectingNeighborUpdater.NeighborUpdates neighborUpdates = this.stack.peek();
|
|
+
|
|
+ while(this.addedThisLayer.isEmpty()) {
|
|
+ if (!neighborUpdates.runNext(this.level)) {
|
|
+ this.stack.pop();
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
+ } finally {
|
|
+ this.stack.clear();
|
|
+ this.addedThisLayer.clear();
|
|
+ this.count = 0;
|
|
}
|
|
- } finally {
|
|
- this.stack.clear();
|
|
- this.addedThisLayer.clear();
|
|
- this.count = 0;
|
|
+ }finally {
|
|
+ this.lock.unlockWrite(lockid);
|
|
}
|
|
-
|
|
}
|
|
|
|
static record FullNeighborUpdate(BlockState state, BlockPos pos, Block block, BlockPos neighborPos, boolean movedByPiston) implements CollectingNeighborUpdater.NeighborUpdates {
|