mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-08 16:56:25 +00:00
dwa
This commit is contained in:
@@ -6,6 +6,7 @@ import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisExternalDatapackReplaceTargets;
|
||||
import art.arcane.iris.engine.object.IrisExternalDatapackStructurePatch;
|
||||
import art.arcane.iris.engine.object.TileData;
|
||||
import art.arcane.iris.util.common.data.B;
|
||||
import art.arcane.iris.util.common.math.Vector3i;
|
||||
@@ -53,6 +54,7 @@ import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -71,6 +73,8 @@ import java.util.zip.ZipFile;
|
||||
public final class ExternalDataPackPipeline {
|
||||
private static final Pattern STRUCTURE_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/structure/(.+)\\.json$");
|
||||
private static final Pattern STRUCTURE_SET_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/structure_set/(.+)\\.json$");
|
||||
private static final Pattern CONFIGURED_FEATURE_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/configured_feature/(.+)\\.json$");
|
||||
private static final Pattern PLACED_FEATURE_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/placed_feature/(.+)\\.json$");
|
||||
private static final Pattern TEMPLATE_POOL_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/template_pool/(.+)\\.json$");
|
||||
private static final Pattern PROCESSOR_LIST_JSON_ENTRY = Pattern.compile("(?i)^data/([^/]+)/worldgen/processor_list/(.+)\\.json$");
|
||||
private static final Pattern BIOME_HAS_STRUCTURE_TAG_ENTRY = Pattern.compile("(?i)^data/([^/]+)/tags/worldgen/biome/has_structure/(.+)\\.json$");
|
||||
@@ -581,7 +585,12 @@ public final class ExternalDataPackPipeline {
|
||||
|
||||
String relative = source.toPath().relativize(child.toPath()).toString().replace('\\', '/');
|
||||
String normalizedRelative = normalizeRelativePath(relative);
|
||||
if (normalizedRelative == null || !shouldProjectEntry(normalizedRelative, request)) {
|
||||
if (normalizedRelative == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ProjectedEntry projectedEntry = parseProjectedEntry(normalizedRelative);
|
||||
if (!shouldProjectEntry(projectedEntry, request)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -590,7 +599,7 @@ public final class ExternalDataPackPipeline {
|
||||
if (parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
copyFile(child, output);
|
||||
copyProjectedFileEntry(child, output, request, projectedEntry);
|
||||
copied++;
|
||||
}
|
||||
}
|
||||
@@ -607,7 +616,12 @@ public final class ExternalDataPackPipeline {
|
||||
|
||||
for (ZipEntry zipEntry : entries) {
|
||||
String normalizedRelative = normalizeRelativePath(zipEntry.getName());
|
||||
if (normalizedRelative == null || !shouldProjectEntry(normalizedRelative, request)) {
|
||||
if (normalizedRelative == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ProjectedEntry projectedEntry = parseProjectedEntry(normalizedRelative);
|
||||
if (!shouldProjectEntry(projectedEntry, request)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -617,7 +631,7 @@ public final class ExternalDataPackPipeline {
|
||||
parent.mkdirs();
|
||||
}
|
||||
try (InputStream inputStream = zipFile.getInputStream(zipEntry)) {
|
||||
writeInputStreamToFile(inputStream, output);
|
||||
copyProjectedStreamEntry(inputStream, output, request, projectedEntry);
|
||||
}
|
||||
copied++;
|
||||
}
|
||||
@@ -625,6 +639,46 @@ public final class ExternalDataPackPipeline {
|
||||
return copied;
|
||||
}
|
||||
|
||||
private static void copyProjectedFileEntry(File sourceFile, File output, DatapackRequest request, ProjectedEntry projectedEntry) throws IOException {
|
||||
Integer startHeightAbsolute = getPatchedStartHeightAbsolute(projectedEntry, request);
|
||||
if (startHeightAbsolute == null) {
|
||||
copyFile(sourceFile, output);
|
||||
return;
|
||||
}
|
||||
|
||||
String content = Files.readString(sourceFile.toPath(), StandardCharsets.UTF_8);
|
||||
String patched = applyStructureStartHeightPatch(content, startHeightAbsolute);
|
||||
Files.writeString(output.toPath(), patched, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static void copyProjectedStreamEntry(InputStream inputStream, File output, DatapackRequest request, ProjectedEntry projectedEntry) throws IOException {
|
||||
Integer startHeightAbsolute = getPatchedStartHeightAbsolute(projectedEntry, request);
|
||||
if (startHeightAbsolute == null) {
|
||||
writeInputStreamToFile(inputStream, output);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] bytes = inputStream.readAllBytes();
|
||||
String content = new String(bytes, StandardCharsets.UTF_8);
|
||||
String patched = applyStructureStartHeightPatch(content, startHeightAbsolute);
|
||||
Files.writeString(output.toPath(), patched, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static Integer getPatchedStartHeightAbsolute(ProjectedEntry projectedEntry, DatapackRequest request) {
|
||||
if (projectedEntry == null || request == null || projectedEntry.type() != ProjectedEntryType.STRUCTURE) {
|
||||
return null;
|
||||
}
|
||||
return request.structureStartHeights().get(projectedEntry.key());
|
||||
}
|
||||
|
||||
private static String applyStructureStartHeightPatch(String content, int startHeightAbsolute) {
|
||||
JSONObject root = new JSONObject(content);
|
||||
JSONObject startHeight = new JSONObject();
|
||||
startHeight.put("absolute", startHeightAbsolute);
|
||||
root.put("start_height", startHeight);
|
||||
return root.toString(4);
|
||||
}
|
||||
|
||||
private static void writeInputStreamToFile(InputStream inputStream, File output) throws IOException {
|
||||
File parent = output.getParentFile();
|
||||
if (parent != null) {
|
||||
@@ -653,8 +707,7 @@ public final class ExternalDataPackPipeline {
|
||||
Files.writeString(new File(managedFolder, "pack.mcmeta").toPath(), root.toString(4), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static boolean shouldProjectEntry(String relativePath, DatapackRequest request) {
|
||||
ProjectedEntry entry = parseProjectedEntry(relativePath);
|
||||
private static boolean shouldProjectEntry(ProjectedEntry entry, DatapackRequest request) {
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -674,6 +727,8 @@ public final class ExternalDataPackPipeline {
|
||||
return switch (entry.type()) {
|
||||
case STRUCTURE -> request.structures().contains(entry.key());
|
||||
case STRUCTURE_SET -> request.structureSets().contains(entry.key());
|
||||
case CONFIGURED_FEATURE -> request.configuredFeatures().contains(entry.key());
|
||||
case PLACED_FEATURE -> request.placedFeatures().contains(entry.key());
|
||||
case TEMPLATE_POOL -> request.templatePools().contains(entry.key());
|
||||
case PROCESSOR_LIST -> request.processorLists().contains(entry.key());
|
||||
case BIOME_HAS_STRUCTURE_TAG -> request.biomeHasStructureTags().contains(entry.key());
|
||||
@@ -695,6 +750,18 @@ public final class ExternalDataPackPipeline {
|
||||
return key == null ? null : new ProjectedEntry(ProjectedEntryType.STRUCTURE_SET, normalizeNamespace(matcher.group(1)), key);
|
||||
}
|
||||
|
||||
matcher = CONFIGURED_FEATURE_JSON_ENTRY.matcher(normalized);
|
||||
if (matcher.matches()) {
|
||||
String key = normalizeResourceKey(matcher.group(1), matcher.group(2), "worldgen/configured_feature/");
|
||||
return key == null ? null : new ProjectedEntry(ProjectedEntryType.CONFIGURED_FEATURE, normalizeNamespace(matcher.group(1)), key);
|
||||
}
|
||||
|
||||
matcher = PLACED_FEATURE_JSON_ENTRY.matcher(normalized);
|
||||
if (matcher.matches()) {
|
||||
String key = normalizeResourceKey(matcher.group(1), matcher.group(2), "worldgen/placed_feature/");
|
||||
return key == null ? null : new ProjectedEntry(ProjectedEntryType.PLACED_FEATURE, normalizeNamespace(matcher.group(1)), key);
|
||||
}
|
||||
|
||||
matcher = TEMPLATE_POOL_JSON_ENTRY.matcher(normalized);
|
||||
if (matcher.matches()) {
|
||||
String key = normalizeResourceKey(matcher.group(1), matcher.group(2), "worldgen/template_pool/");
|
||||
@@ -1831,9 +1898,12 @@ public final class ExternalDataPackPipeline {
|
||||
boolean replaceVanilla,
|
||||
Set<String> structures,
|
||||
Set<String> structureSets,
|
||||
Set<String> configuredFeatures,
|
||||
Set<String> placedFeatures,
|
||||
Set<String> templatePools,
|
||||
Set<String> processorLists,
|
||||
Set<String> biomeHasStructureTags
|
||||
Set<String> biomeHasStructureTags,
|
||||
Map<String, Integer> structureStartHeights
|
||||
) {
|
||||
public DatapackRequest(
|
||||
String id,
|
||||
@@ -1842,7 +1912,8 @@ public final class ExternalDataPackPipeline {
|
||||
String requiredEnvironment,
|
||||
boolean required,
|
||||
boolean replaceVanilla,
|
||||
IrisExternalDatapackReplaceTargets replaceTargets
|
||||
IrisExternalDatapackReplaceTargets replaceTargets,
|
||||
KList<IrisExternalDatapackStructurePatch> structurePatches
|
||||
) {
|
||||
this(
|
||||
normalizeRequestId(id, url),
|
||||
@@ -1853,12 +1924,15 @@ public final class ExternalDataPackPipeline {
|
||||
replaceVanilla,
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getStructures(), "worldgen/structure/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getStructureSets(), "worldgen/structure_set/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getConfiguredFeatures(), "worldgen/configured_feature/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getPlacedFeatures(), "worldgen/placed_feature/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getTemplatePools(), "worldgen/template_pool/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getProcessorLists(), "worldgen/processor_list/"),
|
||||
normalizeTargets(replaceTargets == null ? null : replaceTargets.getBiomeHasStructureTags(),
|
||||
"tags/worldgen/biome/has_structure/",
|
||||
"worldgen/biome/has_structure/",
|
||||
"has_structure/")
|
||||
"has_structure/"),
|
||||
normalizeStructureStartHeights(structurePatches)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1869,9 +1943,12 @@ public final class ExternalDataPackPipeline {
|
||||
requiredEnvironment = normalizeEnvironment(requiredEnvironment);
|
||||
structures = immutableSet(structures);
|
||||
structureSets = immutableSet(structureSets);
|
||||
configuredFeatures = immutableSet(configuredFeatures);
|
||||
placedFeatures = immutableSet(placedFeatures);
|
||||
templatePools = immutableSet(templatePools);
|
||||
processorLists = immutableSet(processorLists);
|
||||
biomeHasStructureTags = immutableSet(biomeHasStructureTags);
|
||||
structureStartHeights = immutableMap(structureStartHeights);
|
||||
}
|
||||
|
||||
public String getDedupeKey() {
|
||||
@@ -1881,6 +1958,8 @@ public final class ExternalDataPackPipeline {
|
||||
public boolean hasReplacementTargets() {
|
||||
return !structures.isEmpty()
|
||||
|| !structureSets.isEmpty()
|
||||
|| !configuredFeatures.isEmpty()
|
||||
|| !placedFeatures.isEmpty()
|
||||
|| !templatePools.isEmpty()
|
||||
|| !processorLists.isEmpty()
|
||||
|| !biomeHasStructureTags.isEmpty();
|
||||
@@ -1903,9 +1982,12 @@ public final class ExternalDataPackPipeline {
|
||||
replaceVanilla || other.replaceVanilla,
|
||||
union(structures, other.structures),
|
||||
union(structureSets, other.structureSets),
|
||||
union(configuredFeatures, other.configuredFeatures),
|
||||
union(placedFeatures, other.placedFeatures),
|
||||
union(templatePools, other.templatePools),
|
||||
union(processorLists, other.processorLists),
|
||||
union(biomeHasStructureTags, other.biomeHasStructureTags)
|
||||
union(biomeHasStructureTags, other.biomeHasStructureTags),
|
||||
unionStructureStartHeights(structureStartHeights, other.structureStartHeights)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1947,6 +2029,14 @@ public final class ExternalDataPackPipeline {
|
||||
return Set.copyOf(copy);
|
||||
}
|
||||
|
||||
private static Map<String, Integer> immutableMap(Map<String, Integer> values) {
|
||||
LinkedHashMap<String, Integer> copy = new LinkedHashMap<>();
|
||||
if (values != null) {
|
||||
copy.putAll(values);
|
||||
}
|
||||
return Map.copyOf(copy);
|
||||
}
|
||||
|
||||
private static Set<String> union(Set<String> first, Set<String> second) {
|
||||
LinkedHashSet<String> merged = new LinkedHashSet<>();
|
||||
if (first != null) {
|
||||
@@ -1957,6 +2047,44 @@ public final class ExternalDataPackPipeline {
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
private static Map<String, Integer> normalizeStructureStartHeights(KList<IrisExternalDatapackStructurePatch> patches) {
|
||||
LinkedHashMap<String, Integer> normalized = new LinkedHashMap<>();
|
||||
if (patches == null) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
for (IrisExternalDatapackStructurePatch patch : patches) {
|
||||
if (patch == null || !patch.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String structure = patch.getStructure();
|
||||
if (structure == null || structure.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String normalizedStructure = normalizeResourceKey("minecraft", structure, "worldgen/structure/");
|
||||
if (normalizedStructure == null || normalizedStructure.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
normalized.put(normalizedStructure, patch.getStartHeightAbsolute());
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static Map<String, Integer> unionStructureStartHeights(Map<String, Integer> first, Map<String, Integer> second) {
|
||||
LinkedHashMap<String, Integer> merged = new LinkedHashMap<>();
|
||||
if (first != null) {
|
||||
merged.putAll(first);
|
||||
}
|
||||
if (second != null) {
|
||||
merged.putAll(second);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PipelineSummary {
|
||||
@@ -2087,6 +2215,8 @@ public final class ExternalDataPackPipeline {
|
||||
private enum ProjectedEntryType {
|
||||
STRUCTURE,
|
||||
STRUCTURE_SET,
|
||||
CONFIGURED_FEATURE,
|
||||
PLACED_FEATURE,
|
||||
TEMPLATE_POOL,
|
||||
PROCESSOR_LIST,
|
||||
STRUCTURE_NBT,
|
||||
|
||||
@@ -214,7 +214,8 @@ public class ServerConfigurator {
|
||||
environment,
|
||||
externalDatapack.isRequired(),
|
||||
externalDatapack.isReplaceVanilla(),
|
||||
replaceTargets
|
||||
replaceTargets,
|
||||
externalDatapack.getStructurePatches()
|
||||
);
|
||||
|
||||
String dedupeKey = request.getDedupeKey();
|
||||
|
||||
@@ -238,8 +238,37 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
@BlockCoordinates
|
||||
default IrisBiome getCaveBiome(int x, int y, int z) {
|
||||
IrisBiome caveBiome = getCaveBiome(x, z);
|
||||
IrisBiome surfaceBiome = getSurfaceBiome(x, z);
|
||||
IrisBiome entryBiome = null;
|
||||
int worldY = y + getWorld().minHeight();
|
||||
KList<IrisDimensionCarvingEntry> carvingEntries = getDimension().getCarving();
|
||||
if (carvingEntries != null && !carvingEntries.isEmpty()) {
|
||||
for (IrisDimensionCarvingEntry entry : carvingEntries) {
|
||||
if (entry == null || !entry.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = entry.getBiome();
|
||||
if (key == null || key.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisRange worldYRange = entry.getWorldYRange();
|
||||
if (worldYRange != null && !worldYRange.contains(worldY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisBiome loadedBiome = getData().getBiomeLoader().load(key.trim());
|
||||
if (loadedBiome != null) {
|
||||
entryBiome = loadedBiome;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entryBiome != null) {
|
||||
return entryBiome;
|
||||
}
|
||||
|
||||
IrisBiome caveBiome = getCaveBiome(x, z);
|
||||
if (caveBiome == null) {
|
||||
return surfaceBiome;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class IrisCaveCarver3D {
|
||||
public int carve(MantleWriter writer, int chunkX, int chunkZ) {
|
||||
double[] fullWeights = new double[256];
|
||||
Arrays.fill(fullWeights, 1D);
|
||||
return carve(writer, chunkX, chunkZ, fullWeights, 0D, 0D);
|
||||
return carve(writer, chunkX, chunkZ, fullWeights, 0D, 0D, null);
|
||||
}
|
||||
|
||||
public int carve(
|
||||
@@ -95,6 +95,18 @@ public class IrisCaveCarver3D {
|
||||
double[] columnWeights,
|
||||
double minWeight,
|
||||
double thresholdPenalty
|
||||
) {
|
||||
return carve(writer, chunkX, chunkZ, columnWeights, minWeight, thresholdPenalty, null);
|
||||
}
|
||||
|
||||
public int carve(
|
||||
MantleWriter writer,
|
||||
int chunkX,
|
||||
int chunkZ,
|
||||
double[] columnWeights,
|
||||
double minWeight,
|
||||
double thresholdPenalty,
|
||||
IrisRange worldYRange
|
||||
) {
|
||||
if (columnWeights == null || columnWeights.length < 256) {
|
||||
double[] fullWeights = new double[256];
|
||||
@@ -107,6 +119,13 @@ public class IrisCaveCarver3D {
|
||||
int worldHeight = writer.getMantle().getWorldHeight();
|
||||
int minY = Math.max(0, (int) Math.floor(profile.getVerticalRange().getMin()));
|
||||
int maxY = Math.min(worldHeight - 1, (int) Math.ceil(profile.getVerticalRange().getMax()));
|
||||
if (worldYRange != null) {
|
||||
int worldMinHeight = engine.getWorld().minHeight();
|
||||
int rangeMinY = (int) Math.floor(worldYRange.getMin() - worldMinHeight);
|
||||
int rangeMaxY = (int) Math.ceil(worldYRange.getMax() - worldMinHeight);
|
||||
minY = Math.max(minY, rangeMinY);
|
||||
maxY = Math.min(maxY, rangeMaxY);
|
||||
}
|
||||
int sampleStep = Math.max(1, profile.getSampleStep());
|
||||
int surfaceClearance = Math.max(0, profile.getSurfaceClearance());
|
||||
int surfaceBreakDepth = Math.max(0, profile.getSurfaceBreakDepth());
|
||||
|
||||
@@ -24,12 +24,15 @@ import art.arcane.iris.engine.mantle.IrisMantleComponent;
|
||||
import art.arcane.iris.engine.mantle.MantleWriter;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisCaveProfile;
|
||||
import art.arcane.iris.engine.object.IrisDimensionCarvingEntry;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisRange;
|
||||
import art.arcane.iris.util.project.context.ChunkContext;
|
||||
import art.arcane.volmlib.util.documentation.ChunkCoordinates;
|
||||
import art.arcane.volmlib.util.mantle.flag.ReservedFlag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.IdentityHashMap;
|
||||
@@ -55,14 +58,14 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
|
||||
List<WeightedProfile> weightedProfiles = resolveWeightedProfiles(x, z);
|
||||
for (WeightedProfile weightedProfile : weightedProfiles) {
|
||||
carveProfile(weightedProfile.profile, weightedProfile.columnWeights, writer, x, z);
|
||||
carveProfile(weightedProfile, writer, x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
private void carveProfile(IrisCaveProfile profile, double[] columnWeights, MantleWriter writer, int cx, int cz) {
|
||||
IrisCaveCarver3D carver = getCarver(profile);
|
||||
carver.carve(writer, cx, cz, columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY);
|
||||
private void carveProfile(WeightedProfile weightedProfile, MantleWriter writer, int cx, int cz) {
|
||||
IrisCaveCarver3D carver = getCarver(weightedProfile.profile);
|
||||
carver.carve(writer, cx, cz, weightedProfile.columnWeights, MIN_WEIGHT, THRESHOLD_PENALTY, weightedProfile.worldYRange);
|
||||
}
|
||||
|
||||
private List<WeightedProfile> resolveWeightedProfiles(int chunkX, int chunkZ) {
|
||||
@@ -99,10 +102,45 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
}
|
||||
|
||||
double averageWeight = totalWeight / CHUNK_AREA;
|
||||
weightedProfiles.add(new WeightedProfile(profile, weights, averageWeight));
|
||||
weightedProfiles.add(new WeightedProfile(profile, weights, averageWeight, null));
|
||||
}
|
||||
|
||||
weightedProfiles.sort(Comparator.comparingDouble(WeightedProfile::averageWeight));
|
||||
weightedProfiles.addAll(0, resolveDimensionCarvingProfiles());
|
||||
return weightedProfiles;
|
||||
}
|
||||
|
||||
private List<WeightedProfile> resolveDimensionCarvingProfiles() {
|
||||
List<WeightedProfile> weightedProfiles = new ArrayList<>();
|
||||
List<IrisDimensionCarvingEntry> entries = getDimension().getCarving();
|
||||
if (entries == null || entries.isEmpty()) {
|
||||
return weightedProfiles;
|
||||
}
|
||||
|
||||
for (IrisDimensionCarvingEntry entry : entries) {
|
||||
if (entry == null || !entry.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String biomeKey = entry.getBiome();
|
||||
if (biomeKey == null || biomeKey.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisBiome biome = getData().getBiomeLoader().load(biomeKey.trim());
|
||||
if (biome == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisCaveProfile profile = biome.getCaveProfile();
|
||||
if (!isProfileEnabled(profile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisRange worldYRange = entry.getWorldYRange();
|
||||
weightedProfiles.add(new WeightedProfile(profile, fullWeights(), -1D, worldYRange));
|
||||
}
|
||||
|
||||
return weightedProfiles;
|
||||
}
|
||||
|
||||
@@ -160,6 +198,12 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
return (BLEND_RADIUS + 1D) - edgeDistance;
|
||||
}
|
||||
|
||||
private double[] fullWeights() {
|
||||
double[] weights = new double[CHUNK_AREA];
|
||||
Arrays.fill(weights, 1D);
|
||||
return weights;
|
||||
}
|
||||
|
||||
private IrisCaveProfile resolveColumnProfile(int worldX, int worldZ) {
|
||||
IrisCaveProfile resolved = null;
|
||||
IrisCaveProfile dimensionProfile = getDimension().getCaveProfile();
|
||||
@@ -221,11 +265,13 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
private final IrisCaveProfile profile;
|
||||
private final double[] columnWeights;
|
||||
private final double averageWeight;
|
||||
private final IrisRange worldYRange;
|
||||
|
||||
private WeightedProfile(IrisCaveProfile profile, double[] columnWeights, double averageWeight) {
|
||||
private WeightedProfile(IrisCaveProfile profile, double[] columnWeights, double averageWeight, IrisRange worldYRange) {
|
||||
this.profile = profile;
|
||||
this.columnWeights = columnWeights;
|
||||
this.averageWeight = averageWeight;
|
||||
this.worldYRange = worldYRange;
|
||||
}
|
||||
|
||||
private double averageWeight() {
|
||||
|
||||
@@ -144,6 +144,9 @@ public class IrisDimension extends IrisRegistrant {
|
||||
private boolean postProcessingWalls = true;
|
||||
@Desc("Enable or disable all carving for this dimension")
|
||||
private boolean carvingEnabled = true;
|
||||
@ArrayType(type = IrisDimensionCarvingEntry.class, min = 1)
|
||||
@Desc("Dimension-level cave biome carving overrides with absolute world Y ranges")
|
||||
private KList<IrisDimensionCarvingEntry> carving = new KList<>();
|
||||
@Desc("Profile-driven 3D cave configuration")
|
||||
private IrisCaveProfile caveProfile = new IrisCaveProfile();
|
||||
@Desc("Configuration of fluid bodies such as rivers & lakes")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Snippet("dimension-carving-entry")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Dimension-level cave biome override with absolute world Y bounds.")
|
||||
@Data
|
||||
public class IrisDimensionCarvingEntry {
|
||||
@Desc("Stable id for this carving entry")
|
||||
private String id = "";
|
||||
|
||||
@Desc("Enable or disable this carving entry")
|
||||
private boolean enabled = true;
|
||||
|
||||
@RegistryListResource(IrisBiome.class)
|
||||
@Desc("Cave biome to apply when world Y falls within worldYRange")
|
||||
private String biome = "";
|
||||
|
||||
@Desc("Absolute world Y bounds where this carving entry applies")
|
||||
private IrisRange worldYRange = new IrisRange(-64, 320);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -29,4 +31,8 @@ public class IrisExternalDatapack {
|
||||
|
||||
@Desc("Explicit replacement targets for minecraft namespace assets")
|
||||
private IrisExternalDatapackReplaceTargets replaceTargets = new IrisExternalDatapackReplaceTargets();
|
||||
|
||||
@ArrayType(type = IrisExternalDatapackStructurePatch.class, min = 1)
|
||||
@Desc("Structure placement patches applied when this external datapack is projected")
|
||||
private KList<IrisExternalDatapackStructurePatch> structurePatches = new KList<>();
|
||||
}
|
||||
|
||||
@@ -34,11 +34,21 @@ public class IrisExternalDatapackReplaceTargets {
|
||||
@Desc("Biome has_structure tag ids that may be replaced when replaceVanilla is enabled")
|
||||
private KList<String> biomeHasStructureTags = new KList<>();
|
||||
|
||||
@ArrayType(type = String.class, min = 1)
|
||||
@Desc("Configured feature ids that may be replaced when replaceVanilla is enabled")
|
||||
private KList<String> configuredFeatures = new KList<>();
|
||||
|
||||
@ArrayType(type = String.class, min = 1)
|
||||
@Desc("Placed feature ids that may be replaced when replaceVanilla is enabled")
|
||||
private KList<String> placedFeatures = new KList<>();
|
||||
|
||||
public boolean hasAnyTargets() {
|
||||
return !structures.isEmpty()
|
||||
|| !structureSets.isEmpty()
|
||||
|| !templatePools.isEmpty()
|
||||
|| !processorLists.isEmpty()
|
||||
|| !biomeHasStructureTags.isEmpty();
|
||||
|| !biomeHasStructureTags.isEmpty()
|
||||
|| !configuredFeatures.isEmpty()
|
||||
|| !placedFeatures.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@Desc("Defines a structure-level patch override for external datapack projection")
|
||||
public class IrisExternalDatapackStructurePatch {
|
||||
@Desc("Structure id to patch")
|
||||
private String structure = "";
|
||||
|
||||
@Desc("Enable or disable this patch entry")
|
||||
private boolean enabled = true;
|
||||
|
||||
@Desc("Absolute start height override for this structure")
|
||||
private int startHeightAbsolute = -27;
|
||||
}
|
||||
@@ -204,13 +204,16 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
int blockX = x << 2;
|
||||
int blockZ = z << 2;
|
||||
int blockY = y << 2;
|
||||
int surfaceY = engine.getComplex().getHeightStream().get(blockX, blockZ).intValue();
|
||||
int caveSwitchY = Math.min(-8, engine.getMinHeight() + 40);
|
||||
boolean deepUnderground = blockY <= caveSwitchY;
|
||||
boolean belowSurface = blockY <= surfaceY - 8;
|
||||
int worldMinHeight = engine.getWorld().minHeight();
|
||||
int surfaceInternalY = engine.getComplex().getHeightStream().get(blockX, blockZ).intValue();
|
||||
int surfaceWorldY = surfaceInternalY + worldMinHeight;
|
||||
int caveSwitchWorldY = Math.min(-8, worldMinHeight + 40);
|
||||
boolean deepUnderground = blockY <= caveSwitchWorldY;
|
||||
boolean belowSurface = blockY <= surfaceWorldY - 8;
|
||||
boolean underground = deepUnderground && belowSurface;
|
||||
int internalY = blockY - worldMinHeight;
|
||||
IrisBiome irisBiome = underground
|
||||
? engine.getCaveBiome(blockX, blockY, blockZ)
|
||||
? engine.getCaveBiome(blockX, internalY, blockZ)
|
||||
: engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
||||
if (irisBiome == null && underground) {
|
||||
irisBiome = engine.getComplex().getTrueBiomeStream().get(blockX, blockZ);
|
||||
|
||||
Reference in New Issue
Block a user