Skip to content

Commit bdcb3f1

Browse files
committed
replace overwrite mixin with ASM hook
1 parent 110e5da commit bdcb3f1

File tree

7 files changed

+285
-221
lines changed

7 files changed

+285
-221
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ minecraft_fp {
1717
}
1818

1919
core {
20+
coreModClass = "internal.core.CoreLoadingPlugin"
2021
accessTransformerFile = "fluidlogged_at.cfg"
2122
}
2223

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This file is part of FluidLogged.
3+
*
4+
* Copyright (C) 2025 The MEGA Team, FalsePattern
5+
* All Rights Reserved
6+
*
7+
* The above copyright notice, this permission notice and the word "MEGA"
8+
* shall be included in all copies or substantial portions of the Software.
9+
*
10+
* FluidLogged is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Lesser General Public License as published by
12+
* the Free Software Foundation, only version 3 of the License.
13+
*
14+
* FluidLogged is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with FluidLogged. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package mega.fluidlogged.internal.core;
24+
25+
import lombok.val;
26+
import mega.fluidlogged.internal.FluidLogBlockAccess;
27+
28+
import net.minecraft.client.renderer.RenderBlocks;
29+
30+
@SuppressWarnings("unused") // Called by ASM
31+
public class ASMHooks {
32+
public static int drawFluidLogged(RenderBlocks renderBlocks, int x, int y, int z, int pass) {
33+
34+
val fluid = ((FluidLogBlockAccess)renderBlocks.blockAccess).fl$getFluid(x, y, z);
35+
val fluidBlock = fluid == null ? null : fluid.toBlock();
36+
37+
int result = 0;
38+
39+
if (pass < 1 && fluidBlock != null && fluidBlock.getRenderBlockPass() > 0) {
40+
result |= 0b1;
41+
}
42+
if (fluidBlock != null && fluidBlock.canRenderInPass(pass) && renderBlocks.renderBlockByRenderType(fluidBlock, x, y, z)) {
43+
result |= 0b10;
44+
}
45+
46+
return result;
47+
}
48+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* ChunkAPI
3+
*
4+
* Copyright (C) 2023-2024 FalsePattern
5+
* All Rights Reserved
6+
*
7+
* The above copyright notice and this permission notice
8+
* shall be included in all copies or substantial portions of the Software.
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Affero General Public License as published by
12+
* the Free Software Foundation, either version 3 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU Affero General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Affero General Public License
21+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*
23+
* This program comes with additional permissions according to Section 7 of the
24+
* GNU Affero General Public License. See the full LICENSE file for details.
25+
*/
26+
27+
package mega.fluidlogged.internal.core;
28+
29+
import mega.fluidlogged.Tags;
30+
31+
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
32+
33+
import java.util.Map;
34+
35+
@IFMLLoadingPlugin.TransformerExclusions(Tags.ROOT_PKG + ".internal.core")
36+
public class CoreLoadingPlugin implements IFMLLoadingPlugin {
37+
@Override
38+
public String[] getASMTransformerClass() {
39+
return new String[]{Tags.ROOT_PKG + ".internal.core.FluidLogTransformer"};
40+
}
41+
42+
@Override
43+
public String getModContainerClass() {
44+
return null;
45+
}
46+
47+
@Override
48+
public String getSetupClass() {
49+
return null;
50+
}
51+
52+
@Override
53+
public void injectData(Map<String, Object> data) {
54+
55+
}
56+
57+
@Override
58+
public String getAccessTransformerClass() {
59+
return null;
60+
}
61+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* This file is part of FluidLogged.
3+
*
4+
* Copyright (C) 2025 The MEGA Team, FalsePattern
5+
* All Rights Reserved
6+
*
7+
* The above copyright notice, this permission notice and the word "MEGA"
8+
* shall be included in all copies or substantial portions of the Software.
9+
*
10+
* FluidLogged is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Lesser General Public License as published by
12+
* the Free Software Foundation, only version 3 of the License.
13+
*
14+
* FluidLogged is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with FluidLogged. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package mega.fluidlogged.internal.core;
24+
25+
import com.falsepattern.lib.asm.ASMUtil;
26+
import com.falsepattern.lib.mapping.MappingManager;
27+
import com.falsepattern.lib.mapping.types.UniversalMethod;
28+
import com.falsepattern.lib.turboasm.ClassNodeHandle;
29+
import com.falsepattern.lib.turboasm.TurboClassTransformer;
30+
import lombok.val;
31+
import mega.fluidlogged.Tags;
32+
import org.jetbrains.annotations.NotNull;
33+
import org.objectweb.asm.Opcodes;
34+
import org.objectweb.asm.Type;
35+
import org.objectweb.asm.tree.InsnNode;
36+
import org.objectweb.asm.tree.MethodInsnNode;
37+
import org.objectweb.asm.tree.VarInsnNode;
38+
39+
import net.minecraft.client.renderer.RenderBlocks;
40+
41+
import java.lang.reflect.Method;
42+
43+
/**
44+
* Waterlogging renderer hook
45+
*
46+
* Injection point:
47+
* <pre>{@code
48+
* <------------ here
49+
* int k3 = block.getRenderBlockPass();
50+
*
51+
* if (k3 > k2)
52+
* {
53+
* flag = true;
54+
* }
55+
*
56+
* if (!block.canRenderInPass(k2)) continue;
57+
* }</pre>
58+
*
59+
* Injected code snippet:
60+
* <pre>{@code
61+
* int tmp = ASMHooks.drawFluidLogged(renderblocks, x, y, z, pass);
62+
* nextPass |= tmp & 1;
63+
* renderedAnything |= (tmp >>> 1) & 1;
64+
* }</pre>
65+
*/
66+
public class FluidLogRendererInjector implements TurboClassTransformer {
67+
@Override
68+
public String owner() {
69+
return Tags.MOD_ID;
70+
}
71+
72+
@Override
73+
public String name() {
74+
return "FluidLogRendererInjector";
75+
}
76+
77+
@Override
78+
public boolean shouldTransformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) {
79+
return "net.minecraft.client.renderer.WorldRenderer".equals(className);
80+
}
81+
82+
@Override
83+
public boolean transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) {
84+
val cn = classNode.getNode();
85+
if (cn == null) {
86+
return false;
87+
}
88+
val method = ASMUtil.findMethodFromMCP(cn, "updateRenderer", "(Lnet/minecraft/entity/EntityLivingBase;)V", false);
89+
val iter = method.instructions.iterator();
90+
while (iter.hasNext()) {
91+
val insn = iter.next();
92+
if (!(insn instanceof MethodInsnNode))
93+
continue;
94+
val mInsn = (MethodInsnNode) insn;
95+
if (!"net/minecraft/block/Block".equals(mInsn.owner))
96+
continue;
97+
UniversalMethod uMethod;
98+
try {
99+
uMethod = MappingManager.getMethod(mInsn);
100+
} catch (ClassNotFoundException | NoSuchMethodException ignored) {
101+
continue;
102+
}
103+
if (!"getRenderBlockPass".equals(uMethod.name.mcp())) {
104+
continue;
105+
}
106+
iter.previous();
107+
iter.add(new VarInsnNode(Opcodes.ALOAD, 16));
108+
iter.add(new VarInsnNode(Opcodes.ILOAD, 23));
109+
iter.add(new VarInsnNode(Opcodes.ILOAD, 21));
110+
iter.add(new VarInsnNode(Opcodes.ILOAD, 22));
111+
iter.add(new VarInsnNode(Opcodes.ILOAD, 17));
112+
Method target;
113+
try {
114+
target = ASMHooks.class.getDeclaredMethod("drawFluidLogged", RenderBlocks.class, int.class, int.class, int.class, int.class);
115+
} catch (NoSuchMethodException e) {
116+
throw new RuntimeException(e);
117+
}
118+
iter.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(target.getDeclaringClass()), target.getName(), Type.getMethodDescriptor(target), false));
119+
iter.add(new InsnNode(Opcodes.DUP));
120+
iter.add(new InsnNode(Opcodes.ICONST_1));
121+
iter.add(new InsnNode(Opcodes.IAND));
122+
iter.add(new VarInsnNode(Opcodes.ILOAD, 18));
123+
iter.add(new InsnNode(Opcodes.IOR));
124+
iter.add(new VarInsnNode(Opcodes.ISTORE, 18));
125+
iter.add(new InsnNode(Opcodes.ICONST_1));
126+
iter.add(new InsnNode(Opcodes.IUSHR));
127+
iter.add(new InsnNode(Opcodes.ICONST_1));
128+
iter.add(new InsnNode(Opcodes.IAND));
129+
iter.add(new VarInsnNode(Opcodes.ILOAD, 19));
130+
iter.add(new InsnNode(Opcodes.IOR));
131+
iter.add(new VarInsnNode(Opcodes.ISTORE, 19));
132+
return true;
133+
}
134+
return false;
135+
}
136+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This file is part of FluidLogged.
3+
*
4+
* Copyright (C) 2025 The MEGA Team, FalsePattern
5+
* All Rights Reserved
6+
*
7+
* The above copyright notice, this permission notice and the word "MEGA"
8+
* shall be included in all copies or substantial portions of the Software.
9+
*
10+
* FluidLogged is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Lesser General Public License as published by
12+
* the Free Software Foundation, only version 3 of the License.
13+
*
14+
* FluidLogged is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with FluidLogged. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package mega.fluidlogged.internal.core;
24+
25+
import com.falsepattern.lib.turboasm.MergeableTurboTransformer;
26+
import com.falsepattern.lib.turboasm.TurboClassTransformer;
27+
28+
import java.util.Collections;
29+
import java.util.List;
30+
31+
public class FluidLogTransformer extends MergeableTurboTransformer {
32+
private static List<TurboClassTransformer> transformers() {
33+
return Collections.singletonList(new FluidLogRendererInjector());
34+
}
35+
public FluidLogTransformer() {
36+
super(transformers());
37+
}
38+
}

0 commit comments

Comments
 (0)