Skip to content

Commit

Permalink
Make extended fluids start to work with Sodium
Browse files Browse the repository at this point in the history
  • Loading branch information
Cadiboo committed Jan 20, 2024
1 parent aeaf23a commit 204b13a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 22 deletions.
3 changes: 3 additions & 0 deletions src/main/java/io/github/cadiboo/nocubes/hooks/Hooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static boolean collisionsEnabledFor(BlockStateBase state) {
/**
* Called from: {@link RebuildTask#compile} right before the BlockPos.getAllInBoxMutable iteration
* Calls: {@link RendererDispatcher#renderChunk} to render our fluids and smooth terrain
* Call injected by {@link MixinAsm#transformChunkRenderer}
*/
@OnlyIn(Dist.CLIENT)
public static void preIteration(
Expand All @@ -76,6 +77,7 @@ public static void preIteration(

/**
* Same as {@link Hooks#preIteration} but for Sodium.
* Call injected by {@link MixinAsm#transformSodiumChunkRenderer}
*/
@OnlyIn(Dist.CLIENT)
public static void preIterationSodium(
Expand Down Expand Up @@ -113,6 +115,7 @@ public static void preIterationSodium(

/**
* Called from: {@link RebuildTask#compile} and {@link LiquidBlockRenderer#tesselate} instead of {@link BlockState#getFluidState()}
* Call injected by {@link MixinAsm#transformChunkRenderer} or {@link MixinAsm#transformSodiumChunkRenderer}
* <p>
* Hooking this makes extended fluids render properly
*/
Expand Down
64 changes: 42 additions & 22 deletions src/main/java/io/github/cadiboo/nocubes/hooks/MixinAsm.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,27 +88,11 @@ public static void transformChunkRenderer(ClassNode targetClass) {
print("Done injecting the preIteration hook");
}

// Redirects 'state.getFluidState()' to our own code so we can have extended fluids render properly
{
var getFluidStateCall = findFirstMethodCall(
methodNode,
ASMAPI.MethodType.VIRTUAL,
"net/minecraft/world/level/block/state/BlockState",
ASMAPI.mapMethod("m_60819_"), // getFluidState
"()Lnet/minecraft/world/level/material/FluidState;",
0 // startIndex
);
var previousLabel = findFirstLabelBefore(instructions, getFluidStateCall);
removeBetweenIndicesInclusive(instructions, instructions.indexOf(previousLabel) + 1, instructions.indexOf(getFluidStateCall));
instructions.insert(previousLabel, ASMAPI.listOf(
new VarInsnNode(Opcodes.ALOAD, isOptiFinePresent ? (ofg8 ? 19 : 17) : 16), // pos
new VarInsnNode(Opcodes.ALOAD, isOptiFinePresent ? (ofg8 ? 20 : 18) : 18), // state
callNoCubesHook("getRenderFluidState", "(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/level/material/FluidState;")
));
// We didn't remove the ASTORE instruction with our 'removeBetweenIndicesInclusive' so the result of our hook call automatically gets stored
print("Done injecting the fluid state getter redirect");
}

redirectBlockStateGetFluidStateSoExtendedFluidsWork(
methodNode,
// blockPos local variable index
isOptiFinePresent ? (ofg8 ? 19 : 17) : 16
);
}

static boolean detectOptiFine(InsnList instructions) {
Expand All @@ -127,6 +111,39 @@ static boolean detectOptiFine(InsnList instructions) {
return false;
}

/**
* Redirects 'state.getFluidState()' to our own code, so we can have extended fluids render properly
* Specifically: changes 'state.getFluidState()' to 'Hooks.getRenderFluidState(pos, state)'
*/
static void redirectBlockStateGetFluidStateSoExtendedFluidsWork(MethodNode methodNode, int blockPosLocalVarIndex) {
var getFluidStateCall = findFirstMethodCall(
methodNode,
ASMAPI.MethodType.VIRTUAL,
"net/minecraft/world/level/block/state/BlockState",
ASMAPI.mapMethod("m_60819_"), // getFluidState
"()Lnet/minecraft/world/level/material/FluidState;",
0 // startIndex
);

var instructions = methodNode.instructions;
var previousLabel = findFirstLabelBefore(instructions, getFluidStateCall);

// Change
// LABEL
// <Somehow put BlockState onto the stack>
// INVOKE BlockState.getFluidState
// to
// LABEL
// LOAD blockPos
// <Somehow put BlockState onto the stack>
// INVOKE Hooks.getFluidState
instructions.insert(previousLabel, new VarInsnNode(Opcodes.ALOAD, blockPosLocalVarIndex));
instructions.insert(getFluidStateCall, callNoCubesHook("getRenderFluidState", "(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/level/material/FluidState;"));
instructions.remove(getFluidStateCall);

print("Done injecting the fluid state getter redirect");
}

// endregion

// region Fluid rendering
Expand Down Expand Up @@ -217,6 +234,7 @@ public static void transformSodiumChunkRenderer(ClassNode targetClass) {
var storeRenderContext = renderContextConstructor.getNext();
assertInstructionFound(storeRenderContext, "ASTORE blockRenderContext", instructions);

var blockPosLocalVarIndex = 14;
instructions.insert(storeRenderContext, ASMAPI.listOf(
// Fields
new VarInsnNode(Opcodes.ALOAD, 0), // this
Expand All @@ -235,11 +253,13 @@ public static void transformSodiumChunkRenderer(ClassNode targetClass) {
new VarInsnNode(Opcodes.ILOAD, 11), // maxX
new VarInsnNode(Opcodes.ILOAD, 12), // maxY
new VarInsnNode(Opcodes.ILOAD, 13), // maxZ
new VarInsnNode(Opcodes.ALOAD, 14), // blockPos
new VarInsnNode(Opcodes.ALOAD, blockPosLocalVarIndex), // blockPos
new VarInsnNode(Opcodes.ALOAD, 15), // modelOffset
new VarInsnNode(Opcodes.ALOAD, 16), // context
callNoCubesHook("preIterationSodium", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lnet/minecraft/client/renderer/chunk/VisGraph;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;IIIIIILnet/minecraft/core/BlockPos$MutableBlockPos;Lnet/minecraft/core/BlockPos$MutableBlockPos;Ljava/lang/Object;)V")
));

redirectBlockStateGetFluidStateSoExtendedFluidsWork(methodNode, blockPosLocalVarIndex);
}

/**
Expand Down

0 comments on commit 204b13a

Please sign in to comment.