|
| 1 | +package gregtech.loaders.recipe.component; |
| 2 | + |
| 3 | +import gregtech.api.util.GTLog; |
| 4 | +import net.minecraftforge.fml.common.discovery.ASMDataTable; |
| 5 | +import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData; |
| 6 | + |
| 7 | +import java.lang.reflect.Constructor; |
| 8 | +import java.lang.reflect.Field; |
| 9 | +import java.lang.reflect.Modifier; |
| 10 | +import java.util.Set; |
| 11 | + |
| 12 | +public class AnnotatedComponentHandlerLoader { |
| 13 | + |
| 14 | + public static void discoverAndLoadAnnotatedComponentHandlers(ASMDataTable asmDataTable) { |
| 15 | + Set<ASMData> annotations = asmDataTable.getAll(IComponentHandler.RegisterComponentHandler.class.getName()); |
| 16 | + int componentHandlersRegistered = 0; |
| 17 | + for (ASMData annotationData :annotations) { |
| 18 | + String componentHandlerClassName = annotationData.getClassName(); |
| 19 | + Class<?> componentHandlerClass; |
| 20 | + try { |
| 21 | + componentHandlerClass = Class.forName(componentHandlerClassName); |
| 22 | + } catch (ClassNotFoundException e) { |
| 23 | + GTLog.logger.error("Failed to load annotated component handler class {}. FML annotation data is broken perhaps?", componentHandlerClassName); |
| 24 | + continue; |
| 25 | + } |
| 26 | + String denyReason = null; |
| 27 | + Throwable loadingError = null; |
| 28 | + |
| 29 | + Field instanceField = null; |
| 30 | + Constructor<?> constructor = null; |
| 31 | + |
| 32 | + if (!IComponentHandler.class.isAssignableFrom(componentHandlerClass)) { |
| 33 | + denyReason = "class does not implement IComponentHandler"; |
| 34 | + } else if (Modifier.isAbstract(componentHandlerClass.getModifiers())) { |
| 35 | + denyReason = "class is abstract and cannot be initialized"; |
| 36 | + } |
| 37 | + try { |
| 38 | + instanceField = componentHandlerClass.getField("INSTANCE"); |
| 39 | + if (instanceField.getType() != componentHandlerClass) { |
| 40 | + denyReason = "found INSTANCE field, but it's type is not the same as class type"; |
| 41 | + } else if (!Modifier.isStatic(instanceField.getModifiers())) { |
| 42 | + denyReason = "found INSTANCE field, but it's not static and cannot be used"; |
| 43 | + } |
| 44 | + } catch (NoSuchFieldException noSuchField) { |
| 45 | + try { |
| 46 | + constructor = componentHandlerClass.getConstructor(); |
| 47 | + } catch (NoSuchMethodException noSuchMethod) { |
| 48 | + denyReason = "didn't found public static final INSTANCE field or public no-arg constructor for initialization"; |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + IComponentHandler componentHandler = null; |
| 53 | + if (denyReason == null) { |
| 54 | + if (instanceField != null) { |
| 55 | + try { |
| 56 | + componentHandler = (IComponentHandler) instanceField.get(null); |
| 57 | + } catch (ReflectiveOperationException e) { |
| 58 | + denyReason = "failed to retrieve INSTANCE field value"; |
| 59 | + loadingError = e; |
| 60 | + } |
| 61 | + } else { |
| 62 | + try { |
| 63 | + componentHandler = (IComponentHandler) constructor.newInstance(); |
| 64 | + } catch (ReflectiveOperationException e) { |
| 65 | + denyReason = "failed to initialize component handler"; |
| 66 | + loadingError = e; |
| 67 | + } |
| 68 | + } |
| 69 | + } |
| 70 | + if (denyReason == null) { |
| 71 | + GTLog.logger.info("Registered component handler {}", componentHandler.getClass().getName()); |
| 72 | + IComponentHandler.registerComponentHandler(componentHandler); |
| 73 | + componentHandlersRegistered++; |
| 74 | + } else { |
| 75 | + GTLog.logger.error("Failed to load material handler class {} from {}: {}", |
| 76 | + componentHandlerClassName, annotationData.getCandidate().getModContainer().getName(), denyReason, loadingError); |
| 77 | + GTLog.logger.error("Consult the mod author for a fix on their side."); |
| 78 | + } |
| 79 | + } |
| 80 | + GTLog.logger.info("{} annotated component handlers registered", componentHandlersRegistered); |
| 81 | + } |
| 82 | +} |
0 commit comments