mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 08:07:42 +00:00
Scored ingest biome placement
- Mod biomes pick their template across all regions by climate distance, biome category agreement from minecraft and c tags, a reuse penalty that spreads biomes over equally good templates, and the region's overall climate - Regions much rarer than the dimension's median region are treated as themed and only receive a mod biome when nothing else fits - Templates derived from void biomes no longer act as climate references - /iris ingest mods accepts excludeRegions=<a,b> to keep mod biomes out of named regions; unknown region names are refused
This commit is contained in:
1 parent
8388194129
commit
0bc235afb6
34 files changed
+389
-66
No files matched your search
+29
-4
@@ -26,21 +26,25 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
record ModIngestArguments(String sourcePack, String targetPack, String dimension, Set<String> namespaces, boolean replace) {
|
||||
static final List<String> OPTION_SUGGESTIONS = List.of("dimension=", "namespaces=", "replace=true");
|
||||
record ModIngestArguments(String sourcePack, String targetPack, String dimension, Set<String> namespaces,
|
||||
Set<String> excludedRegions, boolean replace) {
|
||||
static final List<String> OPTION_SUGGESTIONS = List.of("dimension=", "namespaces=", "excludeRegions=", "replace=true");
|
||||
private static final Pattern PACK = Pattern.compile("[A-Za-z0-9_.-]+");
|
||||
private static final Pattern TARGET_PACK = Pattern.compile("[A-Za-z0-9_-]+");
|
||||
private static final Pattern DIMENSION = Pattern.compile("[A-Za-z0-9_/.-]+");
|
||||
private static final Pattern NAMESPACE = Pattern.compile("[a-z0-9_.-]+");
|
||||
private static final Pattern REGION = Pattern.compile("[A-Za-z0-9_/.-]+");
|
||||
private static final String DIMENSION_KEY = "dimension";
|
||||
private static final String NAMESPACES_KEY = "namespaces";
|
||||
private static final String REPLACE_KEY = "replace";
|
||||
private static final String EXCLUDE_REGIONS_KEY = "excludeRegions";
|
||||
|
||||
ModIngestArguments {
|
||||
Objects.requireNonNull(sourcePack, "sourcePack");
|
||||
Objects.requireNonNull(targetPack, "targetPack");
|
||||
Objects.requireNonNull(dimension, "dimension");
|
||||
namespaces = Set.copyOf(Objects.requireNonNull(namespaces, "namespaces"));
|
||||
excludedRegions = Set.copyOf(Objects.requireNonNull(excludedRegions, "excludedRegions"));
|
||||
}
|
||||
|
||||
static ModIngestArguments parse(String raw) {
|
||||
@@ -62,7 +66,8 @@ record ModIngestArguments(String sourcePack, String targetPack, String dimension
|
||||
continue;
|
||||
}
|
||||
String key = token.substring(0, equals);
|
||||
if (!key.equals(DIMENSION_KEY) && !key.equals(NAMESPACES_KEY) && !key.equals(REPLACE_KEY)) {
|
||||
if (!key.equals(DIMENSION_KEY) && !key.equals(NAMESPACES_KEY) && !key.equals(REPLACE_KEY)
|
||||
&& !key.equals(EXCLUDE_REGIONS_KEY)) {
|
||||
throw new IllegalArgumentException("unknown option '" + key + "'");
|
||||
}
|
||||
if (options.putIfAbsent(key, token.substring(equals + 1)) != null) {
|
||||
@@ -88,7 +93,7 @@ record ModIngestArguments(String sourcePack, String targetPack, String dimension
|
||||
throw new IllegalArgumentException("invalid dimension key '" + dimension + "'");
|
||||
}
|
||||
return new ModIngestArguments(source, target, dimension, namespaces(options.get(NAMESPACES_KEY)),
|
||||
replace(options.get(REPLACE_KEY)));
|
||||
regions(options.get(EXCLUDE_REGIONS_KEY)), replace(options.get(REPLACE_KEY)));
|
||||
}
|
||||
|
||||
private static void requirePack(String pack) {
|
||||
@@ -117,6 +122,26 @@ record ModIngestArguments(String sourcePack, String targetPack, String dimension
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
private static Set<String> regions(String raw) {
|
||||
if (raw == null) {
|
||||
return Set.of();
|
||||
}
|
||||
Set<String> regions = new LinkedHashSet<>();
|
||||
for (String part : raw.split(",")) {
|
||||
if (part.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!REGION.matcher(part).matches() || part.contains("..")) {
|
||||
throw new IllegalArgumentException("invalid region '" + part + "'");
|
||||
}
|
||||
regions.add(part);
|
||||
}
|
||||
if (regions.isEmpty()) {
|
||||
throw new IllegalArgumentException("excludeRegions must not be empty");
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
|
||||
private static boolean replace(String raw) {
|
||||
if (raw == null || raw.equals("false")) {
|
||||
return false;
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ final class ModdedCatalogCommands {
|
||||
}
|
||||
Path targetPack = packsRoot.toPath().toAbsolutePath().normalize().resolve(arguments.targetPack());
|
||||
ModIngestRequest request = new ModIngestRequest(sourcePack.toPath(), targetPack, arguments.dimension(),
|
||||
catalog.get(), arguments.namespaces(), arguments.replace());
|
||||
catalog.get(), arguments.namespaces(), arguments.excludedRegions(), arguments.replace());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCatalogMessages.INGEST_STARTED,
|
||||
MessageArgument.untrusted("source", arguments.sourcePack()),
|
||||
MessageArgument.untrusted("target", arguments.targetPack()),
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ final class ModdedCommandHelp {
|
||||
));
|
||||
SECTIONS.put("pk", SECTIONS.get("pack"));
|
||||
SECTIONS.put("ingest", List.of(
|
||||
Entry.command("mods", "<source> <target> [dimension=<key>] [namespaces=<a,b>] [replace=true]", ModdedCatalogMessages.HELP_INGEST_MODS)
|
||||
Entry.command("mods", "<source> <target> [dimension=<key>] [namespaces=<a,b>] [excludeRegions=<a,b>] [replace=true]", ModdedCatalogMessages.HELP_INGEST_MODS)
|
||||
));
|
||||
SECTIONS.put("world", List.of(
|
||||
Entry.command("enable", "<dimension> <pack|pack:dimensionKey> [seed|random]", ModdedHelpMessages.COMMAND_ENABLE_CREATE_AND_INJECT_A_PERSISTENT_IRIS_DIMENSION_AT_RUNTIME_DOWNLOADS_THE_PACK, "create"),
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public final class ModdedCatalogMessages {
|
||||
public static final TextKey INGEST_INVALID = TextKey.of(
|
||||
"iris.modded.catalog.ingest_invalid",
|
||||
"Invalid arguments: {reason}. Usage: /iris ingest mods <source> <target> [dimension=<key>] "
|
||||
+ "[namespaces=<a,b>] [replace=true]"
|
||||
+ "[namespaces=<a,b>] [excludeRegions=<a,b>] [replace=true]"
|
||||
);
|
||||
public static final TextKey INGEST_PACK_MISSING = TextKey.of(
|
||||
"iris.modded.catalog.ingest_pack_missing",
|
||||
|
||||
+5
-1
@@ -36,15 +36,17 @@ public class ModIngestArgumentsTest {
|
||||
assertEquals("modded_overworld", arguments.targetPack());
|
||||
assertEquals("overworld", arguments.dimension());
|
||||
assertEquals(Set.of(), arguments.namespaces());
|
||||
assertEquals(Set.of(), arguments.excludedRegions());
|
||||
assertFalse(arguments.replace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keyedOptionalsAreParsedInAnyOrder() {
|
||||
ModIngestArguments arguments = ModIngestArguments.parse(
|
||||
" overworld modded replace=true namespaces=biomesoplenty,terralith dimension=overworld_alt ");
|
||||
" overworld modded replace=true namespaces=biomesoplenty,terralith excludeRegions=prismatics,estranged dimension=overworld_alt ");
|
||||
|
||||
assertEquals("overworld_alt", arguments.dimension());
|
||||
assertEquals(Set.of("prismatics", "estranged"), arguments.excludedRegions());
|
||||
assertEquals(Set.of("biomesoplenty", "terralith"), arguments.namespaces());
|
||||
assertTrue(arguments.replace());
|
||||
}
|
||||
@@ -72,6 +74,8 @@ public class ModIngestArgumentsTest {
|
||||
assertEquals("invalid dimension key 'a..b'", reason("overworld modded dimension=a..b"));
|
||||
assertEquals("invalid namespace 'Bad'", reason("overworld modded namespaces=ok,Bad"));
|
||||
assertEquals("namespaces must not be empty", reason("overworld modded namespaces=,"));
|
||||
assertEquals("invalid region 'a/../b'", reason("overworld modded excludeRegions=a/../b"));
|
||||
assertEquals("excludeRegions must not be empty", reason("overworld modded excludeRegions=,"));
|
||||
assertEquals("source and target must be different packs", reason("overworld overworld"));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public class ModdedCatalogCommandsTest {
|
||||
assertTrue(ModdedCommandHelp.documents("ingest", "mods"));
|
||||
List<String> lines = ModdedCommandHelp.consoleLines("ingest");
|
||||
assertTrue(lines.stream().anyMatch((String line) ->
|
||||
line.startsWith("/iris ingest mods <source> <target> [dimension=<key>] [namespaces=<a,b>] [replace=true] - ")));
|
||||
line.startsWith("/iris ingest mods <source> <target> [dimension=<key>] [namespaces=<a,b>] [excludeRegions=<a,b>] [replace=true] - ")));
|
||||
}
|
||||
|
||||
private static CommandNode<CommandSourceStack> child(CommandNode<CommandSourceStack> parent, String name) {
|
||||
|
||||
Reference in new issue
Block a user