Update the API to allow for N-sized world generation requests

This breaks old world generators
This commit is contained in:
James Seibel
2024-10-07 19:45:33 -05:00
parent 38a2edff06
commit 1ebad39fc1
5 changed files with 211 additions and 20 deletions
@@ -9,17 +9,16 @@ import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.Abstrac
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
public class TestChunkWorldGenerator extends AbstractDhApiChunkWorldGenerator
{
private final ServerLevel level;
private final IDhApiLevelWrapper levelWrapper;
@@ -30,7 +29,7 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
// constructor //
//=============//
public TestWorldGenerator(ServerLevel level)
public TestChunkWorldGenerator(ServerLevel level)
{
this.level = level;
this.levelWrapper = ServerLevelWrapper.getWrapper(level);
@@ -46,7 +45,7 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
public EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.API_CHUNKS; }
@Override
public boolean runApiChunkValidation() { return true; }
public boolean runApiValidation() { return true; }
@@ -0,0 +1,189 @@
package com.seibel.distanthorizons.fabric.testing;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGeneratorReturnType;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.server.level.ServerLevel;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
public class TestGenericWorldGenerator implements IDhApiWorldGenerator
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final IDhApiLevelWrapper levelWrapper;
//=============//
// constructor //
//=============//
public TestGenericWorldGenerator(IDhApiLevelWrapper levelWrapper)
{ this.levelWrapper = levelWrapper; }
//============//
// properties //
//============//
@Override
public byte getSmallestDataDetailLevel() { return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
@Override
public byte getLargestDataDetailLevel() { return (byte) (EDhApiDetailLevel.BLOCK.detailLevel + 12); }
@Override
public EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.API_DATA_SOURCES; }
@Override
public boolean runApiValidation() { return true; }
//==================//
// chunk generation //
//==================//
@Override
public CompletableFuture<Void> generateLod(
int chunkPosMinX, int chunkPosMinZ,
int posX, int posZ, byte detailLevel,
IDhApiFullDataSource pooledFullDataSource,
EDhApiDistantGeneratorMode generatorMode, ExecutorService worldGeneratorThreadPool,
Consumer<IDhApiFullDataSource> resultConsumer)
{
return CompletableFuture.runAsync(() ->
{
// this test is only validated for 1.18.2 and up
// (and it is only needed when testing world gen overrides/API chunks, so it isn't normally needed)
#if MC_VER >= MC_1_18_2
IDhApiBiomeWrapper biome;
IDhApiBlockStateWrapper colorBlock;
IDhApiBlockStateWrapper borderBlock;
IDhApiBlockStateWrapper airBlock;
int maxHeight;
try
{
biome = DhApi.Delayed.wrapperFactory.getBiomeWrapper("minecraft:plains", this.levelWrapper);
airBlock = DhApi.Delayed.wrapperFactory.getAirBlockStateWrapper();
borderBlock = DhApi.Delayed.wrapperFactory.getDefaultBlockStateWrapper("minecraft:stone", this.levelWrapper);
String blockResourceLocation;
switch (detailLevel)
{
case 0:
blockResourceLocation = "minecraft:red_wool";
maxHeight = 60;
break;
case 1:
blockResourceLocation = "minecraft:orange_wool";
maxHeight = 70;
break;
case 2:
blockResourceLocation = "minecraft:yellow_wool";
maxHeight = 80;
break;
case 3:
blockResourceLocation = "minecraft:lime_wool";
maxHeight = 90;
break;
case 4:
blockResourceLocation = "minecraft:cyan_wool";
maxHeight = 100;
break;
case 5:
blockResourceLocation = "minecraft:blue_wool";
maxHeight = 100;
break;
case 6:
blockResourceLocation = "minecraft:magenta_wool";
maxHeight = 110;
break;
case 7:
blockResourceLocation = "minecraft:white_wool";
maxHeight = 120;
break;
case 8:
blockResourceLocation = "minecraft:gray_wool";
maxHeight = 120;
break;
default:
blockResourceLocation = "minecraft:black_wool";
maxHeight = 140;
break;
}
colorBlock = DhApi.Delayed.wrapperFactory.getDefaultBlockStateWrapper(blockResourceLocation, this.levelWrapper);
}
catch (IOException e)
{
LOGGER.error("Failed to get biome/block: "+ e.getMessage(), e);
return;
}
ArrayList<DhApiTerrainDataPoint> dataPoints = new ArrayList<>();
int width = pooledFullDataSource.getWidthInDataColumns();
for (int x = 0; x < width; x++)
{
for (int z = 0; z < width; z++)
{
dataPoints.clear();
IDhApiBlockStateWrapper block = colorBlock;
if (x == 0 || x == (width-1)
|| z == 0 || z == (width-1))
{
block = borderBlock;
}
// TODO make mutable dataPoint object
// sky lighting can be ignored. DH will auto light the LODs after they've been submitted
// block lighting however will need to be generated here
dataPoints.add(DhApiTerrainDataPoint.create((byte)0, 0, 0, 0, maxHeight, block, biome));
dataPoints.add(DhApiTerrainDataPoint.create((byte)0, 0, 0, maxHeight, 256, airBlock, biome));
pooledFullDataSource.setApiDataPointColumn(x, z, dataPoints);
}
}
resultConsumer.accept(pooledFullDataSource);
#else
return null;
#endif
}, worldGeneratorThreadPool);
}
@Override
public void preGeneratorTaskStart() { /* do nothing */ }
//=========//
// cleanup //
//=========//
@Override
public void close() { /* do nothing */ }
}
@@ -8,6 +8,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.server.level.ServerLevel;
import org.apache.logging.log4j.Logger;
// TODO add to API example once Builderb0y has given the all-clear
public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -17,12 +18,20 @@ public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
{
LOGGER.info("DH Level: ["+event.value.levelWrapper.getDimensionType()+"] loaded.");
// Note: whenever you use a wrapper method on a new Minecraft version it is recommended that you
// call wrapper.getClass() to determine which object the API will return before you try casting it.
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
// override the core DH world generator for this level
IDhApiWorldGenerator exampleWorldGen = new TestWorldGenerator(level);
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
try
{
// Note: whenever you use a wrapper method on a new Minecraft version it is recommended that you
// call wrapper.getClass() to determine which object the API will return before you try casting it.
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
// override the core DH world generator for this level
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level);
IDhApiWorldGenerator exampleWorldGen = new TestGenericWorldGenerator(event.value.levelWrapper);
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
}
catch (ClassCastException e)
{
LOGGER.warn("Unable to add world generator to level wrapper ["+event.value.levelWrapper.getClass()+"] - ["+event.value.levelWrapper.getDimensionType()+"].");
}
}
}