我的目标是以编程方式为一个名为 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 做了它应该做的事情,只有我需要它来重命名编译器生成的类文件中的目录和类名。