1

我的目标是以编程方式为一个名为 Minecraft 的游戏编译 java 代码。我正在开发一种修改,允许用户编写 java 文件并编译它们,以便它们可以安装到游戏中(游戏是用 Java 制作的),我使用 JavaCompiler 类并且它工作正常,问题是当游戏被反编译,所有目录和所有内容的名称都发生了变化,但使用 JavaCompiler 并没有像预期的那样。如果有一种方法可以编译java文件,然后用一段代码编辑类,这些代码将用其他设置的字符串替换设置的字符串,我一直在徘徊,我试图在java文件中更改它然后编译,只有编译不起作用,因为导入和类名无效。这是我当前的代码:

package com.marko5049.TechRev.GUI;

import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;
import java.util.Scanner;

import javax.swing.JTextArea;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;

import com.marko5049.TechRev.TileEntityComputer;

import cpw.mods.fml.common.FMLCommonHandler;

public class GuiProgramIDE extends GuiScreenMod
{
    private World world;
    private EntityPlayer entityplayer;
    private Minecraft mc;
    private final TileEntityComputer tile;
    private GuiTextField txtBox;
    private GuiTextField txtName;

    public GuiProgramIDE(World world1, EntityPlayer entityplayer1, Minecraft minecraft, TileEntityComputer compTile)
    {
        world = world1;
        entityplayer = entityplayer1;
        mc = minecraft;
        tile = compTile;
    }

    public void updateScreen()
    {
        this.txtBox.updateCursorCounter();
        this.txtName.updateCursorCounter();
    }

    public void initGui()
    {
        Keyboard.enableRepeatEvents(true);
        buttonList.clear();
        this.txtBox = new GuiTextField(this.fontRenderer, this.width / 2 - 150, 80, 300, 40);
        this.txtBox.setMaxStringLength(999999999);
        this.txtBox.setFocused(true);
        this.txtBox.setText("Text goes here!");
        this.txtName = new GuiTextField(this.fontRenderer, this.width / 2 - 100, 40, 200, 20);
        this.txtName.setMaxStringLength(32);
        this.txtName.setFocused(false);
        this.txtName.setText("Title goes here!");
        buttonList.add(new GuiButton(1, width / 2 - 105, height / 2 + 40, 100, 20, "Save"));
        buttonList.add(new GuiButton(2, width / 2 + 5, height / 2 + 40, 100, 20, "Open"));
        buttonList.add(new GuiButton(3, width / 2 - 105, height / 2 + 60, 210, 20, "Compile"));
    }

    public void onGuiClosed()
    {
        Keyboard.enableRepeatEvents(false);
    }

    protected void actionRPerformed(GuiButton guibutton)
    {

    }

    protected void actionPerformed(GuiButton guibutton)
    {
        if(guibutton.id == 1) {
            BufferedWriter write;
            String text = txtBox.getText();
            String title = txtName.getText();
            String name = txtName.getText() + ".java";
            String path = Minecraft.getMinecraft().mcDataDir.getParent().toString() + "/saves/" + world.getWorldInfo().getWorldName().toString() + "/TechRev/Compiler/";
            File destFolder = new File(path);
            if (!destFolder.exists())
            {
                destFolder.mkdir();
                if(!path.endsWith(name)) path += name;
                try {
                    write = new BufferedWriter(new FileWriter(path));
                    write.write(text);
                    write.close();
                    txtBox.setText(text);
                    txtName.setText(title);
                } catch(Exception e) {}
            } else {
                if(!path.endsWith(name)) path += name;
                try {
                    write = new BufferedWriter(new FileWriter(path));
                    write.write(text);
                    write.close();
                    txtBox.setText(text);
                    txtName.setText(title);
                } catch(Exception e) {}
            }
        }
        if(guibutton.id == 2) {
            String title = txtName.getText();
            String name = title + ".java";
            String path = Minecraft.getMinecraft().mcDataDir.getParent().toString() + "/saves/" + world.getWorldInfo().getWorldName().toString() + "/TechRev/Compiler/";
            File file = new File(path + name);
            if(file.canRead()) {
                String FileTxt = "";
                if((path + name).endsWith(".java")) {
                    try {
                        Scanner read = new Scanner(new FileInputStream(file));
                        while (read.hasNextLine()) {
                            FileTxt += read.nextLine();
                        }
                        read.close();
                    } catch(FileNotFoundException e) {}
                    txtBox.setText(FileTxt);
                    txtName.setText(title);
                }

            } else {
                System.out.print("Cannot Open File!");
            }
        }
        if(guibutton.id == 3) {
            String title = txtName.getText();
            String name = title + ".java";
            String src = Minecraft.getMinecraft().mcDataDir.getParent().toString() + "/saves/" + world.getWorldInfo().getWorldName().toString() + "/TechRev/Compiler/";
            File java = new File(src + name);
            File srcFolder = new File(src);
            if (!srcFolder.exists()) {
                srcFolder.mkdir();
                compile(src + name);
            } else {
                compile(src + name);
            }
        }
    }

    public void compile(String file) {
        String fileToCompile = file;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int compilationResult = compiler.run(null, null, null, fileToCompile);
        if (compilationResult == 0) {
            System.out.println("Compilation is successful");
            entityplayer.addChatMessage("Compilation is successful");
        } else {
            System.out.println("Compilation failed");
            entityplayer.addChatMessage("Compilation failed");
        }
    }

    public boolean doesGuiPauseGame()
    {
            return true;
    }

    protected void keyTyped(char par1, int par2)
    {
        super.keyTyped(par1, par2);
        this.txtBox.textboxKeyTyped(par1, par2);
        this.txtName.textboxKeyTyped(par1, par2);
    }

    protected void mouseClicked(int par1, int par2, int par3)
    {
        super.mouseClicked(par1, par2, par3);
        this.txtName.mouseClicked(par1, par2, par3);
        this.txtBox.mouseClicked(par1, par2, par3);
    }

    public void drawScreen(int i, int j, float f)
    {
            drawDefaultBackground();
            int x = width / 3 - 128;
            int y = height / 3 - 128;
            try{
                    GL11.glPushMatrix();
                    GL11.glScalef(1.5F, 1.5F, 1.5F);
                    GL11.glColor4f(2.0F, 2.0F, 2.0F, 2.0F);
                    mc.renderEngine.bindTexture(new ResourceLocation("TechRev:App.png"));
                    drawTexturedModalRect(x, y, 0, 0, 256, 256);
                    GL11.glPopMatrix();
            }
            finally{
            }
            this.txtBox.drawTextBox();
            this.txtName.drawTextBox();
            super.drawScreen(i, j, f);
    }
}

如您所见,这是一个带有用于编辑的文本框的 GUI,它将文本保存在目录中并保存为 .java 文件。这是我用这个 GUI 编写的测试 java 文件:

import cpw.mods.fml.common.Mod; import net.minecraft.src.ModLoader; import net.minecraft.item.Item; 
@Mod(modid = "TechRev", name = "Technological Revolution", version = "V0.1") 
public class TechRev { 
public static Item ChickenLegs = new Item(3000).setUnlocalizedName("chicken"); 
public TechRev() { init(); } 
public void init(){ ModLoader.addName(ChickenLegs, "Chicken Drumsticks");}}

正如我所说,JavaCompiler 做了它应该做的事情,只有我需要它来重命名编译器生成的类文件中的目录和类名。

4

1 回答 1

0

听起来您需要做一些类似于 immibis 在 Bearded-Octo-Nemesis 工具中所做的事情。BON 允许您使用用于反编译 Minecraft 的 MCP 目录中的配置对 Minecraft mod 档案进行去混淆处理。输入是一个生产模式存档(它引用了混淆的 Minecraft 类/方法/字段名称)和 MCP 目录的路径。输出是一个 mod 存档,应该可以在去混淆的环境中使用,例如 MCP Eclipse 工作区(您可以将去混淆的 mod 存档放在 mcp/jars/mods 文件夹中)。

这是 BON 源代码的链接;immibis 使用相当宽松的许可证,因此您可以调整他的代码以使用作为 Forge 一部分的运行时反混淆数据。 https://github.com/immibis/bearded-octo-nemesis

于 2013-10-03T17:13:29.310 回答