implement new tectonic depthtracker API

This commit is contained in:
dfsek
2021-12-27 23:01:48 -07:00
parent 8d7468457f
commit ea5dd297cb
38 changed files with 224 additions and 129 deletions
+1 -1
View File
@@ -13,6 +13,6 @@ dependencies {
implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:+") implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:+")
implementation("org.ow2.asm:asm:9.2") implementation("org.ow2.asm:asm:9.2")
implementation("org.ow2.asm:asm-tree:9.2") implementation("org.ow2.asm:asm-tree:9.2")
implementation("com.dfsek.tectonic:common:3.1.0") implementation("com.dfsek.tectonic:common:4.2.0")
implementation("org.yaml:snakeyaml:1.27") implementation("org.yaml:snakeyaml:1.27")
} }
+1 -1
View File
@@ -1,6 +1,6 @@
object Versions { object Versions {
object Libraries { object Libraries {
const val tectonic = "4.0.0" const val tectonic = "4.2.0"
const val paralithic = "0.6.0" const val paralithic = "0.6.0"
const val strata = "1.1.1" const val strata = "1.1.1"
@@ -1,5 +1,6 @@
package com.dfsek.terra.addons.biome.pipeline.config; package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -21,7 +22,7 @@ public class BiomeDelegateLoader implements TypeLoader<BiomeDelegate> {
} }
@Override @Override
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, DepthTracker depthTracker) throws LoadException {
if(c.equals("SELF")) return BiomeDelegate.self(); if(c.equals("SELF")) return BiomeDelegate.self();
return biomeRegistry return biomeRegistry
.getByID((String) c) .getByID((String) c)
@@ -7,6 +7,7 @@
package com.dfsek.terra.addons.biome.holder; package com.dfsek.terra.addons.biome.holder;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -17,16 +18,18 @@ import java.util.Map;
import com.dfsek.terra.api.world.chunk.generation.util.Palette; import com.dfsek.terra.api.world.chunk.generation.util.Palette;
import org.jetbrains.annotations.NotNull;
public class PaletteHolderLoader implements TypeLoader<PaletteHolder> { public class PaletteHolderLoader implements TypeLoader<PaletteHolder> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public PaletteHolder load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException { public PaletteHolder load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) throws LoadException {
List<Map<String, Integer>> palette = (List<Map<String, Integer>>) o; List<Map<String, Integer>> palette = (List<Map<String, Integer>>) o;
PaletteHolderBuilder builder = new PaletteHolderBuilder(); PaletteHolderBuilder builder = new PaletteHolderBuilder();
for(Map<String, Integer> layer : palette) { for(Map<String, Integer> layer : palette) {
for(Map.Entry<String, Integer> entry : layer.entrySet()) { for(Map.Entry<String, Integer> entry : layer.entrySet()) {
builder.add(entry.getValue(), configLoader.loadType(Palette.class, entry.getKey())); builder.add(entry.getValue(), configLoader.loadType(Palette.class, entry.getKey(), depthTracker));
} }
} }
return builder.build(); return builder.build();
@@ -79,8 +79,8 @@ public class NoiseAddon implements AddonInitializer {
NOISE_SAMPLER_TOKEN); NOISE_SAMPLER_TOKEN);
event.getPack() event.getPack()
.applyLoader(CellularSampler.DistanceFunction.class, .applyLoader(CellularSampler.DistanceFunction.class,
(t, o, l) -> CellularSampler.DistanceFunction.valueOf((String) o)) (type, o, loader, depthTracker) -> CellularSampler.DistanceFunction.valueOf((String) o))
.applyLoader(CellularSampler.ReturnType.class, (t, o, l) -> CellularSampler.ReturnType.valueOf((String) o)) .applyLoader(CellularSampler.ReturnType.class, (type, o, loader, depthTracker) -> CellularSampler.ReturnType.valueOf((String) o))
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
.applyLoader(FunctionTemplate.class, FunctionTemplate::new); .applyLoader(FunctionTemplate.class, FunctionTemplate::new);
@@ -56,7 +56,7 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
Map<String, Function> noiseFunctionMap = generateFunctions(); Map<String, Function> noiseFunctionMap = generateFunctions();
return new ExpressionFunction(noiseFunctionMap, equation, vars); return new ExpressionFunction(noiseFunctionMap, equation, vars);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to parse expression.", e); throw new RuntimeException("Failed to parse expression.", e);
} }
} }
@@ -31,7 +31,7 @@ public class PaletteAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> { .then(event -> {
event.getPack().registerConfigType(new PaletteConfigType(platform), addon.key("PALETTE"), 2); event.getPack().registerConfigType(new PaletteConfigType(platform), addon.key("PALETTE"), 2);
event.getPack().applyLoader(PaletteLayerHolder.class, new PaletteLayerLoader()); event.getPack().applyLoader(PaletteLayerHolder.class, PaletteLayerLoader::new);
}) })
.failThrough(); .failThrough();
} }
@@ -7,6 +7,10 @@
package com.dfsek.terra.addons.palette.palette; package com.dfsek.terra.addons.palette.palette;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -18,33 +22,22 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unchecked")
public class PaletteLayerLoader implements TypeLoader<PaletteLayerHolder> { public class PaletteLayerLoader implements ObjectTemplate<PaletteLayerHolder> {
private static final AnnotatedType BLOCK_DATA_PROBABILITY_COLLECTION_TYPE; @Value("materials")
static { private ProbabilityCollection<BlockState> collection;
try {
BLOCK_DATA_PROBABILITY_COLLECTION_TYPE = PaletteLayerLoader.class.getDeclaredField("blockStateProbabilityCollection") @Value("sampler")
.getAnnotatedType(); @Default
} catch(NoSuchFieldException e) { private NoiseSampler sampler = null;
throw new Error("this should never happen. i dont know what you did to make this happen but something is very wrong.", e);
} @Value("layers")
} private int layers;
@SuppressWarnings("unused")
private ProbabilityCollection<BlockState> blockStateProbabilityCollection;
@Override @Override
public PaletteLayerHolder load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException { public PaletteLayerHolder get() {
Map<String, Object> map = (Map<String, Object>) o; return new PaletteLayerHolder(collection, sampler, layers);
ProbabilityCollection<BlockState> collection = (ProbabilityCollection<BlockState>) configLoader.loadType(
BLOCK_DATA_PROBABILITY_COLLECTION_TYPE, map.get("materials"));
NoiseSampler sampler = null;
if(map.containsKey("sampler")) {
sampler = configLoader.loadType(NoiseSampler.class, map.get("sampler"));
}
if(collection == null) throw new LoadException("Collection is null: " + map.get("materials"));
return new PaletteLayerHolder(collection, sampler, (Integer) map.get("layers"));
} }
} }
@@ -10,20 +10,22 @@ package com.dfsek.terra.addons.manifest.impl.config.loaders;
import ca.solostudios.strata.Versions; import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version; import ca.solostudios.strata.version.Version;
import com.dfsek.tectonic.api.depth.DepthTracker;
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 org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
public class VersionLoader implements TypeLoader<Version> { public class VersionLoader implements TypeLoader<Version> {
@Override @Override
public Version load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public Version load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
try { try {
return Versions.parseVersion((String) c); return Versions.parseVersion((String) c);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to parse version", e); throw new LoadException("Failed to parse version", e, depthTracker);
} }
} }
} }
@@ -10,20 +10,22 @@ package com.dfsek.terra.addons.manifest.impl.config.loaders;
import ca.solostudios.strata.Versions; import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.VersionRange; import ca.solostudios.strata.version.VersionRange;
import com.dfsek.tectonic.api.depth.DepthTracker;
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 org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
public class VersionRangeLoader implements TypeLoader<VersionRange> { public class VersionRangeLoader implements TypeLoader<VersionRange> {
@Override @Override
public VersionRange load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public VersionRange load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
try { try {
return Versions.parseVersionRange((String) c); return Versions.parseVersionRange((String) c);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to parse version range", e); throw new LoadException("Failed to parse version range", e, depthTracker);
} }
} }
} }
@@ -23,7 +23,7 @@ public class PaletteBlockShortcutAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack() .then(event -> event.getPack()
.registerShortcut(Palette.class, "BLOCK", .registerShortcut(Palette.class, "BLOCK",
(configLoader, input) -> new SingletonPalette(configLoader.loadType(BlockState.class, input)))) (configLoader, input, tracker) -> new SingletonPalette(configLoader.loadType(BlockState.class, input, tracker))))
.failThrough(); .failThrough();
} }
} }
@@ -23,7 +23,7 @@ public class StructureBlockShortcutAddon implements AddonInitializer {
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack() .then(event -> event.getPack()
.registerShortcut(Structure.class, "BLOCK", .registerShortcut(Structure.class, "BLOCK",
(configLoader, input) -> new SingletonStructure(configLoader.loadType(BlockState.class, input) (configLoader, input, tracker) -> new SingletonStructure(configLoader.loadType(BlockState.class, input, tracker)
))) )))
.failThrough(); .failThrough();
} }
@@ -53,7 +53,7 @@ public class TerraScriptAddon implements AddonInitializer {
lootRegistry, lootRegistry,
event.getPack().getOrCreateRegistry(FunctionBuilder.class)); event.getPack().getOrCreateRegistry(FunctionBuilder.class));
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to load script \"" + entry.getKey() + "\"", e); throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e);
} }
}) })
.toList() .toList()
@@ -1,8 +1,9 @@
package com.dfsek.terra.api.tectonic; package com.dfsek.terra.api.tectonic;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
public interface ShortcutLoader<T> { public interface ShortcutLoader<T> {
T load(ConfigLoader configLoader, String input); T load(ConfigLoader configLoader, String input, DepthTracker tracker);
} }
@@ -57,9 +57,10 @@ public class GenericLoaders implements LoaderRegistrar {
if(platform != null) { if(platform != null) {
registry.registerLoader(BaseAddon.class, platform.getAddons()) registry.registerLoader(BaseAddon.class, platform.getAddons())
.registerLoader(BlockType.class, .registerLoader(BlockType.class, (type, object, configLoader, depthTracker) -> platform
(t, object, cf) -> platform.getWorldHandle().createBlockState((String) object).getBlockType()) .getWorldHandle().createBlockState((String) object).getBlockType())
.registerLoader(BlockState.class, (t, object, cf) -> platform.getWorldHandle().createBlockState((String) object)); .registerLoader(BlockState.class, (type, object, configLoader, depthTracker) -> platform
.getWorldHandle().createBlockState((String) object));
} }
} }
} }
@@ -18,6 +18,7 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.ConfigException; import com.dfsek.tectonic.api.exception.ConfigException;
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;
@@ -42,15 +43,13 @@ public class GenericTemplateSupplierLoader<T> implements TypeLoader<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public T load(@NotNull AnnotatedType t, @NotNull Object c, ConfigLoader loader) throws LoadException { public T load(@NotNull AnnotatedType t, @NotNull Object c, ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
Map<String, Object> map = (Map<String, Object>) c; Map<String, Object> map = (Map<String, Object>) c;
try { String type = (String) map.get("type");
return loader return loader
.load(registry.getByID(((String) map.get("type"))) .load(registry.getByID(type)
.orElseThrow(() -> new LoadException("No such entry: " + map.get("type"))) .orElseThrow(() -> new LoadException("No such entry: " + map.get("type"), depthTracker))
.get(), new MapConfiguration(map)).get(); .get(), new MapConfiguration(map), depthTracker.intrinsic("With type \"" + type + "\"")).get();
} catch(ConfigException e) {
throw new LoadException("Unable to load object: ", e);
}
} }
} }
@@ -17,9 +17,11 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.api.depth.DepthTracker;
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 org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
@@ -30,16 +32,17 @@ import java.util.Map;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class LinkedHashMapLoader implements TypeLoader<LinkedHashMap<Object, Object>> { public class LinkedHashMapLoader implements TypeLoader<LinkedHashMap<Object, Object>> {
@Override @Override
public LinkedHashMap<Object, Object> load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public LinkedHashMap<Object, Object> load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
Map<String, Object> config = (Map<String, Object>) c; Map<String, Object> config = (Map<String, Object>) c;
LinkedHashMap<Object, Object> map = new LinkedHashMap<>(); LinkedHashMap<Object, Object> map = new LinkedHashMap<>();
if(t instanceof AnnotatedParameterizedType pType) { if(t instanceof AnnotatedParameterizedType pType) {
AnnotatedType key = pType.getAnnotatedActualTypeArguments()[0]; AnnotatedType key = pType.getAnnotatedActualTypeArguments()[0];
AnnotatedType value = pType.getAnnotatedActualTypeArguments()[1]; AnnotatedType value = pType.getAnnotatedActualTypeArguments()[1];
for(Map.Entry<String, Object> entry : config.entrySet()) { for(Map.Entry<String, Object> entry : config.entrySet()) {
map.put(loader.loadType(key, entry.getKey()), loader.loadType(value, entry.getValue())); map.put(loader.loadType(key, entry.getKey(), depthTracker.entry(entry.getKey())),
loader.loadType(value, entry.getValue(), depthTracker.entry(entry.getKey())));
} }
} else throw new LoadException("Unable to load config"); } else throw new LoadException("Unable to load config", depthTracker);
return map; return map;
} }
@@ -17,6 +17,7 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -27,19 +28,21 @@ import java.util.List;
import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.util.collection.MaterialSet; import com.dfsek.terra.api.util.collection.MaterialSet;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class MaterialSetLoader implements TypeLoader<MaterialSet> { public class MaterialSetLoader implements TypeLoader<MaterialSet> {
@Override @Override
public MaterialSet load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException { public MaterialSet load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) throws LoadException {
List<String> stringData = (List<String>) o; List<String> stringData = (List<String>) o;
MaterialSet set = new MaterialSet(); MaterialSet set = new MaterialSet();
for(String string : stringData) { for(String string : stringData) {
try { try {
set.add(configLoader.loadType(BlockType.class, string)); set.add(configLoader.loadType(BlockType.class, string, depthTracker));
} catch(NullPointerException e) { } catch(NullPointerException e) {
throw new LoadException("Invalid data identifier \"" + string + "\"", e); throw new LoadException("Invalid data identifier \"" + string + "\"", e, depthTracker);
} }
} }
@@ -17,6 +17,7 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -25,38 +26,46 @@ import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ProbabilityCollectionLoader implements TypeLoader<ProbabilityCollection<Object>> { public class ProbabilityCollectionLoader implements TypeLoader<ProbabilityCollection<Object>> {
@Override @Override
public ProbabilityCollection<Object> load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException { public ProbabilityCollection<Object> load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader,
DepthTracker depthTracker) throws LoadException {
ProbabilityCollection<Object> collection = new ProbabilityCollection<>(); ProbabilityCollection<Object> collection = new ProbabilityCollection<>();
if(type instanceof AnnotatedParameterizedType pType) { if(type instanceof AnnotatedParameterizedType pType) {
AnnotatedType generic = pType.getAnnotatedActualTypeArguments()[0]; AnnotatedType generic = pType.getAnnotatedActualTypeArguments()[0];
if(o instanceof Map) { if(o instanceof Map) {
Map<Object, Integer> map = (Map<Object, Integer>) o; Map<Object, Object> map = (Map<Object, Object>) o;
for(Map.Entry<Object, Integer> entry : map.entrySet()) { for(Map.Entry<Object, Object> entry : map.entrySet()) {
collection.add(configLoader.loadType(generic, entry.getKey()), entry.getValue()); collection.add(configLoader.loadType(generic, entry.getKey(), depthTracker.entry((String) entry.getKey())),
configLoader.loadType(Integer.class, entry.getValue(), depthTracker.entry((String) entry.getKey())));
} }
} else if(o instanceof List) { } else if(o instanceof List) {
List<Map<Object, Integer>> map = (List<Map<Object, Integer>>) o; List<Map<Object, Object>> map = (List<Map<Object, Object>>) o;
for(Map<Object, Integer> l : map) { for(int i = 0; i < map.size(); i++) {
for(Map.Entry<Object, Integer> entry : l.entrySet()) { Map<Object, Object> l = map.get(i);
if(entry.getValue() == null) throw new LoadException("No probability defined for entry \"" + entry.getKey() + "\""); for(Entry<Object, Object> entry : l.entrySet()) {
Object val = configLoader.loadType(generic, entry.getKey()); if(entry.getValue() == null) throw new LoadException("No probability defined for entry \"" + entry.getKey() + "\"",
collection.add(val, entry.getValue()); depthTracker);
Object val = configLoader.loadType(generic, entry.getKey(), depthTracker.index(i).entry((String) entry.getKey()));
collection.add(val,
configLoader.loadType(Integer.class, entry.getValue(), depthTracker.entry((String) entry.getKey())));
} }
} }
} else if(o instanceof String) { } else if(o instanceof String) {
return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, o)); return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, o, depthTracker));
} else { } else {
throw new LoadException("Malformed Probability Collection: " + o); throw new LoadException("Malformed Probability Collection: " + o, depthTracker);
} }
} else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type); } else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type, depthTracker);
return collection; return collection;
@@ -17,6 +17,7 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -32,12 +33,12 @@ import com.dfsek.terra.api.util.Range;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class RangeLoader implements TypeLoader<Range> { public class RangeLoader implements TypeLoader<Range> {
@Override @Override
public Range load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader) throws LoadException { public Range load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) throws LoadException {
if(o instanceof Map) { if(o instanceof Map) {
Map<String, Integer> map = (Map<String, Integer>) o; Map<String, Integer> map = (Map<String, Integer>) o;
return new ConstantRange(map.get("min"), map.get("max")); return new ConstantRange(map.get("min"), map.get("max"));
} else { } else {
int h = configLoader.loadType(Integer.class, o); int h = configLoader.loadType(Integer.class, o, depthTracker);
return new ConstantRange(h, h + 1); return new ConstantRange(h, h + 1);
} }
} }
@@ -3,6 +3,7 @@ package com.dfsek.terra.config.loaders;
import ca.solostudios.strata.Versions; import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version; import ca.solostudios.strata.version.Version;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -13,11 +14,11 @@ import java.lang.reflect.AnnotatedType;
public class VersionLoader implements TypeLoader<Version> { public class VersionLoader implements TypeLoader<Version> {
@Override @Override
public Version load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader) throws LoadException { public Version load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
try { try {
return Versions.parseVersion((String) c); return Versions.parseVersion((String) c);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to parse version", e); throw new LoadException("Failed to parse version", e, depthTracker);
} }
} }
} }
@@ -20,20 +20,22 @@ package com.dfsek.terra.config.loaders;
import ca.solostudios.strata.Versions; import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.VersionRange; import ca.solostudios.strata.version.VersionRange;
import com.dfsek.tectonic.api.depth.DepthTracker;
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 org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
public class VersionRangeLoader implements TypeLoader<VersionRange> { public class VersionRangeLoader implements TypeLoader<VersionRange> {
@Override @Override
public VersionRange load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public VersionRange load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
try { try {
return Versions.parseVersionRange((String) c); return Versions.parseVersionRange((String) c);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Failed to parse version range: ", e); throw new LoadException("Failed to parse version range: ", e, depthTracker);
} }
} }
} }
@@ -17,6 +17,7 @@
package com.dfsek.terra.config.loaders.config; package com.dfsek.terra.config.loaders.config;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -28,6 +29,8 @@ import java.lang.reflect.AnnotatedType;
import com.dfsek.terra.api.config.Loader; import com.dfsek.terra.api.config.Loader;
import org.jetbrains.annotations.NotNull;
public class BufferedImageLoader implements TypeLoader<BufferedImage> { public class BufferedImageLoader implements TypeLoader<BufferedImage> {
private final Loader files; private final Loader files;
@@ -37,11 +40,11 @@ public class BufferedImageLoader implements TypeLoader<BufferedImage> {
} }
@Override @Override
public BufferedImage load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException { public BufferedImage load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) throws LoadException {
try { try {
return ImageIO.read(files.get((String) c)); return ImageIO.read(files.get((String) c));
} catch(IOException e) { } catch(IOException e) {
throw new LoadException("Unable to load image", e); throw new LoadException("Unable to load image", e, depthTracker);
} }
} }
} }
@@ -41,6 +41,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
@@ -127,7 +128,7 @@ public class ConfigPackImpl implements ConfigPack {
try { try {
return new YamlConfiguration(new FileInputStream(new File(folder, "pack.yml")), "pack.yml"); return new YamlConfiguration(new FileInputStream(new File(folder, "pack.yml")), "pack.yml");
} catch(FileNotFoundException e) { } catch(FileNotFoundException e) {
throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath()); throw new UncheckedIOException("No pack.yml file found in " + folder.getAbsolutePath(), e);
} }
}), platform); }), platform);
} }
@@ -141,12 +142,12 @@ public class ConfigPackImpl implements ConfigPack {
if(entry.getName().equals("pack.yml")) pack = entry; if(entry.getName().equals("pack.yml")) pack = entry;
} }
if(pack == null) throw new LoadException("No pack.yml file found in " + file.getName()); if(pack == null) throw new IllegalArgumentException("No pack.yml file found in " + file.getName());
try { try {
return new YamlConfiguration(file.getInputStream(pack), "pack.yml"); return new YamlConfiguration(file.getInputStream(pack), "pack.yml");
} catch(IOException e) { } catch(IOException e) {
throw new LoadException("Unable to load pack.yml from ZIP file", e); throw new UncheckedIOException("Unable to load pack.yml from ZIP file", e);
} }
}), platform); }), platform);
} }
@@ -18,9 +18,14 @@
package com.dfsek.terra.config.preprocessor; package com.dfsek.terra.config.preprocessor;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.depth.IndexLevel;
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.preprocessor.Result; import com.dfsek.tectonic.api.preprocessor.Result;
import com.dfsek.terra.api.util.generic.pair.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
@@ -28,6 +33,7 @@ import java.lang.reflect.ParameterizedType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.config.meta.Meta;
@@ -40,7 +46,7 @@ public class MetaListLikePreprocessor extends MetaPreprocessor<Meta> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) { public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) {
if(t.getType() instanceof ParameterizedType parameterizedType) { if(t.getType() instanceof ParameterizedType parameterizedType) {
if(parameterizedType.getRawType() instanceof Class<?> baseClass) { // Should always be true but we check anyways if(parameterizedType.getRawType() instanceof Class<?> baseClass) { // Should always be true but we check anyways
@@ -58,21 +64,40 @@ public class MetaListLikePreprocessor extends MetaPreprocessor<Meta> {
if(!s.startsWith("<< ")) continue; if(!s.startsWith("<< ")) continue;
String meta = s.substring(3); String meta = s.substring(3);
Object metaValue = getMetaValue(meta);
Pair<Configuration, Object> pair = getMetaValue(meta, depthTracker);
Object metaValue = pair.getRight();
if(!(metaValue instanceof List)) { if(!(metaValue instanceof List)) {
throw new LoadException( throw new LoadException(
"MetaList/Set injection candidate must be list, is type " + metaValue.getClass().getCanonicalName()); "MetaList/Set injection candidate must be list, is type " + metaValue.getClass().getCanonicalName(), depthTracker);
} }
List<Object> metaList = (List<Object>) metaValue; List<Object> metaList = (List<Object>) metaValue;
newList.remove(i + offset); // Remove placeholder newList.remove(i + offset); // Remove placeholder
newList.addAll(i + offset, metaList); // Add metalist values where placeholder was newList.addAll(i + offset, metaList); // Add metalist values where placeholder was
int begin = i + offset;
offset += metaList.size() - 1; // add metalist size to offset, subtract one to account for placeholder. offset += metaList.size() - 1; // add metalist size to offset, subtract one to account for placeholder.
int end = i + offset;
depthTracker.addIntrinsicLevel(level -> {
if(level instanceof IndexLevel indexLevel &&
indexLevel.getIndex() >= begin &&
indexLevel.getIndex() < end) {
String configName;
if(pair.getLeft().getName() == null) {
configName = "Anonymous Configuration";
} else {
configName = pair.getLeft().getName();
}
return Optional.of("From configuration \"" + configName + "\"");
}
return Optional.empty();
});
} }
return (Result<T>) Result.overwrite(newList); return (Result<T>) Result.overwrite(newList, depthTracker);
} }
} }
} }
@@ -18,9 +18,14 @@
package com.dfsek.terra.config.preprocessor; package com.dfsek.terra.config.preprocessor;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.depth.EntryLevel;
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.preprocessor.Result; import com.dfsek.tectonic.api.preprocessor.Result;
import com.dfsek.terra.api.util.generic.pair.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
@@ -28,6 +33,7 @@ import java.lang.reflect.ParameterizedType;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
@@ -43,7 +49,7 @@ public class MetaMapPreprocessor extends MetaPreprocessor<Meta> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) { public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) {
if(t.getType() instanceof ParameterizedType parameterizedType) { if(t.getType() instanceof ParameterizedType parameterizedType) {
if(parameterizedType.getRawType() instanceof Class<?> baseClass) { // Should always be true but we check anyways if(parameterizedType.getRawType() instanceof Class<?> baseClass) { // Should always be true but we check anyways
@@ -53,18 +59,33 @@ public class MetaMapPreprocessor extends MetaPreprocessor<Meta> {
if(map.containsKey("<<")) { if(map.containsKey("<<")) {
Map<Object, Object> newMap = new HashMap<>(map); Map<Object, Object> newMap = new HashMap<>(map);
List<String> keys = (List<String>) loader.loadType(STRING_LIST.getAnnotatedType(), map.get("<<")); List<String> keys = (List<String>) loader.loadType(STRING_LIST.getAnnotatedType(), map.get("<<"), depthTracker);
keys.forEach(key -> { keys.forEach(key -> {
Object meta = getMetaValue(key); Pair<Configuration, Object> pair = getMetaValue(key, depthTracker);
Object meta = pair.getRight();
if(!(meta instanceof Map)) { if(!(meta instanceof Map)) {
throw new LoadException( throw new LoadException(
"MetaMap injection candidate must be list, is type " + meta.getClass().getCanonicalName()); "MetaMap injection candidate must be list, is type " + meta.getClass().getCanonicalName(), depthTracker);
} }
newMap.putAll((Map<?, ?>) meta); newMap.putAll((Map<?, ?>) meta);
String configName;
if(pair.getLeft().getName() == null) {
configName = "Anonymous Configuration";
} else {
configName = pair.getLeft().getName();
}
depthTracker.addIntrinsicLevel(level -> {
if(level instanceof EntryLevel entryLevel && ((Map<?, ?>) meta).containsKey(entryLevel.getName())) {
return Optional.of("From configuration \"" + configName + "\"");
}
return Optional.empty();
});
}); });
newMap.putAll(map); newMap.putAll(map);
newMap.remove("<<"); // Remove placeholder newMap.remove("<<"); // Remove placeholder
return (Result<T>) Result.overwrite(newMap); return (Result<T>) Result.overwrite(newMap, depthTracker);
} }
} }
} }
@@ -20,6 +20,7 @@ package com.dfsek.terra.config.preprocessor;
import com.dfsek.paralithic.eval.parser.Parser; import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
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.preprocessor.Result; import com.dfsek.tectonic.api.preprocessor.Result;
@@ -51,13 +52,13 @@ public class MetaNumberPreprocessor extends MetaPreprocessor<Meta> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) { public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) {
if(t.getType() instanceof Class && isNumber((Class<?>) t.getType()) && c instanceof String) { if(t.getType() instanceof Class && isNumber((Class<?>) t.getType()) && c instanceof String) {
String expression = (String) loader.loadType(META_STRING_KEY.getAnnotatedType(), c); String expression = (String) loader.loadType(META_STRING_KEY.getAnnotatedType(), c, depthTracker);
try { try {
return (Result<T>) Result.overwrite(new Parser().parse(expression).evaluate()); return (Result<T>) Result.overwrite(new Parser().parse(expression).evaluate(), depthTracker);
} catch(ParseException e) { } catch(ParseException e) {
throw new LoadException("Invalid expression: ", e); throw new LoadException("Invalid expression: ", e, depthTracker);
} }
} }
return Result.noOp(); return Result.noOp();
@@ -18,9 +18,12 @@
package com.dfsek.terra.config.preprocessor; package com.dfsek.terra.config.preprocessor;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.preprocessor.ValuePreprocessor; import com.dfsek.tectonic.api.preprocessor.ValuePreprocessor;
import com.dfsek.terra.api.util.generic.pair.Pair;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.Map; import java.util.Map;
@@ -32,19 +35,19 @@ public abstract class MetaPreprocessor<A extends Annotation> implements ValuePre
this.configs = configs; this.configs = configs;
} }
protected Object getMetaValue(String meta) { protected Pair<Configuration, Object> getMetaValue(String meta, DepthTracker depthTracker) {
int sep = meta.indexOf(':'); int sep = meta.indexOf(':');
String file = meta.substring(0, sep); String file = meta.substring(0, sep);
String key = meta.substring(sep + 1); String key = meta.substring(sep + 1);
if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file); if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file, depthTracker);
Configuration config = configs.get(file); Configuration config = configs.get(file);
if(!config.contains(key)) { if(!config.contains(key)) {
throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName()); throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName(), depthTracker);
} }
return config.get(key); return Pair.of(config, config.get(key));
} }
} }
@@ -18,6 +18,7 @@
package com.dfsek.terra.config.preprocessor; package com.dfsek.terra.config.preprocessor;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
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.preprocessor.Result; import com.dfsek.tectonic.api.preprocessor.Result;
@@ -37,17 +38,17 @@ public class MetaStringPreprocessor extends MetaPreprocessor<Meta> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation) { public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) {
if(String.class.equals(t.getType()) && c instanceof String candidate) { // String is final so we use #equals if(String.class.equals(t.getType()) && c instanceof String candidate) { // String is final so we use #equals
StringSubstitutor substitutor = new StringSubstitutor(key -> { StringSubstitutor substitutor = new StringSubstitutor(key -> {
Object meta = getMetaValue(key); Object meta = getMetaValue(key, depthTracker).getRight();
if(!(meta instanceof String) && !(meta instanceof Number) && !(meta instanceof Character) && !(meta instanceof Boolean)) { if(!(meta instanceof String) && !(meta instanceof Number) && !(meta instanceof Character) && !(meta instanceof Boolean)) {
throw new LoadException("MetaString template injection candidate must be string or primitive, is type " + throw new LoadException("MetaString template injection candidate must be string or primitive, is type " +
meta.getClass().getCanonicalName()); meta.getClass().getCanonicalName(), depthTracker);
} }
return meta.toString(); return meta.toString();
}); });
return (Result<T>) Result.overwrite(substitutor.replace(candidate)); return (Result<T>) Result.overwrite(substitutor.replace(candidate), depthTracker);
} }
return Result.noOp(); return Result.noOp();
} }
@@ -18,8 +18,12 @@
package com.dfsek.terra.config.preprocessor; package com.dfsek.terra.config.preprocessor;
import com.dfsek.tectonic.api.config.Configuration; import com.dfsek.tectonic.api.config.Configuration;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.preprocessor.Result; import com.dfsek.tectonic.api.preprocessor.Result;
import com.dfsek.terra.api.util.generic.pair.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
@@ -36,11 +40,20 @@ public class MetaValuePreprocessor extends MetaPreprocessor<Meta> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader configLoader, Meta annotation) { public @NotNull <T> Result<T> process(AnnotatedType t, T c, ConfigLoader configLoader, Meta annotation, DepthTracker depthTracker) {
if(c instanceof String) { // Can we do standard metaconfig? if(c instanceof String) { // Can we do standard metaconfig?
String value = ((String) c).trim(); String value = ((String) c).trim();
if(value.startsWith("$")) { // it's a meta value. if(value.startsWith("$")) { // it's a meta value.
return (Result<T>) Result.overwrite(getMetaValue(value.substring(1))); Pair<Configuration, Object> pair = getMetaValue(value.substring(1), depthTracker);
String configName;
if(pair.getLeft().getName() == null) {
configName = "Anonymous Configuration";
} else {
configName = pair.getLeft().getName();
}
return (Result<T>) Result.overwrite(pair.getRight(), depthTracker.intrinsic("From configuration \"" + configName + "\""));
} }
} }
return Result.noOp(); return Result.noOp();
@@ -17,6 +17,7 @@
package com.dfsek.terra.registry; package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -102,7 +103,7 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
} }
@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, DepthTracker depthTracker) throws LoadException {
return registry.load(t, c, loader); return registry.load(t, c, loader, depthTracker);
} }
} }
@@ -17,6 +17,7 @@
package com.dfsek.terra.registry; package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -89,7 +90,7 @@ public class LockedRegistryImpl<T> implements Registry<T> {
} }
@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, DepthTracker depthTracker) throws LoadException {
return registry.load(t, c, loader); return registry.load(t, c, loader, depthTracker);
} }
} }
@@ -17,6 +17,7 @@
package com.dfsek.terra.registry; package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -65,10 +66,10 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
} }
@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, DepthTracker depthTracker) throws LoadException {
return getByID((String) o).orElseThrow(() -> new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o + return getByID((String) o).orElseThrow(() -> new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o +
"\" was found in this registry. Registry contains items: " + "\" was found in this registry. Registry contains items: " +
getItemsFormatted())); getItemsFormatted(), depthTracker));
} }
private String getItemsFormatted() { private String getItemsFormatted() {
@@ -1,5 +1,6 @@
package com.dfsek.terra.registry; package com.dfsek.terra.registry;
import com.dfsek.tectonic.api.depth.DepthTracker;
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;
@@ -34,15 +35,15 @@ public class ShortcutHolder<T> implements TypeLoader<T> {
} }
@Override @Override
public T load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader) throws LoadException { public T load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) throws LoadException {
String id = (String) o; String id = (String) o;
if(id.contains(":")) { if(id.contains(":")) {
String shortcut = id.substring(0, id.indexOf(":")); String shortcut = id.substring(0, id.indexOf(":"));
if(shortcuts.containsKey(shortcut)) { if(shortcuts.containsKey(shortcut)) {
return shortcuts.get(shortcut).load(configLoader, id.substring(id.indexOf(":") + 1)); return shortcuts.get(shortcut).load(configLoader, id.substring(id.indexOf(":") + 1), depthTracker.intrinsic("Using shortcut \"" + shortcut + "\""));
} }
throw new LoadException("Shortcut \"" + shortcut + "\" is not defined."); throw new LoadException("Shortcut \"" + shortcut + "\" is not defined.", depthTracker);
} }
return back.load(annotatedType, o, configLoader); return back.load(annotatedType, o, configLoader, depthTracker);
} }
} }
@@ -18,6 +18,7 @@
package com.dfsek.terra.bukkit; package com.dfsek.terra.bukkit;
import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@@ -85,14 +86,14 @@ public class PlatformImpl extends AbstractPlatform {
@Override @Override
public void register(TypeRegistry registry) { public void register(TypeRegistry registry) {
super.register(registry); super.register(registry);
registry.registerLoader(BlockState.class, (t, o, l) -> handle.createBlockState((String) o)) registry.registerLoader(BlockState.class, (type, o, loader, depthTracker) -> handle.createBlockState((String) o))
.registerLoader(PlatformBiome.class, (t, o, l) -> parseBiome((String) o)) .registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
.registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o)); .registerLoader(EntityType.class, (type, o, loader, depthTracker) -> EntityType.valueOf((String) o));
} }
private BukkitPlatformBiome parseBiome(String id) throws LoadException { private BukkitPlatformBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException {
if(!id.startsWith("minecraft:")) throw new LoadException("Invalid biome identifier " + id); if(!id.startsWith("minecraft:")) throw new LoadException("Invalid biome identifier " + id, depthTracker);
return new BukkitPlatformBiome(org.bukkit.block.Biome.valueOf(id.toUpperCase(Locale.ROOT).substring(10))); return new BukkitPlatformBiome(org.bukkit.block.Biome.valueOf(id.toUpperCase(Locale.ROOT).substring(10)));
} }
} }
@@ -51,7 +51,7 @@ public class BukkitWorldHandle implements WorldHandle {
@Override @Override
public @NotNull EntityType getEntity(@NotNull String id) { public @NotNull EntityType getEntity(@NotNull String id) {
if(!id.startsWith("minecraft:")) throw new LoadException("Invalid entity identifier " + id); if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id.toUpperCase(Locale.ROOT).substring(10))); return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id.toUpperCase(Locale.ROOT).substring(10)));
} }
@@ -60,6 +60,6 @@ public class CLIPlatform extends AbstractPlatform {
@Override @Override
public void register(TypeRegistry registry) { public void register(TypeRegistry registry) {
super.register(registry); super.register(registry);
registry.registerLoader(PlatformBiome.class, (TypeLoader<PlatformBiome>) (annotatedType, o, configLoader) -> () -> o); registry.registerLoader(PlatformBiome.class, (TypeLoader<PlatformBiome>) (annotatedType, o, configLoader, depthTracker) -> () -> o);
} }
} }
@@ -21,6 +21,7 @@ import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version; import ca.solostudios.strata.version.Version;
import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.MinecraftVersion; import net.minecraft.MinecraftVersion;
@@ -137,19 +138,19 @@ public class PlatformImpl extends AbstractPlatform {
@Override @Override
public void register(TypeRegistry registry) { public void register(TypeRegistry registry) {
super.register(registry); super.register(registry);
registry.registerLoader(PlatformBiome.class, (t, o, l) -> parseBiome((String) o)) registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
.registerLoader(Identifier.class, (t, o, l) -> { .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> {
Identifier identifier = Identifier.tryParse((String) o); Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null) if(identifier == null)
throw new LoadException("Invalid identifier: " + o); throw new LoadException("Invalid identifier: " + o, depthTracker);
return identifier; return identifier;
}); });
} }
private ProtoPlatformBiome parseBiome(String id) throws LoadException { private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException {
Identifier identifier = Identifier.tryParse(id); Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier); // failure. if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure.
return new ProtoPlatformBiome(identifier); return new ProtoPlatformBiome(identifier);
} }
} }