Jump to content

WinneonSword

Members
  • Posts

    19
  • Joined

  • Last visited

Everything posted by WinneonSword

  1. Yes, I'm using ASM because I am editing main classes such as the vanilla gui's and a few other things. This is just the first one, and I don't want to go down the crude TickHandler route of overriding gui's when this is more mod - compatible.
  2. With the setup I have, it practically transforms the method you tell it into what you define in a certain class. Pretty standard, huh? Well, it seems to transform it correctly, but then MC cannot find the class that was transformed for some reason and it just crashes. Here is the error: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at net.minecraft.launchwrapper.Launch.launch(Launch.java:131) at net.minecraft.launchwrapper.Launch.main(Launch.java:27) Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/gui/GuiMainMenu at net.minecraft.client.main.Main.main(Main.java:37) ... 6 more Caused by: java.lang.ClassNotFoundException: net.minecraft.client.gui.GuiMainMenu at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:186) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) ... 7 more Caused by: java.lang.NullPointerException at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:340) at net.winneonsword.WCClient.asm.WCClassTransformer.transform(WCClassTransformer.java:92) at net.winneonsword.WCClient.asm.WCClassTransformer.transform(WCClassTransformer.java:38) at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:274) at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:172) ... 9 more ClassTransformer: package net.winneonsword.WCClient.asm; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.LaunchClassLoader; public class WCClassTransformer implements IClassTransformer { private static ArrayList<PatchInfo> list = new ArrayList<PatchInfo>(); static { PatchInfo temp; temp = new PatchInfo("net.minecraft.client.gui.GuiMainMenu"); temp.methods.add(new MethodInfo("addSingleplayerMultiplayerButtons", "b", "(II)V", "(II)V")); list.add(temp); } @Override public byte[] transform(String x, String y, byte[] z){ byte[] bytes = z; PatchInfo patch = this.getPatchInfo(y); if (patch != null){ bytes = this.transform(patch, bytes); } return bytes; } private byte[] transform(PatchInfo patch, byte[] z){ boolean patched = false; byte[] bytes = z; ClassNode node = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(node, 0); System.out.println(String.format("Patching Class: %s", patch.target)); HashMap<MethodNode, MethodNode> replace = new HashMap(); for (MethodNode target : node.methods){ for (MethodInfo method : patch.methods){ if ((method.name.equals(method.name) || method.name.equals(method.mappedName)) && (method.desc.equals(method.desc) || method.desc.equals(method.mappedDesc))){ MethodNode replacement = this.getReplacementMethod(patch, method); replace.put(target, replacement); patched = true; } } } if (patched){ for (MethodNode method : replace.keySet()){ MethodNode replacement = replace.get(method); node.methods.remove(method); node.methods.add(replacement); } ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); node.accept(writer); bytes = writer.toByteArray(); } return bytes; } private PatchInfo getPatchInfo(String name){ for (PatchInfo patch : list){ if (patch.target.equals(name)){ return patch; } } return null; } private MethodNode getReplacementMethod(PatchInfo patch, MethodInfo method){ try { LaunchClassLoader loader = (LaunchClassLoader) this.getClass().getClassLoader(); ClassNode node = new ClassNode(); ClassReader reader = new ClassReader(loader.getClassBytes(patch.getReplacementClass())); reader.accept(node, 0); for (MethodNode m : node.methods){ if ((m.name.equals(method.name) || m.name.equals(method.mappedName)) && (m.desc.equals(method.desc) || m.desc.equals(method.mappedDesc))){ return m; } } } catch (IOException e){ e.printStackTrace(); } return null; } } PatchInfo: package net.winneonsword.WCClient.asm; import java.util.ArrayList; public class PatchInfo { public String target; public ArrayList<MethodInfo> methods = new ArrayList<MethodInfo>(); private static String path = "net.winneonsword.WCClient.asm.containers."; public PatchInfo(String target){ this.target = target; } public String getReplacementClass(){ String[] part = this.target.split("[.]"); String newPath = path + "ASM" + part[part.length - 1]; return newPath; } } MethodInfo: package net.winneonsword.WCClient.asm; public class MethodInfo { public String name; public String mappedName; public String desc; public String mappedDesc; public MethodInfo(String name, String mappedName, String desc, String mappedDesc){ this.name = name; this.mappedName = mappedName; this.desc = desc; this.mappedDesc = mappedDesc; } } The replacement method / class: package net.winneonsword.WCClient.asm.containers; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.resources.I18n; public class ASMGuiMainMenu extends GuiMainMenu { public void addSingleplayerMultiplayerButtons(int par1, int par2){ this.buttonList.add(new GuiButton(1, this.width / 2 - 100, par1, I18n.getString("menu.singleplayer"))); this.buttonList.add(new GuiButton(2, this.width / 2 - 100, par1 + par2 * 1, I18n.getString("menu.multiplayer"))); GuiButton fmlModButton = new GuiButton(6, this.width / 2 - 100, par1 + par2 * 2, "Mods"); this.buttonList.add(fmlModButton); GuiButton minecraftRealmsButton = new GuiButton(14, this.width / 2 - 100, par1 + par2 * 2, I18n.getString("menu.online")); minecraftRealmsButton.width = 98; minecraftRealmsButton.xPosition = this.width / 2 - 100; this.buttonList.add(minecraftRealmsButton); minecraftRealmsButton.drawButton = false; } }
  3. The reason blockSewageWater = new BlockSewageWater(155, "BlockSewageWater"); //Line 264 is returning an undefined error is because the constructor for BlockSewage water is only accepting an integer as a parameter, not a integer and a string as you have in that variable.
  4. I've done some things and almost have it done. But I'm getting an NPE I do not know how to fix. The info is in the first post.
  5. Could you give me an example of this?
  6. I've already experimented with ASM and the sort, and I can modify access values with ASM. I can also replace a class fairly easily. What I would like to know is to easily in 1.6.4 change a method / insert code into a vanilla method, specifically the main menu. Could anyone help me on the matter? EDIT: I have gotten most of it done. But now I'm getting a NullPointerException when trying to get the ClassNode to accept a ClassWriter. Here is the error: Caused by: java.lang.NullPointerException at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:340) at net.winneonsword.WCClient.asm.WCClassTransformer.transform(WCClassTransformer.java:119) at net.winneonsword.WCClient.asm.WCClassTransformer.transform(WCClassTransformer.java:64) at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:274) at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:172) ... 9 more And here is the transform method: @Override public byte[] transform(String x, String y, byte[] z){ byte[] bytes = z; PatchInfo patch = this.getPatchInfo(y); if (patch != null){ bytes = this.transform(patch, bytes); } return z; } private byte[] transform(PatchInfo patch, byte[] z){ boolean patched = false; byte[] bytes = z; ClassNode node = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(node, 0); WCLog.fine("Patching Class: %s", new Object[] { patch.target }); HashMap<MethodNode, MethodNode> replace = new HashMap(); for (MethodNode target : node.methods){ for (MethodInfo method : patch.methods){ if ((method.name.equals(method.name) || method.name.equals(method.mappedName)) && (method.desc.equals(method.desc) || method.desc.equals(method.mappedDesc))){ MethodNode replacement = this.getReplacementMethod(patch, method); replace.put(target, replacement); WCLog.fine("Successfully Patched: %s at %s", new Object[] { method.name, method.desc }); patched = true; } } } if (patched){ for (MethodNode method : replace.keySet()){ MethodNode replacement = replace.get(method); node.methods.remove(method); node.methods.add(replacement); } ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); node.accept(writer); bytes = writer.toByteArray(); } return bytes; } The error is coming from here: ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); node.accept(writer); bytes = writer.toByteArray(); Any ideas?
  7. I just tried if (p.getCurrentArmor(1) != null), but still NPE error.
  8. I did a if (p,.getCurrentArmor() == null) to see if that would fix it, but I got the same NPE error.
  9. Hello, I can't seem to call any ItemStack methods inside a RenderGameOverlayEvent. It always gives a NullPointerException and it points at the line where the ItemStack method is, but it doesn't exactly explain why. Could any of you guys help? Class: public class ArmourOverlay extends Gui{ private Minecraft mc = Minecraft.getMinecraft(); private EntityPlayer p = mc.thePlayer; public ArmourOverlay(Minecraft mc){ super(); this.mc = mc; } @ForgeSubscribe(priority = EventPriority.NORMAL) public void onArmourChange(RenderGameOverlayEvent e){ if (e.type == ElementType.ARMOR){ e.setCanceled(true); if (p.getCurrentArmor(1).itemID == 310){ System.out.println("test"); } } } } Error: java.lang.NullPointerException at ws.mods.wsessentials.overlay.ArmourOverlay.onArmourChange(ArmourOverlay.java:31) at net.minecraftforge.event.ASMEventHandler_5_ArmourOverlay_onArmourChange_RenderGameOverlayEvent.invoke(.dynamic) at net.minecraftforge.event.ASMEventHandler.invoke(ASMEventHandler.java:39) at net.minecraftforge.event.EventBus.post(EventBus.java:108) at net.minecraftforge.client.GuiIngameForge.pre(GuiIngameForge.java:861) at net.minecraftforge.client.GuiIngameForge.renderArmor(GuiIngameForge.java:259) at net.minecraftforge.client.GuiIngameForge.renderGameOverlay(GuiIngameForge.java:136) at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1014) at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:934) at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:826) at net.minecraft.client.main.Main.main(Main.java:93) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at net.minecraft.launchwrapper.Launch.launch(Launch.java:57) at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
  10. OH I get it now. You would set the event type to RenderGameOverlayEvent to .Health and the end, and then do event.setCancelled(true);. Sorry for the trouble, thanks.
  11. That was just an example. I have the variable set, but I can't find out how to cancel it.
  12. Ok so I found the type method, and I registered the variable as ElementType health = e.type.HEALTH;. Now, I'm looking through the methods and I can't find anything that says to cancel it, except for the original e.setCancelled(boolean). But thats a boolean, and I'm not sure if you can find the variable to e... I'm so confused. I'm sorry if I'm a hassle.
  13. How would I check to see which is which... I can't find out how to locate the health GUI and they translate that into a method I can disable.
  14. Hello, Without modifying base classes such as GuiIngame.java, I'm not sure how I would do this. For example, how would I remove the armour or health bars from displaying at all? In my mind, using something like RenderGameOverlayEvent or TickType.RENDER would overlay or add something to the screen, but I don't think using it to delete something would be possible without something maybe like event.setCancelled(true); like Bukkit does. Does anyone else know how I would do this?
  15. Hello, For some reason whenever I activate my HUD for my mod in survival and adventure mode, the text displays fine, but the HUD ( exp bar, health, hunger, etc. ) displays in glitched out white boxes. I'm not sure what's causing this, because I'm not using / editing any textures. I'm just drawing strings on the screen. Do you know what the issue is? ( There is no error in the console either, if you were wondering. ) package ws.mods.wsessentials.overlay; import java.awt.FontMetrics; import java.awt.Graphics; import org.lwjgl.input.Keyboard; import ws.mods.wsessentials.keybinds.HideHUD; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.EventPriority; import net.minecraftforge.event.ForgeSubscribe; public class PositionOverlay extends Gui{ private final Minecraft mc; public PositionOverlay(Minecraft mc){ super(); this.mc = mc; } @ForgeSubscribe(priority = EventPriority.NORMAL) public void onRenderPosition(RenderGameOverlayEvent e){ ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight); FontRenderer fontRender = mc.fontRenderer; int width = res.getScaledWidth(); int height = res.getScaledHeight(); EntityPlayer p = mc.getMinecraft().thePlayer; double xPos = p.posX; double yPos = p.posY - 1; double zPos = p.posZ; mc.entityRenderer.setupOverlayRendering(); String versionNumber = "Minecraft 1.6.2"; String x = "" + xPos; int xIndex = x.indexOf("."); if (xIndex != -1){ x = x.substring(0, xIndex); } String y = "" + yPos; int yIndex = y.indexOf("."); if (yIndex != -1){ y = y.substring(0, yIndex); } String z = "" + zPos; int zIndex = z.indexOf("."); if (zIndex != -1){ z = z.substring(0, zIndex); } String xPOS = "x " + x; String yPOS = "y " + y; String zPOS = "z " + z; String entities = mc.getEntityDebug().replace("E:", "e"); int entIndex = entities.indexOf("."); if (entIndex != -1){ entities = entities.substring(0, entIndex); } String fps = mc.debug; int fpsIndex = fps.indexOf(","); if (fpsIndex != -1){ fps = fps.substring(0, fpsIndex); } String f3Mode = "HUD disabled due to debug menu."; int xVN = 2; int xE = res.getScaledWidth() - fontRender.getStringWidth(fps) - 2; int xE2 = res.getScaledWidth() - fontRender.getStringWidth(entities) - 2; int xDis = res.getScaledWidth() - fontRender.getStringWidth(f3Mode) - 10; int yVN = 2; int yP1 = 12; int yP2 = 22; int yP3 = 32; int yP4 = 82; int colour = 0xFFFFFF; if (this.mc.gameSettings.showDebugInfo && HideHUD.hasOpenedGUI == false){ // Yay, empty line! Woo! *enthusiasm explosion* } else if (this.mc.gameSettings.showDebugInfo){ fontRender.drawStringWithShadow(f3Mode, xDis, yP4, colour); } else if(HideHUD.hasOpenedGUI == false){ // Empty lines are for re re's. Oh wait... } else { fontRender.drawStringWithShadow(versionNumber, xVN, yVN, colour); fontRender.drawStringWithShadow(xPOS, xVN, yP1, colour); fontRender.drawStringWithShadow(yPOS, xVN, yP2, colour); fontRender.drawStringWithShadow(zPOS, xVN, yP3, colour); fontRender.drawStringWithShadow(fps, xE, yVN, colour); fontRender.drawStringWithShadow(entities, xE2, yP1, colour); } } }
  16. Wow, I don't know why I didn't think of that before. Thank you very much! The GUI is just a simple GUI that extends Gui, but this seems to work brilliantly for it. Thank you.
  17. Hello, I am trying to make a simple Keybind toggle that toggles a HUD gui. But I cannot seem to figure out how to make the keyUp and keyDown methods toggle. All the GUI is doing is running a loop checking to see if keyPressed is true. If keyPressed is true then it doesnt show it. But I want it to toggle, so I don't want to press it and then release it and the GUI toggle on and then off. I want it to be like the F3 menu ( on how it toggles ). Could any of you experienced folk help me a little? package ws.mods.wsessentials; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.EnumSet; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; import net.minecraftforge.common.Configuration; import cpw.mods.fml.client.registry.KeyBindingRegistry.KeyHandler; import cpw.mods.fml.common.TickType; public class KeyBindings extends KeyHandler { public wsEssentials ws; private EnumSet tickTypes = EnumSet.of(TickType.CLIENT); public static boolean keyPressed = false; public static boolean keyReleased = true; public KeyBindings(KeyBinding[] keyBindings, boolean[] repeatings){ super(keyBindings, repeatings); } @Override public String getLabel(){ return "F"; } @Override public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat){ if (keyPressed == false){ keyPressed = true; } else { keyPressed = false; } keyReleased = false; } @Override public void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd){ if (keyPressed == true){ keyReleased = true; } else { keyReleased = true; } } @Override public EnumSet<TickType> ticks(){ return tickTypes; } }
×
×
  • Create New...

Important Information

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