1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package moe.nea.firmament.init;
import me.shedaniel.mm.api.ClassTinkerers;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.block.BlockModels;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.chunk.SectionBuilder;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.util.math.BlockPos;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
public class SectionBuilderRiser extends RiserUtils {
@IntermediaryName(SectionBuilder.class)
String SectionBuilder;
@IntermediaryName(BlockPos.class)
String BlockPos;
@IntermediaryName(BlockRenderManager.class)
String BlockRenderManager;
@IntermediaryName(BlockState.class)
String BlockState;
@IntermediaryName(BakedModel.class)
String BakedModel;
String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
Type getModelDesc = Type.getMethodType(
getTypeForClassName(BlockRenderManager),
getTypeForClassName(BlockState)
);
String getModel = remapper.mapMethodName(
"intermediary",
Intermediary.<BlockRenderManager>className(),
Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel),
Type.getMethodDescriptor(
getTypeForClassName(Intermediary.<BakedModel>className()),
getTypeForClassName(Intermediary.<BlockState>className())
)
);
@Override
public void addTinkerers() {
if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo"))
ClassTinkerers.addTransformation(SectionBuilder, this::handle, true);
}
private void handle(ClassNode classNode) {
for (MethodNode method : classNode.methods) {
if (method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate") &&
method.name.startsWith("redirect$")) {
handleIndigo(method);
return;
}
}
new RuntimeException("Could not inject tesselation hook despite fabric renderer indigo being loaded").printStackTrace();
}
private void handleIndigo(MethodNode method) {
LocalVariableNode blockPosVar = null, blockStateVar = null;
for (LocalVariableNode localVariable : method.localVariables) {
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) {
blockPosVar = localVariable;
}
if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) {
blockStateVar = localVariable;
}
}
if (blockPosVar == null || blockStateVar == null) {
System.err.println("Firmament could inject into indigo: missing either block pos or blockstate");
return;
}
for (AbstractInsnNode instruction : method.instructions) {
if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue;
var methodInsn = (MethodInsnNode) instruction;
if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager))))
continue;
method.instructions.insertBefore(
methodInsn,
new MethodInsnNode(
Opcodes.INVOKESTATIC,
getTypeForClassName(CustomBlockTextures).getInternalName(),
"enterFallbackCall",
Type.getMethodDescriptor(Type.VOID_TYPE)
));
var insnList = new InsnList();
insnList.add(new MethodInsnNode(
Opcodes.INVOKESTATIC,
getTypeForClassName(CustomBlockTextures).getInternalName(),
"exitFallbackCall",
Type.getMethodDescriptor(Type.VOID_TYPE)
));
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index));
insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index));
insnList.add(new MethodInsnNode(
Opcodes.INVOKESTATIC,
getTypeForClassName(CustomBlockTextures).getInternalName(),
"patchIndigo",
Type.getMethodDescriptor(getTypeForClassName(BakedModel),
getTypeForClassName(BakedModel),
getTypeForClassName(BlockPos),
getTypeForClassName(BlockState)),
false
));
method.instructions.insert(methodInsn, insnList);
}
}
}
|