mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 21:40:05 +00:00
bump1
This commit is contained in:
1 parent
796d81e58b
commit
79e80bef33
14 files changed
+419
-134
No files matched your search
@@ -114,6 +114,10 @@ import java.util.regex.Pattern;
|
|||||||
public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
System.setProperty("iris.cache.fast", "true");
|
||||||
|
}
|
||||||
|
|
||||||
public static Iris instance;
|
public static Iris instance;
|
||||||
public static Bindings.Adventure audiences;
|
public static Bindings.Adventure audiences;
|
||||||
public static MultiverseCoreLink linkMultiverseCore;
|
public static MultiverseCoreLink linkMultiverseCore;
|
||||||
@@ -580,6 +584,7 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||||
IrisServices.register(IrisCompat.class, compat);
|
IrisServices.register(IrisCompat.class, compat);
|
||||||
ServerConfigurator.configure();
|
ServerConfigurator.configure();
|
||||||
|
IrisToolbelt.applyPregenPerformanceProfile();
|
||||||
validateAllPacks();
|
validateAllPacks();
|
||||||
IrisSafeguard.execute();
|
IrisSafeguard.execute();
|
||||||
getSender().setTag(getTag());
|
getSender().setTag(getTag());
|
||||||
@@ -607,7 +612,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
services.values().forEach(this::registerListener);
|
services.values().forEach(this::registerListener);
|
||||||
addShutdownHook();
|
addShutdownHook();
|
||||||
processPendingStartupWorldDeletes();
|
processPendingStartupWorldDeletes();
|
||||||
IrisToolbelt.applyPregenPerformanceProfile();
|
|
||||||
WorldLifecycleService.get();
|
WorldLifecycleService.get();
|
||||||
WorldRuntimeControlService.get();
|
WorldRuntimeControlService.get();
|
||||||
|
|
||||||
|
|||||||
+25
-16
@@ -34,8 +34,9 @@ import io.papermc.lib.PaperLib;
|
|||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -350,13 +351,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
static int computePaperLikeRecommendedCap(int workerThreads) {
|
static int computePaperLikeRecommendedCap(int workerThreads) {
|
||||||
int normalizedWorkers = Math.max(1, workerThreads);
|
int normalizedWorkers = Math.max(1, workerThreads);
|
||||||
int recommendedCap = normalizedWorkers * 2;
|
int recommendedCap = normalizedWorkers * 4;
|
||||||
if (recommendedCap < 8) {
|
if (recommendedCap < 16) {
|
||||||
return 8;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recommendedCap > 96) {
|
if (recommendedCap > 128) {
|
||||||
return 96;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recommendedCap;
|
return recommendedCap;
|
||||||
@@ -721,13 +722,18 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
public static void increaseWorkerThreads() {
|
public static void increaseWorkerThreads() {
|
||||||
THREAD_COUNT.updateAndGet(i -> {
|
THREAD_COUNT.updateAndGet(i -> {
|
||||||
if (i > 0) return 1;
|
if (i > 0) {
|
||||||
var adjusted = IrisSettings.get().getConcurrency().getWorldGenThreads();
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adjusted = IrisSettings.get().getConcurrency().getWorldGenThreads();
|
||||||
try {
|
try {
|
||||||
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
Field field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
||||||
var pool = field.get(null);
|
Object pool = field.get(null);
|
||||||
var threads = ((Thread[]) pool.getClass().getDeclaredMethod("getCoreThreads").invoke(pool)).length;
|
int threads = ((Thread[]) pool.getClass().getDeclaredMethod("getCoreThreads").invoke(pool)).length;
|
||||||
if (threads >= adjusted) return 0;
|
if (threads >= adjusted) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pool.getClass().getDeclaredMethod("adjustThreadCount", int.class).invoke(pool, adjusted);
|
pool.getClass().getDeclaredMethod("adjustThreadCount", int.class).invoke(pool, adjusted);
|
||||||
return threads;
|
return threads;
|
||||||
@@ -745,11 +751,14 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
public static void resetWorkerThreads() {
|
public static void resetWorkerThreads() {
|
||||||
THREAD_COUNT.updateAndGet(i -> {
|
THREAD_COUNT.updateAndGet(i -> {
|
||||||
if (i == 0) return 0;
|
if (i == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
Field field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
||||||
var pool = field.get(null);
|
Object pool = field.get(null);
|
||||||
var method = pool.getClass().getDeclaredMethod("adjustThreadCount", int.class);
|
Method method = pool.getClass().getDeclaredMethod("adjustThreadCount", int.class);
|
||||||
method.invoke(pool, i);
|
method.invoke(pool, i);
|
||||||
return 0;
|
return 0;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import art.arcane.iris.engine.IrisComplex;
|
|||||||
import art.arcane.iris.engine.UpperDimensionContext;
|
import art.arcane.iris.engine.UpperDimensionContext;
|
||||||
import art.arcane.iris.engine.object.IrisBiome;
|
import art.arcane.iris.engine.object.IrisBiome;
|
||||||
import art.arcane.iris.engine.object.IrisDimension;
|
import art.arcane.iris.engine.object.IrisDimension;
|
||||||
|
import art.arcane.iris.engine.object.IrisOreGenerator;
|
||||||
import art.arcane.iris.engine.object.IrisRegion;
|
import art.arcane.iris.engine.object.IrisRegion;
|
||||||
import art.arcane.volmlib.util.collection.KList;
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
import art.arcane.iris.util.project.context.ChunkedDataCache;
|
import art.arcane.iris.util.project.context.ChunkedDataCache;
|
||||||
@@ -236,8 +237,14 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
|||||||
int topY = Math.min(hf, chunkHeight - 1);
|
int topY = Math.min(hf, chunkHeight - 1);
|
||||||
PlatformBlockState fluid = fluidCache.get(xf, zf);
|
PlatformBlockState fluid = fluidCache.get(xf, zf);
|
||||||
PlatformBlockState rock = rockCache.get(xf, zf);
|
PlatformBlockState rock = rockCache.get(xf, zf);
|
||||||
boolean hasSurfaceOres = !hideOres && (biome.hasSurfaceOres() || region.hasSurfaceOres() || dimension.hasSurfaceOres());
|
KList<IrisOreGenerator> biomeSurfaceOres = hideOres ? null : biome.getSurfaceOreGenerators();
|
||||||
boolean hasUndergroundOres = !hideOres && (biome.hasUndergroundOres() || region.hasUndergroundOres() || dimension.hasUndergroundOres());
|
KList<IrisOreGenerator> regionSurfaceOres = hideOres ? null : region.getSurfaceOreGenerators();
|
||||||
|
KList<IrisOreGenerator> dimensionSurfaceOres = hideOres ? null : dimension.getSurfaceOreGenerators();
|
||||||
|
KList<IrisOreGenerator> biomeUndergroundOres = hideOres ? null : biome.getUndergroundOreGenerators();
|
||||||
|
KList<IrisOreGenerator> regionUndergroundOres = hideOres ? null : region.getUndergroundOreGenerators();
|
||||||
|
KList<IrisOreGenerator> dimensionUndergroundOres = hideOres ? null : dimension.getUndergroundOreGenerators();
|
||||||
|
boolean hasSurfaceOres = !hideOres && (!biomeSurfaceOres.isEmpty() || !regionSurfaceOres.isEmpty() || !dimensionSurfaceOres.isEmpty());
|
||||||
|
boolean hasUndergroundOres = !hideOres && (!biomeUndergroundOres.isEmpty() || !regionUndergroundOres.isEmpty() || !dimensionUndergroundOres.isEmpty());
|
||||||
KList<PlatformBlockState> blocks = null;
|
KList<PlatformBlockState> blocks = null;
|
||||||
KList<PlatformBlockState> fblocks = null;
|
KList<PlatformBlockState> fblocks = null;
|
||||||
|
|
||||||
@@ -250,9 +257,9 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
|||||||
|
|
||||||
PlatformBlockState ore = null;
|
PlatformBlockState ore = null;
|
||||||
if (hasSurfaceOres) {
|
if (hasSurfaceOres) {
|
||||||
ore = biome.generateSurfaceOres(realX, i, realZ, localRng, data);
|
ore = generateOres(biomeSurfaceOres, realX, i, realZ, localRng, data);
|
||||||
ore = ore == null ? region.generateSurfaceOres(realX, i, realZ, localRng, data) : ore;
|
ore = ore == null ? generateOres(regionSurfaceOres, realX, i, realZ, localRng, data) : ore;
|
||||||
ore = ore == null ? dimension.generateSurfaceOres(realX, i, realZ, localRng, data) : ore;
|
ore = ore == null ? generateOres(dimensionSurfaceOres, realX, i, realZ, localRng, data) : ore;
|
||||||
}
|
}
|
||||||
if (ore != null) {
|
if (ore != null) {
|
||||||
h.setRaw(xf, i, zf, ore);
|
h.setRaw(xf, i, zf, ore);
|
||||||
@@ -285,9 +292,9 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasUndergroundOres) {
|
if (hasUndergroundOres) {
|
||||||
ore = biome.generateUndergroundOres(realX, i, realZ, localRng, data);
|
ore = generateOres(biomeUndergroundOres, realX, i, realZ, localRng, data);
|
||||||
ore = ore == null ? region.generateUndergroundOres(realX, i, realZ, localRng, data) : ore;
|
ore = ore == null ? generateOres(regionUndergroundOres, realX, i, realZ, localRng, data) : ore;
|
||||||
ore = ore == null ? dimension.generateUndergroundOres(realX, i, realZ, localRng, data) : ore;
|
ore = ore == null ? generateOres(dimensionUndergroundOres, realX, i, realZ, localRng, data) : ore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ore != null) {
|
if (ore != null) {
|
||||||
@@ -329,4 +336,21 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PlatformBlockState generateOres(KList<IrisOreGenerator> oreGenerators, int x, int y, int z, RNG rng, IrisData data) {
|
||||||
|
if (oreGenerators == null || oreGenerators.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oreCount = oreGenerators.size();
|
||||||
|
for (int oreIndex = 0; oreIndex < oreCount; oreIndex++) {
|
||||||
|
IrisOreGenerator oreGenerator = oreGenerators.get(oreIndex);
|
||||||
|
PlatformBlockState ore = oreGenerator.generate(x, y, z, rng, data);
|
||||||
|
if (ore != null) {
|
||||||
|
return ore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,10 +15,11 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public interface MatterGenerator {
|
public interface MatterGenerator {
|
||||||
Executor DISPATCHER = MultiBurst.burst;
|
MultiBurst DISPATCHER = MultiBurst.burst;
|
||||||
|
ConcurrentHashMap<MatterTaskKey, CompletableFuture<Void>> IN_FLIGHT_COMPONENTS = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
Engine getEngine();
|
Engine getEngine();
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ public interface MatterGenerator {
|
|||||||
try (MantleWriter writer = new MantleWriter(getEngine().getMantle(), getMantle(), x, z, writeRadius, multicore)) {
|
try (MantleWriter writer = new MantleWriter(getEngine().getMantle(), getMantle(), x, z, writeRadius, multicore)) {
|
||||||
for (Pair<List<MantleComponent>, Integer> pair : getComponents()) {
|
for (Pair<List<MantleComponent>, Integer> pair : getComponents()) {
|
||||||
int passRadius = pair.getB();
|
int passRadius = pair.getB();
|
||||||
List<CompletableFuture<Void>> launchedTasks = multicore ? new ArrayList<>() : null;
|
Set<CompletableFuture<Void>> launchedTasks = multicore ? new HashSet<>() : null;
|
||||||
|
|
||||||
for (int i = -passRadius; i <= passRadius; i++) {
|
for (int i = -passRadius; i <= passRadius; i++) {
|
||||||
for (int j = -passRadius; j <= passRadius; j++) {
|
for (int j = -passRadius; j <= passRadius; j++) {
|
||||||
@@ -55,6 +56,7 @@ public interface MatterGenerator {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<MantleComponent> eligibleComponents = new ArrayList<>(pair.getA().size());
|
||||||
for (MantleComponent component : pair.getA()) {
|
for (MantleComponent component : pair.getA()) {
|
||||||
if (!component.isEnabled()) {
|
if (!component.isEnabled()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -88,18 +90,27 @@ public interface MatterGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int finalPassX = passX;
|
eligibleComponents.add(component);
|
||||||
int finalPassZ = passZ;
|
}
|
||||||
MantleChunk<Matter> finalChunk = chunk;
|
|
||||||
MantleComponent finalComponent = component;
|
|
||||||
Runnable task = () -> finalChunk.raiseFlagSuspend(finalComponent.getFlag(),
|
|
||||||
() -> finalComponent.generateLayer(writer, finalPassX, finalPassZ, context));
|
|
||||||
|
|
||||||
if (multicore) {
|
if (eligibleComponents.isEmpty()) {
|
||||||
launchedTasks.add(CompletableFuture.runAsync(task, DISPATCHER));
|
continue;
|
||||||
} else {
|
}
|
||||||
task.run();
|
|
||||||
|
int finalPassX = passX;
|
||||||
|
int finalPassZ = passZ;
|
||||||
|
Runnable task = () -> {
|
||||||
|
for (MantleComponent component : eligibleComponents) {
|
||||||
|
runComponentInline(chunk, component, writer, finalPassX, finalPassZ, context);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (multicore) {
|
||||||
|
for (MantleComponent component : eligibleComponents) {
|
||||||
|
launchedTasks.add(runComponentAsync(chunk, component, writer, finalPassX, finalPassZ, context));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,4 +139,110 @@ public interface MatterGenerator {
|
|||||||
private static long chunkKey(int x, int z) {
|
private static long chunkKey(int x, int z) {
|
||||||
return (((long) x) << 32) ^ (z & 0xffffffffL);
|
return (((long) x) << 32) ^ (z & 0xffffffffL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<Void> runComponentAsync(
|
||||||
|
MantleChunk<Matter> chunk,
|
||||||
|
MantleComponent component,
|
||||||
|
MantleWriter writer,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
ChunkContext context
|
||||||
|
) {
|
||||||
|
MantleFlag flag = component.getFlag();
|
||||||
|
if (chunk.isFlagged(flag)) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
MatterTaskKey key = new MatterTaskKey(getMantle(), chunkX, chunkZ, flag.ordinal());
|
||||||
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
|
CompletableFuture<Void> existing = IN_FLIGHT_COMPONENTS.putIfAbsent(key, future);
|
||||||
|
if (existing != null) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (DISPATCHER.ownsCurrentThread()) {
|
||||||
|
completeComponentTask(future, key, chunk, component, writer, chunkX, chunkZ, context);
|
||||||
|
} else {
|
||||||
|
CompletableFuture.runAsync(() -> completeComponentTask(future, key, chunk, component, writer, chunkX, chunkZ, context), DISPATCHER);
|
||||||
|
}
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
IN_FLIGHT_COMPONENTS.remove(key, future);
|
||||||
|
future.completeExceptionally(throwable);
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void completeComponentTask(
|
||||||
|
CompletableFuture<Void> future,
|
||||||
|
MatterTaskKey key,
|
||||||
|
MantleChunk<Matter> chunk,
|
||||||
|
MantleComponent component,
|
||||||
|
MantleWriter writer,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
ChunkContext context
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
runComponentInline(chunk, component, writer, chunkX, chunkZ, context);
|
||||||
|
future.complete(null);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
future.completeExceptionally(throwable);
|
||||||
|
throw throwable;
|
||||||
|
} finally {
|
||||||
|
IN_FLIGHT_COMPONENTS.remove(key, future);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runComponentInline(
|
||||||
|
MantleChunk<Matter> chunk,
|
||||||
|
MantleComponent component,
|
||||||
|
MantleWriter writer,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
ChunkContext context
|
||||||
|
) {
|
||||||
|
chunk.raiseFlagSuspend(component.getFlag(), () -> component.generateLayer(writer, chunkX, chunkZ, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MatterTaskKey {
|
||||||
|
private final Mantle<Matter> mantle;
|
||||||
|
private final int chunkX;
|
||||||
|
private final int chunkZ;
|
||||||
|
private final int flagOrdinal;
|
||||||
|
|
||||||
|
MatterTaskKey(Mantle<Matter> mantle, int chunkX, int chunkZ, int flagOrdinal) {
|
||||||
|
this.mantle = mantle;
|
||||||
|
this.chunkX = chunkX;
|
||||||
|
this.chunkZ = chunkZ;
|
||||||
|
this.flagOrdinal = flagOrdinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(object instanceof MatterTaskKey other)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mantle == other.mantle
|
||||||
|
&& chunkX == other.chunkX
|
||||||
|
&& chunkZ == other.chunkZ
|
||||||
|
&& flagOrdinal == other.flagOrdinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = System.identityHashCode(mantle);
|
||||||
|
result = 31 * result + chunkX;
|
||||||
|
result = 31 * result + chunkZ;
|
||||||
|
result = 31 * result + flagOrdinal;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,7 @@ import art.arcane.iris.util.project.hunk.Hunk;
|
|||||||
import art.arcane.volmlib.util.collection.KList;
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
import art.arcane.volmlib.util.mantle.runtime.Mantle;
|
import art.arcane.volmlib.util.mantle.runtime.Mantle;
|
||||||
import art.arcane.volmlib.util.mantle.runtime.MantleChunk;
|
import art.arcane.volmlib.util.mantle.runtime.MantleChunk;
|
||||||
|
import art.arcane.volmlib.util.mantle.runtime.TectonicPlate;
|
||||||
import art.arcane.volmlib.util.math.BlockPosition;
|
import art.arcane.volmlib.util.math.BlockPosition;
|
||||||
import art.arcane.volmlib.util.math.M;
|
import art.arcane.volmlib.util.math.M;
|
||||||
import art.arcane.volmlib.util.math.PowerOfTwoCoordinates;
|
import art.arcane.volmlib.util.math.PowerOfTwoCoordinates;
|
||||||
@@ -229,55 +230,53 @@ public class IrisCarveModifier extends EngineAssignedModifier<PlatformBlockState
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean westLoaded = mantle.hasTectonicPlate(((chunkX - 1) >> 5), (chunkZ >> 5));
|
MantleChunk<Matter> west = existingMantleChunk(mantle, chunkX - 1, chunkZ);
|
||||||
boolean eastLoaded = mantle.hasTectonicPlate(((chunkX + 1) >> 5), (chunkZ >> 5));
|
MantleChunk<Matter> east = existingMantleChunk(mantle, chunkX + 1, chunkZ);
|
||||||
boolean northLoaded = mantle.hasTectonicPlate((chunkX >> 5), ((chunkZ - 1) >> 5));
|
MantleChunk<Matter> north = existingMantleChunk(mantle, chunkX, chunkZ - 1);
|
||||||
boolean southLoaded = mantle.hasTectonicPlate((chunkX >> 5), ((chunkZ + 1) >> 5));
|
MantleChunk<Matter> south = existingMantleChunk(mantle, chunkX, chunkZ + 1);
|
||||||
if (!westLoaded && !eastLoaded && !northLoaded && !southLoaded) {
|
if (west == null && east == null && north == null && south == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int yy = 1; yy <= maxY; yy++) {
|
for (int yy = 1; yy <= maxY; yy++) {
|
||||||
for (int offset = 0; offset < 16; offset++) {
|
for (int offset = 0; offset < 16; offset++) {
|
||||||
if (westLoaded) {
|
if (west != null) {
|
||||||
tryAddBoundaryWall(mantle, mc, walls, boundaryMasks, boundaryCaverns, 0, yy, offset, baseX, baseZ, -1, 0);
|
tryAddBoundaryWall(mc, west, walls, boundaryMasks, boundaryCaverns, 0, yy, offset, 15, offset);
|
||||||
}
|
}
|
||||||
if (eastLoaded) {
|
if (east != null) {
|
||||||
tryAddBoundaryWall(mantle, mc, walls, boundaryMasks, boundaryCaverns, 15, yy, offset, baseX, baseZ, 1, 0);
|
tryAddBoundaryWall(mc, east, walls, boundaryMasks, boundaryCaverns, 15, yy, offset, 0, offset);
|
||||||
}
|
}
|
||||||
if (northLoaded) {
|
if (north != null) {
|
||||||
tryAddBoundaryWall(mantle, mc, walls, boundaryMasks, boundaryCaverns, offset, yy, 0, baseX, baseZ, 0, -1);
|
tryAddBoundaryWall(mc, north, walls, boundaryMasks, boundaryCaverns, offset, yy, 0, offset, 15);
|
||||||
}
|
}
|
||||||
if (southLoaded) {
|
if (south != null) {
|
||||||
tryAddBoundaryWall(mantle, mc, walls, boundaryMasks, boundaryCaverns, offset, yy, 15, baseX, baseZ, 0, 1);
|
tryAddBoundaryWall(mc, south, walls, boundaryMasks, boundaryCaverns, offset, yy, 15, offset, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryAddBoundaryWall(
|
private void tryAddBoundaryWall(
|
||||||
Mantle<Matter> mantle,
|
|
||||||
MantleChunk<Matter> mc,
|
MantleChunk<Matter> mc,
|
||||||
|
MantleChunk<Matter> neighborChunk,
|
||||||
PackedWallBuffer walls,
|
PackedWallBuffer walls,
|
||||||
ColumnMask[] boundaryMasks,
|
ColumnMask[] boundaryMasks,
|
||||||
MatterCavern[] boundaryCaverns,
|
MatterCavern[] boundaryCaverns,
|
||||||
int localX,
|
int localX,
|
||||||
int yy,
|
int yy,
|
||||||
int localZ,
|
int localZ,
|
||||||
int baseX,
|
int neighborX,
|
||||||
int baseZ,
|
int neighborZ
|
||||||
int dx,
|
|
||||||
int dz
|
|
||||||
) {
|
) {
|
||||||
int worldX = baseX + localX;
|
if (mc.get(localX, yy, localZ, MatterCavern.class) != null) {
|
||||||
int worldZ = baseZ + localZ;
|
|
||||||
if (mc.get(worldX, yy, worldZ, MatterCavern.class) != null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MatterCavern neighbor = mantle.get(worldX + dx, yy, worldZ + dz, MatterCavern.class);
|
|
||||||
|
MatterCavern neighbor = neighborChunk.get(neighborX, yy, neighborZ, MatterCavern.class);
|
||||||
if (neighbor == null) {
|
if (neighbor == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
walls.put(localX, yy, localZ, neighbor);
|
walls.put(localX, yy, localZ, neighbor);
|
||||||
int columnIndex = PowerOfTwoCoordinates.packLocal16(localX, localZ);
|
int columnIndex = PowerOfTwoCoordinates.packLocal16(localX, localZ);
|
||||||
boundaryMasks[columnIndex].add(yy);
|
boundaryMasks[columnIndex].add(yy);
|
||||||
@@ -286,6 +285,14 @@ public class IrisCarveModifier extends EngineAssignedModifier<PlatformBlockState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MantleChunk<Matter> existingMantleChunk(Mantle<Matter> mantle, int chunkX, int chunkZ) {
|
||||||
|
TectonicPlate<Matter> plate = mantle.getLoadedRegions().get(Mantle.key(chunkX >> 5, chunkZ >> 5));
|
||||||
|
if (plate == null || plate.isClosed()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return plate.get(chunkX & 31, chunkZ & 31);
|
||||||
|
}
|
||||||
|
|
||||||
private void processColumnFromMask(
|
private void processColumnFromMask(
|
||||||
Hunk<PlatformBlockState> output,
|
Hunk<PlatformBlockState> output,
|
||||||
MantleChunk<Matter> mc,
|
MantleChunk<Matter> mc,
|
||||||
|
|||||||
@@ -237,6 +237,14 @@ public class IrisBiome extends IrisRegistrant implements IRare {
|
|||||||
undergroundOreCache.reset();
|
undergroundOreCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getSurfaceOreGenerators() {
|
||||||
|
return getOres(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getUndergroundOreGenerators() {
|
||||||
|
return getOres(false);
|
||||||
|
}
|
||||||
|
|
||||||
private KList<IrisOreGenerator> getSurfaceOres() {
|
private KList<IrisOreGenerator> getSurfaceOres() {
|
||||||
return getOres(true);
|
return getOres(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,6 +342,14 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
undergroundOreCache.reset();
|
undergroundOreCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getSurfaceOreGenerators() {
|
||||||
|
return getOres(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getUndergroundOreGenerators() {
|
||||||
|
return getOres(false);
|
||||||
|
}
|
||||||
|
|
||||||
private KList<IrisOreGenerator> getSurfaceOres() {
|
private KList<IrisOreGenerator> getSurfaceOres() {
|
||||||
return getOres(true);
|
return getOres(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,14 @@ public class IrisRegion extends IrisRegistrant implements IRare {
|
|||||||
undergroundOreCache.reset();
|
undergroundOreCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getSurfaceOreGenerators() {
|
||||||
|
return getOres(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KList<IrisOreGenerator> getUndergroundOreGenerators() {
|
||||||
|
return getOres(false);
|
||||||
|
}
|
||||||
|
|
||||||
private KList<IrisOreGenerator> getSurfaceOres() {
|
private KList<IrisOreGenerator> getSurfaceOres() {
|
||||||
return getOres(true);
|
return getOres(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import art.arcane.iris.core.nms.INMS;
|
|||||||
import art.arcane.iris.spi.PlatformBlockState;
|
import art.arcane.iris.spi.PlatformBlockState;
|
||||||
import art.arcane.iris.util.common.data.IrisCustomData;
|
import art.arcane.iris.util.common.data.IrisCustomData;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -37,18 +38,65 @@ public final class BukkitBlockState implements PlatformBlockState {
|
|||||||
private final BlockData data;
|
private final BlockData data;
|
||||||
private final String key;
|
private final String key;
|
||||||
private final String namespace;
|
private final String namespace;
|
||||||
private volatile Boolean air;
|
private final Boolean air;
|
||||||
private volatile Boolean solid;
|
private final Boolean solid;
|
||||||
private volatile Boolean occluding;
|
private final Boolean occluding;
|
||||||
private volatile Boolean fluid;
|
private final Boolean fluid;
|
||||||
private volatile Boolean water;
|
private final Boolean water;
|
||||||
private volatile Boolean foliage;
|
private final Boolean waterLogged;
|
||||||
private volatile Boolean decorant;
|
private final Boolean lit;
|
||||||
|
private final Boolean updatable;
|
||||||
|
private final Boolean foliage;
|
||||||
|
private final Boolean foliagePlantable;
|
||||||
|
private final Boolean decorant;
|
||||||
|
private final Boolean storage;
|
||||||
|
private final Boolean storageChest;
|
||||||
|
private final Boolean ore;
|
||||||
|
private final Boolean deepSlate;
|
||||||
|
private final Boolean vineBlock;
|
||||||
|
private volatile Boolean tileEntity;
|
||||||
|
|
||||||
private BukkitBlockState(BlockData data, String key) {
|
private BukkitBlockState(BlockData data, String key) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.namespace = parseNamespace(key);
|
this.namespace = parseNamespace(key);
|
||||||
|
Material material = data.getMaterial();
|
||||||
|
if (material == null) {
|
||||||
|
this.air = null;
|
||||||
|
this.solid = null;
|
||||||
|
this.occluding = null;
|
||||||
|
this.fluid = null;
|
||||||
|
this.water = null;
|
||||||
|
this.waterLogged = null;
|
||||||
|
this.lit = null;
|
||||||
|
this.updatable = null;
|
||||||
|
this.foliage = null;
|
||||||
|
this.foliagePlantable = null;
|
||||||
|
this.decorant = null;
|
||||||
|
this.storage = null;
|
||||||
|
this.storageChest = null;
|
||||||
|
this.ore = null;
|
||||||
|
this.deepSlate = null;
|
||||||
|
this.vineBlock = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.air = BukkitBlockResolution.isAir(data);
|
||||||
|
this.solid = BukkitBlockResolution.isSolid(data);
|
||||||
|
this.occluding = material.isOccluding();
|
||||||
|
this.fluid = BukkitBlockResolution.isFluid(data);
|
||||||
|
this.water = BukkitBlockResolution.isWater(data);
|
||||||
|
this.waterLogged = BukkitBlockResolution.isWaterLogged(data);
|
||||||
|
this.lit = BukkitBlockResolution.isLit(data);
|
||||||
|
this.updatable = BukkitBlockResolution.isUpdatable(data);
|
||||||
|
this.foliage = BukkitBlockResolution.isFoliage(data);
|
||||||
|
this.foliagePlantable = BukkitBlockResolution.isFoliagePlantable(data);
|
||||||
|
this.decorant = BukkitBlockResolution.isDecorant(data);
|
||||||
|
this.storage = BukkitBlockResolution.isStorage(data);
|
||||||
|
this.storageChest = BukkitBlockResolution.isStorageChest(data);
|
||||||
|
this.ore = BukkitBlockResolution.isOre(data);
|
||||||
|
this.deepSlate = BukkitBlockResolution.isDeepSlate(data);
|
||||||
|
this.vineBlock = BukkitBlockResolution.isVineBlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BukkitBlockState of(BlockData data) {
|
public static BukkitBlockState of(BlockData data) {
|
||||||
@@ -125,32 +173,17 @@ public final class BukkitBlockState implements PlatformBlockState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAir() {
|
public boolean isAir() {
|
||||||
Boolean cached = air;
|
return air != null ? air : BukkitBlockResolution.isAir(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isAir(data);
|
|
||||||
air = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSolid() {
|
public boolean isSolid() {
|
||||||
Boolean cached = solid;
|
return solid != null ? solid : BukkitBlockResolution.isSolid(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isSolid(data);
|
|
||||||
solid = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOccluding() {
|
public boolean isOccluding() {
|
||||||
Boolean cached = occluding;
|
return occluding != null ? occluding : data.getMaterial().isOccluding();
|
||||||
if (cached == null) {
|
|
||||||
cached = data.getMaterial().isOccluding();
|
|
||||||
occluding = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -160,87 +193,67 @@ public final class BukkitBlockState implements PlatformBlockState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFluid() {
|
public boolean isFluid() {
|
||||||
Boolean cached = fluid;
|
return fluid != null ? fluid : BukkitBlockResolution.isFluid(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isFluid(data);
|
|
||||||
fluid = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWater() {
|
public boolean isWater() {
|
||||||
Boolean cached = water;
|
return water != null ? water : BukkitBlockResolution.isWater(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isWater(data);
|
|
||||||
water = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWaterLogged() {
|
public boolean isWaterLogged() {
|
||||||
return BukkitBlockResolution.isWaterLogged(data);
|
return waterLogged != null ? waterLogged : BukkitBlockResolution.isWaterLogged(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLit() {
|
public boolean isLit() {
|
||||||
return BukkitBlockResolution.isLit(data);
|
return lit != null ? lit : BukkitBlockResolution.isLit(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUpdatable() {
|
public boolean isUpdatable() {
|
||||||
return BukkitBlockResolution.isUpdatable(data);
|
return updatable != null ? updatable : BukkitBlockResolution.isUpdatable(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFoliage() {
|
public boolean isFoliage() {
|
||||||
Boolean cached = foliage;
|
return foliage != null ? foliage : BukkitBlockResolution.isFoliage(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isFoliage(data);
|
|
||||||
foliage = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFoliagePlantable() {
|
public boolean isFoliagePlantable() {
|
||||||
return BukkitBlockResolution.isFoliagePlantable(data);
|
return foliagePlantable != null ? foliagePlantable : BukkitBlockResolution.isFoliagePlantable(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDecorant() {
|
public boolean isDecorant() {
|
||||||
Boolean cached = decorant;
|
return decorant != null ? decorant : BukkitBlockResolution.isDecorant(data);
|
||||||
if (cached == null) {
|
|
||||||
cached = BukkitBlockResolution.isDecorant(data);
|
|
||||||
decorant = cached;
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStorage() {
|
public boolean isStorage() {
|
||||||
return BukkitBlockResolution.isStorage(data);
|
return storage != null ? storage : BukkitBlockResolution.isStorage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStorageChest() {
|
public boolean isStorageChest() {
|
||||||
return BukkitBlockResolution.isStorageChest(data);
|
return storageChest != null ? storageChest : BukkitBlockResolution.isStorageChest(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOre() {
|
public boolean isOre() {
|
||||||
return BukkitBlockResolution.isOre(data);
|
return ore != null ? ore : BukkitBlockResolution.isOre(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDeepSlate() {
|
public boolean isDeepSlate() {
|
||||||
return BukkitBlockResolution.isDeepSlate(data);
|
return deepSlate != null ? deepSlate : BukkitBlockResolution.isDeepSlate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVineBlock() {
|
public boolean isVineBlock() {
|
||||||
return BukkitBlockResolution.isVineBlock(data);
|
return vineBlock != null ? vineBlock : BukkitBlockResolution.isVineBlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -255,7 +268,20 @@ public final class BukkitBlockState implements PlatformBlockState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTileEntity() {
|
public boolean hasTileEntity() {
|
||||||
return INMS.get().hasTile(data.getMaterial());
|
Boolean cached = tileEntity;
|
||||||
|
if (cached == null) {
|
||||||
|
cached = INMS.get().hasTile(data.getMaterial());
|
||||||
|
tileEntity = cached;
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAirOrFluid() {
|
||||||
|
if (air != null && fluid != null) {
|
||||||
|
return air || fluid;
|
||||||
|
}
|
||||||
|
return PlatformBlockState.super.isAirOrFluid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -2,19 +2,22 @@ package art.arcane.iris.util.common.data;
|
|||||||
|
|
||||||
import art.arcane.iris.spi.IrisPlatforms;
|
import art.arcane.iris.spi.IrisPlatforms;
|
||||||
import art.arcane.iris.spi.PlatformBlockState;
|
import art.arcane.iris.spi.PlatformBlockState;
|
||||||
|
import art.arcane.iris.spi.PlatformRegistries;
|
||||||
import art.arcane.volmlib.util.collection.KList;
|
import art.arcane.volmlib.util.collection.KList;
|
||||||
|
|
||||||
public class B {
|
public class B {
|
||||||
|
private static volatile PlatformRegistries registries;
|
||||||
|
|
||||||
public static PlatformBlockState getState(String bdxf) {
|
public static PlatformBlockState getState(String bdxf) {
|
||||||
return IrisPlatforms.get().registries().block(bdxf);
|
return registries().block(bdxf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformBlockState getStateOrNull(String bdxf) {
|
public static PlatformBlockState getStateOrNull(String bdxf) {
|
||||||
return IrisPlatforms.get().registries().blockOrNull(bdxf);
|
return registries().blockOrNull(bdxf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformBlockState getStateOrNull(String bdxf, boolean warn) {
|
public static PlatformBlockState getStateOrNull(String bdxf, boolean warn) {
|
||||||
return IrisPlatforms.get().registries().blockOrNull(bdxf, warn);
|
return registries().blockOrNull(bdxf, warn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KList<PlatformBlockState> getStates(KList<String> find) {
|
public static KList<PlatformBlockState> getStates(KList<String> find) {
|
||||||
@@ -26,11 +29,11 @@ public class B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformBlockState getAirState() {
|
public static PlatformBlockState getAirState() {
|
||||||
return IrisPlatforms.get().registries().air();
|
return registries().air();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformBlockState toDeepSlateOre(PlatformBlockState block, PlatformBlockState ore) {
|
public static PlatformBlockState toDeepSlateOre(PlatformBlockState block, PlatformBlockState ore) {
|
||||||
return IrisPlatforms.get().registries().deepSlateOre(block, ore);
|
return registries().deepSlateOre(block, ore);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAir(PlatformBlockState state) {
|
public static boolean isAir(PlatformBlockState state) {
|
||||||
@@ -108,4 +111,15 @@ public class B {
|
|||||||
public static boolean matches(PlatformBlockState filter, PlatformBlockState state) {
|
public static boolean matches(PlatformBlockState filter, PlatformBlockState state) {
|
||||||
return filter != null && state != null && filter.matches(state);
|
return filter != null && state != null && filter.matches(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PlatformRegistries registries() {
|
||||||
|
PlatformRegistries cached = registries;
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformRegistries resolved = IrisPlatforms.get().registries();
|
||||||
|
registries = resolved;
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,8 @@ import art.arcane.volmlib.util.math.M;
|
|||||||
import kotlinx.coroutines.CoroutineDispatcher;
|
import kotlinx.coroutines.CoroutineDispatcher;
|
||||||
import kotlinx.coroutines.ExecutorsKt;
|
import kotlinx.coroutines.ExecutorsKt;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
import java.util.concurrent.ForkJoinWorkerThread;
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
public class MultiBurst extends MultiBurstSupport {
|
public class MultiBurst extends MultiBurstSupport {
|
||||||
@@ -46,6 +48,20 @@ public class MultiBurst extends MultiBurstSupport {
|
|||||||
return dispatcher;
|
return dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean ownsCurrentThread() {
|
||||||
|
Thread thread = Thread.currentThread();
|
||||||
|
if (!(thread instanceof ForkJoinWorkerThread worker)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecutorService service = service();
|
||||||
|
if (!(service instanceof ForkJoinPool pool)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return worker.getPool() == pool;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BurstExecutor burst(int estimate) {
|
public BurstExecutor burst(int estimate) {
|
||||||
return new BurstExecutor(service(), estimate);
|
return new BurstExecutor(service(), estimate);
|
||||||
|
|||||||
@@ -60,16 +60,47 @@ public class ChunkDataHunkHolder extends AtomicHunk<PlatformBlockState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void apply() {
|
public void apply() {
|
||||||
for (int i = 0; i < getHeight(); i++) {
|
int height = getHeight();
|
||||||
for (int j = 0; j < getWidth(); j++) {
|
for (int x = 0; x < getWidth(); x++) {
|
||||||
for (int k = 0; k < getDepth(); k++) {
|
for (int z = 0; z < getDepth(); z++) {
|
||||||
PlatformBlockState b = super.getRaw(j, i, k);
|
BlockData activeBlock = null;
|
||||||
|
int runStart = -1;
|
||||||
|
|
||||||
if (b != null) {
|
for (int y = 0; y < height; y++) {
|
||||||
chunk.setBlock(j, i + chunk.getMinHeight(), k, (BlockData) b.nativeHandle());
|
PlatformBlockState state = super.getRaw(x, y, z);
|
||||||
|
BlockData block = state == null ? null : (BlockData) state.nativeHandle();
|
||||||
|
if (block == null) {
|
||||||
|
flushRun(x, z, runStart, y, activeBlock);
|
||||||
|
activeBlock = null;
|
||||||
|
runStart = -1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activeBlock != null && activeBlock.equals(block)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
flushRun(x, z, runStart, y, activeBlock);
|
||||||
|
activeBlock = block;
|
||||||
|
runStart = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flushRun(x, z, runStart, height, activeBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void flushRun(int x, int z, int startY, int endY, BlockData block) {
|
||||||
|
if (block == null || startY < 0 || endY <= startY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minY = chunk.getMinHeight();
|
||||||
|
if (endY - startY == 1) {
|
||||||
|
chunk.setBlock(x, startY + minY, z, block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.setRegion(x, startY + minY, z, x + 1, endY + minY, z + 1, block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
-4
@@ -7,10 +7,11 @@ import static org.junit.Assert.assertEquals;
|
|||||||
public class AsyncPregenMethodConcurrencyCapTest {
|
public class AsyncPregenMethodConcurrencyCapTest {
|
||||||
@Test
|
@Test
|
||||||
public void paperLikeRecommendedCapTracksWorkerThreads() {
|
public void paperLikeRecommendedCapTracksWorkerThreads() {
|
||||||
assertEquals(8, AsyncPregenMethod.computePaperLikeRecommendedCap(1));
|
assertEquals(16, AsyncPregenMethod.computePaperLikeRecommendedCap(1));
|
||||||
assertEquals(8, AsyncPregenMethod.computePaperLikeRecommendedCap(4));
|
assertEquals(16, AsyncPregenMethod.computePaperLikeRecommendedCap(4));
|
||||||
assertEquals(24, AsyncPregenMethod.computePaperLikeRecommendedCap(12));
|
assertEquals(48, AsyncPregenMethod.computePaperLikeRecommendedCap(12));
|
||||||
assertEquals(96, AsyncPregenMethod.computePaperLikeRecommendedCap(80));
|
assertEquals(128, AsyncPregenMethod.computePaperLikeRecommendedCap(80));
|
||||||
|
assertEquals(128, AsyncPregenMethod.computePaperLikeRecommendedCap(128));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+12
@@ -11,6 +11,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class BurstExecutorSupportReentrantTest {
|
public class BurstExecutorSupportReentrantTest {
|
||||||
|
@Test
|
||||||
|
public void multiBurstRecognizesOwnedWorkerThread() throws Exception {
|
||||||
|
MultiBurst burst = new MultiBurst("Iris Test", Thread.NORM_PRIORITY, () -> 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Future<Boolean> future = burst.submit(burst::ownsCurrentThread);
|
||||||
|
assertTrue(future.get(5, TimeUnit.SECONDS));
|
||||||
|
} finally {
|
||||||
|
burst.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runsNestedBurstInlineOnSameForkJoinPoolWorker() throws Exception {
|
public void runsNestedBurstInlineOnSameForkJoinPoolWorker() throws Exception {
|
||||||
ForkJoinPool pool = new ForkJoinPool(1);
|
ForkJoinPool pool = new ForkJoinPool(1);
|
||||||
|
|||||||
Reference in new issue
Block a user