Skip to content

Commit

Permalink
Improved Module usability (#2146)
Browse files Browse the repository at this point in the history
  • Loading branch information
kumquat-ir authored Nov 5, 2023
1 parent 90b4b9d commit b15f0ce
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 5 deletions.
24 changes: 24 additions & 0 deletions src/main/java/gregtech/api/modules/GregTechModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,47 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* All of your {@link IGregTechModule} classes must be annotated with this to be registered.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GregTechModule {

/**
* The ID of this module. Must be unique within its container.
*/
String moduleID();

/**
* The ID of the container to associate this module with.
*/
String containerID();

/**
* A human-readable name for this module.
*/
String name();

/**
* A list of mod IDs that this module depends on. If any mods specified are not present, the module will not load.
*/
String[] modDependencies() default {};

/**
* Whether this module is the "core" module for its container.
* Each container must have exactly one core module, which will be loaded before all other modules in the container.
* <p>
* Core modules should not have mod dependencies.
*/
boolean coreModule() default false;

String author() default "";

String version() default "";

/**
* A lang key to use for the description of this module in the module configuration file.
*/
String descriptionKey() default "";
}
20 changes: 20 additions & 0 deletions src/main/java/gregtech/api/modules/IGregTechModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,18 @@
import java.util.List;
import java.util.Set;

/**
* All modules must implement this interface.
* <p>
* Provides methods for responding to FML lifecycle events, adding event bus subscriber classes, and processing IMC messages.
*/
public interface IGregTechModule {

/**
* What other modules this module depends on.
* <p>
* e.g. <code>new ResourceLocation("gregtech", "foo_module")</code> represents a dependency on the module "foo_module" in the container "gregtech"
*/
@Nonnull
default Set<ResourceLocation> getDependencyUids() {
return Collections.emptySet();
Expand Down Expand Up @@ -46,9 +56,16 @@ default void serverStopping(FMLServerStoppingEvent event) {
default void serverStopped(FMLServerStoppedEvent event) {
}

/**
* Register packets using GregTech's packet handling API here.
*/
default void registerPackets() {
}

/**
* @return A list of classes to subscribe to the Forge event bus.
* As the class gets subscribed, not any specific instance, event handlers must be static!
*/
@Nonnull
default List<Class<?>> getEventBusSubscribers() {
return Collections.emptyList();
Expand All @@ -58,6 +75,9 @@ default boolean processIMC(FMLInterModComms.IMCMessage message) {
return false;
}

/**
* @return A logger to use for this module.
*/
@Nonnull
Logger getLogger();
}
3 changes: 3 additions & 0 deletions src/main/java/gregtech/api/modules/IModuleContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@

public interface IModuleContainer {

/**
* The ID of this container. If this is your mod's only container, you should use your mod ID to prevent collisions.
*/
String getID();
}
14 changes: 14 additions & 0 deletions src/main/java/gregtech/api/modules/ModuleContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gregtech.api.modules;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotate your {@link IModuleContainer} with this for it to be automatically registered.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModuleContainer {
}
35 changes: 30 additions & 5 deletions src/main/java/gregtech/modules/ModuleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

public class ModuleManager implements IModuleManager {

Expand All @@ -21,7 +22,7 @@ public class ModuleManager implements IModuleManager {
//private static final String MODULE_CFG_CATEGORY_NAME = "modules";
//private static File configFolder;

private final Map<String, IModuleContainer> containers = new HashMap<>();
private Map<String, IModuleContainer> containers = new LinkedHashMap<>();
private final Map<ResourceLocation, IGregTechModule> sortedModules = new LinkedHashMap<>();
private final Set<IGregTechModule> loadedModules = new LinkedHashSet<>();

Expand Down Expand Up @@ -77,6 +78,14 @@ public void registerContainer(IModuleContainer container) {
}

public void setup(ASMDataTable asmDataTable, File configDirectory) {
// find and register all containers registered with the @ModuleContainer annotation, then sort them by container name
discoverContainers(asmDataTable);
containers = containers.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new
));

currentStage = ModuleStage.M_SETUP;
//configFolder = new File(configDirectory, GTValues.MODID);
Map<String, List<IGregTechModule>> modules = getModules(asmDataTable);
Expand Down Expand Up @@ -204,8 +213,8 @@ public void processIMC(ImmutableList<FMLInterModComms.IMCMessage> messages) {
private void configureModules(Map<String, List<IGregTechModule>> modules) {
//Locale locale = Locale.getDefault();
//Locale.setDefault(Locale.ENGLISH);
Set<ResourceLocation> toLoad = new HashSet<>();
Set<IGregTechModule> modulesToLoad = new HashSet<>();
Set<ResourceLocation> toLoad = new LinkedHashSet<>();
Set<IGregTechModule> modulesToLoad = new LinkedHashSet<>();
//Configuration config = getConfiguration();

for (IModuleContainer container : containers.values()) {
Expand Down Expand Up @@ -259,7 +268,7 @@ private void configureModules(Map<String, List<IGregTechModule>> modules) {
}
} while (changed);

// Sort modules
// Sort modules by their module dependencies
do {
changed = false;
iterator = modulesToLoad.iterator();
Expand Down Expand Up @@ -326,7 +335,23 @@ private List<IGregTechModule> getInstances(ASMDataTable table) {
logger.info("Module {} is missing at least one of mod dependencies: {}, skipping loading...", moduleID, modDependencies);
}
}
return instances;
return instances.stream().sorted((m1, m2) -> {
GregTechModule m1a = m1.getClass().getAnnotation(GregTechModule.class);
GregTechModule m2a = m2.getClass().getAnnotation(GregTechModule.class);
return (m1a.containerID() + ":" + m1a.moduleID()).compareTo(m2a.containerID() + ":" + m2a.moduleID());
}).collect(Collectors.toCollection(ArrayList::new));
}

private void discoverContainers(ASMDataTable table) {
Set<ASMDataTable.ASMData> dataSet = table.getAll(ModuleContainer.class.getCanonicalName());
for (ASMDataTable.ASMData data : dataSet) {
try {
Class<?> clazz = Class.forName(data.getClassName());
registerContainer((IModuleContainer) clazz.newInstance());
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
logger.error("Could not initialize module container " + data.getClassName(), e);
}
}
}

/*
Expand Down

0 comments on commit b15f0ce

Please sign in to comment.