Skip to content

Commit

Permalink
Replace example mod with the actual InfiniteFluids mod
Browse files Browse the repository at this point in the history
  • Loading branch information
josephcsible committed Jul 10, 2016
1 parent dfe5670 commit 93487f2
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 28 deletions.
12 changes: 9 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ buildscript {

apply plugin: 'forge'

version = "1.0"
group= "com.yourname.modid" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "modid"
version = "0.1.0"
group= "josephcsible.infinitefluids" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "infinitefluids"

minecraft {
version = "1.7.10-10.13.4.1614-1.7.10"
runDir = "eclipse"
}

jar {
manifest {
attributes 'FMLCorePlugin': 'josephcsible.infinitefluids.InfiniteFluidsLoadingPlugin'
}
}

dependencies {
// you may put jars on which you depend on in ./libs
// or you may define them like so..
Expand Down
Binary file added dummy.jar
Binary file not shown.
20 changes: 0 additions & 20 deletions src/main/java/com/example/examplemod/ExampleMod.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package josephcsible.infinitefluids;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import static org.objectweb.asm.Opcodes.*;

import net.minecraft.block.material.Material;
import net.minecraft.launchwrapper.IClassTransformer;

public class InfiniteFluidsClassTransformer implements IClassTransformer {

private void transformUpdateTick(MethodNode mn) {
/*
We're trying to change this:
if (this.field_149815_a >= 2 && this.blockMaterial == Material.water)
to this:
if (this.field_149815_a >= 2 && InfiniteFluidsHooks.shouldCreateSourceBlock(this, worldIn, x, y, z, rand))
Here's the relevant piece of the bytecode:
L18
LINENUMBER 72 L18
FRAME CHOP 1
ALOAD 0
GETFIELD net/minecraft/block/BlockDynamicLiquid.field_149815_a : I
ICONST_2 *** searched for
IF_ICMPLT L23 *** searched for
ALOAD 0 *** target node
*** new stuff goes here
GETFIELD net/minecraft/block/BlockDynamicLiquid.blockMaterial : Lnet/minecraft/block/material/Material; *** removed
GETSTATIC net/minecraft/block/material/Material.water : Lnet/minecraft/block/material/Material; *** removed
IF_ACMPNE L23 *** removed
*/

final String hookDesc = InfiniteFluidsLoadingPlugin.runtimeDeobfuscationEnabled ? "(Lakr;Lahb;IIILjava/util/Random;)Z" : "(Lnet/minecraft/block/BlockDynamicLiquid;Lnet/minecraft/world/World;IIILjava/util/Random;)Z";
AbstractInsnNode targetNode = null;
for (AbstractInsnNode instruction : mn.instructions.toArray())
{
if (instruction.getOpcode() == ICONST_2 && instruction.getNext().getOpcode() == IF_ICMPLT)
{
targetNode = instruction.getNext().getNext(); // this is ALOAD 0
break;
}
}
if (targetNode == null)
{
System.err.println("Failed to find the part of updateTick we need to patch!");
return;
}
System.out.println("Patching updateTick");
mn.instructions.remove(targetNode.getNext()); // remove GETFIELD
mn.instructions.remove(targetNode.getNext()); // remove GETSTATIC
JumpInsnNode n = (JumpInsnNode)targetNode.getNext();
LabelNode ln = n.label;
mn.instructions.remove(n); // remove IF_ACMPNE
InsnList toInsert = new InsnList();
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new VarInsnNode(ILOAD, 2));
toInsert.add(new VarInsnNode(ILOAD, 3));
toInsert.add(new VarInsnNode(ILOAD, 4));
toInsert.add(new VarInsnNode(ALOAD, 5));
toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(InfiniteFluidsHooks.class), "shouldCreateSourceBlock", hookDesc, false));
toInsert.add(new JumpInsnNode(IFEQ, ln));
mn.instructions.insert(targetNode, toInsert);
}

private static ClassNode byteArrayToClassNode(byte[] basicClass) {
ClassNode cn = new ClassNode();
ClassReader cr = new ClassReader(basicClass);
cr.accept(cn, 0);
return cn;
}

private static byte[] classNodeToByteArray(ClassNode cn) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cn.accept(cw);
return cw.toByteArray();
}

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass)
{
if(!transformedName.equals("net.minecraft.block.BlockDynamicLiquid")) {
return basicClass;
}
ClassNode cn = byteArrayToClassNode(basicClass);

String updateTickName, updateTickDesc;
if(InfiniteFluidsLoadingPlugin.runtimeDeobfuscationEnabled) {
updateTickName = "a";
updateTickDesc = "(Lahb;IIILjava/util/Random;)V";
} else {
updateTickName = "updateTick";
updateTickDesc = "(Lnet/minecraft/world/World;IIILjava/util/Random;)V";
}
for(MethodNode mn : cn.methods) {
if (mn.name.equals(updateTickName) && mn.desc.equals(updateTickDesc)) {
transformUpdateTick(mn);
return classNodeToByteArray(cn);
}
}
System.err.println("Failed to find the updateTick method!");
return classNodeToByteArray(cn);
}
}
15 changes: 15 additions & 0 deletions src/main/java/josephcsible/infinitefluids/InfiniteFluidsHooks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package josephcsible.infinitefluids;

import java.util.Random;
import net.minecraft.block.BlockDynamicLiquid;
import net.minecraft.block.material.Material;
import net.minecraft.world.World;

public class InfiniteFluidsHooks {
public static boolean shouldCreateSourceBlock(BlockDynamicLiquid liquid, World worldIn, int x, int y, int z, Random rand) {
Material material = liquid.getMaterial();
if(material == Material.water) return true;
if(material == Material.lava && worldIn.provider.isHellWorld) return true;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package josephcsible.infinitefluids;

import java.util.Map;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;

@MCVersion("1.7.10")
public class InfiniteFluidsLoadingPlugin implements IFMLLoadingPlugin {

// XXX this feels hacky. Is this really the best way to keep track of this?
public static boolean runtimeDeobfuscationEnabled;

@Override
public String[] getASMTransformerClass() {
return new String[]{InfiniteFluidsClassTransformer.class.getName()};
}

@Override
public String getModContainerClass() {
return InfiniteFluidsModContainer.class.getName();
}

@Override
public String getSetupClass() {
return null;
}

@Override
public void injectData(Map<String, Object> data) {
runtimeDeobfuscationEnabled = (Boolean) data.get("runtimeDeobfuscationEnabled");
}

@Override
public String getAccessTransformerClass() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package josephcsible.infinitefluids;

import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.LoadController;
import cpw.mods.fml.common.ModMetadata;

public class InfiniteFluidsModContainer extends DummyModContainer {
public InfiniteFluidsModContainer() {
super(new ModMetadata());
ModMetadata metadata = getMetadata();
// XXX almost all this is duplicated between here and mcmod.info
metadata.modId = "infinitefluids";
// XXX version is duplicated between here and build.gradle
metadata.version = "0.1.0";
metadata.name = "InfiniteFluids";
metadata.description = "Allows fluids other than water to be infinite (i.e., turn non-source blocks next to source blocks into source blocks).";
metadata.url = "";
metadata.authorList.add("Joseph C. Sible");
}

@Override
public boolean registerBus(EventBus bus, LoadController controller) {
return true; // even if we don't have anything to register for, if we return false, Forge says we're not loaded
}
}
10 changes: 5 additions & 5 deletions src/main/resources/mcmod.info
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[
{
"modid": "examplemod",
"name": "Example Mod",
"description": "Example placeholder mod.",
"modid": "infinitefluids",
"name": "InfiniteFluids",
"description": "Allows fluids other than water to be infinite (i.e., turn non-source blocks next to source blocks into source blocks).",
"version": "${version}",
"mcversion": "${mcversion}",
"url": "",
"updateUrl": "",
"authorList": ["ExampleDude"],
"credits": "The Forge and FML guys, for making this example",
"authorList": ["Joseph C. Sible"],
"credits": "",
"logoFile": "",
"screenshots": [],
"dependencies": []
Expand Down

0 comments on commit 93487f2

Please sign in to comment.