aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java')
-rw-r--r--src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
new file mode 100644
index 0000000..2be11a6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
@@ -0,0 +1,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);
+ }
+ }
+}