Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop beta 26 #520

Merged
merged 7 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=true

# Versions
versionConnector=1.0.0-beta.25
versionAdapter=1.8.12-1.20.1-20231112.230129
versionAdapterDefinition=1.8.16
versionConnector=1.0.0-beta.26
versionAdapter=1.8.16-1.20.1-20231120.221506
versionAdapterDefinition=1.8.19

versionMc=1.20.1
versionForge=47.1.3
versionForgeAutoRenamingTool=1.0.8
versionForgeAutoRenamingTool=1.0.9
versionFabricLoader=2.5.2+0.14.21+1.20.1
versionAccessWidener=2.1.0
versionFabricApi=0.90.7+1.9.32+1.20.1
versionFabricApi=0.90.7+1.9.33+1.20.1
versionMixin=0.12.5+mixin.0.8.5
versionMixinTransmog=0.4.1+1.20.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

public class FabricASMFixer {
private static final Logger LOGGER = LogUtils.getLogger();
private static final String FABRIC_ASM_MODID = "mm";
private static final Set<String> FABRIC_ASM_MODIDS = Set.of("mm", "mm_shedaniel");
private static final String MINECRAFT_MODULE = "minecraft";
public static final List<URL> URLS = new ArrayList<>();

Expand All @@ -57,7 +57,7 @@ public static void permitEnumSubclass(ClassNode enumNode, String anonymousClassN

public static void injectMinecraftModuleReader() {
try {
if (!FabricLoader.getInstance().isModLoaded(FABRIC_ASM_MODID)) {
if (FABRIC_ASM_MODIDS.stream().noneMatch(FabricLoader.getInstance()::isModLoaded)) {
return;
}
ModuleLayer layer = Launcher.INSTANCE.findLayerManager().orElseThrow().getLayer(IModuleLayerManager.Layer.GAME).orElseThrow();
Expand Down Expand Up @@ -115,7 +115,7 @@ public static class FabricASMGeneratedClassesSecureJar implements SecureJar {
}

private static class FabricASMGeneratedClassesProvider implements SecureJar.ModuleDataProvider {
private static final String GEN_PACKAGE = "com.chocohead.gen.mixin";
private static final Set<String> GEN_PACKAGES = Set.of("com.chocohead.gen.mixin", "me.shedaniel.gen.mixin");
private ModuleDescriptor descriptor;

@Override
Expand All @@ -127,7 +127,7 @@ public String name() {
public ModuleDescriptor descriptor() {
if (descriptor == null) {
descriptor = ModuleDescriptor.newAutomaticModule(name())
.packages(Set.of(GEN_PACKAGE))
.packages(GEN_PACKAGES)
.build();
}
return descriptor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.su5ed.sinytra.connector.transformer;

import dev.su5ed.sinytra.adapter.patch.selector.AnnotationHandle;
import dev.su5ed.sinytra.adapter.patch.util.MethodQualifier;
import net.minecraftforge.fart.api.ClassProvider;
import net.minecraftforge.fart.api.Transformer;
Expand All @@ -13,22 +14,34 @@
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

public final class OptimizedRenamingTransformer extends RenamingTransformer {
private static final String CLASS_DESC_PATTERN = "^L[a-zA-Z0-9/$_]+;$";
private static final String FQN_CLASS_NAME_PATTERN = "^([a-zA-Z0-9$_]+\\.)*[a-zA-Z0-9$_]+$";

public static Transformer create(ClassProvider classProvider, Consumer<String> log, IMappingFile mappingFile, Map<String, String> flatMappings) {
RenamingClassProvider reverseProvider = new RenamingClassProvider(classProvider, mappingFile, mappingFile.reverse(), log);
Expand All @@ -40,6 +53,100 @@ public OptimizedRenamingTransformer(EnhancedRemapper remapper, boolean collectAb
super(remapper, collectAbstractParams);
}

@Override
protected void postProcess(ClassNode node) {
super.postProcess(node);

// Remap raw values (usually found in reflection calls) and unmapped mixin annotations
// This is done in a "post-processing" phase rather than inside the main remapper's mapValue method
// so that we're able to determine the "remap" mixin annotation value ahead of time, and only remap it when necessary
PostProcessRemapper postProcessRemapper = new PostProcessRemapper(((RelocatingEnhancedRemapper) this.remapper).flatMappings, this.remapper);
for (MethodNode method : node.methods) {
if (method.visibleAnnotations != null) {
// If remap has been set to false during compilation, we must manually map the annotation values ourselves instead of relying on the provided refmap
if (method.visibleAnnotations.stream().anyMatch(ann -> new AnnotationHandle(ann).<Boolean>getValue("remap").map(h -> !h.get()).orElse(false))) {
for (AnnotationNode annotation : method.visibleAnnotations) {
postProcessRemapper.mapAnnotationValues(annotation.values);
}
}
}
for (AbstractInsnNode insn : method.instructions) {
if (insn instanceof LdcInsnNode ldc) {
ldc.cst = postProcessRemapper.mapValue(ldc.cst);
}
if (insn instanceof InvokeDynamicInsnNode indy) {
for (int i = 0; i < indy.bsmArgs.length; i++) {
indy.bsmArgs[i] = postProcessRemapper.mapValue(indy.bsmArgs[i]);
indy.bsm = (Handle) postProcessRemapper.mapValue(indy.bsm);
}
}
}
}
for (FieldNode field : node.fields) {
field.value = postProcessRemapper.mapValue(field.value);
}
}

private static class PostProcessRemapper {
private final Map<String, String> flatMappings;
private final Remapper remapper;

public PostProcessRemapper(Map<String, String> flatMappings, Remapper remapper) {
this.flatMappings = flatMappings;
this.remapper = remapper;
}

public void mapAnnotationValues(List<Object> values) {
for (int i = 1; i < values.size(); i += 2) {
values.set(i, mapAnnotationValue(values.get(i)));
}
}

public Object mapAnnotationValue(Object obj) {
if (obj instanceof AnnotationNode annotation) {
mapAnnotationValues(annotation.values);
}
else if (obj instanceof List list) {
list.replaceAll(this::mapAnnotationValue);
}
else {
return mapValue(obj);
}
return obj;
}

public Object mapValue(Object value) {
if (value instanceof String str) {
if (str.matches(CLASS_DESC_PATTERN)) {
String mapped = flatMappings.get(str.substring(1, str.length() - 1));
if (mapped != null) {
return 'L' + mapped + ';';
}
}
else if (str.matches(FQN_CLASS_NAME_PATTERN)) {
String mapped = flatMappings.get(str.replace('.', '/'));
if (mapped != null) {
return mapped.replace('/', '.');
}
}

MethodQualifier qualifier = MethodQualifier.create(str).orElse(null);
if (qualifier != null && qualifier.desc() != null) {
String owner = qualifier.owner() != null ? this.remapper.mapDesc(qualifier.owner()) : "";
String name = qualifier.name() != null ? this.flatMappings.getOrDefault(qualifier.name(), qualifier.name()) : "";
String desc = qualifier.desc() != null ? this.remapper.mapMethodDesc(qualifier.desc()) : "";
return owner + name + desc;
}

String mapped = this.flatMappings.get(str);
if (mapped != null) {
return mapped;
}
}
return this.remapper.mapValue(value);
}
}

private static final class RenamingClassProvider implements ClassProvider {
private final ClassProvider upstream;
private final IMappingFile forwardMapping;
Expand Down Expand Up @@ -85,44 +192,6 @@ public void close() throws IOException {
}
}

private static class MixinTargetAnalyzer extends ClassVisitor {
private final Set<String> targets = new HashSet<>();

public MixinTargetAnalyzer(int api, ClassVisitor classVisitor) {
super(api, classVisitor);
}

@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
return new MixinAnnotationVisitor(this.api, super.visitAnnotation(descriptor, visible), this.targets, null);
}
}

private static class MixinAnnotationVisitor extends AnnotationVisitor {
private final Set<String> targets;
private final String attributeName;

public MixinAnnotationVisitor(int api, AnnotationVisitor annotationVisitor, Set<String> targets, String attributeName) {
super(api, annotationVisitor);

this.targets = targets;
this.attributeName = attributeName;
}

@Override
public void visit(String name, Object value) {
super.visit(name, value);
if ("value".equals(this.attributeName) && value instanceof Type type) {
this.targets.add(type.getInternalName());
}
}

@Override
public AnnotationVisitor visitArray(String name) {
return new MixinAnnotationVisitor(this.api, super.visitArray(name), this.targets, name);
}
}

private static class RelocatingEnhancedRemapper extends EnhancedRemapper {
private final Map<String, String> flatMappings;

Expand Down Expand Up @@ -185,32 +254,43 @@ public String mapPackageName(String name) {
// We don't need to map these
return name;
}
}

private static class MixinTargetAnalyzer extends ClassVisitor {
private final Set<String> targets = new HashSet<>();

public MixinTargetAnalyzer(int api, ClassVisitor classVisitor) {
super(api, classVisitor);
}

// An attempt at remapping reflection calls and mixin method names
@Override
public Object mapValue(Object value) {
if (value instanceof String str) {
if (str.matches(CLASS_DESC_PATTERN)) {
String mapped = this.flatMappings.get(str.substring(1, str.length() - 1));
if (mapped != null) {
return 'L' + mapped + ';';
}
}
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
return new MixinAnnotationVisitor(this.api, super.visitAnnotation(descriptor, visible), this.targets, null);
}
}

MethodQualifier qualifier = MethodQualifier.create(str).orElse(null);
if (qualifier != null && qualifier.desc() != null) {
String owner = qualifier.owner() != null ? mapDesc(qualifier.owner()) : "";
String name = qualifier.name() != null ? this.flatMappings.getOrDefault(qualifier.name(), qualifier.name()) : "";
String desc = qualifier.desc() != null ? mapMethodDesc(qualifier.desc()) : "";
return owner + name + desc;
}
private static class MixinAnnotationVisitor extends AnnotationVisitor {
private final Set<String> targets;
private final String attributeName;

String mapped = this.flatMappings.get(str);
if (mapped != null) {
return mapped;
}
public MixinAnnotationVisitor(int api, AnnotationVisitor annotationVisitor, Set<String> targets, String attributeName) {
super(api, annotationVisitor);

this.targets = targets;
this.attributeName = attributeName;
}

@Override
public void visit(String name, Object value) {
super.visit(name, value);
if ("value".equals(this.attributeName) && value instanceof Type type) {
this.targets.add(type.getInternalName());
}
return super.mapValue(value);
}

@Override
public AnnotationVisitor visitArray(String name) {
return new MixinAnnotationVisitor(this.api, super.visitArray(name), this.targets, name);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.Maps;
import com.google.gson.GsonBuilder;
import dev.su5ed.sinytra.adapter.patch.util.MethodQualifier;
import net.minecraftforge.srgutils.IMappingFile;

import java.util.HashMap;
Expand All @@ -13,7 +14,6 @@
import java.util.stream.Collectors;

public class SrgRemappingReferenceMapper {
private static final Pattern METHOD_REF_PATTERN = Pattern.compile("^(?<owner>L[a-zA-Z0-9/_$]+;)?(?<name>[a-zA-Z0-9_]+|<[a-z0-9_]+>)?(?<desc>\\((?:\\[?[VZCBSIFJD]|\\[?L[a-zA-Z0-9/_$]+;)*\\)(?:[VZCBSIFJD]|\\[?L[a-zA-Z0-9/_;$]+))$");
private static final Pattern FIELD_REF_PATTERN = Pattern.compile("^(?<owner>L[a-zA-Z0-9/_$]+;)?(?<name>[a-zA-Z0-9_]+):(?<desc>.+)$");

private final IMappingFile mappingFile;
Expand Down Expand Up @@ -54,7 +54,7 @@ private Map<String, Map<String, String>> remapReferences(Map<String, Map<String,
}

private String remapRef(String reference) {
Matcher methodMatcher = METHOD_REF_PATTERN.matcher(reference);
Matcher methodMatcher = MethodQualifier.METHOD_QUALIFIER_PATTERN.matcher(reference);
if (methodMatcher.matches()) {
return remapRefMapEntry(methodMatcher, "", (name, desc) -> this.methods.get(name + desc));
}
Expand All @@ -73,7 +73,8 @@ private <T extends IMappingFile.INode> String remapRefMapEntry(Matcher matcher,
String mappedName = node != null ? node.getMapped() : name != null ? name : "";

String mappedOwner = owner != null ? this.mappingFile.remapDescriptor(owner) : "";
return mappedOwner + mappedName + separator + this.mappingFile.remapDescriptor(desc);
String mappedDesc = desc != null ? this.mappingFile.remapDescriptor(desc) : "";
return mappedOwner + mappedName + separator + mappedDesc;
}

public static class SimpleRefmap {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.mojang.logging.LogUtils;
import dev.su5ed.sinytra.connector.loader.ConnectorEarlyLoader;
import dev.su5ed.sinytra.connector.mod.compat.LazyEntityAttributes;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.api.ModInitializer;
Expand Down Expand Up @@ -45,6 +46,7 @@ public static void load() {
ProgressMeter progress = StartupNotificationManager.addProgressBar("[Connector] Loading mods", 0);
try {
loading = true;
LazyEntityAttributes.inject();

// Invoke entry points
EntrypointUtils.invoke("main", ModInitializer.class, ModInitializer::onInitialize);
Expand All @@ -55,6 +57,7 @@ public static void load() {
EntrypointUtils.invoke("server", DedicatedServerModInitializer.class, DedicatedServerModInitializer::onInitializeServer);
}

LazyEntityAttributes.release();
loading = false;
finishedLoading = true;
} catch (Throwable t) {
Expand Down
Loading