diff --git a/README.MD b/README.MD index 4accac3..81ebc74 100644 --- a/README.MD +++ b/README.MD @@ -16,4 +16,8 @@ This mod also contains patches for the following mods: Mods not listed here may or may not work. A good rule of thumb is that the more invasive a mod is, the higher the chance it's broken without a patch once the IDs exceed 4096 and 32000. -If you find any crashes or incompatibilities, don't hesitate to open an issue. \ No newline at end of file +If you find any crashes or incompatibilities, don't hesitate to open an issue. + +## Dependencies +- [FalsePatternLib](https://www.curseforge.com/minecraft/mc-mods/falsepatternlib) +- Either [SpongeMixins](https://www.curseforge.com/minecraft/mc-mods/spongemixins) or [Grimoire](https://www.curseforge.com/minecraft/mc-mods/grimoire-api) diff --git a/dependencies.gradle b/dependencies.gradle index 089e802..20a9fae 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,6 +4,8 @@ dependencies { } annotationProcessor("org.projectlombok:lombok:1.18.22") + compile("com.falsepattern:falsepatternlib-mc1.7.10:0.5.0:dev") + compileOnly("curse.maven:undergroundbiomesconstructs-72744:2304497") { transitive = false } diff --git a/repositories.gradle b/repositories.gradle index a23eb3b..cbb0403 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -8,4 +8,8 @@ repositories { includeGroup "curse.maven" } } + maven { + name = "mavenpattern" + url = "https://maven.falsepattern.com/" + } } diff --git a/src/main/java/com/falsepattern/endlessids/EndlessIDs.java b/src/main/java/com/falsepattern/endlessids/EndlessIDs.java index dbddd64..554b586 100644 --- a/src/main/java/com/falsepattern/endlessids/EndlessIDs.java +++ b/src/main/java/com/falsepattern/endlessids/EndlessIDs.java @@ -2,5 +2,9 @@ package com.falsepattern.endlessids; import cpw.mods.fml.common.Mod; -@Mod(modid = Tags.MODID, name = Tags.MODNAME, version = Tags.VERSION) +@Mod(modid = Tags.MODID, + version = Tags.VERSION, + name = Tags.MODNAME, + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:falsepatternlib@[0.5.0,);") public class EndlessIDs {} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/MinecraftURLClassPath.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/MinecraftURLClassPath.java deleted file mode 100644 index ac8abf0..0000000 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/MinecraftURLClassPath.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.falsepattern.endlessids.mixin.plugin; - -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.ModClassLoader; -import net.minecraft.launchwrapper.LaunchClassLoader; -import sun.misc.URLClassPath; - -import java.io.File; -import java.lang.reflect.Field; -import java.nio.file.Path; -/** - * Backport from spongemixins 1.3 - */ -public final class MinecraftURLClassPath { - /** - * Utility to manipulate the minecraft URL ClassPath - */ - - private static final Field modClassLoaderField; - private static final Field loaderinstanceField; - private static final Field mainClassLoaderField; - private static final Field ucpField; - private static final ModClassLoader modClassLoader; - private static final LaunchClassLoader mainClassLoader; - private static final URLClassPath ucp; - - static { - try { - modClassLoaderField = Loader.class.getDeclaredField("modClassLoader"); - modClassLoaderField.setAccessible(true); - - loaderinstanceField = Loader.class.getDeclaredField("instance"); - loaderinstanceField.setAccessible(true); - - mainClassLoaderField = ModClassLoader.class.getDeclaredField("mainClassLoader"); - mainClassLoaderField.setAccessible(true); - - ucpField = LaunchClassLoader.class.getSuperclass().getDeclaredField("ucp"); - ucpField.setAccessible(true); - - Object loader = loaderinstanceField.get(null); - modClassLoader = (ModClassLoader)modClassLoaderField.get(loader); - mainClassLoader = (LaunchClassLoader)mainClassLoaderField.get(modClassLoader); - ucp = (URLClassPath)ucpField.get(mainClassLoader); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Adds a Jar to the Minecraft URL ClassPath - * - Needed when using mixins on classes outside of Minecraft or other coremods - */ - public static void addJar(File pathToJar) throws Exception { - ucp.addURL(pathToJar.toURI().toURL()); - } - - private MinecraftURLClassPath() { - } - - -} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java index 9440426..01fc59e 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java @@ -1,127 +1,70 @@ package com.falsepattern.endlessids.mixin.plugin; import com.falsepattern.endlessids.IEConfig; -import cpw.mods.fml.relauncher.FMLLaunchHandler; +import com.falsepattern.lib.mixin.IMixin; +import com.falsepattern.lib.mixin.ITargetedMod; +import lombok.Getter; +import lombok.RequiredArgsConstructor; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.function.Supplier; +import java.util.function.Predicate; -public enum Mixin { +import static com.falsepattern.lib.mixin.IMixin.PredicateHelpers.*; + +@RequiredArgsConstructor +public enum Mixin implements IMixin { //region Minecraft //region common //region storage - AnvilChunkLoaderMixin(builder(Side.COMMON).mixin("vanilla.storage.AnvilChunkLoaderMixin")), - ExtendedBlockStorageMixin(builder(Side.COMMON).mixin("vanilla.storage.ExtendedBlockStorageMixin")), - ItemStackMixin(builder(Side.COMMON).mixin("vanilla.storage.ItemStackMixin")), + AnvilChunkLoaderMixin(Side.COMMON, always(), "vanilla.storage.AnvilChunkLoaderMixin"), + ExtendedBlockStorageMixin(Side.COMMON, always(), "vanilla.storage.ExtendedBlockStorageMixin"), + ItemStackMixin(Side.COMMON, always(), "vanilla.storage.ItemStackMixin"), //endregion storage //region networking - PacketBufferMixin(builder(Side.COMMON).mixin("vanilla.networking.PacketBufferMixin")), - PlayerControllerMPMixin(builder(Side.COMMON).mixin("vanilla.networking.PlayerControllerMPMixin")), - S21PacketChunkDataMixin(builder(Side.COMMON).mixin("vanilla.networking.S21PacketChunkDataMixin")), - S22PacketMultiBlockChangeMixin(builder(Side.COMMON).mixin("vanilla.networking.S22PacketMultiBlockChangeMixin")), - S24PacketBlockActionMixin(builder(Side.COMMON).mixin("vanilla.networking.S24PacketBlockActionMixin")), - S26PacketMapChunkBulkMixin(builder(Side.COMMON).mixin("vanilla.networking.S26PacketMapChunkBulkMixin")), + PacketBufferMixin(Side.COMMON, always(), "vanilla.networking.PacketBufferMixin"), + PlayerControllerMPMixin(Side.COMMON, always(), "vanilla.networking.PlayerControllerMPMixin"), + S21PacketChunkDataMixin(Side.COMMON, always(), "vanilla.networking.S21PacketChunkDataMixin"), + S22PacketMultiBlockChangeMixin(Side.COMMON, always(), "vanilla.networking.S22PacketMultiBlockChangeMixin"), + S24PacketBlockActionMixin(Side.COMMON, always(), "vanilla.networking.S24PacketBlockActionMixin"), + S26PacketMapChunkBulkMixin(Side.COMMON, always(), "vanilla.networking.S26PacketMapChunkBulkMixin"), //endregion networking //region misc - BlockFireMixin(builder(Side.COMMON).mixin("vanilla.misc.BlockFireMixin")), - DataWatcherMixin(builder(Side.COMMON).condition(() -> IEConfig.extendDataWatcher).mixin("vanilla.misc.DataWatcherMixin")), - ItemInWorldManagerMixin(builder(Side.COMMON).mixin("vanilla.misc.ItemInWorldManagerMixin")), - StatListMixin(builder(Side.COMMON).mixin("vanilla.misc.StatListMixin")), - WorldMixin(builder(Side.COMMON).mixin("vanilla.misc.WorldMixin")), + BlockFireMixin(Side.COMMON, always(), "vanilla.misc.BlockFireMixin"), + DataWatcherMixin(Side.COMMON, condition(() -> IEConfig.extendDataWatcher), "vanilla.misc.DataWatcherMixin"), + ItemInWorldManagerMixin(Side.COMMON, always(), "vanilla.misc.ItemInWorldManagerMixin"), + StatListMixin(Side.COMMON, always(), "vanilla.misc.StatListMixin"), + WorldMixin(Side.COMMON, always(), "vanilla.misc.WorldMixin"), //endregion misc //endregion common //region client - ChunkMixin(builder(Side.CLIENT).mixin("vanilla.ChunkMixin")), - NetHandlerPlayClientMixin(builder(Side.CLIENT).mixin("vanilla.NetHandlerPlayClientMixin")), - RenderGlobalMixin(builder(Side.CLIENT).mixin("vanilla.RenderGlobalMixin")), + ChunkMixin(Side.CLIENT, always(), "vanilla.ChunkMixin"), + NetHandlerPlayClientMixin(Side.CLIENT, always(), "vanilla.NetHandlerPlayClientMixin"), + RenderGlobalMixin(Side.CLIENT, always(), "vanilla.RenderGlobalMixin"), //endregion client //endregion Minecraft //region UBC->common - OreUBifierMixin(builder(Side.COMMON).target(TargetedMod.UBC).mixin("ubc.OreUBifierMixin")), - BiomeUndergroundDecoratorMixin(builder(Side.COMMON).target(TargetedMod.UBC).mixin("ubc.BiomeUndergroundDecoratorMixin")), + OreUBifierMixin(Side.COMMON, require(TargetedMod.UBC), "ubc.OreUBifierMixin"), + BiomeUndergroundDecoratorMixin(Side.COMMON, require(TargetedMod.UBC), "ubc.BiomeUndergroundDecoratorMixin"), //endregion UBC->common //region CoFHLib->common - CofhBlockHelperMixin(builder(Side.COMMON).target(TargetedMod.COFHLIB).mixin("cofhlib.BlockHelperMixin")), + CofhBlockHelperMixin(Side.COMMON, require(TargetedMod.COFHLIB), "cofhlib.BlockHelperMixin"), //endregion CoFHLib->common //region DragonAPI->common - BlockPropertiesMixin(builder(Side.COMMON).target(TargetedMod.DRAGONAPI).mixin("dragonapi.BlockPropertiesMixin")), + BlockPropertiesMixin(Side.COMMON, require(TargetedMod.DRAGONAPI), "dragonapi.BlockPropertiesMixin"), //endregion DragonAPI->common //region MFQM->common - MFQMMixin(builder(Side.COMMON).target(TargetedMod.MFQM).mixin("mfqm.MFQMMixin")), - MFQMDataWatcherMixin(builder(Side.COMMON).target(TargetedMod.MFQM).condition(() -> IEConfig.extendDataWatcher).mixin("mfqm.MFQMDataWatcherMixin")), + MFQMMixin(Side.COMMON, require(TargetedMod.MFQM), "mfqm.MFQMMixin"), + MFQMDataWatcherMixin(Side.COMMON, require(TargetedMod.MFQM).and(condition(() -> IEConfig.extendDataWatcher)), "mfqm.MFQMDataWatcherMixin"), //endregion MFQM->common //region WorldEdit->common - BaseBlockMixin(builder(Side.COMMON).target(TargetedMod.WORLDEDIT).mixin("worldedit.BaseBlockMixin")), + BaseBlockMixin(Side.COMMON, require(TargetedMod.WORLDEDIT), "worldedit.BaseBlockMixin"), //endregion WorldEdit->common ; - - public final String mixin; - public final Set targetedMods; - public final Set avoidedMods; - public final Set> allowConditions; + @Getter private final Side side; - - Mixin(Builder builder) { - this.mixin = builder.mixin; - this.targetedMods = builder.targetedMods; - this.avoidedMods = builder.avoidedMods; - this.allowConditions = builder.allowConditions; - this.side = builder.side; - } - - public boolean shouldLoad(List loadedMods) { - return (side == Side.COMMON - || side == Side.SERVER && FMLLaunchHandler.side().isServer() - || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) - && loadedMods.containsAll(targetedMods) - && avoidedMods.stream().noneMatch(loadedMods::contains) - && allowConditions.stream().allMatch(Supplier::get); - } - - - @SuppressWarnings("SameParameterValue") - private static Builder builder(Side side) { - return new Builder(side); - } - - private static class Builder { - public String mixin; - public Side side; - public final Set targetedMods = new HashSet<>(); - public final Set avoidedMods = new HashSet<>(); - public final Set> allowConditions = new HashSet<>(); - - public Builder(Side side) { - this.side = side; - } - - public Builder mixin(String mixinClass) { - mixin = side.name().toLowerCase() + "." + mixinClass; - return this; - } - - public Builder target(TargetedMod mod) { - targetedMods.add(mod); - return this; - } - - public Builder avoid(TargetedMod mod) { - avoidedMods.add(mod); - return this; - } - - public Builder condition(Supplier cond) { - allowConditions.add(cond); - return this; - } - } - - private enum Side { - COMMON, - CLIENT, - SERVER - } + @Getter + private final Predicate> filter; + @Getter + private final String mixin; } diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/MixinPlugin.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/MixinPlugin.java index d024249..0e10827 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/MixinPlugin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/MixinPlugin.java @@ -1,138 +1,23 @@ package com.falsepattern.endlessids.mixin.plugin; import com.falsepattern.endlessids.Tags; -import lombok.val; -import net.minecraft.launchwrapper.Launch; -import org.apache.logging.log4j.LogManager; +import com.falsepattern.lib.mixin.IMixin; +import com.falsepattern.lib.mixin.IMixinPlugin; +import com.falsepattern.lib.mixin.ITargetedMod; +import lombok.Getter; import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.lib.tree.ClassNode; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.nio.file.Files.walk; - -public class MixinPlugin implements IMixinConfigPlugin { - - private static final Logger LOG = LogManager.getLogger(Tags.MODNAME + " Mixin Loader"); - private static final Path MODS_DIRECTORY_PATH = new File(Launch.minecraftHome, "mods/").toPath(); +public class MixinPlugin implements IMixinPlugin { + @Getter + private final Logger logger = IMixinPlugin.createLogger(Tags.MODNAME); @Override - public void onLoad(String mixinPackage) { - + public IMixin[] getMixinEnumValues() { + return Mixin.values(); } @Override - public String getRefMapperConfig() { - return null; - } - - @Override - public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - return true; - } - - @Override - public void acceptTargets(Set myTargets, Set otherTargets) { - - } - - // This method return a List of mixins. Every mixins in this list will be loaded. - @Override - public List getMixins() { - val isDevelopmentEnvironment = (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); - - val loadedMods = - Arrays.stream(TargetedMod.values()) - .filter(mod -> mod == TargetedMod.VANILLA - || (mod.loadInDevelopment && isDevelopmentEnvironment) - || loadJarOf(mod)) - .collect(Collectors.toList()); - - for (TargetedMod mod : TargetedMod.values()) { - if(loadedMods.contains(mod)) { - LOG.info("Found " + mod.modName + "! Integrating now..."); - } - else { - LOG.info("Could not find " + mod.modName + "! Skipping integration...."); - } - } - - val mixins = new ArrayList(); - for (val mixin : Mixin.values()) { - if (mixin.shouldLoad(loadedMods)) { - mixins.add(mixin.mixin); - LOG.info("Loading mixin: " + mixin.mixin); - } - } - return mixins; - } - - private int grimoireDetected = -1; - - private boolean loadJarOf(final TargetedMod mod) { - try { - val jar = findJarOf(mod); - if(jar == null) { - LOG.info("Jar not found for " + mod); - return false; - } - - LOG.info("Attempting to add " + jar + " to the URL Class Path"); - if (!jar.exists()) { - throw new FileNotFoundException(jar.toString()); - } - if (grimoireDetected < 0) { - try { - Class.forName("io.github.crucible.grimoire.Grimoire", false, getClass().getClassLoader()); - grimoireDetected = 1; - } catch (ClassNotFoundException ignored) { - grimoireDetected = 0; - } - } - if (grimoireDetected == 1) { - LOG.info("Not adding " + jar + " to the URL Class Path, because Grimoire breaks our utility class."); - } else { - MinecraftURLClassPath.addJar(jar); - } - return true; - } - catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public static File findJarOf(final TargetedMod mod) { - try { - return walk(MODS_DIRECTORY_PATH) - .filter(mod::isMatchingJar) - .map(Path::toFile) - .findFirst() - .orElse(null); - } - catch (IOException e) { - e.printStackTrace(); - return null; - } - } - - @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - - } - - @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - + public ITargetedMod[] getTargetedModEnumValues() { + return TargetedMod.values(); } } diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java index 205d5cd..50ce6c2 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/TargetedMod.java @@ -1,47 +1,27 @@ package com.falsepattern.endlessids.mixin.plugin; -import com.google.common.io.Files; -import lombok.val; +import com.falsepattern.lib.mixin.ITargetedMod; +import lombok.Getter; +import lombok.RequiredArgsConstructor; -import java.nio.file.Path; +import java.util.function.Predicate; -public enum TargetedMod { +import static com.falsepattern.lib.mixin.ITargetedMod.PredicateHelpers.*; - VANILLA("Minecraft", "", "", true), - UBC("Underground Biomes Constructs", "undergroundbiomesconstructs-", "", false), - COFHLIB("CoFH Lib", "cofhlib-", "", false), - DRAGONAPI("DragonAPI", "dragonapi", "", false), - MFQM("More Fun Quicksand Mod", "morefunquicksandmod-", "", false), - WORLDEDIT("WorldEdit", "worldedit-", "", false), +@RequiredArgsConstructor +public enum TargetedMod implements ITargetedMod { + + UBC("Underground Biomes Constructs", false, startsWith("undergroundbiomesconstructs-")), + COFHLIB("CoFH Lib", false, startsWith("cofhlib-")), + DRAGONAPI("DragonAPI", false, startsWith("dragonapi")), + MFQM("More Fun Quicksand Mod", false, startsWith("morefunquicksandmod-")), + WORLDEDIT("WorldEdit", false, startsWith("worldedit-")), ; - public final String modName; - public final String jarNamePrefixLowercase; - public final String jarNameContainsLowercase; - - public final boolean loadInDevelopment; - - TargetedMod(String modName, String jarNamePrefix, String jarNameContains, boolean loadInDevelopment) { - this.modName = modName; - this.jarNamePrefixLowercase = jarNamePrefix.toLowerCase(); - this.jarNameContainsLowercase = jarNameContains.toLowerCase(); - this.loadInDevelopment = loadInDevelopment; - } - - @SuppressWarnings("UnstableApiUsage") - public boolean isMatchingJar(Path path) { - val pathString = path.toString(); - val nameLowerCase = Files.getNameWithoutExtension(pathString).toLowerCase(); - val fileExtension = Files.getFileExtension(pathString); - - return "jar".equals(fileExtension) && nameLowerCase.startsWith(jarNamePrefixLowercase) && nameLowerCase.contains(jarNameContainsLowercase); - } - - @Override - public String toString() { - return "TargetedMod{" + - "modName='" + modName + '\'' + - ", jarNamePrefixLowercase='" + jarNamePrefixLowercase + '\'' + - '}'; - } + @Getter + private final String modName; + @Getter + private final boolean loadInDevelopment; + @Getter + private final Predicate condition; }