fix registry overwrite issue

This commit is contained in:
dfsek
2021-07-15 13:54:01 -07:00
parent 95e6479505
commit 8cd2554d3a
7 changed files with 49 additions and 42 deletions

View File

@@ -82,22 +82,18 @@ public class ConfigPackImpl implements ConfigPack {
private final BiomeProviderBuilder biomeProviderBuilder;
private final Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> registryMap = new HashMap<>();
private final ConfigTypeRegistry configTypeRegistry;
private final Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> registryMap = new HashMap<>();
private final TreeMap<Integer, List<ImmutablePair<String, ConfigType<?, ?>>>> configTypes = new TreeMap<>();
public ConfigPackImpl(File folder, TerraPlugin main) throws ConfigException {
try {
this.configTypeRegistry = new ConfigTypeRegistry(main, (id, configType) -> {
OpenRegistry<?> openRegistry = configType.registrySupplier().get();
selfLoader.registerLoader(configType.getTypeClass(), openRegistry);
abstractConfigLoader.registerLoader(configType.getTypeClass(), openRegistry);
registryMap.put(configType.getTypeClass(), ImmutablePair.of(openRegistry, new CheckedRegistryImpl<>(openRegistry)));
});
this.loader = new FolderLoader(folder.toPath());
this.main = main;
this.configTypeRegistry = createRegistry();
long l = System.nanoTime();
register(abstractConfigLoader);
@@ -139,14 +135,9 @@ public class ConfigPackImpl implements ConfigPack {
public ConfigPackImpl(ZipFile file, TerraPlugin main) throws ConfigException {
try {
this.configTypeRegistry = new ConfigTypeRegistry(main, (id, configType) -> {
OpenRegistry<?> openRegistry = configType.registrySupplier().get();
selfLoader.registerLoader(configType.getTypeClass(), openRegistry);
abstractConfigLoader.registerLoader(configType.getTypeClass(), openRegistry);
registryMap.put(configType.getTypeClass(), ImmutablePair.of(openRegistry, new CheckedRegistryImpl<>(openRegistry)));
});
this.loader = new ZIPLoader(file);
this.main = main;
this.configTypeRegistry = createRegistry();
long l = System.nanoTime();
register(selfLoader);
@@ -196,6 +187,19 @@ public class ConfigPackImpl implements ConfigPack {
toWorldConfig(new TerraWorldImpl(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
}
private ConfigTypeRegistry createRegistry() {
return new ConfigTypeRegistry(main, (id, configType) -> {
OpenRegistry<?> openRegistry = configType.registrySupplier().get();
if(registryMap.containsKey(configType.getTypeClass())) { // Someone already registered something; we need to copy things to the new registry.
//noinspection unchecked
registryMap.get(configType.getTypeClass()).getLeft().forEach(((OpenRegistry<Object>) openRegistry)::register);
}
selfLoader.registerLoader(configType.getTypeClass(), openRegistry);
abstractConfigLoader.registerLoader(configType.getTypeClass(), openRegistry);
registryMap.put(configType.getTypeClass(), ImmutablePair.of(openRegistry, new CheckedRegistryImpl<>(openRegistry)));
});
}
private void checkDeadEntries(TerraPlugin main) {
registryMap.forEach((clazz, pair) -> ((OpenRegistryImpl<?>) pair.getLeft()).getDeadEntries().forEach((id, value) -> main.getDebugLogger().warning("Dead entry in '" + clazz + "' registry: '" + id + "'")));
}

View File

@@ -6,7 +6,6 @@ import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -47,10 +46,10 @@ public class OpenRegistryImpl<T> implements OpenRegistry<T> {
@Override
public boolean register(String identifier, T value) {
return add(identifier, new Entry<>(value));
return register(identifier, new Entry<>(value));
}
public boolean add(String identifier, Entry<T> value) {
public boolean register(String identifier, Entry<T> value) {
boolean exists = objects.containsKey(identifier);
objects.put(identifier, value);
return exists;

View File

@@ -19,9 +19,9 @@ public class ConfigTypeRegistry extends OpenRegistryImpl<ConfigType<?, ?>> {
}
@Override
public boolean add(String identifier, Entry<ConfigType<?, ?>> value) {
public boolean register(String identifier, Entry<ConfigType<?, ?>> value) {
callback.accept(identifier, value.getValue());
main.getDebugLogger().info("Registered config registry with ID " + identifier + " to class " + value.getValue().getTypeClass().getCanonicalName());
return super.add(identifier, value);
return super.register(identifier, value);
}
}

View File

@@ -34,7 +34,7 @@ public class AddonRegistry extends OpenRegistryImpl<TerraAddon> {
public boolean register(String identifier, TerraAddon addon) {
if(contains(identifier)) throw new IllegalArgumentException("Addon " + identifier + " is already registered.");
addon.initialize();
main.logger().info("Loaded com.dfsek.terra.addon " + addon.getName() + " v" + addon.getVersion() + ", by " + addon.getAuthor());
main.logger().info("Loaded addon " + addon.getName() + " v" + addon.getVersion() + ", by " + addon.getAuthor());
return super.register(identifier, addon);
}
@@ -44,6 +44,9 @@ public class AddonRegistry extends OpenRegistryImpl<TerraAddon> {
}
public boolean loadAll() {
return loadAll(TerraPlugin.class.getClassLoader());
}
public boolean loadAll(ClassLoader parent) {
InjectorImpl<TerraPlugin> pluginInjector = new InjectorImpl<>(main);
pluginInjector.addExplicitTarget(TerraPlugin.class);
@@ -56,7 +59,7 @@ public class AddonRegistry extends OpenRegistryImpl<TerraAddon> {
try {
for(File jar : addonsFolder.listFiles(file -> file.getName().endsWith(".jar"))) {
main.logger().info("Loading Addon(s) from: " + jar.getName());
for(Class<? extends TerraAddon> addonClass : AddonClassLoader.fetchAddonClasses(jar)) {
for(Class<? extends TerraAddon> addonClass : AddonClassLoader.fetchAddonClasses(jar, parent)) {
pool.add(new PreLoadAddon(addonClass, jar));
}
}

View File

@@ -27,35 +27,36 @@ public class AddonClassLoader extends URLClassLoader {
}
@SuppressWarnings("unchecked")
public static Set<Class<? extends TerraAddon>> fetchAddonClasses(File file) throws IOException {
public static Set<Class<? extends TerraAddon>> fetchAddonClasses(File file, ClassLoader parent) throws IOException {
JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> entries = jarFile.entries();
AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, AddonClassLoader.class.getClassLoader());
try(AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, parent)) {
Set<Class<? extends TerraAddon>> set = new HashSet<>();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
Set<Class<? extends TerraAddon>> set = new HashSet<>();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.');
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.');
try {
Class<?> clazz = loader.loadClass(className);
try {
Class<?> clazz = loader.loadClass(className);
Addon addon = clazz.getAnnotation(Addon.class);
Addon addon = clazz.getAnnotation(Addon.class);
if(addon == null) continue;
if(addon == null) continue;
if(!TerraAddon.class.isAssignableFrom(clazz))
throw new IllegalArgumentException("Addon class \"" + clazz + "\" must extend TerraAddon.");
if(!TerraAddon.class.isAssignableFrom(clazz))
throw new IllegalArgumentException("Addon class \"" + clazz + "\" must extend TerraAddon.");
set.add((Class<? extends TerraAddon>) clazz);
} catch(ClassNotFoundException e) {
throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong
set.add((Class<? extends TerraAddon>) clazz);
} catch(ClassNotFoundException e) {
throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong
}
}
}
return set;
return set;
}
}
}

View File

@@ -33,7 +33,7 @@ public class PreLoadAddon {
public void rebuildDependencies(AddonPool pool, PreLoadAddon origin, boolean levelG1) throws AddonLoadException {
if(this.equals(origin) && !levelG1)
throw new CircularDependencyException("Detected circular dependency in com.dfsek.terra.addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies));
throw new CircularDependencyException("Detected circular dependency in addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies));
for(String dependency : dependencies) {
PreLoadAddon preLoadAddon = pool.get(dependency);

View File

@@ -260,7 +260,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
debugLogger.setDebug(config.isDebugLogging());
if(config.isDebugProfiler()) profiler.start();
if(!addonRegistry.loadAll()) {
if(!addonRegistry.loadAll(getClass().getClassLoader())) {
throw new IllegalStateException("Failed to load addons. Please correct com.dfsek.terra.addon installations to continue.");
}
logger.info("Loaded addons.");
@@ -317,10 +317,10 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
eventManager.registerListener(this, this);
}
@Priority(Priority.LOWEST)
@Priority(Priority.HIGHEST)
@Global
public void injectTrees(ConfigPackPreLoadEvent event) {
CheckedRegistry<Tree> treeRegistry = event.getPack().getCheckedRegistry(Tree.class);
CheckedRegistry<Tree> treeRegistry = event.getPack().getOrCreateRegistry(Tree.class);
injectTree(treeRegistry, "BROWN_MUSHROOM", ConfiguredFeatures.HUGE_BROWN_MUSHROOM);
injectTree(treeRegistry, "RED_MUSHROOM", ConfiguredFeatures.HUGE_RED_MUSHROOM);
injectTree(treeRegistry, "JUNGLE", ConfiguredFeatures.MEGA_JUNGLE_TREE);