Skip to content

Commit 8e9293d

Browse files
committed
feat(allium)!: Make mixin building more like standard class builder experience.
1 parent 6eabc94 commit 8e9293d

28 files changed

Lines changed: 805 additions & 638 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ bin/
3131
# fabric
3232

3333
run/
34+
35+
# allium
36+
37+
docs

allium/src/main/java/dev/moongarden/allium/api/event/MixinMethodHook.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import java.util.ArrayList;
1818
import java.util.List;
1919

20-
@LuaWrapped
2120
public class MixinMethodHook {
2221
private final Script script;
2322
private final String id;
@@ -42,7 +41,10 @@ private static EClass<?> forName(String id, String name) {
4241
}
4342
}
4443

45-
@LuaWrapped
44+
public String id() {
45+
return id;
46+
}
47+
4648
public ScriptResource hook(LuaFunction func, @OptionalArg Boolean destroyOnUnload) {
4749
if (!MixinLib.isComplete())
4850
throw new IllegalStateException("Hook cannot be set during pre-launch phase.");

allium/src/main/java/dev/moongarden/allium/loader/ScriptExecutor.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,11 @@ public LuaValue execute(Path path) throws LuaError, CompileException, IOExceptio
102102
LuaFunction func = LoadState.load(
103103
state,
104104
stream,
105-
'=' + id + ":/" + path.relativize(path),
105+
'=' + id + ":/" + path.getParent().relativize(path),
106106
state.globals()
107107
);
108108
Allium.PROFILER.pop();
109-
try {
110-
return Dispatch.call(state, func);
111-
} catch (UnwindThrowable e) {
112-
logger.warn("Unhandled yield. Avoid using coroutine.yield in places that will bleed into Java logic.");
113-
}
114-
return Constants.NIL;
109+
return LuaThread.runMain(state, func).first();
115110
}
116111

117112
private static final class PrintMethod extends VarArgFunction {

allium/src/main/java/dev/moongarden/allium/loader/lib/MixinLib.java

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88
import dev.moongarden.allium.api.event.MixinMethodHook;
99
import dev.moongarden.allium.loader.Script;
1010
import dev.moongarden.allium.loader.lib.mixin.MixinClassInfo;
11-
import dev.moongarden.allium.loader.lib.mixin.annotation.method.MixinMethodAnnotations;
12-
import dev.moongarden.allium.loader.lib.mixin.annotation.sugar.MixinSugars;
13-
import dev.moongarden.allium.loader.lib.mixin.builder.MixinClassBuilder;
11+
import dev.moongarden.allium.loader.lib.mixin.builder.AbstractMixinBuilder;
12+
import dev.moongarden.allium.loader.lib.mixin.builder.HookDefinition;
1413
import dev.moongarden.allium.loader.type.StaticBinder;
1514
import dev.moongarden.allium.api.LuaWrapped;
1615
import dev.moongarden.allium.api.OptionalArg;
17-
import dev.moongarden.allium.loader.type.userdata.ClassUserdata;
16+
import dev.moongarden.allium.loader.type.exception.InvalidMixinException;
1817
import dev.moongarden.allium.util.ByteArrayStreamHandler;
1918
import dev.moongarden.allium.util.JsonObjectBuilder;
2019
import dev.moongarden.allium.util.asm.VisitedClass;
@@ -30,29 +29,19 @@
3029
import java.lang.reflect.Method;
3130
import java.net.URL;
3231
import java.nio.charset.StandardCharsets;
33-
import java.util.ArrayList;
34-
import java.util.HashMap;
35-
import java.util.List;
36-
import java.util.Map;
32+
import java.util.*;
3733

3834
@LuaWrapped(name = "mixin")
3935
public class MixinLib extends WrappedScriptLibrary {
4036
private static boolean COMPLETE = false;
4137

42-
// This being the way to define embedded "tables" is hilarious to me.
43-
private static final ClassUserdata<MixinMethodAnnotations> ANNOTATION = StaticBinder.bindClass(EClass.fromJava(MixinMethodAnnotations.class));
44-
private static final ClassUserdata<MixinSugars> SUGAR = StaticBinder.bindClass(EClass.fromJava(MixinSugars.class));
45-
46-
47-
@LuaWrapped public final ClassUserdata<MixinMethodAnnotations> annotation = ANNOTATION;
48-
@LuaWrapped public final ClassUserdata<MixinSugars> sugar = SUGAR;
4938
private final String mixinPackage = "allium." + script.getID() + ".mixin";
5039
private final String mixinConfigName = "allium-"+ script.getID() +"-generated.mixins.json";
5140
private final List<MixinClassInfo> mixins = new ArrayList<>();
5241
private final List<MixinClassInfo> client = new ArrayList<>();
5342
private final List<MixinClassInfo> server = new ArrayList<>();
5443
private final Map<String, String> duckMap = new HashMap<>();
55-
private final Map<String, MixinMethodHook> eventMap = new HashMap<>();
44+
private final Map<String, Map<String, MixinMethodHook>> classHooks = new HashMap<>();
5645

5746
private int nextMixinId = 0;
5847

@@ -61,8 +50,11 @@ public MixinLib(Script script) {
6150
}
6251

6352
@LuaWrapped
64-
public MixinMethodHook get(String hookId) {
65-
return eventMap.get(hookId);
53+
public HookDefinition get(String classId) throws InvalidMixinException {
54+
if (!classHooks.containsKey(classId))
55+
throw new InvalidMixinException(InvalidMixinException.Type.INVALID_CLASS_ID, classId);
56+
57+
return new HookDefinition(classHooks.get(classId));
6658
}
6759

6860
@LuaWrapped
@@ -74,7 +66,7 @@ public LuaValue quack(String mixinId) throws ClassNotFoundException {
7466
}
7567

7668
@LuaWrapped
77-
public MixinClassBuilder to(String targetClass, @OptionalArg @Nullable String[] interfaces, @OptionalArg @Nullable String targetEnvironment, @OptionalArg @Nullable Boolean duck) throws LuaError {
69+
public AbstractMixinBuilder to(String targetClass, @OptionalArg @Nullable String[] interfaces, @OptionalArg @Nullable String targetEnvironment, @OptionalArg @Nullable Boolean duck) throws LuaError {
7870
EnvType targetEnv;
7971
if (targetEnvironment == null) {
8072
targetEnv = null;
@@ -85,7 +77,7 @@ public MixinClassBuilder to(String targetClass, @OptionalArg @Nullable String[]
8577
} else {
8678
throw new LuaError("Mixin for " + targetClass + " expects target environment of nil, 'client' or 'server'.");
8779
}
88-
return MixinClassBuilder.create(
80+
return AbstractMixinBuilder.create(
8981
targetClass,
9082
interfaces == null ? new String[]{} : interfaces,
9183
targetEnv,
@@ -114,8 +106,8 @@ public void addDuck(String id, String path) {
114106
duckMap.put(id, path);
115107
}
116108

117-
public void addMethodHook(String id, MixinMethodHook hook) {
118-
eventMap.put(id, hook);
109+
public void addHooks(String id, Map<String, MixinMethodHook> hooks) {
110+
classHooks.put(id, hooks);
119111
}
120112

121113
public JsonArray mixinsToJson(List<MixinClassInfo> list, Map<String, byte[]> configMap) {

allium/src/main/java/dev/moongarden/allium/loader/lib/mixin/annotation/method/InjectorChef.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.moongarden.allium.loader.lib.mixin.annotation.method;
22

3+
import dev.moongarden.allium.api.event.MixinMethodHook;
34
import dev.moongarden.allium.loader.Script;
45
import dev.moongarden.allium.loader.lib.mixin.annotation.sugar.LuaSugar;
56
import dev.moongarden.allium.loader.type.exception.InvalidArgumentException;
@@ -12,12 +13,13 @@
1213
import java.util.List;
1314

1415
public interface InjectorChef {
15-
void bake(
16+
MixinMethodHook bake(
1617
Script script,
18+
String classId,
1719
String eventId,
1820
ClassWriter classWriter,
1921
VisitedClass mixinClass,
2022
List<LuaMethodAnnotation> annotations,
2123
@Nullable List<? extends LuaSugar> sugarParameters
22-
) throws InvalidMixinException, LuaError, InvalidArgumentException;
24+
) throws InvalidMixinException, LuaError;
2325
}

allium/src/main/java/dev/moongarden/allium/loader/lib/mixin/annotation/method/LuaInjectorAnnotation.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import dev.moongarden.allium.api.event.MixinMethodHook;
44
import dev.moongarden.allium.loader.Script;
55
import dev.moongarden.allium.loader.lib.mixin.annotation.LuaAnnotationParser;
6-
import dev.moongarden.allium.loader.lib.mixin.builder.MixinClassBuilder;
7-
import dev.moongarden.allium.loader.lib.mixin.builder.MixinMethodBuilder;
6+
import dev.moongarden.allium.loader.lib.mixin.builder.AbstractMixinBuilder;
7+
import dev.moongarden.allium.loader.lib.mixin.builder.InternalMixinMethodBuilder;
88
import dev.moongarden.allium.loader.lib.mixin.builder.MixinParameter;
99
import dev.moongarden.allium.loader.type.exception.InvalidArgumentException;
1010
import dev.moongarden.allium.loader.type.exception.InvalidMixinException;
@@ -37,7 +37,7 @@ protected String createInjectName(String scriptId, String visitedMethodName) {
3737
}
3838

3939
protected static VisitedMethod getVisitedMethod(VisitedClass mixinClass, LuaAnnotationParser annotation) throws InvalidMixinException, LuaError {
40-
String descriptor = MixinClassBuilder.cleanDescriptor(
40+
String descriptor = AbstractMixinBuilder.cleanDescriptor(
4141
mixinClass,
4242
annotation.findElement("method", String.class)
4343
);
@@ -46,17 +46,20 @@ protected static VisitedMethod getVisitedMethod(VisitedClass mixinClass, LuaAnno
4646
return mixinClass.getMethod(descriptor);
4747
}
4848

49-
protected static MixinMethodBuilder.WriteFactory createInjectWriteFactory(Script script, String eventName) {
49+
protected static InternalMixinMethodBuilder.WriteFactory createInjectWriteFactory(Script script, String classId, String eventName) {
5050
final Type objectType = Type.getType(Object.class);
51+
5152
return (methodVisitor, desc, paramTypes) -> {
5253
int varPrefix = paramTypes.size();
5354
Type returnType = Type.getReturnType(desc);
5455
List<Type> types = paramTypes.stream().map(MixinParameter::getType).toList();
5556

5657
AsmUtil.getScript(methodVisitor, script);
5758
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, Owners.SCRIPT, "getMixinLib", "()Ldev/moongarden/allium/loader/lib/MixinLib;", false);
59+
methodVisitor.visitLdcInsn(classId);
60+
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, Owners.MIXIN_LIB, "get", "(Ljava/lang/String;)Ldev/moongarden/allium/loader/lib/mixin/builder/HookDefinition;", false);
5861
methodVisitor.visitLdcInsn(eventName);
59-
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, Owners.MIXIN_LIB, "get", "(Ljava/lang/String;)Ldev/moongarden/allium/api/event/MixinMethodHook;", false);
62+
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, Owners.HOOK_DEFINITION, "forId", "(Ljava/lang/String;)Ldev/moongarden/allium/api/event/MixinMethodHook;", false);
6063

6164
AsmUtil.createArray(methodVisitor, varPrefix, types, Object.class, (visitor, index, arg) -> {
6265
visitor.visitVarInsn(arg.getOpcode(ILOAD), index); // <- 2

allium/src/main/java/dev/moongarden/allium/loader/lib/mixin/annotation/method/MixinMethodAnnotations.java

Lines changed: 0 additions & 118 deletions
This file was deleted.

allium/src/main/java/dev/moongarden/allium/loader/lib/mixin/annotation/method/injectors/LuaCustom.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package dev.moongarden.allium.loader.lib.mixin.annotation.method.injectors;
22

3+
import dev.moongarden.allium.api.event.MixinMethodHook;
34
import dev.moongarden.allium.loader.Script;
45
import dev.moongarden.allium.loader.lib.mixin.annotation.method.LuaInjectorAnnotation;
56
import dev.moongarden.allium.loader.lib.mixin.annotation.method.LuaMethodAnnotation;
67
import dev.moongarden.allium.loader.lib.mixin.annotation.sugar.LuaSugar;
7-
import dev.moongarden.allium.loader.lib.mixin.builder.MixinMethodBuilder;
8+
import dev.moongarden.allium.loader.lib.mixin.builder.InternalMixinMethodBuilder;
89
import dev.moongarden.allium.loader.lib.mixin.builder.MixinParameter;
910
import dev.moongarden.allium.loader.type.exception.InvalidArgumentException;
1011
import dev.moongarden.allium.loader.type.exception.InvalidMixinException;
@@ -34,23 +35,23 @@ public LuaCustom(LuaState state, LuaTable annotationTable, Class<?> annotation,
3435
}
3536

3637
@Override
37-
public void bake(Script script, String eventId, ClassWriter classWriter, VisitedClass mixinClass, List<LuaMethodAnnotation> annotations, @Nullable List<? extends LuaSugar> sugarParameters) throws InvalidMixinException, LuaError, InvalidArgumentException {
38+
public MixinMethodHook bake(Script script, String classId, String eventId, ClassWriter classWriter, VisitedClass mixinClass, List<LuaMethodAnnotation> annotations, @Nullable List<? extends LuaSugar> sugarParameters) throws InvalidMixinException, LuaError {
3839
VisitedMethod visitedMethod = mixinClass.getMethod(methodDescriptor);
3940
List<MixinParameter> params = parameters.stream().map(str -> new MixinParameter(Type.getType(str))).toList();
4041

41-
MixinMethodBuilder methodBuilder = MixinMethodBuilder.of(
42+
InternalMixinMethodBuilder methodBuilder = new InternalMixinMethodBuilder(
4243
classWriter, visitedMethod, createInjectName(script.getID(), visitedMethod.name()), params
4344
);
4445

4546
if (sugarParameters != null) methodBuilder.sugars(sugarParameters);
4647

47-
methodBuilder
48+
return methodBuilder
4849
.access(visitedMethod.access() & ~(ACC_PUBLIC | ACC_PROTECTED) | ACC_PRIVATE)
4950
.returnType(Type.getType(returnType))
5051
.annotations(annotations.stream().map(LuaMethodAnnotation::parser).toList())
5152
.signature(visitedMethod.signature())
5253
.exceptions(visitedMethod.exceptions())
53-
.code(createInjectWriteFactory(script, eventId))
54-
.build(script, eventId);
54+
.code(createInjectWriteFactory(script, classId, eventId))
55+
.buildForClass(script, eventId);
5556
}
5657
}

0 commit comments

Comments
 (0)