implement namespaced registries

This commit is contained in:
dfsek
2021-12-25 01:01:32 -07:00
parent bb87bfa1de
commit 8467a19781
44 changed files with 427 additions and 235 deletions
@@ -41,7 +41,7 @@ public class ImageBiomeProviderAddon implements AddonInitializer {
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(
PROVIDER_REGISTRY_KEY); PROVIDER_REGISTRY_KEY);
providerRegistry.register("IMAGE", () -> new ImageProviderTemplate(event.getPack().getRegistry(Biome.class))); providerRegistry.register(addon.getKey("IMAGE"), () -> new ImageProviderTemplate(event.getPack().getRegistry(Biome.class)));
}) })
.failThrough(); .failThrough();
} }
@@ -60,22 +60,22 @@ public class BiomePipelineAddon implements AddonInitializer {
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(
PROVIDER_REGISTRY_KEY); PROVIDER_REGISTRY_KEY);
providerRegistry.register("PIPELINE", BiomePipelineTemplate::new); providerRegistry.register(addon.getKey("PIPELINE"), BiomePipelineTemplate::new);
}) })
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeSource>>> sourceRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<BiomeSource>>> sourceRegistry = event.getPack().getOrCreateRegistry(
SOURCE_REGISTRY_KEY); SOURCE_REGISTRY_KEY);
sourceRegistry.register("SAMPLER", SamplerSourceTemplate::new); sourceRegistry.register(addon.getKey("SAMPLER"), SamplerSourceTemplate::new);
}) })
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Stage>>> stageRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<Stage>>> stageRegistry = event.getPack().getOrCreateRegistry(
STAGE_REGISTRY_KEY); STAGE_REGISTRY_KEY);
stageRegistry.register("FRACTAL_EXPAND", ExpanderStageTemplate::new); stageRegistry.register(addon.getKey("FRACTAL_EXPAND"), ExpanderStageTemplate::new);
stageRegistry.register("SMOOTH", SmoothMutatorTemplate::new); stageRegistry.register(addon.getKey("SMOOTH"), SmoothMutatorTemplate::new);
stageRegistry.register("REPLACE", ReplaceMutatorTemplate::new); stageRegistry.register(addon.getKey("REPLACE"), ReplaceMutatorTemplate::new);
stageRegistry.register("REPLACE_LIST", ReplaceListMutatorTemplate::new); stageRegistry.register(addon.getKey("REPLACE_LIST"), ReplaceListMutatorTemplate::new);
stageRegistry.register("BORDER", BorderMutatorTemplate::new); stageRegistry.register(addon.getKey("BORDER"), BorderMutatorTemplate::new);
stageRegistry.register("BORDER_LIST", BorderListMutatorTemplate::new); stageRegistry.register(addon.getKey("BORDER_LIST"), BorderListMutatorTemplate::new);
}) })
.failThrough(); .failThrough();
platform.getEventManager() platform.getEventManager()
@@ -3,6 +3,9 @@ package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader; import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.api.registry.key.RegistryKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
@@ -23,7 +26,7 @@ public class BiomeDelegateLoader implements TypeLoader<BiomeDelegate> {
public BiomeDelegate load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException { public BiomeDelegate load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException {
if(c.equals("SELF")) return BiomeDelegate.self(); if(c.equals("SELF")) return BiomeDelegate.self();
return biomeRegistry return biomeRegistry
.get((String) c) .tryGet((String) c)
.map(BiomeDelegate::from) .map(BiomeDelegate::from)
.orElseGet(() -> BiomeDelegate.ephemeral((String) c)); .orElseGet(() -> BiomeDelegate.ephemeral((String) c));
} }
@@ -40,7 +40,7 @@ public class SingleBiomeProviderAddon implements AddonInitializer {
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(
PROVIDER_REGISTRY_KEY); PROVIDER_REGISTRY_KEY);
providerRegistry.register("SINGLE", SingleBiomeProviderTemplate::new); providerRegistry.register(addon.getKey("SINGLE"), SingleBiomeProviderTemplate::new);
}) })
.failThrough(); .failThrough();
} }
@@ -40,7 +40,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
event.getPack() event.getPack()
.getOrCreateRegistry(ChunkGeneratorProvider.class) .getOrCreateRegistry(ChunkGeneratorProvider.class)
.register("NOISE_3D", .register(addon.getKey("NOISE_3D"),
pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), config.getHorizontalRes(), pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), config.getHorizontalRes(),
config.getVerticalRes())); config.getVerticalRes()));
event.getPack() event.getPack()
@@ -30,7 +30,7 @@ public class BiomeAddon implements AddonInitializer {
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> { .then(event -> {
event.getPack().registerConfigType(new BiomeConfigType(event.getPack()), "BIOME", 5); event.getPack().registerConfigType(new BiomeConfigType(event.getPack()), addon.getKey("BIOME"), 5);
event.getPack().applyLoader(PaletteHolder.class, new PaletteHolderLoader()); event.getPack().applyLoader(PaletteHolder.class, new PaletteHolderLoader());
}) })
.failThrough(); .failThrough();
@@ -47,12 +47,12 @@ public class DistributorAddon implements AddonInitializer {
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Distributor>>> distributorRegistry = event.getPack().getOrCreateRegistry( CheckedRegistry<Supplier<ObjectTemplate<Distributor>>> distributorRegistry = event.getPack().getOrCreateRegistry(
DISTRIBUTOR_TOKEN); DISTRIBUTOR_TOKEN);
distributorRegistry.register("SAMPLER", SamplerDistributorTemplate::new); distributorRegistry.register(addon.getKey("SAMPLER"), SamplerDistributorTemplate::new);
distributorRegistry.register("POINTS", PointSetDistributorTemplate::new); distributorRegistry.register(addon.getKey("POINTS"), PointSetDistributorTemplate::new);
distributorRegistry.register("AND", AndDistributorTemplate::new); distributorRegistry.register(addon.getKey("AND"), AndDistributorTemplate::new);
distributorRegistry.register("OR", OrDistributorTemplate::new); distributorRegistry.register(addon.getKey("OR"), OrDistributorTemplate::new);
distributorRegistry.register("YES", YesDistributorTemplate::new); distributorRegistry.register(addon.getKey("YES"), YesDistributorTemplate::new);
distributorRegistry.register("NO", NoDistributorTemplate::new); distributorRegistry.register(addon.getKey("NO"), NoDistributorTemplate::new);
event.getPack() event.getPack()
.applyLoader(Point.class, PointTemplate::new); .applyLoader(Point.class, PointTemplate::new);
@@ -27,7 +27,7 @@ public class FeatureAddon implements AddonInitializer {
platform.getEventManager() platform.getEventManager()
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().registerConfigType(new FeatureConfigType(), "FEATURE", 3)) .then(event -> event.getPack().registerConfigType(new FeatureConfigType(), addon.getKey("FEATURE"), 3))
.failThrough(); .failThrough();
} }
} }
@@ -30,7 +30,7 @@ public class FloraAddon implements AddonInitializer {
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> { .then(event -> {
event.getPack().registerConfigType(new FloraConfigType(), "FLORA", 2); event.getPack().registerConfigType(new FloraConfigType(), addon.getKey("FLORA"), 2);
event.getPack().applyLoader(BlockLayer.class, BlockLayerTemplate::new); event.getPack().applyLoader(BlockLayer.class, BlockLayerTemplate::new);
}) })
.failThrough(); .failThrough();
@@ -57,29 +57,29 @@ public class LocatorAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Locator>>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN); CheckedRegistry<Supplier<ObjectTemplate<Locator>>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN);
locatorRegistry.register("SURFACE", () -> new SurfaceLocatorTemplate(platform)); locatorRegistry.register(addon.getKey("SURFACE"), () -> new SurfaceLocatorTemplate(platform));
locatorRegistry.register("RANDOM", RandomLocatorTemplate::new); locatorRegistry.register(addon.getKey("RANDOM"), RandomLocatorTemplate::new);
locatorRegistry.register("GAUSSIAN_RANDOM", GaussianRandomLocatorTemplate::new); locatorRegistry.register(addon.getKey("GAUSSIAN_RANDOM"), GaussianRandomLocatorTemplate::new);
locatorRegistry.register("PATTERN", PatternLocatorTemplate::new); locatorRegistry.register(addon.getKey("PATTERN"), PatternLocatorTemplate::new);
locatorRegistry.register("SAMPLER", SamplerLocatorTemplate::new); locatorRegistry.register(addon.getKey("SAMPLER"), SamplerLocatorTemplate::new);
locatorRegistry.register("SAMPLER_3D", Sampler3DLocatorTemplate::new); locatorRegistry.register(addon.getKey("SAMPLER_3D"), Sampler3DLocatorTemplate::new);
locatorRegistry.register("AND", AndLocatorTemplate::new); locatorRegistry.register(addon.getKey("AND"), AndLocatorTemplate::new);
locatorRegistry.register("OR", OrLocatorTemplate::new); locatorRegistry.register(addon.getKey("OR"), OrLocatorTemplate::new);
}) })
.then(event -> { .then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Pattern>>> patternRegistry = event.getPack().getOrCreateRegistry(PATTERN_TOKEN); CheckedRegistry<Supplier<ObjectTemplate<Pattern>>> patternRegistry = event.getPack().getOrCreateRegistry(PATTERN_TOKEN);
patternRegistry.register("MATCH_AIR", AirMatchPatternTemplate::new); patternRegistry.register(addon.getKey("MATCH_AIR"), AirMatchPatternTemplate::new);
patternRegistry.register("MATCH_SOLID", SolidMatchPatternTemplate::new); patternRegistry.register(addon.getKey("MATCH_SOLID"), SolidMatchPatternTemplate::new);
patternRegistry.register("MATCH", SingleBlockMatchPatternTemplate::new); patternRegistry.register(addon.getKey("MATCH"), SingleBlockMatchPatternTemplate::new);
patternRegistry.register("MATCH_SET", BlockSetMatchPatternTemplate::new); patternRegistry.register(addon.getKey("MATCH_SET"), BlockSetMatchPatternTemplate::new);
patternRegistry.register("AND", AndPatternTemplate::new); patternRegistry.register(addon.getKey("AND"), AndPatternTemplate::new);
patternRegistry.register("OR", OrPatternTemplate::new); patternRegistry.register(addon.getKey("OR"), OrPatternTemplate::new);
patternRegistry.register("NOT", NotPatternTemplate::new); patternRegistry.register(addon.getKey("NOT"), NotPatternTemplate::new);
}) })
.failThrough(); .failThrough();
} }
@@ -84,54 +84,54 @@ public class NoiseAddon implements AddonInitializer {
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
.applyLoader(FunctionTemplate.class, FunctionTemplate::new); .applyLoader(FunctionTemplate.class, FunctionTemplate::new);
noiseRegistry.register("LINEAR", LinearNormalizerTemplate::new); noiseRegistry.register(addon.getKey("LINEAR"), LinearNormalizerTemplate::new);
noiseRegistry.register("NORMAL", NormalNormalizerTemplate::new); noiseRegistry.register(addon.getKey("NORMAL"), NormalNormalizerTemplate::new);
noiseRegistry.register("CLAMP", ClampNormalizerTemplate::new); noiseRegistry.register(addon.getKey("CLAMP"), ClampNormalizerTemplate::new);
noiseRegistry.register("PROBABILITY", ProbabilityNormalizerTemplate::new); noiseRegistry.register(addon.getKey("PROBABILITY"), ProbabilityNormalizerTemplate::new);
noiseRegistry.register("SCALE", ScaleNormalizerTemplate::new); noiseRegistry.register(addon.getKey("SCALE"), ScaleNormalizerTemplate::new);
noiseRegistry.register("IMAGE", ImageSamplerTemplate::new); noiseRegistry.register(addon.getKey("IMAGE"), ImageSamplerTemplate::new);
noiseRegistry.register("DOMAIN_WARP", DomainWarpTemplate::new); noiseRegistry.register(addon.getKey("DOMAIN_WARP"), DomainWarpTemplate::new);
noiseRegistry.register("FBM", BrownianMotionTemplate::new); noiseRegistry.register(addon.getKey("FBM"), BrownianMotionTemplate::new);
noiseRegistry.register("PING_PONG", PingPongTemplate::new); noiseRegistry.register(addon.getKey("PING_PONG"), PingPongTemplate::new);
noiseRegistry.register("RIDGED", RidgedFractalTemplate::new); noiseRegistry.register(addon.getKey("RIDGED"), RidgedFractalTemplate::new);
noiseRegistry.register("OPEN_SIMPLEX_2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new)); noiseRegistry.register(addon.getKey("OPEN_SIMPLEX_2"), () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new));
noiseRegistry.register("OPEN_SIMPLEX_2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new)); noiseRegistry.register(addon.getKey("OPEN_SIMPLEX_2S"), () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new));
noiseRegistry.register("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new)); noiseRegistry.register(addon.getKey("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new));
noiseRegistry.register("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new)); noiseRegistry.register(addon.getKey("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new));
noiseRegistry.register("GABOR", GaborNoiseTemplate::new); noiseRegistry.register(addon.getKey("GABOR"), GaborNoiseTemplate::new);
noiseRegistry.register("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new)); noiseRegistry.register(addon.getKey("VALUE"), () -> new SimpleNoiseTemplate(ValueSampler::new));
noiseRegistry.register("VALUE_CUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); noiseRegistry.register(addon.getKey("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new));
noiseRegistry.register("CELLULAR", CellularNoiseTemplate::new); noiseRegistry.register(addon.getKey("CELLULAR"), CellularNoiseTemplate::new);
noiseRegistry.register("WHITE_NOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new)); noiseRegistry.register(addon.getKey("WHITE_NOISE"), () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new));
noiseRegistry.register("POSITIVE_WHITE_NOISE", () -> new SimpleNoiseTemplate(PositiveWhiteNoiseSampler::new)); noiseRegistry.register(addon.getKey("POSITIVE_WHITE_NOISE"), () -> new SimpleNoiseTemplate(PositiveWhiteNoiseSampler::new));
noiseRegistry.register("GAUSSIAN", () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new)); noiseRegistry.register(addon.getKey("GAUSSIAN"), () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new));
noiseRegistry.register("CONSTANT", ConstantNoiseTemplate::new); noiseRegistry.register(addon.getKey("CONSTANT"), ConstantNoiseTemplate::new);
noiseRegistry.register("KERNEL", KernelTemplate::new); noiseRegistry.register(addon.getKey("KERNEL"), KernelTemplate::new);
noiseRegistry.register("LINEAR_HEIGHTMAP", LinearHeightmapSamplerTemplate::new); noiseRegistry.register(addon.getKey("LINEAR_HEIGHTMAP"), LinearHeightmapSamplerTemplate::new);
noiseRegistry.register("ADD", () -> new BinaryArithmeticTemplate<>(AdditionSampler::new)); noiseRegistry.register(addon.getKey("ADD"), () -> new BinaryArithmeticTemplate<>(AdditionSampler::new));
noiseRegistry.register("SUB", () -> new BinaryArithmeticTemplate<>(SubtractionSampler::new)); noiseRegistry.register(addon.getKey("SUB"), () -> new BinaryArithmeticTemplate<>(SubtractionSampler::new));
noiseRegistry.register("MUL", () -> new BinaryArithmeticTemplate<>(MultiplicationSampler::new)); noiseRegistry.register(addon.getKey("MUL"), () -> new BinaryArithmeticTemplate<>(MultiplicationSampler::new));
noiseRegistry.register("DIV", () -> new BinaryArithmeticTemplate<>(DivisionSampler::new)); noiseRegistry.register(addon.getKey("DIV"), () -> new BinaryArithmeticTemplate<>(DivisionSampler::new));
noiseRegistry.register("MAX", () -> new BinaryArithmeticTemplate<>(MaxSampler::new)); noiseRegistry.register(addon.getKey("MAX"), () -> new BinaryArithmeticTemplate<>(MaxSampler::new));
noiseRegistry.register("MIN", () -> new BinaryArithmeticTemplate<>(MinSampler::new)); noiseRegistry.register(addon.getKey("MIN"), () -> new BinaryArithmeticTemplate<>(MinSampler::new));
Map<String, DimensionApplicableNoiseSampler> packSamplers = new LinkedHashMap<>(); Map<String, DimensionApplicableNoiseSampler> packSamplers = new LinkedHashMap<>();
Map<String, FunctionTemplate> packFunctions = new LinkedHashMap<>(); Map<String, FunctionTemplate> packFunctions = new LinkedHashMap<>();
noiseRegistry.register("EXPRESSION", () -> new ExpressionFunctionTemplate(packSamplers, packFunctions)); noiseRegistry.register(addon.getKey("EXPRESSION"), () -> new ExpressionFunctionTemplate(packSamplers, packFunctions));
NoiseConfigPackTemplate template = event.loadTemplate(new NoiseConfigPackTemplate()); NoiseConfigPackTemplate template = event.loadTemplate(new NoiseConfigPackTemplate());
@@ -27,7 +27,7 @@ public class OreAddon implements AddonInitializer {
platform.getEventManager() platform.getEventManager()
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().registerConfigType(new OreConfigType(), "ORE", 1)) .then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.getKey("ORE"), 1))
.failThrough(); .failThrough();
} }
} }
@@ -30,7 +30,7 @@ public class PaletteAddon implements AddonInitializer {
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> { .then(event -> {
event.getPack().registerConfigType(new PaletteConfigType(platform), "PALETTE", 2); event.getPack().registerConfigType(new PaletteConfigType(platform), addon.getKey("PALETTE"), 2);
event.getPack().applyLoader(PaletteLayerHolder.class, new PaletteLayerLoader()); event.getPack().applyLoader(PaletteLayerHolder.class, new PaletteLayerLoader());
}) })
.failThrough(); .failThrough();
@@ -27,7 +27,7 @@ public class StructureAddon implements AddonInitializer {
platform.getEventManager() platform.getEventManager()
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().registerConfigType(new StructureConfigType(), "STRUCTURE", 2)) .then(event -> event.getPack().registerConfigType(new StructureConfigType(), addon.getKey("STRUCTURE"), 2))
.failThrough(); .failThrough();
} }
} }
@@ -54,7 +54,7 @@ public class FeatureGenerationAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack() .then(event -> event.getPack()
.getOrCreateRegistry(STAGE_TYPE_KEY) .getOrCreateRegistry(STAGE_TYPE_KEY)
.register("FEATURE", () -> new FeatureStageTemplate(platform))) .register(addon.getKey("FEATURE"), () -> new FeatureStageTemplate(platform)))
.failThrough(); .failThrough();
platform.getEventManager() platform.getEventManager()
@@ -26,7 +26,7 @@ public class StructureGenerationAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack() .then(event -> event.getPack()
.getOrCreateRegistry(GenerationStageProvider.class) .getOrCreateRegistry(GenerationStageProvider.class)
.register("STRUCTURE", pack -> new StructureGenerationStage(platform))) .register(addon.getKey("STRUCTURE"), pack -> new StructureGenerationStage(platform)))
.failThrough(); .failThrough();
platform.getEventManager() platform.getEventManager()
@@ -60,7 +60,7 @@ public class SpongeSchematicAddon implements AddonInitializer {
event.getPack().getLoader().open("", ".schem").thenEntries(entries -> { event.getPack().getLoader().open("", ".schem").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) { for(Map.Entry<String, InputStream> entry : entries) {
String id = StringUtil.fileName(entry.getKey()); String id = StringUtil.fileName(entry.getKey());
structureRegistry.register(id, convert(entry.getValue(), id)); structureRegistry.register(addon.getKey(id), convert(entry.getValue(), id));
} }
}).close(); }).close();
}) })
@@ -62,7 +62,7 @@ public class TerraScriptAddon implements AddonInitializer {
} }
}) })
.toList() .toList()
.forEach(structureScript -> structureRegistry.register(structureScript.getID(), .forEach(structureScript -> structureRegistry.register(addon.getKey(structureScript.getID()),
structureScript))) structureScript)))
.close(); .close();
}) })
@@ -67,7 +67,8 @@ public class StructureScript implements Structure {
} }
this.id = id; this.id = id;
functionRegistry.forEach(parser::registerFunction); // Register registry functions. //noinspection unchecked
functionRegistry.forEach((key, function) -> parser.registerFunction(key.getID(), function)); // Register registry functions.
parser parser
.registerFunction("block", new BlockFunctionBuilder(platform)) .registerFunction("block", new BlockFunctionBuilder(platform))
@@ -11,6 +11,7 @@ import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.entity.Container; import com.dfsek.terra.api.block.entity.Container;
import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent; import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3;
import net.jafama.FastMath; import net.jafama.FastMath;
@@ -66,7 +67,7 @@ public class LootFunction implements Function<Void> {
String id = data.apply(implementationArguments, variableMap); String id = data.apply(implementationArguments, variableMap);
registry.get(id) registry.get(RegistryKey.parse(id))
.ifPresentOrElse(table -> { .ifPresentOrElse(table -> {
Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()), Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()),
y.apply(implementationArguments, variableMap) y.apply(implementationArguments, variableMap)
@@ -9,10 +9,13 @@ package com.dfsek.terra.addons.terrascript.script.functions;
import com.dfsek.terra.addons.terrascript.script.StructureScript; import com.dfsek.terra.addons.terrascript.script.StructureScript;
import com.dfsek.terra.api.registry.key.RegistryKey;
import net.jafama.FastMath; import net.jafama.FastMath;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -68,7 +71,7 @@ public class StructureFunction implements Function<Boolean> {
String app = id.apply(implementationArguments, variableMap); String app = id.apply(implementationArguments, variableMap);
return registry.get(app).map(script -> { return registry.tryGet(app).map(script -> {
Rotation rotation1; Rotation rotation1;
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap); String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap);
try { try {
@@ -23,7 +23,7 @@ public class TerraScriptCheckFunctionAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.priority(1) .priority(1)
.then(event -> { .then(event -> {
event.getPack().getOrCreateRegistry(FunctionBuilder.class).register("check", new CheckFunctionBuilder(platform)); event.getPack().getOrCreateRegistry(FunctionBuilder.class).register(addon.getKey("check"), new CheckFunctionBuilder(platform));
}) })
.failThrough(); .failThrough();
} }
@@ -10,6 +10,8 @@ import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.registry.exception.NoSuchEntryException; import com.dfsek.terra.api.registry.exception.NoSuchEntryException;
import com.dfsek.terra.api.registry.key.RegistryKey;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@@ -92,12 +94,12 @@ public class RegistryArgument<T, R> extends CommandArgument<T, R> {
public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext, public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext,
@NonNull Queue<@NonNull String> inputQueue) { @NonNull Queue<@NonNull String> inputQueue) {
String input = inputQueue.remove(); String input = inputQueue.remove();
return registry.get(input).map(ArgumentParseResult::success).orElse(ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + input))); return registry.get(RegistryKey.parse(input)).map(ArgumentParseResult::success).orElse(ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + input)));
} }
@Override @Override
public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext<T> commandContext, @NonNull String input) { public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext<T> commandContext, @NonNull String input) {
return registry.keys().stream().sorted().collect(Collectors.toList()); return registry.keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList());
} }
} }
} }
@@ -15,7 +15,9 @@ import java.util.Map;
import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.Namespaced; import com.dfsek.terra.api.registry.key.Namespaced;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.registry.meta.RegistryHolder; import com.dfsek.terra.api.registry.meta.RegistryHolder;
import com.dfsek.terra.api.tectonic.ConfigLoadingDelegate; import com.dfsek.terra.api.tectonic.ConfigLoadingDelegate;
import com.dfsek.terra.api.tectonic.LoaderRegistrar; import com.dfsek.terra.api.tectonic.LoaderRegistrar;
@@ -27,9 +29,9 @@ import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider;
public interface ConfigPack extends LoaderRegistrar, ConfigLoadingDelegate, RegistryHolder, StringIdentifiable, Namespaced { public interface ConfigPack extends LoaderRegistrar, ConfigLoadingDelegate, RegistryHolder, Keyed {
ConfigPack registerConfigType(ConfigType<?, ?> type, String id, int priority); ConfigPack registerConfigType(ConfigType<?, ?> type, RegistryKey id, int priority);
Map<BaseAddon, VersionRange> addons(); Map<BaseAddon, VersionRange> addons();
@@ -7,6 +7,8 @@
package com.dfsek.terra.api.registry; package com.dfsek.terra.api.registry;
import com.dfsek.terra.api.registry.key.RegistryKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException; import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
@@ -21,5 +23,5 @@ public interface CheckedRegistry<T> extends Registry<T> {
* *
* @throws DuplicateEntryException If an entry with the same identifier is already present. * @throws DuplicateEntryException If an entry with the same identifier is already present.
*/ */
void register(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException; void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
} }
@@ -7,6 +7,8 @@
package com.dfsek.terra.api.registry; package com.dfsek.terra.api.registry;
import com.dfsek.terra.api.registry.key.RegistryKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException; import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
@@ -19,7 +21,7 @@ public interface OpenRegistry<T> extends Registry<T> {
* @param identifier Identifier to assign value. * @param identifier Identifier to assign value.
* @param value Value to register. * @param value Value to register.
*/ */
boolean register(@NotNull String identifier, @NotNull T value); boolean register(@NotNull RegistryKey identifier, @NotNull T value);
/** /**
* Add a value to this registry, checking whether it is present first. * Add a value to this registry, checking whether it is present first.
@@ -29,7 +31,7 @@ public interface OpenRegistry<T> extends Registry<T> {
* *
* @throws DuplicateEntryException If an entry with the same identifier is already present. * @throws DuplicateEntryException If an entry with the same identifier is already present.
*/ */
void registerChecked(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException; void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
/** /**
* Clears all entries from the registry. * Clears all entries from the registry.
@@ -9,39 +9,41 @@ package com.dfsek.terra.api.registry;
import com.dfsek.tectonic.api.loader.type.TypeLoader; import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import com.google.common.reflect.TypeToken;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
public interface Registry<T> extends TypeLoader<T> { public interface Registry<T> extends TypeLoader<T> {
/** /**
* Get a value from the registry. * Get a value from the registry.
* *
* @param identifier Identifier of value. * @param key Identifier of value.
* *
* @return Value matching the identifier, {@code null} if no value is present. * @return Value matching the identifier, {@code null} if no value is present.
*/ */
@Contract(pure = true) @Contract(pure = true)
Optional<T> get(@NotNull String identifier); Optional<T> get(@NotNull RegistryKey key);
/** /**
* Check if the registry contains a value. * Check if the registry contains a value.
* *
* @param identifier Identifier of value. * @param key Identifier of value.
* *
* @return Whether the registry contains the value. * @return Whether the registry contains the value.
*/ */
@Contract(pure = true) @Contract(pure = true)
boolean contains(@NotNull String identifier); boolean contains(@NotNull RegistryKey key);
/** /**
* Perform the given action for every value in the registry. * Perform the given action for every value in the registry.
@@ -55,7 +57,7 @@ public interface Registry<T> extends TypeLoader<T> {
* *
* @param consumer Action to perform on pair. * @param consumer Action to perform on pair.
*/ */
void forEach(@NotNull BiConsumer<String, T> consumer); void forEach(@NotNull BiConsumer<RegistryKey, T> consumer);
/** /**
* Get the entries of this registry as a {@link Set}. * Get the entries of this registry as a {@link Set}.
@@ -73,7 +75,30 @@ public interface Registry<T> extends TypeLoader<T> {
*/ */
@NotNull @NotNull
@Contract(pure = true) @Contract(pure = true)
Set<String> keys(); Set<RegistryKey> keys();
TypeKey<T> getType(); TypeKey<T> getType();
default Optional<T> tryGet(String attempt) {
return get(attempt, map -> {
if(map.isEmpty()) return Optional.empty();
if(map.size() == 1) {
return map.values().stream().findFirst(); // only one value.
}
throw new IllegalArgumentException("ID \"" + attempt + "\" is ambiguous; matches: " + map
.keySet()
.stream()
.map(RegistryKey::toString)
.reduce("", (a, b) -> a + "\n - " + b));
});
}
Map<RegistryKey, T> get(String id);
default Optional<T> get(String attempt, Function<Map<RegistryKey, T>, Optional<T>> reduction) {
if(attempt.contains(":")) {
return get(RegistryKey.parse(attempt));
}
return reduction.apply(get(attempt));
}
} }
@@ -0,0 +1,15 @@
package com.dfsek.terra.api.registry.key;
public interface Keyed extends Namespaced, StringIdentifiable {
RegistryKey getRegistryKey();
@Override
default String getNamespace() {
return getRegistryKey().getNamespace();
}
@Override
default String getID() {
return getRegistryKey().getID();
}
}
@@ -3,17 +3,7 @@ package com.dfsek.terra.api.registry.key;
public interface Namespaced { public interface Namespaced {
String getNamespace(); String getNamespace();
default RegistryKey getKey(String key) { default RegistryKey getKey(String id) {
return new RegistryKey() { return RegistryKey.of(getNamespace(), id);
@Override
public String getNamespace() {
return Namespaced.this.getNamespace();
}
@Override
public String getID() {
return key;
}
};
} }
} }
@@ -1,5 +1,70 @@
package com.dfsek.terra.api.registry.key; package com.dfsek.terra.api.registry.key;
public interface RegistryKey extends StringIdentifiable, Namespaced { import java.util.Objects;
import java.util.regex.Pattern;
public final class RegistryKey implements StringIdentifiable, Namespaced {
private static final Pattern ID_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]*$");
private final String namespace;
private final String id;
private RegistryKey(String namespace, String id) {
if(!ID_PATTERN.matcher(namespace).matches()) {
throw new IllegalArgumentException(
"Namespace must only contain alphanumeric characters, hyphens, and underscores. \"" + namespace +
"\" is not a valid namespace.");
}
if(!ID_PATTERN.matcher(id).matches()) {
throw new IllegalArgumentException(
"ID must only contain alphanumeric characters, hyphens, and underscores. \"" + id +
"\" is not a valid ID.");
}
this.namespace = namespace;
this.id = id;
}
public static RegistryKey parse(String key) {
if(key.chars().filter(c -> c == ':').count() != 1) {
throw new IllegalArgumentException("Malformed RegistryKey: " + key);
}
String namespace = key.substring(0, key.indexOf(":"));
String id = key.substring(key.indexOf(":") + 1);
return new RegistryKey(namespace, id);
}
public static RegistryKey of(String namespace, String id) {
return new RegistryKey(namespace, id);
}
@Override
public String getNamespace() {
return namespace;
}
@Override
public String getID() {
return id;
}
@Override
public int hashCode() {
return Objects.hash(namespace, id);
}
@Override
public boolean equals(Object obj) {
if(obj instanceof RegistryKey that) {
return this.id.equals(that.id) && this.namespace.equals(that.namespace);
}
return false;
}
@Override
public String toString() {
return namespace + ":" + id;
}
} }
@@ -209,7 +209,7 @@ public abstract class AbstractPlatform implements Platform {
platformInjector.inject(addon); platformInjector.inject(addon);
addon.initialize(); addon.initialize();
if(!(addon instanceof EphemeralAddon)) { // ephemeral addons exist only for version checking if(!(addon instanceof EphemeralAddon)) { // ephemeral addons exist only for version checking
addonRegistry.register(addon.getID(), addon); addonRegistry.register(addon.getKey(addon.getID()), addon);
} }
}); });
@@ -30,6 +30,8 @@ import java.util.function.Supplier;
import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.registry.Registry;
import org.jetbrains.annotations.NotNull;
public class GenericTemplateSupplierLoader<T> implements TypeLoader<T> { public class GenericTemplateSupplierLoader<T> implements TypeLoader<T> {
private final Registry<Supplier<ObjectTemplate<T>>> registry; private final Registry<Supplier<ObjectTemplate<T>>> registry;
@@ -40,12 +42,11 @@ public class GenericTemplateSupplierLoader<T> implements TypeLoader<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public T load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public T load(@NotNull AnnotatedType t, @NotNull Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> map = (Map<String, Object>) c; Map<String, Object> map = (Map<String, Object>) c;
try { try {
return loader return loader
.load(registry .load(registry.tryGet(((String) map.get("type")))
.get(((String) map.get("type")))
.orElseThrow(() -> new LoadException("No such entry: " + map.get("type"))) .orElseThrow(() -> new LoadException("No such entry: " + map.get("type")))
.get(), new MapConfiguration(map)).get(); .get(), new MapConfiguration(map)).get();
} catch(ConfigException e) { } catch(ConfigException e) {
@@ -27,6 +27,9 @@ import com.dfsek.tectonic.api.loader.AbstractConfigLoader;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader; import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.tectonic.yaml.YamlConfiguration; import com.dfsek.tectonic.yaml.YamlConfiguration;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -115,10 +118,9 @@ public class ConfigPackImpl implements ConfigPack {
private final Map<Type, ShortcutHolder<?>> shortcuts = new HashMap<>(); private final Map<Type, ShortcutHolder<?>> shortcuts = new HashMap<>();
private final OpenRegistry<ConfigType<?, ?>> configTypeRegistry; private final OpenRegistry<ConfigType<?, ?>> configTypeRegistry;
private final TreeMap<Integer, List<Pair<String, ConfigType<?, ?>>>> configTypes = new TreeMap<>(); private final TreeMap<Integer, List<Pair<RegistryKey, ConfigType<?, ?>>>> configTypes = new TreeMap<>();
private final String namespace; private final RegistryKey key;
private final String id;
public ConfigPackImpl(File folder, Platform platform) { public ConfigPackImpl(File folder, Platform platform) {
this(new FolderLoader(folder.toPath()), Construct.construct(() -> { this(new FolderLoader(folder.toPath()), Construct.construct(() -> {
@@ -175,14 +177,18 @@ public class ConfigPackImpl implements ConfigPack {
selfLoader.load(template, packManifest); selfLoader.load(template, packManifest);
String namespace;
String id;
if(template.getID().contains(":")) { if(template.getID().contains(":")) {
this.namespace = template.getID().substring(0, template.getID().indexOf(":")); namespace = template.getID().substring(0, template.getID().indexOf(":"));
this.id = template.getID().substring(template.getID().indexOf(":") + 1); id = template.getID().substring(template.getID().indexOf(":") + 1);
} else { } else {
this.id = template.getID(); id = template.getID();
this.namespace = template.getID(); namespace = template.getID();
} }
this.key = RegistryKey.of(namespace, id);
logger.info("Loading config pack \"{}:{}\"", id, namespace); logger.info("Loading config pack \"{}:{}\"", id, namespace);
configTypes.values().forEach(list -> list.forEach(pair -> configTypeRegistry.register(pair.getLeft(), pair.getRight()))); configTypes.values().forEach(list -> list.forEach(pair -> configTypeRegistry.register(pair.getLeft(), pair.getRight())));
@@ -214,7 +220,7 @@ public class ConfigPackImpl implements ConfigPack {
return Pair.of(configuration.getID(), loaded); return Pair.of(configuration.getID(), loaded);
}) })
.toList() .toList()
.forEach(pair -> registry.register(pair.getLeft(), pair.getRight())); .forEach(pair -> registry.register(getKey(pair.getLeft()), pair.getRight()));
platform.getEventManager().callEvent(new ConfigTypePostLoadEvent(configType, registry, this)); platform.getEventManager().callEvent(new ConfigTypePostLoadEvent(configType, registry, this));
}); });
@@ -282,13 +288,13 @@ public class ConfigPackImpl implements ConfigPack {
} }
@Override @Override
public ConfigPack registerConfigType(ConfigType<?, ?> type, String id, int priority) { public ConfigPack registerConfigType(ConfigType<?, ?> type, RegistryKey key, int priority) {
Set<String> contained = new HashSet<>(); Set<RegistryKey> contained = new HashSet<>();
configTypes.forEach((p, configs) -> configs.forEach(pair -> { configTypes.forEach((p, configs) -> configs.forEach(pair -> {
if(contained.contains(pair.getLeft())) throw new IllegalArgumentException("Duplicate config ID: " + id); if(contained.contains(pair.getLeft())) throw new IllegalArgumentException("Duplicate config key: " + key);
contained.add(id); contained.add(key);
})); }));
configTypes.computeIfAbsent(priority, p -> new ArrayList<>()).add(Pair.of(id, type)); configTypes.computeIfAbsent(priority, p -> new ArrayList<>()).add(Pair.of(key, type));
return this; return this;
} }
@@ -374,7 +380,7 @@ public class ConfigPackImpl implements ConfigPack {
private OpenRegistry<ConfigType<?, ?>> createConfigRegistry() { private OpenRegistry<ConfigType<?, ?>> createConfigRegistry() {
return new OpenRegistryImpl<>(new LinkedHashMap<>(), CONFIG_TYPE_TYPE_KEY) { return new OpenRegistryImpl<>(new LinkedHashMap<>(), CONFIG_TYPE_TYPE_KEY) {
@Override @Override
public boolean register(@NotNull String identifier, @NotNull ConfigType<?, ?> value) { public boolean register(@NotNull RegistryKey key, @NotNull ConfigType<?, ?> value) {
if(!registryMap if(!registryMap
.containsKey(value.getTypeKey() .containsKey(value.getTypeKey()
.getType())) { .getType())) {
@@ -383,7 +389,7 @@ public class ConfigPackImpl implements ConfigPack {
abstractConfigLoader.registerLoader(value.getTypeKey().getType(), openRegistry); abstractConfigLoader.registerLoader(value.getTypeKey().getType(), openRegistry);
registryMap.put(value.getTypeKey().getType(), new CheckedRegistryImpl<>(openRegistry)); registryMap.put(value.getTypeKey().getType(), new CheckedRegistryImpl<>(openRegistry));
} }
return super.register(identifier, value); return super.register(key, value);
} }
}; };
} }
@@ -411,12 +417,7 @@ public class ConfigPackImpl implements ConfigPack {
} }
@Override @Override
public String getID() { public RegistryKey getRegistryKey() {
return id; return key;
}
@Override
public String getNamespace() {
return namespace;
} }
} }
@@ -20,6 +20,7 @@ package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.ApiStatus.Internal;
@@ -27,6 +28,7 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@@ -55,18 +57,18 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
} }
@Override @Override
public void register(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException { public void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException {
registry.registerChecked(identifier, value); registry.registerChecked(identifier, value);
} }
@Override @Override
public Optional<T> get(@NotNull String identifier) { public Optional<T> get(@NotNull RegistryKey key) {
return registry.get(identifier); return registry.get(key);
} }
@Override @Override
public boolean contains(@NotNull String identifier) { public boolean contains(@NotNull RegistryKey key) {
return registry.contains(identifier); return registry.contains(key);
} }
@Override @Override
@@ -75,7 +77,7 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
} }
@Override @Override
public void forEach(@NotNull BiConsumer<String, T> consumer) { public void forEach(@NotNull BiConsumer<RegistryKey, T> consumer) {
registry.forEach(consumer); registry.forEach(consumer);
} }
@@ -85,7 +87,7 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
} }
@Override @Override
public @NotNull Set<String> keys() { public @NotNull Set<RegistryKey> keys() {
return registry.keys(); return registry.keys();
} }
@@ -94,6 +96,11 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
return registry.getType(); return registry.getType();
} }
@Override
public Map<RegistryKey, T> get(String id) {
return registry.get(id);
}
@Override @Override
public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException { public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException {
return registry.load(t, c, loader); return registry.load(t, c, loader);
@@ -20,12 +20,14 @@ package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@@ -47,13 +49,13 @@ public class LockedRegistryImpl<T> implements Registry<T> {
} }
@Override @Override
public Optional<T> get(@NotNull String identifier) { public Optional<T> get(@NotNull RegistryKey key) {
return registry.get(identifier); return registry.get(key);
} }
@Override @Override
public boolean contains(@NotNull String identifier) { public boolean contains(@NotNull RegistryKey key) {
return registry.contains(identifier); return registry.contains(key);
} }
@Override @Override
@@ -62,7 +64,7 @@ public class LockedRegistryImpl<T> implements Registry<T> {
} }
@Override @Override
public void forEach(@NotNull BiConsumer<String, T> consumer) { public void forEach(@NotNull BiConsumer<RegistryKey, T> consumer) {
registry.forEach(consumer); registry.forEach(consumer);
} }
@@ -72,7 +74,7 @@ public class LockedRegistryImpl<T> implements Registry<T> {
} }
@Override @Override
public @NotNull Set<String> keys() { public @NotNull Set<RegistryKey> keys() {
return registry.keys(); return registry.keys();
} }
@@ -81,6 +83,11 @@ public class LockedRegistryImpl<T> implements Registry<T> {
return registry.getType(); return registry.getType();
} }
@Override
public Map<RegistryKey, T> get(String id) {
return registry.get(id);
}
@Override @Override
public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException { public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException {
return registry.load(t, c, loader); return registry.load(t, c, loader);
@@ -20,20 +20,25 @@ package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.dfsek.terra.api.registry.OpenRegistry; import com.dfsek.terra.api.registry.OpenRegistry;
@@ -47,36 +52,45 @@ import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
*/ */
public class OpenRegistryImpl<T> implements OpenRegistry<T> { public class OpenRegistryImpl<T> implements OpenRegistry<T> {
private static final Entry<?> NULL = new Entry<>(null); private static final Entry<?> NULL = new Entry<>(null);
private static final Pattern ID_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]*$"); private final Map<RegistryKey, Entry<T>> objects;
private final Map<String, Entry<T>> objects; private final ListMultimap<String, Pair<RegistryKey, Entry<T>>> objectIDs = Multimaps.newListMultimap(new HashMap<>(), ArrayList::new);
private final TypeKey<T> typeKey; private final TypeKey<T> typeKey;
public OpenRegistryImpl(TypeKey<T> typeKey) { public OpenRegistryImpl(TypeKey<T> typeKey) {
this(new HashMap<>(), typeKey); this(new HashMap<>(), typeKey);
} }
protected OpenRegistryImpl(Map<String, Entry<T>> init, TypeKey<T> typeKey) { protected OpenRegistryImpl(Map<RegistryKey, Entry<T>> init, TypeKey<T> typeKey) {
this.objects = init; this.objects = init;
this.typeKey = typeKey; this.typeKey = typeKey;
} }
@Override @Override
public T load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader) throws LoadException { public T load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader) throws LoadException {
return get((String) o).orElseThrow(() -> { return tryGet((String) o).orElseThrow(() -> new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o +
String list = objects.keySet().stream().sorted().reduce("", (a, b) -> a + "\n - " + b); "\" was found in this registry. Registry contains items: " +
if(objects.isEmpty()) list = "[ ]"; getItemsFormatted()));
return new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o + }
"\" was found in this registry. Registry contains items: " + list);
}); private String getItemsFormatted() {
if(objects.isEmpty()) {
return "[ ]";
}
return objects
.keySet()
.stream()
.map(RegistryKey::toString)
.sorted()
.reduce("", (a, b) -> a + "\n - " + b);
} }
@Override @Override
public boolean register(@NotNull String identifier, @NotNull T value) { public boolean register(@NotNull RegistryKey identifier, @NotNull T value) {
return register(identifier, new Entry<>(value)); return register(identifier, new Entry<>(value));
} }
@Override @Override
public void registerChecked(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException { public void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException {
if(objects.containsKey(identifier)) if(objects.containsKey(identifier))
throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry."); throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry.");
register(identifier, value); register(identifier, value);
@@ -87,25 +101,22 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
objects.clear(); objects.clear();
} }
public boolean register(String identifier, Entry<T> value) { private boolean register(RegistryKey identifier, Entry<T> value) {
if(!ID_PATTERN.matcher(identifier).matches())
throw new IllegalArgumentException(
"Registry ID must only contain alphanumeric characters, hyphens, and underscores. \"" + identifier +
"\" is not a valid ID.");
boolean exists = objects.containsKey(identifier); boolean exists = objects.containsKey(identifier);
objects.put(identifier, value); objects.put(identifier, value);
objectIDs.put(identifier.getID(), Pair.of(identifier, value));
return exists; return exists;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public Optional<T> get(@NotNull String identifier) { public Optional<T> get(@NotNull RegistryKey key) {
return Optional.ofNullable(objects.getOrDefault(identifier, (Entry<T>) NULL).getValue()); return Optional.ofNullable(objects.getOrDefault(key, (Entry<T>) NULL).getValue());
} }
@Override @Override
public boolean contains(@NotNull String identifier) { public boolean contains(@NotNull RegistryKey key) {
return objects.containsKey(identifier); return objects.containsKey(key);
} }
@Override @Override
@@ -114,7 +125,7 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
} }
@Override @Override
public void forEach(@NotNull BiConsumer<String, T> consumer) { public void forEach(@NotNull BiConsumer<RegistryKey, T> consumer) {
objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw())); objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw()));
} }
@@ -124,7 +135,7 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
} }
@Override @Override
public @NotNull Set<String> keys() { public @NotNull Set<RegistryKey> keys() {
return objects.keySet(); return objects.keySet();
} }
@@ -133,8 +144,16 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
return typeKey; return typeKey;
} }
public Map<String, T> getDeadEntries() { @Override
Map<String, T> dead = new HashMap<>(); public Map<RegistryKey, T> get(String id) {
return objectIDs
.get(id)
.stream()
.collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), pair.getRight().getValue()), Map::putAll);
}
public Map<RegistryKey, T> getDeadEntries() {
Map<RegistryKey, T> dead = new HashMap<>();
objects.forEach((id, entry) -> { objects.forEach((id, entry) -> {
if(entry.dead()) dead.put(id, entry.value); // dont increment value here. if(entry.dead()) dead.put(id, entry.value); // dont increment value here.
}); });
@@ -142,7 +161,7 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
} }
protected static final class Entry<T> { private static final class Entry<T> {
private final T value; private final T value;
private final AtomicInteger access = new AtomicInteger(0); private final AtomicInteger access = new AtomicInteger(0);
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
@@ -46,14 +47,14 @@ public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
public void load(File folder, Platform platform) throws ConfigException { public void load(File folder, Platform platform) throws ConfigException {
ConfigPack pack = new ConfigPackImpl(folder, platform); ConfigPack pack = new ConfigPackImpl(folder, platform);
register(pack.getID(), pack); register(pack.getRegistryKey(), pack);
} }
public boolean loadAll(Platform platform) { public boolean loadAll(Platform platform) {
boolean valid = true; boolean valid = true;
File packsFolder = new File(platform.getDataFolder(), "packs"); File packsFolder = new File(platform.getDataFolder(), "packs");
packsFolder.mkdirs(); packsFolder.mkdirs();
for(File dir : packsFolder.listFiles(File::isDirectory)) { for(File dir : Objects.requireNonNull(packsFolder.listFiles(File::isDirectory))) {
try { try {
load(dir, platform); load(dir, platform);
} catch(ConfigException e) { } catch(ConfigException e) {
@@ -61,7 +62,8 @@ public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
valid = false; valid = false;
} }
} }
for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra"))) { for(File zip : Objects.requireNonNull(
packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra")))) {
try { try {
logger.info("Loading ZIP archive: {}", zip.getName()); logger.info("Loading ZIP archive: {}", zip.getName());
load(new ZipFile(zip), platform); load(new ZipFile(zip), platform);
@@ -75,6 +77,6 @@ public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
public void load(ZipFile file, Platform platform) throws ConfigException { public void load(ZipFile file, Platform platform) throws ConfigException {
ConfigPackImpl pack = new ConfigPackImpl(file, platform); ConfigPackImpl pack = new ConfigPackImpl(file, platform);
register(pack.getTemplate().getID(), pack); register(pack.getRegistryKey(), pack);
} }
} }
@@ -24,7 +24,7 @@ import com.dfsek.terra.api.entity.CommandSender;
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
import com.dfsek.terra.api.util.generic.Construct; import com.dfsek.terra.fabric.data.Codecs;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
@@ -33,9 +33,6 @@ import net.minecraft.util.registry.Registry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
public class FabricEntryPoint implements ModInitializer { public class FabricEntryPoint implements ModInitializer {
private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class); private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class);
@@ -51,8 +48,8 @@ public class FabricEntryPoint implements ModInitializer {
public void onInitialize() { public void onInitialize() {
logger.info("Initializing Terra Fabric mod..."); logger.info("Initializing Terra Fabric mod...");
// register the things // register the things
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC); Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE);
FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>( FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>(
CommandExecutionCoordinator.simpleCoordinator(), CommandExecutionCoordinator.simpleCoordinator(),
@@ -74,7 +74,7 @@ public class PlatformImpl extends AbstractPlatform {
worlds.forEach(world -> { worlds.forEach(world -> {
FabricChunkGeneratorWrapper chunkGeneratorWrapper = ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()); FabricChunkGeneratorWrapper chunkGeneratorWrapper = ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator());
chunkGeneratorWrapper.setPack(getConfigRegistry().get(chunkGeneratorWrapper.getPack().getID()).orElseThrow()); chunkGeneratorWrapper.setPack(getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).orElseThrow());
}); });
return succeed; return succeed;
@@ -0,0 +1,58 @@
package com.dfsek.terra.fabric.data;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.dynamic.RegistryLookupCodec;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
public final class Codecs {
public static final Codec<RegistryKey> REGISTRY_KEY = RecordCodecBuilder
.create(registryKey -> registryKey.group(Codec.STRING.fieldOf("namespace")
.forGetter(RegistryKey::getNamespace),
Codec.STRING.fieldOf("id")
.forGetter(RegistryKey::getID))
.apply(registryKey, registryKey.stable(RegistryKey::of)));
public static final Codec<ConfigPack> CONFIG_PACK = RecordCodecBuilder
.create(config -> config.group(REGISTRY_KEY.fieldOf("pack")
.forGetter(ConfigPack::getRegistryKey))
.apply(config, config.stable(id -> FabricEntryPoint.getPlatform()
.getConfigRegistry()
.get(id)
.orElseThrow(() -> new IllegalArgumentException(
"No such config pack " +
id)))));
public static final Codec<TerraBiomeSource> TERRA_BIOME_SOURCE = RecordCodecBuilder
.create(instance -> instance.group(RegistryLookupCodec.of(Registry.BIOME_KEY)
.forGetter(TerraBiomeSource::getBiomeRegistry),
Codec.LONG.fieldOf("seed").stable()
.forGetter(TerraBiomeSource::getSeed),
CONFIG_PACK.fieldOf("pack").stable()
.forGetter(TerraBiomeSource::getPack))
.apply(instance, instance.stable(
TerraBiomeSource::new)));
public static final Codec<FabricChunkGeneratorWrapper> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
TERRA_BIOME_SOURCE.fieldOf("biome_source")
.forGetter(FabricChunkGeneratorWrapper::getBiomeSource),
Codec.LONG.fieldOf("seed").stable()
.forGetter(FabricChunkGeneratorWrapper::getSeed),
CONFIG_PACK.fieldOf("pack").stable()
.forGetter(FabricChunkGeneratorWrapper::getPack),
ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings")
.forGetter(FabricChunkGeneratorWrapper::getSettingsSupplier)
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
);
}
@@ -18,19 +18,17 @@
package com.dfsek.terra.fabric.generation; package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.fabric.FabricEntryPoint; import com.dfsek.terra.fabric.data.Codecs;
import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor;
import com.dfsek.terra.fabric.util.FabricAdapter; import com.dfsek.terra.fabric.util.FabricAdapter;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnGroup;
import net.minecraft.util.collection.Pool; import net.minecraft.util.collection.Pool;
@@ -61,30 +59,7 @@ import java.util.function.Supplier;
public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper {
public static final Codec<ConfigPack> PACK_CODEC = RecordCodecBuilder.create(
config -> config.group(
Codec.STRING.fieldOf("pack")
.forGetter(ConfigPack::getID)
).apply(config, config.stable(id -> FabricEntryPoint.getPlatform()
.getConfigRegistry()
.get(id)
.orElseThrow(
() -> new IllegalArgumentException(
"No such config pack " +
id)))));
private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class);
public static final Codec<FabricChunkGeneratorWrapper> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
TerraBiomeSource.CODEC.fieldOf("biome_source")
.forGetter(generator -> generator.biomeSource),
Codec.LONG.fieldOf("seed").stable()
.forGetter(generator -> generator.seed),
PACK_CODEC.fieldOf("pack").stable()
.forGetter(generator -> generator.pack),
ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings")
.forGetter(generator -> generator.settingsSupplier)
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
);
private final long seed; private final long seed;
private final TerraBiomeSource biomeSource; private final TerraBiomeSource biomeSource;
@@ -107,7 +82,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
@Override @Override
protected Codec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() { protected Codec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() {
return CODEC; return Codecs.CODEC;
} }
@Override @Override
@@ -251,4 +226,17 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
public ChunkGenerator getHandle() { public ChunkGenerator getHandle() {
return delegate; return delegate;
} }
public long getSeed() {
return seed;
}
public Supplier<ChunkGeneratorSettings> getSettingsSupplier() {
return settingsSupplier;
}
@Override
public TerraBiomeSource getBiomeSource() {
return biomeSource;
}
} }
@@ -17,47 +17,33 @@
package com.dfsek.terra.fabric.generation; package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.fabric.data.Codecs;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.RegistryLookupCodec;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.source.BiomeSource; import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.util.FabricUtil; import com.dfsek.terra.fabric.util.FabricUtil;
public class TerraBiomeSource extends BiomeSource { public class TerraBiomeSource extends BiomeSource {
public static final Codec<ConfigPack> PACK_CODEC = (RecordCodecBuilder.create(config -> config.group(
Codec.STRING.fieldOf("pack").forGetter(ConfigPack::getID)
)
.apply(config, config.stable(
id -> FabricEntryPoint.getPlatform()
.getConfigRegistry()
.get(id)
.orElseThrow(
() -> new IllegalArgumentException(
"No such config pack " +
id))))));
public static final Codec<TerraBiomeSource> CODEC = RecordCodecBuilder.create(instance -> instance.group(
RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry),
Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed),
PACK_CODEC.fieldOf("pack").stable().forGetter(source -> source.pack))
.apply(instance, instance.stable(
TerraBiomeSource::new)));
private final Registry<net.minecraft.world.biome.Biome> biomeRegistry; private final Registry<net.minecraft.world.biome.Biome> biomeRegistry;
private final long seed; private final long seed;
private ConfigPack pack; private ConfigPack pack;
private final Map<Biome, net.minecraft.world.biome.Biome> terraToMinecraft = new HashMap<>();
public TerraBiomeSource(Registry<net.minecraft.world.biome.Biome> biomes, long seed, ConfigPack pack) { public TerraBiomeSource(Registry<net.minecraft.world.biome.Biome> biomes, long seed, ConfigPack pack) {
super(biomes.stream() super(biomes.stream()
.filter(biome -> Objects.requireNonNull(biomes.getId(biome)) .filter(biome -> Objects.requireNonNull(biomes.getId(biome))
@@ -75,7 +61,7 @@ public class TerraBiomeSource extends BiomeSource {
@Override @Override
protected Codec<? extends BiomeSource> getCodec() { protected Codec<? extends BiomeSource> getCodec() {
return CODEC; return Codecs.TERRA_BIOME_SOURCE;
} }
@Override @Override
@@ -86,10 +72,23 @@ public class TerraBiomeSource extends BiomeSource {
@Override @Override
public net.minecraft.world.biome.Biome getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) { public net.minecraft.world.biome.Biome getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) {
Biome biome = pack.getBiomeProvider().getBiome(biomeX << 2, biomeZ << 2, seed); Biome biome = pack.getBiomeProvider().getBiome(biomeX << 2, biomeZ << 2, seed);
return biomeRegistry.get(new Identifier("terra", FabricUtil.createBiomeID(pack, biome.getID()))); return terraToMinecraft.computeIfAbsent(biome, b -> biomeRegistry
.get(new Identifier("terra", FabricUtil.createBiomeID(pack, pack.getKey(b.getID())))));
} }
public BiomeProvider getProvider() { public BiomeProvider getProvider() {
return pack.getBiomeProvider(); return pack.getBiomeProvider();
} }
public Registry<net.minecraft.world.biome.Biome> getBiomeRegistry() {
return biomeRegistry;
}
public ConfigPack getPack() {
return pack;
}
public long getSeed() {
return seed;
}
} }
@@ -85,7 +85,7 @@ public abstract class GeneratorOptionsMixin {
prop = prop.substring(prop.indexOf(":") + 1); prop = prop.substring(prop.indexOf(":") + 1);
String finalProp = prop; String finalProp = prop;
ConfigPack config = main.getConfigRegistry().get(prop).orElseThrow(() -> new IllegalArgumentException( ConfigPack config = main.getConfigRegistry().tryGet(prop).orElseThrow(() -> new IllegalArgumentException(
"No such pack " + finalProp)); "No such pack " + finalProp));
cir.setReturnValue( cir.setReturnValue(
@@ -54,8 +54,9 @@ public final class FabricUtil {
private static final Map<RegistryKey<net.minecraft.world.biome.Biome>, List<RegistryKey<net.minecraft.world.biome.Biome>>> private static final Map<RegistryKey<net.minecraft.world.biome.Biome>, List<RegistryKey<net.minecraft.world.biome.Biome>>>
terraVanillaBiomes = new HashMap<>(); terraVanillaBiomes = new HashMap<>();
public static String createBiomeID(ConfigPack pack, String biomeID) { public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
return pack.getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); return pack.getID()
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
} }
/** /**
@@ -64,7 +65,8 @@ public final class FabricUtil {
* @param biome The Terra BiomeBuilder. * @param biome The Terra BiomeBuilder.
* @param pack The ConfigPack this biome belongs to. * @param pack The ConfigPack this biome belongs to.
*/ */
public static void registerBiome(Biome biome, ConfigPack pack, DynamicRegistryManager registryManager, String id) { public static void registerBiome(Biome biome, ConfigPack pack, DynamicRegistryManager registryManager,
com.dfsek.terra.api.registry.key.RegistryKey id) {
// BiomeTemplate template = biome.getTemplate(); // BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = new HashMap<>(); // template.getColors(); Map<String, Integer> colors = new HashMap<>(); // template.getColors();