Multi noise support for scarpet (#1176)

* fix: infinite params bug in AnnotationParser
feat: scarpet function query_noise()

* refactor: remove Method reflection

* fix: use BiomeCoords

* update: game version to 1.18-pre5

* feat: biome lookup from multinoise
fix: noise lookup wrongly scaled

* fix: jagged noise. Thanks, @Starmute

* fix: cave cheese and layer. Thanks, @Starmute

* fix: revert formatting
fix: caveLayer and caveCheese
feat: add terrain support

* more formatting reverts

* fix mapping issue

* use BlockPos

* docs: add documentation for query_noise

* docs: add documentation for biome(noise_map)
This commit is contained in:
Crec0 authored and GitHub committed 2021-11-30 02:47:28 +01:00
1 parent 6c7ac72c3e
commit aa57b586cb
8 files changed
+388 -9

No files matched your search

@@ -5,6 +5,7 @@ import carpet.CarpetSettings;
import carpet.fakes.BiomeArrayInterface;
import carpet.fakes.ChunkGeneratorInterface;
import carpet.fakes.ChunkTicketManagerInterface;
import carpet.fakes.NoiseColumnSamplerInterface;
import carpet.fakes.ServerChunkManagerInterface;
import carpet.fakes.ServerWorldInterface;
import carpet.fakes.SpawnHelperInnerInterface;
@@ -16,6 +17,8 @@ import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff;
import carpet.script.LazyValue;
import carpet.script.annotation.Locator;
import carpet.script.annotation.ScarpetFunction;
import carpet.script.argument.BlockArgument;
import carpet.script.argument.Vector3Argument;
import carpet.script.exception.InternalExpressionException;
@@ -93,6 +96,9 @@ import net.minecraft.world.SpawnHelper;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeCoords;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.biome.source.MultiNoiseBiomeSource;
import net.minecraft.world.biome.source.util.MultiNoiseUtil;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.WorldChunk;
@@ -221,6 +227,20 @@ public class WorldAccess {
return bs;
}
private static void nullCheck(Value v, String name) {
if (v.isNull()) {
throw new IllegalArgumentException(name + " cannot be null");
}
}
private static float numberGetOrThrow(Value v) {
double num = v.readDoubleNumber();
if (Double.isNaN(num)) {
throw new IllegalArgumentException(v.getString() + " needs to be a numeric value");
}
return (float) num;
}
private static void BooYah(ChunkGenerator generator)
{
synchronized (generator)
@@ -343,7 +363,7 @@ public class WorldAccess {
}
String poiTypeString = poi.getString().toLowerCase(Locale.ROOT);
PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(InputValidator.identifierOf(poiTypeString))
.orElseThrow(() -> new ThrowStatement(poiTypeString, Throwables.UNKNOWN_POI));
.orElseThrow(() -> new ThrowStatement(poiTypeString, Throwables.UNKNOWN_POI));
int occupancy = 0;
if (locator.offset + 1 < lv.size())
{
@@ -1129,19 +1149,55 @@ public class WorldAccess {
return BooleanValue.of(blockLocator.block.getBlockState().isIn(blockTag));
});
expression.addContextFunction("biome", -1, (c, t, lv) -> {
CarpetContext cc = (CarpetContext)c;
CarpetContext cc = (CarpetContext) c;
ServerWorld world = cc.s.getWorld();
if (lv.size() == 0)
return ListValue.wrap(world.getRegistryManager().get(Registry.BIOME_KEY).getIds().stream().map(ValueConversions::of));
BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true);
Biome biome;
BiomeSource biomeSource = world.getChunkManager().getChunkGenerator().getBiomeSource();
if ( lv.size() == 1
&& lv.get(0) instanceof MapValue map
&& biomeSource instanceof MultiNoiseBiomeSource mnbs
) {
Value temperature = map.get(new StringValue("temperature"));
nullCheck(temperature, "temperature");
Value humidity = map.get(new StringValue("humidity"));
nullCheck(humidity, "humidity");
Value continentalness = map.get(new StringValue("continentalness"));
nullCheck(continentalness, "continentalness");
Value erosion = map.get(new StringValue("erosion"));
nullCheck(erosion, "erosion");
Value depth = map.get(new StringValue("depth"));
nullCheck(depth, "depth");
Value weirdness = map.get(new StringValue("weirdness"));
nullCheck(weirdness, "weirdness");
MultiNoiseUtil.NoiseValuePoint point = new MultiNoiseUtil.NoiseValuePoint(
MultiNoiseUtil.method_38665(numberGetOrThrow(temperature)),
MultiNoiseUtil.method_38665(numberGetOrThrow(humidity)),
MultiNoiseUtil.method_38665(numberGetOrThrow(continentalness)),
MultiNoiseUtil.method_38665(numberGetOrThrow(erosion)),
MultiNoiseUtil.method_38665(numberGetOrThrow(depth)),
MultiNoiseUtil.method_38665(numberGetOrThrow(weirdness))
);
biome = mnbs.getBiomeAtPoint(point);
Identifier biomeId = cc.s.getServer().getRegistryManager().get(Registry.BIOME_KEY).getId(biome);
return new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId));
}
BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true);
if (locator.replacement != null)
{
biome = world.getRegistryManager().get(Registry.BIOME_KEY).get(InputValidator.identifierOf(locator.replacement));
if (biome == null) throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME) ;
if (biome == null) throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME);
}
else
{
@@ -1156,7 +1212,8 @@ public class WorldAccess {
}
String biomeFeature = lv.get(locator.offset).getString();
BiFunction<ServerWorld, Biome, Value> featureProvider = BiomeInfo.biomeFeatures.get(biomeFeature);
if (featureProvider == null) throw new InternalExpressionException("Unknown biome feature: "+biomeFeature);
if (featureProvider == null)
throw new InternalExpressionException("Unknown biome feature: " + biomeFeature);
return featureProvider.apply(world, biome);
});
@@ -1512,4 +1569,23 @@ public class WorldAccess {
});
}
@ScarpetFunction(maxParams = -1)
public Value query_noise(Context c, @Locator.Block BlockPos pos, String... noiseQueries) {
int mappedX = BiomeCoords.fromBlock(pos.getX());
int mappedY = BiomeCoords.fromBlock(pos.getY());
int mappedZ = BiomeCoords.fromBlock(pos.getZ());
MultiNoiseUtil.MultiNoiseSampler mns = ((CarpetContext) c).s.getWorld().getChunkManager().getChunkGenerator().getMultiNoiseSampler();
Map<Value, Value> ret = new HashMap<>();
if (noiseQueries.length == 0) {
noiseQueries = new String[]{"continentalness", "erosion", "weirdness", "temperature", "humidity", "depth"};
}
for (String noise : noiseQueries) {
double noiseValue = ((NoiseColumnSamplerInterface) mns).getNoiseSample(noise, mappedX, mappedY, mappedZ);
ret.put(new StringValue(noise), new NumericValue(noiseValue));
}
return MapValue.wrap(ret);
}
}