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 40 #908

Merged
merged 11 commits into from
Mar 23, 2024
1 change: 0 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
dependency-graph: generate-and-submit
gradle-home-cache-cleanup: true
gradle-home-cache-excludes: |
gradle.properties
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,23 @@ jobs:
matrix:
include:
- name: Maven
environment: maven
task: publish
url: https://maven.su5ed.dev/releases/dev/su5ed/sinytra/Connector
- name: GitHub
environment: github
task: publishGithub
url: https://github.com/Sinytra/Connector/releases
- name: CurseForge
environment: curseforge
task: publishCurseforge
url: https://www.curseforge.com/minecraft/mc-mods/sinytra-connector
- name: Modrinth
environment: modrinth
task: publishModrinth
url: https://modrinth.com/mod/connector
name: Publish ${{ matrix.name }}
needs: build
runs-on: ubuntu-22.04
environment: ${{ matrix.environment }}
environment:
name: ${{ matrix.name }}
url: ${{ matrix.url }}
steps:
- uses: actions/checkout@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ dependencies {
shade(group = "org.ow2.sat4j", name = "org.ow2.sat4j.pb", version = "2.3.6")
shade(group = "net.minecraftforge", name = "srgutils", version = "0.5.4")
shade(group = "net.fabricmc", name = "access-widener", version = versionAccessWidener)
shade(group = "dev.su5ed.sinytra", name = "ForgeAutoRenamingTool", version = versionForgeAutoRenamingTool)
shade(group = "org.sinytra", name = "ForgeAutoRenamingTool", version = versionForgeAutoRenamingTool)
shade(group = "org.sinytra.adapter", name = "definition", version = versionAdapterDefinition) { isTransitive = false }
shade(group = "io.github.steelwoolmc", name = "mixin-transmogrifier", version = versionMixinTransmog)
adapterData(group = "org.sinytra.adapter", name = "adapter", version = versionAdapter)
Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=true

# Versions
versionConnector=1.0.0-beta.39
versionAdapter=1.11.30-1.20.1-20240308.152751
versionAdapterDefinition=1.11.30
versionConnector=1.0.0-beta.40
versionAdapter=1.11.32-1.20.1-20240314.234555
versionAdapterDefinition=1.11.34

versionMc=1.20.1
versionForge=47.1.3
versionForgeAutoRenamingTool=1.0.9
versionFabricLoader=2.7.1+0.15.3+1.20.1
versionForgeAutoRenamingTool=1.0.11
versionFabricLoader=2.7.2+0.15.3+1.20.1
versionAccessWidener=2.1.0
versionFabricApi=0.92.0+1.11.2+1.20.1
versionMixin=0.12.5+mixin.0.8.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static void removeAliasedModDependencyConstraints(LoaderModMetadata metad
.map(dep -> {
// Aliased mods typically don't follow the same version convention as the original,
// therefore we must widen all dependency constraints to wildcards
if (aliases.values().contains(dep.getModId())) {
if (aliases.keys().contains(dep.getModId()) || aliases.values().contains(dep.getModId())) {
return dep.getKind() == ModDependency.Kind.BREAKS ? null : uncheck(() -> new ModDependencyImpl(dep.getKind(), dep.getModId(), List.of("*")));
}
return dep;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.sinytra.adapter.patch.api.MixinClassGenerator;
import org.sinytra.adapter.patch.api.MixinConstants;
import org.sinytra.adapter.patch.api.Patch;
import org.sinytra.adapter.patch.api.PatchContext;
import org.sinytra.adapter.patch.api.PatchEnvironment;
import org.sinytra.adapter.patch.fixes.FieldTypePatchTransformer;
import org.sinytra.adapter.patch.fixes.FieldTypeUsageTransformer;
Expand Down Expand Up @@ -224,6 +225,11 @@ public ClassEntry process(ClassEntry entry) {
patchResult = patchResult.or(patch.apply(node, this.environment));
}
}
else {
for (ClassTransform transform : CLASS_TRANSFORMS) {
patchResult = patchResult.or(transform.apply(node, null, PatchContext.create(node, List.of(), this.environment)));
}
}

// TODO if a mixin method is extracted, roll back the status from compute frames to apply,
// Alternatively, change the order of patches so that extractmixin comes first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ public static List<Patch> getPatches() {
.modifyMethodAccess(new ModifyMethodAccess.AccessChange(false, Opcodes.ACC_STATIC))
.extractMixin("net/minecraftforge/common/extensions/IForgeBlockState")
.build(),
Patch.builder()
.targetClass("net/minecraft/client/multiplayer/MultiPlayerGameMode")
.targetMethod("m_105267_")
.targetInjectionPoint("Lnet/minecraft/world/level/block/Block;m_5707_(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/player/Player;)V")
.modifyInjectionPoint("Lnet/minecraft/world/level/block/state/BlockState;onDestroyedByPlayer(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;ZLnet/minecraft/world/level/material/FluidState;)Z")
.build(),
Patch.builder()
.targetClass("net/minecraft/world/level/block/FarmBlock")
.targetMethod("m_53258_(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;)Z")
.targetInjectionPoint("Lnet/minecraft/world/level/material/FluidState;m_205070_(Lnet/minecraft/tags/TagKey;)Z")
.modifyInjectionPoint("Lnet/minecraft/world/level/block/state/BlockState;canBeHydrated(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/material/FluidState;Lnet/minecraft/core/BlockPos;)Z")
.build(),
Patch.builder()
.targetClass("net/minecraft/world/entity/LivingEntity")
.targetMethod("m_6075_")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.SourceInterpreter;
import org.objectweb.asm.tree.analysis.SourceValue;
import org.sinytra.adapter.patch.analysis.MethodCallAnalyzer;
import org.sinytra.adapter.patch.selector.AnnotationHandle;
import org.sinytra.adapter.patch.util.MethodQualifier;

Expand All @@ -47,19 +43,14 @@ 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$_]+$";

private final SourceInterpreter reflectionRemapper;

public static Transformer create(ClassProvider classProvider, Consumer<String> log, IMappingFile mappingFile, IntermediateMapping flatMappings) {
IntermediaryClassProvider reverseProvider = new IntermediaryClassProvider(classProvider, mappingFile, mappingFile.reverse(), log);
EnhancedRemapper enhancedRemapper = new MixinAwareEnhancedRemapper(reverseProvider, mappingFile, flatMappings, log);
SourceInterpreter reflectionRemapper = new ReflectionRemapperInterpreter(Opcodes.ASM9, mappingFile, flatMappings);
return new OptimizedRenamingTransformer(enhancedRemapper, false, reflectionRemapper);
return new OptimizedRenamingTransformer(enhancedRemapper, false);
}

public OptimizedRenamingTransformer(EnhancedRemapper remapper, boolean collectAbstractParams, SourceInterpreter reflectionRemapper) {
public OptimizedRenamingTransformer(EnhancedRemapper remapper, boolean collectAbstractParams) {
super(remapper, collectAbstractParams);

this.reflectionRemapper = reflectionRemapper;
}

@Override
Expand Down Expand Up @@ -95,8 +86,6 @@ protected void postProcess(ClassNode node) {
}
}
}

MethodCallAnalyzer.analyzeInterpretMethod(method, this.reflectionRemapper);
}
for (FieldNode field : node.fields) {
field.value = postProcessRemapper.mapValue(field.value);
Expand Down Expand Up @@ -270,62 +259,6 @@ public String mapPackageName(String name) {
}
}

private static class ReflectionRemapperInterpreter extends SourceInterpreter {
private static final Type STR_TYPE = Type.getType(String.class);

private final Collection<MethodInsnNode> seen = new HashSet<>();
private final IMappingFile mappings;
private final IntermediateMapping fastMappings;

public ReflectionRemapperInterpreter(int api, IMappingFile mappings, IntermediateMapping fastMappings) {
super(api);
this.mappings = mappings;
this.fastMappings = fastMappings;
}

@Override
public SourceValue naryOperation(AbstractInsnNode insn, List<? extends SourceValue> values) {
if (insn instanceof MethodInsnNode methodInsn && !this.seen.contains(methodInsn)) {
this.seen.add(methodInsn);
// Try to remap reflection method call args
Type[] args = Type.getArgumentTypes(methodInsn.desc);
if (args.length >= 3 && STR_TYPE.equals(args[0]) && STR_TYPE.equals(args[1]) && STR_TYPE.equals(args[2]) && values.size() >= 3) {
LdcInsnNode ownerInsn = getSingleLDCString(values.get(0));
LdcInsnNode nameInsn = getSingleLDCString(values.get(1));
LdcInsnNode descInsn = getSingleLDCString(values.get(2));
if (ownerInsn != null && nameInsn != null && descInsn != null) {
String owner = (String) ownerInsn.cst;
IMappingFile.IClass cls = this.mappings.getClass(owner.replace('.', '/'));
if (cls != null) {
String name = (String) nameInsn.cst;
String desc = (String) descInsn.cst;
IMappingFile.IMethod mtd = cls.getMethod(name, desc);
if (mtd != null) {
ownerInsn.cst = owner.contains(".") ? cls.getMapped().replace('/', '.') : cls.getMapped();
nameInsn.cst = mtd.getMapped();
descInsn.cst = mtd.getMappedDescriptor();
}
else {
String mappedName = this.fastMappings.mapMethod(name, desc);
if (mappedName != null) {
ownerInsn.cst = owner.contains(".") ? cls.getMapped().replace('/', '.') : cls.getMapped();
nameInsn.cst = mappedName;
descInsn.cst = this.mappings.remapDescriptor(desc);
}
}
}
}
}
}
return super.naryOperation(insn, values);
}

@Nullable
private static LdcInsnNode getSingleLDCString(SourceValue value) {
return value.insns.size() == 1 && value.insns.iterator().next() instanceof LdcInsnNode ldc && ldc.cst instanceof String ? ldc : null;
}
}

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package dev.su5ed.sinytra.connector.transformer.jar;

import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.ClassTransformer;
import cpw.mods.modlauncher.LaunchPluginHandler;
import cpw.mods.modlauncher.TransformStore;
import cpw.mods.modlauncher.TransformationServiceDecorator;
import cpw.mods.modlauncher.TransformingClassLoader;
import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ITransformationService;
import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.ITransformerActivity;
import net.minecraftforge.coremod.CoreModProvider;
import net.minecraftforge.fart.api.ClassProvider;
import net.minecraftforge.fml.loading.moddiscovery.CoreModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileParser;
import net.minecraftforge.fml.unsafe.UnsafeHacks;
import net.minecraftforge.forgespi.locating.IModFile;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;

import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.uncheck;

public class EarlyJSCoremodTransformer implements ClassProvider {
private static final MethodHandle GET_CORE_MODS = uncheck(() -> MethodHandles.privateLookupIn(ModFileParser.class, MethodHandles.lookup()).findStatic(ModFileParser.class, "getCoreMods", MethodType.methodType(List.class, ModFile.class)));
private static final MethodHandle TRANSFORM = uncheck(() -> MethodHandles.privateLookupIn(ClassTransformer.class, MethodHandles.lookup()).findVirtual(ClassTransformer.class, "transform", MethodType.methodType(byte[].class, byte[].class, String.class, String.class)));
private static final Logger LOGGER = LogUtils.getLogger();

private final ClassProvider provider;
private final ClassTransformer transformer;

public static EarlyJSCoremodTransformer create(ClassProvider classProvider, Iterable<IModFile> loadedMods) {
try {
CoreModProvider provider = new CoreModProvider();
for (IModFile mf : loadedMods) {
List<CoreModFile> list = (List<CoreModFile>) GET_CORE_MODS.invoke((ModFile) mf);
if (!list.isEmpty()) {
for (CoreModFile f : list) {
provider.addCoreMod(f);
}
}
}
List<ITransformer<?>> transformers = provider.getCoreModTransformers();

TransformStore transformStore = new TransformStore();
ITransformationService service = new DummyService(transformers);

Constructor<TransformationServiceDecorator> cst = TransformationServiceDecorator.class.getDeclaredConstructor(ITransformationService.class);
cst.setAccessible(true);
TransformationServiceDecorator decorator = cst.newInstance(service);
decorator.gatherTransformers(transformStore);

LaunchPluginHandler plugins = UnsafeHacks.newInstance(LaunchPluginHandler.class);
Field pluginsField = LaunchPluginHandler.class.getDeclaredField("plugins");
pluginsField.setAccessible(true);
pluginsField.set(plugins, new HashMap<>());

Constructor<ClassTransformer> xformCst = ClassTransformer.class.getDeclaredConstructor(TransformStore.class, LaunchPluginHandler.class, TransformingClassLoader.class);
xformCst.setAccessible(true);
ClassTransformer classTransformer = xformCst.newInstance(transformStore, plugins, null);
return new EarlyJSCoremodTransformer(classProvider, classTransformer);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

public EarlyJSCoremodTransformer(ClassProvider provider, ClassTransformer transformer) {
this.provider = provider;
this.transformer = transformer;
}

@Override
public Optional<? extends IClassInfo> getClass(String s) {
return this.provider.getClass(s);
}

@Override
public Optional<byte[]> getClassBytes(String s) {
return this.provider.getClassBytes(s)
.map(bytes -> {
try {
return (byte[]) TRANSFORM.invoke(this.transformer, bytes, s, ITransformerActivity.COMPUTING_FRAMES_REASON);
} catch (Throwable t) {
LOGGER.error("Error transforming class " + s, t);
return bytes;
}
});
}

@Override
public void close() throws IOException {
this.provider.close();
}

@SuppressWarnings("rawtypes")
private record DummyService(List transformers) implements ITransformationService {
@Override
@NotNull
public String name() {
return "connector_early_js_coremods";
}

@Override
public void initialize(IEnvironment environment) {}

@Override
public void onLoad(IEnvironment env, Set<String> otherServices) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.gson.JsonElement;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.JsonOps;
import dev.su5ed.sinytra.connector.transformer.patch.ReflectionRenamingTransformer;
import org.sinytra.adapter.patch.LVTOffsets;
import org.sinytra.adapter.patch.api.GlobalReferenceMapper;
import org.sinytra.adapter.patch.api.Patch;
Expand Down Expand Up @@ -120,6 +121,7 @@ public void transformJar(File input, Path output, FabricModFileMetadata metadata
MappingResolverImpl resolver = FabricLoaderImpl.INSTANCE.getMappingResolver();
RefmapRemapper.RefmapFiles refmap = RefmapRemapper.processRefmaps(input.toPath(), metadata.refmaps(), this.remapper, this.libs);
IMappingFile srgToIntermediary = resolver.getMap(OBF_NAMESPACE, SOURCE_NAMESPACE);
IMappingFile intermediaryToSrg = resolver.getCurrentMap(SOURCE_NAMESPACE);
AccessorRedirectTransformer accessorRedirectTransformer = new AccessorRedirectTransformer(srgToIntermediary);

List<Patch> extraPatches = Stream.concat(this.adapterPatches.stream(), AccessorRedirectTransformer.PATCHES.stream()).toList();
Expand All @@ -132,15 +134,17 @@ public void transformJar(File input, Path output, FabricModFileMetadata metadata
.add(new JarSignatureStripper())
.add(new ClassNodeTransformer(
new FieldToMethodTransformer(metadata.modMetadata().getAccessWidener(), srgToIntermediary),
accessorRedirectTransformer
accessorRedirectTransformer,
new ReflectionRenamingTransformer(intermediaryToSrg, IntermediateMapping.get(SOURCE_NAMESPACE))
))
.add(this.remappingTransformer)
.add(new ClassNodeTransformer(new ClassAnalysingTransformer()))
.add(patchTransformer)
.add(refmapRemapper)
.add(new ModMetadataGenerator(metadata.modMetadata().getId()))
.logger(s -> LOGGER.trace(TRANSFORM_MARKER, s))
.debug(s -> LOGGER.trace(TRANSFORM_MARKER, s));
.debug(s -> LOGGER.trace(TRANSFORM_MARKER, s))
.ignoreJarPathPrefix("assets/", "data/");
if (!metadata.containsAT()) {
builder.add(new AccessWidenerTransformer(metadata.modMetadata().getAccessWidener(), resolver, IntermediateMapping.get(SOURCE_NAMESPACE)));
}
Expand Down
Loading
Loading