使用JavaCompiler编译Minecraft
我的目标是以编程方式为名为Minecraft的游戏编译java代码。我正在开发一个修改,允许用户编写java文件并进行编译,以便安装到游戏中(游戏是用java制作的),我使用JavaCompiler类,它工作正常,问题是当游戏被反编译时,所有目录和名称都会发生变化,但对于JavaCompiler,它并不像预期的那样。我想知道是否有一种方法可以编译java文件,然后用一段代码来编辑类,用其他同样设置的字符串替换设置字符串,我尝试在java文件中更改它,然后进行编译,但编译不起作用,因为导入和类名无效。这是我目前的代码:使用JavaCompiler编译Minecraft,java,string,compilation,rename,minecraft,Java,String,Compilation,Rename,Minecraft,我的目标是以编程方式为名为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做了它应该做的,只是我需要它来重命名编译器生成的类文件中的目录和类名。听起来你需要做一些类似于immibis在Beard Octo Nemesis工具中所做的事情。BON允许您使用用于反编译Minecraft的MCP目录中的配置来消除Minecraft mod归档文件的混淆。输入是一个production mod archive(参考模糊的Minecraft类/方法/字段名)和MCP目录的路径。输出是一个mod归档,应该可以在一个deobfouscated环境中使用,比如MCP Eclipse工作区(您可以将deobfouscated mod归档放在MCP/jars/mods文件夹中) 这里是一个链接到苯教的源代码;immibis使用一个相当许可的许可证,因此您可以修改他的代码,以使用Forge中的运行时deobfousation数据。