2019-12-25 01:39:38 -05:00
package mindustry ;
2017-05-03 00:09:48 -04:00
2019-12-25 01:39:38 -05:00
import arc.* ;
import arc.assets.* ;
import arc.assets.loaders.* ;
import arc.audio.* ;
2022-06-26 08:35:08 -04:00
import arc.files.* ;
2019-12-25 01:39:38 -05:00
import arc.graphics.* ;
import arc.graphics.g2d.* ;
import arc.math.* ;
import arc.util.* ;
2020-11-13 12:40:23 -05:00
import mindustry.ai.* ;
2019-12-25 01:39:38 -05:00
import mindustry.core.* ;
2020-01-11 20:09:20 -05:00
import mindustry.ctype.* ;
2019-12-25 01:39:38 -05:00
import mindustry.game.EventType.* ;
2020-05-09 22:24:13 -04:00
import mindustry.game.* ;
2019-12-25 01:39:38 -05:00
import mindustry.gen.* ;
import mindustry.graphics.* ;
import mindustry.maps.* ;
import mindustry.mod.* ;
2022-02-19 14:53:06 -05:00
import mindustry.net.* ;
2020-01-17 18:08:23 -05:00
import mindustry.ui.* ;
2017-05-03 00:09:48 -04:00
2019-12-25 01:39:38 -05:00
import static arc.Core.* ;
import static mindustry.Vars.* ;
2018-01-27 14:43:35 -05:00
2019-08-30 17:32:49 -04:00
public abstract class ClientLauncher extends ApplicationCore implements Platform {
2019-08-27 16:32:22 -04:00
private static final int loadingFPS = 20 ;
2019-07-03 19:11:22 -04:00
private long lastTime ;
2019-08-27 16:32:22 -04:00
private long beginTime ;
2019-08-26 13:15:53 -04:00
private boolean finished = false ;
2020-05-06 19:07:37 -04:00
private LoadRenderer loader ;
2018-01-27 23:42:42 -05:00
2018-12-26 17:38:40 -05:00
@Override
public void setup ( ) {
2021-03-04 16:34:23 +01:00
String dataDir = OS . env ( " MINDUSTRY_DATA_DIR " ) ;
if ( dataDir ! = null ) {
Core . settings . setDataDirectory ( files . absolute ( dataDir ) ) ;
}
2021-02-19 13:28:31 -05:00
checkLaunch ( ) ;
2020-08-04 23:37:12 -04:00
loadLogger ( ) ;
2020-05-06 19:07:37 -04:00
loader = new LoadRenderer ( ) ;
2020-02-13 09:11:35 -05:00
Events . fire ( new ClientCreateEvent ( ) ) ;
2020-06-25 12:54:55 -04:00
loadFileLogger ( ) ;
platform = this ;
2021-06-02 11:08:08 -04:00
maxTextureSize = Gl . getInt ( Gl . maxTextureSize ) ;
2019-08-27 16:32:22 -04:00
beginTime = Time . millis ( ) ;
2019-08-26 13:15:53 -04:00
2020-06-11 15:25:46 -04:00
//debug GL information
Log . info ( " [GL] Version: @ " , graphics . getGLVersion ( ) ) ;
2021-06-02 11:08:08 -04:00
Log . info ( " [GL] Max texture size: @ " , maxTextureSize ) ;
2020-06-26 11:58:35 -04:00
Log . info ( " [GL] Using @ context. " , gl30 ! = null ? " OpenGL 3 " : " OpenGL 2 " ) ;
2021-06-02 11:08:08 -04:00
if ( maxTextureSize < 4096 ) Log . warn ( " [GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues. " ) ;
2021-07-15 11:27:21 -04:00
Log . info ( " [JAVA] Version: @ " , OS . javaVersion ) ;
2021-09-07 22:32:27 -04:00
long ram = Runtime . getRuntime ( ) . maxMemory ( ) ;
boolean gb = ram > = 1024 * 1024 * 1024 ;
Log . info ( " [RAM] Available: @ @ " , Strings . fixed ( gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f , 1 ) , gb ? " GB " : " MB " ) ;
2020-06-11 15:25:46 -04:00
2018-12-20 12:38:27 -05:00
Time . setDeltaProvider ( ( ) - > {
float result = Core . graphics . getDeltaTime ( ) * 60f ;
2019-06-08 22:20:30 -04:00
return ( Float . isNaN ( result ) | | Float . isInfinite ( result ) ) ? 1f : Mathf . clamp ( result , 0 . 0001f , 60f / 10f ) ;
2018-12-20 12:38:27 -05:00
} ) ;
2020-06-11 13:42:22 -04:00
batch = new SortedSpriteBatch ( ) ;
2019-08-26 13:15:53 -04:00
assets = new AssetManager ( ) ;
2019-08-27 18:25:38 -04:00
assets . setLoader ( Texture . class , " . " + mapExtension , new MapPreviewLoader ( ) ) ;
2019-10-02 21:03:56 -04:00
tree = new FileTree ( ) ;
2022-06-26 08:35:08 -04:00
assets . setLoader ( Sound . class , new SoundLoader ( tree ) {
@Override
public void loadAsync ( AssetManager manager , String fileName , Fi file , SoundParameter parameter ) {
}
@Override
public Sound loadSync ( AssetManager manager , String fileName , Fi file , SoundParameter parameter ) {
if ( parameter ! = null & & parameter . sound ! = null ) {
mainExecutor . submit ( ( ) - > parameter . sound . load ( file ) ) ;
return parameter . sound ;
} else {
Sound sound = new Sound ( ) ;
mainExecutor . submit ( ( ) - > {
try {
sound . load ( file ) ;
} catch ( Throwable t ) {
Log . err ( " Error loading sound: " + file , t ) ;
}
} ) ;
return sound ;
}
}
} ) ;
2019-10-02 21:03:56 -04:00
assets . setLoader ( Music . class , new MusicLoader ( tree ) ) ;
2019-09-17 21:55:57 -04:00
assets . load ( " sprites/error.png " , Texture . class ) ;
2019-08-26 13:15:53 -04:00
atlas = TextureAtlas . blankAtlas ( ) ;
2019-09-07 14:11:50 -04:00
Vars . net = new Net ( platform . getNet ( ) ) ;
2022-02-20 10:17:20 -05:00
MapPreviewLoader . setupLoaders ( ) ;
2019-10-02 21:03:56 -04:00
mods = new Mods ( ) ;
2020-05-09 22:24:13 -04:00
schematics = new Schematics ( ) ;
2019-08-26 13:15:53 -04:00
2020-01-17 18:08:23 -05:00
Fonts . loadSystemCursors ( ) ;
2019-08-27 16:32:22 -04:00
2019-08-27 09:27:09 -04:00
assets . load ( new Vars ( ) ) ;
2019-08-31 08:47:53 -04:00
2020-01-17 18:08:23 -05:00
Fonts . loadDefaultFont ( ) ;
2019-08-31 08:47:53 -04:00
2020-06-11 15:25:46 -04:00
//load fallback atlas if max texture size is below 4096
2021-08-27 09:31:09 -04:00
assets . load ( new AssetDescriptor < > ( maxTextureSize > = 4096 ? " sprites/sprites.aatls " : " sprites/fallback/sprites.aatls " , TextureAtlas . class ) ) . loaded = t - > atlas = t ;
2019-08-30 17:32:49 -04:00
assets . loadRun ( " maps " , Map . class , ( ) - > maps . loadPreviews ( ) ) ;
2019-08-27 19:33:41 -04:00
2019-08-26 22:53:11 -04:00
Musics . load ( ) ;
Sounds . load ( ) ;
2019-08-26 08:10:27 -04:00
2019-08-27 19:33:41 -04:00
assets . loadRun ( " contentcreate " , Content . class , ( ) - > {
2019-12-07 14:10:39 -05:00
content . createBaseContent ( ) ;
2019-08-27 19:33:41 -04:00
content . loadColors ( ) ;
2019-12-07 14:10:39 -05:00
} , ( ) - > {
mods . loadScripts ( ) ;
content . createModContent ( ) ;
2019-08-27 19:33:41 -04:00
} ) ;
2021-06-02 11:08:08 -04:00
assets . load ( mods ) ;
assets . loadRun ( " mergeUI " , PixmapPacker . class , ( ) - > { } , ( ) - > Fonts . mergeFontAtlas ( atlas ) ) ;
2019-07-06 10:15:21 -04:00
add ( logic = new Logic ( ) ) ;
add ( control = new Control ( ) ) ;
add ( renderer = new Renderer ( ) ) ;
add ( ui = new UI ( ) ) ;
add ( netServer = new NetServer ( ) ) ;
add ( netClient = new NetClient ( ) ) ;
2019-08-26 22:53:11 -04:00
2019-10-17 23:51:23 -04:00
assets . load ( schematics ) ;
2019-09-29 15:21:50 -04:00
2020-01-18 13:24:14 -05:00
assets . loadRun ( " contentinit " , ContentLoader . class , ( ) - > content . init ( ) , ( ) - > content . load ( ) ) ;
2020-11-13 12:40:23 -05:00
assets . loadRun ( " baseparts " , BaseRegistry . class , ( ) - > { } , ( ) - > bases . load ( ) ) ;
2019-08-26 22:53:11 -04:00
}
@Override
public void add ( ApplicationListener module ) {
super . add ( module ) ;
//autoload modules when necessary
2020-11-28 19:12:27 -05:00
if ( module instanceof Loadable l ) {
assets . load ( l ) ;
2019-08-26 22:53:11 -04:00
}
}
@Override
public void resize ( int width , int height ) {
2019-09-03 19:14:33 -04:00
if ( assets = = null ) return ;
2019-11-17 11:20:36 -05:00
if ( ! finished ) {
2019-08-26 22:53:11 -04:00
Draw . proj ( ) . setOrtho ( 0 , 0 , width , height ) ;
2019-09-01 00:45:54 -04:00
} else {
super . resize ( width , height ) ;
2019-08-26 22:53:11 -04:00
}
2018-07-27 17:26:12 -04:00
}
2018-06-11 15:18:25 -04:00
2019-07-03 19:11:22 -04:00
@Override
public void update ( ) {
2019-08-27 17:44:25 -04:00
if ( ! finished ) {
2020-05-07 14:08:27 -04:00
if ( loader ! = null ) {
loader . draw ( ) ;
}
2020-05-07 14:04:22 -04:00
if ( assets . update ( 1000 / loadingFPS ) ) {
2020-05-07 14:08:27 -04:00
loader . dispose ( ) ;
loader = null ;
2021-03-09 19:04:29 -05:00
Log . info ( " Total time to load: @ms " , Time . timeSinceMillis ( beginTime ) ) ;
2019-08-27 17:44:25 -04:00
for ( ApplicationListener listener : modules ) {
listener . init ( ) ;
}
2019-12-14 20:49:55 -05:00
mods . eachClass ( Mod : : init ) ;
2019-08-26 13:15:53 -04:00
finished = true ;
2022-02-15 00:24:43 -05:00
Events . fire ( new ClientLoadEvent ( ) ) ;
2021-06-02 11:08:08 -04:00
clientLoaded = true ;
2019-10-18 19:31:01 -04:00
super . resize ( graphics . getWidth ( ) , graphics . getHeight ( ) ) ;
2021-02-19 13:28:31 -05:00
app . post ( ( ) - > app . post ( ( ) - > app . post ( ( ) - > app . post ( ( ) - > {
super . resize ( graphics . getWidth ( ) , graphics . getHeight ( ) ) ;
//mark initialization as complete
finishLaunch ( ) ;
} ) ) ) ) ;
2019-08-26 13:15:53 -04:00
}
2019-08-27 17:44:25 -04:00
} else {
2020-05-13 18:11:28 -04:00
asyncCore . begin ( ) ;
2020-04-30 20:03:11 -04:00
2019-08-26 13:15:53 -04:00
super . update ( ) ;
2020-04-30 20:03:11 -04:00
2020-05-13 18:11:28 -04:00
asyncCore . end ( ) ;
2019-08-26 13:15:53 -04:00
}
2019-07-03 19:11:22 -04:00
int targetfps = Core . settings . getInt ( " fpscap " , 120 ) ;
2019-07-07 14:11:57 -04:00
if ( targetfps > 0 & & targetfps < = 240 ) {
2019-07-03 19:11:22 -04:00
long target = ( 1000 * 1000000 ) / targetfps ; //target in nanos
long elapsed = Time . timeSinceNanos ( lastTime ) ;
if ( elapsed < target ) {
2019-10-18 20:11:02 -04:00
Threads . sleep ( ( target - elapsed ) / 1000000 , ( int ) ( ( target - elapsed ) % 1000000 ) ) ;
2019-07-03 19:11:22 -04:00
}
}
lastTime = Time . nanos ( ) ;
}
2021-02-19 13:28:31 -05:00
@Override
public void exit ( ) {
//on graceful exit, finish the launch normally.
Vars . finishLaunch ( ) ;
}
2018-07-27 17:26:12 -04:00
@Override
2018-12-20 12:38:27 -05:00
public void init ( ) {
2019-08-26 22:53:11 -04:00
setup ( ) ;
}
@Override
public void resume ( ) {
if ( finished ) {
super . resume ( ) ;
}
2019-08-26 13:15:53 -04:00
}
2019-08-30 17:32:49 -04:00
@Override
public void pause ( ) {
2021-02-19 13:28:31 -05:00
//when the user tabs out on mobile, the exit() event doesn't fire reliably - in that case, just assume they're about to kill the app
//this isn't 100% reliable but it should work for most cases
if ( mobile ) {
Vars . finishLaunch ( ) ;
}
2019-08-30 17:32:49 -04:00
if ( finished ) {
super . pause ( ) ;
}
}
2017-05-03 00:09:48 -04:00
}