Jump to content

[1.7.10][SOLVED] Insert method call beteween multiple } (}}(here)}})


Elix_x

Recommended Posts

Good day, i have a quastion: how can i insert my method call between multiple }???

So, here's the code that i'm modifiying (i'm not posting whole method, it's too long) and insertion parts are marked by //INSERTION:, because i'm inserting 2 calls:

for (int k2 = 0; k2 < 2; ++k2)
                {
                    boolean flag = false;
                    boolean flag1 = false;
                    boolean flag2 = false;

                    for (int l2 = j; l2 < i1; ++l2)
                    {
                        for (int i3 = k; i3 < j1; ++i3)
                        {
                            for (int j3 = i; j3 < l; ++j3)
                            {
                                Block block = chunkcache.getBlock(j3, l2, i3);
							//INSERTION: SUCCESFULL
                                if (block.getMaterial() != Material.air)
                                {
                                    if (!flag2)
                                    {
                                        flag2 = true;
                                        this.preRenderBlocks(k2);
                                    }

                                    if (k2 == 0 && block.hasTileEntity(chunkcache.getBlockMetadata(j3, l2, i3)))
                                    {
                                        TileEntity tileentity = chunkcache.getTileEntity(j3, l2, i3);

                                        if (TileEntityRendererDispatcher.instance.hasSpecialRenderer(tileentity))
                                        {
                                            this.tileEntityRenderers.add(tileentity);
                                        }
                                    }

                                    int k3 = block.getRenderBlockPass();

                                    if (k3 > k2)
                                    {
                                        flag = true;
                                    }

                                    if (!block.canRenderInPass(k2)) continue;

                                    {
                                        flag1 |= renderblocks.renderBlockByRenderType(block, j3, l2, i3);

                                        if (block.getRenderType() == 0 && j3 == l1 && l2 == i2 && i3 == j2)
                                        {
                                            renderblocks.setRenderFromInside(true);
                                            renderblocks.setRenderAllFaces(true);
                                            renderblocks.renderBlockByRenderType(block, j3, l2, i3);
                                            renderblocks.setRenderFromInside(false);
                                            renderblocks.setRenderAllFaces(false);
                                        }
                                    }
                                }
							//INSERTION: UNSUCCESFULL, CODE MOVES TO 3 LINES ABOVE (i think, because it is called, but not always...)
                            }
                        }
                    }

What i also tried: in first insertion create ifeq redirecting to labale node above second statement, to which called method will always return true, but it is not working either...

 

And if you want, method to patch it (not sure if needed, but):

private byte[] patchWorldRenderer(String name, byte[] bytes) {
	String updateRenderer = ColourfullBlocksTranslator.getMapedMethodName("WorldRenderer", "func_147892_a", "updateRenderer");
	String updateRendererDesc = ColourfullBlocksTranslator.getMapedMethodDesc("WorldRenderer", "func_147892_a", "(Lnet/minecraft/entity/EntityLivingBase;)V");

	ClassNode classNode = new ClassNode();
	ClassReader classReader = new ClassReader(bytes);
	classReader.accept(classNode, 0);

	for(MethodNode method : classNode.methods){
		if(method.name.equals(updateRenderer) && method.desc.equals(updateRendererDesc)){
			try{
				logger.info("**************************************************");
				logger.info("Patching updateRenderer");

				/*
				 * INVOKEVIRTUAL net/minecraft/world/ChunkCache.getBlock (III)Lnet/minecraft/block/Block;
				 * ASTORE 24
				 */

				AbstractInsnNode targetNode = null;
				AbstractInsnNode targetNode2 = null;

				for(AbstractInsnNode currentNode : method.instructions.toArray()){
					if(currentNode.getOpcode() == Opcodes.INVOKEVIRTUAL){
						MethodInsnNode m = (MethodInsnNode) currentNode;
						if(m.owner.replace("/", ".").equals(ColourfullBlocksTranslator.getMapedClassName("world.ChunkCache")) && m.name.equals(ColourfullBlocksTranslator.getMapedMethodName("ChunkCache", "func_147439_a", "getBlock"))){
							/*if(m.getNext().getOpcode() == Opcodes.ASTORE){
								VarInsnNode var = (VarInsnNode) m.getNext();
								if(var.var == 24){*/
							targetNode = currentNode.getNext();
							break;
							/*}
							}*/
						}
					}
				}

				/*
				 * ICONST_0
				 * INVOKEVIRTUAL net/minecraft/client/renderer/RenderBlocks.setRenderAllFaces (Z)V
				 */

				for(AbstractInsnNode currentNode : method.instructions.toArray()){
					if(currentNode.getOpcode() == Opcodes.INVOKEVIRTUAL){
						MethodInsnNode m = (MethodInsnNode) currentNode;
						if(m.owner.replace("/", ".").equals(ColourfullBlocksTranslator.getMapedClassName("client.renderer.RenderBlocks")) && m.name.equals(ColourfullBlocksTranslator.getMapedMethodName("RenderBlocks", "func_147753_b", "setRenderAllFaces"))){
							if(m.getPrevious().getOpcode() == Opcodes.ICONST_0){
								targetNode2 = currentNode;
								break;
							}
						}
					}
				}

				LabelNode goToEnd = new LabelNode();

				InsnList list = new InsnList();
				list.add(new VarInsnNode(Opcodes.ALOAD, 0));
				list.add(new VarInsnNode(Opcodes.ALOAD, 16));
				list.add(new VarInsnNode(Opcodes.ALOAD, 1));
				list.add(new VarInsnNode(Opcodes.ILOAD, 23));
				list.add(new VarInsnNode(Opcodes.ILOAD, 21));
				list.add(new VarInsnNode(Opcodes.ILOAD, 22));
				list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "code.elix_x.coremods.colourfullblocks.core.ColourfullBlocksHooks".replace(".", "/"), "renderBlock", "(L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.WorldRenderer").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.RenderBlocks").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("entity.EntityLivingBase").replace(".", "/") + ";III)Z", false));
				list.add(new JumpInsnNode(Opcodes.IFEQ, goToEnd));
				method.instructions.insert(targetNode, list);

				InsnList l = new InsnList();
				l.add(goToEnd);
				l.add(new VarInsnNode(Opcodes.ALOAD, 0));
				l.add(new VarInsnNode(Opcodes.ALOAD, 16));
				l.add(new VarInsnNode(Opcodes.ALOAD, 1));
				l.add(new VarInsnNode(Opcodes.ILOAD, 23));
				l.add(new VarInsnNode(Opcodes.ILOAD, 21));
				l.add(new VarInsnNode(Opcodes.ILOAD, 22));
				l.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "code.elix_x.coremods.colourfullblocks.core.ColourfullBlocksHooks".replace(".", "/"), "postRenderBlock", "(L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.WorldRenderer").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.RenderBlocks").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("entity.EntityLivingBase").replace(".", "/") + ";III)V", false));
				method.instructions.insert(targetNode2, l);

				logger.info("Patching updateRenderer Completed");
				logger.info("**************************************************");
			}catch(Exception e){
				logger.info("Patching updateRenderer Failed With Exception:");
				e.printStackTrace();
				logger.info("**************************************************");
			}
		}
	}

	ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
	classNode.accept(writer);
	return writer.toByteArray();
}

 

Any help is appreciated.

If you want any code - just ask.

 

Link to comment
Share on other sites

Don't think in "}"'s or "{"'s or even in Java code. Think in bytecode.

 

To be honest, you are probably not qualified to make a coremod if you ask this question (general policy is: "If you can't figure out how to coremod, you should not do it").

 

So, why do you want a coremod?

First: i understand that in bytecode there's no such thing as {}, there are labels and ifs are represented like "if true - continue, if not - goto l254"...

And that poses problems, because last "}" redirects it directly to end (in this case back to loop) without passing via additional labels (and it must not). I know that i could manually change redirection to new label, but will not it be too much redirections to apply? So i was thinking if there's easier way???

 

Second: why i want coremod: disable rendering of certain blocks (any) in certain positions (any)...

Link to comment
Share on other sites

There is no easier way. javac optimizes nested statements to use one common "exit-label". If you want to rewrite this, you have to either find a different place for your hook (in general keep it as simple as possible, if anyhow possible inject at beginning of end of method and only inject something like a static method call into your mod).

 

Don't worry about "multiple jumps" (goto labela; labela: goto labelb; etc.). This is a trivial thing to optimize away for the JVM and it will happily do so.

Thanks, i'm already inserting one call in beginning, but i need one in the end (for different purpose, for different mod). So it will be easier easier to replace them... Okay, but there's 3 "final" ifs and one continue... Ok, i'll try it...

 

EDIT: Hmm, this is end of loop, and has first in method IINC, probably i can use it as mark of where i can insert code...

Link to comment
Share on other sites

Actually, the easiest way of making a coremod is to replace the whole class or the whole method. This would save time since you don't need to work to find out where the byte code insert. Of course, this reduces compatibility.

 

Edit: It's "replace" not "place"

Author of Tao Land Mod.

width=200 height=69http://taoland.herbix.me/images/1/14/TaoLandLogo.png[/img]

Also, author of RenderTo

----

I'm not an English native speaker. I just try my best.

Link to comment
Share on other sites

Do not do this.

It defeats the entire purpose of a coremod.

 

Sorry about that.

I know this would cause compatibility issues. But... I don't know the purpose of a coremod even I have wrote some. Is it bad to replace a method or a class?

Author of Tao Land Mod.

width=200 height=69http://taoland.herbix.me/images/1/14/TaoLandLogo.png[/img]

Also, author of RenderTo

----

I'm not an English native speaker. I just try my best.

Link to comment
Share on other sites

Do not do this.

It defeats the entire purpose of a coremod.

 

Sorry about that.

I know this would cause compatibility issues. But... I don't know the purpose of a coremod even I have wrote some. Is it bad to replace a method or a class?

 

It is not necessarily "bad" BUT it is not good. It does no one any good replacing a method or class. Not only does it limit compatibility, but it can potentially break the game. Around here it is strongly frowned upon to do such, and it should only ever be used as an absolutely last resort, which you should never reach. Almost anything you will ever want to do, either Forge already provides a way, or a coremod will fill the gap. I will admit, I know nothing about how to make a core mod, my programming skills are no where near where they need to be to do that. But I can say, if you don'd think there is a way in Forge to do something, then you can either request it on github, or consider making a coremod, just do NOT edit the classes directly.

Link to comment
Share on other sites

But I can say, if you don'd think there is a way in Forge to do something, then you can either request it on github, or consider making a coremod, just do NOT edit the classes directly.

 

I don't mean to directly modify vanilla classes. I mean I would replace it by a coremod.

Author of Tao Land Mod.

width=200 height=69http://taoland.herbix.me/images/1/14/TaoLandLogo.png[/img]

Also, author of RenderTo

----

I'm not an English native speaker. I just try my best.

Link to comment
Share on other sites

I don't mean to directly modify vanilla classes. I mean I would replace it by a coremod.

 

It is not bad to use a Coremod. Diesieben was saying not to edit Minecraft classes directly, as that is what it sounded like you were saying. I cannot go into the specifics of how coremods work. As I said in my last post, my programming skill level is nowhere near being able to make a coremod, and I have a basic understanding of them, but cannot explain how they work clearly.

Link to comment
Share on other sites

What I was saying was: The benefit of coremods over "traditional" jar mods is that more than one mod can edit the same class or even method. If you just plaster new versions of classes/methods into the game you go back to the same problems jar mods have.

 

Yes, you are right. I know it now.

Thank you.

Author of Tao Land Mod.

width=200 height=69http://taoland.herbix.me/images/1/14/TaoLandLogo.png[/img]

Also, author of RenderTo

----

I'm not an English native speaker. I just try my best.

Link to comment
Share on other sites

Okay, i tried what i found, and it not seems to be working: patch succesfull, method not called...

1) So, iinc that i'm interested in is second in whole method, that's why there's boolean and if else...

2) Instead of redirecting each label redirection to new, i tried to insert my code below this label and move old code one label below

Transofmer's part responsible for this:

boolean b = false;

				for(AbstractInsnNode currentNode : method.instructions.toArray()){
					if(currentNode.getOpcode() == Opcodes.IINC){
						if(!b){
							b = true;
						} else {	
							targetNode2 = currentNode.getPrevious();
							break;
						}
					}
				}

				InsnList l = new InsnList();
				l.add(new VarInsnNode(Opcodes.ALOAD, 0));
				l.add(new VarInsnNode(Opcodes.ALOAD, 16));
				l.add(new VarInsnNode(Opcodes.ALOAD, 1));
				l.add(new VarInsnNode(Opcodes.ILOAD, 23));
				l.add(new VarInsnNode(Opcodes.ILOAD, 21));
				l.add(new VarInsnNode(Opcodes.ILOAD, 22));
				l.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "code.elix_x.coremods.colourfullblocks.core.ColourfullBlocksHooks".replace(".", "/"), "postRenderBlock", "(L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.WorldRenderer").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("client.renderer.RenderBlocks").replace(".", "/") + ";L" + ColourfullBlocksTranslator.getMapedClassName("entity.EntityLivingBase").replace(".", "/") + ";III)V", false));
				l.add(new LabelNode());
				method.instructions.insert(targetNode2, l);

And this label's bytecode:

L48
    LINENUMBER 175 L48
   FRAME CHOP 2
    IINC 23 1
    GOTO L44

 

Any help is appreciated...

If you have any questions - just ask!

 

EDIT: changed transformer once more, now it's working!!!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.