diff options
Diffstat (limited to 'src/main/java/gregtech/mixin')
-rw-r--r-- | src/main/java/gregtech/mixin/LateMixinPlugin.java | 21 | ||||
-rw-r--r-- | src/main/java/gregtech/mixin/Mixin.java | 236 | ||||
-rw-r--r-- | src/main/java/gregtech/mixin/MixinsVariablesHelper.java | 6 | ||||
-rw-r--r-- | src/main/java/gregtech/mixin/TargetedMod.java | 75 |
4 files changed, 338 insertions, 0 deletions
diff --git a/src/main/java/gregtech/mixin/LateMixinPlugin.java b/src/main/java/gregtech/mixin/LateMixinPlugin.java new file mode 100644 index 0000000000..dab8cc5f03 --- /dev/null +++ b/src/main/java/gregtech/mixin/LateMixinPlugin.java @@ -0,0 +1,21 @@ +package gregtech.mixin; + +import java.util.List; +import java.util.Set; + +import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; +import com.gtnewhorizon.gtnhmixins.LateMixin; + +@LateMixin +public class LateMixinPlugin implements ILateMixinLoader { + + @Override + public String getMixinConfig() { + return "mixins.gregtech.late.json"; + } + + @Override + public List<String> getMixins(Set<String> loadedMods) { + return Mixin.getLateMixins(loadedMods); + } +} diff --git a/src/main/java/gregtech/mixin/Mixin.java b/src/main/java/gregtech/mixin/Mixin.java new file mode 100644 index 0000000000..3e0ad23f0a --- /dev/null +++ b/src/main/java/gregtech/mixin/Mixin.java @@ -0,0 +1,236 @@ +package gregtech.mixin; + +import static gregtech.mixin.TargetedMod.VANILLA; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.github.bartimaeusnek.bartworks.common.configs.ConfigHandler; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; + +public enum Mixin { + + // Minecraft + SoundManagerMixin(new Builder("Seeking sound playback") + .addMixinClasses("minecraft.SoundManagerMixin", "minecraft.SoundManagerInnerMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.CLIENT)), + WorldMixin(new Builder("Block update detection").addMixinClasses("minecraft.WorldMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.BOTH)), + StringTranslateMixin(new Builder("Keep track of currently translating mods") + .addMixinClasses("minecraft.StringTranslateMixin", "minecraft.LanguageRegistryMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.BOTH)), + LocaleMixin(new Builder("Keep track of currently translating client mods").addMixinClasses("minecraft.LocaleMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.CLIENT)), + CacheCraftingManagerRecipes( + new Builder("Cache CraftingManager recipes").addMixinClasses("minecraft.CraftingManagerMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> ConfigHandler.enabledPatches[3]) + .setPhase(Phase.EARLY) + .setSide(Side.BOTH)), + CraftingRecipeAccessorMixin(new Builder("Add accessors to crafting recipe types") + .addMixinClasses( + "minecraft.VanillaShapedRecipeMixin", + "minecraft.VanillaShapelessRecipeMixin", + "minecraft.ForgeShapedRecipeMixin", + "minecraft.ForgeShapelessRecipeMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.BOTH)), + BlockStemMixin(new Builder("Stem Crop Block Accessor").addMixinClasses("minecraft.BlockStemMixin") + .addTargetedMod(VANILLA) + .setApplyIf(() -> true) + .setPhase(Phase.EARLY) + .setSide(Side.BOTH)); + + public static final Logger LOGGER = LogManager.getLogger("GregTech-Mixin"); + + private final List<String> mixinClasses; + private final List<TargetedMod> targetedMods; + private final List<TargetedMod> excludedMods; + private final Supplier<Boolean> applyIf; + private final Phase phase; + private final Side side; + + Mixin(Builder builder) { + this.mixinClasses = builder.mixinClasses; + this.targetedMods = builder.targetedMods; + this.excludedMods = builder.excludedMods; + this.applyIf = builder.applyIf; + this.phase = builder.phase; + this.side = builder.side; + if (this.mixinClasses.isEmpty()) { + throw new RuntimeException("No mixin class specified for Mixin : " + this.name()); + } + if (this.targetedMods.isEmpty()) { + throw new RuntimeException("No targeted mods specified for Mixin : " + this.name()); + } + if (this.applyIf == null) { + throw new RuntimeException("No ApplyIf function specified for Mixin : " + this.name()); + } + if (this.phase == null) { + throw new RuntimeException("No Phase specified for Mixin : " + this.name()); + } + if (this.side == null) { + throw new RuntimeException("No Side function specified for Mixin : " + this.name()); + } + } + + public static List<String> getEarlyMixins(Set<String> loadedCoreMods) { + final List<String> mixins = new ArrayList<>(); + final List<String> notLoading = new ArrayList<>(); + for (Mixin mixin : Mixin.values()) { + if (mixin.phase == Phase.EARLY) { + if (mixin.shouldLoad(loadedCoreMods, Collections.emptySet())) { + mixins.addAll(mixin.mixinClasses); + } else { + notLoading.addAll(mixin.mixinClasses); + } + } + } + LOGGER.info("Not loading the following EARLY mixins: {}", notLoading.toString()); + return mixins; + } + + public static List<String> getLateMixins(Set<String> loadedMods) { + // NOTE: Any targetmod here needs a modid, not a coremod id + final List<String> mixins = new ArrayList<>(); + final List<String> notLoading = new ArrayList<>(); + for (Mixin mixin : Mixin.values()) { + if (mixin.phase == Phase.LATE) { + if (mixin.shouldLoad(Collections.emptySet(), loadedMods)) { + mixins.addAll(mixin.mixinClasses); + } else { + notLoading.addAll(mixin.mixinClasses); + } + } + } + LOGGER.info("Not loading the following LATE mixins: {}", notLoading.toString()); + return mixins; + } + + private boolean shouldLoadSide() { + return side == Side.BOTH || (side == Side.SERVER && FMLLaunchHandler.side() + .isServer()) + || (side == Side.CLIENT && FMLLaunchHandler.side() + .isClient()); + } + + private boolean allModsLoaded(List<TargetedMod> targetedMods, Set<String> loadedCoreMods, Set<String> loadedMods) { + if (targetedMods.isEmpty()) return false; + + for (TargetedMod target : targetedMods) { + if (target == TargetedMod.VANILLA) continue; + + // Check coremod first + if (!loadedCoreMods.isEmpty() && target.coreModClass != null + && !loadedCoreMods.contains(target.coreModClass)) return false; + else if (!loadedMods.isEmpty() && target.modId != null && !loadedMods.contains(target.modId)) return false; + } + + return true; + } + + private boolean noModsLoaded(List<TargetedMod> targetedMods, Set<String> loadedCoreMods, Set<String> loadedMods) { + if (targetedMods.isEmpty()) return true; + + for (TargetedMod target : targetedMods) { + if (target == TargetedMod.VANILLA) continue; + + // Check coremod first + if (!loadedCoreMods.isEmpty() && target.coreModClass != null + && loadedCoreMods.contains(target.coreModClass)) return false; + else if (!loadedMods.isEmpty() && target.modId != null && loadedMods.contains(target.modId)) return false; + } + + return true; + } + + private boolean shouldLoad(Set<String> loadedCoreMods, Set<String> loadedMods) { + return (shouldLoadSide() && applyIf.get() + && allModsLoaded(targetedMods, loadedCoreMods, loadedMods) + && noModsLoaded(excludedMods, loadedCoreMods, loadedMods)); + } + + private static class Builder { + + private final String name; + private final List<String> mixinClasses = new ArrayList<>(); + private final List<TargetedMod> targetedMods = new ArrayList<>(); + private final List<TargetedMod> excludedMods = new ArrayList<>(); + private Supplier<Boolean> applyIf = null; + private Phase phase = null; + private Side side = null; + + public Builder(String name) { + this.name = name; + } + + public Builder addMixinClasses(String... mixinClasses) { + this.mixinClasses.addAll(Arrays.asList(mixinClasses)); + return this; + } + + public Builder setPhase(Phase phase) { + if (this.phase != null) { + throw new RuntimeException("Trying to define Phase twice for " + this.name); + } + this.phase = phase; + return this; + } + + public Builder setSide(Side side) { + if (this.side != null) { + throw new RuntimeException("Trying to define Side twice for " + this.name); + } + this.side = side; + return this; + } + + public Builder setApplyIf(Supplier<Boolean> applyIf) { + this.applyIf = applyIf; + return this; + } + + public Builder addTargetedMod(TargetedMod mod) { + this.targetedMods.add(mod); + return this; + } + + public Builder addExcludedMod(TargetedMod mod) { + this.excludedMods.add(mod); + return this; + } + } + + private enum Side { + BOTH, + CLIENT, + SERVER + } + + private enum Phase { + EARLY, + LATE, + } +} diff --git a/src/main/java/gregtech/mixin/MixinsVariablesHelper.java b/src/main/java/gregtech/mixin/MixinsVariablesHelper.java new file mode 100644 index 0000000000..96cc2ee115 --- /dev/null +++ b/src/main/java/gregtech/mixin/MixinsVariablesHelper.java @@ -0,0 +1,6 @@ +package gregtech.mixin; + +public class MixinsVariablesHelper { + + public static String currentlyTranslating = null; +} diff --git a/src/main/java/gregtech/mixin/TargetedMod.java b/src/main/java/gregtech/mixin/TargetedMod.java new file mode 100644 index 0000000000..d8e1018f17 --- /dev/null +++ b/src/main/java/gregtech/mixin/TargetedMod.java @@ -0,0 +1,75 @@ +package gregtech.mixin; + +import cpw.mods.fml.common.Mod; + +public enum TargetedMod { + + // NOTE: This doesn't work - late mods need a modid, not a coremod class + ADVANCED_SOLAR_PANELS("Advanced Solar Panels", null, "AdvancedSolarPanel"), + ANGELICA("Angelica", "com.gtnewhorizons.angelica.loading.AngelicaTweaker", "angelica"), + ARCHAICFIX("ArchaicFix", "org.embeddedt.archaicfix.ArchaicCore", "archaicfix"), + AUTOMAGY("Automagy", null, "Automagy"), + BAUBLES("Baubles", null, "Baubles"), + BETTERHUD("Better HUD", null, "hud"), + BIBLIOCRAFT("Bibliocraft", null, "BiblioCraft"), + BOP("BiomesOPlenty", null, "BiomesOPlenty"), + BUGTORCH("BugTorch", "jss.bugtorch.mixinplugin.BugTorchEarlyMixins", "bugtorch"), + BUKKIT("Bukkit/Thermos", "Bukkit", null), + COFH_CORE("CoFHCore", "cofh.asm.LoadingPlugin", "CoFHCore"), + DAMAGE_INDICATORS("Damage Indicators", null, "DamageIndicatorsMod"), + EXTRATIC("ExtraTiC", null, "ExtraTiC"), + EXTRA_UTILITIES("ExtraUtilities", null, "ExtraUtilities"), + FASTCRAFT("FastCraft", "fastcraft.Tweaker"), + GALACTICRAFT_CORE("GalacticraftCore", "micdoodle8.mods.galacticraft.core.asm.GCLoadingPlugin", "GalacticraftCore"), + GT5U("GregTech5u", null, "gregtech"), // Also matches GT6. + GT6("GregTech6", "gregtech.asm.GT_ASM", "gregapi"), // Can be used to exclude GT6 from the GT5U target. + GTNHLIB("GTNHLib", "com.gtnewhorizon.gtnhlib.core.GTNHLibCore", "gtnhlib"), + HARVESTCRAFT("harvestcraft", null, "harvestcraft"), + HARVESTTHENETHER("harvestthenether", null, "harvestthenether"), + HUNGER_OVERHAUL("HungerOverhaul", null, "HungerOverhaul"), + IC2("IC2", "ic2.core.coremod.IC2core", "IC2"), + IMMERSIVE_ENGINENEERING("Immersive Engineering", null, "ImmersiveEngineering"), + JOURNEYMAP("JourneyMap", null, "journeymap"), + LOTR("The Lord of the rings mod", "lotr.common.coremod.LOTRLoadingPlugin", "lotr"), + LWJGL3IFY("lwjgl3ify", "me.eigenraven.lwjgl3ify.core.Lwjgl3ifyCoremod", "lwjgl3ify"), + MINECHEM("Minechem", null, "minechem"), + MINEFACTORY_RELOADED("MineFactory Reloaded", null, "MineFactoryReloaded"), + MRTJPCORE("MrTJPCore", null, "MrTJPCoreMod"), + NOTENOUGHITEMS("NotEnoughItems", "codechicken.nei.asm.NEICorePlugin", "NotEnoughItems"), + OPTIFINE("Optifine", "optifine.OptiFineForgeTweaker", "Optifine"), + PORTAL_GUN("PortalGun", null, "PortalGun"), + PROJECTE("ProjectE", null, "ProjectE"), + RAILCRAFT("Railcraft", null, "Railcraft"), + THAUMCRAFT("Thaumcraft", null, "Thaumcraft"), // "thaumcraft.codechicken.core.launch.DepLoader" + THERMALDYNAMICS("Thermal Dynamics", null, "ThermalDynamics"), + THERMALEXPANSION("Thermal Expansion", null, "ThermalExpansion"), + TINKERSCONSTRUCT("TConstruct", null, "TConstruct"), + TRAVELLERSGEAR("TravellersGear", null, "TravellersGear"), + VANILLA("Minecraft", null), + VOXELMAP("VoxelMap", "com.thevoxelbox.voxelmap.litemod.VoxelMapTransformer", "voxelmap"), + WITCHERY("Witchery", null, "witchery"), + XAEROWORLDMAP("Xaero's World Map", null, "XaeroWorldMap"), + ZTONES("ZTones", null, "Ztones"); + + /** The "name" in the {@link Mod @Mod} annotation */ + public final String modName; + /** Class that implements the IFMLLoadingPlugin interface */ + public final String coreModClass; + /** The "modid" in the {@link Mod @Mod} annotation */ + public final String modId; + + TargetedMod(String modName, String coreModClass) { + this(modName, coreModClass, null); + } + + TargetedMod(String modName, String coreModClass, String modId) { + this.modName = modName; + this.coreModClass = coreModClass; + this.modId = modId; + } + + @Override + public String toString() { + return "TargetedMod{modName='" + modName + "', coreModClass='" + coreModClass + "', modId='" + modId + "'}"; + } +} |