Commit 027952f9358b099027c91317cd05be74f0e084f8

Authored by Mumfrey
1 parent 1ef9f4cf

refactoring enumerator

java/common/com/mumfrey/liteloader/api/ContainerRegistry.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +import java.io.File;
  4 +import java.util.Collection;
  5 +
  6 +import com.mumfrey.liteloader.core.ModInfo;
  7 +import com.mumfrey.liteloader.interfaces.Loadable;
  8 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  9 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  10 +
  11 +/**
  12 + * Registry for enabled, disabled, injected and bad containers
  13 + *
  14 + * @author Adam Mummery-Smith
  15 + */
  16 +public interface ContainerRegistry
  17 +{
  18 + public enum DisabledReason
  19 + {
  20 + UNKNOWN("Container %s is could not be loaded for UNKNOWN reason"),
  21 + USER_DISABLED("Container %s is disabled"),
  22 + MISSING_DEPENDENCY("Container %s is missing one or more dependencies"),
  23 + MISSING_API("Container %s is missing one or more required APIs");
  24 +
  25 + private final String message;
  26 +
  27 + private DisabledReason(String message)
  28 + {
  29 + this.message = message;
  30 + }
  31 +
  32 + public String getMessage(LoadableMod<?> container)
  33 + {
  34 + return String.format(this.message, container);
  35 + }
  36 + }
  37 +
  38 + /**
  39 + * Register an enabled container, removes the container from the disabled containers list if present
  40 + */
  41 + public abstract void registerEnabledContainer(LoadableMod<?> container);
  42 +
  43 + /**
  44 + * Get all enabled containers
  45 + */
  46 + public abstract Collection<? extends LoadableMod<?>> getEnabledContainers();
  47 +
  48 + /**
  49 + * Get a specific enabled container by id
  50 + */
  51 + public abstract LoadableMod<?> getEnabledContainer(String identifier);
  52 +
  53 + /**
  54 + * Register a disabled container
  55 + */
  56 + public abstract void registerDisabledContainer(LoadableMod<?> container, DisabledReason reason);
  57 +
  58 + /**
  59 + * Get all disabled containers
  60 + */
  61 + public abstract Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers();
  62 +
  63 + /**
  64 + * Check whether a specific container is registered as disabled
  65 + */
  66 + public abstract boolean isDisabledContainer(LoadableMod<?> container);
  67 +
  68 + /**
  69 + * Register a bad container
  70 + */
  71 + public abstract void registerBadContainer(Loadable<?> container, String reason);
  72 +
  73 + /**
  74 + * Get all bad containers
  75 + */
  76 + public abstract Collection<? extends ModInfo<Loadable<?>>> getBadContainers();
  77 +
  78 + /**
  79 + * Register a candidate tweak container
  80 + */
  81 + public abstract void registerTweakContainer(TweakContainer<File> container);
  82 +
  83 + /**
  84 + * Get all registered tweak containers
  85 + */
  86 + public abstract Collection<TweakContainer<File>> getTweakContainers();
  87 +
  88 + /**
  89 + * Register an injected tweak container
  90 + */
  91 + public abstract void registerInjectedTweak(TweakContainer<File> container);
  92 +
  93 + /**
  94 + * Get all injected tweak containers
  95 + */
  96 + public abstract Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
  97 +}
java/common/com/mumfrey/liteloader/api/EnumerationObserver.java
@@ -2,10 +2,10 @@ package com.mumfrey.liteloader.api; @@ -2,10 +2,10 @@ package com.mumfrey.liteloader.api;
2 2
3 import java.io.File; 3 import java.io.File;
4 4
  5 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
5 import com.mumfrey.liteloader.core.ModInfo; 6 import com.mumfrey.liteloader.core.ModInfo;
6 import com.mumfrey.liteloader.interfaces.LoadableMod; 7 import com.mumfrey.liteloader.interfaces.LoadableMod;
7 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 8 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
8 -import com.mumfrey.liteloader.interfaces.LoaderEnumerator.DisabledReason;  
9 import com.mumfrey.liteloader.interfaces.TweakContainer; 9 import com.mumfrey.liteloader.interfaces.TweakContainer;
10 10
11 /** 11 /**
java/common/com/mumfrey/liteloader/api/EnumeratorPlugin.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  6 +import com.mumfrey.liteloader.launch.LoaderEnvironment;
  7 +import com.mumfrey.liteloader.launch.LoaderProperties;
  8 +
  9 +/**
  10 + * LiteLoader Extensible API - Interface for objects which can interact with the enumeration process, not yet available to APIs
  11 + *
  12 + * @author Adam Mummery-Smith
  13 + */
  14 +public interface EnumeratorPlugin
  15 +{
  16 + /**
  17 + * Initialise this plugin
  18 + */
  19 + public abstract void init(LoaderEnvironment environment, LoaderProperties properties);
  20 +
  21 + /**
  22 + * Get classes in the supplied container
  23 + *
  24 + * @param container Container to inspect
  25 + * @param classloader ClassLoader for this container
  26 + * @param superClass Superclass the class must implement
  27 + * @param supportedPrefixes Registered class prefixes
  28 + * @return
  29 + */
  30 + public abstract <T> List<Class<? extends T>> getClasses(LoadableMod<?> container, ClassLoader classloader, ModClassValidator validator);
  31 +
  32 + public abstract boolean checkEnabled(ContainerRegistry containers, LoadableMod<?> container);
  33 +
  34 + public abstract boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base);
  35 +
  36 + public abstract boolean checkAPIRequirements(ContainerRegistry containers, LoadableMod<?> container);
  37 +}
java/common/com/mumfrey/liteloader/api/ModClassValidator.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +/**
  4 + * Interface for object which validates whether a supplied mod class can be loaded
  5 + *
  6 + * @author Adam Mummery-Smith
  7 + */
  8 +public interface ModClassValidator
  9 +{
  10 + public abstract boolean validateName(String className);
  11 +
  12 + public abstract boolean validateClass(ClassLoader classLoader, Class<?> candidateClass);
  13 +}
java/common/com/mumfrey/liteloader/core/Containers.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import java.io.File;
  4 +import java.util.ArrayList;
  5 +import java.util.Collection;
  6 +import java.util.HashMap;
  7 +import java.util.HashSet;
  8 +import java.util.List;
  9 +import java.util.Map;
  10 +import java.util.Set;
  11 +
  12 +import com.mumfrey.liteloader.api.ContainerRegistry;
  13 +import com.mumfrey.liteloader.interfaces.Loadable;
  14 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  15 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  16 +
  17 +/**
  18 + * Implementation of ContainerRegistry for LiteLoaderEnumerator
  19 + *
  20 + * @author Adam Mummery-Smith
  21 + */
  22 +class Containers implements ContainerRegistry
  23 +{
  24 + /**
  25 + * Mod containers which are disabled
  26 + */
  27 + private final Map<String, ModInfo<Loadable<?>>> disabledContainers = new HashMap<String, ModInfo<Loadable<?>>>();
  28 +
  29 + /**
  30 + * Mapping of identifiers to mod containers
  31 + */
  32 + private final Map<String, LoadableMod<?>> enabledContainers = new HashMap<String, LoadableMod<?>>();
  33 +
  34 + /**
  35 + * Map of containers which cannot be loaded to reasons
  36 + */
  37 + private final Set<ModInfo<Loadable<?>>> badContainers = new HashSet<ModInfo<Loadable<?>>>();
  38 +
  39 + /**
  40 + * Tweaks to inject
  41 + */
  42 + private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>();
  43 +
  44 + /**
  45 + * Other tweak-containing jars which we have injected
  46 + */
  47 + private final List<ModInfo<Loadable<?>>> injectedTweaks = new ArrayList<ModInfo<Loadable<?>>>();
  48 +
  49 + /* (non-Javadoc)
  50 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getDisabledContainers()
  51 + */
  52 + @Override
  53 + public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
  54 + {
  55 + return this.disabledContainers.values();
  56 + }
  57 +
  58 + /* (non-Javadoc)
  59 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getEnabledContainers()
  60 + */
  61 + @Override
  62 + public Collection<? extends LoadableMod<?>> getEnabledContainers()
  63 + {
  64 + return this.enabledContainers.values();
  65 + }
  66 +
  67 + /* (non-Javadoc)
  68 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getBadContainers()
  69 + */
  70 + @Override
  71 + public Collection<? extends ModInfo<Loadable<?>>> getBadContainers()
  72 + {
  73 + return this.badContainers;
  74 + }
  75 +
  76 + /* (non-Javadoc)
  77 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getTweakContainers()
  78 + */
  79 + @Override
  80 + public List<TweakContainer<File>> getTweakContainers()
  81 + {
  82 + return this.tweakContainers;
  83 + }
  84 +
  85 + /* (non-Javadoc)
  86 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getInjectedTweaks()
  87 + */
  88 + @Override
  89 + public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
  90 + {
  91 + return this.injectedTweaks;
  92 + }
  93 +
  94 + /* (non-Javadoc)
  95 + * @see com.mumfrey.liteloader.api.ContainerRegistry#isDisabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
  96 + */
  97 + @Override
  98 + public boolean isDisabledContainer(LoadableMod<?> container)
  99 + {
  100 + return this.disabledContainers.containsValue(container);
  101 + }
  102 +
  103 + /* (non-Javadoc)
  104 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getEnabledContainer(java.lang.String)
  105 + */
  106 + @Override
  107 + public LoadableMod<?> getEnabledContainer(String identifier)
  108 + {
  109 + LoadableMod<?> container = this.enabledContainers.get(identifier);
  110 + return container != null ? container : LoadableMod.NONE;
  111 + }
  112 +
  113 + /* (non-Javadoc)
  114 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerBadContainer(com.mumfrey.liteloader.interfaces.Loadable, java.lang.String)
  115 + */
  116 + @Override
  117 + public void registerBadContainer(Loadable<?> container, String reason)
  118 + {
  119 + this.badContainers.add(new BadContainerInfo(container, reason));
  120 + }
  121 +
  122 + /* (non-Javadoc)
  123 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerEnabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
  124 + */
  125 + @Override
  126 + public void registerEnabledContainer(LoadableMod<?> container)
  127 + {
  128 + this.disabledContainers.remove(container.getIdentifier());
  129 + this.enabledContainers.put(container.getIdentifier(), container);
  130 + }
  131 +
  132 + /* (non-Javadoc)
  133 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerDisabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod, com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason)
  134 + */
  135 + @Override
  136 + public void registerDisabledContainer(LoadableMod<?> container, DisabledReason reason)
  137 + {
  138 + this.enabledContainers.remove(container.getIdentifier());
  139 + this.disabledContainers.put(container.getIdentifier(), new NonMod(container, false));
  140 + }
  141 +
  142 + /* (non-Javadoc)
  143 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerTweakContainer(com.mumfrey.liteloader.interfaces.TweakContainer)
  144 + */
  145 + @Override
  146 + public void registerTweakContainer(TweakContainer<File> container)
  147 + {
  148 + this.tweakContainers.add(container);
  149 + }
  150 +
  151 + /* (non-Javadoc)
  152 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerInjectedTweak(com.mumfrey.liteloader.interfaces.TweakContainer)
  153 + */
  154 + @Override
  155 + public void registerInjectedTweak(TweakContainer<File> container)
  156 + {
  157 + this.injectedTweaks.add(new NonMod(container, true));
  158 + }
  159 +}
java/common/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
@@ -27,6 +27,8 @@ import com.mumfrey.liteloader.api.manager.APIRegistry; @@ -27,6 +27,8 @@ import com.mumfrey.liteloader.api.manager.APIRegistry;
27 import com.mumfrey.liteloader.common.LoadingProgress; 27 import com.mumfrey.liteloader.common.LoadingProgress;
28 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI; 28 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
29 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 29 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
  30 +import com.mumfrey.liteloader.launch.ClassTransformerManager;
  31 +import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
30 import com.mumfrey.liteloader.launch.LoaderBootstrap; 32 import com.mumfrey.liteloader.launch.LoaderBootstrap;
31 import com.mumfrey.liteloader.launch.LoaderEnvironment; 33 import com.mumfrey.liteloader.launch.LoaderEnvironment;
32 import com.mumfrey.liteloader.launch.LoaderProperties; 34 import com.mumfrey.liteloader.launch.LoaderProperties;
@@ -259,9 +261,25 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP @@ -259,9 +261,25 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
259 } 261 }
260 262
261 @Override 263 @Override
262 - public ITweaker getTweaker() 264 + public boolean addCascadedTweaker(String tweakClass, int priority)
263 { 265 {
264 - return this.tweaker; 266 + if (this.tweaker instanceof LiteLoaderTweaker)
  267 + {
  268 + return ((LiteLoaderTweaker)this.tweaker).addCascadedTweaker(tweakClass, priority);
  269 + }
  270 +
  271 + return false;
  272 + }
  273 +
  274 + @Override
  275 + public ClassTransformerManager getTransformerManager()
  276 + {
  277 + if (this.tweaker instanceof LiteLoaderTweaker)
  278 + {
  279 + return ((LiteLoaderTweaker)this.tweaker).getTransformerManager();
  280 + }
  281 +
  282 + return null;
265 } 283 }
266 284
267 /* (non-Javadoc) 285 /* (non-Javadoc)
java/common/com/mumfrey/liteloader/core/LiteLoaderEnumerator.java
@@ -9,7 +9,6 @@ import java.util.Collections; @@ -9,7 +9,6 @@ import java.util.Collections;
9 import java.util.HashMap; 9 import java.util.HashMap;
10 import java.util.HashSet; 10 import java.util.HashSet;
11 import java.util.LinkedHashSet; 11 import java.util.LinkedHashSet;
12 -import java.util.LinkedList;  
13 import java.util.List; 12 import java.util.List;
14 import java.util.Map; 13 import java.util.Map;
15 import java.util.Set; 14 import java.util.Set;
@@ -19,17 +18,22 @@ import net.minecraft.launchwrapper.LaunchClassLoader; @@ -19,17 +18,22 @@ import net.minecraft.launchwrapper.LaunchClassLoader;
19 18
20 import com.google.common.base.Throwables; 19 import com.google.common.base.Throwables;
21 import com.mumfrey.liteloader.LiteMod; 20 import com.mumfrey.liteloader.LiteMod;
  21 +import com.mumfrey.liteloader.api.ContainerRegistry;
  22 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
22 import com.mumfrey.liteloader.api.EnumerationObserver; 23 import com.mumfrey.liteloader.api.EnumerationObserver;
23 import com.mumfrey.liteloader.api.EnumeratorModule; 24 import com.mumfrey.liteloader.api.EnumeratorModule;
  25 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
24 import com.mumfrey.liteloader.api.LiteAPI; 26 import com.mumfrey.liteloader.api.LiteAPI;
25 -import com.mumfrey.liteloader.api.manager.APIProvider; 27 +import com.mumfrey.liteloader.api.ModClassValidator;
  28 +import com.mumfrey.liteloader.core.api.DefaultClassValidator;
  29 +import com.mumfrey.liteloader.core.api.DefaultEnumeratorPlugin;
26 import com.mumfrey.liteloader.core.event.HandlerList; 30 import com.mumfrey.liteloader.core.event.HandlerList;
27 -import com.mumfrey.liteloader.core.exceptions.OutdatedLoaderException;  
28 import com.mumfrey.liteloader.interfaces.FastIterableDeque; 31 import com.mumfrey.liteloader.interfaces.FastIterableDeque;
29 import com.mumfrey.liteloader.interfaces.Loadable; 32 import com.mumfrey.liteloader.interfaces.Loadable;
30 import com.mumfrey.liteloader.interfaces.LoadableMod; 33 import com.mumfrey.liteloader.interfaces.LoadableMod;
31 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 34 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
32 import com.mumfrey.liteloader.interfaces.TweakContainer; 35 import com.mumfrey.liteloader.interfaces.TweakContainer;
  36 +import com.mumfrey.liteloader.launch.ClassTransformerManager;
33 import com.mumfrey.liteloader.launch.LiteLoaderTweaker; 37 import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
34 import com.mumfrey.liteloader.launch.LoaderEnvironment; 38 import com.mumfrey.liteloader.launch.LoaderEnvironment;
35 import com.mumfrey.liteloader.launch.LoaderProperties; 39 import com.mumfrey.liteloader.launch.LoaderProperties;
@@ -73,55 +77,32 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -73,55 +77,32 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
73 private final LoaderEnvironment environment; 77 private final LoaderEnvironment environment;
74 78
75 private final LoaderProperties properties; 79 private final LoaderProperties properties;
76 -  
77 - private final LiteLoaderTweaker tweaker;  
78 80
79 /** 81 /**
80 * Reference to the launch classloader 82 * Reference to the launch classloader
81 */ 83 */
82 private final LaunchClassLoader classLoader; 84 private final LaunchClassLoader classLoader;
83 -  
84 - /**  
85 - * Classes to load, mapped by class name  
86 - */  
87 - private final Set<ModInfo<LoadableMod<?>>> modsToLoad = new LinkedHashSet<ModInfo<LoadableMod<?>>>();  
88 85
89 /** 86 /**
90 - * Mod containers which are disabled  
91 - */  
92 - private final Map<String, ModInfo<Loadable<?>>> disabledContainers = new HashMap<String, ModInfo<Loadable<?>>>();  
93 -  
94 - /**  
95 - * Mapping of identifiers to mod containers  
96 - */  
97 - private final Map<String, LoadableMod<?>> enabledContainers = new HashMap<String, LoadableMod<?>>();  
98 -  
99 - /**  
100 - * Map of containers which cannot be loaded to reasons 87 + *
101 */ 88 */
102 - private final Set<ModInfo<Loadable<?>>> badContainers = new HashSet<ModInfo<Loadable<?>>>(); 89 + private final List<EnumeratorModule> modules = new ArrayList<EnumeratorModule>();
103 90
104 - /**  
105 - * Containers which have already been checked for potential mod candidates  
106 - */  
107 - private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>(); 91 + private final List<EnumeratorPlugin> plugins = new ArrayList<EnumeratorPlugin>();
108 92
109 - /**  
110 - * Tweaks to inject  
111 - */  
112 - private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>(); 93 + private final ContainerRegistry containers = new Containers();
113 94
114 /** 95 /**
115 - * Other tweak-containing jars which we have injected 96 + * Containers which have already been checked for potential mod candidates
116 */ 97 */
117 - private final List<ModInfo<Loadable<?>>> injectedTweaks = new ArrayList<ModInfo<Loadable<?>>>(); 98 + private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>();
118 99
119 /** 100 /**
120 - * 101 + * Classes to load, mapped by class name
121 */ 102 */
122 - private final List<EnumeratorModule> modules = new ArrayList<EnumeratorModule>(); 103 + private final Set<ModInfo<LoadableMod<?>>> modsToLoad = new LinkedHashSet<ModInfo<LoadableMod<?>>>();
123 104
124 - private final String[] supportedPrefixes; 105 + private final ModClassValidator validator;
125 106
126 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class); 107 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class);
127 108
@@ -136,9 +117,11 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -136,9 +117,11 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
136 { 117 {
137 this.environment = environment; 118 this.environment = environment;
138 this.properties = properties; 119 this.properties = properties;
139 - this.tweaker = (LiteLoaderTweaker)environment.getTweaker();  
140 this.classLoader = classLoader; 120 this.classLoader = classLoader;
141 - this.supportedPrefixes = this.getSupportedPrefixes(environment); 121 + this.validator = this.getValidator(environment);
  122 +
  123 + this.initModules(environment);
  124 + this.registerPlugin(new DefaultEnumeratorPlugin());
142 125
143 // Initialise observers 126 // Initialise observers
144 this.observers.addAll(environment.getAPIAdapter().getPreInitObservers(EnumerationObserver.class)); 127 this.observers.addAll(environment.getAPIAdapter().getPreInitObservers(EnumerationObserver.class));
@@ -150,12 +133,30 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -150,12 +133,30 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
150 /** 133 /**
151 * @param environment 134 * @param environment
152 */ 135 */
153 - private String[] getSupportedPrefixes(LoaderEnvironment environment) 136 + private ModClassValidator getValidator(LoaderEnvironment environment)
154 { 137 {
155 List<String> prefixes = new ArrayList<String>(); 138 List<String> prefixes = new ArrayList<String>();
156 139
157 for (LiteAPI api : environment.getAPIProvider().getAPIs()) 140 for (LiteAPI api : environment.getAPIProvider().getAPIs())
158 { 141 {
  142 + String prefix = api.getModClassPrefix();
  143 + if (prefix != null)
  144 + {
  145 + LiteLoaderLogger.info("Adding supported mod class prefix '%s'", prefix);
  146 + prefixes.add(prefix);
  147 + }
  148 + }
  149 +
  150 + return new DefaultClassValidator<LiteMod>(LiteMod.class, prefixes);
  151 + }
  152 +
  153 + /**
  154 + * @param environment
  155 + */
  156 + private void initModules(LoaderEnvironment environment)
  157 + {
  158 + for (LiteAPI api : environment.getAPIProvider().getAPIs())
  159 + {
159 List<EnumeratorModule> apiModules = api.getEnumeratorModules(); 160 List<EnumeratorModule> apiModules = api.getEnumeratorModules();
160 161
161 if (apiModules != null) 162 if (apiModules != null)
@@ -165,18 +166,9 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -165,18 +166,9 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
165 this.registerModule(module); 166 this.registerModule(module);
166 } 167 }
167 } 168 }
168 -  
169 - String prefix = api.getModClassPrefix();  
170 - if (prefix != null)  
171 - {  
172 - LiteLoaderLogger.info("Adding supported mod class prefix '%s'", prefix);  
173 - prefixes.add(prefix);  
174 - }  
175 } 169 }
176 -  
177 - return prefixes.toArray(new String[prefixes.size()]);  
178 } 170 }
179 - 171 +
180 private void checkState(EnumeratorState state, String action) 172 private void checkState(EnumeratorState state, String action)
181 { 173 {
182 if (this.state != state) 174 if (this.state != state)
@@ -243,6 +235,19 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -243,6 +235,19 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
243 } 235 }
244 } 236 }
245 237
  238 + @Override
  239 + public void registerPlugin(EnumeratorPlugin plugin)
  240 + {
  241 + this.checkState(EnumeratorState.INIT, "registerPlugin");
  242 +
  243 + if (plugin != null && !this.plugins.contains(plugin))
  244 + {
  245 + LiteLoaderLogger.info("Registering enumerator plugin %s: [%s]", plugin.getClass().getSimpleName(), plugin);
  246 + this.plugins.add(plugin);
  247 + plugin.init(this.environment, this.properties);
  248 + }
  249 + }
  250 +
246 /** 251 /**
247 * Get the list of all enumerated mod classes to load 252 * Get the list of all enumerated mod classes to load
248 */ 253 */
@@ -250,7 +255,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -250,7 +255,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
250 public Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad() 255 public Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad()
251 { 256 {
252 this.checkState(EnumeratorState.FINALISED, "getModsToLoad"); 257 this.checkState(EnumeratorState.FINALISED, "getModsToLoad");
253 -  
254 return Collections.unmodifiableSet(this.modsToLoad); 258 return Collections.unmodifiableSet(this.modsToLoad);
255 } 259 }
256 260
@@ -261,27 +265,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -261,27 +265,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
261 public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers() 265 public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
262 { 266 {
263 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers"); 267 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers");
264 -  
265 - return this.disabledContainers.values(); 268 + return this.containers.getDisabledContainers();
266 } 269 }
267 270
268 @Override 271 @Override
269 public Collection<? extends ModInfo<Loadable<?>>> getBadContainers() 272 public Collection<? extends ModInfo<Loadable<?>>> getBadContainers()
270 { 273 {
271 this.checkState(EnumeratorState.FINALISED, "getBadContainers"); 274 this.checkState(EnumeratorState.FINALISED, "getBadContainers");
272 -  
273 - return this.badContainers; 275 + return this.containers.getBadContainers();
274 } 276 }
275 277
276 /** 278 /**
277 * Get the list of injected tweak containers 279 * Get the list of injected tweak containers
278 */ 280 */
279 @Override 281 @Override
280 - public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks() 282 + public Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
281 { 283 {
282 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks"); 284 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks");
283 -  
284 - return this.injectedTweaks; 285 + return this.containers.getInjectedTweaks();
285 } 286 }
286 287
287 /** 288 /**
@@ -304,7 +305,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -304,7 +305,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
304 public String getModMetaData(Class<? extends LiteMod> modClass, String metaDataKey, String defaultValue) 305 public String getModMetaData(Class<? extends LiteMod> modClass, String metaDataKey, String defaultValue)
305 { 306 {
306 this.checkState(EnumeratorState.FINALISED, "getModMetaData"); 307 this.checkState(EnumeratorState.FINALISED, "getModMetaData");
307 -  
308 return this.getContainerForMod(modClass).getMetaValue(metaDataKey, defaultValue); 308 return this.getContainerForMod(modClass).getMetaValue(metaDataKey, defaultValue);
309 } 309 }
310 310
@@ -315,17 +315,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -315,17 +315,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
315 public LoadableMod<?> getContainer(String identifier) 315 public LoadableMod<?> getContainer(String identifier)
316 { 316 {
317 this.checkState(EnumeratorState.FINALISED, "getContainer"); 317 this.checkState(EnumeratorState.FINALISED, "getContainer");
318 -  
319 - return this.getContainerById(identifier);  
320 - }  
321 -  
322 - /**  
323 - * @param identifier  
324 - */  
325 - private LoadableMod<?> getContainerById(String identifier)  
326 - {  
327 - LoadableMod<?> container = this.enabledContainers.get(identifier);  
328 - return container != null ? container : LoadableMod.NONE; 318 + return this.containers.getEnabledContainer(identifier);
329 } 319 }
330 320
331 /** 321 /**
@@ -335,7 +325,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -335,7 +325,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
335 public LoadableMod<?> getContainer(Class<? extends LiteMod> modClass) 325 public LoadableMod<?> getContainer(Class<? extends LiteMod> modClass)
336 { 326 {
337 this.checkState(EnumeratorState.FINALISED, "getContainer"); 327 this.checkState(EnumeratorState.FINALISED, "getContainer");
338 -  
339 return this.getContainerForMod(modClass); 328 return this.getContainerForMod(modClass);
340 } 329 }
341 330
@@ -403,7 +392,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -403,7 +392,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
403 { 392 {
404 this.gotoState(EnumeratorState.INJECT); 393 this.gotoState(EnumeratorState.INJECT);
405 394
406 - for (TweakContainer<File> tweakContainer : this.tweakContainers) 395 + for (TweakContainer<File> tweakContainer : this.containers.getTweakContainers())
407 { 396 {
408 this.addTweaksFrom(tweakContainer); 397 this.addTweaksFrom(tweakContainer);
409 } 398 }
@@ -418,36 +407,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -418,36 +407,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
418 try 407 try
419 { 408 {
420 this.gotoState(EnumeratorState.INJECT); 409 this.gotoState(EnumeratorState.INJECT);
421 -  
422 - for (EnumeratorModule module : this.modules)  
423 - {  
424 - try  
425 - {  
426 - module.injectIntoClassLoader(this, this.classLoader);  
427 - }  
428 - catch (Throwable th)  
429 - {  
430 - LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst injecting", module.getClass().getName());  
431 - }  
432 - } 410 + this.injectIntoClassLoader();
433 411
434 this.gotoState(EnumeratorState.REGISTER); 412 this.gotoState(EnumeratorState.REGISTER);
435 -  
436 - for (EnumeratorModule module : this.modules)  
437 - {  
438 - try  
439 - {  
440 - module.registerMods(this, this.classLoader);  
441 - }  
442 - catch (Throwable th)  
443 - {  
444 - LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst registering mods", module.getClass().getName());  
445 - }  
446 - }  
447 -  
448 - LiteLoaderLogger.info("Mod class discovery completed"); 413 + this.registerMods();
449 414
450 this.gotoState(EnumeratorState.FINALISED); 415 this.gotoState(EnumeratorState.FINALISED);
  416 + LiteLoaderLogger.info("Mod class discovery completed");
451 } 417 }
452 catch (IllegalStateException ex) // wut? 418 catch (IllegalStateException ex) // wut?
453 { 419 {
@@ -459,6 +425,42 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -459,6 +425,42 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
459 } 425 }
460 } 426 }
461 427
  428 + /**
  429 + *
  430 + */
  431 + private void injectIntoClassLoader()
  432 + {
  433 + for (EnumeratorModule module : this.modules)
  434 + {
  435 + try
  436 + {
  437 + module.injectIntoClassLoader(this, this.classLoader);
  438 + }
  439 + catch (Throwable th)
  440 + {
  441 + LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst injecting", module.getClass().getName());
  442 + }
  443 + }
  444 + }
  445 +
  446 + /**
  447 + *
  448 + */
  449 + private void registerMods()
  450 + {
  451 + for (EnumeratorModule module : this.modules)
  452 + {
  453 + try
  454 + {
  455 + module.registerMods(this, this.classLoader);
  456 + }
  457 + catch (Throwable th)
  458 + {
  459 + LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst registering mods", module.getClass().getName());
  460 + }
  461 + }
  462 + }
  463 +
462 /* (non-Javadoc) 464 /* (non-Javadoc)
463 * @see com.mumfrey.liteloader.interfaces.ModularEnumerator#registerModContainer(com.mumfrey.liteloader.interfaces.LoadableMod) 465 * @see com.mumfrey.liteloader.interfaces.ModularEnumerator#registerModContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
464 */ 466 */
@@ -469,7 +471,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -469,7 +471,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
469 471
470 if (container != null) 472 if (container != null)
471 { 473 {
472 - if (!container.isEnabled(this.environment)) 474 + if (!this.checkEnabled(container))
473 { 475 {
474 this.registerDisabledContainer(container, DisabledReason.USER_DISABLED); 476 this.registerDisabledContainer(container, DisabledReason.USER_DISABLED);
475 return false; 477 return false;
@@ -492,14 +494,12 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -492,14 +494,12 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
492 494
493 return true; 495 return true;
494 } 496 }
495 - 497 +
496 @Override 498 @Override
497 public void registerBadContainer(Loadable<?> container, String reason) 499 public void registerBadContainer(Loadable<?> container, String reason)
498 { 500 {
499 this.checkState(EnumeratorState.DISCOVER, "registerBadContainer"); 501 this.checkState(EnumeratorState.DISCOVER, "registerBadContainer");
500 -  
501 - BadContainerInfo badMod = new BadContainerInfo(container, reason);  
502 - this.badContainers.add(badMod); 502 + this.containers.registerBadContainer(container, reason);
503 } 503 }
504 504
505 /** 505 /**
@@ -508,10 +508,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -508,10 +508,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
508 protected void registerEnabledContainer(LoadableMod<?> container) 508 protected void registerEnabledContainer(LoadableMod<?> container)
509 { 509 {
510 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer"); 510 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer");
511 -  
512 - this.disabledContainers.remove(container.getIdentifier());  
513 - this.enabledContainers.put(container.getIdentifier(), container);  
514 - 511 + this.containers.registerEnabledContainer(container);
515 this.observers.all().onRegisterEnabledContainer(this, container); 512 this.observers.all().onRegisterEnabledContainer(this, container);
516 } 513 }
517 514
@@ -523,10 +520,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -523,10 +520,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
523 this.checkState(EnumeratorState.DISCOVER, "registerDisabledContainer"); 520 this.checkState(EnumeratorState.DISCOVER, "registerDisabledContainer");
524 521
525 LiteLoaderLogger.info(Verbosity.REDUCED, reason.getMessage(container)); 522 LiteLoaderLogger.info(Verbosity.REDUCED, reason.getMessage(container));
526 -  
527 - this.enabledContainers.remove(container.getIdentifier());  
528 - this.disabledContainers.put(container.getIdentifier(), new NonMod(container, false));  
529 - 523 + this.containers.registerDisabledContainer(container, reason);
530 this.observers.all().onRegisterDisabledContainer(this, container, reason); 524 this.observers.all().onRegisterDisabledContainer(this, container, reason);
531 } 525 }
532 526
@@ -544,7 +538,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -544,7 +538,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
544 return false; 538 return false;
545 } 539 }
546 540
547 - this.tweakContainers.add(container); 541 + this.containers.registerTweakContainer(container);
548 this.observers.all().onRegisterTweakContainer(this, container); 542 this.observers.all().onRegisterTweakContainer(this, container);
549 return true; 543 return true;
550 } 544 }
@@ -577,14 +571,14 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -577,14 +571,14 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
577 String tweakClass = container.getTweakClassName(); 571 String tweakClass = container.getTweakClassName();
578 int tweakPriority = container.getTweakPriority(); 572 int tweakPriority = container.getTweakPriority();
579 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides tweakClass '%s', adding to Launch queue with priority %d", container.getName(), tweakClass, tweakPriority); 573 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides tweakClass '%s', adding to Launch queue with priority %d", container.getName(), tweakClass, tweakPriority);
580 - if (this.tweaker.addCascadedTweaker(tweakClass, tweakPriority)) 574 + if (this.environment.addCascadedTweaker(tweakClass, tweakPriority))
581 { 575 {
582 LiteLoaderLogger.info(Verbosity.REDUCED, "tweakClass '%s' was successfully added", tweakClass); 576 LiteLoaderLogger.info(Verbosity.REDUCED, "tweakClass '%s' was successfully added", tweakClass);
583 container.injectIntoClassPath(this.classLoader, true); 577 container.injectIntoClassPath(this.classLoader, true);
584 578
585 if (container.isExternalJar()) 579 if (container.isExternalJar())
586 { 580 {
587 - this.injectedTweaks.add(new NonMod(container, true)); 581 + this.containers.registerInjectedTweak(container);
588 } 582 }
589 583
590 String[] classPathEntries = container.getClassPathEntries(); 584 String[] classPathEntries = container.getClassPathEntries();
@@ -618,7 +612,8 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -618,7 +612,8 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
618 for (String classTransformerClass : classTransformerClasses) 612 for (String classTransformerClass : classTransformerClasses)
619 { 613 {
620 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides classTransformer '%s', adding to class loader", container.getName(), classTransformerClass); 614 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides classTransformer '%s', adding to class loader", container.getName(), classTransformerClass);
621 - if (this.tweaker.getTransformerManager().injectTransformer(classTransformerClass)) 615 + ClassTransformerManager transformerManager = this.environment.getTransformerManager();
  616 + if (transformerManager != null && transformerManager.injectTransformer(classTransformerClass))
622 { 617 {
623 LiteLoaderLogger.info(Verbosity.REDUCED, "classTransformer '%s' was successfully added", classTransformerClass); 618 LiteLoaderLogger.info(Verbosity.REDUCED, "classTransformer '%s' was successfully added", classTransformerClass);
624 container.injectIntoClassPath(this.classLoader, true); 619 container.injectIntoClassPath(this.classLoader, true);
@@ -638,7 +633,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -638,7 +633,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
638 { 633 {
639 this.checkState(EnumeratorState.REGISTER, "registerModsFrom"); 634 this.checkState(EnumeratorState.REGISTER, "registerModsFrom");
640 635
641 - if (this.disabledContainers.containsValue(container)) 636 + if (this.containers.isDisabledContainer(container))
642 { 637 {
643 throw new IllegalArgumentException("Attempted to register mods from a disabled container '" + container.getName() + "'"); 638 throw new IllegalArgumentException("Attempted to register mods from a disabled container '" + container.getName() + "'");
644 } 639 }
@@ -651,7 +646,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -651,7 +646,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
651 646
652 this.enumeratedContainers.add(container); 647 this.enumeratedContainers.add(container);
653 648
654 - LinkedList<Class<? extends LiteMod>> modClasses = LiteLoaderEnumerator.<LiteMod>getSubclassesFor(container, this.classLoader, LiteMod.class, this.supportedPrefixes); 649 + List<Class<? extends LiteMod>> modClasses = new ArrayList<Class<? extends LiteMod>>();
  650 +
  651 + for (EnumeratorPlugin plugin : this.plugins)
  652 + {
  653 + List<Class<? extends LiteMod>> classes = plugin.getClasses(container, this.classLoader, this.validator);
  654 + LiteLoaderLogger.debug("Plugin %s returned %d classes for %s", plugin.getClass(), classes.size(), container.getDisplayName());
  655 + modClasses.addAll(classes);
  656 + }
  657 +
655 for (Class<? extends LiteMod> modClass : modClasses) 658 for (Class<? extends LiteMod> modClass : modClasses)
656 { 659 {
657 Mod mod = new Mod(container, modClass); 660 Mod mod = new Mod(container, modClass);
@@ -661,9 +664,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -661,9 +664,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
661 if (modClasses.size() > 0) 664 if (modClasses.size() > 0)
662 { 665 {
663 LiteLoaderLogger.info("Found %d potential matches", modClasses.size()); 666 LiteLoaderLogger.info("Found %d potential matches", modClasses.size());
664 -  
665 - this.disabledContainers.remove(container.getIdentifier());  
666 - this.enabledContainers.put(container.getIdentifier(), container); 667 + this.containers.registerEnabledContainer(container);
667 } 668 }
668 } 669 }
669 670
@@ -684,169 +685,37 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -684,169 +685,37 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
684 685
685 this.observers.all().onModAdded(this, mod); 686 this.observers.all().onModAdded(this, mod);
686 } 687 }
687 -  
688 - /**  
689 - * Enumerate classes on the classpath which are subclasses of the specified  
690 - * class  
691 - *  
692 - * @param superClass  
693 - */  
694 - private static <T> LinkedList<Class<? extends T>> getSubclassesFor(LoadableMod<?> container, ClassLoader classloader, Class<T> superClass, String[] supportedPrefixes) 688 +
  689 + private boolean checkEnabled(LoadableMod<?> container)
695 { 690 {
696 - LinkedList<Class<? extends T>> classes = new LinkedList<Class<? extends T>>();  
697 -  
698 - if (container != null) 691 + for (EnumeratorPlugin plugin : this.plugins)
699 { 692 {
700 - try  
701 - {  
702 - for (String fullClassName : container.getContainedClassNames())  
703 - {  
704 - boolean isDefaultPackage = fullClassName.lastIndexOf('.') == -1;  
705 - String className = isDefaultPackage ? fullClassName : fullClassName.substring(fullClassName.lastIndexOf('.') + 1);  
706 - if (supportedPrefixes == null || supportedPrefixes.length == 0 || LiteLoaderEnumerator.startsWithAny(className, supportedPrefixes))  
707 - {  
708 - LiteLoaderEnumerator.<T>checkAndAddClass(classloader, superClass, classes, fullClassName);  
709 - }  
710 - }  
711 - }  
712 - catch (OutdatedLoaderException ex)  
713 - {  
714 - classes.clear();  
715 - LiteLoaderLogger.info(Verbosity.REDUCED, "Error searching in '%s', missing API component '%s', your loader is probably out of date", container, ex.getMessage());  
716 - }  
717 - catch (Throwable th)  
718 - {  
719 - LiteLoaderLogger.warning(th, "Enumeration error");  
720 - } 693 + if (!plugin.checkEnabled(this.containers, container)) return false;
721 } 694 }
722 695
723 - return classes; 696 + return true;
724 } 697 }
725 698
726 - /**  
727 - * @param classloader  
728 - * @param superClass  
729 - * @param classes  
730 - * @param className  
731 - * @throws OutdatedLoaderException  
732 - */  
733 - private static <T> void checkAndAddClass(ClassLoader classloader, Class<T> superClass, LinkedList<Class<? extends T>> classes, String className) throws OutdatedLoaderException 699 + @Override
  700 + public boolean checkAPIRequirements(LoadableMod<?> container)
734 { 701 {
735 - if (className.indexOf('$') > -1)  
736 - return;  
737 -  
738 - try 702 + for (EnumeratorPlugin plugin : this.plugins)
739 { 703 {
740 - Class<?> subClass = classloader.loadClass(className);  
741 -  
742 - if (subClass != null && !superClass.equals(subClass) && superClass.isAssignableFrom(subClass) && !subClass.isInterface() && !classes.contains(subClass))  
743 - {  
744 - @SuppressWarnings("unchecked")  
745 - Class<? extends T> matchingClass = (Class<? extends T>)subClass;  
746 - classes.add(matchingClass);  
747 - } 704 + if (!plugin.checkAPIRequirements(this.containers, container)) return false;
748 } 705 }
749 - catch (Throwable th)  
750 - {  
751 - if (th.getCause() != null)  
752 - {  
753 - String missingClassName = th.getCause().getMessage();  
754 - if (th.getCause() instanceof NoClassDefFoundError && missingClassName != null)  
755 - {  
756 - if (missingClassName.startsWith("com/mumfrey/liteloader/"))  
757 - {  
758 - throw new OutdatedLoaderException(missingClassName.substring(missingClassName.lastIndexOf('/') + 1));  
759 - }  
760 -  
761 -// String mahClassName = LiteLoaderEnumerator.getMissingAPIHandlerClass(classloader, className);  
762 -// if (mahClassName != null)  
763 -// {  
764 -// LiteLoaderEnumerator.checkAndAddClass(classloader, superClass, classes, mahClassName);  
765 -// return;  
766 -// }  
767 - }  
768 - }  
769 -  
770 - LiteLoaderLogger.warning(th, "checkAndAddClass error while checking '%s'", className);  
771 - }  
772 - }  
773 -  
774 -// private static String getMissingAPIHandlerClass(ClassLoader classloader, String className)  
775 -// {  
776 -// String mahTypeDescriptor = Type.getDescriptor(MissingAPIHandlerClass.class);  
777 -//  
778 -// if (classloader instanceof LaunchClassLoader)  
779 -// {  
780 -// try  
781 -// {  
782 -// byte[] basicClass = ((LaunchClassLoader)classloader).getClassBytes(className);  
783 -// ClassNode classNode = LiteLoaderEnumerator.readClass(basicClass);  
784 -//  
785 -// if (classNode.invisibleAnnotations != null)  
786 -// {  
787 -// for (AnnotationNode annotation : classNode.invisibleAnnotations)  
788 -// {  
789 -// if (mahTypeDescriptor.equals(annotation.desc))  
790 -// {  
791 -// return LiteLoaderEnumerator.<String>getAnnotationValue(annotation, "value");  
792 -// }  
793 -// }  
794 -// }  
795 -// }  
796 -// catch (IOException ex)  
797 -// {  
798 -// ex.printStackTrace();  
799 -// }  
800 -// }  
801 -//  
802 -// return null;  
803 -// }  
804 -//  
805 -// /**  
806 -// * @param basicClass  
807 -// * @return  
808 -// */  
809 -// private static ClassNode readClass(byte[] basicClass)  
810 -// {  
811 -// ClassReader classReader = new ClassReader(basicClass);  
812 -// ClassNode classNode = new ClassNode();  
813 -// classReader.accept(classNode, ClassReader.EXPAND_FRAMES);  
814 -// return classNode;  
815 -// }  
816 -//  
817 -// /**  
818 -// * @param annotation  
819 -// * @param key  
820 -// * @return  
821 -// */  
822 -// @SuppressWarnings("unchecked")  
823 -// private static <T> T getAnnotationValue(AnnotationNode annotation, String key)  
824 -// {  
825 -// boolean getNextValue = false;  
826 -// for (Object value : annotation.values)  
827 -// {  
828 -// if (getNextValue) return (T)value;  
829 -// if (value.equals(key)) getNextValue = true;  
830 -// }  
831 -// return null;  
832 -// }  
833 - 706 +
  707 + return true;
  708 + }
  709 +
834 @Override 710 @Override
835 - public boolean checkAPIRequirements(LoadableMod<?> container) 711 + public boolean checkDependencies(LoadableMod<?> container)
836 { 712 {
837 - boolean result = true;  
838 - APIProvider apiProvider = this.environment.getAPIProvider();  
839 -  
840 - for (String identifier : container.getRequiredAPIs()) 713 + for (EnumeratorPlugin plugin : this.plugins)
841 { 714 {
842 - if (!apiProvider.isAPIAvailable(identifier))  
843 - {  
844 - container.registerMissingAPI(identifier);  
845 - result = false;  
846 - } 715 + if (!plugin.checkDependencies(this.containers, container)) return false;
847 } 716 }
848 717
849 - return result; 718 + return true;
850 } 719 }
851 720
852 @SuppressWarnings("unchecked") 721 @SuppressWarnings("unchecked")
@@ -860,59 +729,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -860,59 +729,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
860 return true; 729 return true;
861 } 730 }
862 731
863 - @Override  
864 - public boolean checkDependencies(LoadableMod<?> base)  
865 - {  
866 - if (base == null || !base.hasDependencies()) return true;  
867 -  
868 - HashSet<String> circularDependencySet = new HashSet<String>();  
869 - circularDependencySet.add(base.getIdentifier());  
870 -  
871 - boolean result = this.checkDependencies(base, base, circularDependencySet);  
872 - LiteLoaderLogger.info(Verbosity.REDUCED, "Dependency check for %s %s", base.getIdentifier(), result ? "passed" : "failed");  
873 -  
874 - return result;  
875 - }  
876 -  
877 - private boolean checkDependencies(LoadableMod<?> base, LoadableMod<?> container, Set<String> circularDependencySet)  
878 - {  
879 - if (container.getDependencies().size() == 0)  
880 - return true;  
881 -  
882 - boolean result = true;  
883 -  
884 - for (String dependency : container.getDependencies())  
885 - {  
886 - if (!circularDependencySet.contains(dependency))  
887 - {  
888 - circularDependencySet.add(dependency);  
889 -  
890 - LoadableMod<?> dependencyContainer = this.getContainerById(dependency);  
891 - if (dependencyContainer != LoadableMod.NONE)  
892 - {  
893 - if (this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), dependency))  
894 - {  
895 - result &= this.checkDependencies(base, dependencyContainer, circularDependencySet);  
896 - }  
897 - else  
898 - {  
899 -// LiteLoaderLogger.warning("Dependency %s required by %s is currently disabled", dependency, base.getIdentifier());  
900 - base.registerMissingDependency(dependency);  
901 - result = false;  
902 - }  
903 - }  
904 - else  
905 - {  
906 -// LiteLoaderLogger.info("Dependency %s for %s is was not located, no container ", dependency, base.getIdentifier());  
907 - base.registerMissingDependency(dependency);  
908 - result = false;  
909 - }  
910 - }  
911 - }  
912 -  
913 - return result;  
914 - }  
915 -  
916 public static String getModClassName(LiteMod mod) 732 public static String getModClassName(LiteMod mod)
917 { 733 {
918 return LiteLoaderEnumerator.getModClassName(mod.getClass()); 734 return LiteLoaderEnumerator.getModClassName(mod.getClass());
@@ -922,12 +738,4 @@ public class LiteLoaderEnumerator implements LoaderEnumerator @@ -922,12 +738,4 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
922 { 738 {
923 return mod.getSimpleName().substring(7); 739 return mod.getSimpleName().substring(7);
924 } 740 }
925 -  
926 - private static boolean startsWithAny(String string, String[] candidates)  
927 - {  
928 - for (String candidate : candidates)  
929 - if (string.startsWith(candidate)) return true;  
930 -  
931 - return false;  
932 - }  
933 } 741 }
934 \ No newline at end of file 742 \ No newline at end of file
java/common/com/mumfrey/liteloader/core/LiteLoaderMods.java
1 package com.mumfrey.liteloader.core; 1 package com.mumfrey.liteloader.core;
2 2
3 import java.io.File; 3 import java.io.File;
  4 +import java.util.Collection;
4 import java.util.Collections; 5 import java.util.Collections;
5 import java.util.Deque; 6 import java.util.Deque;
6 import java.util.HashMap; 7 import java.util.HashMap;
@@ -19,7 +20,6 @@ import com.mumfrey.liteloader.interfaces.LoadableMod; @@ -19,7 +20,6 @@ import com.mumfrey.liteloader.interfaces.LoadableMod;
19 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 20 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
20 import com.mumfrey.liteloader.interfaces.TweakContainer; 21 import com.mumfrey.liteloader.interfaces.TweakContainer;
21 import com.mumfrey.liteloader.launch.ClassTransformerManager; 22 import com.mumfrey.liteloader.launch.ClassTransformerManager;
22 -import com.mumfrey.liteloader.launch.LiteLoaderTweaker;  
23 import com.mumfrey.liteloader.launch.LoaderEnvironment; 23 import com.mumfrey.liteloader.launch.LoaderEnvironment;
24 import com.mumfrey.liteloader.launch.LoaderProperties; 24 import com.mumfrey.liteloader.launch.LoaderProperties;
25 import com.mumfrey.liteloader.modconfig.ConfigManager; 25 import com.mumfrey.liteloader.modconfig.ConfigManager;
@@ -57,11 +57,6 @@ public class LiteLoaderMods @@ -57,11 +57,6 @@ public class LiteLoaderMods
57 protected final LoaderEnumerator enumerator; 57 protected final LoaderEnumerator enumerator;
58 58
59 /** 59 /**
60 - * Tweaker  
61 - */  
62 - private final LiteLoaderTweaker tweaker;  
63 -  
64 - /**  
65 * Configuration manager 60 * Configuration manager
66 */ 61 */
67 private final ConfigManager configManager; 62 private final ConfigManager configManager;
@@ -113,7 +108,6 @@ public class LiteLoaderMods @@ -113,7 +108,6 @@ public class LiteLoaderMods
113 this.loader = loader; 108 this.loader = loader;
114 this.environment = environment; 109 this.environment = environment;
115 this.enumerator = environment.getEnumerator(); 110 this.enumerator = environment.getEnumerator();
116 - this.tweaker = (LiteLoaderTweaker)environment.getTweaker();  
117 this.properties = properties; 111 this.properties = properties;
118 this.configManager = configManager; 112 this.configManager = configManager;
119 } 113 }
@@ -179,7 +173,7 @@ public class LiteLoaderMods @@ -179,7 +173,7 @@ public class LiteLoaderMods
179 /** 173 /**
180 * Get the list of injected tweak containers 174 * Get the list of injected tweak containers
181 */ 175 */
182 - public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks() 176 + public Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
183 { 177 {
184 return this.enumerator.getInjectedTweaks(); 178 return this.enumerator.getInjectedTweaks();
185 } 179 }
@@ -672,7 +666,7 @@ public class LiteLoaderMods @@ -672,7 +666,7 @@ public class LiteLoaderMods
672 */ 666 */
673 private void validateModTransformers() 667 private void validateModTransformers()
674 { 668 {
675 - ClassTransformerManager transformerManager = this.tweaker.getTransformerManager(); 669 + ClassTransformerManager transformerManager = this.environment.getTransformerManager();
676 Set<String> injectedTransformers = transformerManager.getInjectedTransformers(); 670 Set<String> injectedTransformers = transformerManager.getInjectedTransformers();
677 671
678 for (Mod mod : this.loadedMods) 672 for (Mod mod : this.loadedMods)
@@ -728,7 +722,7 @@ public class LiteLoaderMods @@ -728,7 +722,7 @@ public class LiteLoaderMods
728 { 722 {
729 if (!mod.hasClassTransformers()) return false; 723 if (!mod.hasClassTransformers()) return false;
730 724
731 - Set<String> injectedTransformers = this.tweaker.getTransformerManager().getInjectedTransformers(); 725 + Set<String> injectedTransformers = this.environment.getTransformerManager().getInjectedTransformers();
732 List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames(); 726 List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames();
733 727
734 for (String modTransformer : modTransformers) 728 for (String modTransformer : modTransformers)
java/common/com/mumfrey/liteloader/core/api/DefaultClassValidator.java 0 → 100644
  1 +package com.mumfrey.liteloader.core.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.mumfrey.liteloader.api.ModClassValidator;
  6 +
  7 +public class DefaultClassValidator<T> implements ModClassValidator
  8 +{
  9 + private final Class<T> superClass;
  10 +
  11 + private final List<String> supportedPrefixes;
  12 +
  13 + public DefaultClassValidator(Class<T> superClass, List<String> supportedPrefixes)
  14 + {
  15 + this.supportedPrefixes = supportedPrefixes;
  16 + this.superClass = superClass;
  17 + }
  18 +
  19 + @Override
  20 + public boolean validateName(String className)
  21 + {
  22 + return this.supportedPrefixes == null || this.supportedPrefixes.size() == 0 || DefaultClassValidator.startsWithAny(className, this.supportedPrefixes);
  23 + }
  24 +
  25 + @Override
  26 + public boolean validateClass(ClassLoader classLoader, Class<?> candidateClass)
  27 + {
  28 + return (candidateClass != null && !this.superClass.equals(candidateClass) && this.superClass.isAssignableFrom(candidateClass) && !candidateClass.isInterface());
  29 + }
  30 +
  31 + private static boolean startsWithAny(String string, List<String> candidates)
  32 + {
  33 + for (String candidate : candidates)
  34 + if (string.startsWith(candidate)) return true;
  35 +
  36 + return false;
  37 + }
  38 +}
java/common/com/mumfrey/liteloader/core/api/DefaultEnumeratorPlugin.java 0 → 100644
  1 +package com.mumfrey.liteloader.core.api;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.HashSet;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import com.mumfrey.liteloader.api.ContainerRegistry;
  9 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
  10 +import com.mumfrey.liteloader.api.ModClassValidator;
  11 +import com.mumfrey.liteloader.api.manager.APIProvider;
  12 +import com.mumfrey.liteloader.core.exceptions.OutdatedLoaderException;
  13 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  14 +import com.mumfrey.liteloader.launch.LoaderEnvironment;
  15 +import com.mumfrey.liteloader.launch.LoaderProperties;
  16 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  17 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger.Verbosity;
  18 +
  19 +public class DefaultEnumeratorPlugin implements EnumeratorPlugin
  20 +{
  21 + private LoaderEnvironment environment;
  22 +
  23 + @Override
  24 + public void init(LoaderEnvironment environment, LoaderProperties properties)
  25 + {
  26 + this.environment = environment;
  27 + }
  28 +
  29 + @Override
  30 + public boolean checkEnabled(ContainerRegistry containers, LoadableMod<?> container)
  31 + {
  32 + return container.isEnabled(this.environment);
  33 + }
  34 +
  35 + @Override
  36 + public boolean checkAPIRequirements(ContainerRegistry containers, LoadableMod<?> container)
  37 + {
  38 + boolean result = true;
  39 + APIProvider apiProvider = this.environment.getAPIProvider();
  40 +
  41 + for (String identifier : container.getRequiredAPIs())
  42 + {
  43 + if (!apiProvider.isAPIAvailable(identifier))
  44 + {
  45 + container.registerMissingAPI(identifier);
  46 + result = false;
  47 + }
  48 + }
  49 +
  50 + return result;
  51 + }
  52 +
  53 + @Override
  54 + public boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base)
  55 + {
  56 + if (base == null || !base.hasDependencies()) return true;
  57 +
  58 + HashSet<String> circularDependencySet = new HashSet<String>();
  59 + circularDependencySet.add(base.getIdentifier());
  60 +
  61 + boolean result = this.checkDependencies(containers, base, base, circularDependencySet);
  62 + LiteLoaderLogger.info(Verbosity.REDUCED, "Dependency check for %s %s", base.getIdentifier(), result ? "passed" : "failed");
  63 +
  64 + return result;
  65 + }
  66 +
  67 + private boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base, LoadableMod<?> container, Set<String> circularDependencySet)
  68 + {
  69 + if (container.getDependencies().size() == 0)
  70 + return true;
  71 +
  72 + boolean result = true;
  73 +
  74 + for (String dependency : container.getDependencies())
  75 + {
  76 + if (!circularDependencySet.contains(dependency))
  77 + {
  78 + circularDependencySet.add(dependency);
  79 +
  80 + LoadableMod<?> dependencyContainer = containers.getEnabledContainer(dependency);
  81 + if (dependencyContainer != LoadableMod.NONE)
  82 + {
  83 + String identifier = dependency;
  84 + if (this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier))
  85 + {
  86 + result &= this.checkDependencies(containers, base, dependencyContainer, circularDependencySet);
  87 + }
  88 + else
  89 + {
  90 +// LiteLoaderLogger.warning("Dependency %s required by %s is currently disabled", dependency, base.getIdentifier());
  91 + base.registerMissingDependency(dependency);
  92 + result = false;
  93 + }
  94 + }
  95 + else
  96 + {
  97 +// LiteLoaderLogger.info("Dependency %s for %s is was not located, no container ", dependency, base.getIdentifier());
  98 + base.registerMissingDependency(dependency);
  99 + result = false;
  100 + }
  101 + }
  102 + }
  103 +
  104 + return result;
  105 + }
  106 +
  107 + /**
  108 + * Enumerate classes on the classpath which are subclasses of the specified
  109 + * class
  110 + *
  111 + * @param superClass
  112 + */
  113 + @Override
  114 + public <T> List<Class<? extends T>> getClasses(LoadableMod<?> container, ClassLoader classloader, ModClassValidator validator)
  115 + {
  116 + List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
  117 +
  118 + if (container != null)
  119 + {
  120 + try
  121 + {
  122 + for (String fullClassName : container.getContainedClassNames())
  123 + {
  124 + boolean isDefaultPackage = fullClassName.lastIndexOf('.') == -1;
  125 + String className = isDefaultPackage ? fullClassName : fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
  126 + if (validator.validateName(className))
  127 + {
  128 + Class<? extends T> clazz = DefaultEnumeratorPlugin.<T>checkClass(classloader, validator, fullClassName);
  129 + if (clazz != null && !classes.contains(clazz))
  130 + {
  131 + classes.add(clazz);
  132 + }
  133 + }
  134 + }
  135 + }
  136 + catch (OutdatedLoaderException ex)
  137 + {
  138 + classes.clear();
  139 + LiteLoaderLogger.info(Verbosity.REDUCED, "Error searching in '%s', missing API component '%s', your loader is probably out of date", container, ex.getMessage());
  140 + }
  141 + catch (Throwable th)
  142 + {
  143 + LiteLoaderLogger.warning(th, "Enumeration error");
  144 + }
  145 + }
  146 +
  147 + return classes;
  148 + }
  149 +
  150 + @SuppressWarnings("unchecked")
  151 + private static <T> Class<? extends T> checkClass(ClassLoader classLoader, ModClassValidator validator, String className) throws OutdatedLoaderException
  152 + {
  153 + if (className.indexOf('$') > -1)
  154 + return null;
  155 +
  156 + try
  157 + {
  158 + Class<?> candidateClass = classLoader.loadClass(className);
  159 +
  160 + if (validator.validateClass(classLoader, candidateClass))
  161 + {
  162 + return (Class<? extends T>)candidateClass;
  163 + }
  164 + }
  165 + catch (Throwable th)
  166 + {
  167 + th.printStackTrace();
  168 +
  169 + if (th.getCause() != null)
  170 + {
  171 + String missingClassName = th.getCause().getMessage();
  172 + if (th.getCause() instanceof NoClassDefFoundError && missingClassName != null)
  173 + {
  174 + if (missingClassName.startsWith("com/mumfrey/liteloader/"))
  175 + {
  176 + throw new OutdatedLoaderException(missingClassName.substring(missingClassName.lastIndexOf('/') + 1));
  177 + }
  178 + }
  179 + }
  180 +
  181 + LiteLoaderLogger.warning(th, "checkAndAddClass error while checking '%s'", className);
  182 + }
  183 +
  184 + return null;
  185 + }
  186 +}
java/common/com/mumfrey/liteloader/interfaces/LoaderEnumerator.java
1 package com.mumfrey.liteloader.interfaces; 1 package com.mumfrey.liteloader.interfaces;
2 2
3 import java.util.Collection; 3 import java.util.Collection;
4 -import java.util.List;  
5 import java.util.Map; 4 import java.util.Map;
6 5
7 import com.mumfrey.liteloader.LiteMod; 6 import com.mumfrey.liteloader.LiteMod;
@@ -14,26 +13,6 @@ import com.mumfrey.liteloader.core.ModInfo; @@ -14,26 +13,6 @@ import com.mumfrey.liteloader.core.ModInfo;
14 */ 13 */
15 public interface LoaderEnumerator extends ModularEnumerator 14 public interface LoaderEnumerator extends ModularEnumerator
16 { 15 {
17 - public enum DisabledReason  
18 - {  
19 - UNKNOWN("Container %s is could not be loaded for UNKNOWN reason"),  
20 - USER_DISABLED("Container %s is disabled"),  
21 - MISSING_DEPENDENCY("Container %s is missing one or more dependencies"),  
22 - MISSING_API("Container %s is missing one or more required APIs");  
23 -  
24 - private final String message;  
25 -  
26 - private DisabledReason(String message)  
27 - {  
28 - this.message = message;  
29 - }  
30 -  
31 - public String getMessage(LoadableMod<?> container)  
32 - {  
33 - return String.format(this.message, container);  
34 - }  
35 - }  
36 -  
37 /** 16 /**
38 * Perform pre-init tasks (container discovery) 17 * Perform pre-init tasks (container discovery)
39 */ 18 */
@@ -109,7 +88,7 @@ public interface LoaderEnumerator extends ModularEnumerator @@ -109,7 +88,7 @@ public interface LoaderEnumerator extends ModularEnumerator
109 /** 88 /**
110 * Get all tweakers which were injected 89 * Get all tweakers which were injected
111 */ 90 */
112 - public abstract List<? extends ModInfo<Loadable<?>>> getInjectedTweaks(); 91 + public abstract Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
113 92
114 /** 93 /**
115 * Get the shared modlist data 94 * Get the shared modlist data
java/common/com/mumfrey/liteloader/interfaces/ModularEnumerator.java
@@ -3,6 +3,7 @@ package com.mumfrey.liteloader.interfaces; @@ -3,6 +3,7 @@ package com.mumfrey.liteloader.interfaces;
3 import java.io.File; 3 import java.io.File;
4 4
5 import com.mumfrey.liteloader.api.EnumeratorModule; 5 import com.mumfrey.liteloader.api.EnumeratorModule;
  6 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
6 import com.mumfrey.liteloader.core.ModInfo; 7 import com.mumfrey.liteloader.core.ModInfo;
7 8
8 /** 9 /**
@@ -20,6 +21,13 @@ public interface ModularEnumerator @@ -20,6 +21,13 @@ public interface ModularEnumerator
20 public abstract void registerModule(EnumeratorModule module); 21 public abstract void registerModule(EnumeratorModule module);
21 22
22 /** 23 /**
  24 + * Register a plugin into the enumerator
  25 + *
  26 + * @param plugin
  27 + */
  28 + public abstract void registerPlugin(EnumeratorPlugin plugin);
  29 +
  30 + /**
23 * @param container 31 * @param container
24 */ 32 */
25 public abstract boolean registerModContainer(LoadableMod<?> container); 33 public abstract boolean registerModContainer(LoadableMod<?> container);
java/common/com/mumfrey/liteloader/launch/LoaderEnvironment.java
@@ -2,8 +2,6 @@ package com.mumfrey.liteloader.launch; @@ -2,8 +2,6 @@ package com.mumfrey.liteloader.launch;
2 2
3 import java.io.File; 3 import java.io.File;
4 4
5 -import net.minecraft.launchwrapper.ITweaker;  
6 -  
7 import com.mumfrey.liteloader.api.manager.APIAdapter; 5 import com.mumfrey.liteloader.api.manager.APIAdapter;
8 import com.mumfrey.liteloader.api.manager.APIProvider; 6 import com.mumfrey.liteloader.api.manager.APIProvider;
9 import com.mumfrey.liteloader.core.EnabledModsList; 7 import com.mumfrey.liteloader.core.EnabledModsList;
@@ -75,8 +73,7 @@ public interface LoaderEnvironment extends GameEnvironment @@ -75,8 +73,7 @@ public interface LoaderEnvironment extends GameEnvironment
75 */ 73 */
76 public abstract File inflectVersionedConfigPath(LiteLoaderVersion version); 74 public abstract File inflectVersionedConfigPath(LiteLoaderVersion version);
77 75
78 - /**  
79 - * Get the tweaker  
80 - */  
81 - public abstract ITweaker getTweaker(); 76 + public abstract boolean addCascadedTweaker(String tweakClass, int priority);
  77 +
  78 + public abstract ClassTransformerManager getTransformerManager();
82 } 79 }
java/common/com/mumfrey/liteloader/transformers/event/json/ModEvents.java
@@ -8,13 +8,13 @@ import java.util.Map; @@ -8,13 +8,13 @@ import java.util.Map;
8 import net.minecraft.launchwrapper.Launch; 8 import net.minecraft.launchwrapper.Launch;
9 9
10 import com.google.common.base.Charsets; 10 import com.google.common.base.Charsets;
  11 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
11 import com.mumfrey.liteloader.api.EnumerationObserver; 12 import com.mumfrey.liteloader.api.EnumerationObserver;
12 import com.mumfrey.liteloader.core.ModInfo; 13 import com.mumfrey.liteloader.core.ModInfo;
13 import com.mumfrey.liteloader.core.api.LoadableModFile; 14 import com.mumfrey.liteloader.core.api.LoadableModFile;
14 import com.mumfrey.liteloader.interfaces.LoadableMod; 15 import com.mumfrey.liteloader.interfaces.LoadableMod;
15 import com.mumfrey.liteloader.interfaces.LoaderEnumerator; 16 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
16 import com.mumfrey.liteloader.interfaces.TweakContainer; 17 import com.mumfrey.liteloader.interfaces.TweakContainer;
17 -import com.mumfrey.liteloader.interfaces.LoaderEnumerator.DisabledReason;  
18 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 18 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
19 19
20 public class ModEvents implements EnumerationObserver 20 public class ModEvents implements EnumerationObserver