2017-04-01 07:37:48 +02:00
package net.ME1312.SubServers.Host.Executable ;
import net.ME1312.SubServers.Host.Library.Config.YAMLSection ;
import net.ME1312.SubServers.Host.Library.Container ;
import net.ME1312.SubServers.Host.Library.Exception.InvalidServerException ;
2017-05-30 21:38:51 +02:00
import net.ME1312.SubServers.Host.Library.Exception.InvalidTemplateException ;
2017-04-01 07:37:48 +02:00
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.PacketExCreateServer ;
import net.ME1312.SubServers.Host.Network.Packet.PacketOutExLogMessage ;
2017-04-16 19:02:14 +02:00
import net.ME1312.SubServers.Host.ExHost ;
2017-04-01 07:37:48 +02:00
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 javax.xml.parsers.DocumentBuilderFactory ;
import java.io.* ;
import java.net.URL ;
import java.nio.charset.Charset ;
import java.util.UUID ;
/ * *
* Internal SubCreator Class
* /
public class SubCreator {
2017-04-16 19:02:14 +02:00
private ExHost host ;
2017-04-01 07:37:48 +02:00
private SubLogger logger ;
private Process process = null ;
private Thread thread = null ;
2017-05-30 21:38:51 +02:00
public static class ServerTemplate {
private String name ;
private String nick = null ;
private boolean enabled ;
private String icon ;
private File directory ;
private ServerType type ;
private YAMLSection build ;
private YAMLSection options ;
/ * *
* Create a SubCreator Template
*
* @param name Template Name
* @param directory Template Directory
* @param build Build Options
* @param options Configuration Options
* /
public ServerTemplate ( String name , boolean enabled , String icon , File directory , YAMLSection build , YAMLSection options ) {
if ( Util . isNull ( name , enabled , directory , build , options ) ) throw new NullPointerException ( ) ;
if ( name . contains ( " " ) ) throw new InvalidTemplateException ( " Template names cannot have spaces: " + name ) ;
this . name = name ;
this . enabled = enabled ;
this . icon = icon ;
this . directory = directory ;
this . type = ( build . contains ( " Server-Type " ) ) ? ServerType . valueOf ( build . getRawString ( " Server-Type " ) . toUpperCase ( ) ) : ServerType . CUSTOM ;
this . build = build ;
this . options = options ;
}
/ * *
* Get the Name of this Template
*
* @return Template Name
* /
public String getName ( ) {
return name ;
}
/ * *
* Get the Display Name of this Template
*
* @return Display Name
* /
public String getDisplayName ( ) {
return ( nick = = null ) ? getName ( ) : nick ;
}
/ * *
* Sets the Display Name for this Template
*
* @param value Value ( or null to reset )
* /
public void setDisplayName ( String value ) {
if ( value = = null | | value . length ( ) = = 0 | | getName ( ) . equals ( value ) ) {
this . nick = null ;
} else {
this . nick = value ;
}
}
/ * *
* Get the Enabled Status of this Template
*
* @return Enabled Status
* /
public boolean isEnabled ( ) {
return enabled ;
}
/ * *
* Set the Enabled Status of this Template
*
* @param value Value
* /
public void setEnabled ( boolean value ) {
enabled = value ;
}
/ * *
* Get the Item Icon for this Template
*
* @return Item Icon Name / ID
* /
public String getIcon ( ) {
return icon ;
}
/ * *
* Set the Item Icon for this Template
*
* @param value Value
* /
public void setIcon ( String value ) {
icon = value ;
}
/ * *
* Get the Directory for this Template
*
* @return Directory
* /
public File getDirectory ( ) {
return directory ;
}
/ * *
* Get the Type of this Template
*
* @return Template Type
* /
public ServerType getType ( ) {
return type ;
}
/ * *
* Get the Build Options for this Template
*
* @return Build Options
* /
public YAMLSection getBuildOptions ( ) {
return build ;
}
/ * *
* Get the Configuration Options for this Template
*
* @return Configuration Options
* /
public YAMLSection getConfigOptions ( ) {
return options ;
}
}
2017-04-01 07:37:48 +02:00
public enum ServerType {
SPIGOT ,
VANILLA ,
2017-05-30 21:38:51 +02:00
SPONGE ,
CUSTOM ;
2017-04-01 07:37:48 +02:00
@Override
public String toString ( ) {
return super . toString ( ) . substring ( 0 , 1 ) . toUpperCase ( ) + super . toString ( ) . substring ( 1 ) . toLowerCase ( ) ;
}
}
/ * *
* Creates a SubCreator Instance
*
* @param host SubServers . Host
* /
2017-04-16 19:02:14 +02:00
public SubCreator ( ExHost host ) {
2017-04-01 07:37:48 +02:00
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 ) ;
2017-04-01 07:37:48 +02:00
}
2017-05-30 21:38:51 +02:00
private void run ( String name , ServerTemplate template , Version version , int port , UUID address , String id ) {
2017-04-01 07:37:48 +02:00
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... " ) ;
2017-04-01 07:37:48 +02:00
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " Generating Server Files... " ) ) ;
2017-05-30 21:38:51 +02:00
try {
Util . copyDirectory ( template . getDirectory ( ) , dir ) ;
generateProperties ( dir , port ) ;
generateClient ( dir , template . getType ( ) , name ) ;
2017-04-01 07:37:48 +02:00
2017-05-30 21:38:51 +02:00
if ( template . getType ( ) = = ServerType . SPONGE ) {
2017-04-01 22:31:57 +02:00
logger . logger . info . println ( " Searching Versions... " ) ;
2017-04-01 07:37:48 +02:00
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 ( ) ) ;
}
}
}
2017-05-30 21:38:51 +02:00
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 ( ) + '"' ) ;
2017-04-01 07:37:48 +02:00
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 ( ) ) ;
}
}
}
2017-05-30 21:38:51 +02:00
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 ( ) + '"' ) ;
2017-04-01 07:37:48 +02:00
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " Found \" forge- " + mcfversion . toString ( ) + '"' ) ) ;
2017-05-30 21:38:51 +02:00
version = new Version ( mcfversion . toString ( ) + " " + spversion . toString ( ) ) ;
2017-04-01 07:37:48 +02:00
}
2017-05-30 21:38:51 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2017-04-01 07:37:48 +02:00
}
2017-05-30 21:38:51 +02:00
boolean error = false ;
2017-07-19 01:28:59 +02:00
if ( template . getBuildOptions ( ) . contains ( " Shell-Location " ) ) {
2017-05-30 21:38:51 +02:00
File gitBash = new File ( host . host . getRawString ( " Git-Bash " ) , " bin " + File . separatorChar + " bash.exe " ) ;
if ( ! ( System . getProperty ( " os.name " ) . toLowerCase ( ) . indexOf ( " win " ) > = 0 ) & & template . getBuildOptions ( ) . contains ( " Permission " ) ) {
2017-04-14 04:39:51 +02:00
try {
2017-05-30 21:38:51 +02:00
Process process = Runtime . getRuntime ( ) . exec ( " chmod " + template . getBuildOptions ( ) . getRawString ( " Permission " ) + ' ' + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) , null , dir ) ;
Thread . sleep ( 500 ) ;
if ( process . exitValue ( ) ! = 0 ) {
logger . logger . info . println ( " Couldn't set " + template . getBuildOptions ( ) . getRawString ( " Permission " ) + " permissions to " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ;
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " Couldn't set " + template . getBuildOptions ( ) . getRawString ( " Permission " ) + " permissions to " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ) ;
2017-04-14 04:39:51 +02:00
}
2017-05-30 21:38:51 +02:00
} catch ( Exception e ) {
logger . logger . info . println ( " Couldn't set " + template . getBuildOptions ( ) . getRawString ( " Permission " ) + " permissions to " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ;
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " Couldn't set " + template . getBuildOptions ( ) . getRawString ( " Permission " ) + " permissions to " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ) ;
e . printStackTrace ( ) ;
}
}
2017-04-01 07:37:48 +02:00
2017-05-30 21:38:51 +02:00
try {
logger . logger . info . println ( " /Creator > Launching " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ;
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " /Creator > Launching " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) ) ) ;
process = Runtime . getRuntime ( ) . exec ( ( System . getProperty ( " os.name " ) . toLowerCase ( ) . indexOf ( " win " ) > = 0 ) ? " \" " + gitBash + " \" --login -i -c \" bash " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) + ' ' + version . toString ( ) + '\"' : ( " bash " + template . getBuildOptions ( ) . getRawString ( " Shell-Location " ) + ' ' + version . toString ( ) + " " + System . getProperty ( " user.home " ) ) , null , dir ) ;
logger . process = this . process ;
logger . log . set ( true ) ;
logger . address = address ;
logger . file = new File ( dir , " SubCreator- " + template . getType ( ) . toString ( ) + " - " + version . toString ( ) . replace ( " " , " @ " ) + " .log " ) ;
logger . start ( ) ;
2017-04-01 07:37:48 +02:00
2017-05-30 21:38:51 +02:00
process . waitFor ( ) ;
Thread . sleep ( 500 ) ;
if ( process . exitValue ( ) ! = 0 ) error = true ;
} catch ( Exception e ) {
error = true ;
e . printStackTrace ( ) ;
}
}
new UniversalFile ( dir , " template.yml " ) . delete ( ) ;
if ( ! error ) {
2017-07-19 01:28:59 +02:00
host . subdata . sendPacket ( new PacketExCreateServer ( 0 , " Created Server Successfully " , template . getConfigOptions ( ) . toJSON ( ) , id ) ) ;
2017-05-30 21:38:51 +02:00
} else {
logger . logger . info . println ( " Couldn't build the server jar. See \" SubCreator- " + template . getType ( ) . toString ( ) + " - " + version . toString ( ) . replace ( " " , " @ " ) + " .log \" for more details. " ) ;
host . subdata . sendPacket ( new PacketOutExLogMessage ( address , " Couldn't build the server jar. See \" SubCreator- " + template . getType ( ) . toString ( ) + " - " + version . toString ( ) . replace ( " " , " @ " ) + " .log \" for more details. " ) ) ;
}
2017-04-01 07:37:48 +02:00
}
2017-05-30 21:38:51 +02:00
public boolean create ( String name , ServerTemplate template , Version version , int port , UUID address , String id ) {
if ( Util . isNull ( name , template , version , port , address ) ) throw new NullPointerException ( ) ;
2017-04-01 07:37:48 +02:00
if ( ! isBusy ( ) ) {
( thread = new Thread ( ( ) - > {
2017-05-30 21:38:51 +02:00
SubCreator . this . run ( name , template , version , port , address , id ) ;
2017-04-01 07:37:48 +02:00
} ) ) . 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 ( ) ;
}
2017-05-30 21:38:51 +02:00
private void generateClient ( File dir , ServerType type , String name ) throws IOException {
if ( new UniversalFile ( dir , " subservers.client " ) . exists ( ) ) {
if ( type = = ServerType . SPIGOT ) {
if ( ! new UniversalFile ( dir , " plugins " ) . exists ( ) ) new UniversalFile ( dir , " plugins " ) . mkdirs ( ) ;
Util . copyFromJar ( ExHost . class . getClassLoader ( ) , " net/ME1312/SubServers/Host/Library/Files/Client/spigot.jar " , new UniversalFile ( dir , " plugins:SubServers.Client.jar " ) . getPath ( ) ) ;
} else if ( type = = ServerType . SPONGE ) {
// TODO
2017-07-19 01:28:59 +02:00
// if (!new UniversalFile(dir, "mods").exists()) new UniversalFile(dir, "mods").mkdirs();
2017-05-30 21:38:51 +02:00
// Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Host/Library/Files/Client/sponge.jar", new UniversalFile(dir, "mods:SubServers.Client.jar").getPath());
}
2017-06-30 15:36:16 +02:00
JSONObject config = new JSONObject ( ) ;
2017-05-30 21:38:51 +02:00
FileWriter writer = new FileWriter ( new UniversalFile ( dir , " subservers.client " ) , false ) ;
config . put ( " Name " , name ) ;
config . put ( " Address " , host . config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getRawString ( " Address " ) ) ;
config . put ( " Password " , host . config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getRawString ( " Password " ) ) ;
2017-06-30 15:36:16 +02:00
config . put ( " Encryption " , host . config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getRawString ( " Encryption " , " NONE " ) ) ;
2017-05-30 21:38:51 +02:00
config . write ( writer ) ;
writer . close ( ) ;
2017-04-01 07:37:48 +02:00
}
}
2017-04-14 04:39:51 +02:00
private void generateProperties ( File dir , int port ) throws IOException {
File file = new File ( dir , " server.properties " ) ;
2017-05-30 21:38:51 +02:00
if ( ! file . exists ( ) ) file . createNewFile ( ) ;
2017-04-14 04:39:51 +02:00
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 ) ;
2017-04-01 07:37:48 +02:00
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 ( ) ;
}
}
}
}
}