diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index e0e89b339ff..f73a8cd9d8e 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -14,10 +14,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: 'maven' server-id: cardforge-repo diff --git a/.github/workflows/publish-android.yml b/.github/workflows/publish-android.yml index 02d48aaf85c..39ef368da3c 100644 --- a/.github/workflows/publish-android.yml +++ b/.github/workflows/publish-android.yml @@ -20,10 +20,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '17' distribution: 'temurin' cache: 'maven' server-id: cardforge-repo @@ -31,20 +31,20 @@ jobs: server-password: ${{ secrets.FTP_PASSWORD }} settings-path: ${{ github.workspace }} # location for the settings.xml file - - name: Install old maven (3.6.3) + - name: Install old maven (3.8.1) run: | - curl -o apache-maven-3.6.3-bin.tar.gz https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz - tar xf apache-maven-3.6.3-bin.tar.gz - export PATH=$PWD/apache-maven-3.6.3/bin:$PATH - export MAVEN_HOME=$PWD/apache-maven-3.6.3 + curl -o apache-maven-3.8.1-bin.tar.gz https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz + tar xf apache-maven-3.8.1-bin.tar.gz + export PATH=$PWD/apache-maven-3.8.1/bin:$PATH + export MAVEN_HOME=$PWD/apache-maven-3.8.1 mvn --version - name: Install android SDK uses: maxim-lobanov/setup-android-tools@v1 with: packages: | - platforms;android-26 - build-tools;30.0.3 + platforms;android-35 + build-tools;35.0.0 - name: Install virtual framebuffer (if not available) to allow running GUI on a headless server run: | @@ -83,7 +83,7 @@ jobs: - name: Build/Install/Publish to GitHub Packages Apache Maven run: | export _JAVA_OPTIONS="-Xmx2g" - mvn -U -B -P android-release-build,android-release-sign,android-release-upload install -e -Dsign.keystore=forge.keystore -Dsign.alias=Forge -Dsign.storepass=${{ secrets.SIGN_STORE_PASS }} -Dsign.keypass=${{ secrets.SIGN_STORE_PASS }} -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} -Dandroid.sdk.path=/usr/local/lib/android/sdk -Dandroid.buildToolsVersion=30.0.3 -Dmaven.test.skip=true + mvn -U -B -P android-release-build,android-release-upload install -e -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} -Dandroid.sdk.path=/usr/local/lib/android/sdk -Dandroid.buildToolsVersion=35.0.0 -Dmaven.test.skip=true env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/snapshots-android.yml b/.github/workflows/snapshots-android.yml index 1bdf3784cbf..04fdf794e11 100644 --- a/.github/workflows/snapshots-android.yml +++ b/.github/workflows/snapshots-android.yml @@ -29,10 +29,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '17' distribution: 'temurin' cache: 'maven' server-id: cardforge-repo @@ -40,19 +40,17 @@ jobs: server-password: ${{ secrets.FTP_PASSWORD }} settings-path: ${{ github.workspace }} # location for the settings.xml file - - name: Install old maven (3.6.3) + - name: Install old maven (3.8.1) run: | - curl -o apache-maven-3.6.3-bin.tar.gz https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz - tar xf apache-maven-3.6.3-bin.tar.gz - export PATH=$PWD/apache-maven-3.6.3/bin:$PATH - export MAVEN_HOME=$PWD/apache-maven-3.6.3 + curl -o apache-maven-3.8.1-bin.tar.gz https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz + tar xf apache-maven-3.8.1-bin.tar.gz + export PATH=$PWD/apache-maven-3.8.1/bin:$PATH + export MAVEN_HOME=$PWD/apache-maven-3.8.1 mvn --version - name: Set Up Android tools run: | - JAVA_HOME=${JAVA_HOME_11_X64} ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platform-tools" - JAVA_HOME=${JAVA_HOME_11_X64} ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT --install "platforms;android-26" - JAVA_HOME=${JAVA_HOME_11_X64} ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT --install "build-tools;30.0.3" + JAVA_HOME=${JAVA_HOME_17_X64} ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT --install "build-tools;35.0.0" "platform-tools" "platforms;android-35" - name: Install virtual framebuffer (if not available) to allow running GUI on a headless server run: | @@ -91,10 +89,10 @@ jobs: - name: Build/Install/Publish to GitHub Packages Apache Maven run: | export _JAVA_OPTIONS="-Xmx2g" - d=$(date +%m-%d) + d=$(date +%m.%d) # Replace date in forge-gui-mobile/src/forge/Forge.java - sed -i -e "s/-SNAPSHOT/-SNAPSHOT-${d}/g" forge-gui-mobile/src/forge/Forge.java - mvn -U -B -P android-release-build,android-release-sign install -e -Dsign.keystore=forge.keystore -Dsign.alias=Forge -Dsign.storepass=${{ secrets.SIGN_STORE_PASS }} -Dsign.keypass=${{ secrets.SIGN_STORE_PASS }} -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} -Dandroid.sdk.path=/usr/local/lib/android/sdk -Dandroid.buildToolsVersion=30.0.3 -Dmaven.test.skip=true + # sed -i -e "s/-SNAPSHOT/-SNAPSHOT-${d}/g" forge-gui-mobile/src/forge/Forge.java + mvn -U -B -P android-release-build install -e -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} -Dandroid.sdk.path=/usr/local/lib/android/sdk -Dandroid.buildToolsVersion=35.0.0 -Dmaven.test.skip=true mkdir -p forge-gui-android/target/upload mv forge-gui-android/target/*-signed-aligned.apk forge-gui-android/target/upload/ mv forge-gui-android/target/assets.zip forge-gui-android/target/upload/ @@ -107,7 +105,7 @@ jobs: version=$(echo "$apk_file" | grep -oP 'forge-android-\K\d+\.\d+\.\d+-SNAPSHOT' | sed 's/-signed-aligned.apk//') echo "APK File: $apk_file" echo "Version: $version" - mv *.apk "forge-android-$version-$d-signed-aligned.apk" + # mv *.apk "forge-android-$version-$d-signed-aligned.apk" echo "$version-$d" > version.txt else diff --git a/.github/workflows/snapshots-pc.yml b/.github/workflows/snapshots-pc.yml index 8d317fa8f39..11a5a7dac2b 100644 --- a/.github/workflows/snapshots-pc.yml +++ b/.github/workflows/snapshots-pc.yml @@ -23,10 +23,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: 'maven' server-id: cardforge-repo @@ -45,7 +45,7 @@ jobs: run: | export DISPLAY=":1" Xvfb :1 -screen 0 800x600x8 & - mvn -U -B clean -P windows-linux install -T 1C -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} + mvn -U -B clean -P windows-linux install -T 1C -Dcardforge-repo.username=${{ secrets.FTP_USERNAME }} -Dcardforge-repo.password=${{ secrets.FTP_PASSWORD }} env: GITHUB_TOKEN: ${{ github.token }} @@ -55,13 +55,27 @@ jobs: - name: Rename before upload run: | - mkdir tarball + mkdir izpack # If this works just gotta figure out how to append datetime - mv /home/runner/.m2/repository/forge/forge-gui-desktop/*/*.bz2 tarball/ - cd tarball - out="$(basename -s .tar.bz2 *)" - d=$(date +%m-%d) - mv "${out}.tar.bz2" "${out}-${d}.tar.bz2" + mv /home/runner/.m2/repository/forge/forge-installer/*/*.jar izpack/ + cd izpack + d=$(date +%m.%d) + ls + # rename files + jar_file=$(find . -maxdepth 1 -type f -name '*.jar' -print -quit) + if [ -n "$jar_file" ]; then + outj="$(basename -s .jar *)" + mv "${outj}.jar" "${outj}-${d}.jar" + else + echo "No .jar files found in the specified folder." + fi + bz2_file=$(find . -maxdepth 1 -type f -name '*.bz2' -print -quit) + if [ -n "$bz2_file" ]; then + outb="$(basename -s .tar.bz2 *)" + mv "${outb}.tar.bz2" "${outb}-${d}.tar.bz2" + else + echo "No .bz2 files found in the specified folder." + fi - name: 📂 Sync files uses: SamKirkland/FTP-Deploy-Action@v4.3.4 @@ -69,10 +83,9 @@ jobs: server: ftp.cardforge.org username: ${{ secrets.FTP_USERNAME }} password: ${{ secrets.FTP_PASSWORD }} - local-dir: tarball/ + local-dir: izpack/ server-dir: downloads/dailysnapshots/ exclude: | - *.jar *.pom *.repositories *.xml diff --git a/.github/workflows/test-android-build.yml b/.github/workflows/test-android-build.yml new file mode 100644 index 00000000000..b25cf539f38 --- /dev/null +++ b/.github/workflows/test-android-build.yml @@ -0,0 +1,60 @@ +name: Test Android build + +on: + push: + paths: [ 'forge-gui-android/**' ] + pull_request: + paths: [ 'forge-gui-android/**' ] + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + deployments: write + packages: write + strategy: + matrix: + java: [ '17' ] + name: Test with Java ${{ matrix.Java }} + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: ${{ matrix.java }} + distribution: 'temurin' + cache: 'maven' + + - name: Install old maven (3.8.1) + run: | + curl -o apache-maven-3.8.1-bin.tar.gz https://archive.apache.org/dist/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz + tar xf apache-maven-3.8.1-bin.tar.gz + export PATH=$PWD/apache-maven-3.8.1/bin:$PATH + export MAVEN_HOME=$PWD/apache-maven-3.8.1 + mvn --version + + - name: Set Up Android tools + run: | + JAVA_HOME=${JAVA_HOME_17_X64} ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT --install "build-tools;35.0.0" "platform-tools" "platforms;android-35" + + - name: Install Android maven plugin + run: | + mkdir -p ~/.m2/repository/com/simpligility/maven/plugins/android-maven-plugin/4.6.2 + cd ~/.m2/repository/com/simpligility/maven/plugins/android-maven-plugin/4.6.2 + curl -L -o android-maven-plugin-4.6.2.jar https://github.com/Card-Forge/android-maven-plugin/releases/download/4.6.2/android-maven-plugin-4.6.2.jar + curl -L -o android-maven-plugin-4.6.2.pom https://github.com/Card-Forge/android-maven-plugin/releases/download/4.6.2/android-maven-plugin-4.6.2.pom + #mvn install:install-file -Dfile=android-maven-plugin-4.6.2.jar -DgroupId=com.simpligility.maven.plugins -DartifactId=android-maven-plugin -Dversion=4.6.2 -Dpackaging=jar + cd - + mvn install -Dmaven.test.skip=true + mvn dependency:tree + + - name: Install virtual framebuffer (if not available) to allow running GUI on a headless server + run: command -v Xvfb >/dev/null 2>&1 || { sudo apt update && sudo apt install -y xvfb; } + + - name: Run build in virtual framebuffer + run: | + export DISPLAY=":1" + Xvfb :1 -screen 0 800x600x8 & + mvn -U -B -P android-test-build verify -e -T 1C -Dandroid.sdk.path=$ANDROID_SDK_ROOT -Dandroid.buildToolsVersion=35.0.0 -Dmaven.test.skip=true diff --git a/.github/workflows/test-build.yaml b/.github/workflows/test-build.yaml index 48949da0e0c..59aaaffdc04 100644 --- a/.github/workflows/test-build.yaml +++ b/.github/workflows/test-build.yaml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '11' ] + java: [ '17' ] name: Test with Java ${{ matrix.Java }} steps: - uses: actions/checkout@v3 @@ -26,4 +26,4 @@ jobs: run: | export DISPLAY=":1" Xvfb :1 -screen 0 800x600x8 & - mvn -U -B clean -P windows-linux test + mvn -U -B clean test diff --git a/.github/workflows/test-maven-settings.yml b/.github/workflows/test-maven-settings.yml index 8e2f3c044dc..a6bc0679807 100644 --- a/.github/workflows/test-maven-settings.yml +++ b/.github/workflows/test-maven-settings.yml @@ -14,10 +14,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: 'maven' server-id: cardforge-repo diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f10cf418bab..9b9bb5d4c3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Dev instructions here: [Getting Started](https://github.com/Card-Forge/forge/wik ## Requirements / Tools - you favourite Java IDE (IntelliJ, Eclipse, VSCodium, Emacs, Vi...) -- Java JDK 8 or later (some IDEs such as Eclipse require JDK11+, whereas the Android build currently only works with JDK8) +- Java JDK 17 or later - Git - Git client (optional) - Maven @@ -46,9 +46,9 @@ At this time, Eclipse is not the recommended IDE for Forge development. - Clone your forked repo to your local machine. -- Make sure the Java SDK is installed -- not just the JRE. Java 8 or newer required. If you execute `java -version` at the shell or command prompt, it should report version 1.8 or later. +- Make sure the Java SDK is installed -- not just the JRE. Java 17 or newer required. If you execute `java -version` at the shell or command prompt, it should report version 17 or later. -- Install Eclipse 2018-12 or later for Java. Launch it. +- Install Eclipse 2021-12 or later for Java. Launch it. - Create a workspace. Go to the workbench. Right-click inside of Package Explorer > Import... > Maven > Existing Maven Projects > Navigate to root path of the local forge repo and ensure everything is checked > Finish. @@ -79,16 +79,15 @@ This is the configuration used for doing mobile development using the Windows / ### Eclipse / Android SDK Integration -Google no longer supports Android SDK releases for Eclipse. That said, it is still possible to build and debug Android platforms. +Google no longer supports Android SDK releases for Eclipse. use IntelliJ. #### Android SDK -Reference SO for obtaining a specific release: https://stackoverflow.com/questions/27043522/where-can-i-download-an-older-version-of-the-android-sdk +TBD ##### Windows -Download the following archived version of the Android SDK: http://dl-ssl.google.com/android/repository/tools_r25.2.3-windows.zip. Install it somewhere on your machine. This is referenced -in the following instructions as your 'Android SDK Install' path. +TBD ##### Linux / Mac OSX @@ -96,68 +95,30 @@ TBD #### Android Plugin for Eclipse -Google's last plugin release does not work completely with target's running Android 7.0 or later. Download the ADT-24.2.0-20160729.zip plugin -from: https://github.com/khaledev/ADT/releases - -In Eclipse go to: Help > Install New Software... > Add > Name: ADT Update, Click on the "Archive:" button and navigate to the downloaded ADT-24.2.0-20160729.zip file > Add. Install all "Developer Tools". Eclipse -should restart and prompt you to run the SDK Manager. Launch it and continue to the next steps below. +TBD #### Android Platform -In Eclipse, if the SDK Manager is not already running, go to Window > Android SDK Manager. Install the following options / versions: +In Intellij, if the SDK Manager is not already running, go to Tools > Android > Android SDK Manager. Install the following options / versions: -- Android SDK Build-tools 26.0.1 -- Android 8.0.0 (API 26) SDK Platform -- Google USB Driver (in case your phone is not detected by ADB) - -Note that this will populate additional tools in the Android SDK install path extracted above. +- Android SDK Build-tools 35.0.0 +- Android 15 (API 35) SDK Platform #### Proguard update -The Proguard included with the Android SDK Build-tools is outdated and does not work with Java 1.8. Download Proguard 6.0.3 or later (last tested with 7.0.1) from https://github.com/Guardsquare/proguard -- Go to the Android SDK install path. Rename the tools/proguard/ path to tools/proguard-4.7/. - -- Extract your Proguard version to the Android SDK install path under tools/. You will need to either rename the dir proguard- to proguard/ or, if your filesystem supports it, use a symbolic link (the later is highly recommended), such as `ln -s proguard proguard-`. +Standalone Proguard 7.6.0 is included with the project (proguard.jar) under forge-gui-android > tools and supports up to Java 23 (latest android uses Java 17). #### Android Build -The Eclipse plug-ins do NOT support building things for Android. They do however allow you to use the debugger so you can still set breakpoints and trace -things out. The steps below show how to generate a debug Android build. - -1) Create a Maven build for the forge top-level project. Right-click on the forge project. Run as.. > Maven build... - - On the Main tab, set Goals: clean install - -2) Run forge Maven build. If everything built, you should see "BUILD SUCCESS" in the Console View. - -3) Right-click on the forge-gui-android project. Run as.. > Maven build... - - - On the Main tab, set Goals: install, Profiles: android-debug - - On the Environment tab, you may need to define the variable ANDROID_HOME with the value containing the path to your Android SDK installation. For example, Variable: ANDROID_HOME, Value: Your Android SDK install path here. - -4) Run the forge-gui-android Maven build. This may take a few minutes. If everything worked, you should see "BUILD SUCCESS" in the Console View. - -Assuming you got this far, you should have an Android forge-android-[version].apk in the forge-gui-android/target path. +TBD #### Android Deploy -You'll need to have the Android SDK install path platform-tools/ path in your command search path to easily deploy builds. - -- Open a command prompt. Navigate to the forge-gui-android/target/ path. - -- Connect your Android device to your dev machine. - -- Ensure the device is visible using `adb devices` - -- Remove the old Forge install if present: `adb uninstall forge.app` - -- Install the new apk: `adb install forge-android-[version].apk` +TBD #### Android Debugging -Assuming the apk is installed, launch it from the device. - -In Eclipse, launch the DDMS. Window > Perspective > Open Perspective > Other... > DDMS. You should see the forge app in the list. Highlight the app, click on the green debug button and a -green debug button should appear next to the app's name. You can now set breakpoints and step through the source code. +TBD ### Windows / Linux SNAPSHOT build diff --git a/adventure-editor/pom.xml b/adventure-editor/pom.xml new file mode 100644 index 00000000000..542d52eb86c --- /dev/null +++ b/adventure-editor/pom.xml @@ -0,0 +1,117 @@ + + + + forge + forge + ${revision} + + 4.0.0 + + adventure-editor + jar + Adventure Editor + + + src/main/java + + + ${project.basedir} + + **/gear.gif + + + + adventure-editor + + + maven-compiler-plugin + + 17 + 17 + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + package + + replace + + + + + ${basedir}/${configSourceDirectory} + adventure-editor.sh, adventure-editor.command, adventure-editor.cmd + ${project.build.directory} + . + false + + + $project.build.finalName$ + ${project.build.finalName}-jar-with-dependencies.jar + + + + + + + maven-assembly-plugin + + false + + jar-with-dependencies + + + + forge.adventure.Main + true + + + splash/gear.gif + + + + + + make-assembly + + package + + + single + + + + + + + + + forge + forge-gui + ${project.version} + compile + + + forge + forge-gui-mobile + ${project.version} + compile + + + org.jetbrains + annotations + 26.0.1 + compile + + + + + 17 + 17 + + + diff --git a/forge-adventure/sentry.properties b/adventure-editor/sentry.properties similarity index 100% rename from forge-adventure/sentry.properties rename to adventure-editor/sentry.properties diff --git a/adventure-editor/splash/gear.gif b/adventure-editor/splash/gear.gif new file mode 100644 index 00000000000..1180c8264fb Binary files /dev/null and b/adventure-editor/splash/gear.gif differ diff --git a/adventure-editor/src/main/config/adventure-editor.cmd b/adventure-editor/src/main/config/adventure-editor.cmd new file mode 100644 index 00000000000..39ee18ff370 --- /dev/null +++ b/adventure-editor/src/main/config/adventure-editor.cmd @@ -0,0 +1,24 @@ +@echo off + +pushd %~dp0 + +java -version 1>nul 2>nul || ( + echo no java installed + popd + exit /b 2 +) +for /f tokens^=2^ delims^=.-_^+^" %%j in ('java -fullversion 2^>^&1') do set "jver=%%j" + +if %jver% LEQ 16 ( + echo unsupported java + popd + exit /b 2 +) + +if %jver% GEQ 17 ( + java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ + popd + exit /b 0 +) + +popd \ No newline at end of file diff --git a/forge-adventure/src/main/config/forge-adventure-editor.command b/adventure-editor/src/main/config/adventure-editor.command similarity index 100% rename from forge-adventure/src/main/config/forge-adventure-editor.command rename to adventure-editor/src/main/config/adventure-editor.command diff --git a/forge-adventure/src/main/config/forge-adventure-editor.sh b/adventure-editor/src/main/config/adventure-editor.sh similarity index 100% rename from forge-adventure/src/main/config/forge-adventure-editor.sh rename to adventure-editor/src/main/config/adventure-editor.sh diff --git a/forge-adventure/src/main/config/forge-adventure-editor.ico b/adventure-editor/src/main/config/forge-adventure-editor.ico similarity index 100% rename from forge-adventure/src/main/config/forge-adventure-editor.ico rename to adventure-editor/src/main/config/forge-adventure-editor.ico diff --git a/forge-adventure/src/main/config/forge-adventure.ico b/adventure-editor/src/main/config/forge-adventure.ico similarity index 100% rename from forge-adventure/src/main/config/forge-adventure.ico rename to adventure-editor/src/main/config/forge-adventure.ico diff --git a/forge-adventure/src/main/config/forge.ico b/adventure-editor/src/main/config/forge.ico similarity index 100% rename from forge-adventure/src/main/config/forge.ico rename to adventure-editor/src/main/config/forge.ico diff --git a/forge-adventure/src/main/java/forge/adventure/Main.java b/adventure-editor/src/main/java/forge/adventure/Main.java similarity index 88% rename from forge-adventure/src/main/java/forge/adventure/Main.java rename to adventure-editor/src/main/java/forge/adventure/Main.java index 55de46c1215..bec6ae5a4ca 100644 --- a/forge-adventure/src/main/java/forge/adventure/Main.java +++ b/adventure-editor/src/main/java/forge/adventure/Main.java @@ -16,7 +16,6 @@ public class Main { public static void main(String[] args) { GuiBase.setInterface(new GuiMobile(Files.exists(Paths.get("./res"))?"./":"../forge-gui/")); GuiBase.setDeviceInfo("", "", 0, 0); - Config.instance(); - new EditorMainWindow(); + new EditorMainWindow(Config.instance()); } } diff --git a/forge-adventure/src/main/java/forge/adventure/editor/ActionEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/ActionEdit.java similarity index 95% rename from forge-adventure/src/main/java/forge/adventure/editor/ActionEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/ActionEdit.java index aa509bcb56f..49b70994bf0 100644 --- a/forge-adventure/src/main/java/forge/adventure/editor/ActionEdit.java +++ b/adventure-editor/src/main/java/forge/adventure/editor/ActionEdit.java @@ -2,7 +2,9 @@ package forge.adventure.editor; import forge.adventure.data.DialogData; -import javax.swing.*; +import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -158,9 +160,9 @@ public class ActionEdit extends FormPanel { advanceQuestFlag.setText(currentData.advanceQuestFlag); advanceCharacterFlag.setText(currentData.advanceCharacterFlag); - battleWithActorID.setText("" + currentData.battleWithActorID); - activateObjectID.setText("" + currentData.battleWithActorID); - deleteMapObject.setText("" + currentData.deleteMapObject); + battleWithActorID.setText(String.valueOf(currentData.battleWithActorID)); + activateObjectID.setText(String.valueOf(currentData.battleWithActorID)); + deleteMapObject.setText(String.valueOf(currentData.deleteMapObject)); setColorIdentity.setText(currentData.setColorIdentity); addLife.getModel().setValue(currentData.addLife); addReputation.getModel().setValue(currentData.addMapReputation); diff --git a/forge-adventure/src/main/java/forge/adventure/editor/ActionEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/ActionEditor.java similarity index 61% rename from forge-adventure/src/main/java/forge/adventure/editor/ActionEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/ActionEditor.java index 462fc38624b..ed60e5a9ce6 100644 --- a/forge-adventure/src/main/java/forge/adventure/editor/ActionEditor.java +++ b/adventure-editor/src/main/java/forge/adventure/editor/ActionEditor.java @@ -2,20 +2,27 @@ package forge.adventure.editor; import forge.adventure.data.DialogData; -import javax.swing.*; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JToolBar; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; import java.awt.event.ActionListener; /** * Editor class to edit configuration, maybe moved or removed */ -public class ActionEditor extends JComponent{ +public class ActionEditor extends JComponent { DefaultListModel model = new DefaultListModel<>(); JList list = new JList<>(model); JToolBar toolBar = new JToolBar("toolbar"); - ActionEdit edit=new ActionEdit(); + ActionEdit edit = new ActionEdit(); boolean updating; @@ -25,43 +32,43 @@ public class ActionEditor extends JComponent{ JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if(!(value instanceof DialogData.ActionData)) + if (!(value instanceof DialogData.ActionData)) return label; - DialogData.ActionData action=(DialogData.ActionData) value; + /*DialogData.ActionData action=(DialogData.ActionData) value; StringBuilder builder=new StringBuilder(); -// if(action.type==null||action.type.isEmpty()) + if(action.type==null||action.type.isEmpty()) builder.append("Action"); -// else -// builder.append(action.type); - label.setText(builder.toString()); + else + builder.append(action.type);*/ + label.setText("Action"); return label; } } - public void addButton(String name, ActionListener action) - { - JButton newButton=new JButton(name); + + public void addButton(String name, ActionListener action) { + JButton newButton = new JButton(name); newButton.addActionListener(action); toolBar.add(newButton); } - public ActionEditor() - { + public ActionEditor() { list.setCellRenderer(new RewardDataRenderer()); list.addListSelectionListener(e -> ActionEditor.this.updateEdit()); addButton("add", e -> ActionEditor.this.addAction()); addButton("remove", e -> ActionEditor.this.remove()); addButton("copy", e -> ActionEditor.this.copy()); - BorderLayout layout=new BorderLayout(); + BorderLayout layout = new BorderLayout(); setLayout(layout); add(list, BorderLayout.LINE_START); add(toolBar, BorderLayout.PAGE_START); - add(edit,BorderLayout.CENTER); + add(edit, BorderLayout.CENTER); edit.addChangeListener(e -> emitChanged()); } + protected void emitChanged() { if (updating) return; @@ -73,63 +80,64 @@ public class ActionEditor extends JComponent{ } } } + private void copy() { - int selected=list.getSelectedIndex(); - if(selected<0) + int selected = list.getSelectedIndex(); + if (selected < 0) return; - DialogData.ActionData data=new DialogData.ActionData(model.get(selected)); - model.add(model.size(),data); + DialogData.ActionData data = new DialogData.ActionData(model.get(selected)); + model.add(model.size(), data); } private void updateEdit() { - int selected=list.getSelectedIndex(); - if(selected<0) + int selected = list.getSelectedIndex(); + if (selected < 0) return; edit.setCurrentAction(model.get(selected)); } - void addAction() - { - DialogData.ActionData data=new DialogData.ActionData(); - model.add(model.size(),data); + void addAction() { + DialogData.ActionData data = new DialogData.ActionData(); + model.add(model.size(), data); } - void remove() - { - int selected=list.getSelectedIndex(); - if(selected<0) + + void remove() { + int selected = list.getSelectedIndex(); + if (selected < 0) return; model.remove(selected); } + public void setAction(DialogData.ActionData[] actions) { model.clear(); - if(actions==null) + if (actions == null) return; - for (int i=0;i 0){ + for (int i = 0; i < actions.length; i++) { + if (actions[i].grantRewards.length > 0) { continue; //handled in separate editor and joined in on save, will get duplicated if it appears here } - model.add(i,actions[i]); + model.add(i, actions[i]); } } public DialogData.ActionData[] getAction() { - DialogData.ActionData[] action= new DialogData.ActionData[model.getSize()]; - for(int i=0;i EventQueue.invokeLater(() -> { + newButton.setEnabled(false); + try { + CodeSource codeSource = EditorMainWindow.class.getProtectionDomain().getCodeSource(); + File jarFile = new File(codeSource.getLocation().toURI().getPath()); + String jarDir = jarFile.getParentFile().getPath(); + Desktop.getDesktop().open(new File(jarDir + "/gdx-particle-editor.jar")); + } catch (Exception ex) { + new ErrorDialog("Error", ex.getMessage()); + newButton.setEnabled(true); + } + })); + JButton quit = new JButton("Quit"); + quit.addActionListener(e -> System.exit(0)); + toolBar.add(newButton); + toolBar.add(quit); + setLayout(layout); + toolBar.setFloatable(false); + add(toolBar, BorderLayout.NORTH); + add(tabs, BorderLayout.CENTER); + tabs.addTab("World", worldEditor); + tabs.addTab("POI", new PointOfInterestEditor()); + tabs.addTab("Items", new ItemsEditor()); + tabs.addTab("Enemies", new EnemyEditor()); + tabs.addTab("Quests", new QuestEditor()); + setSize(config.getSettingData().width, config.getSettingData().height); + setLocationRelativeTo(null); + setVisible(true); + } + + static class ErrorDialog { + public ErrorDialog(String title, String message) { + List options = new ArrayList<>(); + JButton ok = new JButton("OK"); + options.add(ok); + JOptionPane pane = new JOptionPane(message, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options.toArray()); + JDialog dlg = pane.createDialog(JOptionPane.getRootFrame(), title); + ok.addActionListener(e -> { + dlg.setVisible(false); + System.exit(0); + }); + dlg.setResizable(false); + dlg.setVisible(true); + } + } +} diff --git a/forge-adventure/src/main/java/forge/adventure/editor/EffectEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/EffectEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/EffectEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/EffectEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/EnemyEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/EnemyEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/EnemyEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/EnemyEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/EnemyEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/EnemyEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/EnemyEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/EnemyEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/FilePicker.java b/adventure-editor/src/main/java/forge/adventure/editor/FilePicker.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/FilePicker.java rename to adventure-editor/src/main/java/forge/adventure/editor/FilePicker.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/FloatSpinner.java b/adventure-editor/src/main/java/forge/adventure/editor/FloatSpinner.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/FloatSpinner.java rename to adventure-editor/src/main/java/forge/adventure/editor/FloatSpinner.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/FormPanel.java b/adventure-editor/src/main/java/forge/adventure/editor/FormPanel.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/FormPanel.java rename to adventure-editor/src/main/java/forge/adventure/editor/FormPanel.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/IntSpinner.java b/adventure-editor/src/main/java/forge/adventure/editor/IntSpinner.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/IntSpinner.java rename to adventure-editor/src/main/java/forge/adventure/editor/IntSpinner.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/ItemEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/ItemEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/ItemEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/ItemEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/ItemsEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/ItemsEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/ItemsEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/ItemsEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/PointOfInterestEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/PointOfInterestEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/PointOfInterestEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/PointOfInterestEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/PointOfInterestEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/PointOfInterestEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/PointOfInterestEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/PointOfInterestEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestController.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestController.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestController.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestController.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestEdit.java similarity index 96% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestEdit.java index 53731c93a78..3e2657a49e0 100644 --- a/forge-adventure/src/main/java/forge/adventure/editor/QuestEdit.java +++ b/adventure-editor/src/main/java/forge/adventure/editor/QuestEdit.java @@ -2,10 +2,23 @@ package forge.adventure.editor; import forge.adventure.data.AdventureQuestData; -import javax.swing.*; +import javax.swing.AbstractAction; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.KeyStroke; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Enumeration; @@ -285,7 +298,7 @@ public class QuestEdit extends FormPanel { } setVisible(true); updating=true; - id.setText(currentData.getID() + ""); + id.setText(String.valueOf(currentData.getID())); name.setText(currentData.name); description.setText(currentData.description); synopsis.setText(currentData.synopsis); diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestStageEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestStageEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestStageEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestStageEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestStageEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestStageEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestStageEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestStageEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/QuestTagSelector.java b/adventure-editor/src/main/java/forge/adventure/editor/QuestTagSelector.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/QuestTagSelector.java rename to adventure-editor/src/main/java/forge/adventure/editor/QuestTagSelector.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/RewardEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/RewardEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/RewardEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/RewardEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/RewardsEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/RewardsEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/RewardsEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/RewardsEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/StructureEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/StructureEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/StructureEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/StructureEditor.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/SwingAtlas.java b/adventure-editor/src/main/java/forge/adventure/editor/SwingAtlas.java similarity index 98% rename from forge-adventure/src/main/java/forge/adventure/editor/SwingAtlas.java rename to adventure-editor/src/main/java/forge/adventure/editor/SwingAtlas.java index 6241b824add..eeeccf80b20 100644 --- a/forge-adventure/src/main/java/forge/adventure/editor/SwingAtlas.java +++ b/adventure-editor/src/main/java/forge/adventure/editor/SwingAtlas.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.Array; import javax.imageio.ImageIO; -import javax.swing.*; +import javax.swing.ImageIcon; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; @@ -65,7 +65,7 @@ public class SwingAtlas { return new ImageIcon(img.getSubimage(sprite.left,sprite.top, sprite.width, sprite.height).getScaledInstance((int) (imageSize*(sprite.width/(float)sprite.height)),imageSize,SCALE_FAST)); } - catch (IOException e) + catch (Exception e) { return null; } diff --git a/forge-adventure/src/main/java/forge/adventure/editor/SwingAtlasPreview.java b/adventure-editor/src/main/java/forge/adventure/editor/SwingAtlasPreview.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/SwingAtlasPreview.java rename to adventure-editor/src/main/java/forge/adventure/editor/SwingAtlasPreview.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/TerrainsEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/TerrainsEditor.java similarity index 89% rename from forge-adventure/src/main/java/forge/adventure/editor/TerrainsEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/TerrainsEditor.java index 3af4f12d352..6fe0070f0b0 100644 --- a/forge-adventure/src/main/java/forge/adventure/editor/TerrainsEditor.java +++ b/adventure-editor/src/main/java/forge/adventure/editor/TerrainsEditor.java @@ -3,10 +3,17 @@ package forge.adventure.editor; import forge.adventure.data.BiomeData; import forge.adventure.data.BiomeTerrainData; -import javax.swing.*; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JToolBar; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; import java.awt.event.ActionListener; /** @@ -29,11 +36,11 @@ public class TerrainsEditor extends JComponent{ if(!(value instanceof BiomeTerrainData)) return label; BiomeTerrainData terrainData=(BiomeTerrainData) value; - StringBuilder builder=new StringBuilder(); + /*StringBuilder builder=new StringBuilder(); builder.append("Terrain"); builder.append(" "); - builder.append(terrainData.spriteName); - label.setText(builder.toString()); + builder.append(terrainData.spriteName);*/ + label.setText("Terrain " + terrainData.spriteName); return label; } } diff --git a/forge-adventure/src/main/java/forge/adventure/editor/TextListEdit.java b/adventure-editor/src/main/java/forge/adventure/editor/TextListEdit.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/TextListEdit.java rename to adventure-editor/src/main/java/forge/adventure/editor/TextListEdit.java diff --git a/forge-adventure/src/main/java/forge/adventure/editor/WorldEditor.java b/adventure-editor/src/main/java/forge/adventure/editor/WorldEditor.java similarity index 100% rename from forge-adventure/src/main/java/forge/adventure/editor/WorldEditor.java rename to adventure-editor/src/main/java/forge/adventure/editor/WorldEditor.java diff --git a/adventure-editor/tools/gdx-particle-editor.jar b/adventure-editor/tools/gdx-particle-editor.jar new file mode 100644 index 00000000000..edd61cb028f Binary files /dev/null and b/adventure-editor/tools/gdx-particle-editor.jar differ diff --git a/forge-adventure/fallback_skin/adv_bg_splash.png b/forge-adventure/fallback_skin/adv_bg_splash.png deleted file mode 100644 index d6da1088913..00000000000 Binary files a/forge-adventure/fallback_skin/adv_bg_splash.png and /dev/null differ diff --git a/forge-adventure/fallback_skin/adv_bg_texture.jpg b/forge-adventure/fallback_skin/adv_bg_texture.jpg deleted file mode 100644 index 5ea4ad54c16..00000000000 Binary files a/forge-adventure/fallback_skin/adv_bg_texture.jpg and /dev/null differ diff --git a/forge-adventure/fallback_skin/bg_splash.png b/forge-adventure/fallback_skin/bg_splash.png deleted file mode 100644 index 66249347632..00000000000 Binary files a/forge-adventure/fallback_skin/bg_splash.png and /dev/null differ diff --git a/forge-adventure/fallback_skin/bg_texture.jpg b/forge-adventure/fallback_skin/bg_texture.jpg deleted file mode 100644 index 7c925524eb3..00000000000 Binary files a/forge-adventure/fallback_skin/bg_texture.jpg and /dev/null differ diff --git a/forge-adventure/fallback_skin/font1.ttf b/forge-adventure/fallback_skin/font1.ttf deleted file mode 100644 index 4b4ecc66671..00000000000 Binary files a/forge-adventure/fallback_skin/font1.ttf and /dev/null differ diff --git a/forge-adventure/fallback_skin/title_bg_lq.png b/forge-adventure/fallback_skin/title_bg_lq.png deleted file mode 100644 index daeccff1431..00000000000 Binary files a/forge-adventure/fallback_skin/title_bg_lq.png and /dev/null differ diff --git a/forge-adventure/fallback_skin/title_bg_lq_portrait.png b/forge-adventure/fallback_skin/title_bg_lq_portrait.png deleted file mode 100644 index 658ecdf2c4a..00000000000 Binary files a/forge-adventure/fallback_skin/title_bg_lq_portrait.png and /dev/null differ diff --git a/forge-adventure/fallback_skin/transition.png b/forge-adventure/fallback_skin/transition.png deleted file mode 100644 index 2ba659b5ce2..00000000000 Binary files a/forge-adventure/fallback_skin/transition.png and /dev/null differ diff --git a/forge-adventure/libs/gdx-backend-lwjgl-natives.jar b/forge-adventure/libs/gdx-backend-lwjgl-natives.jar deleted file mode 100644 index c9dc62392d6..00000000000 Binary files a/forge-adventure/libs/gdx-backend-lwjgl-natives.jar and /dev/null differ diff --git a/forge-adventure/libs/gdx-backend-lwjgl-sources.jar b/forge-adventure/libs/gdx-backend-lwjgl-sources.jar deleted file mode 100644 index 8fbd0cb3813..00000000000 Binary files a/forge-adventure/libs/gdx-backend-lwjgl-sources.jar and /dev/null differ diff --git a/forge-adventure/libs/gdx-backend-lwjgl.jar b/forge-adventure/libs/gdx-backend-lwjgl.jar deleted file mode 100644 index f1422b30d71..00000000000 Binary files a/forge-adventure/libs/gdx-backend-lwjgl.jar and /dev/null differ diff --git a/forge-adventure/libs/gdx-freetype-natives.jar b/forge-adventure/libs/gdx-freetype-natives.jar deleted file mode 100644 index 87ceb2eb26e..00000000000 Binary files a/forge-adventure/libs/gdx-freetype-natives.jar and /dev/null differ diff --git a/forge-adventure/libs/gdx-natives.jar b/forge-adventure/libs/gdx-natives.jar deleted file mode 100644 index 10d0a113c8a..00000000000 Binary files a/forge-adventure/libs/gdx-natives.jar and /dev/null differ diff --git a/forge-adventure/pom.xml b/forge-adventure/pom.xml deleted file mode 100644 index 1cdc2f9b211..00000000000 --- a/forge-adventure/pom.xml +++ /dev/null @@ -1,309 +0,0 @@ - - - - forge - forge - 1.6.66-SNAPSHOT - - 4.0.0 - - forge-adventure - jar - Forge Adventure - - - 4thline-repo - http://4thline.org/m2 - - false - - - - jitpack.io - https://jitpack.io - - - - src/main/java - - - ${project.basedir} - - **/*.vert - **/*.frag - **/title_bg_lq.png - **/title_bg_lq_portrait.png - **/transition.png - **/adv_bg_texture.jpg - **/adv_bg_splash.png - **/bg_splash.png - **/bg_texture.jpg - **/font1.ttf - - - - - - maven-compiler-plugin - - 1.8 - 1.8 - - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 1.7.25 - - - l4j-adv - package - - launch4j - - - gui - ${project.build.directory}/forge-adventure-editor-java8.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge-adventure-editor.ico - - forge.adventure.Main - false - anything - - - 1.8.0 - 4096 - - -Dfile.encoding=UTF-8 - - - - - 1.0.0.0 - - - 1.0.0.0 - - Forge - Forge - - 1.0.0.0 - - - 1.0.0.0 - - forge-adventure-editor - forge-adventure-editor - forge-adventure-editor-java8.exe - - - - - - l4j-adv2 - package - - launch4j - - - gui - ${project.build.directory}/forge-adventure-editor.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - https://www.oracle.com/java/technologies/downloads/ - src/main/config/forge-adventure-editor.ico - - forge.adventure.Main - false - anything - - - 11.0.1 - jdkOnly - 4096 - - -Dfile.encoding=UTF-8 - --add-opens java.base/java.lang=ALL-UNNAMED - --add-opens java.base/java.math=ALL-UNNAMED - --add-opens java.base/jdk.internal.misc=ALL-UNNAMED - --add-opens java.base/java.nio=ALL-UNNAMED - --add-opens=java.base/sun.nio.ch=ALL-UNNAMED - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang.reflect=ALL-UNNAMED - --add-opens java.base/java.text=ALL-UNNAMED - --add-opens java.desktop/java.awt=ALL-UNNAMED - --add-opens java.desktop/java.awt.font=ALL-UNNAMED - --add-opens java.desktop/java.awt.image=ALL-UNNAMED - --add-opens java.desktop/java.awt.color=ALL-UNNAMED - --add-opens java.desktop/sun.awt.image=ALL-UNNAMED - --add-opens java.desktop/javax.swing=ALL-UNNAMED - --add-opens java.desktop/javax.swing.border=ALL-UNNAMED - --add-opens java.desktop/javax.swing.event=ALL-UNNAMED - --add-opens java.desktop/sun.swing=ALL-UNNAMED - --add-opens java.desktop/java.beans=ALL-UNNAMED - --add-opens java.base/java.util.concurrent=ALL-UNNAMED - --add-opens java.base/java.net=ALL-UNNAMED - -Dio.netty.tryReflectionSetAccessible=true - - - - - 1.0.0.0 - - - 1.0.0.0 - - Forge - Forge - - 1.0.0.0 - - - 1.0.0.0 - - forge-adventure-editor - forge-adventure-editor - forge-adventure-editor.exe - - - - - - - - - com.google.code.maven-replacer-plugin - replacer - 1.5.2 - - - package - - replace - - - - - ${basedir}/${configSourceDirectory} - forge-adventure-editor.sh, forge-adventure-editor-mac.sh, forge-adventure-editor.command, forge-adventure-editor.cmd - ${project.build.directory} - . - false - - - $project.build.finalName$ - ${project.build.finalName}-jar-with-dependencies.jar - - - - - - - maven-assembly-plugin - - false - - jar-with-dependencies - - - - forge.adventure.Main - true - - - - - - make-assembly - - package - - - single - - - - - - - - - com.badlogicgames.gdx - gdx - 1.12.1 - compile - - - com.badlogicgames.gdx - gdx-platform - 1.12.1 - natives-desktop - - - com.badlogicgames.gdx - gdx-freetype - 1.12.1 - - - com.badlogicgames.gdx - gdx-backend-lwjgl - 1.12.1 - compile - - - com.badlogicgames.gdx - gdx-tools - 1.12.1 - compile - - - com.badlogicgames.gdx - gdx-freetype-platform - 1.12.1 - natives-desktop - - - forge - forge-core - ${project.version} - - - forge - forge-gui - ${project.version} - - - forge - forge-gui-mobile - ${project.version} - - - org.jetbrains - annotations - 22.0.0 - compile - - - com.badlogicgames.gdx-controllers - gdx-controllers-desktop - 2.2.3 - - - com.badlogicgames.gdx - gdx - - - - - - - 8 - 8 - - - diff --git a/forge-adventure/shaders/grayscale.frag b/forge-adventure/shaders/grayscale.frag deleted file mode 100644 index 4d801c770a4..00000000000 --- a/forge-adventure/shaders/grayscale.frag +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef GL_ES -precision mediump float; -#endif - -varying vec4 v_color; -varying vec2 v_texCoords; -uniform sampler2D u_texture; -uniform float u_grayness; -uniform float u_bias; - -void main() { - vec4 c = v_color * texture2D(u_texture, v_texCoords); - float grey = dot( c.rgb, vec3(0.22, 0.707, 0.071) ); - vec3 blendedColor = mix(c.rgb, vec3(grey), u_grayness); - gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), vec4(blendedColor.rgb, c.a), u_bias); -} \ No newline at end of file diff --git a/forge-adventure/shaders/grayscale.vert b/forge-adventure/shaders/grayscale.vert deleted file mode 100644 index 17d96ca8dde..00000000000 --- a/forge-adventure/shaders/grayscale.vert +++ /dev/null @@ -1,14 +0,0 @@ -attribute vec4 a_position; -attribute vec4 a_color; -attribute vec2 a_texCoord0; - -uniform mat4 u_projTrans; - -varying vec4 v_color; -varying vec2 v_texCoords; - -void main() { - v_color = a_color; - v_texCoords = a_texCoord0; - gl_Position = u_projTrans * a_position; -} \ No newline at end of file diff --git a/forge-adventure/shaders/outline.frag b/forge-adventure/shaders/outline.frag deleted file mode 100644 index 738d23c1f71..00000000000 --- a/forge-adventure/shaders/outline.frag +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; -uniform vec2 u_viewportInverse; -uniform vec3 u_color; -uniform float u_offset; -uniform float u_step; - -varying vec4 v_color; -varying vec2 v_texCoord; - -#define ALPHA_VALUE_BORDER 0.5 - -void main() { - vec2 T = v_texCoord.xy; - - float alpha = 0.0; - bool allin = true; - for( float ix = -u_offset; ix < u_offset; ix += u_step ) - { - for( float iy = -u_offset; iy < u_offset; iy += u_step ) - { - float newAlpha = texture2D(u_texture, T + vec2(ix, iy) * u_viewportInverse).a; - allin = allin && newAlpha > ALPHA_VALUE_BORDER; - if (newAlpha > ALPHA_VALUE_BORDER && newAlpha >= alpha) - { - alpha = newAlpha; - } - } - } - if (allin) - { - alpha = 0.0; - } - - gl_FragColor = vec4(u_color,alpha); -} \ No newline at end of file diff --git a/forge-adventure/shaders/outline.vert b/forge-adventure/shaders/outline.vert deleted file mode 100644 index 1b6e438116d..00000000000 --- a/forge-adventure/shaders/outline.vert +++ /dev/null @@ -1,16 +0,0 @@ -uniform mat4 u_projTrans; - -attribute vec4 a_position; -attribute vec2 a_texCoord0; -attribute vec4 a_color; - -varying vec4 v_color; -varying vec2 v_texCoord; - -uniform vec2 u_viewportInverse; - -void main() { - gl_Position = u_projTrans * a_position; - v_texCoord = a_texCoord0; - v_color = a_color; -} \ No newline at end of file diff --git a/forge-adventure/shaders/underwater.frag b/forge-adventure/shaders/underwater.frag deleted file mode 100644 index 6287a862c9c..00000000000 --- a/forge-adventure/shaders/underwater.frag +++ /dev/null @@ -1,26 +0,0 @@ -#ifdef GL_ES -#define PRECISION mediump -precision PRECISION float; -precision PRECISION int; -#else -#define PRECISION -#endif - -varying vec2 v_texCoords; -uniform sampler2D u_texture; -uniform float u_amount; -uniform float u_speed; -uniform float u_time; -uniform float u_bias; - -void main () { - vec2 uv = v_texCoords; - - uv.y += (cos((uv.y + (u_time * 0.04 * u_speed)) * 45.0) * 0.0019 * u_amount) + (cos((uv.y + (u_time * 0.1 * u_speed)) * 10.0) * 0.002 * u_amount); - - uv.x += (sin((uv.y + (u_time * 0.07 * u_speed)) * 15.0) * 0.0029 * u_amount) + (sin((uv.y + (u_time * 0.1 * u_speed)) * 15.0) * 0.002 * u_amount); - - vec4 texColor = texture2D(u_texture, uv); - - gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texColor, u_bias); -} \ No newline at end of file diff --git a/forge-adventure/shaders/warp.frag b/forge-adventure/shaders/warp.frag deleted file mode 100644 index f8a7022fa2c..00000000000 --- a/forge-adventure/shaders/warp.frag +++ /dev/null @@ -1,57 +0,0 @@ -#ifdef GL_ES -precision mediump float; -#endif - -varying vec2 v_texCoords; -uniform sampler2D u_texture; - -uniform float u_time; -uniform float u_speed; -uniform float u_amount; -uniform vec2 u_viewport; -uniform vec2 u_position; - -float random2d(vec2 n) { - return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); -} - -float randomRange (in vec2 seed, in float min, in float max) { - return min + random2d(seed) * (max - min); -} - -float insideRange(float v, float bottom, float top) { - return step(bottom, v) - step(top, v); -} - -void main() -{ - float time = floor(u_time * u_speed * 60.0); - - vec3 outCol = texture2D(u_texture, v_texCoords).rgb; - - float maxOffset = u_amount/2.0; - for (float i = 0.0; i < 2.0; i += 1.0) { - float sliceY = random2d(vec2(time, 2345.0 + float(i))); - float sliceH = random2d(vec2(time, 9035.0 + float(i))) * 0.25; - float hOffset = randomRange(vec2(time, 9625.0 + float(i)), -maxOffset, maxOffset); - vec2 uvOff = v_texCoords; - uvOff.x += hOffset; - if (insideRange(v_texCoords.y, sliceY, fract(sliceY+sliceH)) == 1.0){ - outCol = texture2D(u_texture, uvOff).rgb; - } - } - - float maxColOffset = u_amount / 6.0; - float rnd = random2d(vec2(time , 9545.0)); - vec2 colOffset = vec2(randomRange(vec2(time , 9545.0), -maxColOffset, maxColOffset), - randomRange(vec2(time , 7205.0), -maxColOffset, maxColOffset)); - if (rnd < 0.33) { - outCol.r = texture2D(u_texture, v_texCoords + colOffset).r; - } else if (rnd < 0.66) { - outCol.g = texture2D(u_texture, v_texCoords + colOffset).g; - } else { - outCol.b = texture2D(u_texture, v_texCoords + colOffset).b; - } - - gl_FragColor = vec4(outCol, 1.0); -} \ No newline at end of file diff --git a/forge-adventure/src/main/config/forge-adventure-editor-mac.sh b/forge-adventure/src/main/config/forge-adventure-editor-mac.sh deleted file mode 100644 index eb3d4f9adb7..00000000000 --- a/forge-adventure/src/main/config/forge-adventure-editor-mac.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd $(dirname "${0}") -java -XstartOnFirstThread -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ diff --git a/forge-adventure/src/main/config/forge-adventure-editor.cmd b/forge-adventure/src/main/config/forge-adventure-editor.cmd deleted file mode 100644 index 8779fa25870..00000000000 --- a/forge-adventure/src/main/config/forge-adventure-editor.cmd +++ /dev/null @@ -1,25 +0,0 @@ -@echo off - -pushd %~dp0 - -java -version 1>nul 2>nul || ( - echo no java installed - popd - exit /b 2 -) -for /f tokens^=2^ delims^=.-_^+^" %%j in ('java -fullversion 2^>^&1') do set "jver=%%j" - -if %jver% GEQ 17 ( - java --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ - popd - exit /b 0 -) - -if %jver% GEQ 11 ( - java --illegal-access=permit -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ - popd - exit /b 0 -) - -java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ -popd \ No newline at end of file diff --git a/forge-adventure/src/main/java/forge/adventure/editor/EditorMainWindow.java b/forge-adventure/src/main/java/forge/adventure/editor/EditorMainWindow.java deleted file mode 100644 index c9c857d371e..00000000000 --- a/forge-adventure/src/main/java/forge/adventure/editor/EditorMainWindow.java +++ /dev/null @@ -1,62 +0,0 @@ -package forge.adventure.editor; - - - -import com.badlogic.gdx.tools.particleeditor.ParticleEditor; -import forge.localinstance.properties.ForgeConstants; -import forge.localinstance.properties.ForgePreferences; -import forge.model.FModel; -import forge.util.Lang; -import forge.util.Localizer; - -import javax.swing.*; -import java.awt.*; - -/** - * Editor class to edit configuration, maybe moved or removed - */ -public class EditorMainWindow extends JFrame { - public final static WorldEditor worldEditor = new WorldEditor(); - JTabbedPane tabs =new JTabbedPane(); - - public EditorMainWindow() - { - UIManager.LookAndFeelInfo[] var1 = UIManager.getInstalledLookAndFeels(); - FModel.initialize(null, preferences -> { - preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, true); - return null; - }); - Lang.createInstance(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_LANGUAGE)); - Localizer.getInstance().initialize(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR); - int var2 = var1.length; - - for (UIManager.LookAndFeelInfo info : var1) { - if ("Nimbus".equals(info.getName())) { - try { - UIManager.setLookAndFeel(info.getClassName()); - } catch (Throwable var6) { - } - break; - } - } - BorderLayout layout=new BorderLayout(); - JToolBar toolBar = new JToolBar("toolbar"); - JButton newButton=new JButton("open ParticleEditor"); - newButton.addActionListener(e -> EventQueue.invokeLater(ParticleEditor::new)); - toolBar.add(newButton); - setLayout(layout); - toolBar.setFloatable(false); - add(toolBar, BorderLayout.NORTH); - add(tabs, BorderLayout.CENTER); - tabs.addTab("World",worldEditor); - tabs.addTab("POI",new PointOfInterestEditor()); - tabs.addTab("Items",new ItemsEditor()); - tabs.addTab("Enemies",new EnemyEditor()); - tabs.addTab("Quests",new QuestEditor()); - - setVisible(true); - setSize(800,600); - GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow( this ); - - } -} diff --git a/forge-ai/pom.xml b/forge-ai/pom.xml index 8b2743db97b..b51460f8ce7 100644 --- a/forge-ai/pom.xml +++ b/forge-ai/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-ai diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index fd176603ff0..662a42b7318 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -838,12 +838,12 @@ public class AiCostDecision extends CostDecisionMakerBase { @Override public PaymentDecision visit(CostUnattach cost) { - final Card cardToUnattach = cost.findCardToUnattach(source, player, ability); - if (cardToUnattach == null) { + final CardCollection cardToUnattach = cost.findCardToUnattach(source, player, ability); + if (cardToUnattach.isEmpty()) { // We really shouldn't be able to get here if there's nothing to unattach return null; } - return PaymentDecision.card(cardToUnattach); + return PaymentDecision.card(cardToUnattach.getFirst()); } @Override diff --git a/forge-ai/src/main/java/forge/ai/ability/PeekAndRevealAi.java b/forge-ai/src/main/java/forge/ai/ability/PeekAndRevealAi.java index eeda8d90462..a72bfab20c7 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PeekAndRevealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PeekAndRevealAi.java @@ -1,6 +1,7 @@ package forge.ai.ability; import forge.ai.AiAttackController; +import forge.ai.ComputerUtilCost; import forge.ai.SpellAbilityAi; import forge.ai.SpellApiToAi; import forge.game.card.Card; @@ -66,6 +67,14 @@ public class PeekAndRevealAi extends SpellAbilityAi { return false; } + if ("X".equals(sa.getParam("PeekAmount")) && sa.getSVar("X").equals("Count$xPaid")) { + int xPay = ComputerUtilCost.getMaxXValue(sa, aiPlayer, sa.isTrigger()); + if (xPay == 0) { + return false; + } + sa.getRootAbility().setXManaCostPaid(xPay); + } + return true; } diff --git a/forge-core/pom.xml b/forge-core/pom.xml index 7d1ec0902c0..d96a8c7ead6 100644 --- a/forge-core/pom.xml +++ b/forge-core/pom.xml @@ -6,7 +6,7 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-core @@ -16,12 +16,12 @@ com.google.guava guava - 33.2.1-android + 33.3.1-android org.apache.commons commons-lang3 - 3.12.0 + 3.17.0 diff --git a/forge-core/src/main/java/forge/card/mana/ManaCost.java b/forge-core/src/main/java/forge/card/mana/ManaCost.java index eb96946b575..fdfa28734c2 100644 --- a/forge-core/src/main/java/forge/card/mana/ManaCost.java +++ b/forge-core/src/main/java/forge/card/mana/ManaCost.java @@ -92,15 +92,15 @@ public final class ManaCost implements Comparable, Iterable shardsTemp = Lists.newArrayList(); - this.hasNoCost = false; while (parser.hasNext()) { final ManaCostShard shard = parser.next(); if (shard != null && shard != ManaCostShard.GENERIC) { shardsTemp.add(shard); } // null is OK - that was generic mana } - this.genericCost = parser.getTotalGenericCost(); // collect generic mana - // here + int generic = parser.getTotalGenericCost(); // collect generic mana here + this.hasNoCost = generic == -1; + this.genericCost = generic == -1 ? 0 : generic; sealClass(shardsTemp); } @@ -281,6 +281,9 @@ public final class ManaCost implements Comparable, Iterable forge forge - 1.6.66-SNAPSHOT + ${revision} forge-game @@ -26,13 +26,13 @@ org.testng testng - 7.4.0 + 7.10.2 test io.sentry sentry-logback - 7.14.0 + 7.15.0 diff --git a/forge-game/src/main/java/forge/game/GameEntityCounterTable.java b/forge-game/src/main/java/forge/game/GameEntityCounterTable.java index 5813dfa7675..e3d58805c90 100644 --- a/forge-game/src/main/java/forge/game/GameEntityCounterTable.java +++ b/forge-game/src/main/java/forge/game/GameEntityCounterTable.java @@ -177,12 +177,18 @@ public class GameEntityCounterTable extends ForwardingTable, Ga value = Math.min(value, Integer.parseInt(cause.getParam("MaxFromEffect")) - gm.getKey().getCounters(ec.getKey())); } gm.getKey().addCounterInternal(ec.getKey(), value, e.getKey().orNull(), true, result, runParams); - if (remember && ec.getValue() >= 1) { + if (remember && ec.getValue() > 0) { cause.getHostCard().addRemembered(gm.getKey()); } } } } + + int totalAdded = totalValues(); + if (totalAdded > 0 && cause != null && cause.hasParam("RememberAmount")) { + cause.getHostCard().addRemembered(totalAdded); + } + result.triggerCountersPutAll(game); return !result.isEmpty(); } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index a45215cbcd4..a431613f569 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2740,6 +2740,7 @@ public class AbilityUtils { for (Card card : cards) { manaCost.add(card.getManaCost().getShortString()); } + manaCost.remove(ManaCost.NO_COST.getShortString()); return doXMath(manaCost.size(), expr, c, ctb); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java index 258b6db8c48..a7568f18ad8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutAllEffect.java @@ -116,12 +116,6 @@ public class CountersPutAllEffect extends SpellAbilityEffect { } table.replaceCounterEffect(game, sa, true); - - //for cards like Agitator Ant/Spectacular Showdown that care if counters were actually put on, - // instead use "RememberPut" – this checks after replacement - if (sa.hasParam("RememberCards")) { // remembers whether counters actually placed or not - host.addRemembered(table.columnKeySet()); - } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java index fa13b0a3ced..3045b416051 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java @@ -591,18 +591,14 @@ public class CountersPutEffect extends SpellAbilityEffect { final Card card = sa.getHostCard(); final Game game = card.getGame(); final Player activator = sa.getActivatingPlayer(); - - String amount = sa.getParamOrDefault("CounterNum", "1"); - boolean rememberAmount = sa.hasParam("RememberAmount"); + final String amount = sa.getParamOrDefault("CounterNum", "1"); + final int counterAmount = AbilityUtils.calculateAmount(card, amount, sa); Player placer = activator; if (sa.hasParam("Placer")) { - final String pstr = sa.getParam("Placer"); - placer = AbilityUtils.getDefinedPlayers(card, pstr, sa).get(0); + placer = AbilityUtils.getDefinedPlayers(card, sa.getParam("Placer"), sa).get(0); } - int counterAmount = AbilityUtils.calculateAmount(card, amount, sa); - GameEntityCounterTable table = new GameEntityCounterTable(); if (sa.hasParam("TriggeredCounterMap")) { @@ -648,12 +644,6 @@ public class CountersPutEffect extends SpellAbilityEffect { table.replaceCounterEffect(game, sa, true); - int totalAdded = table.totalValues(); - if (totalAdded > 0 && rememberAmount) { - // TODO use SpellAbility Remember later - card.addRemembered(totalAdded); - } - if (sa.hasParam("RemovePhase")) { for (Map.Entry> e : table.row(Optional.of(placer)).entrySet()) { for (Map.Entry ce : e.getValue().entrySet()) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index 434872bba1d..8962414e52f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -389,9 +389,6 @@ public class PlayEffect extends SpellAbilityEffect { abCost = Iterables.find(tgtCard.getNonManaAbilities(), s -> s.isKeyword(Keyword.SUSPEND)).getPayCosts(); } else { if (cost.contains("ConvertedManaCost")) { - if (unpayableCost) { - continue; - } final String costcmc = Integer.toString(tgtCard.getCMC()); cost = cost.replace("ConvertedManaCost", costcmc); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index c8982425fc7..f1c797e921e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -474,15 +474,6 @@ public class PumpEffect extends SpellAbilityEffect { List affectedKeywords = Lists.newArrayList(keywords); if (!affectedKeywords.isEmpty()) { - Iterables.removeIf(affectedKeywords, input -> { - if (input.contains("CardManaCost")) { - if (tgtC.getManaCost().isNoCost()) { - return true; - } - } - return false; - }); - affectedKeywords = Lists.transform(affectedKeywords, input -> { if (input.contains("CardManaCost")) { input = input.replace("CardManaCost", tgtC.getManaCost().getShortString()); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 1eee35c287a..ce9b68189f8 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1462,7 +1462,7 @@ public class CardFactoryUtil { final String trigStr = "Mode$ Exiled | ValidCard$ Card.Self | Madness$ True | Secondary$ True" + " | TriggerDescription$ Play Madness " + ManaCostParser.parse(manacost) + " - " + card.getName(); - final String playMadnessStr = "DB$ Play | Defined$ Self | PlayCost$ " + manacost + + final String playMadnessStr = "DB$ Play | Defined$ Self | ValidSA$ Spell | PlayCost$ " + manacost + " | ConditionDefined$ Self | ConditionPresent$ Card.StrictlySelf+inZoneExile" + " | Optional$ True | RememberPlayed$ True | Madness$ True"; diff --git a/forge-game/src/main/java/forge/game/cost/CostUnattach.java b/forge-game/src/main/java/forge/game/cost/CostUnattach.java index f4d6739f6fd..97d863b416f 100644 --- a/forge-game/src/main/java/forge/game/cost/CostUnattach.java +++ b/forge-game/src/main/java/forge/game/cost/CostUnattach.java @@ -17,9 +17,8 @@ */ package forge.game.cost; -import java.util.List; - import forge.game.card.Card; +import forge.game.card.CardCollection; import forge.game.card.CardLists; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -70,27 +69,27 @@ public class CostUnattach extends CostPartWithList { */ @Override public final boolean canPay(final SpellAbility ability, final Player payer, final boolean effect) { - return findCardToUnattach(ability.getHostCard(), payer, ability) != null; + return !findCardToUnattach(ability.getHostCard(), payer, ability).isEmpty(); } - public Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) { + public CardCollection findCardToUnattach(final Card source, Player activator, SpellAbility ability) { + CardCollection attachees = new CardCollection(); if (payCostFromSource()) { if (source.isEquipping()) { - return source; + attachees.add(source); } } else if (getType().equals("OriginalHost")) { Card originalEquipment = ability.getOriginalHost(); if (originalEquipment.isEquipping()) { - return originalEquipment; + attachees.add(originalEquipment); } } else { - List attachees = CardLists.getValidCards(source.getEquippedBy(), this.getType(), activator, source, ability); - if (attachees.size() > 0) { - // Just pick the first one, although maybe give a dialog - return attachees.get(0); + attachees.addAll(source.getEquippedBy()); + if (!getType().contains("X") || ability.getXManaCostPaid() != null) { + attachees = CardLists.getValidCards(attachees, this.getType(), activator, source, ability); } } - return null; + return attachees; } /* (non-Javadoc) diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java index 04788a01ae3..995b62f2dfd 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java +++ b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java @@ -97,7 +97,10 @@ public class ManaCostBeingPaid { @Override public int getTotalGenericCost() { ShardCount c = unpaidShards.get(ManaCostShard.GENERIC); - return c == null ? 0 : c.totalCount; + if (c == null) { + return unpaidShards.isEmpty() ? -1 : 0; + } + return c.totalCount; } } diff --git a/forge-game/src/main/java/forge/game/spellability/Spell.java b/forge-game/src/main/java/forge/game/spellability/Spell.java index 13a379afaa5..81ed51fb199 100644 --- a/forge-game/src/main/java/forge/game/spellability/Spell.java +++ b/forge-game/src/main/java/forge/game/spellability/Spell.java @@ -23,7 +23,6 @@ import forge.game.card.CardCopyService; import org.apache.commons.lang3.ObjectUtils; import forge.card.CardStateName; -import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.ability.AbilityKey; import forge.game.card.Card; @@ -71,6 +70,11 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable return false; } + // CR 118.6 cost is unpayable + if (getPayCosts().hasManaCost() && getPayCosts().getCostMana().getMana().isNoCost()) { + return false; + } + Player activator = this.getActivatingPlayer(); if (activator == null) { activator = card.getController(); @@ -84,9 +88,6 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable return false; } - // Save the original cost and the face down info for a later check since the LKI copy will overwrite them - ManaCost origCost = card.getState(card.isFaceDown() ? CardStateName.Original : card.getCurrentStateName()).getManaCost(); - // do performanceMode only for cases where the activator is different than controller if (!Spell.performanceMode && !card.getController().equals(activator)) { // always make a lki copy in this case? @@ -100,13 +101,6 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable return false; } - // for uncastables like lotus bloom, check if manaCost is blank (except for morph spells) - // but ignore if it comes from PlayEffect - if (!isCastFaceDown() && !isCastFromPlayEffect() - && isBasicSpell() && origCost.isNoCost()) { - return false; - } - if (!CostPayment.canPayAdditionalCosts(this.getPayCosts(), this, false)) { return false; } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index 2a323934c65..6d379797868 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -731,9 +731,6 @@ public final class StaticAbilityContinuous { final List extraKeywords = Lists.newArrayList(); Iterables.removeIf(newKeywords, input -> { - if (input.contains("CardManaCost") && affectedCard.getManaCost().isNoCost()) { - return true; - } // replace one Keyword with list of keywords if (input.startsWith("Protection") && input.contains("CardColors")) { for (Byte color : affectedCard.getColor()) { diff --git a/forge-gui-android/assets/fallback_skin/bg_splash.png b/forge-gui-android/assets/fallback_skin/bg_splash.png index 66249347632..0bcba091a57 100644 Binary files a/forge-gui-android/assets/fallback_skin/bg_splash.png and b/forge-gui-android/assets/fallback_skin/bg_splash.png differ diff --git a/forge-gui-android/assets/fallback_skin/bg_texture.jpg b/forge-gui-android/assets/fallback_skin/bg_texture.jpg index 7c925524eb3..50f37309ff0 100644 Binary files a/forge-gui-android/assets/fallback_skin/bg_texture.jpg and b/forge-gui-android/assets/fallback_skin/bg_texture.jpg differ diff --git a/forge-gui-android/assets/fallback_skin/font1.ttf b/forge-gui-android/assets/fallback_skin/font1.ttf index 4b4ecc66671..28cf43d7e7f 100644 Binary files a/forge-gui-android/assets/fallback_skin/font1.ttf and b/forge-gui-android/assets/fallback_skin/font1.ttf differ diff --git a/forge-gui-android/filters/version.txt b/forge-gui-android/filters/version.txt index 6bc41fb80cb..fb02fab734c 100644 --- a/forge-gui-android/filters/version.txt +++ b/forge-gui-android/filters/version.txt @@ -1 +1 @@ -${alpha-version} \ No newline at end of file +${snapshot-version} \ No newline at end of file diff --git a/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so b/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so index f3a8a41cdcc..9fe83039884 100644 Binary files a/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so and b/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so differ diff --git a/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so b/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so index 9f7e218abc9..1a2b34ff4e2 100644 Binary files a/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so and b/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so differ diff --git a/forge-gui-android/libs/arm64-v8a/libgdx.so b/forge-gui-android/libs/arm64-v8a/libgdx.so index ffb154277e7..9df8b027c47 100644 Binary files a/forge-gui-android/libs/arm64-v8a/libgdx.so and b/forge-gui-android/libs/arm64-v8a/libgdx.so differ diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so b/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so index 00700e9d50c..82f2cee2ea0 100644 Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so and b/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so differ diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so b/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so index 6ceab900ad0..62a2aebae2c 100644 Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so and b/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so differ diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx.so b/forge-gui-android/libs/armeabi-v7a/libgdx.so index 7192dc626f0..005705b3a23 100644 Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx.so and b/forge-gui-android/libs/armeabi-v7a/libgdx.so differ diff --git a/forge-gui-android/libs/gdx-backend-android-sources.jar b/forge-gui-android/libs/gdx-backend-android-sources.jar index 524836a1f35..5d44f0a0b9c 100644 Binary files a/forge-gui-android/libs/gdx-backend-android-sources.jar and b/forge-gui-android/libs/gdx-backend-android-sources.jar differ diff --git a/forge-gui-android/libs/gdx-backend-android.jar b/forge-gui-android/libs/gdx-backend-android.jar index f67fc316ccd..da5c7c2bd25 100644 Binary files a/forge-gui-android/libs/gdx-backend-android.jar and b/forge-gui-android/libs/gdx-backend-android.jar differ diff --git a/forge-gui-android/libs/gdx-controllers-android.jar b/forge-gui-android/libs/gdx-controllers-android.jar new file mode 100644 index 00000000000..7ebd2b4df97 Binary files /dev/null and b/forge-gui-android/libs/gdx-controllers-android.jar differ diff --git a/forge-gui-android/libs/gdx-freetype.jar b/forge-gui-android/libs/gdx-freetype.jar index 7882e998dda..daf2f4f1d70 100644 Binary files a/forge-gui-android/libs/gdx-freetype.jar and b/forge-gui-android/libs/gdx-freetype.jar differ diff --git a/forge-gui-android/libs/gdx-sources.jar b/forge-gui-android/libs/gdx-sources.jar index 85793e30966..11bed47689d 100644 Binary files a/forge-gui-android/libs/gdx-sources.jar and b/forge-gui-android/libs/gdx-sources.jar differ diff --git a/forge-gui-android/libs/gdx.jar b/forge-gui-android/libs/gdx.jar index cca18342888..50d65286c35 100644 Binary files a/forge-gui-android/libs/gdx.jar and b/forge-gui-android/libs/gdx.jar differ diff --git a/forge-gui-android/libs/sun-misc.jar b/forge-gui-android/libs/sun-misc.jar new file mode 100644 index 00000000000..a4817c34dbb Binary files /dev/null and b/forge-gui-android/libs/sun-misc.jar differ diff --git a/forge-gui-android/libs/x86/libgdx-box2d.so b/forge-gui-android/libs/x86/libgdx-box2d.so index 98a5aefa823..4b80ce2fd6a 100644 Binary files a/forge-gui-android/libs/x86/libgdx-box2d.so and b/forge-gui-android/libs/x86/libgdx-box2d.so differ diff --git a/forge-gui-android/libs/x86/libgdx-freetype.so b/forge-gui-android/libs/x86/libgdx-freetype.so index b98bf59da7b..0d5a244fa40 100644 Binary files a/forge-gui-android/libs/x86/libgdx-freetype.so and b/forge-gui-android/libs/x86/libgdx-freetype.so differ diff --git a/forge-gui-android/libs/x86/libgdx.so b/forge-gui-android/libs/x86/libgdx.so index 623b66290d5..7fbd858dd76 100644 Binary files a/forge-gui-android/libs/x86/libgdx.so and b/forge-gui-android/libs/x86/libgdx.so differ diff --git a/forge-gui-android/libs/x86_64/libgdx-box2d.so b/forge-gui-android/libs/x86_64/libgdx-box2d.so index 6d8d101fb9b..04fbd2ca6af 100644 Binary files a/forge-gui-android/libs/x86_64/libgdx-box2d.so and b/forge-gui-android/libs/x86_64/libgdx-box2d.so differ diff --git a/forge-gui-android/libs/x86_64/libgdx-freetype.so b/forge-gui-android/libs/x86_64/libgdx-freetype.so index b71ab3b08f0..ca5b553d52e 100644 Binary files a/forge-gui-android/libs/x86_64/libgdx-freetype.so and b/forge-gui-android/libs/x86_64/libgdx-freetype.so differ diff --git a/forge-gui-android/libs/x86_64/libgdx.so b/forge-gui-android/libs/x86_64/libgdx.so index 87a2ca594ed..c93c34d8d3b 100644 Binary files a/forge-gui-android/libs/x86_64/libgdx.so and b/forge-gui-android/libs/x86_64/libgdx.so differ diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index ef462a09720..5d5ab45a55c 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -5,11 +5,10 @@ ${maven.build.timestamp} yyyy-MM-dd HH:mm:ss true - 2,2,2,4 + 2,2,4,2 jar -Xms1024m -Xmx1536m - 1.6.66-SNAPSHOT keystore alias storepass @@ -22,7 +21,7 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui-android @@ -39,11 +38,45 @@ src + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + timestamp-property + initialize + + timestamp-property + + + + month.date + MM.dd + + + + regex-property + initialize + + regex-property + + + + snapshot-version + ${revision} + -SNAPSHOT + -SNAPSHOT-${month.date} + false + + + + maven-compiler-plugin - 1.8 - 1.8 + 17 + 17 @@ -53,13 +86,14 @@ true - forge-android-${alpha-version} + + forge-android-${snapshot-version} org.robolectric android-all - 8.0.0_r4-robolectric-0 + 15-robolectric-12468137 provided @@ -76,24 +110,6 @@ system ${pom.basedir}/libs/relinker.jar - - - org.apache.httpcomponents - httpclient - 4.5.14 - - - commons-codec - commons-codec - - - - - - commons-codec - commons-codec - 1.16.0 - forge forge-core @@ -119,23 +135,17 @@ forge-gui-mobile ${project.version} - - xmlpull - xmlpull - 1.1.3.1 - provided - com.badlogicgames.gdx gdx-backend-android - 1.12.1 + 1.13.0 system ${pom.basedir}/libs/gdx-backend-android.jar io.sentry sentry-android - 7.14.0 + 7.15.0 aar @@ -152,7 +162,7 @@ io.sentry sentry-android-core - 7.14.0 + 7.15.0 aar @@ -172,7 +182,7 @@ io.sentry sentry-android-ndk - 7.14.0 + 7.15.0 aar @@ -197,7 +207,8 @@ com.badlogicgames.gdx-controllers gdx-controllers-android 2.2.3 - aar + system + ${pom.basedir}/libs/gdx-controllers-android.jar com.badlogicgames.gdx @@ -225,9 +236,16 @@ 2.3.1 - net.sf.proguard - proguard-base - 6.2.2 + com.sun.xml.bind + jaxb-impl + 2.3.4 + + + sun + misc + 1 + system + ${pom.basedir}/libs/sun-misc.jar 4.6.2 @@ -237,8 +255,8 @@ true - 26 - 30.0.3 + 35 + 35.0.0 true ${project.basedir}/assets @@ -249,6 +267,7 @@ false ${project.basedir}/proguard.cfg + ${pom.basedir}/tools/proguard.jar true d8 @@ -286,6 +305,39 @@ + + exec-maven-plugin + 3.4.1 + org.codehaus.mojo + + + SignV2 + verify + + exec + + + + + ${pom.basedir} + java + + -jar + ${pom.basedir}/tools/uber-apk-signer.jar + -a + ${pom.basedir}/target/ + --ks + forge.keystore + --ksAlias + Forge + --ksKeyPass + forge72 + --ksPass + forge72 + --debug + + + com.simpligility.maven.plugins android-maven-plugin @@ -296,9 +348,16 @@ 2.3.1 - net.sf.proguard - proguard-base - 6.2.2 + com.sun.xml.bind + jaxb-impl + 2.3.4 + + + sun + misc + 1 + system + ${pom.basedir}/libs/sun-misc.jar 4.6.2 @@ -308,8 +367,8 @@ false - 26 - 30.0.3 + 35 + 35.0.0 false @@ -323,6 +382,7 @@ false ${project.basedir}/proguard.cfg + ${pom.basedir}/tools/proguard.jar true d8 @@ -347,101 +407,16 @@ manifest-merger - - - - - - - - android-release-sign - - apk - - - - - org.apache.maven.plugins - maven-jarsigner-plugin - 1.3.2 - - - signing - - sign - verify - - package - true - true - - - ${project.build.directory}/${project.build.finalName}.apk - - ${sign.keystore} - ${sign.alias} - ${sign.storepass} - ${sign.keypass} - true - - -sigalg - MD5withRSA - -digestalg - SHA1 - + ${snapshot-version} - - com.simpligility.maven.plugins - android-maven-plugin - - - javax.xml.bind - jaxb-api - 2.3.1 - - - net.sf.proguard - proguard-base - 6.2.2 - - - 4.6.2 - true - - - false - - - false - true - ${project.build.directory}/${project.build.finalName}.apk - ${project.build.directory}/${project.build.finalName}-signed-aligned.apk - - - - - android-align - package - - zipalign - - - - update-manifest - - manifest-merger - - - - org.apache.maven.plugins maven-antrun-plugin - 1.7 + 3.0.0 org.apache.ant @@ -499,7 +474,7 @@ org.apache.maven.plugins maven-antrun-plugin - 1.7 + 3.0.0 org.apache.ant @@ -509,22 +484,22 @@ commons-net commons-net - 3.3 + 3.11.1 org.apache.ant ant-commons-net - 1.9.4 + 1.10.15 android-ftp - package + install - - + + @@ -546,5 +521,116 @@ + + + android-test-build + + apk + + + + + exec-maven-plugin + 3.4.1 + org.codehaus.mojo + + + SignV2 + verify + + exec + + + + + ${pom.basedir} + java + + -jar + ${pom.basedir}/tools/uber-apk-signer.jar + -a + ${pom.basedir}/target/ + --debug + + + + + com.simpligility.maven.plugins + android-maven-plugin + + + javax.xml.bind + jaxb-api + 2.3.1 + + + com.sun.xml.bind + jaxb-impl + 2.3.4 + + + sun + misc + 1 + system + ${pom.basedir}/libs/sun-misc.jar + + + 4.6.2 + true + + + false + + + 35 + 35.0.0 + + + false + + true + ${project.basedir}/assets + ${project.basedir}/res + ${project.basedir}/libs + true + + false + ${project.basedir}/proguard.cfg + + ${pom.basedir}/tools/proguard.jar + true + d8 + + 26 + + ${build.min.memory} + ${build.max.memory} + + + + true + + ${build.min.memory} + ${build.max.memory} + + --min-sdk-version=26 + + + + + update-manifest + + manifest-merger + + + ${snapshot-version} + + + + + + + diff --git a/forge-gui-android/proguard.cfg b/forge-gui-android/proguard.cfg index b4cc8fcab34..7079b6c5d64 100644 --- a/forge-gui-android/proguard.cfg +++ b/forge-gui-android/proguard.cfg @@ -1,20 +1,24 @@ -dontobfuscate --optimizationpasses 3 +#-optimizationpasses 3 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses --dontpreverify +# disable the -dontpreverify since it produces tons of warning when compiled using Android 14 and newer Build-tools +#-dontpreverify -verbose --optimizations !code/simplification/*,!field/*,!class/merging/*,!code/allocation/variable,!library/gson +# IntelliJ marks -android is invalid since the default inspection uses R8, we use Proguard exclusively and -android is available. +-android +# https://stackoverflow.com/a/32615580 +-optimizations !code/simplification/*,!field/*,!class/merging/*,!code/allocation/variable,!library/gson,!class/unboxing/enum ## Uncomment the line below and set it to the location of rt.jar in JDK if the Proguard step fails to find the libraries ## and spits out a thousand-something Class Not Found errors ##-libraryjars /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar -##-libraryjars /jmods/java.base.jmod(!**.jar;!module-info.class) -##-libraryjars /jmods/java.datatransfer.jmod(!**.jar;!module-info.class) -##-libraryjars /jmods/java.prefs.jmod(!**.jar;!module-info.class) -##-libraryjars /jmods/java.xml.jmod(!**.jar;!module-info.class) -##-libraryjars /jmods/java.desktop.jmod(!**.jar;!module-info.class) -##-libraryjars /jmods/jdk.xml.dom.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/java.base.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/java.datatransfer.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/java.prefs.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/java.xml.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/java.desktop.jmod(!**.jar;!module-info.class) +-libraryjars /jmods/jdk.xml.dom.jmod(!**.jar;!module-info.class) -dontwarn afu.org.checkerframework.** -dontwarn io.netty.** @@ -61,7 +65,7 @@ -keep class org.apache.commons.lang3.** { *; } -keep class com.google.guava.** { *; } -keep class com.google.common.** { *; } -#-keep class com.google.gson.GsonBuilder +##-keep class com.google.gson.GsonBuilder ##-keep class io.sentry.event.Event { *; } ##-keep class io.sentry.android.core.SentryAndroidOptions ##-keep class io.sentry.android.core.SentryAndroid @@ -100,10 +104,11 @@ -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService +# ILicensingService is not available on robolectric dependency +#-keep public class com.android.vending.licensing.ILicensingService -keep public class * extends com.badlogic.gdx.Application --keepclasseswithmembernames class * { +-keepclasseswithmembernames,includedescriptorclasses class * { native ; } @@ -128,7 +133,4 @@ public static final android.os.Parcelable$Creator *; } --keepattributes LineNumberTable,SourceFile - -# https://stackoverflow.com/a/32615580 --optimizations !class/unboxing/enum \ No newline at end of file +-keepattributes *Annotation*,EnclosingMethod,InnerClasses,LineNumberTable,Signature,SourceFile diff --git a/forge-gui-android/src/com/badlogic/gdx/backends/android/ForgeAndroidApplication.java b/forge-gui-android/src/com/badlogic/gdx/backends/android/ForgeAndroidApplication.java new file mode 100644 index 00000000000..4a38863d058 --- /dev/null +++ b/forge-gui-android/src/com/badlogic/gdx/backends/android/ForgeAndroidApplication.java @@ -0,0 +1,537 @@ +/******************************************************************************* + * Copyright 2011 See AUTHORS file. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +package com.badlogic.gdx.backends.android; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.os.Debug; +import android.os.Handler; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import com.badlogic.gdx.*; +// androidx dependencies disabled so it will not crash Forge app on startup +//import com.badlogic.gdx.backends.android.keyboardheight.AndroidXKeyboardHeightProvider; +//import com.badlogic.gdx.backends.android.keyboardheight.KeyboardHeightProvider; +//import com.badlogic.gdx.backends.android.keyboardheight.StandardKeyboardHeightProvider; +import com.badlogic.gdx.backends.android.surfaceview.FillResolutionStrategy; +import com.badlogic.gdx.utils.*; + +/** A modified implementation of the {@link Application} interface for Android - Forge app. Create an {@link Activity} that derives from this class. + * In the {@link Activity#onCreate(Bundle)} method call the {@link #initialize(ApplicationListener)} method specifying the + * configuration for the GLSurfaceView. + * + * @author mzechner */ +public class ForgeAndroidApplication extends Activity implements AndroidApplicationBase { + + protected AndroidGraphics graphics; + protected AndroidInput input; + protected AndroidAudio audio; + protected AndroidFiles files; + protected AndroidNet net; + protected AndroidClipboard clipboard; + protected ApplicationListener listener; + public Handler handler; + protected boolean firstResume = true; + protected final Array runnables = new Array(); + protected final Array executedRunnables = new Array(); + protected final SnapshotArray lifecycleListeners = new SnapshotArray( + LifecycleListener.class); + private final Array androidEventListeners = new Array(); + protected int logLevel = LOG_INFO; + protected ApplicationLogger applicationLogger; + protected boolean useImmersiveMode = false; + private int wasFocusChanged = -1; + private boolean isWaitingForAudio = false; + //private KeyboardHeightProvider keyboardHeightProvider; + + protected boolean renderUnderCutout = false; + + /** This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get + * input, render via OpenGL and so on. Uses a default {@link AndroidApplicationConfiguration}. + * + * @param listener the {@link ApplicationListener} implementing the program logic **/ + public void initialize (ApplicationListener listener) { + AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); + initialize(listener, config); + } + + /** This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get + * input, render via OpenGL and so on. You can configure other aspects of the application with the rest of the fields in the + * {@link AndroidApplicationConfiguration} instance. + * + * @param listener the {@link ApplicationListener} implementing the program logic + * @param config the {@link AndroidApplicationConfiguration}, defining various settings of the application (use accelerometer, + * etc.). */ + public void initialize (ApplicationListener listener, AndroidApplicationConfiguration config) { + init(listener, config, false); + } + + /** This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get + * input, render via OpenGL and so on. Uses a default {@link AndroidApplicationConfiguration}. + *

+ * Note: you have to add the returned view to your layout! + * + * @param listener the {@link ApplicationListener} implementing the program logic + * @return the GLSurfaceView of the application */ + public View initializeForView (ApplicationListener listener) { + AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); + return initializeForView(listener, config); + } + + /** This method has to be called in the {@link Activity#onCreate(Bundle)} method. It sets up all the things necessary to get + * input, render via OpenGL and so on. You can configure other aspects of the application with the rest of the fields in the + * {@link AndroidApplicationConfiguration} instance. + *

+ * Note: you have to add the returned view to your layout! + * + * @param listener the {@link ApplicationListener} implementing the program logic + * @param config the {@link AndroidApplicationConfiguration}, defining various settings of the application (use accelerometer, + * etc.). + * @return the GLSurfaceView of the application */ + public View initializeForView (ApplicationListener listener, AndroidApplicationConfiguration config) { + init(listener, config, true); + return graphics.getView(); + } + + private void init (ApplicationListener listener, AndroidApplicationConfiguration config, boolean isForView) { + if (this.getVersion() < MINIMUM_SDK) { + throw new GdxRuntimeException("libGDX requires Android API Level " + MINIMUM_SDK + " or later."); + } + config.nativeLoader.load(); + setApplicationLogger(new AndroidApplicationLogger()); + graphics = new AndroidGraphics(this, config, + config.resolutionStrategy == null ? new FillResolutionStrategy() : config.resolutionStrategy); + input = createInput(this, this, graphics.view, config); + audio = createAudio(this, config); + files = createFiles(); + net = new AndroidNet(this, config); + this.listener = listener; + this.handler = new Handler(); + this.useImmersiveMode = config.useImmersiveMode; + this.clipboard = new AndroidClipboard(this); + this.renderUnderCutout = config.renderUnderCutout; + + // Add a specialized audio lifecycle listener + addLifecycleListener(new LifecycleListener() { + + @Override + public void resume () { + // No need to resume audio here + } + + @Override + public void pause () { + audio.pause(); + } + + @Override + public void dispose () { + audio.dispose(); + } + }); + + Gdx.app = this; + Gdx.input = this.getInput(); + Gdx.audio = this.getAudio(); + Gdx.files = this.getFiles(); + Gdx.graphics = this.getGraphics(); + Gdx.net = this.getNet(); + + if (!isForView) { + try { + requestWindowFeature(Window.FEATURE_NO_TITLE); + } catch (Exception ex) { + log("AndroidApplication", "Content already displayed, cannot request FEATURE_NO_TITLE", ex); + } + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + setContentView(graphics.getView(), createLayoutParams()); + } + + createWakeLock(config.useWakelock); + useImmersiveMode(this.useImmersiveMode); + if (this.useImmersiveMode) { + AndroidVisibilityListener vlistener = new AndroidVisibilityListener(); + vlistener.createListener(this); + } + + // detect an already connected bluetooth keyboardAvailable + if (getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS) input.setKeyboardAvailable(true); + + setLayoutInDisplayCutoutMode(this.renderUnderCutout); + + // As per the docs, it might work unreliable < 23 https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02 + // So, I guess since 23 is pretty rare we can use the old API for the users + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + keyboardHeightProvider = new AndroidXKeyboardHeightProvider(this); + } else { + keyboardHeightProvider = new StandardKeyboardHeightProvider(this); + }*/ + } + + protected FrameLayout.LayoutParams createLayoutParams () { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.MATCH_PARENT); + layoutParams.gravity = Gravity.CENTER; + return layoutParams; + } + + protected void createWakeLock (boolean use) { + if (use) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + } + + @TargetApi(Build.VERSION_CODES.P) + private void setLayoutInDisplayCutoutMode (boolean render) { + if (render && getVersion() >= Build.VERSION_CODES.P) { + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + } + + @Override + public void onWindowFocusChanged (boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + useImmersiveMode(this.useImmersiveMode); + if (hasFocus) { + this.wasFocusChanged = 1; + if (this.isWaitingForAudio) { + this.audio.resume(); + this.isWaitingForAudio = false; + } + } else { + this.wasFocusChanged = 0; + } + } + + @Override + public void useImmersiveMode (boolean use) { + if (!use) return; + + View view = getWindow().getDecorView(); + int code = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + view.setSystemUiVisibility(code); + } + + @Override + protected void onPause () { + boolean isContinuous = graphics.isContinuousRendering(); + boolean isContinuousEnforced = AndroidGraphics.enforceContinuousRendering; + + // from here we don't want non continuous rendering + AndroidGraphics.enforceContinuousRendering = true; + graphics.setContinuousRendering(true); + // calls to setContinuousRendering(false) from other thread (ex: GLThread) + // will be ignored at this point... + graphics.pause(); + + input.onPause(); + + if (isFinishing()) { + graphics.clearManagedCaches(); + graphics.destroy(); + } + + AndroidGraphics.enforceContinuousRendering = isContinuousEnforced; + graphics.setContinuousRendering(isContinuous); + + graphics.onPauseGLSurfaceView(); + + super.onPause(); + //keyboardHeightProvider.setKeyboardHeightObserver(null); + } + + @Override + protected void onResume () { + Gdx.app = this; + Gdx.input = this.getInput(); + Gdx.audio = this.getAudio(); + Gdx.files = this.getFiles(); + Gdx.graphics = this.getGraphics(); + Gdx.net = this.getNet(); + + input.onResume(); + + if (graphics != null) { + graphics.onResumeGLSurfaceView(); + } + + if (!firstResume) { + graphics.resume(); + } else + firstResume = false; + + this.isWaitingForAudio = true; + if (this.wasFocusChanged == 1 || this.wasFocusChanged == -1) { + this.audio.resume(); + this.isWaitingForAudio = false; + } + super.onResume(); + /*keyboardHeightProvider.setKeyboardHeightObserver((DefaultAndroidInput)Gdx.input); + ((AndroidGraphics)getGraphics()).getView().post(new Runnable() { + @Override + public void run () { + keyboardHeightProvider.start(); + } + });*/ + } + + @Override + protected void onDestroy () { + super.onDestroy(); + //keyboardHeightProvider.close(); + } + + @Override + public ApplicationListener getApplicationListener () { + return listener; + } + + @Override + public Audio getAudio () { + return audio; + } + + @Override + public AndroidInput getInput () { + return input; + } + + @Override + public Files getFiles () { + return files; + } + + @Override + public Graphics getGraphics () { + return graphics; + } + + @Override + public Net getNet () { + return net; + } + + @Override + public ApplicationType getType () { + return ApplicationType.Android; + } + + @Override + public int getVersion () { + return android.os.Build.VERSION.SDK_INT; + } + + @Override + public long getJavaHeap () { + return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + } + + @Override + public long getNativeHeap () { + return Debug.getNativeHeapAllocatedSize(); + } + + @Override + public Preferences getPreferences (String name) { + return new AndroidPreferences(getSharedPreferences(name, Context.MODE_PRIVATE)); + } + + @Override + public Clipboard getClipboard () { + return clipboard; + } + + @Override + public void postRunnable (Runnable runnable) { + synchronized (runnables) { + runnables.add(runnable); + Gdx.graphics.requestRendering(); + } + } + + @Override + public void onConfigurationChanged (Configuration config) { + super.onConfigurationChanged(config); + boolean keyboardAvailable = false; + if (config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) keyboardAvailable = true; + input.setKeyboardAvailable(keyboardAvailable); + } + + @Override + public void exit () { + handler.post(new Runnable() { + @Override + public void run () { + ForgeAndroidApplication.this.finish(); + } + }); + } + + @Override + public void debug (String tag, String message) { + if (logLevel >= LOG_DEBUG) getApplicationLogger().debug(tag, message); + } + + @Override + public void debug (String tag, String message, Throwable exception) { + if (logLevel >= LOG_DEBUG) getApplicationLogger().debug(tag, message, exception); + } + + @Override + public void log (String tag, String message) { + if (logLevel >= LOG_INFO) getApplicationLogger().log(tag, message); + } + + @Override + public void log (String tag, String message, Throwable exception) { + if (logLevel >= LOG_INFO) getApplicationLogger().log(tag, message, exception); + } + + @Override + public void error (String tag, String message) { + if (logLevel >= LOG_ERROR) getApplicationLogger().error(tag, message); + } + + @Override + public void error (String tag, String message, Throwable exception) { + if (logLevel >= LOG_ERROR) getApplicationLogger().error(tag, message, exception); + } + + @Override + public void setLogLevel (int logLevel) { + this.logLevel = logLevel; + } + + @Override + public int getLogLevel () { + return logLevel; + } + + @Override + public void setApplicationLogger (ApplicationLogger applicationLogger) { + this.applicationLogger = applicationLogger; + } + + @Override + public ApplicationLogger getApplicationLogger () { + return applicationLogger; + } + + @Override + public void addLifecycleListener (LifecycleListener listener) { + synchronized (lifecycleListeners) { + lifecycleListeners.add(listener); + } + } + + @Override + public void removeLifecycleListener (LifecycleListener listener) { + synchronized (lifecycleListeners) { + lifecycleListeners.removeValue(listener, true); + } + } + + @Override + protected void onActivityResult (int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + // forward events to our listeners if there are any installed + synchronized (androidEventListeners) { + for (int i = 0; i < androidEventListeners.size; i++) { + androidEventListeners.get(i).onActivityResult(requestCode, resultCode, data); + } + } + } + + /** Adds an event listener for Android specific event such as onActivityResult(...). */ + public void addAndroidEventListener (AndroidEventListener listener) { + synchronized (androidEventListeners) { + androidEventListeners.add(listener); + } + } + + /** Removes an event listener for Android specific event such as onActivityResult(...). */ + public void removeAndroidEventListener (AndroidEventListener listener) { + synchronized (androidEventListeners) { + androidEventListeners.removeValue(listener, true); + } + } + + @Override + public Context getContext () { + return this; + } + + @Override + public Array getRunnables () { + return runnables; + } + + @Override + public Array getExecutedRunnables () { + return executedRunnables; + } + + @Override + public SnapshotArray getLifecycleListeners () { + return lifecycleListeners; + } + + @Override + public Window getApplicationWindow () { + return this.getWindow(); + } + + @Override + public Handler getHandler () { + return this.handler; + } + + @Override + public AndroidAudio createAudio (Context context, AndroidApplicationConfiguration config) { + if (!config.disableAudio) + return new DefaultAndroidAudio(context, config); + else + return new DisabledAndroidAudio(); + } + + @Override + public AndroidInput createInput (Application activity, Context context, Object view, AndroidApplicationConfiguration config) { + return new DefaultAndroidInput(this, this, graphics.view, config); + } + + protected AndroidFiles createFiles () { + this.getFilesDir(); // workaround for Android bug #10515463 + return new DefaultAndroidFiles(this.getAssets(), this, true); + } + + /*public KeyboardHeightProvider getKeyboardHeightProvider () { + return keyboardHeightProvider; + }*/ +} \ No newline at end of file diff --git a/forge-gui-android/src/forge/app/Main.java b/forge-gui-android/src/forge/app/Main.java index de4e9f9a10d..1456dd14155 100644 --- a/forge-gui-android/src/forge/app/Main.java +++ b/forge-gui-android/src/forge/app/Main.java @@ -13,6 +13,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -23,6 +24,8 @@ import android.graphics.Typeface; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; @@ -48,7 +51,7 @@ import android.widget.TableRow; import android.widget.TextView; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Version; -import com.badlogic.gdx.backends.android.AndroidApplication; +import com.badlogic.gdx.backends.android.ForgeAndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; import com.badlogic.gdx.backends.android.AndroidAudio; import com.badlogic.gdx.backends.android.AsynchronousAndroidAudio; @@ -69,7 +72,7 @@ import java.io.OutputStream; import java.text.Normalizer; import java.util.ArrayList; -public class Main extends AndroidApplication { +public class Main extends ForgeAndroidApplication { private AndroidAdapter Gadapter; private ArrayList gamepads; private AndroidClipboard androidClipboard; @@ -80,6 +83,7 @@ public class Main extends AndroidApplication { private View forgeLogo = null, forgeView = null, activeView = null; private ProgressBar progressBar; private TextView progressText; + private String versionString; private AndroidClipboard getAndroidClipboard() { if (androidClipboard == null) @@ -130,6 +134,12 @@ public class Main extends AndroidApplication { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + try { + PackageInfo pInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0); + versionString = pInfo.versionName; + } catch (Exception e) { + versionString = "0.0"; + } setContentView(getResources().getIdentifier("main", "layout", getPackageName())); mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime); sharedPreferences = getPreferences(Context.MODE_PRIVATE); @@ -205,7 +215,12 @@ public class Main extends AndroidApplication { TextView text = new TextView(this); text.setGravity(Gravity.LEFT); text.setTypeface(Typeface.SERIF); - String SP = Build.VERSION.SDK_INT > 29 ? "Files & Media" : "Storage Permission"; + String SP = "Storage Permission"; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + SP = "Photos and Videos, Music and Audio Permissions"; + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + SP = "Files & Media Permissions"; + } String title = "Forge needs " + SP + " to run properly...\n" + "Follow these simple steps:\n\n"; @@ -287,7 +302,7 @@ public class Main extends AndroidApplication { displayMessage(forgeLogo, adapter, exception, msg, false); } else if (title.isEmpty() && steps.isEmpty()) { if (isLandscape) { - Main.this.setRequestedOrientation(Build.VERSION.SDK_INT >= 26 ? + Main.this.setRequestedOrientation(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : //Oreo and above has virtual back/menu buttons ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { @@ -376,8 +391,9 @@ public class Main extends AndroidApplication { private AnimatorSet getAnimator(Animator play, Animator with, AnimatorListenerAdapter adapter) { AnimatorSet animatorSet = new AnimatorSet(); - if (with != null) - animatorSet.play(play).with(with); + if (with != null) { + animatorSet.playTogether(play, with); + } else animatorSet.play(play); animatorSet.addListener(adapter); @@ -396,8 +412,14 @@ public class Main extends AndroidApplication { int pid = android.os.Process.myPid(); int uid = android.os.Process.myUid(); try { - int result = getBaseContext().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, uid); - return result == PackageManager.PERMISSION_GRANTED; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (getBaseContext().checkPermission(android.Manifest.permission.READ_MEDIA_IMAGES, pid, uid) == PackageManager.PERMISSION_GRANTED) + if (getBaseContext().checkPermission(android.Manifest.permission.READ_MEDIA_AUDIO, pid, uid) == PackageManager.PERMISSION_GRANTED) + return getBaseContext().checkPermission(android.Manifest.permission.READ_MEDIA_VIDEO, pid, uid) == PackageManager.PERMISSION_GRANTED; + return false; + } else { + return getBaseContext().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, uid) == PackageManager.PERMISSION_GRANTED; + } } catch (NullPointerException e) { return false; } @@ -418,7 +440,7 @@ public class Main extends AndroidApplication { loadGame("", "", false, adapter, permissiongranted, totalRAM, isTabletDevice, config, true, message); return; } - ASSETS_DIR = Build.VERSION.SDK_INT > 29 ? getContext().getObbDir() + "/Forge/" : Environment.getExternalStorageDirectory() + "/Forge/"; + ASSETS_DIR = Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ? getContext().getObbDir() + "/Forge/" : Environment.getExternalStorageDirectory() + "/Forge/"; if (!FileUtil.ensureDirectoryExists(ASSETS_DIR)) { String message = getDeviceName() + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB" + "\n" + "LibGDX " + Version.VERSION + "\n" + "Can't access external storage\nPath: " + ASSETS_DIR; Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation); @@ -442,11 +464,11 @@ public class Main extends AndroidApplication { adapter.switchOrientationFile = ASSETS_DIR + "switch_orientation.ini"; boolean landscapeMode = adapter.isTablet == !FileUtil.doesFileExist(adapter.switchOrientationFile); - String info = totalRAM < 3500 || Build.VERSION.SDK_INT < 29 ? "Device Specification Check\n" + getDeviceName() + String info = totalRAM < 3500 || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q ? "Device Specification Check\n" + getDeviceName() + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB\n\nMinimum Requirements:" : ""; - String lowV = Build.VERSION.SDK_INT < 29 ? "\nAPI: Android 10 or higher" : ""; + String lowV = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q ? "\nAPI: Android 10 or higher" : ""; String lowM = totalRAM < 3500 ? "\nRAM: 4GB RAM or higher" : ""; - if (landscapeMode && Build.VERSION.SDK_INT > 32) { + if (landscapeMode && Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { //Android 11 onwards Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); } loadGame(info, lowV + lowM, landscapeMode, adapter, permissiongranted, totalRAM, isTabletDevice, config, false, ""); @@ -484,9 +506,12 @@ public class Main extends AndroidApplication { @Override public boolean hasContents() { - if (cm.getPrimaryClip().getItemCount() > 0) { + ClipData clipData = cm.getPrimaryClip(); + if (clipData == null) + return false; + if (clipData.getItemCount() > 0) { try { - return cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).length() > 0; + return clipData.getItemAt(0).coerceToText(getContext()).length() > 0; } catch (Exception ex) { return false; } @@ -496,9 +521,12 @@ public class Main extends AndroidApplication { @Override public String getContents() { - if (cm.getPrimaryClip().getItemCount() > 0) { + ClipData clipData = cm.getPrimaryClip(); + if (clipData == null) + return ""; + if (clipData.getItemCount() > 0) { try { - String text = cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).toString(); + String text = clipData.getItemAt(0).coerceToText(getContext()).toString(); return Normalizer.normalize(text, Normalizer.Form.NFD); } catch (Exception ex) { ex.printStackTrace(); @@ -521,27 +549,78 @@ public class Main extends AndroidApplication { private final boolean isTablet; private final ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); private String switchOrientationFile; + private final Context context; + private boolean connected; private AndroidAdapter(Context context) { + this.context = context; isTablet = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; - } + try { + if (connManager != null) { + connManager.registerDefaultNetworkCallback( + new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(Network network) { + connected = true; + } + @Override + public void onLost(Network network) { + connected = false; + } + } + ); + } + } catch (Exception e) { + connected = false; + } + } + private boolean hasInternet() { + return isNetworkConnected(false); + } + private boolean hasWiFiInternet() { + return isNetworkConnected(true); + } + private boolean isNetworkConnected(boolean wifiOnly) { + boolean result = false; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (connManager != null) { + NetworkCapabilities capabilities = connManager.getNetworkCapabilities(connManager.getActiveNetwork()); + if (capabilities != null) { + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + result = connected; + } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + result = connected && !wifiOnly; + } + } + } + } else { + if (connManager != null) { + NetworkInfo activeNetwork = connManager.getActiveNetworkInfo(); + if (activeNetwork != null) { + // connected to the internet + if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { + result = true; + } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { + result = !wifiOnly; + } + } + } + } + return result; + } @Override public boolean isConnectedToInternet() { - return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(() -> { - NetworkInfo activeNetworkInfo = connManager.getActiveNetworkInfo(); - return activeNetworkInfo != null && activeNetworkInfo.isConnected(); - }, 2000)); //if can't determine Internet connection within two seconds, assume not connected + //if it can't determine Internet connection within two seconds, assume not connected + return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(this::hasInternet, 2000)); } @Override public boolean isConnectedToWifi() { - return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(() -> { - NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); - return wifi.isConnected(); - }, 2000)); //if can't determine Internet connection within two seconds, assume not connected + //if it can't determine Internet connection within two seconds, assume not connected + return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(this::hasWiFiInternet, 2000)); } @Override @@ -549,6 +628,11 @@ public class Main extends AndroidApplication { return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"; } + @Override + public String getVersionString() { + return versionString; + } + @Override public boolean openFile(String filename) { try { @@ -587,6 +671,11 @@ public class Main extends AndroidApplication { System.exit(0); } + @Override + public void closeSplashScreen() { + //only for desktop mobile-dev + } + @Override public boolean isTablet() { return isTablet; @@ -622,7 +711,7 @@ public class Main extends AndroidApplication { WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point size = new Point(); - if (Build.VERSION.SDK_INT >= 17) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // Seems it doesn't compile if using 4.1.1.4 since it's missing this method if (real) display.getRealSize(size); @@ -630,7 +719,7 @@ public class Main extends AndroidApplication { display.getSize(size); //remove this line below and use the method above if using Android libs higher than 4.1.1.4 //return Pair.of(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); // this method don't take account the soft navigation bars taken in rendered screen - } else if (Build.VERSION.SDK_INT >= 14) { + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { try { size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display); size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display); diff --git a/forge-gui-android/src/main/AndroidManifest.xml b/forge-gui-android/src/main/AndroidManifest.xml index ac4c1117274..d7c65c78e87 100644 --- a/forge-gui-android/src/main/AndroidManifest.xml +++ b/forge-gui-android/src/main/AndroidManifest.xml @@ -4,10 +4,25 @@ + android:targetSdkVersion="35" /> + + + + + + + + - + + + @@ -21,20 +36,22 @@ android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:label="@string/app_name" - android:largeHeap="true"> + android:largeHeap="true" + android:resizeableActivity="false"> - - - - - - - - - + android:name=".Launcher" + android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode" + android:theme="@style/Theme.Transparent" + android:exported="true"> + + + + + + + + + forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui-desktop @@ -15,28 +15,86 @@ 0 0 0 + --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dfile.encoding=UTF-8 - + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 2.5.1 + + + l4j-gui + package + + launch4j + + + gui + ${project.build.directory}/forge.exe + ${project.build.finalName}-jar-with-dependencies.jar + true + forge + https://bell-sw.com/pages/downloads/#jdk-17-lts + src/main/config/forge.ico + + forge.view.Main + false + anything + + + 17 + true + 4096 + + ${mandatory.java.args} + + + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + Forge + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 + + Forge + forge + forge.exe + + + + + org.apache.maven.plugins maven-jar-plugin - 2.4 + 3.3.0 true true + + java.desktop/java.beans java.desktop/javax.swing.border java.desktop/javax.swing.event java.desktop/sun.swing java.desktop/java.awt.image java.desktop/java.awt.color java.desktop/sun.awt.image java.desktop/javax.swing java.desktop/java.awt java.base/java.util java.base/java.lang java.base/java.lang.reflect java.base/java.text java.desktop/java.awt.font java.base/jdk.internal.misc java.base/sun.nio.ch java.base/java.nio java.base/java.math java.base/java.util.concurrent java.base/java.net + com.google.code.maven-replacer-plugin replacer - 1.5.2 + 1.5.3 package @@ -56,6 +114,10 @@ $project.build.finalName$ ${project.build.finalName}-jar-with-dependencies.jar + + $mandatory.java.args$ + ${mandatory.java.args} + @@ -68,9 +130,12 @@ - forge.view.Main true + + java.desktop/java.beans java.desktop/javax.swing.border java.desktop/javax.swing.event java.desktop/sun.swing java.desktop/java.awt.image java.desktop/java.awt.color java.desktop/sun.awt.image java.desktop/javax.swing java.desktop/java.awt java.base/java.util java.base/java.lang java.base/java.lang.reflect java.base/java.text java.desktop/java.awt.font java.base/jdk.internal.misc java.base/sun.nio.ch java.base/java.nio java.base/java.math java.base/java.util.concurrent java.base/java.net + forge.view.Main + @@ -88,7 +153,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 + 3.6.0 released-version @@ -108,7 +173,7 @@ se.bjurr.gitchangelog git-changelog-maven-plugin - 1.92 + 1.101.0 GenerateGitChangelog @@ -188,37 +253,87 @@ com.mortennobel java-image-scaling - 0.8.5 + 0.8.6 org.powermock powermock-module-testng-common 2.0.9 + + + com.beust + jcommander + + + net.bytebuddy + byte-buddy + + + org.testng + testng + + + org.objenesis + objenesis + + + net.bytebuddy + byte-buddy-agent + + org.testng testng - 7.4.0 + 7.10.2 test + + + com.beust + jcommander + + org.powermock powermock-module-testng 2.0.9 test + + + org.testng + testng + + org.powermock powermock-core 2.0.9 test + + + net.bytebuddy + byte-buddy + + + net.bytebuddy + byte-buddy-agent + + org.powermock powermock-api-mockito2 2.0.9 test + + + org.mockito + mockito-core + + org.powermock @@ -229,502 +344,75 @@ org.mockito mockito-core - 3.12.4 + 5.14.2 test + + + org.objenesis + objenesis + + + net.bytebuddy + byte-buddy + + + net.bytebuddy + byte-buddy-agent + + net.bytebuddy byte-buddy - 1.12.3 + 1.15.5 net.bytebuddy byte-buddy-agent - 1.12.3 + 1.15.5 test org.objenesis objenesis - 3.2 + 3.4 test org.freemarker freemarker - 2.3.31 + 2.3.33 com.googlecode.soundlibs jlayer - 1.0.1-1 + 1.0.1.4 com.beust jcommander - 1.78 + 1.82 jar com.sipgate mp3-wav - 1.0.3 + 1.0.4 + + + com.googlecode.soundlibs + jlayer + + com.twelvemonkeys.imageio imageio-jpeg - 3.7.0 + 3.12.0 - - windows-linux-release - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 2.1.2 - - - l4j-gui - package - - launch4j - - - gui - ${project.build.directory}/forge-java8.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge.ico - - forge.view.Main - false - anything - - - 1.8.0 - 4096 - - -Dfile.encoding=UTF-8 - - - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - Forge - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - forge - forge-java8.exe - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - win-linux-app-bundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.1.0 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}.tar.bz2 - tar.bz2 - - - - - - - - - - - - windows-linux - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 2.1.2 - - - l4j-gui - package - - launch4j - - - gui - ${project.build.directory}/forge-java8.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge.ico - - forge.view.Main - false - anything - - - 1.8.0 - 4096 - - -Dfile.encoding=UTF-8 - - - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - Forge - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - forge - forge-java8.exe - - - - - - l4j-gui2 - package - - launch4j - - - gui - ${project.build.directory}/forge.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - https://www.oracle.com/java/technologies/downloads/ - src/main/config/forge.ico - - forge.view.Main - false - anything - - - 11.0.1 - jdkOnly - 4096 - - -Dfile.encoding=UTF-8 - --add-opens java.base/java.lang=ALL-UNNAMED - --add-opens java.base/java.math=ALL-UNNAMED - --add-opens java.base/jdk.internal.misc=ALL-UNNAMED - --add-opens java.base/java.nio=ALL-UNNAMED - --add-opens=java.base/sun.nio.ch=ALL-UNNAMED - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang.reflect=ALL-UNNAMED - --add-opens java.base/java.text=ALL-UNNAMED - --add-opens java.desktop/java.awt=ALL-UNNAMED - --add-opens java.desktop/java.awt.font=ALL-UNNAMED - --add-opens java.desktop/java.awt.image=ALL-UNNAMED - --add-opens java.desktop/java.awt.color=ALL-UNNAMED - --add-opens java.desktop/sun.awt.image=ALL-UNNAMED - --add-opens java.desktop/javax.swing=ALL-UNNAMED - --add-opens java.desktop/javax.swing.border=ALL-UNNAMED - --add-opens java.desktop/javax.swing.event=ALL-UNNAMED - --add-opens java.desktop/sun.swing=ALL-UNNAMED - --add-opens java.desktop/java.beans=ALL-UNNAMED - --add-opens java.base/java.util.concurrent=ALL-UNNAMED - --add-opens java.base/java.net=ALL-UNNAMED - -Dio.netty.tryReflectionSetAccessible=true - - - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - Forge - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - - ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}.0 - - Forge - forge - forge.exe - - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - org.apache.ant - ant-nodeps - 1.8.1 - - - - - win-linux-app-bundle - pre-integration-test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.1.0 - - - released-version - validate - - released-version - - - - parse-version - - parse-version - - - - attach-distribution - post-integration-test - - attach-artifact - - - - - ${project.build.directory}/${project.build.finalName}.tar.bz2 - tar.bz2 - - - - - - - - - - "LICENSE.txt" @@ -739,7 +427,7 @@ org.apache.maven.plugins maven-antrun-plugin - 1.7 + 3.0.0 org.apache.ant @@ -801,7 +489,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 + 3.6.0 released-version @@ -854,7 +542,7 @@ org.apache.maven.plugins maven-antrun-plugin - 1.7 + 3.0.0 org.apache.ant @@ -912,7 +600,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 + 3.6.0 released-version diff --git a/forge-gui-desktop/src/main/config/forge.cmd b/forge-gui-desktop/src/main/config/forge.cmd index 8779fa25870..31c7816b15a 100644 --- a/forge-gui-desktop/src/main/config/forge.cmd +++ b/forge-gui-desktop/src/main/config/forge.cmd @@ -9,17 +9,16 @@ java -version 1>nul 2>nul || ( ) for /f tokens^=2^ delims^=.-_^+^" %%j in ('java -fullversion 2^>^&1') do set "jver=%%j" +if %jver% LEQ 16 ( + echo unsupported java + popd + exit /b 2 +) + if %jver% GEQ 17 ( - java --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ + java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ popd exit /b 0 ) -if %jver% GEQ 11 ( - java --illegal-access=permit -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ - popd - exit /b 0 -) - -java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ popd \ No newline at end of file diff --git a/forge-gui-desktop/src/main/config/forge.command b/forge-gui-desktop/src/main/config/forge.command index 1e3165f2ed0..6aa6eee97e0 100644 --- a/forge-gui-desktop/src/main/config/forge.command +++ b/forge-gui-desktop/src/main/config/forge.command @@ -1,3 +1,3 @@ #!/bin/sh cd $(dirname "${0}") -java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ +java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ diff --git a/forge-gui-desktop/src/main/config/forge.sh b/forge-gui-desktop/src/main/config/forge.sh index 8d53f38d841..6aa6eee97e0 100644 --- a/forge-gui-desktop/src/main/config/forge.sh +++ b/forge-gui-desktop/src/main/config/forge.sh @@ -1,52 +1,3 @@ -#!/bin/bash - -# returns the JDK version. -# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected -# Based on the code from this source: https://eed3si9n.com/detecting-java-version-bash -jdk_version() { - local result - local java_cmd - if [[ -n $(type -p java) ]] - then - java_cmd=java - elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]] - then - java_cmd="$JAVA_HOME/bin/java" - fi - local IFS=$'\n' - # remove \r for Cygwin - local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n') - if [[ -z $java_cmd ]] - then - result=no_java - else - for line in $lines; do - if [[ (-z $result) && ($line = *"version \""*) ]] - then - local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q') - # on macOS, sed doesn't support '?' - if [[ $ver = "1."* ]] - then - result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q') - else - result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q') - fi - fi - done - fi - echo "$result" -} -v="$(jdk_version)" - -SHAREDPARAMS='-Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ '"$@" +#!/bin/sh cd $(dirname "${0}") - -if [[ $v -ge 17 ]] -then - java --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true $SHAREDPARAMS -elif [[ $v -ge 11 ]] -then - java --illegal-access=permit $SHAREDPARAMS -else - java $SHAREDPARAMS -fi +java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FCardImageRenderer.java b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FCardImageRenderer.java index 4a3f911309b..4b6fb7c1070 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FCardImageRenderer.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FCardImageRenderer.java @@ -699,7 +699,8 @@ public class FCardImageRenderer { } } else { fillColorBackground(g, colors, x, y, w, h); - SkinIcon icon = FSkin.getIcon(FSkinProp.ICO_LOGO); + //Card Art Logo + SkinIcon icon = FSkin.getIcon(FSkinProp.ICO_CARDART); float artWidth = (float)icon.getSizeForPaint(g).getWidth(); float artHeight = (float)icon.getSizeForPaint(g).getHeight(); if (artWidth / artHeight >= (float)w / (float)h) { diff --git a/forge-gui-desktop/src/main/java/forge/view/Main.java b/forge-gui-desktop/src/main/java/forge/view/Main.java index e10f1dc3d4c..e4ab36ca5da 100644 --- a/forge-gui-desktop/src/main/java/forge/view/Main.java +++ b/forge-gui-desktop/src/main/java/forge/view/Main.java @@ -6,12 +6,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -33,12 +33,14 @@ public final class Main { * Main entry point for Forge */ public static void main(final String[] args) { - Sentry.init(options -> { options.setEnableExternalConfiguration(true); options.setRelease(BuildInfo.getVersionString()); options.setEnvironment(System.getProperty("os.name")); options.setTag("Java Version", System.getProperty("java.version")); + options.setShutdownTimeoutMillis(5000); + if (options.getDsn() == null) + options.setDsn("https://87bc8d329e49441895502737c069067b@sentry.cardforge.org//3"); }, true); // HACK - temporary solution to "Comparison method violates it's general contract!" crash @@ -46,7 +48,7 @@ public final class Main { //Turn off the Java 2D system's use of Direct3D to improve rendering speed (particularly when Full Screen) System.setProperty("sun.java2d.d3d", "false"); - + //Turn on OpenGl acceleration to improve performance //System.setProperty("sun.java2d.opengl", "True"); @@ -67,30 +69,30 @@ public final class Main { // command line startup here String mode = args[0].toLowerCase(); - - switch(mode) { + + switch (mode) { case "sim": SimulateMatch.simulate(args); break; case "parse": - CardReaderExperiments.parseAllCards(args); + CardReaderExperiments.parseAllCards(args); break; case "server": System.out.println("Dedicated server mode.\nNot implemented."); break; - + default: System.out.println("Unknown mode.\nKnown mode is 'sim', 'parse' "); break; } - + System.exit(0); } @SuppressWarnings("deprecation") - @Override + @Override protected void finalize() throws Throwable { try { ExceptionHandler.unregisterErrorHandling(); @@ -100,5 +102,6 @@ public final class Main { } // disallow instantiation - private Main() { } + private Main() { + } } diff --git a/forge-gui-desktop/src/test/java/forge/card/CardMockTestCase.java b/forge-gui-desktop/src/test/java/forge/card/CardMockTestCase.java index cc0b9748a89..13e35f92b45 100644 --- a/forge-gui-desktop/src/test/java/forge/card/CardMockTestCase.java +++ b/forge-gui-desktop/src/test/java/forge/card/CardMockTestCase.java @@ -16,9 +16,9 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.powermock.modules.testng.PowerMockTestCase; -import org.testng.IObjectFactory; +//import org.testng.IObjectFactory; import org.testng.annotations.BeforeMethod; -import org.testng.annotations.ObjectFactory; +//import org.testng.annotations.ObjectFactory; import forge.ImageCache; import forge.ImageKeys; @@ -184,8 +184,8 @@ public class CardMockTestCase extends PowerMockTestCase { PowerMockito.when(FModel.getMagicDb()).thenReturn(data); } - @ObjectFactory + /*@ObjectFactory public IObjectFactory getObjectFactory() { return new org.powermock.modules.testng.PowerMockObjectFactory(); - } + }*/ } diff --git a/forge-gui-ios/libs/gdx-backend-robovm-sources.jar b/forge-gui-ios/libs/gdx-backend-robovm-sources.jar index 4c52154c7e7..5292538e22c 100644 Binary files a/forge-gui-ios/libs/gdx-backend-robovm-sources.jar and b/forge-gui-ios/libs/gdx-backend-robovm-sources.jar differ diff --git a/forge-gui-ios/libs/gdx-backend-robovm.jar b/forge-gui-ios/libs/gdx-backend-robovm.jar index ddf5c9bbfcf..f0c3576d5e5 100644 Binary files a/forge-gui-ios/libs/gdx-backend-robovm.jar and b/forge-gui-ios/libs/gdx-backend-robovm.jar differ diff --git a/forge-gui-ios/libs/gdx-sources.jar b/forge-gui-ios/libs/gdx-sources.jar index 22d94b50342..11bed47689d 100644 Binary files a/forge-gui-ios/libs/gdx-sources.jar and b/forge-gui-ios/libs/gdx-sources.jar differ diff --git a/forge-gui-ios/libs/gdx.jar b/forge-gui-ios/libs/gdx.jar index 1a0381b8566..50d65286c35 100644 Binary files a/forge-gui-ios/libs/gdx.jar and b/forge-gui-ios/libs/gdx.jar differ diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index dcac7acc2ba..e72343d5356 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -6,13 +6,12 @@ jar -Xms128m -Xmx2048m - 1.6.58.001 forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui-ios @@ -25,8 +24,8 @@ maven-compiler-plugin - 1.8 - 1.8 + 17 + 17 @@ -36,7 +35,7 @@ true - forge-ios-${alpha-version} + forge-ios-${revision} @@ -68,7 +67,7 @@ com.badlogicgames.gdx gdx-backend-robovm - 1.12.1 + 1.13.0 diff --git a/forge-gui-ios/src/forge/ios/Main.java b/forge-gui-ios/src/forge/ios/Main.java index fc9c20256b7..fc452ca70ba 100644 --- a/forge-gui-ios/src/forge/ios/Main.java +++ b/forge-gui-ios/src/forge/ios/Main.java @@ -17,27 +17,18 @@ import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration; import com.badlogic.gdx.backends.iosrobovm.IOSFiles; import forge.Forge; -import forge.assets.AssetsDownloader; import forge.interfaces.IDeviceAdapter; -import forge.localinstance.properties.ForgePreferences; -import forge.model.FModel; -import forge.util.FileUtil; public class Main extends IOSApplication.Delegate { @Override protected IOSApplication createApplication() { final String assetsDir = new IOSFiles().getLocalStoragePath() + "/../../forge.ios.Main.app/"; - if (!AssetsDownloader.SHARE_DESKTOP_ASSETS) { - FileUtil.ensureDirectoryExists(assetsDir); - } final IOSApplicationConfiguration config = new IOSApplicationConfiguration(); config.useAccelerometer = false; config.useCompass = false; - ForgePreferences prefs = FModel.getPreferences(); - boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT);//todo get totalRAM && isTabletDevice - final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, propertyConfig, false, 0, false, 0, "", ""); + final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, false, false, 0, false, 0, "", ""); final IOSApplication iosApp = new IOSApplication(app, config); return iosApp; } @@ -82,6 +73,11 @@ public class Main extends IOSApplication.Delegate { return new IOSFiles().getExternalStoragePath(); } + @Override + public String getVersionString() { + return "0.0"; + } + @Override public boolean openFile(final String filename) { return new IOSFiles().local(filename).exists(); @@ -112,6 +108,11 @@ public class Main extends IOSApplication.Delegate { // Not possible on iOS } + @Override + public void closeSplashScreen() { + //only for desktop mobile-dev + } + @Override public void convertToJPEG(InputStream input, OutputStream output) throws IOException { diff --git a/forge-gui-mobile-dev/fallback_skin/bg_splash.png b/forge-gui-mobile-dev/fallback_skin/bg_splash.png index 66249347632..0bcba091a57 100644 Binary files a/forge-gui-mobile-dev/fallback_skin/bg_splash.png and b/forge-gui-mobile-dev/fallback_skin/bg_splash.png differ diff --git a/forge-gui-mobile-dev/fallback_skin/bg_texture.jpg b/forge-gui-mobile-dev/fallback_skin/bg_texture.jpg index 7c925524eb3..50f37309ff0 100644 Binary files a/forge-gui-mobile-dev/fallback_skin/bg_texture.jpg and b/forge-gui-mobile-dev/fallback_skin/bg_texture.jpg differ diff --git a/forge-gui-mobile-dev/fallback_skin/font1.ttf b/forge-gui-mobile-dev/fallback_skin/font1.ttf index 4b4ecc66671..28cf43d7e7f 100644 Binary files a/forge-gui-mobile-dev/fallback_skin/font1.ttf and b/forge-gui-mobile-dev/fallback_skin/font1.ttf differ diff --git a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar index 0485da75bac..96604cce9ff 100644 Binary files a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar and b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar differ diff --git a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl.jar b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl.jar index f1422b30d71..d893c882a8d 100644 Binary files a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl.jar and b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl.jar differ diff --git a/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar b/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar index b8c835fd2c2..c2f4f26f422 100644 Binary files a/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar and b/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar differ diff --git a/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar b/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar index 564d2f5139e..8e1f595b0b3 100644 Binary files a/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar and b/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar differ diff --git a/forge-gui-mobile-dev/libs/gdx-natives.jar b/forge-gui-mobile-dev/libs/gdx-natives.jar index fb8b5e13ec2..15c0b61ffe5 100644 Binary files a/forge-gui-mobile-dev/libs/gdx-natives.jar and b/forge-gui-mobile-dev/libs/gdx-natives.jar differ diff --git a/forge-gui-mobile-dev/pom.xml b/forge-gui-mobile-dev/pom.xml index 362dfd6860f..1f69a13cb61 100644 --- a/forge-gui-mobile-dev/pom.xml +++ b/forge-gui-mobile-dev/pom.xml @@ -1,10 +1,15 @@ 4.0.0 + + ${maven.build.timestamp} + yyyy-MM-dd HH:mm:ss + --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dfile.encoding=UTF-8 + forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui-mobile-dev @@ -27,6 +32,7 @@ **/bg_splash.png **/bg_texture.jpg **/font1.ttf + **/logo.gif @@ -34,41 +40,14 @@ maven-compiler-plugin - 1.8 - 1.8 - - - - - com.google.code.maven-replacer-plugin - replacer - 1.5.2 - - - package - - replace - - - - - ${basedir}/${configSourceDirectory} - forge-adventure.sh, forge-adventure-mac.sh, forge-adventure.command, forge-adventure.cmd - ${project.build.directory} - . - false - - - $project.build.finalName$ - ${project.build.finalName}-jar-with-dependencies.jar - - + 17 + 17 com.akathist.maven.plugins.launch4j launch4j-maven-plugin - 1.7.25 + 2.5.1 l4j-adv @@ -76,93 +55,20 @@ launch4j - - gui - ${project.build.directory}/forge-adventure-java8.exe - ${project.build.finalName}-jar-with-dependencies.jar - true - forge - src/main/config/forge-adventure.ico - - forge.app.Main - false - anything - - - 1.8.0 - 4096 - - -Dfile.encoding=UTF-8 - - - - - 1.0.0.0 - - - 1.0.0.0 - - Forge - Forge - - 1.0.0.0 - - - 1.0.0.0 - - forge-adventure - forge-adventure - forge-adventure-java8.exe - - - - - - l4j-adv2 - package - - launch4j - gui ${project.build.directory}/forge-adventure.exe ${project.build.finalName}-jar-with-dependencies.jar true forge - https://www.oracle.com/java/technologies/downloads/ + https://bell-sw.com/pages/downloads/#jdk-17-lts src/main/config/forge-adventure.ico - - forge.app.Main - false - anything - - 11.0.1 - jdkOnly + 17 + true 4096 - -Dfile.encoding=UTF-8 - --add-opens java.base/java.lang=ALL-UNNAMED - --add-opens java.base/java.math=ALL-UNNAMED - --add-opens java.base/jdk.internal.misc=ALL-UNNAMED - --add-opens java.base/java.nio=ALL-UNNAMED - --add-opens=java.base/sun.nio.ch=ALL-UNNAMED - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang.reflect=ALL-UNNAMED - --add-opens java.base/java.text=ALL-UNNAMED - --add-opens java.desktop/java.awt=ALL-UNNAMED - --add-opens java.desktop/java.awt.font=ALL-UNNAMED - --add-opens java.desktop/java.awt.image=ALL-UNNAMED - --add-opens java.desktop/java.awt.color=ALL-UNNAMED - --add-opens java.desktop/sun.awt.image=ALL-UNNAMED - --add-opens java.desktop/javax.swing=ALL-UNNAMED - --add-opens java.desktop/javax.swing.border=ALL-UNNAMED - --add-opens java.desktop/javax.swing.event=ALL-UNNAMED - --add-opens java.desktop/sun.swing=ALL-UNNAMED - --add-opens java.desktop/java.beans=ALL-UNNAMED - --add-opens java.base/java.util.concurrent=ALL-UNNAMED - --add-opens java.base/java.net=ALL-UNNAMED - -Dio.netty.tryReflectionSetAccessible=true + ${mandatory.java.args} @@ -189,6 +95,36 @@ + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + package + + replace + + + + + ${basedir}/${configSourceDirectory} + forge-adventure.sh, forge-adventure.command, forge-adventure.cmd + ${project.build.directory} + . + false + + + $project.build.finalName$ + ${project.build.finalName}-jar-with-dependencies.jar + + + $mandatory.java.args$ + ${mandatory.java.args} + + + + maven-assembly-plugin @@ -198,9 +134,13 @@ - forge.app.Main true + + java.desktop/java.beans java.desktop/javax.swing.border java.desktop/javax.swing.event java.desktop/sun.swing java.desktop/java.awt.image java.desktop/java.awt.color java.desktop/sun.awt.image java.desktop/javax.swing java.desktop/java.awt java.base/java.util java.base/java.lang java.base/java.lang.reflect java.base/java.text java.desktop/java.awt.font java.base/jdk.internal.misc java.base/sun.nio.ch java.base/java.nio java.base/java.math java.base/java.util.concurrent java.base/java.net + forge.app.Main + splash/logo.gif + @@ -226,25 +166,25 @@ com.badlogicgames.gdx gdx-backend-lwjgl3 - 1.12.1 + 1.13.0 com.badlogicgames.gdx gdx-platform - 1.12.1 + 1.13.0 natives-desktop com.badlogicgames.gdx gdx-freetype-platform - 1.12.1 + 1.13.0 natives-desktop commons-cli commons-cli - 1.4 + 1.9.0 com.badlogicgames.gdx-controllers @@ -260,7 +200,7 @@ com.badlogicgames.gdx gdx-box2d-platform - 1.12.1 + 1.13.0 natives-desktop diff --git a/forge-gui-mobile-dev/splash/logo.gif b/forge-gui-mobile-dev/splash/logo.gif new file mode 100644 index 00000000000..cfdde5e4a6c Binary files /dev/null and b/forge-gui-mobile-dev/splash/logo.gif differ diff --git a/forge-gui-mobile-dev/src/forge/app/DialogWindow.java b/forge-gui-mobile-dev/src/forge/app/DialogWindow.java new file mode 100644 index 00000000000..428767dd500 --- /dev/null +++ b/forge-gui-mobile-dev/src/forge/app/DialogWindow.java @@ -0,0 +1,23 @@ +package forge.app; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import java.util.ArrayList; +import java.util.List; + +public class DialogWindow { + public DialogWindow(String title, String message) { + List options = new ArrayList<>(); + JButton ok = new JButton("OK"); + options.add(ok); + JOptionPane pane = new JOptionPane(message, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options.toArray()); + JDialog dlg = pane.createDialog(JOptionPane.getRootFrame(), title); + ok.addActionListener(e -> { + dlg.setVisible(false); + System.exit(0); + }); + dlg.setResizable(false); + dlg.setVisible(true); + } +} diff --git a/forge-gui-mobile-dev/src/forge/app/GameLauncher.java b/forge-gui-mobile-dev/src/forge/app/GameLauncher.java new file mode 100644 index 00000000000..83d8560dffc --- /dev/null +++ b/forge-gui-mobile-dev/src/forge/app/GameLauncher.java @@ -0,0 +1,75 @@ +package forge.app; + +import com.badlogic.gdx.ApplicationListener; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Clipboard; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3WindowAdapter; +import com.badlogic.gdx.graphics.glutils.HdpiMode; +import com.badlogic.gdx.utils.SharedLibraryLoader; +import forge.Forge; +import forge.adventure.util.Config; +import forge.assets.AssetsDownloader; +import forge.util.FileUtil; +import org.lwjgl.system.Configuration; + +import java.nio.file.Files; +import java.nio.file.Paths; + +public class GameLauncher { + public GameLauncher(final String versionString) { + // Set this to "true" to make the mobile game port run as a full-screen desktop application + boolean desktopMode = true;//cmd.hasOption("fullscreen"); + // Set this to the location where you want the mobile game port to look for assets when working as a full-screen desktop application + // (uncomment the bottom version and comment the top one to load the res folder from the current folder the .jar is in if you would + // like to make the game load from a desktop game folder configuration). + //String desktopModeAssetsDir = "../forge-gui/"; + String desktopModeAssetsDir = "./"; + if (!Files.exists(Paths.get(desktopModeAssetsDir + "res"))) + desktopModeAssetsDir = "../forge-gui/";//try IDE run + + // Assets directory used when the game fully emulates smartphone/tablet mode (desktopMode = false), useful when debugging from IDE + String assetsDir; + if (!AssetsDownloader.SHARE_DESKTOP_ASSETS) { + assetsDir = "testAssets/"; + FileUtil.ensureDirectoryExists(assetsDir); + } else { + assetsDir = "./"; + if (!Files.exists(Paths.get(assetsDir + "res"))) + assetsDir = "../forge-gui/"; + } + + // Place the file "switch_orientation.ini" to your assets folder to make the game switch to landscape orientation (unless desktopMode = true) + String switchOrientationFile = assetsDir + "switch_orientation.ini"; + // This should fix MAC-OS startup without the need for -XstartOnFirstThread parameter + if (SharedLibraryLoader.isMac) { + Configuration.GLFW_LIBRARY_NAME.set("glfw_async"); + } + Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); + config.setResizable(false); + ApplicationListener start = Forge.getApp(new Lwjgl3Clipboard(), new Main.DesktopAdapter(switchOrientationFile),//todo get totalRAM && isTabletDevice + desktopMode ? desktopModeAssetsDir : assetsDir, false, false, 0, false, 0, "", ""); + if (Config.instance().getSettingData().fullScreen) { + config.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode()); + config.setAutoIconify(true); + config.setHdpiMode(HdpiMode.Logical); + } else { + config.setWindowedMode(Config.instance().getSettingData().width, Config.instance().getSettingData().height); + } + config.setTitle("Forge - " + versionString); + config.setWindowListener(new Lwjgl3WindowAdapter() { + @Override + public boolean closeRequested() { + //use the device adpater to exit properly + if (Forge.safeToClose) + Forge.exit(true); + return false; + } + }); + + if (desktopMode) + config.setHdpiMode(HdpiMode.Logical); + + new Lwjgl3Application(start, config); + } +} diff --git a/forge-gui-mobile-dev/src/forge/app/Main.java b/forge-gui-mobile-dev/src/forge/app/Main.java index fbbcd511b87..4103f79dc7a 100644 --- a/forge-gui-mobile-dev/src/forge/app/Main.java +++ b/forge-gui-mobile-dev/src/forge/app/Main.java @@ -1,143 +1,33 @@ package forge.app; -import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.backends.lwjgl3.*; -import com.badlogic.gdx.graphics.glutils.HdpiMode; -import forge.Forge; -import forge.adventure.util.Config; -import forge.assets.AssetsDownloader; import forge.interfaces.IDeviceAdapter; -import forge.localinstance.properties.ForgePreferences; -import forge.model.FModel; +import forge.util.BuildInfo; import forge.util.FileUtil; import forge.util.OperatingSystem; import forge.util.RestartUtil; -import forge.util.Utils; -import org.apache.commons.cli.*; import org.apache.commons.lang3.tuple.Pair; import javax.imageio.ImageIO; -import java.awt.*; +import java.awt.Desktop; +import java.awt.SplashScreen; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.ArrayList; public class Main { + private static final String versionString = BuildInfo.getVersionString(); public static void main(String[] args) { - Options options = new Options(); - options.addOption("h","help", false, "Show help."); - options.addOption("f","fullscreen", false,"fullscreen mode"); - options.addOption("l","landscape", false,"landscape mode"); - options.addOption("r","resolution", true,"resolution (WxH)"); - - CommandLineParser parser = new DefaultParser(); - HelpFormatter formatter = new HelpFormatter(); - CommandLine cmd; - - try { - cmd = parser.parse(options, args); - } catch (ParseException e) { - System.out.println(e.getMessage()); - formatter.printHelp("forge-mobile-dev", options); - - System.exit(1); - return; - } - - // Set this to "true" to make the mobile game port run as a full-screen desktop application - boolean desktopMode = true;//cmd.hasOption("fullscreen"); - // Set this to the location where you want the mobile game port to look for assets when working as a full-screen desktop application - // (uncomment the bottom version and comment the top one to load the res folder from the current folder the .jar is in if you would - // like to make the game load from a desktop game folder configuration). - //String desktopModeAssetsDir = "../forge-gui/"; - String desktopModeAssetsDir = "./"; - if(!Files.exists(Paths.get(desktopModeAssetsDir+"res"))) - desktopModeAssetsDir = "../forge-gui/";//try IDE run - - // Assets directory used when the game fully emulates smartphone/tablet mode (desktopMode = false), useful when debugging from IDE - String assetsDir ; - if (!AssetsDownloader.SHARE_DESKTOP_ASSETS) { - assetsDir= "testAssets/"; - FileUtil.ensureDirectoryExists(assetsDir); - } - else - { - assetsDir= "./"; - if(!Files.exists(Paths.get(assetsDir+"res"))) - assetsDir = "../forge-gui/"; - } - - // Place the file "switch_orientation.ini" to your assets folder to make the game switch to landscape orientation (unless desktopMode = true) - String switchOrientationFile = assetsDir + "switch_orientation.ini"; - boolean landscapeMode = FileUtil.doesFileExist(switchOrientationFile) || cmd.hasOption("landscape"); - String[] res; - - // Width and height for standard smartphone/tablet mode (desktopMode = false) - int screenWidth = landscapeMode ? (int)(Utils.BASE_HEIGHT * 16 / 9) : (int)Utils.BASE_WIDTH; - int screenHeight = (int)Utils.BASE_HEIGHT; - if (cmd.hasOption("resolution")) { - res = cmd.getOptionValue("resolution").split("x"); - if (res.length >= 2) { - screenWidth = Integer.parseInt(res[0].trim()); - screenHeight = Integer.parseInt(res[1].trim()); - } - desktopMode=false; - } - - // Fullscreen width and height for desktop mode (desktopMode = true) - // Can be specified inside the file fullscreen_resolution.ini to override default (in the format WxH, e.g. 1920x1080) - int desktopScreenWidth = Lwjgl3ApplicationConfiguration.getDisplayMode().width; - int desktopScreenHeight = Lwjgl3ApplicationConfiguration.getDisplayMode().height; - boolean fullscreenFlag = true; - if (FileUtil.doesFileExist(desktopModeAssetsDir + "screen_resolution.ini")) { - res = FileUtil.readFileToString(desktopModeAssetsDir + "screen_resolution.ini").split("x"); - fullscreenFlag = res.length != 3 || Integer.parseInt(res[2].trim()) > 0; - if (res.length >= 2) { - desktopScreenWidth = Integer.parseInt(res[0].trim()); - desktopScreenHeight = Integer.parseInt(res[1].trim()); - } - } - - Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); - config.setResizable(false); - ForgePreferences prefs = FModel.getPreferences(); - boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT); - ApplicationListener start = Forge.getApp(new Lwjgl3Clipboard(), new DesktopAdapter(switchOrientationFile),//todo get totalRAM && isTabletDevice - desktopMode ? desktopModeAssetsDir : assetsDir, propertyConfig, false, 0, false, 0, "", ""); - if (Config.instance().getSettingData().fullScreen) { - config.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode()); - config.setAutoIconify(true); - config.setHdpiMode(HdpiMode.Logical); - } else { - config.setWindowedMode(Config.instance().getSettingData().width, Config.instance().getSettingData().height); - } - config.setTitle("Forge"); - config.setWindowListener(new Lwjgl3WindowAdapter(){ - @Override - public boolean closeRequested() { - //use the device adpater to exit properly - if (Forge.safeToClose) - Forge.exit(true); - return false; - } - }); - - if (desktopMode) - config.setHdpiMode(HdpiMode.Logical); - - new Lwjgl3Application(start, config); + new GameLauncher(versionString); } - private static class DesktopAdapter implements IDeviceAdapter { + public static class DesktopAdapter implements IDeviceAdapter { private final String switchOrientationFile; - private DesktopAdapter(String switchOrientationFile0) { + DesktopAdapter(String switchOrientationFile0) { switchOrientationFile = switchOrientationFile0; } @@ -157,13 +47,17 @@ public class Main { return System.getProperty("user.home") + "/Downloads/"; } + @Override + public String getVersionString() { + return versionString; + } + @Override public boolean openFile(String filename) { try { Desktop.getDesktop().open(new File(filename)); return true; - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } return false; @@ -183,6 +77,14 @@ public class Main { System.exit(0); } + @Override + public void closeSplashScreen() { + SplashScreen splash = SplashScreen.getSplashScreen(); + if (splash != null) { + splash.close(); + } + } + @Override public boolean isTablet() { return true; //treat desktop the same as a tablet @@ -193,8 +95,7 @@ public class Main { //create file to indicate that landscape mode should be used if (landscapeMode) { FileUtil.writeFile(switchOrientationFile, "1"); - } - else { + } else { FileUtil.deleteFile(switchOrientationFile); } } diff --git a/forge-gui-mobile-dev/src/main/config/forge-adventure-mac.sh b/forge-gui-mobile-dev/src/main/config/forge-adventure-mac.sh deleted file mode 100644 index 6d208042fee..00000000000 --- a/forge-gui-mobile-dev/src/main/config/forge-adventure-mac.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd $(dirname "${0}") -java -XstartOnFirstThread -Xmx4096m --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dfile.encoding=UTF-8 -jar $project.build.finalName$ diff --git a/forge-gui-mobile-dev/src/main/config/forge-adventure.cmd b/forge-gui-mobile-dev/src/main/config/forge-adventure.cmd index 8779fa25870..31c7816b15a 100644 --- a/forge-gui-mobile-dev/src/main/config/forge-adventure.cmd +++ b/forge-gui-mobile-dev/src/main/config/forge-adventure.cmd @@ -9,17 +9,16 @@ java -version 1>nul 2>nul || ( ) for /f tokens^=2^ delims^=.-_^+^" %%j in ('java -fullversion 2^>^&1') do set "jver=%%j" +if %jver% LEQ 16 ( + echo unsupported java + popd + exit /b 2 +) + if %jver% GEQ 17 ( - java --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ + java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ popd exit /b 0 ) -if %jver% GEQ 11 ( - java --illegal-access=permit -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ - popd - exit /b 0 -) - -java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ popd \ No newline at end of file diff --git a/forge-gui-mobile-dev/src/main/config/forge-adventure.command b/forge-gui-mobile-dev/src/main/config/forge-adventure.command index 1e3165f2ed0..6aa6eee97e0 100644 --- a/forge-gui-mobile-dev/src/main/config/forge-adventure.command +++ b/forge-gui-mobile-dev/src/main/config/forge-adventure.command @@ -1,3 +1,3 @@ #!/bin/sh cd $(dirname "${0}") -java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$ +java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ diff --git a/forge-gui-mobile-dev/src/main/config/forge-adventure.sh b/forge-gui-mobile-dev/src/main/config/forge-adventure.sh index 575b5a5b090..6aa6eee97e0 100644 --- a/forge-gui-mobile-dev/src/main/config/forge-adventure.sh +++ b/forge-gui-mobile-dev/src/main/config/forge-adventure.sh @@ -1,3 +1,3 @@ #!/bin/sh cd $(dirname "${0}") -java -Xmx4096m --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.desktop/javax.swing.border=ALL-UNNAMED --add-opens java.desktop/javax.swing.event=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED --add-opens java.desktop/java.awt.image=ALL-UNNAMED --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dfile.encoding=UTF-8 -jar $project.build.finalName$ +java -Xmx4096m $mandatory.java.args$ -jar $project.build.finalName$ diff --git a/forge-gui-mobile/libs/gdx-freetype.jar b/forge-gui-mobile/libs/gdx-freetype.jar index 7882e998dda..daf2f4f1d70 100644 Binary files a/forge-gui-mobile/libs/gdx-freetype.jar and b/forge-gui-mobile/libs/gdx-freetype.jar differ diff --git a/forge-gui-mobile/libs/gdx-sources.jar b/forge-gui-mobile/libs/gdx-sources.jar index 85793e30966..11bed47689d 100644 Binary files a/forge-gui-mobile/libs/gdx-sources.jar and b/forge-gui-mobile/libs/gdx-sources.jar differ diff --git a/forge-gui-mobile/libs/gdx.jar b/forge-gui-mobile/libs/gdx.jar index cca18342888..50d65286c35 100644 Binary files a/forge-gui-mobile/libs/gdx.jar and b/forge-gui-mobile/libs/gdx.jar differ diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index 52bb5266678..3dd42d225a6 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui-mobile @@ -17,8 +17,8 @@ maven-compiler-plugin - 1.8 - 1.8 + 17 + 17 @@ -75,12 +75,12 @@ com.badlogicgames.gdx gdx - 1.12.1 + 1.13.0 com.badlogicgames.gdx gdx-freetype - 1.12.1 + 1.13.0 com.github.raeleus.TenPatch @@ -97,7 +97,7 @@ com.badlogicgames.gdx gdx-box2d - 1.12.1 + 1.13.0 com.badlogicgames.gdx diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 9d2c72c5848..b0ed15250e6 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -1,7 +1,11 @@ package forge; -import com.badlogic.gdx.*; +import com.badlogic.gdx.Application; +import com.badlogic.gdx.ApplicationListener; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; +import com.badlogic.gdx.Input; +import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.ControllerAdapter; import com.badlogic.gdx.controllers.ControllerListener; @@ -50,8 +54,6 @@ import java.nio.file.Paths; import java.util.*; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.66-SNAPSHOT"; - private static ApplicationListener app = null; static Scene currentScene = null; static Array lastScene = new Array<>(); @@ -88,6 +90,7 @@ public class Forge implements ApplicationListener { private static boolean destroyThis = false; public static String extrawide = "default"; public static float heigtModifier = 0.0f; + public static float deltaTime = 0f; private static boolean isloadingaMatch = false; public static boolean autoAIDeckSelection = false; public static boolean showFPS = false; @@ -122,20 +125,22 @@ public class Forge implements ApplicationListener { public static boolean createNewAdventureMap = false; private static Localizer localizer; - public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation, int totalRAM, boolean isTablet, int AndroidAPI, String AndroidRelease, String deviceName) { - app = new Forge(); - if (GuiBase.getInterface() == null) { - clipboard = clipboard0; - deviceAdapter = deviceAdapter0; - GuiBase.setUsingAppDirectory(assetDir0.contains("forge.app")); //obb directory on android uses the package name as entrypoint - GuiBase.setInterface(new GuiMobile(assetDir0)); - GuiBase.enablePropertyConfig(value); - isPortraitMode = androidOrientation; - totalDeviceRAM = totalRAM; - isTabletDevice = isTablet; - androidVersion = AndroidAPI; + public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean propertyConfig, boolean androidOrientation, int totalRAM, boolean isTablet, int AndroidAPI, String AndroidRelease, String deviceName) { + if (app == null) { + app = new Forge(); + if (GuiBase.getInterface() == null) { + clipboard = clipboard0; + deviceAdapter = deviceAdapter0; + GuiBase.setUsingAppDirectory(assetDir0.contains("forge.app")); //obb directory on android uses the package name as entrypoint + GuiBase.setInterface(new GuiMobile(assetDir0)); + GuiBase.enablePropertyConfig(propertyConfig); + isPortraitMode = androidOrientation; + totalDeviceRAM = totalRAM; + isTabletDevice = isTablet; + androidVersion = AndroidAPI; + } + GuiBase.setDeviceInfo(deviceName, AndroidRelease, AndroidAPI, totalRAM); } - GuiBase.setDeviceInfo(deviceName, AndroidRelease, AndroidAPI, totalRAM); return app; } @@ -154,6 +159,7 @@ public class Forge implements ApplicationListener { public void create() { //install our error handler ExceptionHandler.registerErrorHandling(); + getDeviceAdapter().closeSplashScreen(); GuiBase.setIsAndroid(Gdx.app.getType() == Application.ApplicationType.Android); @@ -709,6 +715,7 @@ public class Forge implements ApplicationListener { } } } + deltaTime = 0f; } } }); @@ -845,6 +852,10 @@ public class Forge implements ApplicationListener { ForgeAnimation.advanceAll(); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear the screen. + //set delta for rotation + deltaTime += Gdx.graphics.getDeltaTime(); + if (deltaTime > 22.5f) + deltaTime = 0f; FContainer screen = currentScreen; diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index 36b1089954d..b7ca391d9bf 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -320,16 +320,17 @@ public class Graphics { fillCircle(skinColor.getColor(), x2, y2, arrowThickness); drawLineArrow(arrowThickness, skinColor.getColor(), x1, y1, x2, y2); fillCircle(Color.WHITE, x2, y2, arrowThickness / 2); - drawLine(arrowThickness / 3, Color.WHITE, x1, y1, x2, y2); + drawLineArrow(arrowThickness / 3, Color.WHITE, x1, y1, x2, y2); + //drawLine(arrowThickness / 3, Color.WHITE, x1, y1, x2, y2); } public void drawLineArrow(float thickness, Color color, float x1, float y1, float x2, float y2) { batch.end(); //must pause batch while rendering shapes - float angle = new Vector2(x1 - x2, y1 - y2).angleRad(); + /*float angle = new Vector2(x1 - x2, y1 - y2).angleRad(); float arrowHeadRotation = (float) (Math.PI * 0.8f); Vector2 arrowCorner3 = new Vector2(x2 + (thickness / 3) * (float) Math.cos(angle + arrowHeadRotation), y2 + (thickness / 3) * (float) Math.sin(angle + arrowHeadRotation)); - Vector2 arrowCorner4 = new Vector2(x2 + (thickness / 3) * (float) Math.cos(angle - arrowHeadRotation), y2 + (thickness / 3) * (float) Math.sin(angle - arrowHeadRotation)); + Vector2 arrowCorner4 = new Vector2(x2 + (thickness / 3) * (float) Math.cos(angle - arrowHeadRotation), y2 + (thickness / 3) * (float) Math.sin(angle - arrowHeadRotation));*/ if (thickness > 1) { Gdx.gl.glLineWidth(thickness); diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java index 116e24915f9..1191fc360ba 100644 --- a/forge-gui-mobile/src/forge/GuiMobile.java +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -54,7 +54,7 @@ public class GuiMobile implements IGuiBase { @Override public String getCurrentVersion() { - return Forge.CURRENT_VERSION; + return Forge.getDeviceAdapter().getVersionString(); } @Override diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 1ec49076a85..c6e918cf1bf 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -27,7 +27,7 @@ public class StartScene extends UIScene { private static StartScene object; Dialog exitDialog, backupDialog, zipDialog, unzipDialog; TextraButton saveButton, resumeButton, continueButton; - TypingLabel version = Controls.newTypingLabel("{GRADIENT}[%80]" + Forge.CURRENT_VERSION + "{ENDGRADIENT}"); + TypingLabel version = Controls.newTypingLabel("{GRADIENT}[%80]v." + Forge.getDeviceAdapter().getVersionString() + "{ENDGRADIENT}"); public StartScene() { diff --git a/forge-gui-mobile/src/forge/assets/AssetsDownloader.java b/forge-gui-mobile/src/forge/assets/AssetsDownloader.java index 6663ae926ff..104840e8f4d 100644 --- a/forge-gui-mobile/src/forge/assets/AssetsDownloader.java +++ b/forge-gui-mobile/src/forge/assets/AssetsDownloader.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.net.URL; import java.util.List; +import com.badlogic.gdx.files.FileHandle; import forge.gui.GuiBase; import org.apache.commons.lang3.StringUtils; @@ -30,7 +31,8 @@ public class AssetsDownloader { public static void checkForUpdates(final SplashScreen splashScreen) { if (Gdx.app.getType() == ApplicationType.Desktop && SHARE_DESKTOP_ASSETS) { return; } - final boolean isSnapshots = Forge.CURRENT_VERSION.contains("SNAPSHOT"); + final String versionString = Forge.getDeviceAdapter().getVersionString(); + final boolean isSnapshots = versionString.contains("SNAPSHOT"); final String snapsURL = "https://downloads.cardforge.org/dailysnapshots/"; final String releaseURL = "https://releases.cardforge.org/forge/forge-gui-android/"; final String versionText = isSnapshots ? snapsURL + "version.txt" : releaseURL + "version.txt"; @@ -45,11 +47,11 @@ public class AssetsDownloader { String version = FileUtil.readFileToString(versionUrl); String filename = "forge-android-" + version + "-signed-aligned.apk"; String apkURL = isSnapshots ? snapsURL + filename : releaseURL + version + "/" + filename; - if (!StringUtils.isEmpty(version) && !Forge.CURRENT_VERSION.equals(version)) { + if (!StringUtils.isEmpty(version) && !versionString.equals(version)) { splashScreen.prepareForDialogs(); message = "A new version of Forge is available (" + version + ").\n" + - "You are currently on an older version (" + Forge.CURRENT_VERSION + ").\n\n" + + "You are currently on an older version (" + versionString + ").\n\n" + "Would you like to update to the new version now?"; if (!Forge.getDeviceAdapter().isConnectedToWifi()) { message += " If so, you may want to connect to wifi first. The download is around 12MB."; @@ -74,6 +76,19 @@ public class AssetsDownloader { } //see if assets need updating + if (GuiBase.isAndroid()) { + FileHandle resDir = Gdx.files.absolute(ForgeConstants.RES_DIR); + FileHandle assetsDir = Gdx.files.absolute(ForgeConstants.ASSETS_DIR); + FileHandle advBG = Gdx.files.absolute(ForgeConstants.DEFAULT_SKINS_DIR).child(ForgeConstants.ADV_TEXTURE_BG_FILE); + if (!advBG.exists()) { + FileHandle deleteVersion = assetsDir.child("version.txt"); + if (deleteVersion.exists()) + deleteVersion.delete(); + FileHandle deleteBuild = resDir.child("build.txt"); + if (deleteBuild.exists()) + deleteBuild.delete(); + } + } File versionFile = new File(ForgeConstants.ASSETS_DIR + "version.txt"); if (!versionFile.exists()) { try { @@ -85,7 +100,7 @@ public class AssetsDownloader { return; } } - else if (Forge.CURRENT_VERSION.equals(FileUtil.readFileToString(versionFile)) && FSkin.getSkinDir() != null) { + else if (versionString.equals(FileUtil.readFileToString(versionFile)) && FSkin.getSkinDir() != null) { return; //if version matches what had been previously saved and FSkin isn't requesting assets download, no need to download assets } @@ -143,7 +158,7 @@ public class AssetsDownloader { //allow deletion on Android 10 or if using app-specific directory boolean allowDeletion = Forge.androidVersion < 30 || GuiBase.isUsingAppDirectory(); - String assetURL = isSnapshots ? snapsURL + "assets.zip" : releaseURL + Forge.CURRENT_VERSION + "/" + "assets.zip"; + String assetURL = isSnapshots ? snapsURL + "assets.zip" : releaseURL + versionString + "/" + "assets.zip"; new GuiDownloadZipService("", "resource files", assetURL, ForgeConstants.ASSETS_DIR, ForgeConstants.RES_DIR, splashScreen.getProgressBar(), allowDeletion).downloadAndUnzip(); @@ -158,7 +173,7 @@ public class AssetsDownloader { //save version string to file once assets finish downloading //so they don't need to be re-downloaded until you upgrade again - FileUtil.writeFile(versionFile, Forge.CURRENT_VERSION); + FileUtil.writeFile(versionFile, versionString); //add restart after assets update String msg = allowDeletion ? "Resource update finished..." : "Forge misses some files for deletion.\nIf you encounter issues, try deleting the Forge/res folder and/or deleting Forge/cache/fonts folder and try to download and update the assets."; diff --git a/forge-gui-mobile/src/forge/assets/FSkin.java b/forge-gui-mobile/src/forge/assets/FSkin.java index 300d18dd752..f36a92818fb 100644 --- a/forge-gui-mobile/src/forge/assets/FSkin.java +++ b/forge-gui-mobile/src/forge/assets/FSkin.java @@ -128,6 +128,17 @@ public class FSkin { //reset hd buttons/icons Forge.hdbuttons = false; Forge.hdstart = false; + // TODO: the "v2" string should be a property of the default skin. + FileHandle v2File = Gdx.files.absolute(ForgeConstants.FONTS_DIR + "v2"); + if (v2File == null || !v2File.exists()) { + //delete cached fonts + FSkinFont.deleteCachedFiles(); + try { + v2File.file().createNewFile(); + } catch (Exception e) { + e.printStackTrace(); + } + } //ensure skins directory exists final FileHandle dir = Gdx.files.absolute(ForgeConstants.CACHE_SKINS_DIR); @@ -164,7 +175,9 @@ public class FSkin { //load theme logo while changing skins Forge.getAssets().loadTexture(getSkinFile("hd_logo.png")); Forge.getAssets().loadTexture(getDefaultSkinFile("adv_logo.png"), new TextureLoader.TextureParameter()); + Forge.getAssets().loadTexture(getDefaultSkinFile("cover.png")); Forge.getAssets().loadTexture(getDefaultSkinFile("overlay_alpha.png")); + Forge.getAssets().loadTexture(getDefaultSkinFile("spiral.png")); Forge.getAssets().loadTexture(getDefaultSkinFile("splatter.png")); if (splashScreen != null) { diff --git a/forge-gui-mobile/src/forge/assets/FSkinImage.java b/forge-gui-mobile/src/forge/assets/FSkinImage.java index 5689db2d006..2b5e42de076 100644 --- a/forge-gui-mobile/src/forge/assets/FSkinImage.java +++ b/forge-gui-mobile/src/forge/assets/FSkinImage.java @@ -219,9 +219,10 @@ public enum FSkinImage implements FSkinImageInterface { UNKNOWN (FSkinProp.ICO_UNKNOWN), LOGO (FSkinProp.ICO_LOGO), + CARDART (FSkinProp.ICO_CARDART), FLIPCARD (FSkinProp.ICO_FLIPCARD), - HDFLIPCARD (FSkinProp.ICO_HDFLIPCARD), + HDFLIPCARD (FSkinProp.ICO_HDFLIPCARD), FAVICON (FSkinProp.ICO_FAVICON), LOCK (FSkinProp.ICO_LOCK), @@ -313,15 +314,15 @@ public enum FSkinImage implements FSkinImageInterface { HDBTN_DOWN_LEFT (FSkinProp.IMG_HDBTN_DOWN_LEFT), HDBTN_DOWN_CENTER (FSkinProp.IMG_HDBTN_DOWN_CENTER), HDBTN_DOWN_RIGHT (FSkinProp.IMG_HDBTN_DOWN_RIGHT), - HDBTN_FOCUS_LEFT (FSkinProp.IMG_HDBTN_FOCUS_LEFT), - HDBTN_FOCUS_CENTER (FSkinProp.IMG_HDBTN_FOCUS_CENTER), - HDBTN_FOCUS_RIGHT (FSkinProp.IMG_HDBTN_FOCUS_RIGHT), - HDBTN_TOGGLE_LEFT (FSkinProp.IMG_HDBTN_TOGGLE_LEFT), - HDBTN_TOGGLE_CENTER (FSkinProp.IMG_HDBTN_TOGGLE_CENTER), - HDBTN_TOGGLE_RIGHT (FSkinProp.IMG_HDBTN_TOGGLE_RIGHT), - HDBTN_DISABLED_LEFT (FSkinProp.IMG_HDBTN_DISABLED_LEFT), - HDBTN_DISABLED_CENTER (FSkinProp.IMG_HDBTN_DISABLED_CENTER), - HDBTN_DISABLED_RIGHT (FSkinProp.IMG_HDBTN_DISABLED_RIGHT), + HDBTN_FOCUS_LEFT (FSkinProp.IMG_HDBTN_FOCUS_LEFT), + HDBTN_FOCUS_CENTER (FSkinProp.IMG_HDBTN_FOCUS_CENTER), + HDBTN_FOCUS_RIGHT (FSkinProp.IMG_HDBTN_FOCUS_RIGHT), + HDBTN_TOGGLE_LEFT (FSkinProp.IMG_HDBTN_TOGGLE_LEFT), + HDBTN_TOGGLE_CENTER (FSkinProp.IMG_HDBTN_TOGGLE_CENTER), + HDBTN_TOGGLE_RIGHT (FSkinProp.IMG_HDBTN_TOGGLE_RIGHT), + HDBTN_DISABLED_LEFT (FSkinProp.IMG_HDBTN_DISABLED_LEFT), + HDBTN_DISABLED_CENTER (FSkinProp.IMG_HDBTN_DISABLED_CENTER), + HDBTN_DISABLED_RIGHT (FSkinProp.IMG_HDBTN_DISABLED_RIGHT), //Foils FOIL_01 (FSkinProp.FOIL_01), diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index faaa7a3ecb4..542b9bd2323 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -156,19 +156,20 @@ public class CardImageRenderer { } //space for artist textBoxHeight -= 2 * PT_FONT.getCapHeight(); - PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(state.getImageKey()); + PaperCard paperCard = null; + try { + paperCard = ImageUtil.getPaperCardFromImageKey(state.getImageKey()); + } catch (Exception e) {} String artist = "WOTC"; if (paperCard != null && !paperCard.getArtist().isEmpty()) artist = paperCard.getArtist(); float minTextBoxHeight = 2 * headerHeight; if (textBoxHeight < minTextBoxHeight) { - if (textBoxHeight < minTextBoxHeight) { - artHeight -= (minTextBoxHeight - textBoxHeight); //subtract from art height if text box not big enough otherwise - textBoxHeight = minTextBoxHeight; - if (artHeight < 0) { - textBoxHeight += artHeight; - artHeight = 0; - } + artHeight -= (minTextBoxHeight - textBoxHeight); //subtract from art height if text box not big enough otherwise + textBoxHeight = minTextBoxHeight; + if (artHeight < 0) { + textBoxHeight += artHeight; + artHeight = 0; } } @@ -302,8 +303,8 @@ public class CardImageRenderer { private static final FBufferedImage stretchedArt; static { - final float logoWidth = FSkinImage.LOGO.getWidth(); - final float logoHeight = FSkinImage.LOGO.getHeight(); + final float logoWidth = FSkinImage.CARDART.getWidth(); + final float logoHeight = FSkinImage.CARDART.getHeight(); float h = logoHeight * 1.1f; float w = h * CardRenderer.CARD_ART_RATIO; forgeArt = new FBufferedImage(w, h) { @@ -311,7 +312,7 @@ public class CardImageRenderer { protected void draw(Graphics g, float w, float h) { g.drawImage(Forge.isMobileAdventureMode ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, w, h); g.fillRect(FScreen.getTextureOverlayColor(), 0, 0, w, h); - g.drawImage(FSkinImage.LOGO, (w - logoWidth) / 2, (h - logoHeight) / 2, logoWidth, logoHeight); + g.drawImage(FSkinImage.CARDART, (w - logoWidth) / 2, (h - logoHeight) / 2, logoWidth, logoHeight); } }; stretchedArt = new FBufferedImage(w, h) { @@ -319,20 +320,24 @@ public class CardImageRenderer { protected void draw(Graphics g, float w, float h) { g.drawImage(Forge.isMobileAdventureMode ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, w, h); g.fillRect(FScreen.getTextureOverlayColor(), 0, 0, w, h); - g.drawImage(FSkinImage.LOGO, (w - logoWidth) / 2, ((h - logoHeight) / 2) + h / 3.5f, logoWidth, logoHeight / 3); + int newW = Math.round((h * (logoWidth / logoHeight)) * 1.5f); + int newH = Math.round(logoHeight / 2); + g.drawImage(FSkinImage.CARDART, (w - newW) /2, (h - newH) / 2, newW, newH); } }; } private static void drawArt(CardView cv, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) { - boolean isSaga = cv.getCurrentState().getType().hasSubtype("Saga"); - boolean isClass = cv.getCurrentState().getType().hasSubtype("Class") || cv.getCurrentState().getType().hasSubtype("Case"); - boolean isDungeon = cv.getCurrentState().getType().isDungeon(); + boolean useStretchedArt = cv.getCurrentState().getType().hasSubtype("Saga") + || cv.getCurrentState().getType().hasSubtype("Class") + || cv.getCurrentState().getType().hasSubtype("Case") + || cv.getCurrentState().getType().isDungeon(); ColorSet colorSet = cv.getCurrentState().getColors(); if (altState && cv.hasAlternateState()) { - isSaga = cv.getAlternateState().getType().hasSubtype("Saga"); - isClass = cv.getAlternateState().getType().hasSubtype("Class") || cv.getAlternateState().getType().hasSubtype("Case"); - isDungeon = cv.getAlternateState().getType().isDungeon(); + useStretchedArt = cv.getAlternateState().getType().hasSubtype("Saga") + || cv.getAlternateState().getType().hasSubtype("Class") + || cv.getAlternateState().getType().hasSubtype("Case") + || cv.getAlternateState().getType().isDungeon(); colorSet = cv.getAlternateState().getColors(); } if (cv == null) { @@ -344,7 +349,7 @@ public class CardImageRenderer { } } //fallback - if (isSaga || isClass || isDungeon) { + if (useStretchedArt) { g.drawImage(stretchedArt, x, y, w, h); } else { g.drawImage(forgeArt, x, y, w, h); @@ -359,7 +364,7 @@ public class CardImageRenderer { || cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.FORETELL_IMAGE))); if (cardArt != null) { if (isHidden && !altState) { - if (isSaga || isClass || isDungeon) { + if (useStretchedArt) { g.drawImage(stretchedArt, x, y, w, h); } else { g.drawImage(forgeArt, x, y, w, h); @@ -391,14 +396,14 @@ public class CardImageRenderer { } } } else { - if (isSaga || isClass || isDungeon) { + if (useStretchedArt) { g.drawImage(stretchedArt, x, y, w, h); } else { g.drawImage(forgeArt, x, y, w, h); } } } else { - if (isSaga || isClass || isDungeon) { + if (useStretchedArt) { g.drawImage(stretchedArt, x, y, w, h); } else { g.drawImage(forgeArt, x, y, w, h); diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 83fb9310633..91253cb501e 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -59,6 +59,8 @@ import forge.model.FModel; import forge.screens.match.MatchController; import forge.toolbox.FList; +import static forge.assets.FSkin.getDefaultSkinFile; + public class CardRenderer { public enum CardStackPosition { Top, @@ -813,13 +815,12 @@ public class CardRenderer { g.drawRect(BORDER_THICKNESS, Color.MAGENTA, cx, cy, cw, ch); } //Ability Icons - boolean onbattlefield = ZoneType.Battlefield.equals(card.getZone()); if (unselectable) { g.setAlphaComposite(0.6f); } - if (onbattlefield && onTop) { - drawAbilityIcons(g, card, cx, cy, cw, cx + ((cw * 2) / 2.3f), cy, cw / 5.5f, cw / 5.7f, showAbilityIcons(card)); - } else if (canShow && !onbattlefield && showAbilityIcons(card)) { + if (ZoneType.Battlefield.equals(card.getZone()) && onTop) { + drawAbilityIcons(g, card, cx, cy, cw, ch, cx + ((cw * 2) / 2.3f), cy, cw / 5.5f, cw / 5.7f, showAbilityIcons(card)); + } else if (canShow && !ZoneType.Battlefield.equals(card.getZone()) && showAbilityIcons(card)) { //draw indicator for flash or can be cast at instant speed, enabled if show ability icons is enabled String keywordKey = card.getCurrentState().getKeywordKey(); String abilityText = card.getCurrentState().getAbilityText(); @@ -873,7 +874,7 @@ public class CardRenderer { g.setAlphaComposite(oldAlpha); } - public static void drawAbilityIcons(Graphics g, CardView card, float cx, float cy, float cw, float abiX, float abiY, float abiScale, float abiSpace, boolean showAbilityIcons) { + public static void drawAbilityIcons(Graphics g, CardView card, float cx, float cy, float cw, float ch, float abiX, float abiY, float abiScale, float abiSpace, boolean showAbilityIcons) { float abiCount = 0; //show token indicator as status if (card.isToken()) { @@ -882,9 +883,19 @@ public class CardRenderer { abiCount += 1; } if (card.isSick()) { - CardFaceSymbols.drawSymbol("summonsick", g, abiX, abiY, cw / 4.7f, cw / 4.7f); - abiY += abiSpace + 1.7f; - abiCount += 1; + Texture spiral = Forge.getAssets().getTexture(getDefaultSkinFile("spiral.png"), false); + if (spiral != null) { + float newX = card.isTapped() ? cx + cw / 4.5f : cx; + float newY = card.isTapped() ? cy + cw / 4.75f : cy; + g.startRotateTransform(newX + cw / 2f, newY + ch / 2, -(Forge.deltaTime * 16f)); + g.drawImage(spiral, newX, newY, cw, ch); + g.endTransform(); + } else { + //old indicator + CardFaceSymbols.drawSymbol("summonsick", g, abiX, abiY, cw / 4.7f, cw / 4.7f); + abiY += abiSpace + 1.7f; + abiCount += 1; + } } if (card.isPhasedOut()) { CardFaceSymbols.drawSymbol("phasing", g, abiX, abiY, cw / 4.7f, cw / 4.7f); diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java index 789c68d2a86..34f4f5b57a3 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java @@ -38,6 +38,8 @@ import java.util.Map.Entry; import java.util.TreeMap; import java.util.stream.IntStream; +import static forge.assets.FSkin.getDefaultSkinFile; + public class ImageView extends ItemView { private static final float PADDING = Utils.scale(5); private static final float PILE_SPACING_Y = 0.1f; @@ -1101,6 +1103,8 @@ public class ImageView extends ItemView { TextureRegion tr = ImageCache.croppedBorderImage(dpImg); g.drawImage(tr, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); } + //draw plastic effect overlay. + g.drawImage(Forge.getAssets().getTexture(getDefaultSkinFile("cover.png")), x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); } //fake labelname shadow g.drawText(item.getName(), GROUP_HEADER_FONT, Color.BLACK, (x + PADDING) - 1f, (y + PADDING * 2) + 1f, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false); @@ -1123,8 +1127,18 @@ public class ImageView extends ItemView { } } } else { - //generic box - g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y - (h * 0.25f), w, h, Color.GREEN, selected); + if (itemManager.getConfig() == ItemManagerConfig.STRING_ONLY) { + //draw generic box for stringOnly config + g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y - (h * 0.25f), w, h, Color.GREEN, selected); + } else { + //draw missing box display if not avail or loading... + g.drawImage(FSkin.getDeckbox().get(0), FSkin.getDeckbox().get(0), x, y, w, h, Color.GREEN, selected); + //temporary fill image + g.fillRect(Color.BLACK, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); + //draw plastic effect overlay. + g.drawImage(Forge.getAssets().getTexture(getDefaultSkinFile("cover.png")), x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); + + } } if (deckColor != null) { //deck color identity diff --git a/forge-gui-mobile/src/forge/screens/FScreen.java b/forge-gui-mobile/src/forge/screens/FScreen.java index c3f2fbdaa54..8cbd8fc7efe 100644 --- a/forge-gui-mobile/src/forge/screens/FScreen.java +++ b/forge-gui-mobile/src/forge/screens/FScreen.java @@ -63,6 +63,7 @@ public abstract class FScreen extends FContainer { } public void onActivate() { + Forge.startContinuousRendering(); } public void onSwitchAway(Callback canSwitchCallback) { diff --git a/forge-gui-mobile/src/forge/screens/SplashScreen.java b/forge-gui-mobile/src/forge/screens/SplashScreen.java index 11ed0c23358..bd44347f286 100644 --- a/forge-gui-mobile/src/forge/screens/SplashScreen.java +++ b/forge-gui-mobile/src/forge/screens/SplashScreen.java @@ -11,6 +11,7 @@ import forge.animation.ForgeAnimation; import forge.assets.FSkin; import forge.assets.FSkinColor; import forge.assets.FSkinFont; +import forge.assets.FSkinImage; import forge.assets.FSkinTexture; import forge.toolbox.FButton; import forge.toolbox.FContainer; @@ -137,7 +138,7 @@ public class SplashScreen extends FContainer { } float hmod = Forge.isLandscapeMode() ? 1f : 1.3f; float ymod = 2.6f; - g.drawImage(splashTexture, Forge.getScreenWidth()/2 - (w*percentage*hmod)/2 , Forge.getScreenHeight()/2 - (h*percentage*hmod)/ymod, (w*percentage)*hmod, (h*percentage)*hmod); + g.drawImage(splashTexture, Forge.getScreenWidth()/2f - (w*percentage*hmod)/2 , Forge.getScreenHeight()/2f - (h*percentage*hmod)/ymod, (w*percentage)*hmod, (h*percentage)*hmod); y += h * 295f / 450f; if (disclaimerFont == null) { @@ -153,10 +154,10 @@ public class SplashScreen extends FContainer { float pbHeight = 57f / 450f * h; y += 78f / 450f * h; - float w2 = Forge.isLandscapeMode() ? Forge.getScreenWidth() / 2 : Forge.getScreenHeight() / 2; + float w2 = Forge.isLandscapeMode() ? Forge.getScreenWidth() / 2f : Forge.getScreenHeight() / 2f; float h2 = 57f / 450f * (w2/2); - String version = "v. " + Forge.CURRENT_VERSION; + String version = "v." + Forge.getDeviceAdapter().getVersionString(); g.drawText(version, disclaimerFont, FProgressBar.SEL_FORE_COLOR, x, getHeight() - disclaimerHeight, w, disclaimerHeight, false, Align.center, true); progressBar.setBounds((Forge.getScreenWidth() - w2)/2, Forge.getScreenHeight() - h2 * 2f, w2, h2); g.draw(progressBar); @@ -280,7 +281,7 @@ public class SplashScreen extends FContainer { float xmod = Forge.getScreenHeight() > 1000 ? 1.5f : Forge.getScreenHeight() > 800 ? 1.3f : 1f; g.drawImage(FSkin.getLogo(), getWidth() / 2 - (FSkin.getLogo().getWidth() * xmod) / 2, getHeight() / 2 - (FSkin.getLogo().getHeight() * xmod) / 1.5f, FSkin.getLogo().getWidth() * xmod, FSkin.getLogo().getHeight() * xmod); } else { - g.drawImage(splashTexture, x, y, w, h); + g.drawImage(FSkinImage.LOGO, getWidth() / 2 - (FSkinImage.LOGO.getWidth() * 2f) / 2, getHeight() / 2 - (FSkinImage.LOGO.getHeight() * 2f) / 1.3f, FSkinImage.LOGO.getWidth() * 2f, FSkinImage.LOGO.getHeight() * 2f); } y += h * 295f / 450f; float padding = 20f / 450f * w; @@ -380,7 +381,7 @@ public class SplashScreen extends FContainer { progressBar.setBounds(x + padding, y, w - 2 * padding, pbHeight); g.draw(progressBar); - String version = "v. " + Forge.CURRENT_VERSION; + String version = "v." + Forge.getDeviceAdapter().getVersionString(); g.drawText(version, disclaimerFont, FProgressBar.SEL_FORE_COLOR, x, getHeight() - disclaimerHeight, w, disclaimerHeight, false, Align.center, true); } } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 15d16f0d70d..41528cf4aaa 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -479,7 +479,7 @@ public class MatchScreen extends FScreen { //draw arrows for combat final CombatView combat = game.getCombat(); for (CardView c : cardsonBattlefield) { - TargetingOverlay.assembleArrows(g, c, endpoints, combat, is4Player() || is3Player() ? playerViewSet : null); + TargetingOverlay.assembleArrows(g, c, endpoints, combat, playerViewSet); } } catch (Exception e) { } diff --git a/forge-gui-mobile/src/forge/sound/AudioClip.java b/forge-gui-mobile/src/forge/sound/AudioClip.java index 2f3aaf81be4..3d71c2839eb 100644 --- a/forge-gui-mobile/src/forge/sound/AudioClip.java +++ b/forge-gui-mobile/src/forge/sound/AudioClip.java @@ -52,7 +52,11 @@ public class AudioClip implements IAudioClip { catch (InterruptedException ex) { ex.printStackTrace(); } - clip.play(value); + try { + clip.play(value); + } catch (Exception e) { + e.printStackTrace(); + } } public final void loop() { @@ -65,13 +69,21 @@ public class AudioClip implements IAudioClip { catch (InterruptedException ex) { ex.printStackTrace(); } - clip.loop(); + try { + clip.loop(); + } catch (Exception e) { + e.printStackTrace(); + } } @Override public void dispose() { if (clip != null) { - clip.dispose(); + try { + clip.dispose(); + } catch (Exception e) { + e.printStackTrace(); + } clip = null; } } @@ -80,7 +92,11 @@ public class AudioClip implements IAudioClip { if (clip == null) { return; } - clip.stop(); + try { + clip.stop(); + } catch (Exception e) { + e.printStackTrace(); + } } public final boolean isDone() { diff --git a/forge-gui/COMPILE.txt b/forge-gui/COMPILE.txt index 62de574338e..b2d60e52ea4 100644 --- a/forge-gui/COMPILE.txt +++ b/forge-gui/COMPILE.txt @@ -2,9 +2,7 @@ This file contains the current build notes for Forge. -- Compiling Forge for Android: Pre-requisites -- When compiling Forge for Android, make sure the following prerequisites are met: -Java 8 (JDK 1.8.0), either Oracle or OpenJDK. -Android SDK 25 -Android Build-Tools 26 (this is important, build-tools 25 do not work with Java 8) -Proguard 5.3 (download from the official website and replace the contents of the -Proguard folder of the Android SDK (under "tools/proguard") with the contents of -the downloaded archive). +Java 17, either Oracle or OpenJDK. +Android SDK 35 +Android Build-Tools 35.0.0 (this is important, build-tools 33 and below do not work with Java 17) +Proguard 7.6.0 (proguard.jar included under "forge-gui-android/tools"). diff --git a/forge-gui/MANUAL.txt b/forge-gui/MANUAL.txt index 1da21baf453..58652319817 100644 --- a/forge-gui/MANUAL.txt +++ b/forge-gui/MANUAL.txt @@ -108,8 +108,8 @@ If you're trying to run Forge for the first time, but it doesn't open up, you ca - Current versions of Forge no longer include a launcher script for Mac OS, proceed to step three. 3) Run Forge -- On Windows, just type "forge.exe", Enter (If you have Java 8 installed, use forge-java8.exe) - if you want to run mobile/adventure instead of the desktop interface, type "forge-adventure.exe", Enter (If you have Java 8 installed, use forge-adventure-java8.exe) +- On Windows, just type "forge.exe", Enter. + if you want to run mobile/adventure instead of the desktop interface, type "forge-adventure.exe", Enter. - On Linux, just type "forge.sh", Enter (if you want to run mobile/adventure interface use forge-adventure.sh) - Launch the Forge application bundle by double clicking on the program named "Forge.app". @@ -125,7 +125,7 @@ if you're running Windows 7, make sure you're running the program as an admin, o Java Issues: ------------ -Forge requires Java 8 as minimum installed and will not run if you have an earlier version of Java. You will need to update to Java 8. (Java 11 is recommended) +Forge requires Java 17 as minimum installed and will not run if you have an earlier version of Java. You will need to update to Java 17. (Java 21 is recommended) Card Picture Issues: diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index 9fd725c3278..2feebeda020 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -4,7 +4,7 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-gui @@ -36,15 +36,26 @@ forge-ai ${project.version} + + xmlpull + xmlpull + 1.1.3.4a + com.thoughtworks.xstream xstream - 1.4.19 + 1.4.20 + + + xmlpull + xmlpull + + io.netty netty-all - 4.1.71.Final + 4.1.114.Final compile diff --git a/forge-gui/res/cardsfolder/c/cyclopean_tomb.txt b/forge-gui/res/cardsfolder/c/cyclopean_tomb.txt index cb5261addaa..fe7e2892e20 100644 --- a/forge-gui/res/cardsfolder/c/cyclopean_tomb.txt +++ b/forge-gui/res/cardsfolder/c/cyclopean_tomb.txt @@ -1,7 +1,7 @@ Name:Cyclopean Tomb ManaCost:4 Types:Artifact -A:AB$ PutCounter | Cost$ 2 T | ValidTgts$ Land.nonSwamp | TgtPrompt$ Select target non-Swamp land | RememberCards$ True | CounterType$ MIRE | CounterNum$ 1 | ActivationPhases$ Upkeep | SubAbility$ DBEffect | SpellDescription$ Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate only during your upkeep. +A:AB$ PutCounter | Cost$ 2 T | ValidTgts$ Land.nonSwamp | TgtPrompt$ Select target non-Swamp land | RememberPut$ True | CounterType$ MIRE | CounterNum$ 1 | ActivationPhases$ Upkeep | SubAbility$ DBEffect | SpellDescription$ Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate only during your upkeep. SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | StaticAbilities$ TombStatic | ForgetOnMoved$ Battlefield | ForgetCounter$ MIRE | Duration$ Permanent SVar:TombStatic:Mode$ Continuous | EffectZone$ Command | Affected$ Card.IsRemembered | AddType$ Swamp | RemoveLandTypes$ True | Description$ That land is a Swamp for as long as it has a mire counter on it. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME is put into a graveyard from the battlefield, at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with CARDNAME but that a mire counter has not been removed from with CARDNAME. diff --git a/forge-gui/res/cardsfolder/e/experimental_lab_staff_room.txt b/forge-gui/res/cardsfolder/e/experimental_lab_staff_room.txt index 05e81708bcd..915f88ddfaa 100644 --- a/forge-gui/res/cardsfolder/e/experimental_lab_staff_room.txt +++ b/forge-gui/res/cardsfolder/e/experimental_lab_staff_room.txt @@ -13,7 +13,7 @@ ALTERNATE Name:Staff Room ManaCost:2 G Types:Enchantment Room -T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl | ValidTgts$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigChoose | TriggerDescription$ Whenever a creature you control deals combat damage to a player, turn that creature face up or put a +1/+1 counter on it. +T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigChoose | TriggerDescription$ Whenever a creature you control deals combat damage to a player, turn that creature face up or put a +1/+1 counter on it. SVar:TrigChoose:DB$ GenericChoice | Choices$ DBPutCounter,DBTurnFaceUp SVar:DBTurnFaceUp:DB$ SetState | Defined$ TriggeredSourceLKICopy | Mode$ TurnFaceUp | IsPresent$ Card.canBeTurnedFaceUp+faceDown | PresentDefined$ TriggeredSourceLKICopy | SpellDescription$ Turn it face up SVar:DBPutCounter:DB$ PutCounter | Defined$ TriggeredSourceLKICopy | CounterType$ P1P1 | CounterNum$ 1 | IsPresent$ Card.canReceiveCounters P1P1 | PresentDefined$ TriggeredSourceLKICopy | SpellDescription$ Put a +1/+1 counter on it diff --git a/forge-gui/res/cardsfolder/upcoming/black_panther_wakandan_king.txt b/forge-gui/res/cardsfolder/upcoming/black_panther_wakandan_king.txt new file mode 100644 index 00000000000..b71c3bcfd90 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/black_panther_wakandan_king.txt @@ -0,0 +1,14 @@ +Name:Black Panther, Wakandan King +ManaCost:G W +Types:Legendary Creature Human Noble Hero +PT:2/2 +K:First Strike +T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.YouCtrl+Other | Origin$ Any | Destination$ Battlefield | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Survey the Realm — Whenever NICKNAME or another creature you control enters, put a +1/+1 counter on target land you control. +SVar:TrigPutCounter:DB$ PutCounter | CounterNum$ 1 | CounterType$ P1P1 | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control +A:AB$ Pump | Cost$ 3 | PrecostDesc$ Mine Vibranium — | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control | SubAbility$ DBMove | StackDescription$ SpellDescription | SpellDescription$ Move all +1/+1 counters from target land you control onto target creature. If one or more +1/+1 counters are moved this way, you gain that much life and draw a card. +SVar:DBMove:DB$ MoveCounter | Source$ ParentTarget | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ All | RememberAmount$ True | SubAbility$ DBGainLife | StackDescription$ None +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBDraw | StackDescription$ None +SVar:DBDraw:DB$ Draw | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup | StackDescription$ None +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Count$RememberedNumber +Oracle:First strike\nSurvey the Realm — Whenever Black Panther or another creature you control enters, put a +1/+1 counter on target land you control.\nMine Vibranium — {3}: Move all +1/+1 counters from target land you control onto target creature. If one or more +1/+1 counters are moved this way, you gain that much life and draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/captain_america_first_avenger.txt b/forge-gui/res/cardsfolder/upcoming/captain_america_first_avenger.txt new file mode 100644 index 00000000000..201c540ead9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/captain_america_first_avenger.txt @@ -0,0 +1,9 @@ +Name:Captain America, First Avenger +ManaCost:R W U +Types:Legendary Creature Human Soldier Hero +PT:4/4 +A:AB$ DealDamage | Cost$ 3 Unattach | Announce$ X | PrecostDesc$ Throw . . . — | ValidTgts$ Any | TgtPrompt$ Select any target to distribute damage to | NumDmg$ X | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ X | SpellDescription$ He deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets. +SVar:X:Count$xPaid +T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ DBAttach | TriggerDescription$ . . . Catch — At the beginning of combat on your turn, attach up one target Equipment you control to NICKNAME. +SVar:DBAttach:DB$ Attach | ValidTgts$ Equipment.YouCtrl | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target Equipment you control | Object$ Targeted | Defined$ Self +Oracle:Throw . . . — {3}, Unattach an Equipment from Captain America: He deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets.\n. . . Catch — At the beginning of combat on your turn, attach up one target Equipment you control to Captain America. diff --git a/forge-gui/res/cardsfolder/upcoming/iron_man_titan_of_innovation.txt b/forge-gui/res/cardsfolder/upcoming/iron_man_titan_of_innovation.txt new file mode 100644 index 00000000000..93c7ca00ebf --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/iron_man_titan_of_innovation.txt @@ -0,0 +1,15 @@ +Name:Iron Man, Titan of Innovation +ManaCost:3 U R +Types:Legendary Artifact Creature Human Hero +PT:4/4 +K:Flying +K:Haste +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Genius Industrialist — Whenever NICKNAME attacks, create a Treasure token, then you may sacrifice a noncreature artifact. If you do, search your library for an artifact card with mana value equal to 1 plus the sacrificed artifact's mana value, put it onto the battlefield tapped, then shuffle. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You | SubAbility$ DBSacrifice +SVar:DBSacrifice:DB$ Sacrifice | SacValid$ Artifact.nonCreature | SacMessage$ noncreature artifact | Optional$ True | RememberSacrificed$ True | SubAbility$ DBChangeZone +SVar:DBChangeZone:DB$ ChangeZone | ConditionDefined$ Remembered | ConditionPresent$ Card | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcEQX | ChangeTypeDesc$ artifact card with mana value equal to 1 plus the sacrificed artifact's mana value | ChangeNum$ 1 | Tapped$ True | AILogic$ SacAndUpgrade | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:Remembered$CardManaCost/Plus.1 +SVar:AIPreference:SacCost$Artifact +DeckNeeds:Type$Artifact +Oracle:Flying, haste\nGenius Industrialist — Whenever Iron Man attacks, create a Treasure token, then you may sacrifice a noncreature artifact. If you do, search your library for an artifact card with mana value equal to 1 plus the sacrificed artifact's mana value, put it onto the battlefield tapped, then shuffle. diff --git a/forge-gui/res/cardsfolder/upcoming/storm_force_of_nature.txt b/forge-gui/res/cardsfolder/upcoming/storm_force_of_nature.txt new file mode 100644 index 00000000000..b2638d03281 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/storm_force_of_nature.txt @@ -0,0 +1,12 @@ +Name:Storm, Force of Nature +ManaCost:1 G U R +Types:Legendary Creature Mutant Hero +PT:3/4 +K:Flying +K:Vigilance +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigEffect | CombatDamage$ True | TriggerDescription$ Ceaseless Tempest — Whenever NICKNAME deals combat damage to a player, the next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.) +SVar:TrigEffect:DB$ Effect | StaticAbilities$ GrantStorm | Triggers$ ExileEffect +SVar:GrantStorm:Mode$ Continuous | EffectZone$ Command | Affected$ Instant.YouCtrl,Sorcery.YouCtrl | AffectedZone$ Stack | AddKeyword$ Storm | Description$ The next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.) +SVar:ExileEffect:Mode$ SpellCast | EffectZone$ Command | ValidCard$ Instant.YouCtrl,Sorcery.YouCtrl | Execute$ RemoveEffect | Static$ True +SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self +Oracle:Flying, vigilance\nCeaseless Tempest — Whenever Storm deals combat damage to a player, the next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.) diff --git a/forge-gui/res/cardsfolder/upcoming/wolverine_best_there_is.txt b/forge-gui/res/cardsfolder/upcoming/wolverine_best_there_is.txt new file mode 100644 index 00000000000..f51e1283552 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/wolverine_best_there_is.txt @@ -0,0 +1,12 @@ +Name:Wolverine, Best There Is +ManaCost:1 R G +Types:Legendary Creature Mutant Berserker Hero +PT:2/2 +R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card.Self | ValidTarget$ Permanent,Player | ReplaceWith$ DmgTwice | Description$ Unrivaled Lethality — Double all damage NICKNAME would deal. +SVar:DmgTwice:DB$ ReplaceEffect | VarName$ DamageAmount | VarValue$ X +SVar:X:ReplaceCount$DamageAmount/Twice +T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ Y | SVarCompare$ GE1 | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of each end step, if NICKNAME dealt damage to another creature this turn, put a +1/+1 counter on him. +SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 +SVar:Y:Count$NumDamageThisTurn Card.Self Creature.Other +A:AB$ Regenerate | Cost$ 1 G | SpellDescription$ Regenerate NICKNAME. (The next time he would be destroyed this turn, instead tap him, remove him from combat, and heal all damage on him.) +Oracle:Unrivaled Lethality — Double all damage Wolverine would deal.\nAt the beginning of each end step, if Wolverine dealt damage to another creature this turn, put a +1/+1 counter on him.\n{1}{G}: Regenerate Wolverine. (The next time he would be destroyed this turn, instead tap him, remove him from combat, and heal all damage on him.) diff --git a/forge-gui/res/editions/Foundations.txt b/forge-gui/res/editions/Foundations.txt index 71f7209be98..7f07155ddd0 100644 --- a/forge-gui/res/editions/Foundations.txt +++ b/forge-gui/res/editions/Foundations.txt @@ -12,14 +12,23 @@ ScryfallCode=FDN 66 R Nine-Lives Familiar @Bram Sels 76 U Vengeful Bloodwitch @Jarel Threat 116 R Anthem of Champions @Chris Rallis +134 M Ajani, Caller of the Pride @D. Alexander Gregory 140 R Day of Judgment @Vincent Proce 146 U Savannah Lions @Winona Nelson 161 M Omniscience @Jason Chan 175 U Hero's Downfall @Chris Rallis +176 M Liliana, Dreadhorde General @Chris Rallis 185 U Stromkirk Bloodthief @Caroline Gariba 227 C Llanowar Elves @Kev Walker +234 M Vivien Reid @Anna Steinbauer 273 L Plains @Tingting Yeh 277 L Swamp @Rebecca Guay +312 M Omniscience @Dominik Mayer +321 R Nine-Lives Familiar @Xabi Gaztelua +344 R Anthem of Champions @Ryan Pancoast +357 M Ajani, Caller of the Pride @Victor Adame Minguez +359 M Liliana, Dreadhorde General @Dmitry Burmak +361 M Vivien Reid @Zara Alfonso 379 M Omniscience @Dominik Mayer 385 R Nine-Lives Familiar @Xabi Gaztelua 405 R Anthem of Champions @Ryan Pancoast diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index 314bf0950dd..b6dc746ddcc 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -806,12 +806,14 @@ F798 M Discord, Lord of Disharmony @Narendra Bintara Adi 878 R Prosperous Innkeeper @Tyler Jacobson 879 M Minsc & Boo, Timeless Heroes @Justin Gerard 880 R Stuffy Doll @Robin Olausson +886 R Solve the Equation @Mike Burns 900 M The Scarab God @Barely Human 901 R Lightning Bolt @Christopher Rush 903 M The Locust God @See Machine 904 M The Scorpion God @Ricardo Cavolo 906 R Ignoble Hierarch @John F. Malta 907 R Seedborn Muse @Princess Hidir +908 R Arcane Signet @Alexander Forssberg 1001 M Elspeth, Knight-Errant @Volkan Baǵa 1002 R Patron Wizard @Volkan Baǵa 1003 M Berserk @Volkan Baǵa @@ -1612,6 +1614,31 @@ F1540 M Rainbow Dash @John Thacker 1719 R Preordain @Helvetica Blanc 1720 M Sphinx of the Second Sun @Helvetica Blanc 1721 R Teferi's Ageless Insight @Helvetica Blanc +1726 M Captain America, First Avenger @Ryan Pancoast +1727 R Sigarda's Aid @Howard Lyon +1728 R Flawless Maneuver @Chris Rahn +1729 M In the Trenches @Livia Prima +1730 M Sword of War and Peace @Anthony Devine +1731 M Iron Man, Titan of Innovation @Justyna Dura +1732 R Galvanic Blast @Bud Cook +1733 M Commander's Plate @Marco Teixeira +1734 R Sol Ring @Anna Steinbauer +1735 R Inventors' Fair @Lie Setiawan +1737 M Wolverine, Best There Is @Victor Adame Minguez +1738 M Berserk @Alexander Mokhov +1739 R Rite of Passage @Alexander Mokhov +1740 R Rhythm of the Wild @Anna Podedworna +1741 R The Ozolith @Robin Olausson +1742 M Storm, Force of Nature @Magali Villeneuve +1743 R Lightning Bolt @Francisco Miyara +1744 R Jeska's Will @Miguel Mercado +1745 R Ice Storm @Kevin Sidharta +1746 R Manamorphose @Pauline Voss +1747 M Black Panther, Wakandan King @Tyler Jacobson +1748 R Secure the Wastes @Ernanda Souza +1749 R Primal Vigor @Swayart +1750 R Heroic Intervention @Jake Murray +1751 R Karn's Bastion @Salvatorre Zee Yazzie 1758 R Phyrexian Metamorph @Cacho Rubione 1759 R Cauldron Familiar @Scott Buoncristiano 1760 R Dauthi Voidwalker @Ivan Shavrin @@ -1694,6 +1721,7 @@ b_2_2_zombie c_a_clue_draw c_a_treasure_sac c_a_treasure_sac +c_a_treasure_sac g_0_0_hydra g_0_1_egg_defender g_1_1_cat @@ -1708,6 +1736,7 @@ w_1_1_cat_lifelink w_1_1_cat_lifelink w_1_1_dog w_1_1_spirit_flying +w_1_1_warrior w_4_4_angel_flying walker walker diff --git a/forge-gui/res/editions/Spotlight Series.txt b/forge-gui/res/editions/Spotlight Series.txt new file mode 100644 index 00000000000..0631a776d5a --- /dev/null +++ b/forge-gui/res/editions/Spotlight Series.txt @@ -0,0 +1,9 @@ +[metadata] +Code=PSPL +Date=2025-01-03 +Name=Spotlight Series +Type=Promo +ScryfallCode=PSPL + +[cards] +1 M Terror of the Peaks @Richard Kane Ferguson diff --git a/forge-gui/res/editions/Unstable.txt b/forge-gui/res/editions/Unstable.txt index cd1b746fc20..23637ce69e2 100644 --- a/forge-gui/res/editions/Unstable.txt +++ b/forge-gui/res/editions/Unstable.txt @@ -277,7 +277,6 @@ ScryfallCode=UST [tokens] storm_crow -c_2_2_homunculus c_4_4_dragon_flying w_2_2_cat w_0_1_goat diff --git a/forge-gui/res/editions/Wizards Play Network 2024.txt b/forge-gui/res/editions/Wizards Play Network 2024.txt index 60e071d9eb4..0e45caa9af2 100644 --- a/forge-gui/res/editions/Wizards Play Network 2024.txt +++ b/forge-gui/res/editions/Wizards Play Network 2024.txt @@ -21,3 +21,5 @@ ScryfallCode=PW24 14 R Costly Plunder @Ben Maier 15 R Ravenous Squirrel @Dan Murayama Scott 16 R Heirloom Blade @Carmen Sinek +17 R Crippling Fear @Néstor Ossandón Leal +18 R Night's Whisper @John Severin Brassell diff --git a/forge-gui/res/formats/Archived/Arena Standard/2024-10-22.txt b/forge-gui/res/formats/Archived/Arena Standard/2024-10-22.txt new file mode 100644 index 00000000000..56bf01e7806 --- /dev/null +++ b/forge-gui/res/formats/Archived/Arena Standard/2024-10-22.txt @@ -0,0 +1,7 @@ +[format] +Name:Arena Standard (2024-10-22) +Type:Archived +Subtype:Standard +Effective:2024-10-22 +Sets:DMU, BRO, ONE, MOM, MAT, WOE, LCI, MKM, OTJ, BIG, BLB, DSK +Banned:Leyline of Resonance diff --git a/forge-gui/res/formats/Archived/Legacy/2024-11-04.txt b/forge-gui/res/formats/Archived/Legacy/2024-11-04.txt new file mode 100644 index 00000000000..5104e1c8109 --- /dev/null +++ b/forge-gui/res/formats/Archived/Legacy/2024-11-04.txt @@ -0,0 +1,8 @@ +[format] +Name:Legacy (2024-11-04) +Type:Archived +Subtype:Legacy +Effective:2024-11-04 +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, HOP, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, ARC, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, PC2, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, PCA, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, E01, HOU, C17, XLN, DDT, IMA, V17, E02, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, Q06, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR, ONE, ONC, MOM, MOC, MUL, MAT, LTR, LTC, CMM, WOE, WOC, WOT, WHO, LCI, LCC, REX, RVR, MKM, MKC, CLU, PIP, OTJ, OTC, OTP, BIG, MH3, M3C, H2R, ACR, BLB, BLC, MB2, DSK, DSC +Banned:"Lifetime" Pass Holder; _____ _____ _____ Trespasser; _____ _____ Rocketship; _____ Balls of Fire; _____ Bird Gets the Worm; _____ Goblin; _____-o-saurus; Adriana's Valor; Advantageous Proclamation; Aerialephant; Ambassador Blorpityblorpboop; Amulet of Quoz; Ancestral Recall; Arcum's Astrolabe; Assemble the Rank and Vile; Baaallerina; Backup Plan; Balance; Bazaar of Baghdad; Bioluminary; Black Lotus; Brago's Favor; Bronze Tablet; Carnival Carnivore; Channel; Chaos Orb; Chicken Troupe; Clandestine Chameleon; Cleanse; Coming Attraction; Command Performance; Complaints Clerk; Contract from Below; Crusade; Darkpact; Deadbeat Attendant; Deathrite Shaman; Dee Kay, Finder of the Lost; Demonic Attorney; Demonic Consultation; Demonic Tutor; Dig Through Time; Discourtesy Clerk; Done for the Day; Double Stroke; Draconian Gate-Bot; Dreadhorde Arcanist; Earthcraft; Echoing Boon; Emissary's Ploy; Expressive Iteration; Falling Star; Fastbond; Fight the _____ Fight; Finishing Move; Flash; Frantic Search; Gitaxian Probe; Glitterflitter; Goblin Recruiter; Grief; Gush; Hermit Druid; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imperial Seal; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Last Voyage of the _____; Library of Alexandria; Line Cutter; Lineprancers; Lurrus of the Dream-Den; Make a _____ Splash; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Minotaur de Force; Mishra's Workshop; Monitor Monitor; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Muzzio's Preparations; Myra the Magnificent; Mystical Tutor; Natural Unity; Necropotence; Oath of Druids; Oko, Thief of Crowns; Park Bleater; Petting Zookeeper; Pin Collection; Power Play; Pradesh Gypsies; Prize Wall; Proficient Pyrodancer; Quick Fixer; Rad Rascal; Ragavan, Nimble Pilferer; Rebirth; Ride Guide; Robo-Piñata; Roxi, Publicist to the Stars; Scampire; Seasoned Buttoneer; Secret Summoning; Secrets of Paradise; Sensei's Divining Top; Sentinel Dispatch; Shahrazad; Skullclamp; Sol Ring; Soul Swindler; Sovereign's Realm; Spinnerette, Arachnobat; Squirrel Squatters; Step Right Up; Stiltstrider; Stone-Throwing Devils; Strip Mine; Summoner's Bond; Survival of the Fittest; Sword-Swallowing Seraph; Tempest Efreet; The Most Dangerous Gamer; Ticketomaton; Time Vault; Time Walk; Timetwister; Timmerian Fiends; Tinker; Tolarian Academy; Treasure Cruise; Tusk and Whiskers; Underworld Breach; Unexpected Potential; Vampiric Tutor; Weight Advantage; Wheel of Fortune; White Plume Adventurer; Wicker Picker; Windfall; Wizards of the _____; Wolf in _____ Clothing; Worldknit; Wrenn and Six; Yawgmoth's Bargain; Yawgmoth's Will; Zirda, the Dawnwaker +Additional:Aisha of Sparks and Smoke; Arden Angel; Arvinox, the Mind Flail; Baldin, Century Herdmaster; Bjorna, Nightfall Alchemist; Black Panther, Wakandan King; Blanka, Ferocious Friend; Captain America, First Avenger; Cecily, Haunted Mage; Chief Jim Hopper; Chun-Li, Countless Kicks; Daryl, Hunter of Walkers; Dhalsim, Pliable Pacifist; Doric, Nature's Warden; Dustin, Gadget Genius; E. Honda, Sumo Champion; Edgin, Larcenous Lutenist; Eleven, the Mage; Elmar, Ulvenwald Informant; Enkira, Hostile Scavenger; Forge, Neverwinter Charlatan; Gisa's Favorite Shovel; Glenn, the Voice of Calm; Gregor, Shrewd Magistrate; Greymond, Avacyn's Stalwart; Guile, Sonic Soldier; Hansk, Slayer Zealot; Hargilde, Kindly Runechanter; Havengul Laboratory; Hawkins National Laboratory; Holga, Relentless Rager; Immard, the Stormcleaver; Iron Man, Titan of Innovation; Ken, Burning Brawler; Lara Croft, Tomb Raider; Lucas, the Sharpshooter; Lucille; Maarika, Brutal Gladiator; Malik, Grim Manipulator; Max, the Daredevil; Michonne, Ruthless Survivor; Mike, the Dungeon Master; Mind Flayer, the Shadow; Negan, the Cold-Blooded; Othelm, Sigardian Outcast; Rick, Steadfast Leader; Rose Noble; Ryu, World Warrior; Simon, Wild Magic Sorcerer; Sophina, Spearsage Deserter; Storm, Force of Nature; Tadeas, Juniper Ascendant; The Celestial Toymaker; The Fifteenth Doctor; The Fourteenth Doctor; The Howling Abomination; The Meep; Themberchaud; Vikya, Scorching Stalwart; Wernog, Rider's Chaplain; Will the Wise; Wolverine, Best There Is; Xenk, Paladin Unbroken; Zangief, the Red Cyclone; Zethi, Arcane Blademaster diff --git a/forge-gui/res/formats/Archived/Vintage/2024-11-04.txt b/forge-gui/res/formats/Archived/Vintage/2024-11-04.txt new file mode 100644 index 00000000000..ba93ec0823f --- /dev/null +++ b/forge-gui/res/formats/Archived/Vintage/2024-11-04.txt @@ -0,0 +1,9 @@ +[format] +Name:Vintage (2024-11-04) +Type:Archived +Subtype:Vintage +Effective:2024-11-04 +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, HOP, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, ARC, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, PC2, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, PCA, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, E01, HOU, C17, XLN, DDT, IMA, V17, E02, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, Q06, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR, ONE, ONC, MOM, MOC, MUL, MAT, LTR, LTC, CMM, WOE, WOC, WOT, WHO, LCI, LCC, REX, RVR, MKM, MKC, CLU, PIP, OTJ, OTC, OTP, BIG, MH3, M3C, H2R, ACR, BLB, BLC, MB2, DSK, DSC +Restricted:Ancestral Recall; Balance; Black Lotus; Brainstorm; Chalice of the Void; Channel; Demonic Consultation; Demonic Tutor; Dig Through Time; Flash; Gitaxian Probe; Golgari Grave-Troll; Gush; Imperial Seal; Karn, the Great Creator; Library of Alexandria; Lion's Eye Diamond; Lodestone Golem; Lotus Petal; Mana Crypt; Mana Vault; Memory Jar; Mental Misstep; Merchant Scroll; Mind's Desire; Monastery Mentor; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystic Forge; Mystical Tutor; Narset, Parter of Veils; Necropotence; Sol Ring; Strip Mine; Thorn of Amethyst; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Trinisphere; Urza's Saga; Vampiric Tutor; Vexing Bauble; Wheel of Fortune; Windfall; Yawgmoth's Will +Banned:"Lifetime" Pass Holder; _____ _____ _____ Trespasser; _____ _____ Rocketship; _____ Balls of Fire; _____ Bird Gets the Worm; _____ Goblin; _____-o-saurus; Adriana's Valor; Advantageous Proclamation; Aerialephant; Ambassador Blorpityblorpboop; Amulet of Quoz; Assemble the Rank and Vile; Baaallerina; Backup Plan; Bioluminary; Brago's Favor; Bronze Tablet; Carnival Carnivore; Chaos Orb; Chicken Troupe; Clandestine Chameleon; Cleanse; Coming Attraction; Command Performance; Complaints Clerk; Contract from Below; Crusade; Darkpact; Deadbeat Attendant; Dee Kay, Finder of the Lost; Demonic Attorney; Discourtesy Clerk; Done for the Day; Double Stroke; Draconian Gate-Bot; Echoing Boon; Emissary's Ploy; Falling Star; Fight the _____ Fight; Finishing Move; Glitterflitter; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Last Voyage of the _____; Line Cutter; Lineprancers; Make a _____ Splash; Minotaur de Force; Monitor Monitor; Muzzio's Preparations; Myra the Magnificent; Natural Unity; Park Bleater; Petting Zookeeper; Pin Collection; Power Play; Pradesh Gypsies; Prize Wall; Proficient Pyrodancer; Quick Fixer; Rad Rascal; Rebirth; Ride Guide; Robo-Piñata; Roxi, Publicist to the Stars; Scampire; Seasoned Buttoneer; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Shahrazad; Soul Swindler; Sovereign's Realm; Spinnerette, Arachnobat; Squirrel Squatters; Step Right Up; Stiltstrider; Stone-Throwing Devils; Summoner's Bond; Sword-Swallowing Seraph; Tempest Efreet; The Most Dangerous Gamer; Ticketomaton; Timmerian Fiends; Tusk and Whiskers; Unexpected Potential; Weight Advantage; Wicker Picker; Wizards of the _____; Wolf in _____ Clothing; Worldknit +Additional:Aisha of Sparks and Smoke; Arden Angel; Arvinox, the Mind Flail; Baldin, Century Herdmaster; Bjorna, Nightfall Alchemist; Black Panther, Wakandan King; Blanka, Ferocious Friend; Captain America, First Avenger; Cecily, Haunted Mage; Chief Jim Hopper; Chun-Li, Countless Kicks; Daryl, Hunter of Walkers; Dhalsim, Pliable Pacifist; Doric, Nature's Warden; Dustin, Gadget Genius; E. Honda, Sumo Champion; Edgin, Larcenous Lutenist; Eleven, the Mage; Elmar, Ulvenwald Informant; Enkira, Hostile Scavenger; Forge, Neverwinter Charlatan; Gisa's Favorite Shovel; Glenn, the Voice of Calm; Gregor, Shrewd Magistrate; Greymond, Avacyn's Stalwart; Guile, Sonic Soldier; Hansk, Slayer Zealot; Hargilde, Kindly Runechanter; Havengul Laboratory; Hawkins National Laboratory; Holga, Relentless Rager; Immard, the Stormcleaver; Iron Man, Titan of Innovation; Ken, Burning Brawler; Lara Croft, Tomb Raider; Lucas, the Sharpshooter; Lucille; Maarika, Brutal Gladiator; Malik, Grim Manipulator; Max, the Daredevil; Michonne, Ruthless Survivor; Mike, the Dungeon Master; Mind Flayer, the Shadow; Negan, the Cold-Blooded; Othelm, Sigardian Outcast; Rick, Steadfast Leader; Rose Noble; Ryu, World Warrior; Simon, Wild Magic Sorcerer; Sophina, Spearsage Deserter; Storm, Force of Nature; Tadeas, Juniper Ascendant; The Celestial Toymaker; The Fifteenth Doctor; The Fourteenth Doctor; The Howling Abomination; The Meep; Themberchaud; Vikya, Scorching Stalwart; Wernog, Rider's Chaplain; Will the Wise; Wolverine, Best There Is; Xenk, Paladin Unbroken; Zangief, the Red Cyclone; Zethi, Arcane Blademaster diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index ddf7270260b..2c7c9f95993 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -134,6 +134,7 @@ Halfling:Halflings Hamster:Hamsters Harpy:Harpies Hellion:Hellions +Hero:Heroes Hippo:Hippos Hippogriff:Hippogriffs Homarid:Homarids diff --git a/forge-gui/res/lists/skinsList.txt b/forge-gui/res/lists/skinsList.txt index af3af64b853..3583f6f0267 100644 --- a/forge-gui/res/lists/skinsList.txt +++ b/forge-gui/res/lists/skinsList.txt @@ -143,3 +143,39 @@ https://downloads.cardforge.org/skins/magic_blue/sprite_buttons.png https://downloads.cardforge.org/skins/magic_blue/sprite_icons.png https://downloads.cardforge.org/skins/magic_blue/sprite_start.png https://downloads.cardforge.org/skins/magic_blue/sprite_trophies.png +https://downloads.cardforge.org/skins/old_forge/bg_chaos_wheel.png +https://downloads.cardforge.org/skins/old_forge/bg_day.jpg +https://downloads.cardforge.org/skins/old_forge/bg_draft_deck.png +https://downloads.cardforge.org/skins/old_forge/bg_match.jpg +https://downloads.cardforge.org/skins/old_forge/bg_night.jpg +https://downloads.cardforge.org/skins/old_forge/bg_space.png +https://downloads.cardforge.org/skins/old_forge/bg_splash.png +https://downloads.cardforge.org/skins/old_forge/bg_splash_hd.png +https://downloads.cardforge.org/skins/old_forge/bg_texture.jpg +https://downloads.cardforge.org/skins/old_forge/font1.ttf +https://downloads.cardforge.org/skins/old_forge/hd_logo.png +https://downloads.cardforge.org/skins/old_forge/sprite_ability.png +https://downloads.cardforge.org/skins/old_forge/sprite_adv_buttons.png +https://downloads.cardforge.org/skins/old_forge/sprite_adventure.png +https://downloads.cardforge.org/skins/old_forge/sprite_attraction_lights.png +https://downloads.cardforge.org/skins/old_forge/sprite_avatars.png +https://downloads.cardforge.org/skins/old_forge/sprite_border.png +https://downloads.cardforge.org/skins/old_forge/sprite_buttons.png +https://downloads.cardforge.org/skins/old_forge/sprite_cracks.png +https://downloads.cardforge.org/skins/old_forge/sprite_cursor.png +https://downloads.cardforge.org/skins/old_forge/sprite_deckbox.png +https://downloads.cardforge.org/skins/old_forge/sprite_draftranks.png +https://downloads.cardforge.org/skins/old_forge/sprite_favicons.png +https://downloads.cardforge.org/skins/old_forge/sprite_foils.png +https://downloads.cardforge.org/skins/old_forge/sprite_hybrid_colorless.png +https://downloads.cardforge.org/skins/old_forge/sprite_icons.png +https://downloads.cardforge.org/skins/old_forge/sprite_manaicons.png +https://downloads.cardforge.org/skins/old_forge/sprite_old_foils.png +https://downloads.cardforge.org/skins/old_forge/sprite_phyrexian.png +https://downloads.cardforge.org/skins/old_forge/sprite_planar_conquest.png +https://downloads.cardforge.org/skins/old_forge/sprite_setlogo.png +https://downloads.cardforge.org/skins/old_forge/sprite_sleeves.png +https://downloads.cardforge.org/skins/old_forge/sprite_sleeves2.png +https://downloads.cardforge.org/skins/old_forge/sprite_start.png +https://downloads.cardforge.org/skins/old_forge/sprite_trophies.png +https://downloads.cardforge.org/skins/old_forge/sprite_watermark.png diff --git a/forge-gui/res/lists/token-images.txt b/forge-gui/res/lists/token-images.txt index dbc54516161..602467b2f96 100644 --- a/forge-gui/res/lists/token-images.txt +++ b/forge-gui/res/lists/token-images.txt @@ -2100,7 +2100,6 @@ w_2_1_e_cleric.jpg https://downloads.cardforge.org/images/tokens/w_2_1_e_cleric. w_2_1_e_cleric_cmm.jpg https://downloads.cardforge.org/images/tokens/w_2_1_e_cleric_cmm.jpg w_2_1_e_cleric_ths.jpg https://downloads.cardforge.org/images/tokens/w_2_1_e_cleric_ths.jpg w_2_2 knight_vigilance_afc.jpg https://downloads.cardforge.org/images/tokens/w_2_2_knight_vigilance_afc.jpg -w_2_2_alien_rhino_who.jpg https://downloads.cardforge.org/images/tokens/w_2_2_alien_rhino_who.jpg w_2_2_alien_who.jpg https://downloads.cardforge.org/images/tokens/w_2_2_alien_who.jpg w_2_2_astartes_warrior_vigilance_40k.jpg https://downloads.cardforge.org/images/tokens/w_2_2_astartes_warrior_vigilance_40k.jpg w_2_2_cat.jpg https://downloads.cardforge.org/images/tokens/w_2_2_cat.jpg @@ -2291,7 +2290,6 @@ wu_4_4_a_golem_lci.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_a_go wu_4_4_elemental_woe.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_elemental_woe.jpg wu_4_4_sphinx_flying_vigilance.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_sphinx_flying_vigilance.jpg wu_4_4_sphinx_flying_vigilance_rna.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_sphinx_flying_vigilance_rna.jpg -wubrg_2_2_citizen_war.jpg https://downloads.cardforge.org/images/tokens/wubrg_2_2_citizen_war.jpg #Copies @@ -2309,7 +2307,7 @@ embalm_labyrinth_guardian_akh.jpg https://downloads.cardforge.org/images/tokens/ embalm_oketra's_attendant_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_oketra%27s_attendant_akh.jpg embalm_sacred_cat_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_sacred_cat_akh.jpg embalm_tah-crop_skirmisher_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_tah-crop_skirmisher_akh.jpg -embalm_temmet,_vizier_of_naktamun_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_temmet,_vizier_of_naktamun_akh.jpg +embalm_temmet_vizier_of_naktamun_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_temmet,_vizier_of_naktamun_akh.jpg embalm_trueheart_duelist_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_trueheart_duelist_akh.jpg embalm_unwavering_initiate_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_unwavering_initiate_akh.jpg embalm_vizier_of_many_faces_akh.jpg https://downloads.cardforge.org/images/tokens/embalm_vizier_of_many_faces_akh.jpg diff --git a/forge-gui/res/puzzle/PS_DSK2.pzl b/forge-gui/res/puzzle/PS_DSK2.pzl new file mode 100644 index 00000000000..02757f254d5 --- /dev/null +++ b/forge-gui/res/puzzle/PS_DSK2.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - Duskmourn: House of Horror #02 +URL:https://i0.wp.com/www.possibilitystorm.com/wp-content/uploads/2024/09/latest-2-scaled.jpg?ssl=1 +Goal:Win +Turns:1 +Difficulty:Rare +Description:Win this turn. Ensure your solution satisfies all possible blocking decisions. Good luck! +[state] +turn=1 +activeplayer=p0 +activephase=MAIN1 +p0life=20 +p0hand=Marvin, Murderous Mimic;Draconic Destiny;Corpses of the Lost;Sporogenic Infection;Gold Pan +p0battlefield=Kaito, Bane of Nightmares|Counters:LOYALTY=3;Three Tree Mascot;Island;Island;Island;Island;Island +p1life=7 +p1battlefield=Innkeeper's Talent|ClassLevel:2;Omnivorous Flytrap|Counters:P1P1=1;Cackling Slasher|Counters:P1P1=1 diff --git a/forge-gui/res/skins/default/bg_chaos_wheel.png b/forge-gui/res/skins/default/bg_chaos_wheel.png index 607aee4d149..fb42c050942 100644 Binary files a/forge-gui/res/skins/default/bg_chaos_wheel.png and b/forge-gui/res/skins/default/bg_chaos_wheel.png differ diff --git a/forge-gui/res/skins/default/bg_match.jpg b/forge-gui/res/skins/default/bg_match.jpg index ce143a5381d..b0630064e21 100644 Binary files a/forge-gui/res/skins/default/bg_match.jpg and b/forge-gui/res/skins/default/bg_match.jpg differ diff --git a/forge-gui/res/skins/default/bg_space.png b/forge-gui/res/skins/default/bg_space.png index c1cdad089cc..4e397df298c 100644 Binary files a/forge-gui/res/skins/default/bg_space.png and b/forge-gui/res/skins/default/bg_space.png differ diff --git a/forge-gui/res/skins/default/bg_splash.png b/forge-gui/res/skins/default/bg_splash.png index dca090ee57f..0bcba091a57 100644 Binary files a/forge-gui/res/skins/default/bg_splash.png and b/forge-gui/res/skins/default/bg_splash.png differ diff --git a/forge-gui/res/skins/default/bg_splash_hd.png b/forge-gui/res/skins/default/bg_splash_hd.png index d4b3279275a..2fca0a004d8 100644 Binary files a/forge-gui/res/skins/default/bg_splash_hd.png and b/forge-gui/res/skins/default/bg_splash_hd.png differ diff --git a/forge-gui/res/skins/default/bg_texture.jpg b/forge-gui/res/skins/default/bg_texture.jpg index 7c925524eb3..50f37309ff0 100644 Binary files a/forge-gui/res/skins/default/bg_texture.jpg and b/forge-gui/res/skins/default/bg_texture.jpg differ diff --git a/forge-gui/res/skins/default/cover.png b/forge-gui/res/skins/default/cover.png new file mode 100644 index 00000000000..376c2eb303a Binary files /dev/null and b/forge-gui/res/skins/default/cover.png differ diff --git a/forge-gui/res/skins/default/font1.ttf b/forge-gui/res/skins/default/font1.ttf index 8723f9e2252..28cf43d7e7f 100644 Binary files a/forge-gui/res/skins/default/font1.ttf and b/forge-gui/res/skins/default/font1.ttf differ diff --git a/forge-gui/res/skins/default/hd_logo.png b/forge-gui/res/skins/default/hd_logo.png index b4ea23cf2db..c89614178e0 100644 Binary files a/forge-gui/res/skins/default/hd_logo.png and b/forge-gui/res/skins/default/hd_logo.png differ diff --git a/forge-gui/res/skins/default/spiral.png b/forge-gui/res/skins/default/spiral.png new file mode 100644 index 00000000000..f540a2061de Binary files /dev/null and b/forge-gui/res/skins/default/spiral.png differ diff --git a/forge-gui/res/skins/default/sprite_avatars.png b/forge-gui/res/skins/default/sprite_avatars.png index 5f5e4c32a53..9aac05003f5 100644 Binary files a/forge-gui/res/skins/default/sprite_avatars.png and b/forge-gui/res/skins/default/sprite_avatars.png differ diff --git a/forge-gui/res/skins/default/sprite_buttons.png b/forge-gui/res/skins/default/sprite_buttons.png index b92e016be99..bc032afe096 100644 Binary files a/forge-gui/res/skins/default/sprite_buttons.png and b/forge-gui/res/skins/default/sprite_buttons.png differ diff --git a/forge-gui/res/skins/default/sprite_deckbox.png b/forge-gui/res/skins/default/sprite_deckbox.png index 71dc02f164d..b5148bb344b 100644 Binary files a/forge-gui/res/skins/default/sprite_deckbox.png and b/forge-gui/res/skins/default/sprite_deckbox.png differ diff --git a/forge-gui/res/skins/default/sprite_icons.png b/forge-gui/res/skins/default/sprite_icons.png index 774067843b0..44c1131b9a2 100644 Binary files a/forge-gui/res/skins/default/sprite_icons.png and b/forge-gui/res/skins/default/sprite_icons.png differ diff --git a/forge-gui/res/skins/default/sprite_planar_conquest.png b/forge-gui/res/skins/default/sprite_planar_conquest.png index fdd23e45b0a..97d36b0673a 100644 Binary files a/forge-gui/res/skins/default/sprite_planar_conquest.png and b/forge-gui/res/skins/default/sprite_planar_conquest.png differ diff --git a/forge-gui/res/skins/default/sprite_sleeves.png b/forge-gui/res/skins/default/sprite_sleeves.png index 8182a942d9b..130b8b84750 100644 Binary files a/forge-gui/res/skins/default/sprite_sleeves.png and b/forge-gui/res/skins/default/sprite_sleeves.png differ diff --git a/forge-gui/res/skins/default/sprite_sleeves2.png b/forge-gui/res/skins/default/sprite_sleeves2.png index 0a5f0565eb1..75c4e5f5891 100644 Binary files a/forge-gui/res/skins/default/sprite_sleeves2.png and b/forge-gui/res/skins/default/sprite_sleeves2.png differ diff --git a/forge-gui/res/skins/default/sprite_start.png b/forge-gui/res/skins/default/sprite_start.png index 3b20b24c5b7..b5240c7d2b9 100644 Binary files a/forge-gui/res/skins/default/sprite_start.png and b/forge-gui/res/skins/default/sprite_start.png differ diff --git a/forge-gui/res/skins/default/sprite_trophies.png b/forge-gui/res/skins/default/sprite_trophies.png index baebc020b1b..a8c2847ea48 100644 Binary files a/forge-gui/res/skins/default/sprite_trophies.png and b/forge-gui/res/skins/default/sprite_trophies.png differ diff --git a/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java b/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java index d324d5c703a..bfa1da0b429 100644 --- a/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java +++ b/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java @@ -12,11 +12,13 @@ public interface IDeviceAdapter { boolean isConnectedToWifi(); boolean isTablet(); String getDownloadsDir(); + String getVersionString(); boolean openFile(String filename); void setLandscapeMode(boolean landscapeMode); void preventSystemSleep(boolean preventSleep); void restart(); void exit(); + void closeSplashScreen(); void convertToJPEG(InputStream input, OutputStream output) throws IOException; Pair getRealScreenSize(boolean real); ArrayList getGamepads(); diff --git a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java index f07f1d21d44..7491d40d5ca 100644 --- a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java +++ b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java @@ -359,6 +359,7 @@ public enum FSkinProp { ICO_UNKNOWN (new int[] {0, 720, 80, 80}, PropType.ICON), ICO_LOGO (new int[] {480, 0, 200, 200}, PropType.ICON), + ICO_CARDART (new int[] {0, 1600, 200, 200}, PropType.ICON), ICO_FLIPCARD (new int[] {400, 0, 80, 120}, PropType.ICON), ICO_HDFLIPCARD (new int[] {2, 1268, 387, 500}, PropType.BUTTONS), diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index 4ffa07d42fc..b64572b0c43 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -1330,9 +1330,20 @@ public class HumanCostDecision extends CostDecisionMakerBase { @Override public PaymentDecision visit(final CostUnattach cost) { - final Card cardToUnattach = cost.findCardToUnattach(source, player, ability); - if (cardToUnattach != null && confirmAction(cost, Localizer.getInstance().getMessage("lblUnattachCardConfirm", CardTranslation.getTranslatedName(cardToUnattach.getName())))) { - return PaymentDecision.card(cardToUnattach); + final CardCollection cardToUnattach = cost.findCardToUnattach(source, player, ability); + if (cardToUnattach.size() == 1 && confirmAction(cost, Localizer.getInstance().getMessage("lblUnattachCardConfirm", CardTranslation.getTranslatedName(cardToUnattach.getFirst().getName())))) { + return PaymentDecision.card(cardToUnattach.getFirst()); + } + if (cardToUnattach.size() > 1) { + int c = cost.getAbilityAmount(ability); + final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, cardToUnattach, ability); + inp.setCancelAllowed(true); + inp.setMessage(Localizer.getInstance().getMessage("lblUnattachCardConfirm", cost.getDescriptiveType())); + inp.showAndWait(); + if (inp.hasCancelled() || inp.getSelected().size() != c) { + return null; + } + return PaymentDecision.card(inp.getSelected()); } return null; } @@ -1341,6 +1352,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { public boolean paysRightAfterDecision() { return true; } + private boolean confirmAction(CostPart costPart, String message) { CardView cardView = ability.getCardView(); if (GuiBase.getInterface().isLibgdxPort()) { diff --git a/forge-gui/src/main/java/forge/util/JVMOptions.java b/forge-gui/src/main/java/forge/util/JVMOptions.java new file mode 100644 index 00000000000..ced2e6e3b66 --- /dev/null +++ b/forge-gui/src/main/java/forge/util/JVMOptions.java @@ -0,0 +1,45 @@ +package forge.util; + +import com.google.common.collect.Sets; + +import java.util.HashSet; +import java.util.List; + +public class JVMOptions { + + static StringBuilder sb; + static HashSet mandatoryArgs = Sets.newHashSet( + "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.math=ALL-UNNAMED", + "--add-opens=java.base/java.net=ALL-UNNAMED", + "--add-opens=java.base/java.nio=ALL-UNNAMED", + "--add-opens=java.base/java.text=ALL-UNNAMED", + "--add-opens=java.base/java.util.concurrent=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED", + "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens=java.desktop/java.awt.font=ALL-UNNAMED", + "--add-opens=java.desktop/java.awt=ALL-UNNAMED", + "--add-opens=java.desktop/java.beans=ALL-UNNAMED", + "--add-opens=java.desktop/javax.swing.border=ALL-UNNAMED", + "--add-opens=java.desktop/javax.swing=ALL-UNNAMED" + ); + public static StringBuilder getStringBuilder() { + if (sb == null) { + sb = new StringBuilder(); + sb.append("Forge failed to initialize JVM arguments.\n") + .append("Use forge.exe | forge.sh | forge.cmd for Desktop UI.\n") + .append("Use forge-adventure.exe | forge-adventure.sh | forge-adventure.cmd for Mobile UI.\n") + .append("Alternatively, add all these JVM Options in your Command line: \n"); + for (String arg : mandatoryArgs) + sb.append(arg.replace("=", " ")).append("\n"); + } + return sb; + } + public static boolean checkRuntime(List arguments) { + if (arguments.isEmpty()) + return false; + return Sets.newHashSet(arguments).containsAll(mandatoryArgs); + } +} diff --git a/forge-installer/ReadMeForge.txt b/forge-installer/ReadMeForge.txt new file mode 100644 index 00000000000..1d03a043109 --- /dev/null +++ b/forge-installer/ReadMeForge.txt @@ -0,0 +1,29 @@ +What is Forge? + +Forge is a "Rules Engine" for the game Magic: the Gathering. +Forge is not related in any way with Wizards of the Coast. +Forge is open source software released under the GNU Public License. + +Adventure Mode + +Forge now has an Adventure Mode, along with the Classic deck building and match game modes with AI. + +Adventure is baked into the Android/Mobile release of Forge, and as a separate executable already provided in the Desktop release package. + +Java Requirement + +Forge Requires Java to run, please make sure you have Java installed on your machine prior to attempting to run. + +Choices: + +Option 1: Java JDK +Download - https://www.oracle.com/java/technologies/downloads/ + +Option 2: Alternate OpenJDK Distribution (JDK 17 LTS or higher) + +Liberica JDK +Download - https://bell-sw.com/pages/downloads/#jdk-17-lts + +Adoptium +Download - https://adoptium.net/temurin/releases/?version=17 + diff --git a/forge-installer/ic_launcher.png b/forge-installer/ic_launcher.png new file mode 100644 index 00000000000..ad7c6ed96bb Binary files /dev/null and b/forge-installer/ic_launcher.png differ diff --git a/forge-installer/libs/default-dir.txt b/forge-installer/libs/default-dir.txt new file mode 100644 index 00000000000..085649f055b --- /dev/null +++ b/forge-installer/libs/default-dir.txt @@ -0,0 +1 @@ +$project.build.finalName$ \ No newline at end of file diff --git a/forge-installer/libs/eng.xml b/forge-installer/libs/eng.xml new file mode 100644 index 00000000000..3ab2ebbaebf --- /dev/null +++ b/forge-installer/libs/eng.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/forge-installer/libs/install.xml b/forge-installer/libs/install.xml new file mode 100644 index 00000000000..e1aa18b1312 --- /dev/null +++ b/forge-installer/libs/install.xml @@ -0,0 +1,82 @@ + + + + $project.build.finalName$ + $month.date$ + https://card-forge.github.io/forge/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Linux/Unix executables to install with permission if able. Grant permission manually if the installer failed to access permission. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/forge-installer/pom.xml b/forge-installer/pom.xml new file mode 100644 index 00000000000..40604fff99b --- /dev/null +++ b/forge-installer/pom.xml @@ -0,0 +1,294 @@ + + 4.0.0 + + + forge + forge + ${revision} + + + forge-installer + pom + Forge Installer + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + timestamp-property + initialize + + timestamp-property + + + + month.date + MM.dd + + + + regex-property + initialize + + regex-property + + + + snapshot-version + ${revision} + -SNAPSHOT + -SNAPSHOT-${month.date} + false + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + initialize + + replace + + + + + ${project.basedir}/libs + default-dir.txt, install.xml, eng.xml + ${project.basedir}/target + . + false + + + $project.build.finalName$ + ${project.build.finalName} + + + $month.date$ + ${month.date} + + + + + + + + + forge + forge-gui-mobile-dev + ${project.version} + compile + + + forge + forge-gui-desktop + ${project.version} + compile + + + + + windows-linux + + + + org.codehaus.izpack + izpack-maven-plugin + 5.2.3 + + + post-integration-test + + izpack + + + + ${project.basedir}/target + ${project.basedir}/target/install.xml + ${project.basedir}/target + ${project.build.finalName} + + + + + + org.codehaus.izpack + izpack-panel + 5.2.3 + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.0.0 + + + org.apache.ant + ant-nodeps + 1.8.1 + + + + + izpack-prepare + initialize + + + + + + + + + + run + + + + win-linux-app-bundle + pre-integration-test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + released-version + validate + + released-version + + + + parse-version + + parse-version + + + + attach-distribution + verify + + attach-artifact + + + + + ${basedir}/target/${project.build.finalName}.jar + jar + + + + + + + + + + + \ No newline at end of file diff --git a/forge-installer/side.png b/forge-installer/side.png new file mode 100644 index 00000000000..4bff2946814 Binary files /dev/null and b/forge-installer/side.png differ diff --git a/forge-lda/pom.xml b/forge-lda/pom.xml index 133db8447af..7cc9377a9d1 100644 --- a/forge-lda/pom.xml +++ b/forge-lda/pom.xml @@ -4,25 +4,21 @@ forge forge - 1.6.66-SNAPSHOT + ${revision} forge-lda jar Forge LDA - - 1.6.39.001 - - src maven-compiler-plugin - 1.8 - 1.8 + 17 + 17 @@ -32,7 +28,7 @@ true - forge-lda-${alpha-version} + forge-lda-${revision} @@ -56,11 +52,6 @@ forge-gui ${project.version} - - org.apache.commons - commons-lang3 - 3.8.1 - forge forge-gui-desktop diff --git a/pom.xml b/pom.xml index 4a92e6929c3..14ebe1ebca8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ forge pom Forge Parent - 1.6.66-SNAPSHOT + ${revision} Forge lets you play the card game Magic: The Gathering against a computer opponent using all of the rules. @@ -24,7 +24,13 @@ UTF-8 ./forge-gui src/main/config - 8 + 17 + + 2.0.00 + + -SNAPSHOT + + ${versionCode}${snapshotName} @@ -61,12 +67,13 @@ forge-ai forge-gui forge-gui-mobile - forge-adventure forge-gui-mobile-dev - forge-gui-android - forge-gui-ios forge-gui-desktop + forge-gui-ios forge-lda + adventure-editor + forge-gui-android + forge-installer @@ -88,7 +95,7 @@ org.apache.maven.wagon wagon-ftp - 2.6 + 3.5.3 @@ -102,17 +109,18 @@ maven-compiler-plugin - 3.1 + 3.8.1 - 1.8 - 1.8 + 17 + 17 + 17 org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 3.10.1 true false @@ -125,18 +133,30 @@ org.apache.maven.plugins maven-surefire-plugin - 2.16 + 3.1.2 + + + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.time=ALL-UNNAMED + --add-opens java.base/java.text=ALL-UNNAMED + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.util.regex=ALL-UNNAMED + --add-opens java.base/java.util.stream=ALL-UNNAMED + --add-opens java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.desktop/javax.imageio.spi=ALL-UNNAMED + + org.apache.maven.plugins maven-deploy-plugin - 2.8.1 + 3.0.0 org.apache.maven.wagon wagon-ftp - 2.6 + 3.5.3 @@ -144,40 +164,40 @@ org.apache.maven.plugins maven-jar-plugin - 2.4 + 3.3.0 org.apache.maven.plugins maven-site-plugin - 3.3 + 3.9.1 org.apache.maven.plugins maven-antrun-plugin - 1.7 + 3.0.0 maven-assembly-plugin - 2.4 + 3.3.0 maven-install-plugin - 2.5.1 + 3.0.1 org.apache.maven.plugins maven-dependency-plugin - 2.8 + 3.1.2 maven-release-plugin - 2.5 + 3.0.1 true @@ -188,33 +208,32 @@ maven-resources-plugin - 2.6 + 3.3.1 org.apache.maven.plugins maven-clean-plugin - 2.5 + 3.1.0 org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.1 org.apache.maven.plugins maven-scm-plugin - 1.9 + 1.11.2 org.apache.maven.wagon wagon-ftp - 2.6 + 3.5.3 - @@ -228,7 +247,7 @@ org.codehaus.mojo build-helper-maven-plugin - [3.1,) + [3.2,) released-version parse-version @@ -272,10 +291,10 @@ - [3.5.9,) + [3.8.1,) - [1.8,) + 17 @@ -286,7 +305,14 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.0.0 + 3.1.2 + + + com.puppycrawl.tools + checkstyle + 10.18.2 + + checkstyle-validation @@ -305,8 +331,32 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.6.0 + + true + resolveCiFriendliesOnly + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + - @@ -314,12 +364,17 @@ ch.qos.logback logback-classic - 1.2.11 + 1.5.11 ch.qos.logback logback-core - 1.2.11 + 1.5.11 + + + org.slf4j + slf4j-api + 2.0.16