[SOLVED] How to gradle run my game

I’ve finally switched from SDK to IDEA+gradle. Previously, I just ran the game with the SDK launcher, now instead I use “gradle run”.

However, I have one annoyance: gradle run packs all the assets every time a change is made. This is unnecessary and I’d like to just “run” the game as the assets are already at the right place.

I could just add a script and bypass the problem, but I think there should be a right way to do it.

This is my build.gradle:

//import org.gradle.internal.os.OperatingSystem

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'idea'

version = "QUI_NOME_VERSIONE"
mainClassName='com.pesegato.p8s.Main'

buildscript {
    dependencies {
        classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.8.0'
    }

    repositories {
        mavenCentral()
    }
}

/*
switch ( OperatingSystem.current() ) {
case OperatingSystem.WINDOWS:
    project.ext.lwjglNatives = "natives-windows"
    break
case OperatingSystem.LINUX:
    project.ext.lwjglNatives = "natives-linux"
    break
case OperatingSystem.MAC_OS:
    project.ext.lwjglNatives = "natives-macos"
    break
}

project.ext.lwjglVersion = "3.2.0"
*/
repositories {
    mavenLocal()
    jcenter()
    maven { url "https://jitpack.io" }
}

ext {
    jvm = org.gradle.internal.jvm.Jvm.current()
    javaVersion = JavaVersion.current()
    jmeVersion = "[3.1,)" 
    //isCiServer = System.getenv("TURBO")
    isCiServer = (System.getProperty("user.name").equals("michele"))
    isWindows = org.gradle.internal.os.OperatingSystem.current().windows
    System.out.println("CI mode: "+isCiServer);
}

project(":assets") {

    apply plugin: "java"
    
    buildDir = rootProject.file("build/assets")
    
    sourceSets {
        main {
            resources {
                srcDirs = [ '.', '../run/assets' ]
                exclude('**/*.blend','**/*.j3odata','**/*.tga','Textures/MonkeySheet/*.png')
//                exclude('**/*.blend','**/*.j3odata','**/*.tga','Textures/MonkeySheet/*')
            }
        }
    }    

}

//project(":assetsDDS") {
//
//    apply plugin: "java"
//
//    buildDir = rootProject.file("build/assets")
//
//    sourceSets {
//        main {
//            resources {
//                srcDirs = [ '.' ]
//                exclude('**/*.png')
//                include('Textures/MonkeySheet/*.tga')
//            }
//        }
//    }
//
//}


task myPack(type: Jar) {
    from 'assets','run/assets'
    exclude('**/*.blend','**/*.j3odata','**/*.tga')
    baseName 'assets'
}


def buildDate
def buildCommit
def bitnessFlavor

task dateInfo(type:Exec){
    commandLine 'powershell get-date -format "{dd-MM-yyyy HHmm}"'.split()
    standardOutput = new ByteArrayOutputStream()

    bitnessFlavor = System.properties['sun.arch.data.model']

    doLast {
        //versionfile.text = 'build.date=' + standardOutput.toString()
        buildDate=standardOutput.toString().trim()
        if (version.equals("QUI_NOME_VERSIONE")) {
            version=buildDate
        }
    }
}

task dateInfo2(type:Exec){
    commandLine 'git describe --always --dirty'.split()
    //ext.versionfile = new File('assets/buildinfo2.properties')
    standardOutput = new ByteArrayOutputStream()

    doLast {
        //versionfile.text = 'build.revision=' + standardOutput.toString()
        buildCommit=standardOutput.toString().trim()
    }
}

task versionInfo {

    doLast {
        def props = new Properties()
        /*
        ['assets/buildinfo1.properties','assets/buildinfo2.properties'].each {
        props.load(new FileReader(file(it)))
        }
         */
        props.put('build.date',buildDate)
        props.put('build.revision',buildCommit)
        def writer = new FileWriter(file('assets/buildinfo.properties'))
        try {
            props.store(writer, 'Automatically generated by gradle')
            writer.flush()
        } finally {
            writer.close()
        }
    }
}
versionInfo.dependsOn dateInfo
versionInfo.dependsOn dateInfo2

/*
task versionInfo(type:Exec){
def props = new Properties()
File propsFile = new File('assets/buildinfo.properties')
commandLine 'hg id -i -b -t'.split()
standardOutput = new ByteArrayOutputStream()
props.setProperty('build.revision', 'aaa' )
commandLine 'powershell get-date'.split() // -format "{dd-MM-yyyy HH:mm}"'
props.setProperty('build.date', 'bbb' )
props.store(propsFile.newWriter(), null)
ext.versionfile = new File('assets/buildinfo.properties')

doLast {
versionfile.text = 'build.revision=' + standardOutput.toString() + 'build.date='
}
}
 */


def jme3 = ["v" : '[3.1,)', "g": "org.jmonkeyengine"]
def pesegato = ["g" :"com.pesegato" ,"v":"latest.integration"]
if (isCiServer){
    pesegato.g="com.github.Pesegato"
    pesegato.v="master-SNAPSHOT"
}


sourceSets {
    main {
        java { srcDir 'src'}
    }
}


dependencies {
 
    compile "org.jmonkeyengine:jme3-core:$jmeVersion"
    compile "org.jmonkeyengine:jme3-desktop:$jmeVersion"
    compile "org.jmonkeyengine:jme3-lwjgl:$jmeVersion"
    
    /*
    // LWJGL dependencies START
    compile "org.lwjgl:lwjgl:$lwjglVersion"
    compile "org.lwjgl:lwjgl-assimp:$lwjglVersion"
    compile "org.lwjgl:lwjgl-glfw:$lwjglVersion"
    compile "org.lwjgl:lwjgl-openal:$lwjglVersion"
    compile "org.lwjgl:lwjgl-opengl:$lwjglVersion"
    compile "org.lwjgl:lwjgl-stb:$lwjglVersion"
    compile "org.lwjgl:lwjgl:$lwjglVersion:$lwjglNatives"
    compile "org.lwjgl:lwjgl-assimp:$lwjglVersion:$lwjglNatives"
    compile "org.lwjgl:lwjgl-glfw:$lwjglVersion:$lwjglNatives"
    compile "org.lwjgl:lwjgl-openal:$lwjglVersion:$lwjglNatives"
    compile "org.lwjgl:lwjgl-opengl:$lwjglVersion:$lwjglNatives"
    compile "org.lwjgl:lwjgl-stb:$lwjglVersion:$lwjglNatives"
    // LWJGL dependencies END
    */
    compile "org.jmonkeyengine:jme3-jogg:$jmeVersion"
    compile "org.jmonkeyengine:jme3-effects:$jmeVersion"
    compile 'com.simsilica:zay-es:[1.2,)'
    compile 'com.simsilica:lemur:[1.12,)'
    compile 'com.simsilica:lemur-proto:[1.9,)'
    compile 'com.simsilica:lemur-props:[1.0,)'
    compile 'com.simsilica:sio2:[1.1,)'
    //compile 'com.simsilica:sim-math:1.1.1'
    compile 'com.google.guava:guava:19.0'
    compile 'net.java.dev.jna:jna:4.2.2'
    compile 'net.java.dev.jna:jna-platform:4.2.2'
    compile 'org.slf4j:slf4j-api:1.7.21'
    compile "${pesegato.g}:GoldMonkey:${pesegato.v}"
    compile "${pesegato.g}:GibbonDice:${pesegato.v}"
    compile "${pesegato.g}:BigBanana:${pesegato.v}"
    compile "${pesegato.g}:MonkeySheet:${pesegato.v}"

    compile files('../commons-math3-3.5.jar')
    compile files('../tonegod.emitter.jar')
    compile files('../tonegodgui-0.0.2.jar')
    compile files('../Mermaid.jar')
    
    runtime project(':assets')
//    runtime project(':assetsDDS')
}

apply plugin: 'javafx-gradle-plugin'

// configure javafx-gradle-plugin
jfx {
    verbose = true
    mainClass = "com.pesegato.p8s.Main"
    jfxAppOutputDir = "build/jfx/app"
    jfxMainAppJarName = "Simonetta.jar"
    deployDir = "src/main/deploy"

    // gradle jfxJar
    css2bin = false
    preLoader = null
    updateExistingJar = false
    allPermissions = false
    manifestAttributes = null // Map<String, String>
    addPackagerJar = true

    // gradle jfxNative
    identifier = null // setting this for windows-bundlers makes it possible to generate upgradeable installers (using same GUID)
    vendor = "some serious business corp."
    nativeOutputDir = "build/jfx/native"
    bundler = "ALL" // set this to some specific, if your don't want all bundlers running, examples "windows.app", "jnlp", ...
    jvmProperties = null // Map<String, String>
    jvmArgs = null // List<String>
    userJvmArgs = null // Map<String, String>
    launcherArguments = null // List<String>
    nativeReleaseVersion = "1.0"
    needShortcut = false
    needMenu = false
    /*
    bundleArguments = [
    // dont bundle JRE (not recommended, but increases build-size/-speed)
    ]
     */
    appName = "simonetta" // this is used for files below "src/main/deploy", e.g. "src/main/deploy/windows/project.ico"
    additionalAppResources = null // path to some additional resources when creating application-bundle
    //secondaryLaunchers = [[appName:"somethingDifferent"], [appName:"somethingDifferent2"]]
    fileAssociations = null // List<Map<String, Object>>
    noBlobSigning = false // when using bundler "jnlp", you can choose to NOT use blob signing
    customBundlers // List<String>
    skipNativeLauncherWorkaround205 = false

    skipNativeLauncherWorkaround124 = false
    skipNativeLauncherWorkaround167 = false
    skipJNLPRessourcePathWorkaround182 = false
    skipSigningJarFilesJNLP185 = false
    skipSizeRecalculationForJNLP185 = false
    /*
    // gradle jfxGenerateKeyStore
    keyStore = "src/main/deploy/keystore.jks"
    keyStoreAlias = "myalias"
    keyStorePassword = "password"
    keyPassword = null // will default to keyStorePassword
    keyStoreType = "jks"
    overwriteKeyStore = false

    certDomain = null // required
    certOrgUnit = null // defaults to "none"
    certOrg = null // required
    certState = null // required
    certCountry = null // required
     */
}

    ext.unarchiveDir = "run/assets/Textures/MonkeySheet"
	task convertToDDS(type : Copy) {
		from unarchiveDir
		into unarchiveDir
		include('**/*.TGA', '**/*.tga')
		//include('**/*.PNG', '**/*.png')
		eachFile { FileCopyDetails fcd ->
			println "convert to dds ${fcd}"
			//on windows:
			//commandLine 'cmd', '/c', 'nvcompress'
			def cmd = ["C:/Program Files/NVIDIA Corporation/NVIDIA Texture Tools 2/bin/nvcompress.exe"]
			cmd += "-alpha"
			cmd += "-nomips"
			cmd += "-bc3"
			cmd += fcd.file.absolutePath
			//println "convert to dds >>> ${fcd.file} >>  ${fcd.getSourceName()} >>  ${fcd.name}"
			fcd.name = fcd.name.substring(0, fcd.name.lastIndexOf(".")) + ".dds"
			fcd.name = fcd.name.toLowerCase()
			//def proc  = "nvcompress ${options} ${f}".execute();
			//proc.waitFor();
			//println "return code: ${ proc.exitValue()}"
			exec {
				commandLine cmd
			}
			fcd.exclude()
		}
	}

/*
PER 32bit
set JAVA_HOME="C:\Program Files (x86)\Java\jdk1.8.0_91"

PER 64bit
set JAVA_HOME="C:\Program Files\Java\jdk1.8.0_77
gradlew clean
gradlew release
 */

task makePretty(type: Delete) {
    delete 'build/jfx/native/simonetta/simonetta.ico' //, 'uglyFile'
}

task release(type: Zip) {
    from 'build/jfx/native'
    baseName "Simonetta-Windows-x$bitnessFlavor-FULL"
}

task releaseApp(type: Zip) {
    from 'build/jfx/native/simonetta/app'
    baseName "Simonetta-Windows-x$bitnessFlavor-APP"
}

releaseApp.dependsOn makePretty
release.dependsOn makePretty
makePretty.dependsOn jfxNative
jfxNative.dependsOn build
jar.dependsOn versionInfo

Should only be every time a change to an asset is made… which of course you’d want to repack every time.

You could probably configure your gradle to hit the assets directory directly and just ignore your assets.jar project. Then things would work like in the SDK where you can be all happy thinking everything is working until you run your game somewhere else.

But it’s possible. The straight-forward but hacky way is to just comment out your assets project and have your project depend on the directory directly:
runtime files(‘assets’)

And actually, since you use the application plugin, if that’s the way you also deploy your app then your assets would just be bundled right into the zip I guess, without being packed into an assets.jar. That’s probably ok even for most people I guess.

1 Like

Actually not true, unfortunately. Should I make a separate Task for that?

Maybe something else is missing but I use this technique in one of my demos to include raw jars… and they do make it into the distZip.

1 Like

Solved with this

    isCiServer = System.getProperty("something") == "somevalue"


    if (isCiServer) {
        runtime project(':assets')
    } else {
        runtime files('assets')
    }
1 Like