Компиляция Minecraft с помощью JavaCompiler

Моя цель — программно скомпилировать Java-код для игры под названием Minecraft. Я разрабатываю модификацию, которая позволяет пользователю писать 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);
    }
}

Как видите, это графический интерфейс с текстовым полем для редактирования, он сохраняет текст в каталоге и в виде файлов .java. Вот мой тестовый 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 делает то, что должен, только мне нужно, чтобы он переименовывал каталоги и имена классов в файле класса, созданном компилятором.


person Community    schedule 03.10.2013    source источник


Ответы (1)


Похоже, вам нужно сделать что-то похожее на то, что делается в инструменте Bearded-Octo-Nemesis от immibis. BON позволяет деобфусцировать архивы модов Minecraft, используя конфигурацию из каталога MCP, который использовался для декомпиляции Minecraft. Ввод представляет собой архив производственного мода (который ссылается на запутанные имена классов/методов/полей Minecraft) и путь к вашему каталогу MCP. На выходе получается архив модов, который можно использовать в деобфусцированной среде, такой как рабочее пространство MCP Eclipse (вы должны поместить деобфусцированный архив модов в папку mcp/jars/mods).

Вот ссылка на исходный код BON; immibis использует довольно разрешительную лицензию, поэтому вы можете адаптировать его код для использования данных деобфускации во время выполнения, которые являются частью Forge. https://github.com/immibis/bearded-octo-nemesis

person bspkrs    schedule 03.10.2013