mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-06-25 06:05:05 +02:00
update
This commit is contained in:
parent
2c205e034e
commit
be67395994
|
@ -157,6 +157,7 @@ # Patches
|
|||
| server | Custom Locale Support | Zoe | |
|
||||
| server | Custom table implementation for blockstate state lookups | Spottedleaf | |
|
||||
| server | Customizable wither health and healing | jmp | |
|
||||
| server | Decompile fixes for WorldChunkManagerMultiNoise | ishland | |
|
||||
| api | Default permissions | William Blake Galbreath | |
|
||||
| server | Delay chunk unloads | Spottedleaf | |
|
||||
| server | Despawn rate config options per projectile type | jmp | |
|
||||
|
@ -217,6 +218,7 @@ # Patches
|
|||
| server | Fix the dead lagging the server | William Blake Galbreath | |
|
||||
| server | Fix vanilla command permission handler | William Blake Galbreath | |
|
||||
| server | Flying squids! Oh my! | William Blake Galbreath | |
|
||||
| server | Force world save | ishland | |
|
||||
| server | Full netherite armor grants fire resistance | BillyGalbreath | |
|
||||
| api | Full netherite armor grants fire resistance | BillyGalbreath | |
|
||||
| server | Giants AI settings | William Blake Galbreath | |
|
||||
|
@ -278,6 +280,8 @@ # Patches
|
|||
| server | Movement options for armor stands | Mariell Hoversholm | |
|
||||
| server | Multi-Threaded Server Ticking Vanilla | Spottedleaf | |
|
||||
| server | Multi-Threaded ticking CraftBukkit | Spottedleaf | |
|
||||
| server | Multi-threaded RegionFile IO | ishland | |
|
||||
| server | Multi-threaded World Upgrade | ishland | |
|
||||
| server | Multithreaded entity tracking | Paul Sauve | |
|
||||
| server | Name craft scheduler threads according to the plugin using | Spottedleaf | |
|
||||
| server | New nbt cache | Hugo Planque | ishland |
|
||||
|
@ -395,6 +399,7 @@ # Patches
|
|||
| api | Suspected plugins report | ishland | |
|
||||
| server | Swap priority of checks in chunk ticking | Paul Sauve | |
|
||||
| server | Swaps the predicate order of collision | ㄗㄠˋ ㄑㄧˊ | |
|
||||
| server | Threaded WorldGen | ishland | |
|
||||
| server | Tick fluids config | BillyGalbreath | |
|
||||
| server | Time scoreboard search | Spottedleaf | |
|
||||
| server | Timings stuff | William Blake Galbreath | |
|
||||
|
@ -422,11 +427,14 @@ # Patches
|
|||
| server | Zombie horse naturally spawn | William Blake Galbreath | |
|
||||
| server | add config for logging login location | Simon Gardling | |
|
||||
| server | dont load chunks for physics | Aikar | |
|
||||
| server | fixup! Threaded WorldGen | ishland | |
|
||||
| server | fixup! Threaded WorldGen | ishland | |
|
||||
| server | lithium DataTrackerMixin | JellySquid | tr7zw |
|
||||
| server | lithium HashedList | JellySquid | |
|
||||
| server | lithium MixinBox | JellySquid | |
|
||||
| server | lithium MixinDirection | JellySquid | |
|
||||
| server | lithium MixinGoalSelector | JellySquid | |
|
||||
| server | lithium MultiNoiseBiomeSourceMixin | SuperCoder7979 | |
|
||||
| server | lithium NoiseChunkGeneratorMixin | JellySquid | |
|
||||
| server | lithium PerlinNoiseSamplerMixin | JellySquid | Bud Gidiere |
|
||||
| server | lithium VoronoiBiomeAccessTypeMixin | JellySquid | |
|
||||
|
|
477
patches/server/0064-Threaded-WorldGen.patch
Normal file
477
patches/server/0064-Threaded-WorldGen.patch
Normal file
|
@ -0,0 +1,477 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Sat, 9 Jan 2021 19:21:16 +0800
|
||||
Subject: [PATCH] Threaded WorldGen
|
||||
|
||||
A massive improvement to world generation.
|
||||
This patch actually schedules chunk status upgrade later rather than doing it right away.
|
||||
|
||||
diff --git a/pom.xml b/pom.xml
|
||||
index 734885f97eabffab6f76051b41f94d0dd16b4263..b8f376c015ae373252fd0e4f54cc921bae67b92a 100644
|
||||
--- a/pom.xml
|
||||
+++ b/pom.xml
|
||||
@@ -196,6 +196,12 @@
|
||||
<artifactId>commons-rng-core</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
+ <!-- https://mvnrepository.com/artifact/com.ibm.async/asyncutil -->
|
||||
+ <dependency>
|
||||
+ <groupId>com.ibm.async</groupId>
|
||||
+ <artifactId>asyncutil</artifactId>
|
||||
+ <version>0.1.0</version>
|
||||
+ </dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
index dc641664abe8ff6b36c69c7d21a3200d160ff1b6..c8f2ea95b4ea6e5629ef0b852dd08d45cb127b93 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
@@ -64,6 +64,20 @@ public final class ChunkTaskManager {
|
||||
public String toString() {
|
||||
return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']";
|
||||
}
|
||||
+ // Yatopia start
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ ChunkInfo chunkInfo = (ChunkInfo) o;
|
||||
+ return chunkX == chunkInfo.chunkX && chunkZ == chunkInfo.chunkZ && java.util.Objects.equals(world, chunkInfo.world);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return java.util.Objects.hash(chunkX, chunkZ, world);
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) {
|
||||
@@ -77,7 +91,13 @@ public final class ChunkTaskManager {
|
||||
WAITING_CHUNKS.pop();
|
||||
}
|
||||
}
|
||||
-
|
||||
+ // Yatopia start
|
||||
+ public static boolean hasChunkWait(final WorldServer world, final int chunkX, final int chunkZ) {
|
||||
+ synchronized (WAITING_CHUNKS) {
|
||||
+ return WAITING_CHUNKS.contains(new ChunkInfo(chunkX, chunkZ, world));
|
||||
+ }
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
private static ChunkInfo[] getChunkInfos() {
|
||||
ChunkInfo[] chunks;
|
||||
synchronized (WAITING_CHUNKS) {
|
||||
diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java
|
||||
index ce440ae5cc843fc6101dd11fd45d9089795411e4..06de830c859f3fa04b8542a238f24aa872585e92 100644
|
||||
--- a/src/main/java/net/minecraft/SystemUtils.java
|
||||
+++ b/src/main/java/net/minecraft/SystemUtils.java
|
||||
@@ -122,6 +122,7 @@ public class SystemUtils {
|
||||
return SystemUtils.d;
|
||||
}
|
||||
|
||||
+ public static Executor getMainThreadExecutor() { return f(); } // Yatopia - OBFHELPER
|
||||
public static Executor f() {
|
||||
return SystemUtils.e;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 97bb17236a00dd6ecd4d5926826815bb928bfe9e..b21c09f5b1cde7f7a710fe8960face8cb21040c4 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -953,6 +953,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
// Spigot end
|
||||
// Paper start - move final shutdown items here
|
||||
LOGGER.info("Flushing Chunk IO");
|
||||
+ net.minecraft.server.level.PlayerChunkMap.shutdownScheduler(); // Yatopia
|
||||
+ net.minecraft.world.level.chunk.ChunkStatus.shutdownExecutors(); // Yatopia
|
||||
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true, true); // Paper
|
||||
LOGGER.info("Closing Thread Pool");
|
||||
SystemUtils.shutdownServerThreadPool(); // Paper
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
index 424cd048f905cd0ed3f7a4545a26ffde8da1f91f..194321b7183d3aaa8031608a979dde71006e2fab 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
@@ -11,6 +11,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
+import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
@@ -53,6 +54,10 @@ import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
|
||||
// Tuinity end
|
||||
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
||||
+
|
||||
public class ChunkProviderServer extends IChunkProvider {
|
||||
|
||||
private static final List<ChunkStatus> b = ChunkStatus.a(); public static final List<ChunkStatus> getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER
|
||||
@@ -834,10 +839,27 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
- public boolean runTasks() {
|
||||
- return this.serverThreadQueue.executeNext();
|
||||
+ // Yatopia start - reduce scheduling overhead
|
||||
+ final ConcurrentLinkedQueue<Runnable> poiQueue = new ConcurrentLinkedQueue<>();
|
||||
+ private boolean runPoiQueueNext() { // TODO flush poi queue?
|
||||
+ try {
|
||||
+ final Runnable runnable = poiQueue.poll();
|
||||
+ if (runnable != null)
|
||||
+ runnable.run();
|
||||
+ return runnable != null;
|
||||
+ } catch (Throwable t) {
|
||||
+ t.printStackTrace();
|
||||
+ }
|
||||
+ return false;
|
||||
}
|
||||
|
||||
+ public boolean runTasks() {
|
||||
+ boolean b = this.serverThreadQueue.executeNext();
|
||||
+ if(runPoiQueueNext())
|
||||
+ b = true;
|
||||
+ return b;
|
||||
+ } // Yatopia end
|
||||
+
|
||||
public boolean tickDistanceManager() { // Paper - private -> public
|
||||
if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper
|
||||
if (this.playerChunkMap.unloadingPlayerChunk) { MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Tuinity
|
||||
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
index 58d2f1a10186e889bdd2249724a7f21f3a0a6a6e..b9d38413da1adbffd21df301f03cf181d4cd5cdc 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
@@ -113,6 +113,18 @@ import org.spigotmc.AsyncCatcher;
|
||||
|
||||
public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
+ // Yatopia start
|
||||
+ static final java.util.concurrent.ExecutorService worldGenScheduler = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("Yatopia Async Chunks Scheduler").setDaemon(true).setPriority(Thread.NORM_PRIORITY - 1).build());
|
||||
+ public static void shutdownScheduler() {
|
||||
+ worldGenScheduler.shutdown();
|
||||
+ while (!worldGenScheduler.isTerminated()) {
|
||||
+ try {
|
||||
+ worldGenScheduler.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS);
|
||||
+ } catch (InterruptedException ignored) {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final int GOLDEN_TICKET = 33 + ChunkStatus.b();
|
||||
// Paper start - faster copying
|
||||
@@ -1407,7 +1419,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
return;
|
||||
}
|
||||
// Paper end
|
||||
- this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable));
|
||||
+ worldGenScheduler.execute(runnable); // Yatopia
|
||||
}).thenComposeAsync((either) -> { // Tuinity start - force competion on the main thread
|
||||
return CompletableFuture.completedFuture(either);
|
||||
}, this.mainInvokingExecutor);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
|
||||
index 8ea7ad63c0f091102f793b3c1f90b4121c4d74e0..f1ae11648bab299c3b17ddcee75e7b7d7054d157 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
|
||||
@@ -2773,28 +2773,26 @@ public class WorldServer extends World implements GeneratorAccessSeed {
|
||||
|
||||
// Paper start
|
||||
BlockPosition blockposition1 = blockposition.immutableCopy();
|
||||
- this.getMinecraftServer().execute(() -> {
|
||||
+ // Yatopia start - reduce scheduling overhead
|
||||
+ chunkProvider.poiQueue.add(() -> {
|
||||
if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) {
|
||||
this.getPoiStorage().remove(blockposition1);
|
||||
}
|
||||
- });
|
||||
if (!Objects.equals(optional, optional1)) {
|
||||
//BlockPosition blockposition1 = blockposition.immutableCopy();
|
||||
// Paper end
|
||||
|
||||
optional.ifPresent((villageplacetype) -> {
|
||||
- this.getMinecraftServer().execute(() -> {
|
||||
this.y().a(blockposition1);
|
||||
PacketDebug.b(this, blockposition1);
|
||||
- });
|
||||
});
|
||||
optional1.ifPresent((villageplacetype) -> {
|
||||
- this.getMinecraftServer().execute(() -> {
|
||||
this.y().a(blockposition1, villageplacetype);
|
||||
PacketDebug.a(this, blockposition1);
|
||||
- });
|
||||
});
|
||||
}
|
||||
+ });
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
public final VillagePlace getPoiStorage() { return this.y(); } // Paper - OBFHELPER
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerOverworld.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerOverworld.java
|
||||
index 28b2c69ef1ad7938b09dd39e34008956f4922483..0505fd4d6882bfaa63805464a056f66ad060930e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerOverworld.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerOverworld.java
|
||||
@@ -24,7 +24,7 @@ public class WorldChunkManagerOverworld extends WorldChunkManager {
|
||||
return worldchunkmanageroverworld.k;
|
||||
})).apply(instance, instance.stable(WorldChunkManagerOverworld::new));
|
||||
});
|
||||
- private final GenLayer f;
|
||||
+ private final ThreadLocal<GenLayer> f; // Yatopia
|
||||
private static final List<ResourceKey<BiomeBase>> g = ImmutableList.of(Biomes.OCEAN, Biomes.PLAINS, Biomes.DESERT, Biomes.MOUNTAINS, Biomes.FOREST, Biomes.TAIGA, Biomes.SWAMP, Biomes.RIVER, Biomes.FROZEN_OCEAN, Biomes.FROZEN_RIVER, Biomes.SNOWY_TUNDRA, Biomes.SNOWY_MOUNTAINS, new ResourceKey[]{Biomes.MUSHROOM_FIELDS, Biomes.MUSHROOM_FIELD_SHORE, Biomes.BEACH, Biomes.DESERT_HILLS, Biomes.WOODED_HILLS, Biomes.TAIGA_HILLS, Biomes.MOUNTAIN_EDGE, Biomes.JUNGLE, Biomes.JUNGLE_HILLS, Biomes.JUNGLE_EDGE, Biomes.DEEP_OCEAN, Biomes.STONE_SHORE, Biomes.SNOWY_BEACH, Biomes.BIRCH_FOREST, Biomes.BIRCH_FOREST_HILLS, Biomes.DARK_FOREST, Biomes.SNOWY_TAIGA, Biomes.SNOWY_TAIGA_HILLS, Biomes.GIANT_TREE_TAIGA, Biomes.GIANT_TREE_TAIGA_HILLS, Biomes.WOODED_MOUNTAINS, Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.BADLANDS, Biomes.WOODED_BADLANDS_PLATEAU, Biomes.BADLANDS_PLATEAU, Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_WARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.DEEP_COLD_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.SUNFLOWER_PLAINS, Biomes.DESERT_LAKES, Biomes.GRAVELLY_MOUNTAINS, Biomes.FLOWER_FOREST, Biomes.TAIGA_MOUNTAINS, Biomes.SWAMP_HILLS, Biomes.ICE_SPIKES, Biomes.MODIFIED_JUNGLE, Biomes.MODIFIED_JUNGLE_EDGE, Biomes.TALL_BIRCH_FOREST, Biomes.TALL_BIRCH_HILLS, Biomes.DARK_FOREST_HILLS, Biomes.SNOWY_TAIGA_MOUNTAINS, Biomes.GIANT_SPRUCE_TAIGA, Biomes.GIANT_SPRUCE_TAIGA_HILLS, Biomes.MODIFIED_GRAVELLY_MOUNTAINS, Biomes.SHATTERED_SAVANNA, Biomes.SHATTERED_SAVANNA_PLATEAU, Biomes.ERODED_BADLANDS, Biomes.MODIFIED_WOODED_BADLANDS_PLATEAU, Biomes.MODIFIED_BADLANDS_PLATEAU});
|
||||
private final long h;
|
||||
private final boolean i;
|
||||
@@ -41,7 +41,7 @@ public class WorldChunkManagerOverworld extends WorldChunkManager {
|
||||
this.i = flag;
|
||||
this.j = flag1;
|
||||
this.k = iregistry;
|
||||
- this.f = GenLayers.a(i, flag, flag1 ? 6 : 4, 4);
|
||||
+ this.f = GenLayers.genLayerThreadLocal(i, flag, flag1 ? 6 : 4, 4); // Yatopia
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,6 +51,6 @@ public class WorldChunkManagerOverworld extends WorldChunkManager {
|
||||
|
||||
@Override
|
||||
public BiomeBase getBiome(int i, int j, int k) {
|
||||
- return this.f.a(this.k, i, k);
|
||||
+ return this.f.get().a(this.k, i, k); // Yatopia
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index ff98335155c86803b98d8c67f0b40b8d65214890..6f6a52bb2e445795f96ffbafaeed63c3d1f15b7e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -56,6 +56,7 @@ public abstract class ChunkGenerator {
|
||||
private final StructureSettings structureSettings;
|
||||
private final long e;
|
||||
private final List<ChunkCoordIntPair> f;
|
||||
+ public final com.ibm.asyncutil.locks.AsyncLock featureGenLock = com.ibm.asyncutil.locks.AsyncLock.createFair(); // Yatopia - threaded WorldGen
|
||||
|
||||
public ChunkGenerator(WorldChunkManager worldchunkmanager, StructureSettings structuresettings) {
|
||||
this(worldchunkmanager, worldchunkmanager, structuresettings, 0L);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
index f4a4d63a2e21b08580023cf0dcd15a68d192cf14..a01d6dfe147383242e514d2807558bf94ff8865a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
@@ -22,9 +22,51 @@ import net.minecraft.world.level.levelgen.HeightMap;
|
||||
import net.minecraft.world.level.levelgen.WorldGenStage;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager;
|
||||
import net.minecraft.world.level.lighting.LightEngine;
|
||||
+// Yatopia start
|
||||
+import java.util.concurrent.PriorityBlockingQueue;
|
||||
+import java.util.concurrent.ThreadPoolExecutor;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+// Yatopia end
|
||||
|
||||
public class ChunkStatus {
|
||||
|
||||
+ // Yatopia start - threaded WorldGen
|
||||
+ private static final ThreadPoolExecutor featureGenExecutor = new ThreadPoolExecutor(
|
||||
+ org.yatopiamc.yatopia.server.YatopiaConfig.featureGenExecutorSize == -1 ? Math.min(Runtime.getRuntime().availableProcessors(), 3) : org.yatopiamc.yatopia.server.YatopiaConfig.featureGenExecutorSize,
|
||||
+ org.yatopiamc.yatopia.server.YatopiaConfig.featureGenExecutorSize == -1 ? Math.min(Runtime.getRuntime().availableProcessors(), 3) : org.yatopiamc.yatopia.server.YatopiaConfig.featureGenExecutorSize,
|
||||
+ 0,
|
||||
+ TimeUnit.SECONDS,
|
||||
+ new PriorityBlockingQueue<>(),
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Yatopia Async Chunks FeatureGen Worker #%d").build()
|
||||
+ );
|
||||
+ private static final ThreadPoolExecutor worldGenExecutor = new ThreadPoolExecutor(
|
||||
+ org.yatopiamc.yatopia.server.YatopiaConfig.worldGenExecutorSize == -1 ? Math.min(Runtime.getRuntime().availableProcessors(), 8) : org.yatopiamc.yatopia.server.YatopiaConfig.worldGenExecutorSize,
|
||||
+ org.yatopiamc.yatopia.server.YatopiaConfig.worldGenExecutorSize == -1 ? Math.min(Runtime.getRuntime().availableProcessors(), 8) : org.yatopiamc.yatopia.server.YatopiaConfig.worldGenExecutorSize,
|
||||
+ 0,
|
||||
+ TimeUnit.SECONDS,
|
||||
+ new PriorityBlockingQueue<>(),
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Yatopia Async Chunks WorldGen Worker #%d").build()
|
||||
+ );
|
||||
+
|
||||
+ public static void shutdownExecutors() {
|
||||
+ featureGenExecutor.shutdown();
|
||||
+ worldGenExecutor.shutdown();
|
||||
+ while (!featureGenExecutor.isTerminated()) {
|
||||
+ try {
|
||||
+ featureGenExecutor.awaitTermination(30, TimeUnit.SECONDS);
|
||||
+ } catch (InterruptedException ignored) {
|
||||
+ }
|
||||
+ }
|
||||
+ while (!worldGenExecutor.isTerminated()) {
|
||||
+ try {
|
||||
+ worldGenExecutor.awaitTermination(30, TimeUnit.SECONDS);
|
||||
+ } catch (InterruptedException ignored) {
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
+
|
||||
private static final EnumSet<HeightMap.Type> n = EnumSet.of(HeightMap.Type.OCEAN_FLOOR_WG, HeightMap.Type.WORLD_SURFACE_WG);
|
||||
private static final EnumSet<HeightMap.Type> o = EnumSet.of(HeightMap.Type.OCEAN_FLOOR, HeightMap.Type.WORLD_SURFACE, HeightMap.Type.MOTION_BLOCKING, HeightMap.Type.MOTION_BLOCKING_NO_LEAVES);
|
||||
private static final ChunkStatus.c p = (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess) -> {
|
||||
@@ -37,17 +79,20 @@ public class ChunkStatus {
|
||||
public static final ChunkStatus EMPTY = a("empty", (ChunkStatus) null, -1, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
});
|
||||
public static final ChunkStatus STRUCTURE_STARTS = a("structure_starts", ChunkStatus.EMPTY, 0, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> result = CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
if (!ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
||||
if (worldserver.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures()) { // CraftBukkit
|
||||
- chunkgenerator.createStructures(worldserver.r(), worldserver.getStructureManager(), ichunkaccess, definedstructuremanager, worldserver.getSeed());
|
||||
+ result = CompletableFuture.supplyAsync(() -> {
|
||||
+ chunkgenerator.createStructures(worldserver.r(), worldserver.getStructureManager(), ichunkaccess, definedstructuremanager, worldserver.getSeed());
|
||||
+ return Either.left(ichunkaccess);
|
||||
+ }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
}
|
||||
-
|
||||
if (ichunkaccess instanceof ProtoChunk) {
|
||||
- ((ProtoChunk) ichunkaccess).a(chunkstatus);
|
||||
+ result.thenRun(() -> ((ProtoChunk) ichunkaccess).a(chunkstatus));
|
||||
}
|
||||
}
|
||||
|
||||
- return CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
+ return result;
|
||||
});
|
||||
public static final ChunkStatus STRUCTURE_REFERENCES = a("structure_references", ChunkStatus.STRUCTURE_STARTS, 8, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
RegionLimitedWorldAccess regionlimitedworldaccess = new RegionLimitedWorldAccess(worldserver, list);
|
||||
@@ -72,6 +117,9 @@ public class ChunkStatus {
|
||||
chunkgenerator.doCarving(worldserver.getSeed(), worldserver.d(), ichunkaccess, WorldGenStage.Features.LIQUID);
|
||||
});
|
||||
public static final ChunkStatus FEATURES = a("features", ChunkStatus.LIQUID_CARVERS, 8, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ // Yatopia start - threaded WorldGen
|
||||
+ return chunkgenerator.featureGenLock.acquireLock().toCompletableFuture().thenComposeAsync(token -> {
|
||||
+ try {
|
||||
ProtoChunk protochunk = (ProtoChunk) ichunkaccess;
|
||||
|
||||
protochunk.a((LightEngine) lightenginethreaded);
|
||||
@@ -82,8 +130,13 @@ public class ChunkStatus {
|
||||
chunkgenerator.addDecorations(regionlimitedworldaccess, worldserver.getStructureManager().a(regionlimitedworldaccess));
|
||||
protochunk.a(chunkstatus);
|
||||
}
|
||||
+ } finally {
|
||||
+ token.releaseLock();
|
||||
+ }
|
||||
|
||||
return CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
+ }, command -> featureGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
+ // Yatopia end
|
||||
});
|
||||
public static final ChunkStatus LIGHT = a("light", ChunkStatus.FEATURES, 1, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
return a(chunkstatus, lightenginethreaded, ichunkaccess);
|
||||
@@ -256,14 +309,18 @@ public class ChunkStatus {
|
||||
|
||||
@Override
|
||||
default CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess) {
|
||||
+ // Yatopia start - threaded worldGen
|
||||
+ return CompletableFuture.supplyAsync(() -> {
|
||||
if (!ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
||||
this.doWork(worldserver, chunkgenerator, list, ichunkaccess);
|
||||
if (ichunkaccess instanceof ProtoChunk) {
|
||||
((ProtoChunk) ichunkaccess).a(chunkstatus);
|
||||
}
|
||||
}
|
||||
+ return Either.left(ichunkaccess);
|
||||
+ }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
|
||||
- return CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
void doWork(WorldServer worldserver, ChunkGenerator chunkgenerator, List<IChunkAccess> list, IChunkAccess ichunkaccess);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java
|
||||
index 9b82ff37faaafc3a799413f6949fb88a993aa9a0..ce8fce0794c92bc4b28c410f42807a17ee3852a3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java
|
||||
@@ -837,7 +837,7 @@ public class DefinedStructure {
|
||||
private final Map<Block, List<DefinedStructure.BlockInfo>> b;
|
||||
|
||||
private a(List<DefinedStructure.BlockInfo> list) {
|
||||
- this.b = Maps.newHashMap();
|
||||
+ this.b = new java.util.concurrent.ConcurrentHashMap<>(); // Yatopia
|
||||
this.a = list;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/newbiome/layer/GenLayers.java b/src/main/java/net/minecraft/world/level/newbiome/layer/GenLayers.java
|
||||
index 5bbd71f2cf6db34dd01e8e209809a4661505aaf1..7000c3a26d0eaf94e33b68b7a56d5d5413e36a6f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/newbiome/layer/GenLayers.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/newbiome/layer/GenLayers.java
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.world.level.newbiome.layer.traits.AreaTransformer2;
|
||||
|
||||
public class GenLayers {
|
||||
|
||||
- private static final Int2IntMap a = (Int2IntMap) SystemUtils.a((Object) (new Int2IntOpenHashMap()), (int2intopenhashmap) -> {
|
||||
+ private static final Int2IntMap a = (Int2IntMap) SystemUtils.a((new Int2IntOpenHashMap()), (int2intopenhashmap) -> { // Yatopia - decompile fix
|
||||
a(int2intopenhashmap, GenLayers.Type.BEACH, 16);
|
||||
a(int2intopenhashmap, GenLayers.Type.BEACH, 26);
|
||||
a(int2intopenhashmap, GenLayers.Type.DESERT, 2);
|
||||
@@ -161,6 +161,11 @@ public class GenLayers {
|
||||
return new GenLayer(areafactory);
|
||||
}
|
||||
|
||||
+ // Yatopia start
|
||||
+ public static ThreadLocal<GenLayer> genLayerThreadLocal(long i, boolean flag, int j, int k) {
|
||||
+ return ThreadLocal.withInitial(() -> new GenLayer(a(flag, j, k, (l) -> new WorldGenContextArea(25, i, l))));
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
public static boolean a(int i, int j) {
|
||||
return i == j ? true : GenLayers.a.get(i) == GenLayers.a.get(j);
|
||||
}
|
||||
diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
index 15e2fa125bc293b954cceb5b1fbcec7fade3e4db..7d8e04a5792283a27c044758fb4bc12567b289cb 100644
|
||||
--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
+++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.yatopiamc.yatopia.server;
|
||||
|
||||
+import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Throwables;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -276,4 +277,13 @@ public class YatopiaConfig {
|
||||
fixProtocolLib = getBoolean("settings.fix-protocollib", fixProtocolLib);
|
||||
}
|
||||
|
||||
+ public static int featureGenExecutorSize = -1;
|
||||
+ public static int worldGenExecutorSize = -1;
|
||||
+ private static void multiThreadedWorldGen() {
|
||||
+ featureGenExecutorSize = getInt("settings.threads.featuregen", -1);
|
||||
+ Preconditions.checkArgument(featureGenExecutorSize == -1 || featureGenExecutorSize > 0, "Invalid settings.threads.featuregen in yatopia.yml");
|
||||
+ worldGenExecutorSize = getInt("settings.threads.worldgen", -1);
|
||||
+ Preconditions.checkArgument(worldGenExecutorSize == -1 || worldGenExecutorSize > 0, "Invalid settings.threads.worldgen in yatopia.yml");
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/src/main/java/org/yatopiamc/yatopia/server/executors/PrioritizedRunnable.java b/src/main/java/org/yatopiamc/yatopia/server/executors/PrioritizedRunnable.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..51dff59bbd9057c4cb249349cd8bb22a8267c237
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/yatopiamc/yatopia/server/executors/PrioritizedRunnable.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package org.yatopiamc.yatopia.server.executors;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import java.util.function.Supplier;
|
||||
+
|
||||
+public class PrioritizedRunnable implements Runnable, Comparable<PrioritizedRunnable> {
|
||||
+
|
||||
+ private final Supplier<Integer> prioritySupplier;
|
||||
+ private final Runnable runnable;
|
||||
+
|
||||
+ public PrioritizedRunnable(Supplier<Integer> prioritySupplier, Runnable runnable) {
|
||||
+ this.prioritySupplier = prioritySupplier;
|
||||
+ this.runnable = runnable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int compareTo(@Nonnull PrioritizedRunnable o) {
|
||||
+ return Integer.compare(this.getPriority(), o.getPriority());
|
||||
+ }
|
||||
+
|
||||
+ public int getPriority() {
|
||||
+ return prioritySupplier.get();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ runnable.run();
|
||||
+ }
|
||||
+}
|
298
patches/server/0065-Multi-threaded-RegionFile-IO.patch
Normal file
298
patches/server/0065-Multi-threaded-RegionFile-IO.patch
Normal file
|
@ -0,0 +1,298 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Sun, 15 Nov 2020 10:42:27 +0800
|
||||
Subject: [PATCH] Multi-threaded RegionFile IO
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java
|
||||
index 9fe91f9512ee8c2589fc8da76bda5f6d70c9fac4..8b81119cfdef81665a302d96cfada5bb43bc1077 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java
|
||||
@@ -35,7 +35,7 @@ import java.util.function.Function;
|
||||
* @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int)
|
||||
* @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)
|
||||
*/
|
||||
-public final class PaperFileIOThread extends QueueExecutorThread {
|
||||
+public final class PaperFileIOThread { // Yatopia
|
||||
|
||||
public static final Logger LOGGER = MinecraftServer.LOGGER;
|
||||
public static final NBTTagCompound FAILURE_VALUE = new NBTTagCompound();
|
||||
@@ -44,23 +44,84 @@ public final class PaperFileIOThread extends QueueExecutorThread {
|
||||
|
||||
public static final PaperFileIOThread INSTANCE = new PaperFileIOThread();
|
||||
|
||||
+ /* Yatopia
|
||||
static {
|
||||
INSTANCE.start();
|
||||
}
|
||||
+ */
|
||||
}
|
||||
|
||||
private final AtomicLong writeCounter = new AtomicLong();
|
||||
+ // Yatopia start - multi-threaded RegionFile IO
|
||||
+ private final com.ibm.asyncutil.locks.AsyncNamedLock<RegionFileCoord> regionFileLock = com.ibm.asyncutil.locks.AsyncNamedLock.createFair();
|
||||
+ private final PrioritizedTaskQueue<PrioritizedTaskQueue.PrioritizedTask> queue;
|
||||
+ private final PaperFileIOThread.FileIOExecutorThread receiver;
|
||||
+ private final java.util.Set<Thread> executorThreads = com.google.common.collect.Sets.newConcurrentHashSet();
|
||||
+ private final java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(
|
||||
+ org.yatopiamc.yatopia.server.YatopiaConfig.regionFileIOThreadPoolSize == -1 ? Math.min(Runtime.getRuntime().availableProcessors(), Integer.getInteger("paper.maxChunkThreads", 8)) : org.yatopiamc.yatopia.server.YatopiaConfig.regionFileIOThreadPoolSize,
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder()
|
||||
+ .setNameFormat("Paper RegionFile IO Worker #%d")
|
||||
+ .setPriority(Thread.NORM_PRIORITY - 1)
|
||||
+ .setDaemon(true)
|
||||
+ .setThreadFactory(r -> {
|
||||
+ Thread thr = new Thread(r);
|
||||
+ executorThreads.add(thr);
|
||||
+ return thr;
|
||||
+ })
|
||||
+ .setUncaughtExceptionHandler((t, e) -> {
|
||||
+ LOGGER.fatal("Uncaught exception thrown from " + t.getName() + ", report this!", e);
|
||||
+ executorThreads.remove(t);
|
||||
+ })
|
||||
+ .build()
|
||||
+ );
|
||||
|
||||
private PaperFileIOThread() {
|
||||
- super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time
|
||||
- this.setName("Paper RegionFile IO Thread");
|
||||
- this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us
|
||||
- this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> {
|
||||
- LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr);
|
||||
+ queue = new PrioritizedTaskQueue<>();
|
||||
+ receiver = new PaperFileIOThread.FileIOExecutorThread(queue, (int) (1.0e6)); // 1.0ms spinwait time
|
||||
+ receiver.setName("Paper RegionFile IO Task Receiver");
|
||||
+ receiver.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us
|
||||
+ receiver.setUncaughtExceptionHandler((final Thread thread, final Throwable thr) -> {
|
||||
+ LOGGER.fatal("Uncaught exception thrown from " + thread.getName() + ", report this!", thr);
|
||||
});
|
||||
+ receiver.start();
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ public void flush() {
|
||||
+ receiver.flush();
|
||||
+ final java.util.Set<CompletableFuture<?>> runningTasks = new java.util.HashSet<>(receiver.runningTasks);
|
||||
+ LOGGER.debug("Flushing Chunk IO: Waiting for {} futures", runningTasks.size());
|
||||
+ for(CompletableFuture<?> future: runningTasks) {
|
||||
+ try {
|
||||
+ future.join();
|
||||
+ } catch (Throwable ignored) {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void queueTask(PrioritizedTaskQueue.PrioritizedTask newTask) {
|
||||
+ queue.add(newTask);
|
||||
+ receiver.notifyTasks();
|
||||
+ }
|
||||
+
|
||||
+ public void close(final boolean wait) {
|
||||
+ receiver.close(wait, true);
|
||||
+ this.flush();
|
||||
+ executor.shutdown();
|
||||
+ while (wait && !executor.isTerminated()) {
|
||||
+ try {
|
||||
+ executor.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS);
|
||||
+ } catch (InterruptedException e) {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
+ public boolean isOnWorkerThread() {
|
||||
+ return executorThreads.contains(Thread.currentThread());
|
||||
}
|
||||
|
||||
- /* run() is implemented by superclass */
|
||||
+ // Yatopia end
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -394,6 +455,85 @@ public final class PaperFileIOThread extends QueueExecutorThread {
|
||||
this.queueTask(new GeneralTask(priority, runnable));
|
||||
}
|
||||
|
||||
+ // Yatopia start
|
||||
+ public static final class RegionFileCoord {
|
||||
+
|
||||
+ public final int x;
|
||||
+ public final int z;
|
||||
+
|
||||
+ public RegionFileCoord(int x, int z) {
|
||||
+ this.x = x;
|
||||
+ this.z = z;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ RegionFileCoord that = (RegionFileCoord) o;
|
||||
+ return x == that.x && z == that.z;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return java.util.Objects.hash(x, z);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final class FileIOExecutorThread<T extends PrioritizedTaskQueue.PrioritizedTask & Runnable> extends QueueExecutorThread<T> {
|
||||
+ private final java.util.Set<CompletableFuture<?>> runningTasks = com.google.common.collect.Sets.newConcurrentHashSet();
|
||||
+
|
||||
+ public FileIOExecutorThread(PrioritizedTaskQueue<T> queue, long spinWaitTime) {
|
||||
+ super(queue, spinWaitTime);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void preMainLoop() {
|
||||
+ runningTasks.removeIf(CompletableFuture::isDone);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected boolean pollTasks(boolean flushTasks) {
|
||||
+ Runnable task;
|
||||
+ boolean ret = false;
|
||||
+
|
||||
+ while ((task = this.queue.poll()) != null) {
|
||||
+ ret = true;
|
||||
+ if (task instanceof ChunkDataTask) {
|
||||
+ ChunkDataTask chunkDataTask = (ChunkDataTask) task;
|
||||
+ runningTasks.add(regionFileLock.acquireLock(new RegionFileCoord(chunkDataTask.x >> 5, chunkDataTask.z >> 5))
|
||||
+ .thenApplyAsync(lockToken -> {
|
||||
+ try {
|
||||
+ chunkDataTask.run();
|
||||
+ } finally {
|
||||
+ lockToken.releaseLock();
|
||||
+ }
|
||||
+ return null;
|
||||
+ }, executor)
|
||||
+ .exceptionally(throwable -> {
|
||||
+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + Thread.currentThread().getName() + "': " + IOUtil.genericToString(chunkDataTask), throwable);
|
||||
+ return null;
|
||||
+ }).toCompletableFuture());
|
||||
+ } else {
|
||||
+ Runnable finalTask = task;
|
||||
+ runningTasks.add(CompletableFuture.supplyAsync(() -> {
|
||||
+ finalTask.run();
|
||||
+ return null;
|
||||
+ }).exceptionally(throwable -> {
|
||||
+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + Thread.currentThread().getName() + "': " + IOUtil.genericToString(finalTask), throwable);
|
||||
+ return null;
|
||||
+ }));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (flushTasks) {
|
||||
+ this.handleFlushThreads(false);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable {
|
||||
|
||||
private final Runnable run;
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java
|
||||
index ee906b594b306906c170180a29a8b61997d05168..7e348fcb813707fee830082b826932e0bbba1c49 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java
|
||||
@@ -35,6 +35,7 @@ public class QueueExecutorThread<T extends PrioritizedTaskQueue.PrioritizedTask
|
||||
final long spinWaitTime = this.spinWaitTime;
|
||||
main_loop:
|
||||
for (;;) {
|
||||
+ preMainLoop(); // Yatopia
|
||||
this.pollTasks(true);
|
||||
|
||||
// spinwait
|
||||
@@ -81,11 +82,17 @@ public class QueueExecutorThread<T extends PrioritizedTaskQueue.PrioritizedTask
|
||||
// LockSupport.park() can fail for any reason
|
||||
do {
|
||||
Thread.interrupted();
|
||||
- LockSupport.park("Waiting on tasks");
|
||||
+ LockSupport.parkNanos("Waiting on tasks", 1_000_000_000); // Yatopia - prevent dead lock
|
||||
} while (this.parked.get());
|
||||
}
|
||||
}
|
||||
|
||||
+ // Yatopia start
|
||||
+ protected void preMainLoop() {
|
||||
+ // Used for PaperFileIOThread
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
+
|
||||
protected boolean handleClose() {
|
||||
if (this.closed) {
|
||||
this.pollTasks(true); // this ensures we've emptied the queue
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index b21c09f5b1cde7f7a710fe8960face8cb21040c4..2c2c299f261685cff2866e4714ec0a251205ed9d 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -955,7 +955,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
LOGGER.info("Flushing Chunk IO");
|
||||
net.minecraft.server.level.PlayerChunkMap.shutdownScheduler(); // Yatopia
|
||||
net.minecraft.world.level.chunk.ChunkStatus.shutdownExecutors(); // Yatopia
|
||||
- com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true, true); // Paper
|
||||
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true); // Paper // Yatopia
|
||||
LOGGER.info("Closing Thread Pool");
|
||||
SystemUtils.shutdownServerThreadPool(); // Paper
|
||||
LOGGER.info("Closing Server");
|
||||
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
index b9d38413da1adbffd21df301f03cf181d4cd5cdc..7b1157de77d4e24a7540c070d922b49f2a06a319 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
@@ -1772,7 +1772,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@Nullable
|
||||
@Override
|
||||
public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
|
||||
- if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) {
|
||||
+ if (!com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.isOnWorkerThread()) { // Yatopia
|
||||
NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE
|
||||
.loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(),
|
||||
false, true, true).join().chunkData;
|
||||
@@ -1787,7 +1787,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
@Override
|
||||
public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException {
|
||||
- if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) {
|
||||
+ if (!com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.isOnWorkerThread()) { // Yatopia
|
||||
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(
|
||||
this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound,
|
||||
com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - writes are async, no need for priority
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
index 29cd71efe86eea2227f373c15c39dc530e9e8199..55d497f4305de50e58c7e0788724576f81128138 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
@@ -504,7 +504,7 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
|
||||
@javax.annotation.Nullable
|
||||
@Override
|
||||
public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException {
|
||||
- if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) {
|
||||
+ if (this.world != null && !com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.isOnWorkerThread()) { // Yatopia
|
||||
NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE
|
||||
.loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(),
|
||||
true, false, true).join().poiData;
|
||||
@@ -519,7 +519,7 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
|
||||
|
||||
@Override
|
||||
public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException {
|
||||
- if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) {
|
||||
+ if (this.world != null && !com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.isOnWorkerThread()) { // Yatopia
|
||||
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(
|
||||
this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null,
|
||||
com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); // Tuinity - writes are async, no need for priority
|
||||
diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
index 7d8e04a5792283a27c044758fb4bc12567b289cb..fa16608b24cd68e4195e72143d39db38702dba40 100644
|
||||
--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
+++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
|
||||
@@ -286,4 +286,9 @@ public class YatopiaConfig {
|
||||
Preconditions.checkArgument(worldGenExecutorSize == -1 || worldGenExecutorSize > 0, "Invalid settings.threads.worldgen in yatopia.yml");
|
||||
}
|
||||
|
||||
+ public static int regionFileIOThreadPoolSize = -1;
|
||||
+ private static void multiThreadedRegionFile() {
|
||||
+ regionFileIOThreadPoolSize = getInt("settings.threads.regionfile", -1);
|
||||
+ Preconditions.checkArgument(regionFileIOThreadPoolSize == -1 || regionFileIOThreadPoolSize > 0, "Invalid settings.threads.regionfile in yatopia.yml");
|
||||
+ }
|
||||
}
|
144
patches/server/0066-Multi-threaded-World-Upgrade.patch
Normal file
144
patches/server/0066-Multi-threaded-World-Upgrade.patch
Normal file
|
@ -0,0 +1,144 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Fri, 5 Feb 2021 19:34:00 +0800
|
||||
Subject: [PATCH] Multi-threaded World Upgrade
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
|
||||
index 6818f8496ab76ee6ffc747bd6848b43830ec8914..1fe2610ed0ddab1e203e273914c9325aec74e7c2 100644
|
||||
--- a/src/main/java/net/minecraft/server/Main.java
|
||||
+++ b/src/main/java/net/minecraft/server/Main.java
|
||||
@@ -281,6 +281,8 @@ public class Main {
|
||||
WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag);
|
||||
IChatBaseComponent ichatbasecomponent = null;
|
||||
|
||||
+ long lastLocation = 0L; // Yatopia
|
||||
+ long lastTime = System.nanoTime(); // Yatopia
|
||||
while (!worldupgrader.b()) {
|
||||
IChatBaseComponent ichatbasecomponent1 = worldupgrader.h();
|
||||
|
||||
@@ -289,13 +291,16 @@ public class Main {
|
||||
Main.LOGGER.info(worldupgrader.h().getString());
|
||||
}
|
||||
|
||||
- int i = worldupgrader.e();
|
||||
-
|
||||
- if (i > 0) {
|
||||
- int j = worldupgrader.f() + worldupgrader.g();
|
||||
-
|
||||
- Main.LOGGER.info("{}% completed ({} / {} chunks)...", MathHelper.d((float) j / (float) i * 100.0F), j, i);
|
||||
- }
|
||||
+ // Yatopia start
|
||||
+ long totalChunkCount = worldupgrader.getTotalChunkCount();
|
||||
+ if (totalChunkCount > 0) {
|
||||
+ long processedCount = worldupgrader.getUpgradedChunkCount() + worldupgrader.getSkippedChunkCount();
|
||||
+ long currentTime = System.nanoTime();
|
||||
+ String speedRate = String.format("%.1f", (processedCount - lastLocation) / ((currentTime - lastTime) / 1_000_000_000.0));
|
||||
+ Main.LOGGER.info("{}% completed ({} / {} chunks) at {}cps...", MathHelper.d((float) processedCount / (float) totalChunkCount * 100.0F), processedCount, totalChunkCount, speedRate);
|
||||
+ lastLocation = processedCount;
|
||||
+ lastTime = currentTime;
|
||||
+ } // Yatopia end
|
||||
|
||||
if (!booleansupplier.getAsBoolean()) {
|
||||
worldupgrader.a();
|
||||
diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
index 6725b31a5183d5af7f8f7566ed21eb61797ef4c9..f13e16aca89f5013ef316e7dbf3d4c67885e6f3e 100644
|
||||
--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
@@ -33,6 +33,13 @@ import net.minecraft.world.level.storage.Convertable;
|
||||
import net.minecraft.world.level.storage.WorldPersistentData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
+// Yatopia start
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
+import java.util.Set;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import java.util.concurrent.ExecutorService;
|
||||
+import java.util.concurrent.Executors;
|
||||
+// Yatopia end
|
||||
|
||||
// CraftBukkit start
|
||||
import net.minecraft.world.level.dimension.DimensionManager;
|
||||
@@ -50,9 +57,9 @@ public class WorldUpgrader {
|
||||
private volatile boolean h = true;
|
||||
private volatile boolean i;
|
||||
private volatile float j;
|
||||
- private volatile int k;
|
||||
- private volatile int l;
|
||||
- private volatile int m;
|
||||
+ private volatile long k; // Yatopia - int -> long
|
||||
+ private volatile long l; // Yatopia - int -> long
|
||||
+ private volatile long m; // Yatopia - int -> long
|
||||
private final Object2FloatMap<ResourceKey<DimensionManager>> n = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(SystemUtils.k())); // CraftBukkit
|
||||
private volatile IChatBaseComponent o = new ChatMessage("optimizeWorld.stage.counting");
|
||||
private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
|
||||
@@ -117,6 +124,11 @@ public class WorldUpgrader {
|
||||
|
||||
this.o = new ChatMessage("optimizeWorld.stage.upgrading");
|
||||
|
||||
+ // Yatopia start
|
||||
+ final ExecutorService upgradeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactoryBuilder().setDaemon(true).setPriority(Thread.NORM_PRIORITY - 1).setNameFormat("WorldUpgrader Worker #%d").build());
|
||||
+ final Set<CompletableFuture<Void>> futures = new ObjectOpenHashSet<>();
|
||||
+ final com.ibm.asyncutil.locks.AsyncNamedLock<Integer> regionFileLocks = com.ibm.asyncutil.locks.AsyncNamedLock.createFair();
|
||||
+ // Yatopia end
|
||||
while (this.h) {
|
||||
boolean flag = false;
|
||||
float f1 = 0.0F;
|
||||
@@ -130,6 +142,11 @@ public class WorldUpgrader {
|
||||
|
||||
if (listiterator.hasNext()) {
|
||||
ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) listiterator.next();
|
||||
+ // Yatopia start
|
||||
+ flag = true;
|
||||
+ futures.add(regionFileLocks.acquireLock(String.format("%d %d", chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()).hashCode()).toCompletableFuture().thenAcceptAsync(lockToken -> {
|
||||
+ try {
|
||||
+ // Yatopia end
|
||||
boolean flag1 = false;
|
||||
|
||||
try {
|
||||
@@ -179,7 +196,12 @@ public class WorldUpgrader {
|
||||
++this.m;
|
||||
}
|
||||
|
||||
- flag = true;
|
||||
+ // Yatopia start
|
||||
+ } finally {
|
||||
+ lockToken.releaseLock();
|
||||
+ }
|
||||
+ }, upgradeExecutor));
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
f2 = (float) listiterator.nextIndex() / f;
|
||||
@@ -192,6 +214,8 @@ public class WorldUpgrader {
|
||||
}
|
||||
}
|
||||
|
||||
+ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); // Yatopia
|
||||
+ upgradeExecutor.shutdown(); // Yatopia
|
||||
this.o = new ChatMessage("optimizeWorld.stage.finished");
|
||||
UnmodifiableIterator unmodifiableiterator3 = immutablemap1.values().iterator();
|
||||
|
||||
@@ -280,16 +304,19 @@ public class WorldUpgrader {
|
||||
}
|
||||
|
||||
public int e() {
|
||||
- return this.k;
|
||||
+ return (int) this.k; // Yatopia
|
||||
}
|
||||
+ public long getTotalChunkCount() { return this.k; } // Yatopia
|
||||
|
||||
public int f() {
|
||||
- return this.l;
|
||||
+ return (int) this.l; // Yatopia
|
||||
}
|
||||
+ public long getUpgradedChunkCount() { return this.l; } // Yatopia
|
||||
|
||||
public int g() {
|
||||
- return this.m;
|
||||
+ return (int) this.m; // Yatopia
|
||||
}
|
||||
+ public long getSkippedChunkCount() { return this.m; } // Yatopia
|
||||
|
||||
public IChatBaseComponent h() {
|
||||
return this.o;
|
|
@ -0,0 +1,147 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Wed, 3 Feb 2021 23:00:18 +0800
|
||||
Subject: [PATCH] Decompile fixes for WorldChunkManagerMultiNoise
|
||||
|
||||
who knows what duplex is doing
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java
|
||||
index c4fb051739c1c186c1574185e0653f513755987d..e9993fa0f3af9e3ecd01f91ef5c14e528bdb33b5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java
|
||||
@@ -52,6 +52,13 @@ import org.apache.logging.log4j.Logger;
|
||||
public final class BiomeBase {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
+ // Yatopia start
|
||||
+ static class cProxy extends BiomeBase.c {
|
||||
+ public cProxy(float f, float f1, float f2, float f3, float f4) {
|
||||
+ super(f, f1, f2, f3, f4);
|
||||
+ }
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
// Paper start
|
||||
private static class dProxy extends BiomeBase.d {
|
||||
private dProxy(Precipitation biomebase_precipitation, float f, TemperatureModifier biomebase_temperaturemodifier, float f1) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
index 5287aec4c384c6cea76334ae1d8dc99070e8f43e..92d1e771c2f896fb3b363a57aa59c04c3f466bea 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.datafixers.util.Function3;
|
||||
+import com.mojang.datafixers.util.Function6; // Yatopia - decompile fix
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
@@ -27,26 +28,43 @@ import net.minecraft.world.level.levelgen.synth.NoiseGeneratorNormal;
|
||||
|
||||
public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
|
||||
+ // Yatopia start - decompile fix
|
||||
+ private static class aProxy extends WorldChunkManagerMultiNoise.a {
|
||||
+ public aProxy(int i, List<Double> list) {
|
||||
+ super(i, list);
|
||||
+ }
|
||||
+ }
|
||||
+ private static class bProxy extends WorldChunkManagerMultiNoise.b {
|
||||
+ public bProxy(MinecraftKey minecraftkey, Function3<WorldChunkManagerMultiNoise.b, IRegistry<BiomeBase>, Long, WorldChunkManagerMultiNoise> function3) {
|
||||
+ super(minecraftkey, function3);
|
||||
+ }
|
||||
+ }
|
||||
+ private static class cProxy extends WorldChunkManagerMultiNoise.c {
|
||||
+ private cProxy(WorldChunkManagerMultiNoise.b worldchunkmanagermultinoise_b, IRegistry<BiomeBase> iregistry, long i) {
|
||||
+ super(worldchunkmanagermultinoise_b, iregistry, i);
|
||||
+ }
|
||||
+ }
|
||||
+ // Yatopia end
|
||||
private static final WorldChunkManagerMultiNoise.a g = new WorldChunkManagerMultiNoise.a(-7, ImmutableList.of(1.0D, 1.0D));
|
||||
public static final MapCodec<WorldChunkManagerMultiNoise> e = RecordCodecBuilder.mapCodec((instance) -> {
|
||||
return instance.group(Codec.LONG.fieldOf("seed").forGetter((worldchunkmanagermultinoise) -> {
|
||||
return worldchunkmanagermultinoise.r;
|
||||
}), RecordCodecBuilder.create((instance1) -> {
|
||||
- return instance1.group(BiomeBase.c.a.fieldOf("parameters").forGetter(Pair::getFirst), BiomeBase.d.fieldOf("biome").forGetter(Pair::getSecond)).apply(instance1, Pair::of);
|
||||
- }).listOf().fieldOf("biomes").forGetter((worldchunkmanagermultinoise) -> {
|
||||
- return worldchunkmanagermultinoise.p;
|
||||
- }), WorldChunkManagerMultiNoise.a.a.fieldOf("temperature_noise").forGetter((worldchunkmanagermultinoise) -> {
|
||||
+ return instance1.group(BiomeBase.cProxy.a.fieldOf("parameters").forGetter((java.util.function.Function) t -> ((Pair) t).getFirst()), BiomeBase.d.fieldOf("biome").forGetter(t1 -> (Supplier<BiomeBase>) ((Pair) t1).getSecond())).apply(instance1, Pair::of); // Yatopia - decompile fix
|
||||
+ }).listOf().fieldOf("biomes").forGetter((Function) worldchunkmanagermultinoise -> { // Yatopia - decompile fix
|
||||
+ return ((WorldChunkManagerMultiNoise) worldchunkmanagermultinoise).p; // Yatopia - decompile fix
|
||||
+ }), WorldChunkManagerMultiNoise.aProxy.a.fieldOf("temperature_noise").forGetter((worldchunkmanagermultinoise) -> { // Yatopia - decompile fix
|
||||
return worldchunkmanagermultinoise.h;
|
||||
- }), WorldChunkManagerMultiNoise.a.a.fieldOf("humidity_noise").forGetter((worldchunkmanagermultinoise) -> {
|
||||
+ }), WorldChunkManagerMultiNoise.aProxy.a.fieldOf("humidity_noise").forGetter((worldchunkmanagermultinoise) -> { // Yatopia - decompile fix
|
||||
return worldchunkmanagermultinoise.i;
|
||||
- }), WorldChunkManagerMultiNoise.a.a.fieldOf("altitude_noise").forGetter((worldchunkmanagermultinoise) -> {
|
||||
+ }), WorldChunkManagerMultiNoise.aProxy.a.fieldOf("altitude_noise").forGetter((worldchunkmanagermultinoise) -> { // Yatopia - decompile fix
|
||||
return worldchunkmanagermultinoise.j;
|
||||
- }), WorldChunkManagerMultiNoise.a.a.fieldOf("weirdness_noise").forGetter((worldchunkmanagermultinoise) -> {
|
||||
+ }), WorldChunkManagerMultiNoise.aProxy.a.fieldOf("weirdness_noise").forGetter((worldchunkmanagermultinoise) -> { // Yatopia - decompile fix
|
||||
return worldchunkmanagermultinoise.k;
|
||||
- })).apply(instance, WorldChunkManagerMultiNoise::new);
|
||||
+ })).apply(instance, (Function6<Long, List<Pair<BiomeBase.c, Supplier<BiomeBase>>>, WorldChunkManagerMultiNoise.a, WorldChunkManagerMultiNoise.a, WorldChunkManagerMultiNoise.a, WorldChunkManagerMultiNoise.a, WorldChunkManagerMultiNoise>) WorldChunkManagerMultiNoise::new); // Yatopia - decompile fix
|
||||
});
|
||||
- public static final Codec<WorldChunkManagerMultiNoise> f = Codec.mapEither(WorldChunkManagerMultiNoise.c.a, WorldChunkManagerMultiNoise.e).xmap((either) -> {
|
||||
- return (WorldChunkManagerMultiNoise) either.map(WorldChunkManagerMultiNoise.c::d, Function.identity());
|
||||
+ public static final Codec<WorldChunkManagerMultiNoise> f = Codec.mapEither(WorldChunkManagerMultiNoise.cProxy.a, WorldChunkManagerMultiNoise.e).xmap((either) -> { // Yatopia - decompile fix
|
||||
+ return (WorldChunkManagerMultiNoise) either.map(c -> c.d(), Function.identity()); // Yatopia - decompile fix
|
||||
}, (worldchunkmanagermultinoise) -> {
|
||||
return (Either) worldchunkmanagermultinoise.d().map(Either::left).orElseGet(() -> {
|
||||
return Either.right(worldchunkmanagermultinoise);
|
||||
@@ -111,13 +129,13 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
}
|
||||
|
||||
public boolean b(long i) {
|
||||
- return this.r == i && this.s.isPresent() && Objects.equals(((Pair) this.s.get()).getSecond(), WorldChunkManagerMultiNoise.b.a);
|
||||
+ return this.r == i && this.s.isPresent() && Objects.equals(((Pair) this.s.get()).getSecond(), WorldChunkManagerMultiNoise.bProxy.a); // Yatopia - decompile fix
|
||||
}
|
||||
|
||||
public static class b {
|
||||
|
||||
- private static final Map<MinecraftKey, WorldChunkManagerMultiNoise.b> b = Maps.newHashMap();
|
||||
- public static final WorldChunkManagerMultiNoise.b a = new WorldChunkManagerMultiNoise.b(new MinecraftKey("nether"), (worldchunkmanagermultinoise_b, iregistry, olong) -> {
|
||||
+ protected static final Map<MinecraftKey, WorldChunkManagerMultiNoise.b> b = Maps.newHashMap(); // Yatopia - decompile fix
|
||||
+ public static final WorldChunkManagerMultiNoise.b a = new WorldChunkManagerMultiNoise.b(new MinecraftKey("nether"), (worldchunkmanagermultinoise_b, iregistry, olong) -> { // Yatopia - decompile fix
|
||||
return new WorldChunkManagerMultiNoise(olong, ImmutableList.of(Pair.of(new BiomeBase.c(0.0F, 0.0F, 0.0F, 0.0F, 0.0F), () -> {
|
||||
return (BiomeBase) iregistry.d(Biomes.NETHER_WASTES);
|
||||
}), Pair.of(new BiomeBase.c(0.0F, -0.5F, 0.0F, 0.0F, 0.0F), () -> {
|
||||
@@ -136,7 +154,7 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
public b(MinecraftKey minecraftkey, Function3<WorldChunkManagerMultiNoise.b, IRegistry<BiomeBase>, Long, WorldChunkManagerMultiNoise> function3) {
|
||||
this.c = minecraftkey;
|
||||
this.d = function3;
|
||||
- WorldChunkManagerMultiNoise.b.b.put(minecraftkey, this);
|
||||
+ WorldChunkManagerMultiNoise.bProxy.b.put(minecraftkey, this); // Yatopia - decompile fix
|
||||
}
|
||||
|
||||
public WorldChunkManagerMultiNoise a(IRegistry<BiomeBase> iregistry, long i) {
|
||||
@@ -144,16 +162,16 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
}
|
||||
}
|
||||
|
||||
- static final class c {
|
||||
+ static class c { // Yatopia - decompile fix
|
||||
|
||||
public static final MapCodec<WorldChunkManagerMultiNoise.c> a = RecordCodecBuilder.mapCodec((instance) -> {
|
||||
return instance.group(MinecraftKey.a.flatXmap((minecraftkey) -> {
|
||||
- return (DataResult) Optional.ofNullable(WorldChunkManagerMultiNoise.b.b.get(minecraftkey)).map(DataResult::success).orElseGet(() -> {
|
||||
+ return (DataResult) Optional.ofNullable(bProxy.b.get(minecraftkey)).map(DataResult::success).orElseGet(() -> { // Yatopia - decompile fix
|
||||
return DataResult.error("Unknown preset: " + minecraftkey);
|
||||
});
|
||||
}, (worldchunkmanagermultinoise_b) -> {
|
||||
- return DataResult.success(worldchunkmanagermultinoise_b.c);
|
||||
- }).fieldOf("preset").stable().forGetter(WorldChunkManagerMultiNoise.c::a), RegistryLookupCodec.a(IRegistry.ay).forGetter(WorldChunkManagerMultiNoise.c::b), Codec.LONG.fieldOf("seed").stable().forGetter(WorldChunkManagerMultiNoise.c::c)).apply(instance, instance.stable(WorldChunkManagerMultiNoise.c::new));
|
||||
+ return DataResult.success(((WorldChunkManagerMultiNoise.b) worldchunkmanagermultinoise_b).c); // Yatopia - decompile fix
|
||||
+ }).fieldOf("preset").stable().forGetter(o -> ((WorldChunkManagerMultiNoise.c) o).a()), (RecordCodecBuilder) RegistryLookupCodec.a(IRegistry.ay).forGetter((Function<WorldChunkManagerMultiNoise.c, IRegistry<BiomeBase>>) c -> c.b()), (RecordCodecBuilder) Codec.LONG.fieldOf("seed").stable().forGetter((Function<WorldChunkManagerMultiNoise.c, Long>) c -> c.c())).apply(instance, instance.stable((Function3<WorldChunkManagerMultiNoise.b, IRegistry<BiomeBase>, Long, WorldChunkManagerMultiNoise.c>) WorldChunkManagerMultiNoise.c::new)); // Yatopia - decompile fix
|
||||
});
|
||||
private final WorldChunkManagerMultiNoise.b b;
|
||||
private final IRegistry<BiomeBase> c;
|
||||
@@ -187,7 +205,7 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
private final int b;
|
||||
private final DoubleList c;
|
||||
public static final Codec<WorldChunkManagerMultiNoise.a> a = RecordCodecBuilder.create((instance) -> {
|
||||
- return instance.group(Codec.INT.fieldOf("firstOctave").forGetter(WorldChunkManagerMultiNoise.a::a), Codec.DOUBLE.listOf().fieldOf("amplitudes").forGetter(WorldChunkManagerMultiNoise.a::b)).apply(instance, WorldChunkManagerMultiNoise.a::new);
|
||||
+ return instance.group(Codec.INT.fieldOf("firstOctave").forGetter((Function<WorldChunkManagerMultiNoise.a, Integer>) a -> a.a()), Codec.DOUBLE.listOf().fieldOf("amplitudes").forGetter(a -> a.b())).apply(instance, WorldChunkManagerMultiNoise.a::new); // Yatopia - decompile fix
|
||||
});
|
||||
|
||||
public a(int i, List<Double> list) {
|
64
patches/server/0068-lithium-MultiNoiseBiomeSourceMixin.patch
Normal file
64
patches/server/0068-lithium-MultiNoiseBiomeSourceMixin.patch
Normal file
|
@ -0,0 +1,64 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
|
||||
Date: Wed, 3 Feb 2021 16:39:27 -0600
|
||||
Subject: [PATCH] lithium MultiNoiseBiomeSourceMixin
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
index 92d1e771c2f896fb3b363a57aa59c04c3f466bea..23637d9be9f9973266c1bba699c40cdc6c5d9e6d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerMultiNoise.java
|
||||
@@ -118,8 +118,44 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
});
|
||||
}
|
||||
|
||||
+ //Yatopia - Faster Method
|
||||
+ /**
|
||||
+ * @reason Remove stream based code in favor of regular collections.
|
||||
+ * @author SuperCoder79
|
||||
+ */
|
||||
@Override
|
||||
public BiomeBase getBiome(int i, int j, int k) {
|
||||
+ // [VanillaCopy] MultiNoiseBiomeSource#getBiomeForNoiseGen
|
||||
+
|
||||
+ // Get the y value for perlin noise sampling. This field is always set to false in vanilla code.
|
||||
+ int l = this.q ? j : 0;
|
||||
+
|
||||
+ // Calculate the noise point based using 4 perlin noise samplers.
|
||||
+ BiomeBase.c biomebase_c = new BiomeBase.c(
|
||||
+ (float) this.l.a(i, l, k),
|
||||
+ (float) this.m.a(i, l, k),
|
||||
+ (float) this.n.a(i, l, k),
|
||||
+ (float) this.o.a(i, l, k),
|
||||
+ 0.0F);
|
||||
+
|
||||
+ int idx = -1;
|
||||
+ float min = Float.POSITIVE_INFINITY;
|
||||
+
|
||||
+ // Iterate through the biome points and calculate the distance to the current noise point.
|
||||
+ for (int itterator = 0; itterator < this.p.size(); itterator++) {
|
||||
+ float distance = this.p.get(itterator).getFirst().a(biomebase_c);
|
||||
+
|
||||
+ // If the distance is less than the recorded minimum, update the minimum and set the current index.
|
||||
+ if (min > distance) {
|
||||
+ idx = itterator;
|
||||
+ min = distance;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Return the biome with the noise point closest to the evaluated one.
|
||||
+ return this.p.get(idx).getSecond().get() == null ? BiomeRegistry.b : this.p.get(idx).getSecond().get();
|
||||
+ }
|
||||
+ /* //Yatopia - Replace Method
|
||||
int l = this.q ? j : 0;
|
||||
BiomeBase.c biomebase_c = new BiomeBase.c((float) this.l.a((double) i, (double) l, (double) k), (float) this.m.a((double) i, (double) l, (double) k), (float) this.n.a((double) i, (double) l, (double) k), (float) this.o.a((double) i, (double) l, (double) k), 0.0F);
|
||||
|
||||
@@ -127,6 +163,8 @@ public class WorldChunkManagerMultiNoise extends WorldChunkManager {
|
||||
return ((BiomeBase.c) pair.getFirst()).a(biomebase_c);
|
||||
})).map(Pair::getSecond).map(Supplier::get).orElse(BiomeRegistry.b);
|
||||
}
|
||||
+ */ //Yatopia End
|
||||
+
|
||||
|
||||
public boolean b(long i) {
|
||||
return this.r == i && this.s.isPresent() && Objects.equals(((Pair) this.s.get()).getSecond(), WorldChunkManagerMultiNoise.bProxy.a); // Yatopia - decompile fix
|
188
patches/server/0069-fixup-Threaded-WorldGen.patch
Normal file
188
patches/server/0069-fixup-Threaded-WorldGen.patch
Normal file
|
@ -0,0 +1,188 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Fri, 5 Feb 2021 23:13:42 +0800
|
||||
Subject: [PATCH] fixup! Threaded WorldGen
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java
|
||||
index d9b134302f739efd93f50e93c8730b474f9a8ccf..d92cbfcf5374940e3bcc7746dd68fb8171ca4df8 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java
|
||||
@@ -586,6 +586,7 @@ public class PlayerChunk {
|
||||
return this.ticketLevel;
|
||||
}
|
||||
|
||||
+ public int getPriority() { return k(); } // Yatopia - OBFHELPER
|
||||
public int k() {
|
||||
return this.n;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
index 7b1157de77d4e24a7540c070d922b49f2a06a319..8bb1e4486be2860fb5642501bf1e4aaba3bbbd40 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
|
||||
@@ -1280,9 +1280,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
if (!com.tuinity.tuinity.config.TuinityConfig.useNewLightEngine && chunkstatus == ChunkStatus.LIGHT) { // Tuinity - we use edge checks, so loading 1 radius neighbours isn't necessary
|
||||
completablefuture1 = this.b(playerchunk, chunkstatus);
|
||||
} else {
|
||||
- completablefuture1 = chunkstatus.a(this.world, this.definedStructureManager, this.lightEngine, (ichunkaccess1) -> {
|
||||
+ completablefuture1 = chunkstatus.runLoadTask(this.world, this.definedStructureManager, this.lightEngine, (ichunkaccess1) -> { // Yatopia
|
||||
return this.c(playerchunk);
|
||||
- }, ichunkaccess);
|
||||
+ }, ichunkaccess, playerchunk.getPriority()); // Yatopia
|
||||
}
|
||||
|
||||
this.worldLoadListener.a(chunkcoordintpair, chunkstatus);
|
||||
@@ -1393,9 +1393,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
return completablefuture.thenComposeAsync((either) -> {
|
||||
return either.map((list) -> { // Paper - Shut up.
|
||||
try {
|
||||
- CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> {
|
||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture1 = chunkstatus.runGenerationTask(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> {
|
||||
return this.c(playerchunk);
|
||||
- }, list);
|
||||
+ }, list, playerchunk.getPriority());
|
||||
|
||||
this.worldLoadListener.a(chunkcoordintpair, chunkstatus);
|
||||
return completablefuture1;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
index a01d6dfe147383242e514d2807558bf94ff8865a..b33dd2602c592f0ed5d45d0a5a1ec87f6904aaed 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
|
||||
@@ -69,7 +69,7 @@ public class ChunkStatus {
|
||||
|
||||
private static final EnumSet<HeightMap.Type> n = EnumSet.of(HeightMap.Type.OCEAN_FLOOR_WG, HeightMap.Type.WORLD_SURFACE_WG);
|
||||
private static final EnumSet<HeightMap.Type> o = EnumSet.of(HeightMap.Type.OCEAN_FLOOR, HeightMap.Type.WORLD_SURFACE, HeightMap.Type.MOTION_BLOCKING, HeightMap.Type.MOTION_BLOCKING_NO_LEAVES);
|
||||
- private static final ChunkStatus.c p = (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess) -> {
|
||||
+ private static final ChunkStatus.c p = (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, priority) -> { // Yatopia
|
||||
if (ichunkaccess instanceof ProtoChunk && !ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
||||
((ProtoChunk) ichunkaccess).a(chunkstatus);
|
||||
}
|
||||
@@ -78,14 +78,14 @@ public class ChunkStatus {
|
||||
};
|
||||
public static final ChunkStatus EMPTY = a("empty", (ChunkStatus) null, -1, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
});
|
||||
- public static final ChunkStatus STRUCTURE_STARTS = a("structure_starts", ChunkStatus.EMPTY, 0, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ public static final ChunkStatus STRUCTURE_STARTS = a("structure_starts", ChunkStatus.EMPTY, 0, ChunkStatus.n, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, priority) -> { // Yatopia
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> result = CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
if (!ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
||||
if (worldserver.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures()) { // CraftBukkit
|
||||
result = CompletableFuture.supplyAsync(() -> {
|
||||
chunkgenerator.createStructures(worldserver.r(), worldserver.getStructureManager(), ichunkaccess, definedstructuremanager, worldserver.getSeed());
|
||||
return Either.left(ichunkaccess);
|
||||
- }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
+ }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : priority, command)));
|
||||
}
|
||||
if (ichunkaccess instanceof ProtoChunk) {
|
||||
result.thenRun(() -> ((ProtoChunk) ichunkaccess).a(chunkstatus));
|
||||
@@ -116,7 +116,7 @@ public class ChunkStatus {
|
||||
public static final ChunkStatus LIQUID_CARVERS = a("liquid_carvers", ChunkStatus.CARVERS, 0, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
chunkgenerator.doCarving(worldserver.getSeed(), worldserver.d(), ichunkaccess, WorldGenStage.Features.LIQUID);
|
||||
});
|
||||
- public static final ChunkStatus FEATURES = a("features", ChunkStatus.LIQUID_CARVERS, 8, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ public static final ChunkStatus FEATURES = a("features", ChunkStatus.LIQUID_CARVERS, 8, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, priority) -> { // Yatopia
|
||||
// Yatopia start - threaded WorldGen
|
||||
return chunkgenerator.featureGenLock.acquireLock().toCompletableFuture().thenComposeAsync(token -> {
|
||||
try {
|
||||
@@ -135,12 +135,12 @@ public class ChunkStatus {
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(Either.left(ichunkaccess));
|
||||
- }, command -> featureGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
+ }, command -> featureGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : priority, command)));
|
||||
// Yatopia end
|
||||
});
|
||||
- public static final ChunkStatus LIGHT = a("light", ChunkStatus.FEATURES, 1, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ public static final ChunkStatus LIGHT = a("light", ChunkStatus.FEATURES, 1, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, priority) -> { // Yatopia
|
||||
return a(chunkstatus, lightenginethreaded, ichunkaccess);
|
||||
- }, (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess) -> {
|
||||
+ }, (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, priority) -> { // Yatopia
|
||||
return a(chunkstatus, lightenginethreaded, ichunkaccess);
|
||||
});
|
||||
public static final ChunkStatus SPAWN = a("spawn", ChunkStatus.LIGHT, 0, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
@@ -148,9 +148,9 @@ public class ChunkStatus {
|
||||
});
|
||||
public static final ChunkStatus HEIGHTMAPS = a("heightmaps", ChunkStatus.SPAWN, 0, ChunkStatus.o, ChunkStatus.Type.PROTOCHUNK, (worldserver, chunkgenerator, list, ichunkaccess) -> {
|
||||
});
|
||||
- public static final ChunkStatus FULL = a("full", ChunkStatus.HEIGHTMAPS, 0, ChunkStatus.o, ChunkStatus.Type.LEVELCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess) -> {
|
||||
+ public static final ChunkStatus FULL = a("full", ChunkStatus.HEIGHTMAPS, 0, ChunkStatus.o, ChunkStatus.Type.LEVELCHUNK, (chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, priority) -> { // Yatopia
|
||||
return (CompletableFuture) function.apply(ichunkaccess);
|
||||
- }, (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess) -> {
|
||||
+ }, (chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, priority) -> { // Yatopia
|
||||
return (CompletableFuture) function.apply(ichunkaccess);
|
||||
});
|
||||
private static final List<ChunkStatus> q = ImmutableList.of(ChunkStatus.FULL, ChunkStatus.FEATURES, ChunkStatus.LIQUID_CARVERS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS);
|
||||
@@ -254,11 +254,23 @@ public class ChunkStatus {
|
||||
}
|
||||
|
||||
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> a(WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list) {
|
||||
- return this.v.doWork(this, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, (IChunkAccess) list.get(list.size() / 2));
|
||||
+ // Yatopia start - add priority param
|
||||
+ return runGenerationTask(worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, Integer.MAX_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> runGenerationTask(WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, int priority) {
|
||||
+ return this.v.doWork(this, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, (IChunkAccess) list.get(list.size() / 2), priority);
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> a(WorldServer worldserver, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, IChunkAccess ichunkaccess) {
|
||||
- return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess);
|
||||
+ // Yatopia start - add priority param
|
||||
+ return runLoadTask(worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, Integer.MAX_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> runLoadTask(WorldServer worldserver, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, IChunkAccess ichunkaccess, int priority) {
|
||||
+ return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, priority);
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
public final int getNeighborRadius() { return this.f(); } // Paper - OBFHELPER
|
||||
@@ -309,6 +321,13 @@ public class ChunkStatus {
|
||||
|
||||
@Override
|
||||
default CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess) {
|
||||
+ // Yatopia start - add priority param
|
||||
+ return doWork(chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, Integer.MAX_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess, int priority) {
|
||||
+ // Yatopia end
|
||||
// Yatopia start - threaded worldGen
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
if (!ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
||||
@@ -318,7 +337,7 @@ public class ChunkStatus {
|
||||
}
|
||||
}
|
||||
return Either.left(ichunkaccess);
|
||||
- }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : 0, command)));
|
||||
+ }, command -> worldGenExecutor.execute(new org.yatopiamc.yatopia.server.executors.PrioritizedRunnable(() -> com.destroystokyo.paper.io.chunk.ChunkTaskManager.hasChunkWait(worldserver, ichunkaccess.getPos().x, ichunkaccess.getPos().z) ? Integer.MIN_VALUE : priority, command)));
|
||||
|
||||
// Yatopia end
|
||||
}
|
||||
@@ -328,11 +347,23 @@ public class ChunkStatus {
|
||||
|
||||
interface c {
|
||||
|
||||
- CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, IChunkAccess ichunkaccess);
|
||||
+ // Yatopia start - add priority param
|
||||
+ default CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, IChunkAccess ichunkaccess) {
|
||||
+ return this.doWork(chunkstatus, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess, Integer.MAX_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, IChunkAccess ichunkaccess, int priority);
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
interface b {
|
||||
|
||||
- CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess);
|
||||
+ // Yatopia start - add priority param
|
||||
+ default CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess) {
|
||||
+ return doWork(chunkstatus, worldserver, chunkgenerator, definedstructuremanager, lightenginethreaded, function, list, ichunkaccess, Integer.MAX_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> doWork(ChunkStatus chunkstatus, WorldServer worldserver, ChunkGenerator chunkgenerator, DefinedStructureManager definedstructuremanager, LightEngineThreaded lightenginethreaded, Function<IChunkAccess, CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> function, List<IChunkAccess> list, IChunkAccess ichunkaccess, int priority);
|
||||
+ // Yatopia end
|
||||
}
|
||||
}
|
42
patches/server/0070-Force-world-save.patch
Normal file
42
patches/server/0070-Force-world-save.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Tue, 9 Feb 2021 21:42:09 +0800
|
||||
Subject: [PATCH] Force world save
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
index 55d497f4305de50e58c7e0788724576f81128138..edb45dd2933b985efb29d61b2a844615f5f1cc9f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java
|
||||
@@ -366,6 +366,7 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
|
||||
}).orElse(false);
|
||||
}
|
||||
|
||||
+ private final java.util.concurrent.atomic.AtomicBoolean hasWorked = new java.util.concurrent.atomic.AtomicBoolean(false); // Yatopia - enforce one chunk unload per tick
|
||||
@Override
|
||||
public void a(BooleanSupplier booleansupplier) {
|
||||
// Paper start - async chunk io
|
||||
@@ -373,7 +374,7 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
|
||||
super.a(booleansupplier);
|
||||
} else {
|
||||
//super.a(booleansupplier); // re-implement below
|
||||
- while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean() && !this.world.isSavingDisabled()) { // Tuinity - unload POI data - don't write to disk if saving is disabled
|
||||
+ hasWorked.set(false); while (!((RegionFileSection)this).d.isEmpty() && (hasWorked.compareAndSet(false, true) || booleansupplier.getAsBoolean()) && !this.world.isSavingDisabled()) { // Tuinity - unload POI data - don't write to disk if saving is disabled // Yatopia - enforce one chunk unload per tick
|
||||
ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r();
|
||||
|
||||
NBTTagCompound data;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java
|
||||
index f70c14385c95763b5f270a6e2ce372cf047ba7bb..4454489153f7932deaaebe8aa32ecb603764f42b 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java
|
||||
@@ -50,8 +50,9 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
|
||||
//this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker
|
||||
}
|
||||
|
||||
+ private final java.util.concurrent.atomic.AtomicBoolean hasWorked = new java.util.concurrent.atomic.AtomicBoolean(false); // Yatopia - enforce one chunk unload per tick
|
||||
protected void a(BooleanSupplier booleansupplier) {
|
||||
- while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) {
|
||||
+ hasWorked.set(false); while (!this.d.isEmpty() && (hasWorked.compareAndSet(false, true) || booleansupplier.getAsBoolean())) { // Yatopia - enforce one chunk unload per tick
|
||||
ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers
|
||||
|
||||
this.d(chunkcoordintpair);
|
37
patches/server/0071-fixup-Threaded-WorldGen.patch
Normal file
37
patches/server/0071-fixup-Threaded-WorldGen.patch
Normal file
|
@ -0,0 +1,37 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Sat, 20 Feb 2021 22:39:16 +0800
|
||||
Subject: [PATCH] fixup! Threaded WorldGen
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
index 194321b7183d3aaa8031608a979dde71006e2fab..f5690544c1fec4b5e2e4535c2692c809074dca66 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
|
||||
@@ -841,16 +841,18 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
|
||||
// Yatopia start - reduce scheduling overhead
|
||||
final ConcurrentLinkedQueue<Runnable> poiQueue = new ConcurrentLinkedQueue<>();
|
||||
- private boolean runPoiQueueNext() { // TODO flush poi queue?
|
||||
- try {
|
||||
- final Runnable runnable = poiQueue.poll();
|
||||
- if (runnable != null)
|
||||
+ private boolean runPoiQueueNext() {
|
||||
+ boolean hasWork = false;
|
||||
+ Runnable runnable;
|
||||
+ while ((runnable = poiQueue.poll()) != null) {
|
||||
+ hasWork = true;
|
||||
+ try {
|
||||
runnable.run();
|
||||
- return runnable != null;
|
||||
- } catch (Throwable t) {
|
||||
- t.printStackTrace();
|
||||
+ } catch (Throwable t) {
|
||||
+ t.printStackTrace();
|
||||
+ }
|
||||
}
|
||||
- return false;
|
||||
+ return hasWork;
|
||||
}
|
||||
|
||||
public boolean runTasks() {
|
Loading…
Reference in New Issue
Block a user