mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 04:37:47 +00:00
ADA
This commit is contained in:
+20
@@ -23,6 +23,7 @@ import art.arcane.iris.nativegen.NativeStructureTerrainIntegrator;
|
||||
import art.arcane.iris.nativegen.NativeStructureVegetationClearer;
|
||||
import art.arcane.iris.nativegen.NativeStructureVerticalPlacer;
|
||||
import art.arcane.iris.nativegen.NativeStructureVanillaLocator;
|
||||
import art.arcane.iris.nativegen.NativeStructureVolumeIndex;
|
||||
import art.arcane.iris.nativegen.WorldgenTerrainHeightmaps;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.common.data.IrisCustomData;
|
||||
@@ -87,6 +88,7 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.spigotmc.SpigotWorldConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@@ -130,6 +132,24 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
|
||||
this.runtimeMinY = level.getMinY();
|
||||
this.runtimeHeight = level.getHeight();
|
||||
this.runtimeSeaLevel = runtimeMinY + engine.getDimension().getFluidHeight();
|
||||
installNativeStructureVolumeIndex(level);
|
||||
}
|
||||
|
||||
private void installNativeStructureVolumeIndex(ServerLevel level) {
|
||||
WeakReference<ServerLevel> levelReference = new WeakReference<>(level);
|
||||
WeakReference<ChunkGenerator> generatorReference = new WeakReference<>(this);
|
||||
WeakReference<BiomeSource> biomeSourceReference = new WeakReference<>(customBiomeSource);
|
||||
NativeStructureVolumeIndex.install(engine, new NativeStructureVolumeIndex.Context(
|
||||
level.registryAccess(),
|
||||
level.getServer().getStructureManager(),
|
||||
level.dimension(),
|
||||
LevelHeightAccessor.create(runtimeMinY, runtimeHeight),
|
||||
generatorReference::get,
|
||||
biomeSourceReference::get,
|
||||
() -> {
|
||||
ServerLevel active = levelReference.get();
|
||||
return active == null ? null : active.getChunkSource().getGeneratorState();
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
@@ -13,6 +13,8 @@ import art.arcane.iris.core.nms.datapack.DataVersion;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.data.chunk.TerrainChunk;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.NativeStructureVolume;
|
||||
import art.arcane.iris.nativegen.NativeStructureVolumeIndex;
|
||||
import art.arcane.iris.engine.object.IrisDimensionRuntimeContract;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.iris.nativegen.NativeStructureFactory;
|
||||
@@ -794,6 +796,11 @@ public class NMSBinding implements INMSBinding {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<NativeStructureVolume> nativeStructureVolumes(Engine engine, int minX, int minZ, int maxX, int maxZ) {
|
||||
return NativeStructureVolumeIndex.volumes(engine, minX, minZ, maxX, maxZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeId(Biome biome) {
|
||||
for (World i : Bukkit.getWorlds()) {
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
package art.arcane.iris.nativegen;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.util.valueproviders.ConstantInt;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlackstoneReplaceProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockAgeProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.CappedProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.GravityProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.JigsawReplacementProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.LavaSubmergedBlockProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.NopProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.ProtectedBlockProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.RuleProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NativeStructureTemplateOccupancyTest {
|
||||
private static final BoundingBox PROCESSING_AREA = new BoundingBox(0, 56, 0, 15, 80, 0);
|
||||
private static final int TEMPLATE_WIDTH = 32;
|
||||
private static final int TERRAIN_HEIGHT = 64;
|
||||
|
||||
@BeforeClass
|
||||
public static void bootstrapMinecraft() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void straddlingGravityPieceReadsHeightsOnlyInsideTheProcessingArea() throws Exception {
|
||||
ColumnRecorder recorder = new ColumnRecorder();
|
||||
|
||||
resolve(straddlingPiece(
|
||||
List.of(new GravityProcessor(Heightmap.Types.WORLD_SURFACE_WG, 0))), recorder);
|
||||
|
||||
assertEquals(columns(0, 15), recorder.heightColumns);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void straddlingPieceRunsProcessorsOnlyInsideTheProcessingArea() throws Exception {
|
||||
CountingProcessor counter = new CountingProcessor();
|
||||
|
||||
resolve(straddlingPiece(List.of(counter)), new ColumnRecorder());
|
||||
|
||||
assertEquals(columns(0, 15), counter.columns);
|
||||
assertTrue(counter.columns.size() < TEMPLATE_WIDTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cappedStraddlingPieceRunsProcessorsAcrossTheWholePiece() throws Exception {
|
||||
CountingProcessor counter = new CountingProcessor();
|
||||
|
||||
resolve(straddlingPiece(List.of(counter,
|
||||
new CappedProcessor(NopProcessor.INSTANCE, ConstantInt.of(0)))),
|
||||
new ColumnRecorder());
|
||||
|
||||
assertEquals(columns(0, TEMPLATE_WIDTH - 1), counter.columns);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cappedProcessorIsTheOnlyProcessorThatDisablesTheProcessingAreaClip() {
|
||||
for (StructureProcessor processor : List.of(
|
||||
BlockIgnoreProcessor.STRUCTURE_BLOCK,
|
||||
JigsawReplacementProcessor.INSTANCE,
|
||||
LavaSubmergedBlockProcessor.INSTANCE,
|
||||
NopProcessor.INSTANCE,
|
||||
BlackstoneReplaceProcessor.INSTANCE,
|
||||
new GravityProcessor(Heightmap.Types.WORLD_SURFACE_WG, 0),
|
||||
new RuleProcessor(List.of()),
|
||||
new BlockAgeProcessor(0.5F),
|
||||
new ProtectedBlockProcessor(HolderSet.empty()))) {
|
||||
assertFalse(processor.getClass().getName(),
|
||||
processor.evaluatesEntirePieceState());
|
||||
}
|
||||
assertTrue(new CappedProcessor(NopProcessor.INSTANCE, ConstantInt.of(4))
|
||||
.evaluatesEntirePieceState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placementSettingsCarryTheProcessingAreaAsTheirClipBox() throws Exception {
|
||||
PoolElementStructurePiece piece = straddlingPiece(List.of());
|
||||
|
||||
StructurePlaceSettings settings = NativeStructureReflection.resolvePlacementSettings(
|
||||
(SinglePoolElement) piece.getElement(), piece, PROCESSING_AREA);
|
||||
|
||||
assertEquals(PROCESSING_AREA, settings.getBoundingBox());
|
||||
}
|
||||
|
||||
private static void resolve(PoolElementStructurePiece piece, ColumnRecorder recorder) {
|
||||
NativeStructureTemplateOccupancy.resolve(
|
||||
world(recorder), piece, piece.getPosition(), PROCESSING_AREA,
|
||||
NativeStructureTemplateOccupancyTest::forbiddenTemplateManager,
|
||||
PROCESSING_AREA::isInside, amount -> {
|
||||
});
|
||||
}
|
||||
|
||||
private static PoolElementStructurePiece straddlingPiece(
|
||||
List<StructureProcessor> processors) throws Exception {
|
||||
BoundingBox bounds = new BoundingBox(0, 70, 0, TEMPLATE_WIDTH - 1, 76, 0);
|
||||
return new PoolElementStructurePiece(
|
||||
null, new InlineSinglePoolElement(template(), processors),
|
||||
new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()),
|
||||
1, Rotation.NONE, bounds, LiquidSettings.APPLY_WATERLOGGING);
|
||||
}
|
||||
|
||||
private static Set<Integer> columns(int minimumX, int maximumX) {
|
||||
Set<Integer> columns = new TreeSet<>();
|
||||
for (int x = minimumX; x <= maximumX; x++) {
|
||||
columns.add(x);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
private static StructureTemplateManager forbiddenTemplateManager() {
|
||||
throw new AssertionError("Inline templates must not resolve a template manager");
|
||||
}
|
||||
|
||||
private static StructureTemplate template() throws Exception {
|
||||
List<StructureTemplate.StructureBlockInfo> blocks = new ArrayList<>();
|
||||
for (int x = 0; x < TEMPLATE_WIDTH; x++) {
|
||||
blocks.add(new StructureTemplate.StructureBlockInfo(
|
||||
new BlockPos(x, 0, 0), Blocks.COBBLESTONE.defaultBlockState(), null));
|
||||
}
|
||||
Constructor<StructureTemplate.Palette> constructor =
|
||||
StructureTemplate.Palette.class.getDeclaredConstructor(List.class);
|
||||
assertTrue(constructor.trySetAccessible());
|
||||
StructureTemplate template = new StructureTemplate();
|
||||
template.palettes.add(constructor.newInstance(blocks));
|
||||
return template;
|
||||
}
|
||||
|
||||
private static WorldGenLevel world(ColumnRecorder recorder) {
|
||||
InvocationHandler handler = (proxy, method, arguments) -> {
|
||||
String methodName = method.getName();
|
||||
if (methodName.equals("getHeight") && arguments.length == 3) {
|
||||
recorder.heightColumns.add((Integer) arguments[1]);
|
||||
return TERRAIN_HEIGHT;
|
||||
}
|
||||
if (methodName.equals("getBlockState")) {
|
||||
recorder.stateColumns.add(((BlockPos) arguments[0]).getX());
|
||||
return Blocks.STONE.defaultBlockState();
|
||||
}
|
||||
if (methodName.equals("getLevel")) {
|
||||
return null;
|
||||
}
|
||||
if (methodName.equals("holderLookup")) {
|
||||
return BuiltInRegistries.BLOCK;
|
||||
}
|
||||
if (methodName.equals("hashCode")) {
|
||||
return System.identityHashCode(proxy);
|
||||
}
|
||||
if (methodName.equals("equals")) {
|
||||
return proxy == arguments[0];
|
||||
}
|
||||
if (methodName.equals("toString")) {
|
||||
return "occupancy-test-world";
|
||||
}
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
};
|
||||
return (WorldGenLevel) Proxy.newProxyInstance(
|
||||
WorldGenLevel.class.getClassLoader(),
|
||||
new Class<?>[]{WorldGenLevel.class}, handler);
|
||||
}
|
||||
|
||||
private static final class ColumnRecorder {
|
||||
private final Set<Integer> heightColumns = new TreeSet<>();
|
||||
private final Set<Integer> stateColumns = new TreeSet<>();
|
||||
}
|
||||
|
||||
private static final class CountingProcessor implements StructureProcessor {
|
||||
private final Set<Integer> columns = new TreeSet<>();
|
||||
|
||||
@Override
|
||||
public StructureTemplate.StructureBlockInfo processBlock(
|
||||
LevelReader level, BlockPos targetPosition, BlockPos referencePos,
|
||||
BlockPos templateRelativePos,
|
||||
StructureTemplate.StructureBlockInfo processedBlockInfo,
|
||||
StructurePlaceSettings settings) {
|
||||
columns.add(processedBlockInfo.pos().getX());
|
||||
return processedBlockInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<? extends StructureProcessor> codec() {
|
||||
return BlockIgnoreProcessor.STRUCTURE_BLOCK.codec();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class InlineSinglePoolElement extends SinglePoolElement {
|
||||
private InlineSinglePoolElement(
|
||||
StructureTemplate template, List<StructureProcessor> processors) {
|
||||
super(Either.right(template),
|
||||
Holder.direct(new StructureProcessorList(processors)),
|
||||
StructureTemplatePool.Projection.RIGID,
|
||||
Optional.<LiquidSettings>empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
package art.arcane.iris.nativegen;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.NativeStructureVolume;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.levelgen.structure.pieces.PiecesContainer;
|
||||
import net.minecraft.world.level.levelgen.structure.structures.SwampHutPiece;
|
||||
import net.minecraft.world.level.levelgen.structure.structures.SwampHutStructure;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NativeStructureVolumeIndexTest {
|
||||
private static final String STRUCTURE_KEY = "minecraft:swamp_hut";
|
||||
|
||||
@BeforeClass
|
||||
public static void bootstrapMinecraftRegistries() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assembledPiecesBecomeWorldSpacePieceVolumes() {
|
||||
StructureStart start = swampHut(0, 0, 4, 6);
|
||||
BoundingBox bounds = start.getPieces().getFirst().getBoundingBox();
|
||||
|
||||
KList<NativeStructureVolume> volumes = NativeStructureVolumeIndex.appendPieces(null, STRUCTURE_KEY, start);
|
||||
|
||||
assertEquals(1, volumes.size());
|
||||
NativeStructureVolume volume = volumes.getFirst();
|
||||
assertEquals(STRUCTURE_KEY, volume.structure());
|
||||
assertEquals(bounds.minX(), volume.minX());
|
||||
assertEquals(bounds.minY(), volume.minY());
|
||||
assertEquals(bounds.minZ(), volume.minZ());
|
||||
assertEquals(bounds.maxX(), volume.maxX());
|
||||
assertEquals(bounds.maxY(), volume.maxY());
|
||||
assertEquals(bounds.maxZ(), volume.maxZ());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidStartsContributeNoVolumes() {
|
||||
assertNull(NativeStructureVolumeIndex.appendPieces(null, STRUCTURE_KEY, StructureStart.INVALID_START));
|
||||
assertNull(NativeStructureVolumeIndex.appendPieces(null, STRUCTURE_KEY, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void coldAndCachedQueriesResolveIdenticalVolumes() {
|
||||
CountingResolver resolver = new CountingResolver(0, 0);
|
||||
NativeStructureVolumeIndex index = NativeStructureVolumeIndex.forTesting(resolver);
|
||||
|
||||
KList<NativeStructureVolume> cold = index.resolve(null, 0, 0, 15, 15);
|
||||
int coldResolutions = resolver.resolutions();
|
||||
KList<NativeStructureVolume> cached = index.resolve(null, 0, 0, 15, 15);
|
||||
|
||||
assertTrue(coldResolutions > 0);
|
||||
assertFalse(cold.isEmpty());
|
||||
assertEquals(cold, cached);
|
||||
assertEquals(coldResolutions, resolver.resolutions());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void independentIndexesResolveIdenticalVolumesFromTheSameSeed() {
|
||||
NativeStructureVolumeIndex first = NativeStructureVolumeIndex.forTesting(new CountingResolver(0, 0));
|
||||
NativeStructureVolumeIndex second = NativeStructureVolumeIndex.forTesting(new CountingResolver(0, 0));
|
||||
|
||||
assertEquals(first.resolve(null, 0, 0, 15, 15), second.resolve(null, 0, 0, 15, 15));
|
||||
assertEquals(first.resolve(null, -32, -32, 47, 47), second.resolve(null, -32, -32, 47, 47));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void volumesOutsideTheQueryRectAreExcluded() {
|
||||
NativeStructureVolumeIndex index = NativeStructureVolumeIndex.forTesting(new CountingResolver(0, 0));
|
||||
BoundingBox bounds = swampHut(0, 0, 4, 6).getPieces().getFirst().getBoundingBox();
|
||||
|
||||
KList<NativeStructureVolume> hit = index.resolve(null, bounds.minX(), bounds.minZ(), bounds.maxX(), bounds.maxZ());
|
||||
KList<NativeStructureVolume> miss = index.resolve(null,
|
||||
bounds.maxX() + 1, bounds.minZ(), bounds.maxX() + 8, bounds.maxZ());
|
||||
|
||||
assertEquals(1, hit.size());
|
||||
assertTrue(miss.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startsWithinTheOriginReachContributeAndBeyondItDoNot() {
|
||||
int reach = NativeStructureVolumeIndex.originReachChunks();
|
||||
NativeStructureVolumeIndex reachable = NativeStructureVolumeIndex.forTesting(new CountingResolver(reach, 0));
|
||||
NativeStructureVolumeIndex unreachable = NativeStructureVolumeIndex.forTesting(new CountingResolver(reach + 1, 0));
|
||||
|
||||
assertFalse(reachable.resolve(null, 0, 0, 15, 15).isEmpty());
|
||||
assertTrue(unreachable.resolve(null, 0, 0, 15, 15).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void volumeResolutionNeverReadsChunkOrOwnershipState() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.nativeStructureVolumeIndexSource")));
|
||||
|
||||
assertFalse(source.contains("StructureManager"));
|
||||
assertFalse(source.contains("getStartForStructure"));
|
||||
assertFalse(source.contains("getAllStarts"));
|
||||
assertFalse(source.contains("ChunkAccess"));
|
||||
assertFalse(source.contains("NativeStructureOwnershipStore"));
|
||||
assertFalse(source.contains("NativeStructureOwnershipRecovery"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vanillaVolumesAreGatedOnPackPolicy() throws Exception {
|
||||
String source = Files.readString(Path.of(System.getProperty("iris.nativeStructureVolumeIndexSource")));
|
||||
|
||||
assertTrue(source.contains("NativeStructureGenerationPolicy.resolve("));
|
||||
assertTrue(source.contains("if (!decision.generate())"));
|
||||
assertTrue(source.contains("isStructureChunk("));
|
||||
}
|
||||
|
||||
private static StructureStart swampHut(int chunkX, int chunkZ, int x, int z) {
|
||||
Structure source = new SwampHutStructure(new Structure.StructureSettings(HolderSet.empty()));
|
||||
SwampHutPiece piece = new SwampHutPiece(RandomSource.create(17L), x, z);
|
||||
return new StructureStart(source, new ChunkPos(chunkX, chunkZ), 0, new PiecesContainer(List.of(piece)));
|
||||
}
|
||||
|
||||
private static final class CountingResolver implements NativeStructureVolumeIndex.OriginResolver {
|
||||
private final AtomicInteger resolutions = new AtomicInteger();
|
||||
private final int originChunkX;
|
||||
private final int originChunkZ;
|
||||
|
||||
private CountingResolver(int originChunkX, int originChunkZ) {
|
||||
this.originChunkX = originChunkX;
|
||||
this.originChunkZ = originChunkZ;
|
||||
}
|
||||
|
||||
private int resolutions() {
|
||||
return resolutions.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<NativeStructureVolume> volumesAt(Engine engine, int chunkX, int chunkZ) {
|
||||
resolutions.incrementAndGet();
|
||||
if (chunkX != originChunkX || chunkZ != originChunkZ) {
|
||||
return NativeStructureVolume.NONE;
|
||||
}
|
||||
return NativeStructureVolumeIndex.appendPieces(null, STRUCTURE_KEY, swampHut(chunkX, chunkZ, 4, 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -23,6 +23,7 @@ import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.datapack.DatapackIngestService;
|
||||
import art.arcane.iris.core.events.IrisEngineHotloadEvent;
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.project.IrisProject;
|
||||
import art.arcane.iris.core.project.IrisCodeWorkspace;
|
||||
import art.arcane.iris.core.service.IrisApiEventSVC;
|
||||
@@ -31,15 +32,22 @@ import art.arcane.iris.core.tools.WorldMaintenance;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineMode;
|
||||
import art.arcane.iris.engine.framework.EnginePlatformHooks;
|
||||
import art.arcane.iris.engine.framework.NativeStructureVolume;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisDimensionRuntimeContract;
|
||||
import art.arcane.iris.engine.object.IrisWorld;
|
||||
import art.arcane.iris.platform.bukkit.BukkitWorldBinding;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import org.bukkit.World;
|
||||
|
||||
public final class BukkitEnginePlatformHooks implements EnginePlatformHooks {
|
||||
@Override
|
||||
public KList<NativeStructureVolume> nativeStructureVolumes(Engine engine, int minX, int minZ, int maxX, int maxZ) {
|
||||
return INMS.get().nativeStructureVolumes(engine, minX, minZ, maxX, maxZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshWorkspace(Engine engine) {
|
||||
new IrisCodeWorkspace(new IrisProject(engine.getData().getDataFolder())).updateWorkspace();
|
||||
|
||||
Reference in New Issue
Block a user