Skip to content

Commit

Permalink
Move UncivServer to own module (and jar) (yairm210#6468)
Browse files Browse the repository at this point in the history
* Move UncivServer to own module (and jar)

* UncivServer isalive logged

* Separate UncivServer - some wiki hints

* Separate UncivServer - how to build UncivServer.jar

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
  • Loading branch information
SomeTroglodyte and yairm210 authored May 8, 2022
1 parent 3ea9c65 commit 4290373
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 23 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ com_crashlytics_export_strings.xml
/android/bin/
/core/bin/
/desktop/bin/
/server/bin/
/html/bin/
/ios/bin/
/ios-moe/bin/
Expand All @@ -57,6 +58,7 @@ com_crashlytics_export_strings.xml
/android/nbproject/private/
/core/nbproject/private/
/desktop/nbproject/private/
/server/nbproject/private/
/html/nbproject/private/
/ios/nbproject/private/
/ios-moe/nbproject/private/
Expand All @@ -65,6 +67,7 @@ com_crashlytics_export_strings.xml
/android/build/
/core/build/
/desktop/build/
/server/build/
/html/build/
/ios/build/
/ios-moe/build/
Expand All @@ -74,6 +77,7 @@ com_crashlytics_export_strings.xml
/android/nbbuild/
/core/nbbuild/
/desktop/nbbuild/
/server/nbbuild/
/html/nbbuild/
/ios/nbbuild/
/ios-moe/nbbuild/
Expand All @@ -82,6 +86,7 @@ com_crashlytics_export_strings.xml
/android/dist/
/core/dist/
/desktop/dist/
/server/dist/
/html/dist/
/ios/dist/
/ios-moe/dist/
Expand All @@ -90,6 +95,7 @@ com_crashlytics_export_strings.xml
/android/nbdist/
/core/nbdist/
/desktop/nbdist/
/server/nbdist/
/html/nbdist/
/ios/nbdist/
/ios-moe/nbdist/
Expand Down Expand Up @@ -131,6 +137,8 @@ android/release/android-release.aab
tests/build/
desktop/packr/
desktop/packrCache/
server/packr/
server/packrCache/
deploy/
android/release/

Expand Down
10 changes: 8 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,18 @@ project(":desktop") {
}

"implementation"("com.github.MinnDevelopment:java-discord-rpc:v2.0.1")

"implementation"("net.java.dev.jna:jna:5.11.0")
"implementation"("net.java.dev.jna:jna-platform:5.11.0")
}
}

// For server-side
// For server-side
project(":server") {
apply(plugin = "kotlin")

dependencies {
// For server-side
"implementation"("io.ktor:ktor-server-core:1.6.8")
"implementation"("io.ktor:ktor-server-netty:1.6.8")
"implementation"("ch.qos.logback:logback-classic:1.2.5")
Expand Down
19 changes: 10 additions & 9 deletions core/src/com/unciv/ui/utils/KeyPressDispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,16 @@ data class KeyCharAndCode(val char: Char, val code: Int) {
/** Guaranteed to be ignored by [KeyPressDispatcher.set] and never to be generated for an actual event, used as fallback to ensure no action is taken */
val UNKNOWN = KeyCharAndCode(Input.Keys.UNKNOWN)

// Kludges because we got crashes: java.lang.NoSuchMethodError: 'int kotlin.CharCodeKt.access$getCode$p(char)'
fun Char.toCode() =
try { code } catch (ex: Throwable) { null }
?: try { @Suppress("DEPRECATION") toInt() } catch (ex: Throwable) { null }
?: 0
fun Int.makeChar() =
try { Char(this) } catch (ex: Throwable) { null }
?: try { toChar() } catch (ex: Throwable) { null }
?: Char.MIN_VALUE
// Kludges because we got crashes: java.lang.NoSuchMethodError: 'int kotlin.CharCodeKt.access$getCode$p(char)'
//TODO fixed by removing UncivServer from the desktop module - clean up comments and all uses
fun Char.toCode() = code
// try { code } catch (ex: Throwable) { null }
// ?: try { @Suppress("DEPRECATION") toInt() } catch (ex: Throwable) { null }
// ?: 0
fun Int.makeChar() = Char(this)
// try { Char(this) } catch (ex: Throwable) { null }
// ?: try { toChar() } catch (ex: Throwable) { null }
// ?: Char.MIN_VALUE

/** mini-factory for control codes - case insensitive */
fun ctrl(letter: Char) = KeyCharAndCode((letter.toCode() and 31).makeChar(),0)
Expand Down
31 changes: 27 additions & 4 deletions docs/Developers/Building-Locally.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ So first things first - the initial "No assumptions" setup to have Unciv run fro
- Select "Show Package Details" in the bottom right
- Choose version 30.0.3 under "Android SDK Build-Tools <whatever version you have>"
- Click "Apply"
- In Android Studio, Run > Edit configurations.
- In Android Studio, Run > Edit configurations (be sure the Gradle sync is finished successfully first).
- Click "+" to add a new configuration
- Choose "Application"
- Set the module to `Unciv.desktop`, main class to `com.unciv.app.desktop.DesktopLauncher` and `<repo_folder>\android\assets\` as the Working directory, OK to close the window
- Give the configuration a name, we recommend "Desktop"
- Set the module classpath (the box to the right of the Java selection) to `Unciv.desktop`, main class to `com.unciv.app.desktop.DesktopLauncher` and `<repo_folder>\android\assets\` as the Working directory, OK to close the window
- If you get a `../../docs/uniques.md (No such file or directory)` error that means you forgot to set the working directory!
- Select the Desktop configuration and click the green arrow button to run!
- Select the Desktop configuration (or however you chose to name it) and click the green arrow button to run! Or you can use the next button -the green critter with six legs and two feelers - to start debugging.
- I also recommend going to Settings > Version Control > Commit and turning off 'Before commit - perform code analysis'

Unciv uses Gradle to specify dependencies and how to run. In the background, the Gradle gnomes will be off fetching the packages (a one-time effort) and, once that's done, will build the project!

Unciv uses Grade 7.2 and the Android Gradle Plugin 7.1.0


Note advanced build commands as described in the next paragraph, specifically the `gradlew desktop:dist` one to build a jar, run just fine in Android Studio's terminal (Alt+F12), with most dependencies already taken care of.

## Without Android Studio

If you also have JDK 11 installed, you can compile Unciv on your own by cloning (or downloading and unzipping) the project, opening a terminal in the Unciv folder and run the following commands:
Expand Down Expand Up @@ -63,6 +66,26 @@ After building, the output .JAR file should be in /desktop/build/libs/Unciv.jar

For actual development, you'll probably need to download Android Studio and build it yourself - see Contributing :)

## UncivServer

The simple multiplayer host included in the sources can be set up to debug or run analogously to the main game:
- In Android Studio, Run > Edit configurations.
- Click "+" to add a new configuration
- Choose "Application" and name the config, e.g. "UncivServer"
- Set the module to `Unciv.server`, main class to `com.unciv.app.server.DesktopLauncher` and `<repo_folder>/android/assets/` as the Working directory, OK to close the window.
- Select the UncivServer configuration and click the green arrow button to run! Or start a debug session as above.

To build a jar file, refer to [Without Android Studio](#Without-Android-Studio) and replace 'desktop' with 'server'. That is, run `./gradlew server:dist` and when it's done look for /server/build/libs/UncivServer.jar

## Unit Tests

You can (and in some cases _should_) run and even debug the unit tests locally.
- In Android Studio, Run > Edit configurations.
- Click "+" to add a new configuration
- Choose "Gradle" and name the config, e.g. "Unit Tests"
- Under "Gradle Project", choose "Unciv" from the dropdown (or type it), set "Tasks" to `:tests:test` and "Arguments" to `--tests "com.unciv.*"`, OK to close the window.
- Select the "Unit Tests" configuration and click the green arrow button to run! Or start a debug session as above.

## Next steps

Congratulations! Unciv should now be running on your computer! Now we can start changing some code, and later we'll see how your changes make it into the main repository!
Expand Down
9 changes: 6 additions & 3 deletions docs/Developers/Project-structure-and-major-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

Since LibGDX, and therefore Unciv, are built for multi-platform support, the project structure is built accordingly.

99% of the code is in the [Core](/com/unciv) project, which contains all the platform-independant code.
99% of the code is in the [core](https://github.com/yairm210/Unciv/tree/master/core) project, which contains all the platform-independant code.

The [Desktop](/) and [Android](/) folders contain platform-specific things, and the Android folder also contains the game Images and the all-important Assets, which are required for running from Desktop as well, so we bundle them up into the .jar file when releasing.
The [desktop](https://github.com/yairm210/Unciv/tree/master/desktop) and [android](https://github.com/yairm210/Unciv/tree/master/android) folders contain platform-specific things, and the Android folder also contains the game Images and the all-important Assets, which are required for running from Desktop as well, so we bundle them up into the .jar file when releasing.

The [tests](https://github.com/yairm210/Unciv/tree/master/tests) folder contains tests that can be run manually via gradle with `./gradlew tests:test`, and are run automatically by Travis for every push.

The [server](https://github.com/yairm210/Unciv/tree/master/server) folder contains the sources for the UncivServer (a host enabling communication between multiplayer game instances), which is packaged into its own separate jar.

The [Test](/com/unciv) folder contains tests that can be run manually via gradle with `./gradlew tests:test`, and are run automatically by Travis for every push.

## Translations

Expand Down
6 changes: 3 additions & 3 deletions docs/Other/Hosting-a-Multiplayer-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Therefore, you can now host your own Unciv server, when not on Android.

To do so, you must have a JDK installed.

From the directory where the Unciv.jar file is located, create a folder named "MultiplayerFiles", open a terminal and run the following line:
`java -cp Unciv.jar com.unciv.app.desktop.UncivServer`
From the directory where the UncivServer.jar file is located, create a folder named "MultiplayerFiles", open a terminal and run the following line:
`java -jar UncivServer.jar`

Don't forget to use 'cd' to switch to the correct dictionary. Here's an example in Windows.

Expand All @@ -16,7 +16,7 @@ D:
cd Games
cd unciv
mkdir MultiplayerFiles
java -cp Unciv.jar com.unciv.app.desktop.UncivServer
java -jar UncivServer.jar
```

Your server has now started!
Expand Down
161 changes: 161 additions & 0 deletions server/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import com.badlogicgames.packr.Packr
import com.badlogicgames.packr.PackrConfig
import com.unciv.build.BuildConfig

plugins {
id("kotlin")
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
}

sourceSets {
main {
java.srcDir("src/")
}
}

val mainClassName = "com.unciv.app.server.UncivServer"
val assetsDir = file("../android/assets")
val deployFolder = file("../deploy")

// See https://github.com/libgdx/libgdx/wiki/Starter-classes-and-configuration#common-issues
// and https://github.com/yairm210/Unciv/issues/5679
val jvmArgsForMac = listOf("-XstartOnFirstThread", "-Djava.awt.headless=true")
tasks.register<JavaExec>("run") {
jvmArgs = mutableListOf<String>()
if ("mac" in System.getProperty("os.name").toLowerCase())
(jvmArgs as MutableList<String>).addAll(jvmArgsForMac)
// These are non-standard, only available/necessary on Mac.

dependsOn(tasks.getByName("classes"))

main = mainClassName
classpath = sourceSets.main.get().runtimeClasspath
standardInput = System.`in`
workingDir = assetsDir
isIgnoreExitValue = true
}

tasks.register<JavaExec>("debug") {
jvmArgs = jvmArgsForMac
dependsOn(tasks.getByName("classes"))
main = mainClassName
classpath = sourceSets.main.get().runtimeClasspath
standardInput = System.`in`
workingDir = assetsDir
isIgnoreExitValue = true
debug = true
}

tasks.register<Jar>("dist") { // Compiles the jar file
dependsOn(tasks.getByName("classes"))

// META-INF/INDEX.LIST and META-INF/io.netty.versions.properties are duplicated, but I don't know why
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

from(files(sourceSets.main.get().output.resourcesDir))
from(files(sourceSets.main.get().output.classesDirs))
// see Laurent1967's comment on https://github.com/libgdx/libgdx/issues/5491
from({ configurations.compileClasspath.get().resolve().map { if (it.isDirectory) it else zipTree(it) } })
archiveFileName.set("UncivServer.jar")

manifest {
attributes(mapOf("Main-Class" to mainClassName, "Specification-Version" to BuildConfig.appVersion))
}
}

for (platform in PackrConfig.Platform.values()) {
val platformName = platform.toString()

tasks.create("packr${platformName}") {
dependsOn(tasks.getByName("dist"))

// Needs to be here and not in doLast because the zip task depends on the outDir
val jarFile = "$rootDir/server/build/libs/UncivServer.jar"
val config = PackrConfig()
config.platform = platform

config.apply {
executable = "UncivServer"
classpath = listOf(jarFile)
removePlatformLibs = config.classpath
mainClass = mainClassName
vmArgs = listOf("Xmx1G")
minimizeJre = "server/packrConfig.json"
outDir = file("packr")
}


doLast {
// https://gist.github.com/seanf/58b76e278f4b7ec0a2920d8e5870eed6
fun String.runCommand(workingDir: File) {
val process = ProcessBuilder(*split(" ").toTypedArray())
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()

if (!process.waitFor(30, TimeUnit.SECONDS)) {
process.destroy()
throw RuntimeException("execution timed out: $this")
}
if (process.exitValue() != 0) {
println("execution returned code ${process.exitValue()}: $this")
}
println(process.inputStream.bufferedReader().readText())
}


if (config.outDir.exists()) delete(config.outDir)

// Requires that both packr and the jre are downloaded, as per buildAndDeploy.yml, "Upload to itch.io"

// Use old version of packr - newer versions aren't Windows32-compliant
if (platform == PackrConfig.Platform.Windows32) {
config.jdk = "jdk-windows-32.zip"
Packr().pack(config)
} else {
val jdkFile =
when (platform) {
PackrConfig.Platform.Linux64 -> "jre-linux-64.tar.gz"
PackrConfig.Platform.Windows64 -> "jdk-windows-64.zip"
else -> "jre-macOS.tar.gz"
}

val platformNameForPackrCmd =
if (platform == PackrConfig.Platform.MacOS) "mac"
else platform.name.toLowerCase()

val command = "java -jar $rootDir/packr-all-4.0.0.jar" +
" --platform $platformNameForPackrCmd" +
" --jdk $jdkFile" +
" --executable UncivServer" +
" --classpath $jarFile" +
" --mainclass $mainClassName" +
" --vmargs Xmx1G " +
(if (platform == PackrConfig.Platform.MacOS) jvmArgsForMac.joinToString(" ") {
it.removePrefix("-")
}
else "") +
" --output ${config.outDir}"
command.runCommand(rootDir)
}
}

tasks.register<Zip>("zip${platformName}") {
archiveFileName.set("UncivServer-${platformName}.zip")
from(config.outDir)
destinationDirectory.set(deployFolder)
}

finalizedBy("zip${platformName}")
}
}

tasks.register<Zip>("zipLinuxFilesForJar") {
archiveFileName.set("linuxFilesForJar.zip")
from(file("linuxFilesForJar"))
destinationDirectory.set(deployFolder)
}
Loading

0 comments on commit 4290373

Please sign in to comment.