mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-04 00:45:57 +00:00
implement shortcut API
This commit is contained in:
parent
a0c46aaf7a
commit
28b16943f7
@ -62,5 +62,11 @@ public interface ConfigPack extends LoaderRegistrar, LoaderHolder, RegistryHolde
|
|||||||
|
|
||||||
RegistryFactory getRegistryFactory();
|
RegistryFactory getRegistryFactory();
|
||||||
|
|
||||||
|
<T> ConfigPack registerShortcut(Type clazz, String shortcut, ShortcutLoader<T> loader);
|
||||||
|
|
||||||
|
default <T> ConfigPack registerShortcut(Class<T> clazz, String shortcut, ShortcutLoader<T> loader) {
|
||||||
|
return registerShortcut((Type) clazz, shortcut, loader);
|
||||||
|
}
|
||||||
|
|
||||||
ChunkGeneratorProvider getGeneratorProvider();
|
ChunkGeneratorProvider getGeneratorProvider();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.dfsek.terra.api.config;
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.api.loader.ConfigLoader;
|
||||||
|
|
||||||
|
|
||||||
|
public interface ShortcutLoader<T> {
|
||||||
|
T load(ConfigLoader configLoader, String input);
|
||||||
|
}
|
@ -28,35 +28,10 @@ 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.impl.abstraction.AbstractConfiguration;
|
import com.dfsek.tectonic.impl.abstraction.AbstractConfiguration;
|
||||||
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
import com.dfsek.tectonic.yaml.YamlConfiguration;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.Platform;
|
import com.dfsek.terra.api.Platform;
|
||||||
import com.dfsek.terra.api.addon.BaseAddon;
|
import com.dfsek.terra.api.addon.BaseAddon;
|
||||||
import com.dfsek.terra.api.config.ConfigFactory;
|
import com.dfsek.terra.api.config.*;
|
||||||
import com.dfsek.terra.api.config.ConfigPack;
|
|
||||||
import com.dfsek.terra.api.config.ConfigType;
|
|
||||||
import com.dfsek.terra.api.config.Loader;
|
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent;
|
import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent;
|
||||||
import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
|
import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
|
||||||
@ -79,16 +54,28 @@ import com.dfsek.terra.config.fileloaders.FolderLoader;
|
|||||||
import com.dfsek.terra.config.fileloaders.ZIPLoader;
|
import com.dfsek.terra.config.fileloaders.ZIPLoader;
|
||||||
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
|
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
|
||||||
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
|
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
|
||||||
import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor;
|
import com.dfsek.terra.config.preprocessor.*;
|
||||||
import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor;
|
|
||||||
import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor;
|
|
||||||
import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor;
|
|
||||||
import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor;
|
|
||||||
import com.dfsek.terra.config.prototype.ProtoConfig;
|
import com.dfsek.terra.config.prototype.ProtoConfig;
|
||||||
import com.dfsek.terra.registry.CheckedRegistryImpl;
|
import com.dfsek.terra.registry.CheckedRegistryImpl;
|
||||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||||
import com.dfsek.terra.registry.RegistryFactoryImpl;
|
import com.dfsek.terra.registry.RegistryFactoryImpl;
|
||||||
import com.dfsek.terra.registry.config.ConfigTypeRegistry;
|
import com.dfsek.terra.registry.ShortcutHolder;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,9 +97,10 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
|
|
||||||
private final BiomeProvider seededBiomeProvider;
|
private final BiomeProvider seededBiomeProvider;
|
||||||
|
|
||||||
private final Map<Type, Pair<OpenRegistry<?>, CheckedRegistry<?>>> registryMap = new HashMap<>();
|
private final Map<Type, CheckedRegistryImpl<?>> registryMap = new HashMap<>();
|
||||||
|
private final Map<Type, ShortcutHolder<?>> shortcuts = new HashMap<>();
|
||||||
|
|
||||||
private final ConfigTypeRegistry configTypeRegistry;
|
private final OpenRegistry<ConfigType<?, ?>> configTypeRegistry;
|
||||||
private final TreeMap<Integer, List<Pair<String, ConfigType<?, ?>>>> configTypes = new TreeMap<>();
|
private final TreeMap<Integer, List<Pair<String, ConfigType<?, ?>>>> configTypes = new TreeMap<>();
|
||||||
|
|
||||||
public ConfigPackImpl(File folder, Platform platform) {
|
public ConfigPackImpl(File folder, Platform platform) {
|
||||||
@ -150,7 +138,7 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
|
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.configTypeRegistry = createRegistry();
|
this.configTypeRegistry = createConfigRegistry();
|
||||||
|
|
||||||
register(selfLoader);
|
register(selfLoader);
|
||||||
platform.register(selfLoader);
|
platform.register(selfLoader);
|
||||||
@ -259,10 +247,10 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(TypeRegistry registry) {
|
public void register(TypeRegistry registry) {
|
||||||
registry
|
registry.registerLoader(ConfigType.class, configTypeRegistry)
|
||||||
.registerLoader(ConfigType.class, configTypeRegistry)
|
|
||||||
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader));
|
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader));
|
||||||
registryMap.forEach((clazz, reg) -> registry.registerLoader(clazz, reg.getLeft()));
|
registryMap.forEach(registry::registerLoader);
|
||||||
|
shortcuts.forEach(registry::registerLoader); // overwrite with delegated shortcuts if present
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -335,8 +323,8 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair.of(registry, new CheckedRegistryImpl<>(registry));
|
return new CheckedRegistryImpl<>(registry);
|
||||||
}).getRight();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -364,37 +352,45 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
return registryFactory;
|
return registryFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked,rawtypes")
|
||||||
|
@Override
|
||||||
|
public <T> ConfigPack registerShortcut(Type clazz, String shortcut, ShortcutLoader<T> loader) {
|
||||||
|
ShortcutHolder<?> holder = shortcuts
|
||||||
|
.computeIfAbsent(clazz, c -> new ShortcutHolder<>(getOrCreateRegistry(clazz)))
|
||||||
|
.register(shortcut, (ShortcutLoader) loader);
|
||||||
|
selfLoader.registerLoader(clazz, holder);
|
||||||
|
abstractConfigLoader.registerLoader(clazz, holder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChunkGeneratorProvider getGeneratorProvider() {
|
public ChunkGeneratorProvider getGeneratorProvider() {
|
||||||
return template.getGeneratorProvider();
|
return template.getGeneratorProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private OpenRegistry<ConfigType<?, ?>> createConfigRegistry() {
|
||||||
private ConfigTypeRegistry createRegistry() {
|
return new OpenRegistryImpl<>(new LinkedHashMap<>()) {
|
||||||
return new ConfigTypeRegistry(platform, (id, configType) -> {
|
@Override
|
||||||
OpenRegistry<?> openRegistry = configType.registrySupplier(this).get();
|
public boolean register(@NotNull String identifier, @NotNull ConfigType<?, ?> value) {
|
||||||
if(registryMap.containsKey(configType.getTypeKey()
|
if(!registryMap
|
||||||
.getType())) { // Someone already registered something; we need to copy things to the
|
.containsKey(value.getTypeKey()
|
||||||
// new registry.
|
.getType())) {
|
||||||
logger.warn("Copying values from old registry for {}", configType.getTypeKey());
|
OpenRegistry<?> openRegistry = value.registrySupplier(ConfigPackImpl.this).get();
|
||||||
registryMap.get(configType.getTypeKey().getType()).getLeft().forEach(((OpenRegistry<Object>) openRegistry)::register);
|
selfLoader.registerLoader(value.getTypeKey().getType(), openRegistry);
|
||||||
|
abstractConfigLoader.registerLoader(value.getTypeKey().getType(), openRegistry);
|
||||||
|
registryMap.put(value.getTypeKey().getType(), new CheckedRegistryImpl<>(openRegistry));
|
||||||
}
|
}
|
||||||
selfLoader.registerLoader(configType.getTypeKey().getType(), openRegistry);
|
return super.register(identifier, value);
|
||||||
abstractConfigLoader.registerLoader(configType.getTypeKey().getType(), openRegistry);
|
}
|
||||||
registryMap.put(configType.getTypeKey().getType(), Pair.of(openRegistry, new CheckedRegistryImpl<>(openRegistry)));
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDeadEntries() {
|
private void checkDeadEntries() {
|
||||||
registryMap.forEach((clazz, pair) -> ((OpenRegistryImpl<?>) pair.getLeft())
|
registryMap.forEach((clazz, pair) -> ((OpenRegistryImpl<?>) pair.getRegistry())
|
||||||
.getDeadEntries()
|
.getDeadEntries()
|
||||||
.forEach((id, value) -> logger.debug("Dead entry in '{}' registry: '{}'", ReflectionUtil.typeToString(clazz), id)));
|
.forEach((id, value) -> logger.debug("Dead entry in '{}' registry: '{}'", ReflectionUtil.typeToString(clazz), id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<Type, Pair<OpenRegistry<?>, CheckedRegistry<?>>> getRegistryMap() {
|
|
||||||
return registryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigPackTemplate getTemplate() {
|
public ConfigPackTemplate getTemplate() {
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
@ -402,18 +398,13 @@ public class ConfigPackImpl implements ConfigPack {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> CheckedRegistry<T> getRegistry(Type type) {
|
public <T> CheckedRegistry<T> getRegistry(Type type) {
|
||||||
return (CheckedRegistry<T>) registryMap.getOrDefault(type, Pair.ofNull()).getRight();
|
return (CheckedRegistry<T>) registryMap.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> CheckedRegistry<T> getCheckedRegistry(Type type) throws IllegalStateException {
|
public <T> CheckedRegistry<T> getCheckedRegistry(Type type) throws IllegalStateException {
|
||||||
return (CheckedRegistry<T>) registryMap.getOrDefault(type, Pair.ofNull()).getRight();
|
return (CheckedRegistry<T>) registryMap.get(type);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected <T> OpenRegistry<T> getOpenRegistry(Class<T> clazz) {
|
|
||||||
return (OpenRegistry<T>) registryMap.getOrDefault(clazz, Pair.ofNull()).getLeft();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,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 org.jetbrains.annotations.ApiStatus.Internal;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.AnnotatedType;
|
import java.lang.reflect.AnnotatedType;
|
||||||
@ -41,6 +42,11 @@ import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
|||||||
public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
|
public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
|
||||||
private final OpenRegistry<T> registry;
|
private final OpenRegistry<T> registry;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public OpenRegistry<T> getRegistry() {
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
public CheckedRegistryImpl(OpenRegistry<T> registry) {
|
public CheckedRegistryImpl(OpenRegistry<T> registry) {
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
}
|
}
|
||||||
@ -81,7 +87,7 @@ public class CheckedRegistryImpl<T> implements CheckedRegistry<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T load(AnnotatedType t, Object c, 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.dfsek.terra.registry;
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.api.exception.LoadException;
|
||||||
|
import com.dfsek.tectonic.api.loader.ConfigLoader;
|
||||||
|
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.config.ShortcutLoader;
|
||||||
|
import com.dfsek.terra.api.registry.Registry;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.AnnotatedType;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public class ShortcutHolder<T> implements TypeLoader<T> {
|
||||||
|
private final Map<String, ShortcutLoader<T>> shortcuts = new HashMap<>();
|
||||||
|
private final Registry<T> back;
|
||||||
|
|
||||||
|
public ShortcutHolder(Registry<T> back) {
|
||||||
|
this.back = back;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShortcutHolder<T> register(String id, ShortcutLoader<T> loader) {
|
||||||
|
if(shortcuts.containsKey(id)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Attempted to register duplicate shortcut " + id + ", previously registered to " + shortcuts.get(id)
|
||||||
|
.getClass()
|
||||||
|
.getCanonicalName());
|
||||||
|
}
|
||||||
|
shortcuts.put(id, loader);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader) throws LoadException {
|
||||||
|
String id = (String) o;
|
||||||
|
if(id.contains(":")) {
|
||||||
|
String shortcut = id.substring(0, id.indexOf(":"));
|
||||||
|
if(shortcuts.containsKey(shortcut)) {
|
||||||
|
return shortcuts.get(shortcut).load(configLoader, id.substring(id.indexOf(":") + 1));
|
||||||
|
}
|
||||||
|
throw new LoadException("Shortcut \"" + shortcut + "\" is not defined.");
|
||||||
|
}
|
||||||
|
return back.load(annotatedType, o, configLoader);
|
||||||
|
}
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Terra.
|
|
||||||
*
|
|
||||||
* Terra is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Terra is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.registry.config;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.Platform;
|
|
||||||
import com.dfsek.terra.api.config.ConfigType;
|
|
||||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
|
||||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
|
||||||
|
|
||||||
|
|
||||||
public class ConfigTypeRegistry extends OpenRegistryImpl<ConfigType<?, ?>> {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConfigTypeRegistry.class);
|
|
||||||
|
|
||||||
private final BiConsumer<String, ConfigType<?, ?>> callback;
|
|
||||||
|
|
||||||
public ConfigTypeRegistry(Platform platform, BiConsumer<String, ConfigType<?, ?>> callback) {
|
|
||||||
super(new LinkedHashMap<>()); // Ordered
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean register(String identifier, Entry<ConfigType<?, ?>> value) {
|
|
||||||
callback.accept(identifier, value.getValue());
|
|
||||||
logger.debug("Registered config registry with ID {} to type {}", identifier,
|
|
||||||
ReflectionUtil.typeToString(value.getValue().getTypeKey().getType()));
|
|
||||||
return super.register(identifier, value);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user