aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch')
-rw-r--r--patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch147
1 files changed, 147 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch
new file mode 100644
index 0000000000..720cf2486b
--- /dev/null
+++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch
@@ -0,0 +1,147 @@
+--- a/net/minecraft/server/level/ChunkMap.java
++++ b/net/minecraft/server/level/ChunkMap.java
+@@ -100,6 +100,9 @@
+ import net.minecraft.world.phys.Vec3;
+ import org.apache.commons.lang3.mutable.MutableBoolean;
+ import org.slf4j.Logger;
++import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
++import org.bukkit.entity.Player;
++// CraftBukkit end
+
+ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
+
+@@ -143,8 +146,29 @@
+ private final Queue<Runnable> unloadQueue;
+ private int serverViewDistance;
+
+- public ChunkMap(ServerLevel serverlevel, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, BlockableEventLoop<Runnable> blockableeventloop, LightChunkGetter lightchunkgetter, ChunkGenerator chunkgenerator, ChunkProgressListener chunkprogresslistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier<DimensionDataStorage> supplier, int i, boolean flag) {
+- super(levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()).resolve("region"), datafixer, flag);
++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
++ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
++
++ private final java.util.Queue<Runnable> queue = new java.util.ArrayDeque<>();
++
++ @Override
++ public void execute(Runnable runnable) {
++ queue.add(runnable);
++ }
++
++ @Override
++ public void run() {
++ Runnable task;
++ while ((task = queue.poll()) != null) {
++ task.run();
++ }
++ }
++ };
++ // CraftBukkit end
++
++ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier<DimensionDataStorage> overworldDataStorage, int viewDistance, boolean sync) {
++ super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync);
+ this.visibleChunkMap = this.updatingChunkMap.clone();
+ this.pendingUnloads = new Long2ObjectLinkedOpenHashMap();
+ this.entitiesInLevel = new LongOpenHashSet();
+@@ -159,10 +183,15 @@
+ Path path = levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension());
+
+ this.storageName = path.getFileName().toString();
+- this.level = serverlevel;
+- this.generator = chunkgenerator;
+- RegistryAccess registryaccess = serverlevel.registryAccess();
+- long j = serverlevel.getSeed();
++ this.level = level;
++ this.generator = generator;
++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random.
++ if (generator instanceof CustomChunkGenerator) {
++ generator = ((CustomChunkGenerator) generator).getDelegate();
++ }
++ // CraftBukkit end
++ RegistryAccess iregistrycustom = level.registryAccess();
++ long j = level.getSeed();
+
+ if (chunkgenerator instanceof NoiseBasedChunkGenerator) {
+ NoiseBasedChunkGenerator noisebasedchunkgenerator = (NoiseBasedChunkGenerator) chunkgenerator;
+@@ -335,8 +364,10 @@
+ List<ChunkAccess> list3 = Lists.newArrayList();
+ final int l1 = 0;
+
+- for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++l1) {
+- final Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = (Either) iterator.next();
++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) {
++ final int l1 = cnt;
++ // CraftBukkit end
++ final Either<ChunkAccess, ChunkHolder.Failure> either = (Either) iterator.next();
+
+ if (either == null) {
+ throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a");
+@@ -749,9 +778,23 @@
+ return chunkstatus1;
+ }
+
+- private static void postLoadProtoChunk(ServerLevel serverlevel, List<CompoundTag> list) {
+- if (!list.isEmpty()) {
+- serverlevel.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(list, serverlevel));
++ private static void postLoadProtoChunk(ServerLevel level, List<CompoundTag> tags) {
++ if (!tags.isEmpty()) {
++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
++ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> {
++ boolean needsRemoval = false;
++ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer();
++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) {
++ entity.discard();
++ needsRemoval = true;
++ }
++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) {
++ entity.discard();
++ needsRemoval = true;
++ }
++ return !needsRemoval;
++ }));
++ // CraftBukkit end
+ }
+
+ }
+@@ -1047,14 +1091,16 @@
+ }
+ }
+
+- private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkpos) {
+- return this.read(chunkpos).thenApplyAsync((optional) -> {
+- return optional.map(this::upgradeChunkTag);
++ private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
++ return this.read(pos).thenApplyAsync((optional) -> {
++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit
+ }, Util.backgroundExecutor());
+ }
+
+- private CompoundTag upgradeChunkTag(CompoundTag compoundtag) {
+- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, compoundtag, this.generator.getTypeNameForDataFixer());
++ // CraftBukkit start
++ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) {
++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level);
++ // CraftBukkit end
+ }
+
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkpos) {
+@@ -1467,7 +1509,7 @@
+ private final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
+
+ public TrackedEntity(Entity entity, int i, int j, boolean flag) {
+- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast);
++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit
+ this.entity = entity;
+ this.range = i;
+ this.lastSectionPos = SectionPos.of((EntityAccess) entity);
+@@ -1529,6 +1569,11 @@
+ double d2 = d0 * d0;
+ boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(serverplayer) && ChunkMap.this.isChunkTracked(serverplayer, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+
++ // CraftBukkit start - respect vanish API
++ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
++ flag = false;
++ }
++ // CraftBukkit end
+ if (flag) {
+ if (this.seenBy.add(serverplayer.connection)) {
+ this.serverEntity.addPairing(serverplayer);