diff --git a/build.gradle.kts b/build.gradle.kts
index 60ec644d1b..4a6ec2c56a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,6 +3,7 @@ import com.unciv.build.BuildConfig.coroutinesVersion
import com.unciv.build.BuildConfig.gdxVersion
import com.unciv.build.BuildConfig.kotlinVersion
import com.unciv.build.BuildConfig.ktorVersion
+import com.unciv.build.BuildConfig.roboVMVersion
// You'll still get kotlin-reflect-1.3.70.jar in your classpath, but will no longer be used
@@ -25,6 +26,7 @@ buildscript {
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${com.unciv.build.BuildConfig.kotlinVersion}")
classpath("com.android.tools.build:gradle:8.2.2")
+ classpath("com.mobidevelop.robovm:robovm-gradle-plugin:2.3.1")
}
}
@@ -111,6 +113,18 @@ project(":android") {
}
}
+project(":ios") {
+ apply(plugin = "kotlin")
+ apply(plugin = "robovm")
+
+ dependencies {
+ "implementation"(project(":core"))
+ "implementation"("com.mobidevelop.robovm:robovm-rt:$roboVMVersion")
+ "implementation"("com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion")
+ "implementation"("com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion")
+ "implementation"("com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios")
+ }
+}
project(":core") {
apply(plugin = "kotlin")
diff --git a/buildSrc/src/main/kotlin/BuildConfig.kt b/buildSrc/src/main/kotlin/BuildConfig.kt
index 3e330c53f8..e85b649e0e 100644
--- a/buildSrc/src/main/kotlin/BuildConfig.kt
+++ b/buildSrc/src/main/kotlin/BuildConfig.kt
@@ -10,6 +10,7 @@ object BuildConfig {
const val gdxVersion = "1.12.1"
const val ktorVersion = "2.3.12"
const val coroutinesVersion = "1.8.1"
+ const val roboVMVersion = "2.3.1"
const val identifier = "com.unciv.app"
}
diff --git a/ios/Info.plist.xml b/ios/Info.plist.xml
new file mode 100644
index 0000000000..9842ae2906
--- /dev/null
+++ b/ios/Info.plist.xml
@@ -0,0 +1,50 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ ${app.name}
+ CFBundleExecutable
+ ${app.executable}
+ CFBundleIdentifier
+ ${app.id}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${app.name}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${app.version}
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ ${app.build}
+ LSRequiresIPhoneOS
+
+ UIViewControllerBasedStatusBarAppearance
+
+ UIStatusBarHidden
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ armv7
+ opengles-2
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ CFBundleIconName
+ AppIcon
+
+
diff --git a/ios/build.gradle.kts b/ios/build.gradle.kts
new file mode 100644
index 0000000000..1349fb05cd
--- /dev/null
+++ b/ios/build.gradle.kts
@@ -0,0 +1,35 @@
+import com.android.build.gradle.internal.tasks.factory.dependsOn
+import com.unciv.build.BuildConfig
+
+sourceSets {
+ main {
+ java.srcDir("src/")
+ }
+}
+
+tasks {
+ compileJava {
+ options.encoding = "UTF-8"
+ }
+ compileTestJava {
+ options.encoding = "UTF-8"
+ }
+}
+
+extra.set("mainClassName", "IOSLauncher")
+
+tasks {
+ launchIPhoneSimulator.dependsOn(build)
+ launchIPadSimulator.dependsOn(build)
+ launchIOSDevice.dependsOn(build)
+ createIPA.dependsOn(build)
+}
+
+robovm {
+ archs = "thumbv7:arm64"
+}
+
+eclipse.project {
+ name = "${BuildConfig.appName}-ios"
+ natures("org.robovm.eclipse.RoboVMNature")
+}
diff --git a/ios/data/Default-1024w-1366h@2x~ipad.png b/ios/data/Default-1024w-1366h@2x~ipad.png
new file mode 100644
index 0000000000..b175eaab6d
Binary files /dev/null and b/ios/data/Default-1024w-1366h@2x~ipad.png differ
diff --git a/ios/data/Default-375w-667h@2x.png b/ios/data/Default-375w-667h@2x.png
new file mode 100644
index 0000000000..f213ce60df
Binary files /dev/null and b/ios/data/Default-375w-667h@2x.png differ
diff --git a/ios/data/Default-414w-736h@3x.png b/ios/data/Default-414w-736h@3x.png
new file mode 100644
index 0000000000..685ba51fcb
Binary files /dev/null and b/ios/data/Default-414w-736h@3x.png differ
diff --git a/ios/data/Default-568h@2x.png b/ios/data/Default-568h@2x.png
new file mode 100644
index 0000000000..101752fe77
Binary files /dev/null and b/ios/data/Default-568h@2x.png differ
diff --git a/ios/data/Default.png b/ios/data/Default.png
new file mode 100644
index 0000000000..f1a5582a01
Binary files /dev/null and b/ios/data/Default.png differ
diff --git a/ios/data/Default@2x.png b/ios/data/Default@2x.png
new file mode 100644
index 0000000000..ca32f62fc2
Binary files /dev/null and b/ios/data/Default@2x.png differ
diff --git a/ios/data/Default@2x~ipad.png b/ios/data/Default@2x~ipad.png
new file mode 100644
index 0000000000..bb77ef073e
Binary files /dev/null and b/ios/data/Default@2x~ipad.png differ
diff --git a/ios/data/Default~ipad.png b/ios/data/Default~ipad.png
new file mode 100644
index 0000000000..855e4f2ad9
Binary files /dev/null and b/ios/data/Default~ipad.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/Contents.json b/ios/data/Media.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..9ed19e123f
--- /dev/null
+++ b/ios/data/Media.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "images" : [
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "iphone-notification-icon-20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "iphone-notification-icon-20@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "iphone-spotlight-settings-icon-29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "iphone-spotlight-settings-icon-29@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "iphone-spotlight-icon-40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "iphone-spotlight-icon-40@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iphone-app-icon-60@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iphone-app-icon-60@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "ipad-notifications-icon-20@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "ipad-notifications-icon-20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "ipad-settings-icon-29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "ipad-settings-icon-29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "ipad-spotlight-icon-40@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "ipad-spotlight-icon-40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "ipad-app-icon-76@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "ipad-app-icon-76@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "83.5x83.5",
+ "idiom" : "ipad",
+ "filename" : "ipad-pro-app-icon-83.5@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "app-store-icon-1024@1x.png",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/app-store-icon-1024@1x.png b/ios/data/Media.xcassets/AppIcon.appiconset/app-store-icon-1024@1x.png
new file mode 100644
index 0000000000..b4a987c1c5
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/app-store-icon-1024@1x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@1x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@1x.png
new file mode 100644
index 0000000000..d425b2ffc8
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@1x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@2x.png
new file mode 100644
index 0000000000..192460f2c6
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-app-icon-76@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@1x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@1x.png
new file mode 100644
index 0000000000..3ad5eb6ebf
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@1x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@2x.png
new file mode 100644
index 0000000000..0dbad4557f
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-notifications-icon-20@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-pro-app-icon-83.5@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-pro-app-icon-83.5@2x.png
new file mode 100644
index 0000000000..0710fdb954
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-pro-app-icon-83.5@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@1x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@1x.png
new file mode 100644
index 0000000000..949fbaa0bc
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@1x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@2x.png
new file mode 100644
index 0000000000..0a82ae9a80
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-settings-icon-29@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@1x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@1x.png
new file mode 100644
index 0000000000..0dbad4557f
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@1x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@2x.png
new file mode 100644
index 0000000000..4fc801a854
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/ipad-spotlight-icon-40@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@2x.png
new file mode 100644
index 0000000000..4ce7690c23
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@3x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@3x.png
new file mode 100644
index 0000000000..a0a4ae42cb
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-app-icon-60@3x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@2x.png
new file mode 100644
index 0000000000..0dbad4557f
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@3x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@3x.png
new file mode 100644
index 0000000000..b4fc090a26
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-notification-icon-20@3x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@2x.png
new file mode 100644
index 0000000000..4fc801a854
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@3x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@3x.png
new file mode 100644
index 0000000000..4ce7690c23
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-icon-40@3x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@2x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@2x.png
new file mode 100644
index 0000000000..0a82ae9a80
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@2x.png differ
diff --git a/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@3x.png b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@3x.png
new file mode 100644
index 0000000000..eb0446e0e1
Binary files /dev/null and b/ios/data/Media.xcassets/AppIcon.appiconset/iphone-spotlight-settings-icon-29@3x.png differ
diff --git a/ios/data/Media.xcassets/Contents.json b/ios/data/Media.xcassets/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/ios/data/Media.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ios/robovm.properties b/ios/robovm.properties
new file mode 100644
index 0000000000..e12bf5565f
--- /dev/null
+++ b/ios/robovm.properties
@@ -0,0 +1,6 @@
+app.version=1.0
+app.id=com.mygdx.game
+app.mainclass=com.unciv.game.IOSLauncher
+app.executable=IOSLauncher
+app.build=1
+app.name=my-gdx-game
diff --git a/ios/robovm.xml b/ios/robovm.xml
new file mode 100644
index 0000000000..ee0da2d5c9
--- /dev/null
+++ b/ios/robovm.xml
@@ -0,0 +1,47 @@
+
+ ${app.executable}
+ ${app.mainclass}
+ ios
+ thumbv7
+ ios
+ Info.plist.xml
+
+
+ ../android/assets
+
+ **
+
+ true
+
+
+ data
+
+
+
+ com.badlogic.gdx.scenes.scene2d.ui.*
+ com.badlogic.gdx.graphics.g3d.particles.**
+ com.android.okhttp.HttpHandler
+ com.android.okhttp.HttpsHandler
+ com.android.org.conscrypt.**
+ com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
+ com.android.org.bouncycastle.jcajce.provider.keystore.BC$Mappings
+ com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi
+ com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std
+ com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
+ com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL
+ org.apache.harmony.security.provider.cert.DRLCertFactory
+ org.apache.harmony.security.provider.crypto.CryptoProvider
+
+
+ z
+
+
+ UIKit
+ OpenGLES
+ QuartzCore
+ CoreGraphics
+ OpenAL
+ AudioToolbox
+ AVFoundation
+
+
diff --git a/ios/src/com/unciv/app/IOSLauncher.java b/ios/src/com/unciv/app/IOSLauncher.java
new file mode 100644
index 0000000000..f56b442e4f
--- /dev/null
+++ b/ios/src/com/unciv/app/IOSLauncher.java
@@ -0,0 +1,21 @@
+package com.unciv.app;
+
+import com.badlogic.gdx.backends.iosrobovm.IOSApplication;
+import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration;
+
+import org.robovm.apple.foundation.NSAutoreleasePool;
+import org.robovm.apple.uikit.UIApplication;
+
+class IOSLauncher extends IOSApplication.Delegate {
+ @Override
+ protected IOSApplication createApplication() {
+ IOSApplicationConfiguration config = new IOSApplicationConfiguration();
+ return new IOSApplication(new com.unciv.UncivGame(), config);
+ }
+
+ public static void main(String[] argv) {
+ NSAutoreleasePool pool = new NSAutoreleasePool();
+ UIApplication.main(argv, null, IOSLauncher.class);
+ pool.close();
+ }
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 9b0f76ae3d..76c2c65126 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1 +1 @@
-include("desktop", "android", "core", "tests", "server")
+include("desktop", "android", "ios", "core", "tests", "server")