Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
Cursed and slow hierarchy support.
Browse files Browse the repository at this point in the history
Remove TinyRemapper dependency.
  • Loading branch information
melontini committed Apr 17, 2024
1 parent d2132e6 commit 2d75fbf
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 144 deletions.
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ tasks.register('fullDependenciesJar', ShadowJar) {
var pck = "me.melontini.commander.impl.lib."

mergeServiceFiles()
relocate("net.fabricmc.mappingio", pck + "net.fabricmc.mappingio")
relocate("com.ezylang.evalex", pck + "com.ezylang.evalex")
relocate("net.fabricmc.mappingio", pck + "net.fabricmc.mappingio")
}

remapJar {
Expand All @@ -71,7 +71,6 @@ dependencies {

implementation shade("com.ezylang:EvalEx:${project.evalex_version}")
implementation shade("net.fabricmc:mapping-io:${project.mappingio_version}")
implementation shade("net.fabricmc:tiny-remapper:${tiny_remapper_version}")
}

loom {
Expand Down
52 changes: 6 additions & 46 deletions src/main/java/me/melontini/commander/impl/Commander.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import me.melontini.commander.impl.event.data.DynamicEventManager;
import me.melontini.commander.impl.util.ArithmeticaLootNumberProvider;
import me.melontini.commander.impl.util.eval.EvalUtils;
import me.melontini.commander.impl.util.eval.ReflectiveMapStructure;
import me.melontini.commander.impl.util.mappings.MappingKeeper;
import me.melontini.commander.impl.util.mappings.MinecraftDownloader;
import me.melontini.dark_matter.api.base.util.Exceptions;
Expand All @@ -21,29 +20,18 @@
import me.melontini.dark_matter.api.data.loading.ServerReloadersEvent;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.item.ItemStack;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.minecraft.loot.provider.number.LootNumberProviderType;
import net.minecraft.loot.provider.number.LootNumberProviderTypes;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;

import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import static net.minecraft.loot.context.LootContextParameters.*;

Expand All @@ -57,7 +45,7 @@ public class Commander implements ModInitializer {
public static final String MINECRAFT_VERSION = getVersion();

@Getter
private static TinyRemapper remapper;
private static MappingKeeper mappingKeeper;

public static Identifier id(String path) {
return new Identifier("commander", path);
Expand All @@ -79,37 +67,9 @@ public void onInitialize() {
EvalUtils.init();
MinecraftDownloader.downloadMappings();

IMappingProvider provider = MappingKeeper.create(MappingKeeper.getMojmapTarget(), MappingKeeper.NAMESPACE, "mojang");
remapper = TinyRemapper.newRemapper()
.renameInvalidLocals(false)
.withMappings(provider)
.build();
remapper.readInputs(remapper.createInputTag(), FabricLoader.getInstance().getModContainer("minecraft").orElseThrow().getOrigin().getPaths().toArray(Path[]::new));

log.info("Scanning common context classes!");
Util.getMainWorkerExecutor().submit(() -> {
Set.of(
ServerPlayerEntity.class,
Vec3d.class, BlockPos.class,
BlockState.class, BlockEntity.class,
ItemStack.class, DamageSource.class,
ServerWorld.class
).forEach(aClass -> {
do {
ReflectiveMapStructure.getAccessors(aClass);
for (Field field : aClass.getFields()) {
ReflectiveMapStructure.getAccessors(field.getType());
}
for (Method method : aClass.getMethods()) {
if (method.getReturnType() == void.class) continue;
ReflectiveMapStructure.getAccessors(method.getReturnType());
}
aClass = aClass.getSuperclass();
}
while (aClass.getSuperclass() != null);
});
log.info("Finished scanning classes!");
});
CompletableFuture<MemoryMappingTree> offMojmap = CompletableFuture.supplyAsync(MappingKeeper::loadOffMojmap, Util.getMainWorkerExecutor());
CompletableFuture<MemoryMappingTree> offTarget = CompletableFuture.supplyAsync(MappingKeeper::loadOffTarget, Util.getMainWorkerExecutor());
mappingKeeper = new MappingKeeper(MappingKeeper.loadMojmapTarget(offMojmap.join(), offTarget.join()));

BuiltInEvents.init();
BuiltInCommands.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import me.melontini.commander.impl.util.mappings.MappingKeeper;
import lombok.extern.log4j.Log4j2;
import me.melontini.commander.impl.Commander;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -14,12 +15,10 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.function.Function;

@Log4j2
public class ReflectiveMapStructure implements Map<String, Object> {

private static final Map<Class<?>, Map<String, Accessor>> MAPPINGS = new Reference2ReferenceOpenHashMap<>();
Expand All @@ -38,18 +37,6 @@ public static Map<String, Accessor> getAccessors(Class<?> cls) {
if (map == null) {
synchronized (MAPPINGS) {
map = new Object2ReferenceOpenHashMap<>();
for (Field field : cls.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
map.put(MappingKeeper.toNamed(field), field::get);
}
for (Method method : cls.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) continue;
if (method.getParameterCount() > 0) continue;
if (method.getReturnType() == void.class) continue;

var accessor = methodAccessor(method);
map.put(MappingKeeper.toNamed(method), accessor::apply);
}
MAPPINGS.put(cls, map);
}
}
Expand Down Expand Up @@ -86,7 +73,61 @@ public boolean isEmpty() {

@Override
public boolean containsKey(Object key) {
return this.mappings.containsKey(key);
if (key == null) return false;
if (key.getClass() != String.class) return false;

var cache = this.mappings.get(key);
if (cache != null) return true;

var accessor = findFieldOrMethod(this.object.getClass(), (String) key);
if (accessor == null) return false;

synchronized (this.mappings) {
this.mappings.put((String) key, accessor);
}
return true;
}

private static Accessor findFieldOrMethod(Class<?> cls, String name) {
String mapped;
Class<?> target = cls;
do {
if ((mapped = Commander.getMappingKeeper().getFieldOrMethod(target, name)) != null) break;
var targetItfs = target.getInterfaces();
if (targetItfs.length == 0) continue;

Queue<Class<?>> interfaces = new ArrayDeque<>(List.of(targetItfs));
while (!interfaces.isEmpty()) {
var itf = interfaces.poll();

if ((mapped = Commander.getMappingKeeper().getFieldOrMethod(itf, name)) != null) {
target = Object.class;
break;
}
if ((targetItfs = itf.getInterfaces()).length > 0) interfaces.addAll(List.of(targetItfs));
}
} while ((target = target.getSuperclass()) != null);
if (mapped == null) mapped = name;

for (Method method : cls.getMethods()) {
if (!method.getName().equals(mapped)) continue;
if (Modifier.isStatic(method.getModifiers())) continue;
if (method.getParameterCount() > 0) continue;
if (method.getReturnType() == void.class) continue;

var ma = methodAccessor(method);
return ma::apply;
}

do {
for (Field field : cls.getFields()) {
if (!field.getName().equals(mapped)) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
return field::get;
}
} while ((cls = cls.getSuperclass()) != null);

return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,43 @@
package me.melontini.commander.impl.util.mappings;

import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import me.melontini.commander.impl.Commander;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.mappingio.tree.MappingTreeView;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.fabricmc.tinyremapper.IMappingProvider;
import org.objectweb.asm.Type;

import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

@Log4j2
public final class MappingKeeper {
public record MappingKeeper(MemoryMappingTree mojmapTarget) {

public static final String NAMESPACE = FabricLoader.getInstance().getMappingResolver().getCurrentRuntimeNamespace();

@Getter(lazy = true)
private static final MemoryMappingTree offMojmap = loadOffMojmap();
@Getter(lazy = true)
private static final MemoryMappingTree offTarget = loadOffTarget();
@Getter(lazy = true)
private static final MemoryMappingTree mojmapTarget = loadMojmapTarget();

@SneakyThrows
public static MemoryMappingTree loadMojmapTarget() {
if (NAMESPACE.equals("mojang")) return getMojmapTarget();
public static MemoryMappingTree loadMojmapTarget(MemoryMappingTree offMojmap, MemoryMappingTree offTarget) {
log.info("Merging mappings...");

var tree = new MemoryMappingTree();
MemoryMappingTree temp = new MemoryMappingTree();
getOffMojmap().accept(temp);
getOffTarget().accept(temp);
log.info("Merging mappings...");
offMojmap.accept(temp);
if (!NAMESPACE.equals("mojang")) offTarget.accept(temp);
temp.accept(new MappingSourceNsSwitch(tree, "mojang", true));
tree.getClass("net/minecraft/server/MinecraftServer").setDstName("net/minecraft/server/MinecraftServer", tree.getNamespaceId(NAMESPACE));
return tree;
}

@SneakyThrows
public static MemoryMappingTree loadOffMojmap() {
var tree = new MemoryMappingTree();
if (NAMESPACE.equals("mojang")) return null;
log.info("Loading official->mojmap mappings...");

var tree = new MemoryMappingTree();
MappingReader.read(Commander.COMMANDER_PATH.resolve("mappings/client_mappings.txt"), new MappingSourceNsSwitch(tree, "target"));
tree.setSrcNamespace("official");
tree.setDstNamespaces(List.of("mojang"));
Expand All @@ -56,72 +46,27 @@ public static MemoryMappingTree loadOffMojmap() {

@SneakyThrows
public static MemoryMappingTree loadOffTarget() {
var tree = new MemoryMappingTree();
log.info("Loading official->{} mappings...", NAMESPACE);

var tree = new MemoryMappingTree();
MappingReader.read(new InputStreamReader(Objects.requireNonNull(MappingKeeper.class.getClassLoader().getResourceAsStream("mappings/mappings.tiny"), "mappings/mappings.tiny is not available?")), tree);
return tree;
}

public static String toNamed(Field field) {
return Commander.getRemapper().getEnvironment().getRemapper().mapFieldName(Type.getInternalName(field.getDeclaringClass()), field.getName(), Type.getDescriptor(field.getType()));
}

public static String toNamed(Method method) {
return Commander.getRemapper().getEnvironment().getRemapper().mapMethodName(Type.getInternalName(method.getDeclaringClass()), method.getName(), Type.getMethodDescriptor(method));
}
public String getFieldOrMethod(Class<?> cls, String name) {
var clsData = mojmapTarget.getClass(Type.getInternalName(cls), mojmapTarget.getNamespaceId(NAMESPACE));
if (clsData == null) return null;

private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) {
return new IMappingProvider.Member(className, memberName, descriptor);
}

public static IMappingProvider create(MappingTree first, String from, String to) {
return (acceptor) -> {
int fromId = first.getNamespaceId(from);
int toId = first.getNamespaceId(to);

for (MappingTree.ClassMapping classDef : first.getClasses()) {
String className = classDef.getName(fromId);
if (className == null) continue;

String dstName = getName(classDef, toId, fromId);

acceptor.acceptClass(className, dstName);
for (MappingTree.FieldMapping field : classDef.getFields()) {
var fieldId = memberOf(className, field.getName(fromId), field.getDesc(fromId));
if (fieldId.name == null) continue;

try {
acceptor.acceptField(fieldId, getName(field, toId, fromId));
} catch (Exception e) {
throw new RuntimeException("from: %s to:%s cls:%s dstCls:%s field:%s fieldMth:%s"
.formatted(from, to, className, dstName, fieldId.name, getName(field, toId, fromId)));
}
}

for (MappingTree.MethodMapping method : classDef.getMethods()) {
var methodIdentifier = memberOf(className, method.getName(fromId), method.getDesc(fromId));
if (methodIdentifier.name == null) continue;

try {
acceptor.acceptMethod(methodIdentifier, getName(method, toId, fromId));
} catch (Exception e) {
throw new RuntimeException("from: %s to:%s cls:%s dstCls:%s mth:%s dstMth:%s"
.formatted(from, to, className, dstName, methodIdentifier.name, getName(method, toId, fromId)));
}
}
for (MappingTree.MethodMapping method : clsData.getMethods()) {
if (Objects.equals(method.getSrcName(), name)) {
var srcDesc = method.getSrcDesc();
if (srcDesc != null && srcDesc.startsWith("()") && !srcDesc.endsWith("V")) return method.getName(NAMESPACE);
}
};
}

private static String getName(MappingTree.ClassMapping classDef, int id, int fallback) {
var s = classDef.getName(id);
if (s != null) return s;
return classDef.getName(fallback);
}
}

public static String getName(MappingTreeView.MemberMappingView method, int id, int fallback) {
var s = method.getName(id);
if (s != null) return s;
return method.getName(fallback);
for (MappingTree.FieldMapping field : clsData.getFields()) {
if (Objects.equals(field.getSrcName(), name)) return field.getName(NAMESPACE);
}
return null;
}
}

0 comments on commit 2d75fbf

Please sign in to comment.