diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestItem.java b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestItem.java new file mode 100644 index 000000000..35e5001b6 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestItem.java @@ -0,0 +1,33 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest; + +import java.util.Objects; + +public record ModIngestItem(String namespace, String sourceKey, String kind, ModIngestTier tier, String target, String reason) { + public ModIngestItem { + Objects.requireNonNull(namespace, "namespace"); + Objects.requireNonNull(sourceKey, "sourceKey"); + Objects.requireNonNull(kind, "kind"); + Objects.requireNonNull(tier, "tier"); + Objects.requireNonNull(target, "target"); + Objects.requireNonNull(reason, "reason"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestReport.java b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestReport.java new file mode 100644 index 000000000..1ae2ddabc --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestReport.java @@ -0,0 +1,32 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest; + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +public record ModIngestReport(Path targetPack, List items, List summaryLines) { + public ModIngestReport { + Objects.requireNonNull(targetPack, "targetPack"); + items = List.copyOf(Objects.requireNonNull(items, "items")); + summaryLines = List.copyOf(Objects.requireNonNull(summaryLines, "summaryLines")); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestRequest.java b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestRequest.java new file mode 100644 index 000000000..5849b6565 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestRequest.java @@ -0,0 +1,36 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest; + +import art.arcane.iris.pack.ingest.catalog.WorldgenCatalog; + +import java.nio.file.Path; +import java.util.Objects; +import java.util.Set; + +public record ModIngestRequest(Path sourcePack, Path targetPack, String dimensionKey, WorldgenCatalog catalog, Set namespaces, boolean replaceTarget) { + public ModIngestRequest { + Objects.requireNonNull(sourcePack, "sourcePack"); + Objects.requireNonNull(targetPack, "targetPack"); + Objects.requireNonNull(dimensionKey, "dimensionKey"); + Objects.requireNonNull(catalog, "catalog"); + namespaces = Set.copyOf(Objects.requireNonNull(namespaces, "namespaces")); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestTier.java b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestTier.java new file mode 100644 index 000000000..bddb2444d --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngestTier.java @@ -0,0 +1,27 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest; + +public enum ModIngestTier { + NATIVE, + ADOPTED, + PASSTHROUGH, + SKIPPED +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/ModIngester.java b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngester.java new file mode 100644 index 000000000..5483dce24 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/ModIngester.java @@ -0,0 +1,31 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest; + +import java.io.IOException; + +public final class ModIngester { + private ModIngester() { + } + + public static ModIngestReport ingest(ModIngestRequest request) throws IOException { + throw new UnsupportedOperationException("Mod ingest is not implemented yet"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogBiome.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogBiome.java new file mode 100644 index 000000000..3ab33c1be --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogBiome.java @@ -0,0 +1,42 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.JsonElement; + +import java.util.List; +import java.util.Objects; + +public record CatalogBiome( + String key, + float temperature, + float downfall, + boolean hasPrecipitation, + List tags, + List> featureSteps, + List spawns, + JsonElement definition) { + public CatalogBiome { + Objects.requireNonNull(key, "key"); + tags = List.copyOf(Objects.requireNonNull(tags, "tags")); + featureSteps = Objects.requireNonNull(featureSteps, "featureSteps").stream().map(List::copyOf).toList(); + spawns = List.copyOf(Objects.requireNonNull(spawns, "spawns")); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogDimensionType.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogDimensionType.java new file mode 100644 index 000000000..dc92d4fdd --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogDimensionType.java @@ -0,0 +1,30 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.JsonElement; + +import java.util.Objects; + +public record CatalogDimensionType(String key, int minY, int height, int logicalHeight, JsonElement definition) { + public CatalogDimensionType { + Objects.requireNonNull(key, "key"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogLevelStem.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogLevelStem.java new file mode 100644 index 000000000..ff1f77ed0 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogLevelStem.java @@ -0,0 +1,38 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.JsonElement; + +import java.util.Objects; + +public record CatalogLevelStem( + String key, + String dimensionType, + String generatorType, + String biomeSourceType, + JsonElement generator) { + public CatalogLevelStem { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(dimensionType, "dimensionType"); + Objects.requireNonNull(generatorType, "generatorType"); + Objects.requireNonNull(biomeSourceType, "biomeSourceType"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogNamespace.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogNamespace.java new file mode 100644 index 000000000..49980ac62 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogNamespace.java @@ -0,0 +1,30 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import java.util.Objects; + +public record CatalogNamespace(String namespace, String displayName, String version) { + public CatalogNamespace { + Objects.requireNonNull(namespace, "namespace"); + Objects.requireNonNull(displayName, "displayName"); + Objects.requireNonNull(version, "version"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogPlacedFeature.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogPlacedFeature.java new file mode 100644 index 000000000..2302ab779 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogPlacedFeature.java @@ -0,0 +1,37 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.JsonElement; + +import java.util.Objects; + +public record CatalogPlacedFeature( + String key, + String configuredFeature, + String featureType, + JsonElement config, + JsonElement placement) { + public CatalogPlacedFeature { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(configuredFeature, "configuredFeature"); + Objects.requireNonNull(featureType, "featureType"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogSpawn.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogSpawn.java new file mode 100644 index 000000000..c6c4b4ab1 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogSpawn.java @@ -0,0 +1,29 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import java.util.Objects; + +public record CatalogSpawn(String category, String entity, int weight, int minCount, int maxCount) { + public CatalogSpawn { + Objects.requireNonNull(category, "category"); + Objects.requireNonNull(entity, "entity"); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogStructure.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogStructure.java new file mode 100644 index 000000000..890ef9580 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/CatalogStructure.java @@ -0,0 +1,42 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import java.util.List; +import java.util.Objects; + +public record CatalogStructure( + String key, + String type, + String step, + String terrainAdaptation, + String biomeTag, + List biomes, + List structureSets) { + public CatalogStructure { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(step, "step"); + Objects.requireNonNull(terrainAdaptation, "terrainAdaptation"); + Objects.requireNonNull(biomeTag, "biomeTag"); + biomes = List.copyOf(Objects.requireNonNull(biomes, "biomes")); + structureSets = List.copyOf(Objects.requireNonNull(structureSets, "structureSets")); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalog.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalog.java new file mode 100644 index 000000000..ca04f42d5 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalog.java @@ -0,0 +1,50 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import java.util.List; +import java.util.Objects; + +public record WorldgenCatalog( + int format, + String minecraftVersion, + String platform, + long capturedAtEpochMillis, + String contentFingerprint, + List namespaces, + List biomes, + List placedFeatures, + List structures, + List dimensionTypes, + List levelStems) { + public static final int FORMAT = 1; + + public WorldgenCatalog { + Objects.requireNonNull(minecraftVersion, "minecraftVersion"); + Objects.requireNonNull(platform, "platform"); + Objects.requireNonNull(contentFingerprint, "contentFingerprint"); + namespaces = List.copyOf(Objects.requireNonNull(namespaces, "namespaces")); + biomes = List.copyOf(Objects.requireNonNull(biomes, "biomes")); + placedFeatures = List.copyOf(Objects.requireNonNull(placedFeatures, "placedFeatures")); + structures = List.copyOf(Objects.requireNonNull(structures, "structures")); + dimensionTypes = List.copyOf(Objects.requireNonNull(dimensionTypes, "dimensionTypes")); + levelStems = List.copyOf(Objects.requireNonNull(levelStems, "levelStems")); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogIndex.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogIndex.java new file mode 100644 index 000000000..c198818e3 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogIndex.java @@ -0,0 +1,111 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; + +public final class WorldgenCatalogIndex { + private final WorldgenCatalog catalog; + private final Map biomes; + private final Map placedFeatures; + private final Map structures; + private final Map dimensionTypes; + private final Map levelStems; + + private WorldgenCatalogIndex(WorldgenCatalog catalog) { + this.catalog = catalog; + this.biomes = index(catalog.biomes(), CatalogBiome::key); + this.placedFeatures = index(catalog.placedFeatures(), CatalogPlacedFeature::key); + this.structures = index(catalog.structures(), CatalogStructure::key); + this.dimensionTypes = index(catalog.dimensionTypes(), CatalogDimensionType::key); + this.levelStems = index(catalog.levelStems(), CatalogLevelStem::key); + } + + public static WorldgenCatalogIndex of(WorldgenCatalog catalog) { + return new WorldgenCatalogIndex(Objects.requireNonNull(catalog, "catalog")); + } + + public static String namespaceOf(String key) { + int colon = key.indexOf(':'); + return colon < 0 ? "minecraft" : key.substring(0, colon); + } + + public WorldgenCatalog catalog() { + return catalog; + } + + public Optional biome(String key) { + return Optional.ofNullable(biomes.get(key)); + } + + public Optional placedFeature(String key) { + return Optional.ofNullable(placedFeatures.get(key)); + } + + public Optional structure(String key) { + return Optional.ofNullable(structures.get(key)); + } + + public Optional dimensionType(String key) { + return Optional.ofNullable(dimensionTypes.get(key)); + } + + public Optional levelStem(String key) { + return Optional.ofNullable(levelStems.get(key)); + } + + public List biomesIn(String namespace) { + List result = new ArrayList<>(); + for (CatalogBiome biome : catalog.biomes()) { + if (namespaceOf(biome.key()).equals(namespace)) { + result.add(biome); + } + } + return Collections.unmodifiableList(result); + } + + public List biomesDeclaring(String placedFeatureKey) { + List result = new ArrayList<>(); + for (CatalogBiome biome : catalog.biomes()) { + for (List step : biome.featureSteps()) { + if (step.contains(placedFeatureKey)) { + result.add(biome); + break; + } + } + } + return Collections.unmodifiableList(result); + } + + private static Map index(List values, Function key) { + Map result = new LinkedHashMap<>(Math.max(16, values.size() * 2)); + for (T value : values) { + result.put(key.apply(value), value); + } + return Collections.unmodifiableMap(result); + } +} diff --git a/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStore.java b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStore.java new file mode 100644 index 000000000..72659f820 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStore.java @@ -0,0 +1,70 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Objects; + +public final class WorldgenCatalogStore { + public static final String FILE_NAME = "worldgen-catalog.json"; + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + + private WorldgenCatalogStore() { + } + + public static WorldgenCatalog read(Path file) throws IOException { + Objects.requireNonNull(file, "file"); + try (Reader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { + WorldgenCatalog catalog = GSON.fromJson(reader, WorldgenCatalog.class); + if (catalog == null) { + throw new IOException("Worldgen catalog is empty: " + file); + } + if (catalog.format() != WorldgenCatalog.FORMAT) { + throw new IOException("Worldgen catalog " + file + " has format " + catalog.format() + ", expected " + WorldgenCatalog.FORMAT); + } + return catalog; + } + } + + public static void write(Path file, WorldgenCatalog catalog) throws IOException { + Objects.requireNonNull(file, "file"); + Objects.requireNonNull(catalog, "catalog"); + Path parent = file.toAbsolutePath().getParent(); + Files.createDirectories(parent); + Path temp = Files.createTempFile(parent, FILE_NAME, ".tmp"); + try { + try (Writer writer = Files.newBufferedWriter(temp, StandardCharsets.UTF_8)) { + GSON.toJson(catalog, writer); + } + Files.move(temp, file, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); + } finally { + Files.deleteIfExists(temp); + } + } +} diff --git a/core/src/test/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStoreTest.java b/core/src/test/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStoreTest.java new file mode 100644 index 000000000..64fd6fba4 --- /dev/null +++ b/core/src/test/java/art/arcane/iris/pack/ingest/catalog/WorldgenCatalogStoreTest.java @@ -0,0 +1,83 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package art.arcane.iris.pack.ingest.catalog; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class WorldgenCatalogStoreTest { + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + @Test + public void writeThenReadPreservesEveryRecord() throws IOException { + JsonObject config = new JsonObject(); + config.add("size", new JsonPrimitive(9)); + WorldgenCatalog catalog = new WorldgenCatalog( + WorldgenCatalog.FORMAT, + "26.3", + "neoforge", + 1234L, + "abc", + List.of(new CatalogNamespace("examplemod", "Example Mod", "1.0.0")), + List.of(new CatalogBiome("examplemod:glade", 0.7F, 0.8F, true, List.of("minecraft:is_overworld"), + List.of(List.of(), List.of("examplemod:ore_glimmer")), + List.of(new CatalogSpawn("creature", "minecraft:sheep", 12, 2, 4)), new JsonObject())), + List.of(new CatalogPlacedFeature("examplemod:ore_glimmer", "examplemod:ore_glimmer", "minecraft:ore", config, null)), + List.of(new CatalogStructure("examplemod:tower", "minecraft:jigsaw", "surface_structures", "none", + "examplemod:has_tower", List.of("examplemod:glade"), List.of("examplemod:towers"))), + List.of(new CatalogDimensionType("examplemod:sky", 0, 256, 256, new JsonObject())), + List.of(new CatalogLevelStem("examplemod:sky", "examplemod:sky", "minecraft:noise", "minecraft:multi_noise", null))); + Path file = folder.getRoot().toPath().resolve("nested").resolve(WorldgenCatalogStore.FILE_NAME); + + WorldgenCatalogStore.write(file, catalog); + WorldgenCatalog read = WorldgenCatalogStore.read(file); + + assertEquals(catalog, read); + assertTrue(Files.list(file.getParent()).allMatch(path -> path.equals(file))); + } + + @Test + public void indexResolvesNamespacesAndFeatureOwners() { + WorldgenCatalog catalog = new WorldgenCatalog(WorldgenCatalog.FORMAT, "26.3", "fabric", 0L, "", + List.of(), + List.of(new CatalogBiome("examplemod:glade", 0.7F, 0.8F, true, List.of(), List.of(List.of("examplemod:flowers")), List.of(), null), + new CatalogBiome("minecraft:forest", 0.7F, 0.8F, true, List.of(), List.of(List.of("examplemod:flowers")), List.of(), null), + new CatalogBiome("minecraft:desert", 2.0F, 0.0F, false, List.of(), List.of(), List.of(), null)), + List.of(), List.of(), List.of(), List.of()); + WorldgenCatalogIndex index = WorldgenCatalogIndex.of(catalog); + + assertEquals(1, index.biomesIn("examplemod").size()); + assertEquals(2, index.biomesDeclaring("examplemod:flowers").size()); + assertEquals("minecraft", WorldgenCatalogIndex.namespaceOf("plains")); + assertTrue(index.biome("minecraft:desert").isPresent()); + } +}