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