SubServers-2/SubServers.Host/src/net/ME1312/SubServers/Host/Executable/SubCreator.java

319 lines
15 KiB
Java
Raw Normal View History

package net.ME1312.SubServers.Host.Executable;
import net.ME1312.SubServers.Host.Library.Config.YAMLConfig;
import net.ME1312.SubServers.Host.Library.Config.YAMLSection;
import net.ME1312.SubServers.Host.Library.Container;
import net.ME1312.SubServers.Host.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Host.Library.UniversalFile;
import net.ME1312.SubServers.Host.Library.Util;
import net.ME1312.SubServers.Host.Library.Version.Version;
import net.ME1312.SubServers.Host.Network.Packet.PacketDownloadBuildScript;
import net.ME1312.SubServers.Host.Network.Packet.PacketExCreateServer;
import net.ME1312.SubServers.Host.Network.Packet.PacketOutExLogMessage;
import net.ME1312.SubServers.Host.SubServers;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.UUID;
/**
* Internal SubCreator Class
*/
public class SubCreator {
private SubServers host;
private SubLogger logger;
private Process process = null;
private Thread thread = null;
public enum ServerType {
SPIGOT,
VANILLA,
SPONGE,;
@Override
public String toString() {
return super.toString().substring(0, 1).toUpperCase()+super.toString().substring(1).toLowerCase();
}
}
/**
* Creates a SubCreator Instance
*
* @param host SubServers.Host
*/
public SubCreator(SubServers host) {
if (Util.isNull(host)) throw new NullPointerException();
this.host = host;
2017-04-01 22:31:57 +02:00
this.logger = new SubLogger(null, this, "SubCreator", null, new Container<Boolean>(false), null);
}
private void run(String name, ServerType type, Version version, int memory, int port, UUID address, String id) {
Executable executable = null;
UniversalFile dir = new UniversalFile(new File(host.host.getRawString("Directory")), name);
dir.mkdirs();
2017-04-01 22:31:57 +02:00
logger.logger.info.println("Generating Server Files...");
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Generating Server Files..."));
if (type == ServerType.SPIGOT) {
executable = new Executable("java -Xmx" + memory + "M -Djline.terminal=jline.UnsupportedTerminal -Dcom.mojang.eula.agree=true -jar Spigot.jar");
try {
copyFolder(new UniversalFile(host.dir, "Templates:Spigot"), dir);
generateProperties(dir, port);
generateClient(dir, name, type);
} catch (Exception e) {
2017-04-03 19:52:28 +02:00
logger.logger.error.println(e);
}
} else if (type == ServerType.VANILLA) {
executable = new Executable("java -Xmx" + memory + "M -jar Vanilla.jar nogui");
try {
copyFolder(new UniversalFile(host.dir, "Templates:Vanilla"), dir);
generateEULA(dir);
generateProperties(dir, port);
} catch (IOException e) {
2017-04-03 19:52:28 +02:00
logger.logger.error.println(e);
}
} else if (type == ServerType.SPONGE) {
try {
executable = new Executable("java -Xmx" + memory + "M -jar Forge.jar");
copyFolder(new UniversalFile(host.dir, "" +
"Templates:Sponge"), dir);
generateEULA(dir);
generateProperties(dir, port);
generateClient(dir, name, type);
2017-04-01 22:31:57 +02:00
logger.logger.info.println("Searching Versions...");
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Searching Versions..."));
Document spongexml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(Util.readAll(new BufferedReader(new InputStreamReader(new URL("http://files.minecraftforge.net/maven/org/spongepowered/spongeforge/maven-metadata.xml").openStream(), Charset.forName("UTF-8")))))));
Document forgexml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(Util.readAll(new BufferedReader(new InputStreamReader(new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/maven-metadata.xml").openStream(), Charset.forName("UTF-8")))))));
NodeList spnodeList = spongexml.getElementsByTagName("version");
Version spversion = null;
for (int i = 0; i < spnodeList.getLength(); i++) {
Node node = spnodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.getTextContent().startsWith(version.toString() + '-') && (spversion == null || new Version(node.getTextContent()).compareTo(spversion) >= 0)) {
spversion = new Version(node.getTextContent());
}
}
}
if (spversion == null) throw new InvalidServerException("Cannot find sponge version for Minecraft " + version.toString());
2017-04-01 22:31:57 +02:00
logger.logger.info.println("Found \"spongeforge-" + spversion.toString() + '"');
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Found \"spongeforge-" + spversion.toString() + '"'));
NodeList mcfnodeList = forgexml.getElementsByTagName("version");
Version mcfversion = null;
for (int i = 0; i < mcfnodeList.getLength(); i++) {
Node node = mcfnodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.getTextContent().contains(spversion.toString().split("\\-")[1]) && (mcfversion == null || new Version(node.getTextContent()).compareTo(mcfversion) >= 0)) {
mcfversion = new Version(node.getTextContent());
}
}
}
if (mcfversion == null) throw new InvalidServerException("Cannot find forge version for Sponge " + spversion.toString());
2017-04-01 22:31:57 +02:00
logger.logger.info.println("Found \"forge-" + mcfversion.toString() + '"');
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Found \"forge-" + mcfversion.toString() + '"'));
version = new Version(mcfversion.toString() + "::" + spversion.toString());
} catch (ParserConfigurationException | IOException | SAXException | NullPointerException e) {
2017-04-03 19:52:28 +02:00
logger.logger.error.println(e);
}
}
Version ver = version;
Executable exec = executable;
host.subdata.sendPacket(new PacketDownloadBuildScript(json -> {
(thread = new Thread(() -> {
try {
PrintWriter writer = new PrintWriter(new UniversalFile(dir, "build.sh"), "UTF-8");
Iterator<Object> i = json.getJSONArray("script").iterator();
while (i.hasNext()) {
String line = (String) i.next();
writer.println(line);
}
writer.close();
if (!(new File(dir, "build.sh").exists())) {
logger.logger.info.println("Problem copying build.sh");
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Problem copying build.sh"));
} else {
File gitBash = new File(host.host.getRawString("Git-Bash"), "bin" + File.separatorChar + "bash.exe");
if (!(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)) {
Process process = Runtime.getRuntime().exec("chmod +x build.sh", null, dir);
try {
process.waitFor();
Thread.sleep(500);
} catch (InterruptedException e) {
logger.logger.error.println(e);
}
if (process.exitValue() != 0) {
logger.logger.info.println("Problem Setting Executable Permissions.");
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Problem Setting Executable Permissions."));
}
}
logger.logger.info.println("Launching build.sh");
host.subdata.sendPacket(new PacketOutExLogMessage(address, "Launching build.sh"));
this.process = Runtime.getRuntime().exec((System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) ?
"\"" + gitBash + "\" --login -i -c \"bash build.sh " + ver.toString() + " " + type.toString().toLowerCase() + "\""
: ("bash build.sh " + ver.toString() + " " + type.toString().toLowerCase() + " " + System.getProperty("user.home")), null, dir);
logger.process = this.process;
logger.log.set(true);
logger.address = address;
logger.file = new File(dir, "SubCreator-" + type.toString() + "-" + ver.toString().replace("::", "@") + ".log");
logger.start();
try {
this.process.waitFor();
Thread.sleep(500);
} catch (InterruptedException e) {
2017-04-03 19:52:28 +02:00
logger.logger.error.println(e);
}
JSONObject info = new JSONObject();
info.put("dir", "." + File.separatorChar + name);
info.put("exec", exec.toString());
host.subdata.sendPacket(new PacketExCreateServer(process.exitValue(), (this.process.exitValue() == 0) ? "Created Server Successfully" : ("Couldn't build the server jar. See \"SubCreator-" + type.toString() + "-" + ver.toString().replace("::", "@") + ".log\" for more details."), info, id));
if (this.process.exitValue() != 0) {
logger.logger.info.println("Couldn't build the server jar. See \"SubCreator-" + type.toString() + "-" + ver.toString().replace("::", "@") + ".log\" for more details.");
}
}
} catch (IOException e) {
host.log.error.println(e);
host.subdata.sendPacket(new PacketExCreateServer(-1, "An Exception occurred while running SubCreator. See the " + host.subdata.getName() + " console for more details.", null, id));
}
})).start();
}));
}
public boolean create(String name, ServerType type, Version version, int memory, int port, UUID address, String id) {
if (Util.isNull(name, type, version, memory, port, address)) throw new NullPointerException();
if (!isBusy()) {
(thread = new Thread(() -> {
SubCreator.this.run(name, type, version, memory, port, address, id);
})).start();
return true;
} else return false;
}
public void terminate() {
if (process != null && this.process.isAlive()) {
process.destroyForcibly();
} else if (thread != null && this.thread.isAlive()) {
thread.interrupt();
}
}
public void waitFor() throws InterruptedException {
while (thread != null && thread.isAlive()) {
Thread.sleep(250);
}
}
public SubLogger getLogger() {
return logger;
}
public boolean isBusy() {
return thread != null && thread.isAlive();
}
private void generateClient(File dir, String name, ServerType type) throws IOException {
if (type == ServerType.SPIGOT) {
new UniversalFile(dir, "plugins:SubServers-Client-Bukkit").mkdirs();
Util.copyFromJar(SubServers.class.getClassLoader(), "net/ME1312/SubServers/Host/Library/Files/bukkit.jar", new UniversalFile(dir, "plugins:SubServers.Client.jar").getPath());
YAMLConfig config = new YAMLConfig(new UniversalFile(dir, "plugins:Subservers-Client-Bukkit:config.yml"));
YAMLSection settings = new YAMLSection();
settings.set("Version", "2.11.2a+");
settings.set("Ingame-Access", true);
settings.set("Use-Title-Messages", true);
YAMLSection subdata = new YAMLSection();
subdata.set("Name", name);
subdata.set("Address", host.config.get().getSection("Settings").getSection("SubData").getRawString("Address"));
subdata.set("Password", host.config.get().getSection("Settings").getSection("SubData").getRawString("Password"));
settings.set("SubData", subdata);
config.get().set("Settings", settings);
config.save();
} else if (type == ServerType.SPONGE) {
// TODO
}
}
private void generateEULA(File dir) throws FileNotFoundException, UnsupportedEncodingException {
PrintWriter writer = new PrintWriter(new File(dir, "eula.txt"), "UTF-8");
writer.println("#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).");
writer.println("#" + new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy").format(Calendar.getInstance().getTime()));
writer.println("eula=true");
writer.close();
}
private void generateProperties(File dir, int port) throws IOException {
File file = new File(dir, "server.properties");
String content = Util.readAll(new BufferedReader(new InputStreamReader(new FileInputStream(file)))).replace("server-port=", "server-port=" + port).replace("server-ip=", "server-ip=" + host.config.get().getSection("Settings").getRawString("Server-Bind"));
file.delete();
PrintWriter writer = new PrintWriter(file, "UTF-8");
writer.write(content);
writer.close();
}
private void copyFolder(File source, File destination) {
if (source.isDirectory()) {
if (!destination.exists()) {
destination.mkdirs();
}
String files[] = source.list();
for (String file : files) {
File srcFile = new File(source, file);
File destFile = new File(destination, file);
copyFolder(srcFile, destFile);
}
} else {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(source);
out = new FileOutputStream(destination);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} catch (Exception e) {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}