2017-04-01 07:37:48 +02:00
package net.ME1312.SubServers.Host.Executable ;
2018-09-09 00:06:21 +02:00
import net.ME1312.Galaxi.Engine.GalaxiEngine ;
import net.ME1312.Galaxi.Library.Config.YAMLSection ;
2020-06-12 07:45:49 +02:00
import net.ME1312.Galaxi.Library.Container.NamedContainer ;
2019-05-13 05:28:27 +02:00
import net.ME1312.Galaxi.Library.Map.ObjectMap ;
2020-06-12 07:45:49 +02:00
import net.ME1312.Galaxi.Library.Container.Container ;
2020-06-13 23:53:18 +02:00
import net.ME1312.Galaxi.Library.Map.ObjectMapValue ;
2018-09-09 00:06:21 +02:00
import net.ME1312.Galaxi.Library.UniversalFile ;
import net.ME1312.Galaxi.Library.Util ;
import net.ME1312.Galaxi.Library.Version.Version ;
2019-05-13 05:28:27 +02:00
import net.ME1312.SubData.Client.SubDataClient ;
2019-08-30 21:44:54 +02:00
import net.ME1312.SubServers.Host.ExHost ;
2017-04-01 07:37:48 +02:00
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-07-23 06:32:57 +02:00
import net.ME1312.SubServers.Host.Library.Exception.SubCreatorException ;
2020-06-13 23:53:18 +02:00
import net.ME1312.SubServers.Host.Library.ReplacementScanner ;
2018-07-29 04:09:47 +02:00
import net.ME1312.SubServers.Host.Network.API.SubCreator.ServerType ;
2017-04-01 07:37:48 +02:00
import net.ME1312.SubServers.Host.Network.Packet.PacketExCreateServer ;
import net.ME1312.SubServers.Host.Network.Packet.PacketOutExLogMessage ;
2019-01-06 07:58:13 +01:00
import net.ME1312.SubServers.Host.SubAPI ;
2017-04-01 07:37:48 +02:00
import org.json.JSONObject ;
import java.io.* ;
import java.net.URL ;
import java.nio.charset.Charset ;
2019-05-13 05:28:27 +02:00
import java.nio.file.Files ;
2020-06-13 23:53:18 +02:00
import java.nio.file.LinkOption ;
import java.nio.file.StandardCopyOption ;
import java.security.MessageDigest ;
2017-07-23 06:32:57 +02:00
import java.util.* ;
2017-04-01 07:37:48 +02:00
/ * *
* Internal SubCreator Class
* /
2019-08-30 21:44:54 +02:00
public class SubCreatorImpl {
2017-04-16 19:02:14 +02:00
private ExHost host ;
2018-10-08 23:07:44 +02:00
private TreeMap < String , CreatorTask > thread ;
2017-04-01 07:37:48 +02:00
2018-07-29 04:09:47 +02:00
public static class ServerTemplate extends net . ME1312 . SubServers . Host . Network . API . SubCreator . ServerTemplate {
2017-05-30 21:38:51 +02:00
private String name ;
private String nick = null ;
private boolean enabled ;
private String icon ;
private File directory ;
private ServerType type ;
2019-05-13 05:28:27 +02:00
private ObjectMap < String > build ;
private ObjectMap < String > options ;
2017-05-30 21:38:51 +02:00
/ * *
* Create a SubCreator Template
*
* @param name Template Name
* @param directory Template Directory
* @param build Build Options
* @param options Configuration Options
* /
2019-05-13 05:28:27 +02:00
public ServerTemplate ( String name , boolean enabled , String icon , File directory , ObjectMap < String > build , ObjectMap < String > options ) {
2018-07-29 04:09:47 +02:00
super ( toRaw ( name , enabled , icon , directory , build , options ) ) ;
2017-05-30 21:38:51 +02:00
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 ;
}
2019-05-13 05:28:27 +02:00
/ * *
* Get whether this Template requires the Version argument
*
* @return Version Requirement
* /
public boolean requiresVersion ( ) {
return getBuildOptions ( ) . getBoolean ( " Require-Version " , false ) ;
}
2019-06-17 05:13:48 +02:00
/ * *
* Get whether this Template can be used to update it ' s servers
*
* @return Updatable Status
* /
public boolean canUpdate ( ) {
return getBuildOptions ( ) . getBoolean ( " Can-Update " , false ) ;
}
2017-05-30 21:38:51 +02:00
/ * *
* Get the Build Options for this Template
*
* @return Build Options
* /
2019-05-13 05:28:27 +02:00
public ObjectMap < String > getBuildOptions ( ) {
2017-05-30 21:38:51 +02:00
return build ;
}
/ * *
* Get the Configuration Options for this Template
*
* @return Configuration Options
* /
2019-05-13 05:28:27 +02:00
public ObjectMap < String > getConfigOptions ( ) {
2017-05-30 21:38:51 +02:00
return options ;
}
2018-07-29 04:09:47 +02:00
2019-05-13 05:28:27 +02:00
private static ObjectMap < String > toRaw ( String name , boolean enabled , String icon , File directory , ObjectMap < String > build , ObjectMap < String > options ) {
2018-07-29 04:09:47 +02:00
if ( Util . isNull ( name , enabled , directory , build , options ) ) throw new NullPointerException ( ) ;
2019-05-13 05:28:27 +02:00
ObjectMap < String > tinfo = new ObjectMap < String > ( ) ;
2018-07-29 04:09:47 +02:00
tinfo . set ( " enabled " , enabled ) ;
tinfo . set ( " name " , name ) ;
tinfo . set ( " display " , name ) ;
tinfo . set ( " icon " , icon ) ;
tinfo . set ( " type " , ( build . contains ( " Server-Type " ) ) ? ServerType . valueOf ( build . getRawString ( " Server-Type " ) . toUpperCase ( ) ) : ServerType . CUSTOM ) ;
return tinfo ;
2017-04-01 07:37:48 +02:00
}
}
2018-10-08 23:07:44 +02:00
private class CreatorTask extends Thread {
2019-08-30 02:01:52 +02:00
private final SubServerImpl update ;
2020-06-13 23:53:18 +02:00
private final UUID player ;
2018-10-08 23:07:44 +02:00
private final String name ;
private final ServerTemplate template ;
private final Version version ;
private final int port ;
private final UUID address ;
2019-05-13 05:28:27 +02:00
private final UUID tracker ;
2019-08-30 21:44:54 +02:00
private final SubLoggerImpl log ;
2020-06-13 23:53:18 +02:00
private final HashMap < String , String > replacements ;
2018-10-08 23:07:44 +02:00
private Process process ;
2020-06-13 23:53:18 +02:00
private CreatorTask ( UUID player , String name , ServerTemplate template , Version version , int port , UUID address , UUID tracker ) {
2019-01-06 07:58:13 +01:00
super ( SubAPI . getInstance ( ) . getAppInfo ( ) . getName ( ) + " ::SubCreator_Process_Handler( " + name + ')' ) ;
2019-06-17 05:13:48 +02:00
this . update = host . servers . getOrDefault ( name . toLowerCase ( ) , null ) ;
2020-06-13 23:53:18 +02:00
this . player = player ;
2018-10-08 23:07:44 +02:00
this . name = name ;
this . template = template ;
this . version = version ;
this . port = port ;
2019-08-30 21:44:54 +02:00
this . log = new SubLoggerImpl ( null , this , name + File . separator + ( ( update = = null ) ? " Creator " : " Updater " ) , address , new Container < Boolean > ( true ) , null ) ;
2020-06-13 23:53:18 +02:00
this . replacements = new HashMap < String , String > ( ) ;
2018-10-08 23:07:44 +02:00
this . address = address ;
2019-05-13 05:28:27 +02:00
this . tracker = tracker ;
2018-10-08 23:07:44 +02:00
}
2017-04-01 07:37:48 +02:00
2019-05-13 05:28:27 +02:00
private ObjectMap < String > build ( File dir , ServerTemplate template , List < ServerTemplate > history ) throws SubCreatorException {
ObjectMap < String > server = new ObjectMap < String > ( ) ;
2018-10-08 23:07:44 +02:00
Version version = this . version ;
2019-01-14 01:52:44 +01:00
HashMap < String , String > var = new HashMap < String , String > ( ) ;
2018-10-08 23:07:44 +02:00
boolean error = false ;
if ( history . contains ( template ) ) throw new IllegalStateException ( " Template Import loop detected " ) ;
history . add ( template ) ;
for ( String other : template . getBuildOptions ( ) . getStringList ( " Import " , new ArrayList < String > ( ) ) ) {
if ( host . templates . keySet ( ) . contains ( other . toLowerCase ( ) ) ) {
if ( host . templates . get ( other . toLowerCase ( ) ) . isEnabled ( ) ) {
2019-05-13 05:28:27 +02:00
if ( version ! = null | | ! host . templates . get ( other . toLowerCase ( ) ) . requiresVersion ( ) ) {
2019-06-17 05:13:48 +02:00
if ( update = = null | | host . templates . get ( other . toLowerCase ( ) ) . canUpdate ( ) ) {
ObjectMap < String > config = build ( dir , host . templates . get ( other . toLowerCase ( ) ) , history ) ;
if ( config = = null ) {
throw new SubCreatorException ( ) ;
} else {
server . setAll ( config ) ;
}
2019-05-13 05:28:27 +02:00
} else {
2019-06-17 05:13:48 +02:00
log . logger . warn . println ( " Skipping template that cannot be run in update mode: " + other ) ;
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Skipping template that cannot be run in update mode: " + other ) ) ;
2019-05-13 05:28:27 +02:00
}
2018-10-08 23:07:44 +02:00
} else {
2019-05-13 05:28:27 +02:00
log . logger . warn . println ( " Skipping template that requires extra versioning: " + other ) ;
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Skipping template that requires extra versioning: " + other ) ) ;
2018-10-08 23:07:44 +02:00
}
2018-08-10 06:50:10 +02:00
} else {
2018-10-08 23:07:44 +02:00
log . logger . warn . println ( " Skipping disabled template: " + other ) ;
2019-05-13 05:28:27 +02:00
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Skipping disabled template: " + other ) ) ;
2018-08-10 06:50:10 +02:00
}
2017-07-23 06:32:57 +02:00
} else {
2018-10-08 23:07:44 +02:00
log . logger . warn . println ( " Skipping missing template: " + other ) ;
2019-05-13 05:28:27 +02:00
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Skipping missing template: " + other ) ) ;
2017-07-23 06:32:57 +02:00
}
}
2018-10-08 23:07:44 +02:00
server . setAll ( template . getConfigOptions ( ) ) ;
try {
log . logger . info . println ( " Loading Template: " + template . getDisplayName ( ) ) ;
2019-05-13 05:28:27 +02:00
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Loading Template: " + template . getDisplayName ( ) ) ) ;
2020-06-13 23:53:18 +02:00
if ( template . getBuildOptions ( ) . getBoolean ( " Update-Files " , false ) ) updateDirectory ( template . getDirectory ( ) , dir ) ;
else Util . copyDirectory ( template . getDirectory ( ) , dir ) ;
for ( ObjectMapValue < String > replacement : template . getBuildOptions ( ) . getMap ( " Replacements " ) . getValues ( ) ) if ( ! replacement . isNull ( ) ) {
replacements . put ( replacement . getHandle ( ) . toLowerCase ( ) . replace ( '-' , '_' ) . replace ( ' ' , '_' ) , replacement . asRawString ( ) ) ;
}
var . putAll ( replacements ) ;
2019-12-18 20:15:02 +01:00
var . put ( " java " , System . getProperty ( " java.home " ) + File . separator + " bin " + File . separator + " java " ) ;
2019-06-17 05:13:48 +02:00
var . put ( " mode " , ( update = = null ) ? " CREATE " : " UPDATE " ) ;
2020-06-13 23:53:18 +02:00
if ( player ! = null ) var . put ( " player " , player . toString ( ) . toUpperCase ( ) ) ;
else var . remove ( " player " ) ;
2019-01-14 01:52:44 +01:00
var . put ( " name " , name ) ;
2020-06-13 23:53:18 +02:00
var . put ( " host " , SubAPI . getInstance ( ) . getName ( ) ) ;
2019-01-14 01:52:44 +01:00
var . put ( " template " , template . getName ( ) ) ;
var . put ( " type " , template . getType ( ) . toString ( ) . toUpperCase ( ) ) ;
2019-05-13 05:28:27 +02:00
if ( version ! = null ) var . put ( " version " , version . toString ( ) ) ;
2020-06-13 23:53:18 +02:00
else var . remove ( " version " ) ;
var . put ( " address " , getAddress ( ) ) ;
2019-01-14 01:52:44 +01:00
var . put ( " port " , Integer . toString ( port ) ) ;
2019-01-04 22:51:58 +01:00
switch ( template . getType ( ) ) {
case SPONGE :
case FORGE :
2019-05-13 05:28:27 +02:00
if ( version ! = null ) {
log . logger . info . println ( " Searching Versions... " ) ;
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Searching Versions... " ) ) ;
YAMLSection spversionmanifest = new YAMLSection ( new JSONObject ( " { \" versions \" : " + Util . readAll ( new BufferedReader ( new InputStreamReader ( new URL ( " https://dl-api.spongepowered.org/v1/org.spongepowered/sponge " + ( ( template . getType ( ) = = ServerType . FORGE ) ? " forge " : " vanilla " ) + " /downloads?type=stable&minecraft= " + version ) . openStream ( ) , Charset . forName ( " UTF-8 " ) ) ) ) + '}' ) ) ;
ObjectMap < String > spprofile = null ;
Version spversion = null ;
for ( ObjectMap < String > profile : spversionmanifest . getMapList ( " versions " ) ) {
if ( profile . getMap ( " dependencies " ) . getRawString ( " minecraft " ) . equalsIgnoreCase ( version . toString ( ) ) & & ( spversion = = null | | new Version ( profile . getRawString ( " version " ) ) . compareTo ( spversion ) > = 0 ) ) {
spprofile = profile ;
spversion = new Version ( profile . getRawString ( " version " ) ) ;
}
2019-01-04 22:51:58 +01:00
}
2019-05-13 05:28:27 +02:00
if ( spversion = = null )
throw new InvalidServerException ( " Cannot find Sponge version for Minecraft " + version . toString ( ) ) ;
log . logger . info . println ( " Found \" sponge " + ( ( template . getType ( ) = = ServerType . FORGE ) ? " forge " : " vanilla " ) + " - " + spversion . toString ( ) + '"' ) ;
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Found \" sponge " + ( ( template . getType ( ) = = ServerType . FORGE ) ? " forge " : " vanilla " ) + " - " + spversion . toString ( ) + '"' ) ) ;
2018-10-08 23:07:44 +02:00
2019-05-13 05:28:27 +02:00
if ( template . getType ( ) = = ServerType . FORGE ) {
Version mcfversion = new Version ( ( ( spprofile . getMap ( " dependencies " ) . getRawString ( " forge " ) . contains ( " - " ) ) ? " " : spprofile . getMap ( " dependencies " ) . getRawString ( " minecraft " ) + '-' ) + spprofile . getMap ( " dependencies " ) . getRawString ( " forge " ) ) ;
log . logger . info . println ( " Found \" forge- " + mcfversion . toString ( ) + '"' ) ;
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Found \" forge- " + mcfversion . toString ( ) + '"' ) ) ;
2017-04-01 07:37:48 +02:00
2019-05-13 05:28:27 +02:00
var . put ( " mcf_version " , mcfversion . toString ( ) ) ;
}
var . put ( " sp_version " , spversion . toString ( ) ) ;
2019-01-04 22:51:58 +01:00
}
break ;
2018-10-08 23:07:44 +02:00
}
} catch ( Exception e ) {
log . logger . error . println ( e ) ;
2017-04-01 07:37:48 +02:00
}
2019-01-17 18:44:47 +01:00
if ( template . getBuildOptions ( ) . contains ( " Executable " ) ) {
2018-10-08 23:07:44 +02:00
File cache ;
if ( template . getBuildOptions ( ) . getBoolean ( " Use-Cache " , true ) ) {
cache = new UniversalFile ( GalaxiEngine . getInstance ( ) . getRuntimeDirectory ( ) , " Cache:Templates: " + template . getName ( ) ) ;
cache . mkdirs ( ) ;
2019-01-17 16:39:15 +01:00
String c = cache . toString ( ) ;
if ( System . getProperty ( " os.name " ) . toLowerCase ( ) . startsWith ( " windows " ) & &
( template . getBuildOptions ( ) . getRawString ( " Executable " ) . toLowerCase ( ) . startsWith ( " bash " ) | | template . getBuildOptions ( ) . getRawString ( " Executable " ) . toLowerCase ( ) . startsWith ( " sh " ) ) ) c = c . replace ( File . separatorChar , '/' ) ;
var . put ( " cache " , c ) ;
2018-10-08 23:07:44 +02:00
} else {
cache = null ;
}
2019-01-04 06:35:56 +01:00
2018-10-08 23:07:44 +02:00
try {
2019-01-14 17:02:17 +01:00
log . logger . info . println ( " Launching Build Script... " ) ;
2019-05-13 05:28:27 +02:00
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketOutExLogMessage ( address , " Launching Build Script... " ) ) ;
2019-01-14 17:02:17 +01:00
ProcessBuilder pb = new ProcessBuilder ( ) . command ( Executable . parse ( host . host . getRawString ( " Git-Bash " ) , template . getBuildOptions ( ) . getRawString ( " Executable " ) ) ) . directory ( dir ) ;
2019-01-14 01:52:44 +01:00
pb . environment ( ) . putAll ( var ) ;
process = pb . start ( ) ;
2019-05-13 05:28:27 +02:00
log . file = new File ( dir , " SubCreator- " + template . getName ( ) + " - " + ( ( version ! = null ) ? " - " + version . toString ( ) : " " ) + " .log " ) ;
2018-10-08 23:07:44 +02:00
log . process = process ;
log . start ( ) ;
process . waitFor ( ) ;
Thread . sleep ( 500 ) ;
if ( process . exitValue ( ) ! = 0 ) error = true ;
} catch ( InterruptedException e ) {
error = true ;
2017-05-30 21:38:51 +02:00
} catch ( Exception e ) {
2018-10-08 23:07:44 +02:00
error = true ;
log . logger . error . println ( e ) ;
}
if ( cache ! = null ) {
if ( cache . isDirectory ( ) & & cache . listFiles ( ) . length = = 0 ) cache . delete ( ) ;
cache = new UniversalFile ( GalaxiEngine . getInstance ( ) . getRuntimeDirectory ( ) , " Cache:Templates " ) ;
if ( cache . isDirectory ( ) & & cache . listFiles ( ) . length = = 0 ) cache . delete ( ) ;
cache = new UniversalFile ( GalaxiEngine . getInstance ( ) . getRuntimeDirectory ( ) , " Cache " ) ;
if ( cache . isDirectory ( ) & & cache . listFiles ( ) . length = = 0 ) cache . delete ( ) ;
2017-05-30 21:38:51 +02:00
}
}
2017-04-01 07:37:48 +02:00
2018-10-08 23:07:44 +02:00
new UniversalFile ( dir , " template.yml " ) . delete ( ) ;
if ( error ) throw new SubCreatorException ( ) ;
return server ;
}
2020-06-13 23:53:18 +02:00
@SuppressWarnings ( " unchecked " )
2018-10-08 23:07:44 +02:00
public void run ( ) {
2020-06-13 23:53:18 +02:00
Runnable declaration = ( ) - > {
replacements . put ( " player " , ( player = = null ) ? " " : player . toString ( ) ) ;
replacements . put ( " name " , name ) ;
replacements . put ( " host " , SubAPI . getInstance ( ) . getName ( ) ) ;
replacements . put ( " template " , template . getName ( ) ) ;
replacements . put ( " type " , template . getType ( ) . toString ( ) ) ;
replacements . put ( " version " , ( version ! = null ) ? version . toString ( ) : " " ) ;
replacements . put ( " address " , getAddress ( ) ) ;
replacements . put ( " port " , Integer . toString ( port ) ) ;
} ;
declaration . run ( ) ;
File dir = ( update ! = null ) ? new File ( update . getFullPath ( ) ) : new File ( host . host . getRawString ( " Directory " ) ,
( template . getConfigOptions ( ) . contains ( " Directory " ) ) ? new ReplacementScanner ( replacements ) . replace ( template . getConfigOptions ( ) . getRawString ( " Directory " ) ) . toString ( ) : name ) ;
2018-10-08 23:07:44 +02:00
dir . mkdirs ( ) ;
2020-06-13 23:53:18 +02:00
ObjectMap < String > config ;
2017-05-30 21:38:51 +02:00
try {
2020-06-13 23:53:18 +02:00
config = build ( dir , template , new LinkedList < > ( ) ) ;
2018-10-08 23:07:44 +02:00
} catch ( SubCreatorException e ) {
2020-06-13 23:53:18 +02:00
config = null ;
2017-05-30 21:38:51 +02:00
} catch ( Exception e ) {
2020-06-13 23:53:18 +02:00
config = null ;
2018-10-08 23:07:44 +02:00
log . logger . error . println ( e ) ;
2017-05-30 21:38:51 +02:00
}
2020-06-13 23:53:18 +02:00
declaration . run ( ) ;
ReplacementScanner replacements = new ReplacementScanner ( this . replacements ) ;
if ( config ! = null ) {
try {
if ( template . getBuildOptions ( ) . getBoolean ( " Install-Client " , true ) ) generateClient ( dir , template . getType ( ) , name ) ;
LinkedList < String > masks = new LinkedList < > ( ) ;
masks . add ( " /server.properties " ) ;
masks . addAll ( template . getBuildOptions ( ) . getRawStringList ( " Replace " , Collections . emptyList ( ) ) ) ;
replacements . replace ( dir , masks . toArray ( new String [ 0 ] ) ) ;
} catch ( Exception e ) {
config = null ;
e . printStackTrace ( ) ;
}
}
if ( config ! = null ) {
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketExCreateServer ( 0 , null , ( Map < String , ? > ) replacements . replace ( config . get ( ) ) , tracker ) ) ;
2018-10-08 23:07:44 +02:00
} else {
log . logger . info . println ( " Couldn't build the server jar. Check the SubCreator logs for more detail. " ) ;
2019-07-30 02:20:38 +02:00
( ( SubDataClient ) SubAPI . getInstance ( ) . getSubDataNetwork ( ) [ 0 ] ) . sendPacket ( new PacketExCreateServer ( - 1 , " Couldn't build the server jar. Check the SubCreator logs for more detail. " , tracker ) ) ;
2018-04-07 21:04:55 +02:00
}
2019-08-30 21:44:54 +02:00
SubCreatorImpl . this . thread . remove ( name . toLowerCase ( ) ) ;
2017-05-30 21:38:51 +02:00
}
2017-07-23 06:32:57 +02:00
}
2018-10-08 23:07:44 +02:00
/ * *
* Creates a SubCreator Instance
*
* @param host SubServers . Host
* /
2019-08-30 21:44:54 +02:00
public SubCreatorImpl ( ExHost host ) {
2018-10-08 23:07:44 +02:00
if ( Util . isNull ( host ) ) throw new NullPointerException ( ) ;
this . host = host ;
this . thread = new TreeMap < > ( ) ;
2017-04-01 07:37:48 +02:00
}
2020-06-13 23:53:18 +02:00
public boolean create ( UUID player , String name , ServerTemplate template , Version version , int port , UUID address , UUID tracker ) {
if ( Util . isNull ( name , template , port , address ) ) throw new NullPointerException ( ) ;
CreatorTask task = new CreatorTask ( player , name , template , version , port , address , tracker ) ;
2018-10-08 23:07:44 +02:00
this . thread . put ( name . toLowerCase ( ) , task ) ;
task . start ( ) ;
2017-07-23 06:32:57 +02:00
return true ;
2017-04-01 07:37:48 +02:00
}
public void terminate ( ) {
2018-10-08 23:07:44 +02:00
HashMap < String , CreatorTask > temp = new HashMap < String , CreatorTask > ( ) ;
2017-07-23 06:32:57 +02:00
temp . putAll ( thread ) ;
for ( String i : temp . keySet ( ) ) {
terminate ( i ) ;
}
}
2017-07-25 21:27:40 +02:00
public void terminate ( String name ) {
2018-10-08 23:07:44 +02:00
if ( this . thread . keySet ( ) . contains ( name . toLowerCase ( ) ) ) {
if ( this . thread . get ( name . toLowerCase ( ) ) . process ! = null & & this . thread . get ( name . toLowerCase ( ) ) . process . isAlive ( ) ) {
2019-01-09 18:37:02 +01:00
Executable . terminate ( this . thread . get ( name . toLowerCase ( ) ) . process ) ;
} else if ( this . thread . get ( name . toLowerCase ( ) ) . isAlive ( ) ) {
2018-10-08 23:07:44 +02:00
this . thread . get ( name . toLowerCase ( ) ) . interrupt ( ) ;
this . thread . remove ( name . toLowerCase ( ) ) ;
}
2017-04-01 07:37:48 +02:00
}
}
public void waitFor ( ) throws InterruptedException {
2018-10-08 23:07:44 +02:00
HashMap < String , CreatorTask > temp = new HashMap < String , CreatorTask > ( ) ;
2017-07-23 06:32:57 +02:00
temp . putAll ( thread ) ;
for ( String i : temp . keySet ( ) ) {
waitFor ( i ) ;
}
}
2017-07-25 21:27:40 +02:00
public void waitFor ( String name ) throws InterruptedException {
2018-10-08 23:07:44 +02:00
while ( this . thread . keySet ( ) . contains ( name . toLowerCase ( ) ) & & this . thread . get ( name . toLowerCase ( ) ) . isAlive ( ) ) {
2017-04-01 07:37:48 +02:00
Thread . sleep ( 250 ) ;
}
}
2019-08-30 21:44:54 +02:00
public List < SubLoggerImpl > getLoggers ( ) {
List < SubLoggerImpl > loggers = new ArrayList < SubLoggerImpl > ( ) ;
2018-10-08 23:07:44 +02:00
HashMap < String , CreatorTask > temp = new HashMap < String , CreatorTask > ( ) ;
2017-07-23 06:32:57 +02:00
temp . putAll ( thread ) ;
for ( String i : temp . keySet ( ) ) {
loggers . add ( getLogger ( i ) ) ;
}
return loggers ;
2017-04-01 07:37:48 +02:00
}
2019-08-30 21:44:54 +02:00
public SubLoggerImpl getLogger ( String name ) {
2018-10-08 23:07:44 +02:00
return this . thread . get ( name ) . log ;
2017-04-01 07:37:48 +02:00
}
2020-06-13 23:53:18 +02:00
private static NamedContainer < YAMLSection , String > address = null ;
private String getAddress ( ) {
if ( address = = null | | host . config . get ( ) ! = address . name ( ) ) {
address = new NamedContainer < > ( host . config . get ( ) , host . config . get ( ) . getMap ( " Settings " ) . getRawString ( " Server-Bind " ) ) ;
}
return address . get ( ) ;
}
2020-06-12 07:45:49 +02:00
private static NamedContainer < YAMLSection , Map < String , Object > > subdata = null ;
2020-06-13 23:53:18 +02:00
private Map < String , Object > getSubData ( ) {
2020-06-12 07:45:49 +02:00
if ( subdata = = null | | host . config . get ( ) ! = subdata . name ( ) ) {
Map < String , Object > map = new HashMap < String , Object > ( ) ;
map . put ( " Address " , host . config . get ( ) . getMap ( " Settings " ) . getMap ( " SubData " ) . getRawString ( " Address " ) ) ;
if ( host . config . get ( ) . getMap ( " Settings " ) . getMap ( " SubData " ) . getRawString ( " Password " , " " ) . length ( ) > 0 ) map . put ( " Password " , host . config . get ( ) . getMap ( " Settings " ) . getMap ( " SubData " ) . getRawString ( " Password " ) ) ;
subdata = new NamedContainer < > ( host . config . get ( ) , map ) ;
}
return subdata . get ( ) ;
}
2017-05-30 21:38:51 +02:00
private void generateClient ( File dir , ServerType type , String name ) throws IOException {
2020-06-13 23:53:18 +02:00
boolean installed = false ;
if ( type = = ServerType . SPIGOT ) {
installed = true ;
if ( ! new UniversalFile ( dir , " plugins " ) . exists ( ) ) new UniversalFile ( dir , " plugins " ) . mkdirs ( ) ;
if ( ! new UniversalFile ( dir , " plugins:SubServers.Client.jar " ) . exists ( ) )
Util . copyFromJar ( ExHost . class . getClassLoader ( ) , " net/ME1312/SubServers/Host/Library/Files/client.jar " , new UniversalFile ( dir , " plugins:SubServers.Client.jar " ) . getPath ( ) ) ;
} else if ( type = = ServerType . FORGE | | type = = ServerType . SPONGE ) {
installed = true ;
if ( ! new UniversalFile ( dir , " mods " ) . exists ( ) ) new UniversalFile ( dir , " mods " ) . mkdirs ( ) ;
if ( ! new UniversalFile ( dir , " mods:SubServers.Client.jar " ) . exists ( ) )
Util . copyFromJar ( ExHost . class . getClassLoader ( ) , " net/ME1312/SubServers/Host/Library/Files/client.jar " , new UniversalFile ( dir , " mods:SubServers.Client.jar " ) . getPath ( ) ) ;
}
if ( installed ) {
2020-06-12 07:45:49 +02:00
YAMLSection config = new YAMLSection ( ) ;
2019-05-13 05:28:27 +02:00
FileWriter writer = new FileWriter ( new UniversalFile ( dir , " subdata.json " ) , false ) ;
2020-06-12 07:45:49 +02:00
config . set ( " Name " , name ) ;
2020-06-13 23:53:18 +02:00
config . setAll ( getSubData ( ) ) ;
2020-06-12 07:45:49 +02:00
writer . write ( config . toJSON ( ) . toString ( ) ) ;
2017-05-30 21:38:51 +02:00
writer . close ( ) ;
2019-05-13 05:28:27 +02:00
2019-06-17 05:13:48 +02:00
if ( ! new UniversalFile ( dir , " subdata.rsa.key " ) . exists ( ) & & new UniversalFile ( " subdata.rsa.key " ) . exists ( ) ) {
2019-05-13 05:28:27 +02:00
Files . copy ( new UniversalFile ( " subdata.rsa.key " ) . toPath ( ) , new UniversalFile ( dir , " subdata.rsa.key " ) . toPath ( ) ) ;
}
2017-04-01 07:37:48 +02:00
}
}
2020-06-13 23:53:18 +02:00
private void updateDirectory ( File from , File to ) {
if ( from . isDirectory ( ) & & ! Files . isSymbolicLink ( from . toPath ( ) ) ) {
if ( ! to . exists ( ) ) {
to . mkdirs ( ) ;
}
String files [ ] = from . list ( ) ;
for ( String file : files ) {
File srcFile = new File ( from , file ) ;
File destFile = new File ( to , file ) ;
updateDirectory ( srcFile , destFile ) ;
}
} else {
try {
if ( ! to . exists ( ) | | from . length ( ) ! = to . length ( ) | | ! Arrays . equals ( generateSHA256 ( to ) , generateSHA256 ( from ) ) ) {
if ( to . exists ( ) ) {
if ( to . isDirectory ( ) ) Util . deleteDirectory ( to ) ;
else to . delete ( ) ;
}
Files . copy ( from . toPath ( ) , to . toPath ( ) , LinkOption . NOFOLLOW_LINKS , StandardCopyOption . REPLACE_EXISTING ) ;
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
}
} private byte [ ] generateSHA256 ( File file ) throws Exception {
MessageDigest md = MessageDigest . getInstance ( " SHA-256 " ) ;
FileInputStream fis = new FileInputStream ( file ) ;
byte [ ] dataBytes = new byte [ 1024 ] ;
int nread ;
while ( ( nread = fis . read ( dataBytes ) ) ! = - 1 ) {
md . update ( dataBytes , 0 , nread ) ;
}
fis . close ( ) ;
return md . digest ( ) ;
2017-04-01 07:37:48 +02:00
}
}