Add Mixingasm module

This commit is contained in:
makamys committed 2023-02-04 18:43:46 +01:00
1 parent 2e751a1937
commit aa2a36e15a
16 files changed
+434 -2

No files matched your search

+14
View File
@@ -25,3 +25,17 @@ Modifications:
- made reflection support Mixin 0.7.11 - made reflection support Mixin 0.7.11
License: LGPL3 (see LICENSE.LGPLv3) License: LGPL3 (see LICENSE.LGPLv3)
## module-mixingasm
Source: https://github.com/makamys/Mixingasm/tree/v0.2.2
Classes used:
*
Modifications:
- removed update check in MixingasmMod
License: Unlicense (see LICENSE.UNLICENSE)
+24
View File
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
+1 -1
View File
@@ -1,7 +1,7 @@
archivesBaseName = archivesBaseName.replace("-1.7.10", "-all-1.7.10") archivesBaseName = archivesBaseName.replace("-1.7.10", "-all-1.7.10")
// The order of these determines the order embedded core plugins get initialized in // The order of these determines the order embedded core plugins get initialized in
ext.moduleNames = ["module-mixin", "module-compat", "module-spongemixins", "module-gtnhmixins"] ext.moduleNames = ["module-mixin", "module-compat", "module-mixingam", "module-spongemixins", "module-gtnhmixins"]
def getModuleJars() { def getModuleJars() {
return moduleNames.collect { it -> tasks.getByPath(":$it:jar").getOutputs().getFiles().getSingleFile() } return moduleNames.collect { it -> tasks.getByPath(":$it:jar").getOutputs().getFiles().getSingleFile() }
+31
View File
@@ -0,0 +1,31 @@
repositories {
maven {
name = 'sponge'
url = 'https://repo.spongepowered.org/maven/'
}
}
dependencies {
compile('org.spongepowered:mixin:0.7.11-SNAPSHOT')
}
archivesBaseName = archivesBaseName.replace("-1.7.10", "-spongemixins-1.7.10")
jar {
manifest {
attributes (
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
'FMLCorePluginContainsFMLMod': true,
'ForceLoadAsMod': true,
'MixinConfigs': 'mixingasm.mixin.json',
'TweakOrder': 0,
)
}
}
ext.extraVersion = "0.2.2"
version += "+" + ext.extraVersion
minecraft {
replace("@VERSION@", extraVersion)
}
@@ -0,0 +1,96 @@
package makamys.mixingasm;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.launchwrapper.Launch;
public class ConfigHelper {
private final String MODID;
private final Logger LOGGER;
public ConfigHelper(String modid) {
this.MODID = modid;
this.LOGGER = LogManager.getLogger(MODID);
}
public Path getDefaultConfigFilePath(Path relPath) throws IOException {
String resourceRelPath = Paths.get("assets/" + MODID + "/default_config/").resolve(relPath).toString().replace('\\', '/');
URL resourceURL = new Object() { }.getClass().getEnclosingClass().getClassLoader().getResource(resourceRelPath);
switch(resourceURL.getProtocol()) {
case "jar":
String urlString = resourceURL.getPath();
int lastExclamation = urlString.lastIndexOf('!');
String newURLString = urlString.substring(0, lastExclamation);
return FileSystems.newFileSystem(new File(URI.create(newURLString)).toPath(), null).getPath(resourceRelPath);
case "file":
return new File(URI.create(resourceURL.toString())).toPath();
default:
return null;
}
}
private void copyDefaultConfigFile(Path src, Path dest) throws IOException {
Files.createDirectories(getParentSafe(dest));
LOGGER.debug("Copying " + src + " -> " + dest);
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
}
public boolean createDefaultConfigFileIfMissing(File configFile, boolean overwrite) {
Path configFolderPath = Paths.get(new File(Launch.minecraftHome, "config").getPath());
Path configFilePath = Paths.get(configFile.getPath());
Path relPath = configFolderPath.relativize(configFilePath);
if (configFilePath.startsWith(configFolderPath)) {
try {
Path defaultConfigPath = getDefaultConfigFilePath(relPath);
if(Files.isRegularFile(defaultConfigPath)) {
if(!configFile.exists() || overwrite) {
copyDefaultConfigFile(defaultConfigPath, configFile.toPath());
}
} else if(Files.isDirectory(defaultConfigPath)) {
Files.createDirectories(Paths.get(configFile.getPath()));
// create contents of directory as well
for(Object po : Files.walk(defaultConfigPath).toArray()) {
Path destPath = configFile.toPath().resolve(
defaultConfigPath.toAbsolutePath().relativize(((Path)po).toAbsolutePath()).toString());
if(Files.isRegularFile((Path)po)) {
if(!Files.exists(destPath) || overwrite) {
copyDefaultConfigFile((Path)po, destPath);
}
}
}
}
} catch (IOException e) {
LOGGER.error("Failed to create default config file for " + relPath.toString() + ": " + e.getMessage());
return false;
}
} else {
LOGGER.debug("Invalid argument for creating default config file: " + relPath.toString()
+ " (file is not in the config directory)");
return false;
}
return true;
}
public Path getParentSafe(Path p) {
if(p == null || p.getParent() == null) {
return Paths.get("");
} else {
return p.getParent();
}
}
}
@@ -0,0 +1,52 @@
package makamys.mixingasm;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
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;
public class MixinConfigPlugin implements IMixinConfigPlugin {
public static final String MODID = "mixingasm";
public static final Logger LOGGER = LogManager.getLogger(MODID);
@Override
public void onLoad(String mixinPackage) {
Mixingasm.run();
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return Arrays.asList();
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}
@@ -0,0 +1,108 @@
package makamys.mixingasm;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.MixinEnvironment;
import makamys.mixingasm.api.IMixinSafeTransformer;
import makamys.mixingasm.api.TransformerInclusions;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
public class Mixingasm {
public static final String MODID = "mixingasm";
public static final Logger LOGGER = LogManager.getLogger(MODID);
public static void run() {
List<String> badTransformers = getBadTransformers();
LOGGER.debug("Excluding transformers: " + badTransformers);
for(String badTransformer : badTransformers) {
MixinEnvironment.getCurrentEnvironment().addTransformerExclusion(badTransformer);
}
}
private static boolean isValidClassPattern(String pattern) {
return !pattern.startsWith(":");
}
private static List<String> getBadTransformers() {
List<String> dynamicTransformerInclusionPatterns = TransformerInclusions.getTransformerInclusionList();
LOGGER.debug("Dynamic transformer inclusion pattern list: " + dynamicTransformerInclusionPatterns);
List<String> badTransformers = new ArrayList<>();
List<String> transformerInclusionPatterns = Stream.of(
readConfig("transformer_inclusion_list_default.txt").stream(),
readConfig("transformer_inclusion_list.txt").stream(),
dynamicTransformerInclusionPatterns.stream())
.flatMap(i -> i)
.filter(Mixingasm::isValidClassPattern)
.collect(Collectors.toList());
List<String> transformerExclusionPatterns =
readConfig("transformer_exclusion_list.txt").stream()
.filter(Mixingasm::isValidClassPattern)
.collect(Collectors.toList());
for(IClassTransformer trans : Launch.classLoader.getTransformers()) {
String name = trans.getClass().getCanonicalName();
boolean included = false;
if((included = (transformerInclusionPatterns.stream().anyMatch(p -> patternMatches(name, p)) || trans instanceof IMixinSafeTransformer))
&& transformerExclusionPatterns.stream().noneMatch(p -> patternMatches(name, p))) {
LOGGER.debug(" Trusting transformer " + name);
} else {
LOGGER.debug(" Not trusting transformer " + name + (included ? " (because it was excluded via the config)" : ""));
badTransformers.add(name);
}
}
return badTransformers;
}
private static boolean patternMatches(String str, String patternStr) {
Pattern pattern = Pattern.compile(patternStr.replace(".", "\\.").replace("*", ".*"));
return pattern.matcher(str).matches();
}
private static List<String> readConfig(String name){
ConfigHelper helper = new ConfigHelper(MODID);
File listFile = new File(Launch.minecraftHome, "config/" + MODID + "/" + name);
listFile.getParentFile().mkdirs();
List<String> lines = listFile.exists() ? readConfigLines(listFile) : null;
boolean overwrite = lines != null && lines.contains(":replaceableFile");
if(lines == null || overwrite) {
helper.createDefaultConfigFileIfMissing(listFile, overwrite);
lines = readConfigLines(listFile);
}
return lines;
}
private static List<String> readConfigLines(File file){
try (FileReader fr = new FileReader(file)){
return IOUtils.readLines(fr).stream()
.map(l -> l.contains("#") ? l.substring(0, l.indexOf('#')) : l)
.map(l -> l.trim())
.filter(l -> !l.isEmpty())
.collect(Collectors.toList());
} catch(Exception e) {
System.out.println("Failed to read " + file);
e.printStackTrace();
}
return Arrays.asList();
}
}
@@ -0,0 +1,7 @@
package makamys.mixingasm.api;
/** Implement this interface to signal that your transformer is "Mixin-safe", i.e. it does not cause issues when run by Mixin's preprocessor. This will be used as a hint that it shouldn't get excluded from the mixin preprocessor's transformer list by Mixingasm. */
public interface IMixinSafeTransformer {
}
@@ -0,0 +1,25 @@
package makamys.mixingasm.api;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.launchwrapper.Launch;
public class TransformerInclusions {
private static final String INCLUSION_LIST_BLACKBOARD_KEY = "mixingasm.transformerInclusionList";
/** Returns Mixingasm's dynamic transformer inclusion list. Add transformer name patterns to this list if you want to spare them from being added to
* the mixin environment's transformer exclusion list, for example if you need to mix into a version of a class that has been transformed by them.
* <br><br>
* <b>Note:</b> this needs to be called before the DEFAULT phase.
*/
public static List<String> getTransformerInclusionList(){
List<String> list = (List<String>)Launch.blackboard.get(INCLUSION_LIST_BLACKBOARD_KEY);
if(list == null) {
Launch.blackboard.put(INCLUSION_LIST_BLACKBOARD_KEY, list = new ArrayList<String>());
}
return list;
}
}
@@ -0,0 +1,9 @@
package makamys.mixingasm.forge;
import cpw.mods.fml.common.Mod;
import makamys.mixingasm.Mixingasm;
@Mod(modid = Mixingasm.MODID, version = "@VERSION@")
public class MixingasmMod {
}
@@ -0,0 +1,6 @@
# Classes listed in this file will be considered "untrusted" by Mixingasm and
# added to the mixin environment's transformer exclusion list.
# See transformer_inclusion_list_default.txt for more info.
# --- Untrusted transformers ---
@@ -0,0 +1,6 @@
# Classes listed in this file will be considered "trusted" by Mixingasm and
# may be spared from the mixin environment's transformer exclusion list.
# See transformer_inclusion_list_default.txt for more info.
# --- Additional trusted transformers ---
@@ -0,0 +1,26 @@
:replaceableFile # This file will get OVERWRITTEN at launch, nullifying any changes made to it, unless you delete this line. It is recommended to edit transformer_inclusion_list.txt and transformer_exclusion_list.txt instead, though.
# Mixingasm adds all transformers it doesn't "trust" to be Mixin-safe to the
# mixin environment's transformer exclusion list, avoiding running them an
# additional time when processing mixins at startup.
# This fixes issues that can arise from non-Mixin-aware transformers being run
# in that way. For example, some transformers break when run more than once.
# A transformer is considered "trusted" if one of these are true...
# * It's matched by a pattern in this file
# * It's matched by a pattern in transformer_inclusion_list.txt
# * It was added to Mixingasm's dynamic inclusion list by a mod using the API at startup
# * The transformer implements IMixinSafeTransformer
# AND the transformer is not matched by a pattern in transformer_exclusion_list.txt
# '*' can be used as a wildcard character.
# --- Trusted transformers ---
cpw.mods.fml.common.asm.*
net.minecraftforge.*
codechicken.core.asm.*
codechicken.lib.asm.*
org.spongepowered.asm.*
@@ -0,0 +1,17 @@
[
{
"modid": "spongemixins",
"name": "UniMixins: Mixingasm",
"description": "UniMixins module that implements Mixingasm (version: ${extraVersion}).",
"version": "${extraVersion}",
"mcversion": "${minecraft_version}",
"url": "",
"updateUrl": "",
"authorList": [
"makamys"
],
"credits": "",
"logoFile": "",
"screenshots": []
}
]
@@ -0,0 +1,10 @@
{
"required": true,
"minVersion": "0.6",
"package": "makamys.mixingasm.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
],
"plugin": "makamys.mixingasm.MixinConfigPlugin"
}
+2 -1
View File
@@ -1,5 +1,6 @@
include 'module-mixin' include 'module-mixin'
include 'module-compat'
include 'module-mixingasm'
include 'module-spongemixins' include 'module-spongemixins'
include 'module-gtnhmixins' include 'module-gtnhmixins'
include 'module-all' include 'module-all'
include 'module-compat'