diff --git a/common/implementation/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java b/common/implementation/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java index 6c96d491c..2da842a0f 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java +++ b/common/implementation/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java @@ -82,22 +82,18 @@ public class ConfigPackImpl implements ConfigPack { private final BiomeProviderBuilder biomeProviderBuilder; + private final Map, ImmutablePair, CheckedRegistry>> registryMap = new HashMap<>(); private final ConfigTypeRegistry configTypeRegistry; - private final Map, ImmutablePair, CheckedRegistry>> registryMap = new HashMap<>(); + private final TreeMap>>> 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) 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 + "'"))); } diff --git a/common/implementation/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java b/common/implementation/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java index 3b551e391..9c2608057 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java +++ b/common/implementation/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java @@ -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 implements OpenRegistry { @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 value) { + public boolean register(String identifier, Entry value) { boolean exists = objects.containsKey(identifier); objects.put(identifier, value); return exists; diff --git a/common/implementation/src/main/java/com/dfsek/terra/registry/config/ConfigTypeRegistry.java b/common/implementation/src/main/java/com/dfsek/terra/registry/config/ConfigTypeRegistry.java index 9963508bb..eb48c2639 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/registry/config/ConfigTypeRegistry.java +++ b/common/implementation/src/main/java/com/dfsek/terra/registry/config/ConfigTypeRegistry.java @@ -19,9 +19,9 @@ public class ConfigTypeRegistry extends OpenRegistryImpl> { } @Override - public boolean add(String identifier, Entry> value) { + public boolean register(String identifier, Entry> 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); } } diff --git a/common/implementation/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java b/common/implementation/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java index 0aba01392..1965c5792 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java +++ b/common/implementation/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java @@ -34,7 +34,7 @@ public class AddonRegistry extends OpenRegistryImpl { 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 { } public boolean loadAll() { + return loadAll(TerraPlugin.class.getClassLoader()); + } + public boolean loadAll(ClassLoader parent) { InjectorImpl pluginInjector = new InjectorImpl<>(main); pluginInjector.addExplicitTarget(TerraPlugin.class); @@ -56,7 +59,7 @@ public class AddonRegistry extends OpenRegistryImpl { try { for(File jar : addonsFolder.listFiles(file -> file.getName().endsWith(".jar"))) { main.logger().info("Loading Addon(s) from: " + jar.getName()); - for(Class addonClass : AddonClassLoader.fetchAddonClasses(jar)) { + for(Class addonClass : AddonClassLoader.fetchAddonClasses(jar, parent)) { pool.add(new PreLoadAddon(addonClass, jar)); } } diff --git a/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java b/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java index e4258ba31..93631de6f 100644 --- a/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java +++ b/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java @@ -27,35 +27,36 @@ public class AddonClassLoader extends URLClassLoader { } @SuppressWarnings("unchecked") - public static Set> fetchAddonClasses(File file) throws IOException { + public static Set> fetchAddonClasses(File file, ClassLoader parent) throws IOException { JarFile jarFile = new JarFile(file); Enumeration 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> set = new HashSet<>(); - while(entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); + Set> 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) clazz); - } catch(ClassNotFoundException e) { - throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong + set.add((Class) clazz); + } catch(ClassNotFoundException e) { + throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong + } } - } - return set; + return set; + } } } diff --git a/common/loader/addon/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java b/common/loader/addon/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java index 379ca5e35..f3b1b0482 100644 --- a/common/loader/addon/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java +++ b/common/loader/addon/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java @@ -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); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java index 6784991d5..7a7e692e2 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java @@ -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 treeRegistry = event.getPack().getCheckedRegistry(Tree.class); + CheckedRegistry 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);