@@ -37,6 +37,147 @@ task runExamples(dependsOn: 'build', type: JavaExec) {
3737 }
3838}
3939
40+ def umuLauncherDownloadUrl = ' https://github.com/Open-Wine-Components/umu-launcher/releases/download/1.4.0/umu-launcher-1.4.0-zipapp.tar'
41+ def umuLauncherArchive = layout. buildDirectory. file(' tmp/umu-launcher-1.4.0-zipapp.tar' )
42+ def umuLauncherExtractDir = layout. buildDirectory. dir(' tools/umu-launcher' )
43+ def protonToolchainVersion = java. toolchain. languageVersion. get(). asInt()
44+ def protonJdkDownloadUrl = " https://api.adoptium.net/v3/binary/latest/${ protonToolchainVersion} /ga/windows/x64/jdk/hotspot/normal/eclipse?project=jdk"
45+ def protonJdkArchive = layout. buildDirectory. file(" tmp/proton-jdk-${ protonToolchainVersion} -windows.zip" )
46+ def protonJdkExtractDir = layout. buildDirectory. dir(' tools/proton-jdk' )
47+
48+ task downloadProtonRuntime {
49+ description = ' Download and extract Proton runtime launcher into jme3-examples/build/tools/umu-launcher.'
50+ outputs. dir(umuLauncherExtractDir)
51+ inputs. property(" url" , umuLauncherDownloadUrl)
52+
53+ doLast {
54+ def archiveFile = umuLauncherArchive. get(). asFile
55+ archiveFile. parentFile. mkdirs()
56+
57+ logger. lifecycle(" Downloading umu-launcher from ${ umuLauncherDownloadUrl} " )
58+
59+ new URL (umuLauncherDownloadUrl). withInputStream { input ->
60+ archiveFile. withOutputStream { output ->
61+ output << input
62+ }
63+ }
64+
65+ def extractRoot = umuLauncherExtractDir. get(). asFile
66+ extractRoot. deleteDir()
67+ extractRoot. mkdirs()
68+
69+ copy {
70+ from tarTree(archiveFile)
71+ into extractRoot
72+ }
73+
74+ def extractedEntries = extractRoot. listFiles()
75+ if (extractedEntries == null || extractedEntries. length == 0 ) {
76+ throw new GradleException (' umu-launcher archive extraction failed: build/tools/umu-launcher is empty' )
77+ }
78+
79+ logger. lifecycle(" umu-launcher extracted to ${ extractRoot.absolutePath} " )
80+ }
81+ }
82+
83+ task downloadProtonJdk {
84+ description = " Download and extract the Adoptium Java ${ protonToolchainVersion} Windows JDK used to bootstrap Gradle inside Proton."
85+ outputs. dir(protonJdkExtractDir)
86+ inputs. property(" url" , protonJdkDownloadUrl)
87+
88+ doLast {
89+ def archiveFile = protonJdkArchive. get(). asFile
90+ archiveFile. parentFile. mkdirs()
91+
92+ logger. lifecycle(" Downloading Windows JDK from ${ protonJdkDownloadUrl} " )
93+
94+ new URL (protonJdkDownloadUrl). withInputStream { input ->
95+ archiveFile. withOutputStream { output ->
96+ output << input
97+ }
98+ }
99+
100+ def extractRoot = protonJdkExtractDir. get(). asFile
101+ extractRoot. deleteDir()
102+ extractRoot. mkdirs()
103+
104+ copy {
105+ from zipTree(archiveFile)
106+ into extractRoot
107+ }
108+
109+ def extractedEntries = extractRoot. listFiles()
110+ if (extractedEntries == null || extractedEntries. length == 0 ) {
111+ throw new GradleException (' Windows JDK extraction failed: build/tools/proton-jdk is empty' )
112+ }
113+
114+ logger. lifecycle(" Windows JDK extracted to ${ extractRoot.absolutePath} " )
115+ }
116+ }
117+
118+ task runExamplesWithProton (dependsOn : [' build' , ' downloadProtonRuntime' , ' downloadProtonJdk' ], type : Exec ) {
119+ description = ' Run jme3 examples under Proton using the downloaded runtime launcher and Windows JDK.'
120+ workingDir = rootProject. projectDir
121+
122+ doFirst {
123+ def extractRoot = umuLauncherExtractDir. get(). asFile
124+ def umuRunScript = new File (extractRoot, ' umu-run' )
125+ if (! umuRunScript. exists()) {
126+ def nestedUmuRun = extractRoot. listFiles()?. find { it. isDirectory() }?. toPath()?. resolve(' umu-run' )?. toFile()
127+ if (nestedUmuRun != null && nestedUmuRun. exists()) {
128+ umuRunScript = nestedUmuRun
129+ }
130+ }
131+ if (! umuRunScript. exists()) {
132+ throw new GradleException (" Could not find umu-run script at ${ umuRunScript.absolutePath} " )
133+ }
134+
135+ def protonJdkRoot = protonJdkExtractDir. get(). asFile
136+ def protonJdkDir = fileTree(protonJdkRoot). find { it. name == ' java.exe' }?. parentFile?. parentFile
137+
138+ def winePrefix = " ${ buildDir} /umu/wineprefix"
139+ def gameId = ' jme3-examples'
140+ def store = ' none'
141+ def protonJavaHome = " Z:${ protonJdkDir.absolutePath.replace('/', '\\\\')} "
142+ def protonJavaExe = " ${ protonJavaHome} \\\\ bin\\\\ java.exe"
143+ def exampleClass = project. findProperty(' example' )?. toString() ?: mainClassName
144+ def runtimeClasspathFiles = sourceSets. main. runtimeClasspath. files as LinkedHashSet
145+ def relevantRuntimeEntries = runtimeClasspathFiles. findAll { file ->
146+ def name = file. name. toLowerCase()
147+ name. contains(' angle' ) || name. contains(' saferalloc' )
148+ }
149+ logger. lifecycle(" Proton runtime entries: ${ relevantRuntimeEntries*.name} " )
150+
151+ def runtimeClasspath = runtimeClasspathFiles. collect { file ->
152+ " Z:${ file.absolutePath.replace('/', '\\\\')} "
153+ }. join(' ;' )
154+ def jvmArgs = []
155+
156+ if (assertions == ' true' ) {
157+ jvmArgs << ' -ea'
158+ }
159+
160+ if (System . properties[' java.util.logging.config.file' ] != null ) {
161+ def loggingConfig = System . properties[' java.util.logging.config.file' ]. replace(' /' , ' \\\\ ' )
162+ jvmArgs << " -Djava.util.logging.config.file=Z:${ loggingConfig} "
163+ }
164+
165+ executable = umuRunScript. absolutePath
166+ args protonJavaExe
167+ args jvmArgs
168+ args ' -cp' , runtimeClasspath, exampleClass
169+
170+ environment ' WINEPREFIX' , winePrefix
171+ environment ' GAMEID' , gameId
172+ environment ' STORE' , store
173+ environment ' JAVA_HOME' , protonJavaHome
174+ environment ' JDK_HOME' , protonJavaHome
175+ environment ' PROTON_VERB' , ' waitforexitandrun'
176+
177+ logger. lifecycle(" Running ${ exampleClass} with Proton via ${ protonJavaExe} " )
178+ }
179+ }
180+
40181dependencies {
41182 implementation project(' :jme3-core' )
42183 implementation project(' :jme3-desktop' )
0 commit comments