From d76012c17d2b34846493d7d5192eecbb53f2eceb Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 19:49:47 +0300 Subject: [PATCH 01/36] Fix travis --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f8d9d6..58f0796 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: java -jdk: -- oraclejdk8 script: - mvn clean install -B -V From 30ab63afad32f5f7463c6b99efd01550721b57d8 Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 20:00:45 +0300 Subject: [PATCH 02/36] Add Sekiro support --- src/com/speedsouls/organizer/games/Game.java | 341 ++++++++++--------- 1 file changed, 171 insertions(+), 170 deletions(-) diff --git a/src/com/speedsouls/organizer/games/Game.java b/src/com/speedsouls/organizer/games/Game.java index f7ed873..8728c15 100644 --- a/src/com/speedsouls/organizer/games/Game.java +++ b/src/com/speedsouls/organizer/games/Game.java @@ -1,170 +1,171 @@ -package com.speedsouls.organizer.games; - - -import java.io.File; -import java.util.Collections; -import java.util.LinkedList; - -import com.speedsouls.organizer.profileconfig.Profile; - - -/** - * Game Enum. - *

- * Enum representing the different games with a constant for each. - * - * @author Kahmul (www.twitch.tv/kahmul78) - * @date 27 Sep 2015 - */ -public enum Game -{ - - DARK_SOULS("Dark Souls", "DS1", "DRAKS0005.sl2"), - DARK_SOULS_REMASTERED("Dark Souls Remastered", "DSR", "DRAKS0005.sl2"), - DARK_SOULS_II("Dark Souls II", "DS2", "DARKSII0000.sl2"), - DARK_SOULS_II_SOTFS("Dark Souls II: SotFS", "DS2SOTFS", "DS2SOFS0000.sl2"), - DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"); - - private String caption; - private String abbr; - private String saveName; - private File directory; - private File saveFile; - private LinkedList profiles; - - - /** - * Creates a new Game constant. - * - * @param caption the caption of this game - * @param abbr the abbreviation of this game - * @param saveName the name of the game's savefile - */ - private Game(String caption, String abbr, String saveName) - { - this.caption = caption; - this.abbr = abbr; - this.saveName = saveName; - profiles = new LinkedList<>(); - } - - - /** - * Returns the caption of this game. - * - * @return the caption of this game - */ - public String getCaption() - { - return caption; - } - - - /** - * Returns the abbreviation of this game. - * - * @return the abbreviation of this game - */ - public String getAbbreviation() - { - return abbr; - } - - - /** - * Returns the directory associated with this game. - * - * @return the directory associated with this game - */ - public File getDirectory() - { - return directory; - } - - - /** - * Sets the directory to associate with this game. - * - * @param file the new directory - */ - public void setDirectory(File file) - { - profiles.clear(); - if (file.isDirectory()) - { - directory = file; - File[] files = file.listFiles(); - for (File dir : files) - { - if (dir.isDirectory()) - { - addProfile(new Profile(dir.getName(), this)); - } - } - } - } - - - /** - * Returns the location of the game's savestate as a File object. - * - * @return the location of the game's savestate. - */ - public File getSaveFileLocation() - { - return saveFile; - } - - - /** - * Sets the location of the savefile of this game. - * - * @param saveFile the new location - */ - public void setSaveFileLocation(File saveFile) - { - if (saveFile.getName().equals(getSaveName())) - this.saveFile = saveFile; - } - - - /** - * Returns the name of the game's savestate. - * - * @return the name of the game's savestate. - */ - public String getSaveName() - { - return saveName; - } - - - /** - * @return the profiles - */ - public LinkedList getProfiles() - { - return profiles; - } - - - /** - * @param profile - */ - public void addProfile(Profile profile) - { - profiles.add(profile); - Collections.sort(profiles); - } - - - /** - * @param profile - */ - public void removeProfile(Profile profile) - { - profiles.remove(profile); - Collections.sort(profiles); - } - -} +package com.speedsouls.organizer.games; + + +import java.io.File; +import java.util.Collections; +import java.util.LinkedList; + +import com.speedsouls.organizer.profileconfig.Profile; + + +/** + * Game Enum. + *

+ * Enum representing the different games with a constant for each. + * + * @author Kahmul (www.twitch.tv/kahmul78) + * @date 27 Sep 2015 + */ +public enum Game +{ + + DARK_SOULS("Dark Souls", "DS1", "DRAKS0005.sl2"), + DARK_SOULS_REMASTERED("Dark Souls Remastered", "DSR", "DRAKS0005.sl2"), + DARK_SOULS_II("Dark Souls II", "DS2", "DARKSII0000.sl2"), + DARK_SOULS_II_SOTFS("Dark Souls II: SotFS", "DS2SOTFS", "DS2SOFS0000.sl2"), + DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"), + SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"); + + private String caption; + private String abbr; + private String saveName; + private File directory; + private File saveFile; + private LinkedList profiles; + + + /** + * Creates a new Game constant. + * + * @param caption the caption of this game + * @param abbr the abbreviation of this game + * @param saveName the name of the game's savefile + */ + Game(String caption, String abbr, String saveName) + { + this.caption = caption; + this.abbr = abbr; + this.saveName = saveName; + profiles = new LinkedList<>(); + } + + + /** + * Returns the caption of this game. + * + * @return the caption of this game + */ + public String getCaption() + { + return caption; + } + + + /** + * Returns the abbreviation of this game. + * + * @return the abbreviation of this game + */ + public String getAbbreviation() + { + return abbr; + } + + + /** + * Returns the directory associated with this game. + * + * @return the directory associated with this game + */ + public File getDirectory() + { + return directory; + } + + + /** + * Sets the directory to associate with this game. + * + * @param file the new directory + */ + public void setDirectory(File file) + { + profiles.clear(); + if (file.isDirectory()) + { + directory = file; + File[] files = file.listFiles(); + for (File dir : files) + { + if (dir.isDirectory()) + { + addProfile(new Profile(dir.getName(), this)); + } + } + } + } + + + /** + * Returns the location of the game's savestate as a File object. + * + * @return the location of the game's savestate. + */ + public File getSaveFileLocation() + { + return saveFile; + } + + + /** + * Sets the location of the savefile of this game. + * + * @param saveFile the new location + */ + public void setSaveFileLocation(File saveFile) + { + if (saveFile.getName().equals(getSaveName())) + this.saveFile = saveFile; + } + + + /** + * Returns the name of the game's savestate. + * + * @return the name of the game's savestate. + */ + public String getSaveName() + { + return saveName; + } + + + /** + * @return the profiles + */ + public LinkedList getProfiles() + { + return profiles; + } + + + /** + * @param profile + */ + public void addProfile(Profile profile) + { + profiles.add(profile); + Collections.sort(profiles); + } + + + /** + * @param profile + */ + public void removeProfile(Profile profile) + { + profiles.remove(profile); + Collections.sort(profiles); + } + +} From e67f9385b2bd128af26ff44f4ce0d53ce3bd9a65 Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 20:28:18 +0300 Subject: [PATCH 03/36] Extend travis support --- .travis.yml | 23 ++++++++++++++++++++--- travis/build.bat | 2 ++ travis/build.sh | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 travis/build.bat create mode 100644 travis/build.sh diff --git a/.travis.yml b/.travis.yml index 58f0796..f219e21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,24 @@ -language: java +os: windows +language: shell + +install: +- choco install jdk11 -params "source=false" +- choco install maven script: -- mvn clean install -B -V +- mvn package notifications: - email: false \ No newline at end of file + email: false + +deploy: + - provider: releases + api_key: + secure: fYIKgl8EvLBYTG8ovd5P9LZVZIR/m3MnYMIPYQtoxYfiPeCTDzJxtGj+gRf5VbX9BgImvr3pWArOT09SCndjBlB63df4szGeuGXPTZMZzKPeaxZhyGo/OTMI2WiMoicrrkt3O024oWr719HL1Hd8Wa9FrV8isRS+bCy2WrTLa8PsclBsPy2onahrK8aAU3hvO0IogPpQz2mxgQ/KuZHdf0N7Xv0E2Qf9zyBFOZoJ5XSff8d3dJMofng7NoUsc8pFdCJmFuA+VlP61677R2OCNu2S4anoOX8g6PNHPD9SR/Itm8uQM7/Vcp4xo9Hn22h6D+kXVcJ0PaeKGctIC7JTNYrOziSORvyC8vHeUDt0u0s2WdOfju+76WN640Tz2EMLsuyIWDG7kyvTYdSUCp6ibQQLBXcZIpuVPfyd8dKjAkoItiuBKCIoN78CZfxRUs6fDFmxT73W6vCHOK+nsUVQseL2cCnn1MR9nGjTdQzXkRqCg/X6A1G8Qnmts9M1rg6kCTDoUo9dTAY2kDJ1wcXWjD28BKpxX16ya5NnMifkt6CGrS9zr+6VI0MgLdpsAj7W8AoVcCvquuaby0vpI/nGWo72hvrz/DDkp6m6MAWP2p+zNUaydouKSiGchs/QAEBrxGR53mWTZM2RqCxo+ycFQ7ofNZyy16IEc+e1twQol4o= + file_glob: true + file: + - $TRAVIS_BUILD_DIR/target/SaveOrganizer.exe + skip_cleanup: true + on: + tags: true + branch: master \ No newline at end of file diff --git a/travis/build.bat b/travis/build.bat new file mode 100644 index 0000000..e16efdc --- /dev/null +++ b/travis/build.bat @@ -0,0 +1,2 @@ +call RefreshEnv.cmd +mvn package \ No newline at end of file diff --git a/travis/build.sh b/travis/build.sh new file mode 100644 index 0000000..1894d09 --- /dev/null +++ b/travis/build.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./travis/build.bat \ No newline at end of file From 84a1ed6dc4f614ac8ad799fdb562a21e5ed0754a Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 20:31:45 +0300 Subject: [PATCH 04/36] Fix travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f219e21..05b310a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ os: windows language: shell install: -- choco install jdk11 -params "source=false" -- choco install maven +- choco install jdk11 -y -params "source=false" +- choco install maven -y script: - mvn package From 00856b8b654ca41110d792e6f3c417dbec96c197 Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 20:34:33 +0300 Subject: [PATCH 05/36] Fix jdk version in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 05b310a..984db6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ os: windows language: shell install: -- choco install jdk11 -y -params "source=false" +- choco install openjdk11 -y - choco install maven -y script: From 3e65080506316f78f73de8a4db6003b3276936f4 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 20:53:41 +0300 Subject: [PATCH 06/36] Create maven-buil.yml --- .github/workflows/maven-buil.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/maven-buil.yml diff --git a/.github/workflows/maven-buil.yml b/.github/workflows/maven-buil.yml new file mode 100644 index 0000000..9c76514 --- /dev/null +++ b/.github/workflows/maven-buil.yml @@ -0,0 +1,26 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master, develop ] + pull_request: + branches: [ master, develop ] + +jobs: + build: + runs-on: windows-latest + steps: + - name: Configure git + run: "git config --global core.autocrlf false" + shell: bash + - uses: actions/checkout@v2 + - name: Set up JDK 12 + uses: actions/setup-java@v1 + with: + java-version: 12 + - name: Build with Maven + shell: bash + run: mvn -B package --file pom.xml From b87db3f0cd6c33a954dcc119062cdfbe9feff3bd Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 20:53:56 +0300 Subject: [PATCH 07/36] Rename maven-buil.yml to maven-build.yml --- .github/workflows/{maven-buil.yml => maven-build.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{maven-buil.yml => maven-build.yml} (100%) diff --git a/.github/workflows/maven-buil.yml b/.github/workflows/maven-build.yml similarity index 100% rename from .github/workflows/maven-buil.yml rename to .github/workflows/maven-build.yml From a617f73363ca611ee7615eda263641c8549d3eff Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 21:05:19 +0300 Subject: [PATCH 08/36] Create maven-publish.yml --- .github/workflows/maven-publish.yml | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/maven-publish.yml diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml new file mode 100644 index 0000000..7a582d9 --- /dev/null +++ b/.github/workflows/maven-publish.yml @@ -0,0 +1,46 @@ +# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path + +name: Maven Package Release + +on: + push: + tags: + - v* + +jobs: + build: + runs-on: windows-latest + steps: + - name: Configure git + run: "git config --global core.autocrlf false" + shell: bash + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up JDK 12 + uses: actions/setup-java@v1 + with: + java-version: 12 + - name: Build with Maven + shell: bash + run: mvn -B package --file pom.xml + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./my-artifact.zip + asset_name: my-artifact.zip + asset_content_type: application/zip From d00d77428eaa197216cfee705039f3c5ca875136 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 21:33:49 +0300 Subject: [PATCH 09/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 7a582d9..dd8c0f8 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -1,7 +1,7 @@ # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created # For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path -name: Maven Package Release +name: [Maven] Package Release on: push: @@ -24,6 +24,10 @@ jobs: - name: Build with Maven shell: bash run: mvn -B package --file pom.xml + - name: Create Zip File + uses: montudor/action-zip@v0.1.0 + with: + args: zip -qq -r ./SaveOrganizer-${{ github.ref }}.zip ./target/SaveOrganizer.exe - name: Create Release id: create_release uses: actions/create-release@v1 @@ -41,6 +45,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./my-artifact.zip - asset_name: my-artifact.zip + asset_path: ./SaveOrganizer-${{ github.ref }}.zip + asset_name: SaveOrganizer-${{ github.ref }}.zip asset_content_type: application/zip From f4ecd0aa1e81f131e694a871859b75741acdb288 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:02:05 +0300 Subject: [PATCH 10/36] Create tagging.yml --- .github/workflows/tagging.yml | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/tagging.yml diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml new file mode 100644 index 0000000..691b4a8 --- /dev/null +++ b/.github/workflows/tagging.yml @@ -0,0 +1,38 @@ +# This is a basic workflow to help you get started with Actions + +name: Add tag + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: [ master ] +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + tag: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + # Runs a single command using the runners shell + - name: Get XML Info + uses: mavrosxristoforos/get-xml-info@1.0 + with: + # The xml file from which to retrieve information. + xml-file: pom.xml + # The XPath of a node, to fetch its contents as output. + xpath: /project/version + + # Runs a set of commands using the runners shell + - name: Commit tagger + uses: tvdias/github-tagger@v0.0.2 + with: + # The GITHUB_TOKEN secret + repo-token: ${{ secrets.GITHUB_TOKEN }} + # Tag text + tag: v'/project/version' From bb486434513055f6365ed480ae61762703fa38c6 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:02:14 +0300 Subject: [PATCH 11/36] Update and rename maven-build.yml to maven-pr.yml --- .../{maven-build.yml => maven-pr.yml} | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) rename .github/workflows/{maven-build.yml => maven-pr.yml} (62%) diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-pr.yml similarity index 62% rename from .github/workflows/maven-build.yml rename to .github/workflows/maven-pr.yml index 9c76514..6f6741c 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-pr.yml @@ -1,13 +1,11 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Java CI with Maven +name: [Maven] Pull Request build and merge on: - push: - branches: [ master, develop ] pull_request: - branches: [ master, develop ] + branches: [ master ] jobs: build: @@ -24,3 +22,15 @@ jobs: - name: Build with Maven shell: bash run: mvn -B package --file pom.xml + merge: + needs: build + name: Merge me! + runs-on: ubuntu-latest + steps: + - name: Merge me! + uses: ridedott/merge-me-action@v1.2.62 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_LOGIN: mckunda + MERGE_METHOD: MERGE + From f1eec313ef7b158d9b0d52acf97bc2bc6ccbb92f Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:04:09 +0300 Subject: [PATCH 12/36] Update tagging.yml --- .github/workflows/tagging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 691b4a8..7e792bd 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -24,7 +24,7 @@ jobs: uses: mavrosxristoforos/get-xml-info@1.0 with: # The xml file from which to retrieve information. - xml-file: pom.xml + xml-file: $GITHUB_WORKSPACE/pom.xml # The XPath of a node, to fetch its contents as output. xpath: /project/version From fd8416f4bc1dd226b0460553276bcf01f77c5d8c Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:05:24 +0300 Subject: [PATCH 13/36] Update tagging.yml --- .github/workflows/tagging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 7e792bd..97a1296 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -24,7 +24,7 @@ jobs: uses: mavrosxristoforos/get-xml-info@1.0 with: # The xml file from which to retrieve information. - xml-file: $GITHUB_WORKSPACE/pom.xml + xml-file: ${{GITHUB_WORKSPACE}}/pom.xml # The XPath of a node, to fetch its contents as output. xpath: /project/version From 3714b25000fccfa780d7c5a93c82bd970dfd2d0b Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:05:59 +0300 Subject: [PATCH 14/36] Update tagging.yml --- .github/workflows/tagging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 97a1296..2558266 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -24,7 +24,7 @@ jobs: uses: mavrosxristoforos/get-xml-info@1.0 with: # The xml file from which to retrieve information. - xml-file: ${{GITHUB_WORKSPACE}}/pom.xml + xml-file: ./pom.xml # The XPath of a node, to fetch its contents as output. xpath: /project/version From 042f86ae39cfa5b3657cd8a2ca2af716425aa124 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:09:16 +0300 Subject: [PATCH 15/36] Update tagging.yml --- .github/workflows/tagging.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 2558266..2ec424c 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -24,9 +24,9 @@ jobs: uses: mavrosxristoforos/get-xml-info@1.0 with: # The xml file from which to retrieve information. - xml-file: ./pom.xml + xml-file: pom.xml # The XPath of a node, to fetch its contents as output. - xpath: /project/version + xpath: '/project/version' # Runs a set of commands using the runners shell - name: Commit tagger From ba42d0e1f3addf5117b939ad5fd4a37d34ff8ec4 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:10:02 +0300 Subject: [PATCH 16/36] Update tagging.yml --- .github/workflows/tagging.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 2ec424c..9e1ba70 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -26,7 +26,7 @@ jobs: # The xml file from which to retrieve information. xml-file: pom.xml # The XPath of a node, to fetch its contents as output. - xpath: '/project/version' + xpath: '//version' # Runs a set of commands using the runners shell - name: Commit tagger @@ -35,4 +35,4 @@ jobs: # The GITHUB_TOKEN secret repo-token: ${{ secrets.GITHUB_TOKEN }} # Tag text - tag: v'/project/version' + tag: v'//version' From c27da0fb6739352a44977fab45d0d5ae66cf5f91 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:53:02 +0300 Subject: [PATCH 17/36] Update tagging.yml --- .github/workflows/tagging.yml | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 9e1ba70..a2bac68 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -20,19 +20,27 @@ jobs: - uses: actions/checkout@v2 # Runs a single command using the runners shell - - name: Get XML Info - uses: mavrosxristoforos/get-xml-info@1.0 + - name: YAML/JSON/XML Converter Action + uses: fabasoad/yaml-json-xml-converter-action@v1.0.1 with: - # The xml file from which to retrieve information. - xml-file: pom.xml - # The XPath of a node, to fetch its contents as output. - xpath: '//version' + # Path to the file + path: pom.xml + # Format of a file. Possible values: json, xml, yaml. + from: xml + # Format of a file as a result. Possible values: json, xml, yaml. + to: json + + - name: Read Properties + id: read_property + uses: ashley-taylor/read-json-property-action@v1.0 + with: + path: pom.json + property: project.version - # Runs a set of commands using the runners shell - name: Commit tagger uses: tvdias/github-tagger@v0.0.2 with: # The GITHUB_TOKEN secret repo-token: ${{ secrets.GITHUB_TOKEN }} # Tag text - tag: v'//version' + tag: v${{ steps.read_property.outputs.value }} From 51bd36c1bd49c23e32a4743430da51fe09425043 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 22:58:21 +0300 Subject: [PATCH 18/36] Update tagging.yml --- .github/workflows/tagging.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index a2bac68..6e8e4ea 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -21,6 +21,7 @@ jobs: # Runs a single command using the runners shell - name: YAML/JSON/XML Converter Action + id: xml2json uses: fabasoad/yaml-json-xml-converter-action@v1.0.1 with: # Path to the file @@ -30,12 +31,13 @@ jobs: # Format of a file as a result. Possible values: json, xml, yaml. to: json - - name: Read Properties - id: read_property - uses: ashley-taylor/read-json-property-action@v1.0 + - name: Get JSON paths + id: jsondata + uses: gr2m/get-json-paths-action@v1.0.1 with: - path: pom.json - property: project.version + # JSON string + json: ${{ steps.xml2json.outputs.data }} + version: "project.version" - name: Commit tagger uses: tvdias/github-tagger@v0.0.2 @@ -43,4 +45,4 @@ jobs: # The GITHUB_TOKEN secret repo-token: ${{ secrets.GITHUB_TOKEN }} # Tag text - tag: v${{ steps.read_property.outputs.value }} + tag: v${{ steps.jsondata.outputs.version }} From 0cde0fee202a5679b9671a2d1b589a339f474236 Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 23:00:29 +0300 Subject: [PATCH 19/36] Update version to v1.4.2 --- pom.xml | 262 +- .../organizer/data/OrganizerManager.java | 2430 ++++++++--------- 2 files changed, 1346 insertions(+), 1346 deletions(-) diff --git a/pom.xml b/pom.xml index fb43b0f..67fc94e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,132 +1,132 @@ - - 4.0.0 - SpeedSouls - SaveOrganizer - 1.4.1-SNAPSHOT - - - - com.1stleg - jnativehook - 2.0.3 - - - com.github.jiconfont - jiconfont-swing - 1.0.0 - - - com.github.jiconfont - jiconfont-font_awesome - 4.7.0.0 - - - com.github.jiconfont - jiconfont-elusive - 2.0.1 - - - com.github.jiconfont - jiconfont-entypo - 2.0.1 - - - com.github.jiconfont - jiconfont-open_iconic - 1.1.1.1 - - - com.github.jiconfont - jiconfont-typicons - 2.0.7.0 - - - org.json - json - 20170516 - - - - - - - src - - - src - - **/*.java - - - - - - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - - - - maven-assembly-plugin - - - jar-with-dependencies - - - - com.speedsouls.organizer.main.OrganizerWindow - - - - - - package - - single - - - - - - - com.akathist.maven.plugins.launch4j - launch4j-maven-plugin - 1.7.23 - - - l4j-gui - package - launch4j - - gui - target/${project.name}.exe - src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico - target/${project.name}-${project.version}-jar-with-dependencies.jar - ${project.name} - - com.speedsouls.organizer.main.OrganizerWindow - - - 1.8 - - - 1.4.1.0 - 1.4.1.0 - ${project.name} - N/A - 1.4.1.0 - 1.4.1.0 - ${project.name} - ${project.name} - ${project.name}.exe - - - - - - - + + 4.0.0 + SpeedSouls + SaveOrganizer + 1.4.2 + + + + com.1stleg + jnativehook + 2.0.3 + + + com.github.jiconfont + jiconfont-swing + 1.0.0 + + + com.github.jiconfont + jiconfont-font_awesome + 4.7.0.0 + + + com.github.jiconfont + jiconfont-elusive + 2.0.1 + + + com.github.jiconfont + jiconfont-entypo + 2.0.1 + + + com.github.jiconfont + jiconfont-open_iconic + 1.1.1.1 + + + com.github.jiconfont + jiconfont-typicons + 2.0.7.0 + + + org.json + json + 20170516 + + + + + + + src + + + src + + **/*.java + + + + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + maven-assembly-plugin + + + jar-with-dependencies + + + + com.speedsouls.organizer.main.OrganizerWindow + + + + + + package + + single + + + + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.7.23 + + + l4j-gui + package + launch4j + + gui + target/${project.name}.exe + src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico + target/${project.name}-${project.version}-jar-with-dependencies.jar + ${project.name} + + com.speedsouls.organizer.main.OrganizerWindow + + + 1.8 + + + 1.4.2.0 + 1.4.2.0 + ${project.name} + N/A + 1.4.2.0 + 1.4.2.0 + ${project.name} + ${project.name} + ${project.name}.exe + + + + + + + \ No newline at end of file diff --git a/src/com/speedsouls/organizer/data/OrganizerManager.java b/src/com/speedsouls/organizer/data/OrganizerManager.java index ffe9173..0a49422 100644 --- a/src/com/speedsouls/organizer/data/OrganizerManager.java +++ b/src/com/speedsouls/organizer/data/OrganizerManager.java @@ -1,1215 +1,1215 @@ -package com.speedsouls.organizer.data; - - -import java.awt.Desktop; -import java.awt.Dimension; -import java.awt.Image; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URI; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.prefs.Preferences; - -import javax.imageio.ImageIO; -import javax.swing.JOptionPane; - -import org.jnativehook.NativeHookException; -import org.json.JSONObject; - -import com.speedsouls.organizer.games.Game; -import com.speedsouls.organizer.hotkeys.GlobalHotkey; -import com.speedsouls.organizer.hotkeys.GlobalKeyboardHook; -import com.speedsouls.organizer.listeners.NavigationListener; -import com.speedsouls.organizer.listeners.ProfileListener; -import com.speedsouls.organizer.listeners.SaveListener; -import com.speedsouls.organizer.listeners.SearchListener; -import com.speedsouls.organizer.listeners.SortingListener; -import com.speedsouls.organizer.main.OrganizerWindow; -import com.speedsouls.organizer.messages.AbstractMessage; -import com.speedsouls.organizer.profileconfig.Profile; -import com.speedsouls.organizer.savelist.Folder; -import com.speedsouls.organizer.savelist.Save; -import com.speedsouls.organizer.savelist.SaveListEntry; -import com.speedsouls.organizer.savelist.SortingCategory; - -import jiconfont.icons.Elusive; -import jiconfont.icons.Entypo; -import jiconfont.icons.FontAwesome; -import jiconfont.icons.Iconic; -import jiconfont.icons.Typicons; -import jiconfont.swing.IconFontSwing; - - -/** - * OrganizerManager. - *

- * Manages storing and retrieving of the used data (e.g. profiles, saves, images). Handles listener events for profiles, saves and - * games. Offers utility methods. - * - * @author Kahmul (www.twitch.tv/kahmul78) - * @date 27 Sep 2015 - */ -public class OrganizerManager -{ - - public static final String VERSION = "1.4.1"; - - /** - * Constants defining various URLs. - */ - public static final String WEB_PAGE_URL = "www.speedsouls.com/SpeedSouls_-_Save_Organizer"; - public static final String GITHUB_REPO_URL = "www.github.com/Kahmul/SpeedSouls-Save-Organizer"; - public static final String TWITTER_URL = "www.twitter.com/Kahmul78"; - public static final String LATEST_RELEASE_JSON_URL = "https://api.github.com/repos/Kahmul/SpeedSouls-Save-Organizer/releases/latest"; - public static final String LATEST_RELEASE_URL = "https://github.com/Kahmul/SpeedSouls-Save-Organizer/releases"; - - /** - * Constants for paths to preferences and resources. - */ - private static final String RESOURCE_PATH = "/com/speedsouls/organizer/resources/"; - private static final String PREFERENCES_PATH = "/com/speedsouls/organizer/prefs"; - - /** - * Constants for the keys used to access preferences. - */ - private static final String PREFS_KEY_INITIAL_STARTUP = "initStartup"; - private static final String PREFS_KEY_VERSION = "Version"; - - private static final String PREFS_KEY_WIN_WIDTH = "WindowWidth"; - private static final String PREFS_KEY_WIN_HEIGHT = "WindowHeight"; - - private static final String PREFS_KEY_SELECTED_GAME = "selectedGame"; - private static final String PREFS_KEY_SELECTED_PROFILE = "selectedProfile"; - private static final String PREFS_KEY_SELECTED_SORTING = "selectedSorting"; - - private static final String PREFS_KEY_SETTING_ALWAYS_ON_TOP = "alwaysOnTop"; - private static final String PREFS_KEY_SETTING_GLOBAL_HOTKEYS = "globalHotkeys"; - - public static final String PREFS_KEY_GLOBAL_HOTKEY_LOAD = "hotkeyLoad"; - public static final String PREFS_KEY_GLOBAL_HOTKEY_READ_ONLY = "hotkeyReadOnly"; - public static final String PREFS_KEY_GLOBAL_HOTKEY_PREV_SAVE = "hotkeyPrevSave"; - public static final String PREFS_KEY_GLOBAL_HOTKEY_NEXT_SAVE = "hotkeyNextSave"; - public static final String PREFS_KEY_GLOBAL_HOTKEY_TOGGLE = "hotkeyToggle"; - - public static final String PREFS_MODIFIER_GAME_DIR = "Path"; - public static final String PREFS_MODIFIER_GAME_SAVEFILE = "Savefile"; - - public static final String PREFS_ERROR_ON_RETRIEVE = "ERROR"; - - public static final String ILLEGAL_CHARACTERS = "~, @, *, {, }, <, >, [, ], |, \u201C, \u201D, \\, /, ^"; - private static final String ILLEGAL_CHARACTERS_REGEX = "[~#@*{}<>\\[\\]|\"\\^\\\\\\/]"; - - private static Preferences prefs; - - private static GlobalKeyboardHook keyboardHook; - - public static Image speedsoulsIcon; - public static Image speedsoulsIconMedium; - public static Image readOnlyIconMedium; - public static Image readOnlyIconSmall; - public static Image settingsIcon; - - private static List profileListeners; - private static List saveListeners; - private static List searchListeners; - private static List sortingListeners; - private static List navigationListeners; - - private static SaveListEntry selectedEntry; - - private static OrganizerWindow mainWindow; - - private static boolean isReady; - - static - { - try - { - initialize(); - } - catch (IOException e) - { - JOptionPane.showMessageDialog(null, "Error when trying to initialize the data. Could not start the Save Organizer.", - "Error occured", JOptionPane.ERROR_MESSAGE); - System.exit(1); - } - } - - - /** - * Initializes the data. Required to be called before using any other methods of this class. - * - * @throws IOException - */ - private static void initialize() throws IOException - { - importImages(); - initListeners(); - initPreferenceData(); - initKeyboardHook(); - mapGamesWithProfiles(); - - isReady = true; - } - - - /** - * Imports all the images and icons used in the program. - * - * @throws IOException - */ - private static void importImages() throws IOException - { - speedsoulsIcon = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SpeedSoulsFlameSmall.png")); - speedsoulsIconMedium = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SpeedSoulsFlameSmall.png")); - readOnlyIconSmall = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "ReadOnlyIconSmall.png")); - readOnlyIconMedium = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "ReadOnlyIconMedium.png")); - settingsIcon = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SettingsIcon.png")); - - IconFontSwing.register(FontAwesome.getIconFont()); - IconFontSwing.register(Elusive.getIconFont()); - IconFontSwing.register(Entypo.getIconFont()); - IconFontSwing.register(Iconic.getIconFont()); - IconFontSwing.register(Typicons.getIconFont()); - } - - - /** - * Inits the listener lists. - */ - private static void initListeners() - { - profileListeners = new ArrayList<>(); - saveListeners = new ArrayList<>(); - searchListeners = new ArrayList<>(); - sortingListeners = new ArrayList<>(); - navigationListeners = new ArrayList<>(); - } - - - /** - * Inits the preferences. - */ - private static void initPreferenceData() - { - prefs = Preferences.userRoot().node(PREFERENCES_PATH); - prefs.put(PREFS_KEY_VERSION, VERSION); - - // reset global hotkeys if this is the first time the organizer is started to avoid incompatibility with older versions - boolean initStartup = prefs.getBoolean(PREFS_KEY_INITIAL_STARTUP, true); - if (initStartup) - { - prefs.remove(PREFS_KEY_SETTING_GLOBAL_HOTKEYS); - prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_LOAD); - prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_READ_ONLY); - prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_PREV_SAVE); - prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_NEXT_SAVE); - prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_TOGGLE); - - prefs.putBoolean(PREFS_KEY_INITIAL_STARTUP, false); - } - } - - - /** - * Inits the global hotkey hook. - */ - private static void initKeyboardHook() - { - try - { - keyboardHook = new GlobalKeyboardHook(); - keyboardHook.setHotkeysEnabled(prefs.getBoolean(PREFS_KEY_SETTING_GLOBAL_HOTKEYS, false)); - } - catch (NativeHookException e) - { - JOptionPane.showMessageDialog(mainWindow, "Error when trying to establish the keyboard hook. Global hotkeys will be disabled.", - "Error occured", JOptionPane.ERROR_MESSAGE); - keyboardHook.setHotkeysEnabled(false); - } - } - - - /** - * Maps all the existing games with their profiles. - */ - private static void mapGamesWithProfiles() - { - if (prefs == null) - return; - Game[] games = Game.values(); - for (Game game : games) - importProfiles(game); - } - - - /** - * Searches for all the profiles of the given game. - * - * @param game the game to import the profiles for - */ - private static void importProfiles(Game game) - { - String gameDirectoryPath = prefs.get(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR, PREFS_ERROR_ON_RETRIEVE); - if (PREFS_ERROR_ON_RETRIEVE.equals(gameDirectoryPath)) - return; - File gameDirectory = new File(gameDirectoryPath); - if (!gameDirectory.exists()) - { - prefs.remove(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR); - return; - } - game.setDirectory(gameDirectory); - String saveLocationPath = prefs.get(game.getAbbreviation() + PREFS_MODIFIER_GAME_SAVEFILE, PREFS_ERROR_ON_RETRIEVE); - if (!PREFS_ERROR_ON_RETRIEVE.equals(saveLocationPath)) - { - game.setSaveFileLocation(new File(saveLocationPath)); - return; - } - // If the user used an old version, then a savefile location might not have been explicitly specified. - // In that case, use the profile directory + saveName as the savefile location - File defaultSaveFileLocation = new File(gameDirectoryPath + File.separator + game.getSaveName()); - if (defaultSaveFileLocation.exists()) - game.setSaveFileLocation(defaultSaveFileLocation); - } - - - public static boolean isApplicationReady() - { - return isReady; - } - - - /** - * Refreshes all profiles and games. - */ - public static void refreshProfiles() - { - mapGamesWithProfiles(); - } - - - /** - * Saves the properties of this game to the preferences. - * - * @param game the game to update - */ - public static void saveProperties(Game game) - { - prefs.put(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR, game.getDirectory().getPath()); - prefs.put(game.getAbbreviation() + PREFS_MODIFIER_GAME_SAVEFILE, game.getSaveFileLocation().getPath()); - importProfiles(game); - } - - - /** - * Adds a profile listener to send events to. - * - * @param listener the listener to add - */ - public static void addProfileListener(ProfileListener listener) - { - if (listener != null) - profileListeners.add(listener); - } - - - /** - * Adds a save listener to send events to. - * - * @param listener the listener to add - */ - public static void addSaveListener(SaveListener listener) - { - if (listener != null) - saveListeners.add(listener); - } - - - /** - * Adds a search listener to send events to. - * - * @param listener the listener to add - */ - public static void addSearchListener(SearchListener listener) - { - if (listener != null) - searchListeners.add(listener); - } - - - /** - * Adds a sorting listener to send events to. - * - * @param listener the listener to add - */ - public static void addSortingListener(SortingListener listener) - { - if (listener != null) - sortingListeners.add(listener); - } - - - /** - * Adds a navigation listener to send events to. - * - * @param listener the listener to add - */ - public static void addNavigationListener(NavigationListener listener) - { - if (listener != null) - navigationListeners.add(listener); - } - - - /** - * Switches the currently selected profile. - * - * @param profile the profile to switch to - */ - public static void switchToProfile(Profile profile) - { - prefs.put(PREFS_KEY_SELECTED_PROFILE, profile.getName()); - fireChangedToProfileEvent(profile); - } - - - /** - * Switches the currently selected game. - * - * @param game the game to switch to - */ - public static void switchToGame(Game game) - { - prefs.put(PREFS_KEY_SELECTED_GAME, game.getCaption()); - fireChangedToGameEvent(game); - } - - - /** - * Sets the currently selected entry in the SaveList. - * - * @param entry the selected entry - */ - public static void setSelectedEntry(SaveListEntry entry) - { - selectedEntry = entry; - fireEntrySelectedEvent(entry); - } - - - /** - * Returns the currently selected entry in the SaveList. - * - * @return the entry selected in the SaveList - */ - public static SaveListEntry getSelectedEntry() - { - return selectedEntry; - } - - - /** - * Returns the currently selected game. - * - * @return the game that is currently selected - */ - public static Game getSelectedGame() - { - String gameName = prefs.get(PREFS_KEY_SELECTED_GAME, ""); - Game[] games = Game.values(); - for (Game game : games) - { - if (game.getCaption().equals(gameName)) - { - return game; - } - } - return games.length > 0 ? games[0] : null; - } - - - /** - * Returns the currently selected profile. - * - * @return the profile that is currently selected - */ - public static Profile getSelectedProfile() - { - String profileName = prefs.get(PREFS_KEY_SELECTED_PROFILE, ""); - Game game = getSelectedGame(); - List profiles = game.getProfiles(); - for (Profile profile : profiles) - { - if (profile.getName().equals(profileName)) - return profile; - } - // if a profile with the saved name doesn't exist, return either the first existing one, or an empty one. - return profiles.size() > 0 ? profiles.get(0) : new Profile("", game); - } - - - /** - * Imports the given directories as profiles into the given game. - * - * @param files the files to import as profiles - * @param game the game the profiles will be imported into - */ - public static void importAsProfiles(File[] files, Game game) - { - if (files == null) - return; - for (File file : files) - { - try - { - if (!file.isDirectory()) - continue; - copyDirectory(file, new File(game.getDirectory() + File.separator + file.getName())); - } - catch (Exception e) - { - JOptionPane.showMessageDialog(mainWindow, "Error when trying to import the profiles!", "Error occured", - JOptionPane.ERROR_MESSAGE); - } - } - } - - - /** - * Imports a new savefile. If a parent is given, it will be imported into that folder. Otherwise the parent will be determined - * based on the selection in the save list. - * - * @param parentFolder the folder to import the savefile into - * @return the imported save - */ - public static Save importSavefile(Folder parentFolder) - { - SaveListEntry parent = getSelectedEntry(); - if (parent instanceof Save) - parent = parent.getParent(); - if (parentFolder != null) - parent = parentFolder; - if (parent == null) - parent = getSelectedProfile().getRoot(); - File saveFile = createFileForNewSave((Folder) parent); - if (saveFile == null) - return null; - Save newSave = new Save((Folder) parent, saveFile); - parent.addChild(newSave); - AbstractMessage.display(AbstractMessage.SUCCESSFUL_IMPORT); - fireEntryCreatedEvent(newSave); - return newSave; - } - - - /** - * Imports a new savefile and replaces an existing one in the list. - * - * @param saveToReplace the save to be replaced by the imported one - */ - public static void importAndReplaceSavefile(Save saveToReplace) - { - Folder parent = saveToReplace.getParent(); - String name = saveToReplace.getName(); - saveToReplace.delete(); - File saveFile = createFileForNewSave((Folder) parent); - if (saveFile == null) - return; - Save newSave = new Save(parent, saveFile); - newSave.rename(name); - parent.addChild(newSave); - fireEntryCreatedEvent(newSave); - AbstractMessage.display(AbstractMessage.SUCCESSFUL_REPLACE); - } - - - public static void createFolder(String name) - { - SaveListEntry parent = getSelectedEntry(); - if (parent == null) - parent = getSelectedProfile().getRoot(); - if (parent instanceof Save) - parent = parent.getParent(); - File dir = new File(parent.getFile().getPath() + File.separator + name); - if (dir.exists()) - { - JOptionPane.showMessageDialog(mainWindow, "This folder already exists!", "Error occured", JOptionPane.ERROR_MESSAGE); - return; - } - dir.mkdirs(); - Folder newFolder = new Folder((Folder) parent, dir); - parent.addChild(newFolder); - fireEntryCreatedEvent(newFolder); - } - - - /** - * Creates the File object and the actual file in the file system for a new save in the given parent folder. - * - * @param parent the parent of the new save - * @return the file object - */ - private static File createFileForNewSave(Folder parent) - { - if (getSelectedGame().getSaveFileLocation() == null) - { - JOptionPane.showMessageDialog(mainWindow, - "To import a savefile you need to set the savefile location in the profile configuration settings!", "Error occured", - JOptionPane.WARNING_MESSAGE); - return null; - } - String parentPath = parent != null ? parent.getFile().getPath() : getSelectedProfile().getRoot().getFile().getPath(); - String name = getSelectedGame().getSaveName(); - File newFile = new File(parentPath + File.separator + name); - for (int i = 0; newFile.exists(); i++) - newFile = new File(parentPath + File.separator + name + "_" + i); - try - { - Files.copy(getSelectedGame().getSaveFileLocation().toPath(), newFile.toPath(), StandardCopyOption.COPY_ATTRIBUTES); - } - catch (IOException e) - { - JOptionPane.showMessageDialog(mainWindow, "Error when trying to import the savefile!", "Error occured", - JOptionPane.ERROR_MESSAGE); - } - return newFile; - } - - - /** - * Loads the given save and overwrites the current gamefile. - * - * @param save the save to load - */ - public static void loadSave(Save save) - { - if (save == null) - return; - fireSaveLoadStartedEvent(save); - Game game = getSelectedGame(); - File gameFile = game.getSaveFileLocation(); - File saveFile = save.getFile(); - boolean canWriteSaveFile = saveFile.canWrite(); - try - { - gameFile.setWritable(true); - saveFile.setWritable(true); - Files.copy(saveFile.toPath(), gameFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - AbstractMessage.display(AbstractMessage.SUCCESSFUL_LOAD); - } - catch (Exception e) - { - JOptionPane.showMessageDialog(mainWindow, "Error when trying to load the savefile!", "Error occured", - JOptionPane.ERROR_MESSAGE); - } - gameFile.setWritable(canWriteSaveFile); - saveFile.setWritable(canWriteSaveFile); - fireSaveLoadFinishedEvent(save); - } - - - /** - * Opens the SpeedSouls webpage for the Save Organizer in the default browser. - */ - public static void openWebPage() - { - try - { - Desktop.getDesktop().browse(new URI(WEB_PAGE_URL)); - } - catch (Exception e) - { - JOptionPane.showMessageDialog(mainWindow, e.getMessage(), "Error occured", JOptionPane.ERROR_MESSAGE); - } - } - - - /** - * Opens the GitHub latest release page. - */ - public static void openLatestReleasePage() - { - try - { - Desktop.getDesktop().browse(new URI(LATEST_RELEASE_URL)); - } - catch (Exception e) - { - JOptionPane.showMessageDialog(mainWindow, e.getMessage(), "Error occured", JOptionPane.ERROR_MESSAGE); - } - } - - - /** - * Enables/disables global hotkeys. - * - * @param flag True to enable, false to disable - */ - public static void setGlobalHotkeysEnabled(boolean flag) - { - prefs.putBoolean(PREFS_KEY_SETTING_GLOBAL_HOTKEYS, flag); - keyboardHook.setHotkeysEnabled(flag); - } - - - /** - * Returns whether global hotkeys are enabled. - * - * @return whether global hotkeys are enabled - */ - public static boolean areGlobalHotkeysEnabled() - { - return keyboardHook.areHotkeysEnabled(); - } - - - /** - * Sets the main window to always be on top or not. - * - * @param flag True for the window to always be on top - */ - public static void setAlwaysOnTop(boolean flag) - { - prefs.putBoolean(PREFS_KEY_SETTING_ALWAYS_ON_TOP, flag); - mainWindow.setAlwaysOnTop(flag); - } - - - /** - * Returns whether the window should always be on top. - * - * @return whether the window should always be on top - */ - public static boolean isAlwaysOnTop() - { - return prefs.getBoolean(PREFS_KEY_SETTING_ALWAYS_ON_TOP, false); - } - - - /** - * Switches the gamefile of the currently selected game between read-only and writeable. - */ - public static void switchCurrentGameFileWritableState() - { - if (getSelectedGame().equals(Game.DARK_SOULS_REMASTERED)) - return; - File gameFile = getSelectedGame().getSaveFileLocation(); - gameFile.setWritable(!gameFile.canWrite()); - fireGameFileWritableStateChangedEvent(gameFile.canWrite()); - } - - - /** - * Navigates upwards in the savefile list - */ - public static void navigateToPrevious() - { - for(NavigationListener listener : navigationListeners) { - listener.navigatedToPrevious(); - } - } - - - /** - * Navigates downwards in the savefile list - */ - public static void navigateToNext() - { - for(NavigationListener listener : navigationListeners) { - listener.navigatedToNext(); - } - } - - - /** - * Returns the window size stored in the preferences. - * - * @return the window size as a Dimension object - */ - public static Dimension getStoredWindowSize() - { - int width = prefs.getInt(PREFS_KEY_WIN_WIDTH, -1); - int height = prefs.getInt(PREFS_KEY_WIN_HEIGHT, -1); - - return new Dimension(width, height); - } - - - /** - * Sets the window size variables stored in the preferences. - * - * @param size the size as a Dimension object - */ - public static void setStoredWindowSize(Dimension size) - { - prefs.putInt(PREFS_KEY_WIN_WIDTH, size.width); - prefs.putInt(PREFS_KEY_WIN_HEIGHT, size.height); - } - - - public static String getStoredHotkeyCode(GlobalHotkey hotkey) - { - return prefs.get(hotkey.getPrefsKey(), ""); - } - - - /** - * Stores the given code for the given hotkey in the preferences. - * - * @param hotkey the hotkey - * @param keyCode the new key code - */ - public static void setStoredHotkeyCode(GlobalHotkey hotkey, String keyCode) - { - prefs.put(hotkey.getPrefsKey(), keyCode); - } - - - public static SortingCategory getSelectedSortingCategory() - { - String caption = prefs.get(PREFS_KEY_SELECTED_SORTING, "ERROR"); - for (SortingCategory category : SortingCategory.values()) - { - if (category.getCaption().equals(caption)) - return category; - } - return SortingCategory.ALPHABET; - } - - - public static void setSelectedSortingCategory(SortingCategory category) - { - prefs.put(PREFS_KEY_SELECTED_SORTING, category.getCaption()); - fireSortingChangedEvent(category); - } - - - /** - * Returns the keyboard hook. - * - * @return the keyboard hook - */ - public static GlobalKeyboardHook getKeyboardHook() - { - return keyboardHook; - } - - - /** - * Sets the main window for the manager. - * - * @param window the main window - */ - public static void setMainWindow(OrganizerWindow window) - { - mainWindow = window; - } - - - /** - * @return the main window - */ - public static OrganizerWindow getMainWindow() - { - return mainWindow; - } - - - /** - * Fires a searchRequested event. - * - * @param input the search input - */ - public static void fireSearchRequestedEvent(String input) - { - for (SearchListener listener : searchListeners) - { - listener.searchRequested(input); - } - } - - - /** - * Fires a sortingChanged event. - * - * @param category the category that was changed to - */ - public static void fireSortingChangedEvent(SortingCategory category) - { - for (SortingListener listener : sortingListeners) - { - listener.sortingChanged(category); - } - } - - - /** - * Fires a profileDeleted event. - * - * @param profile the deleted profile - */ - public static void fireProfileDeletedEvent(Profile profile) - { - for (ProfileListener listener : profileListeners) - { - listener.profileDeleted(profile); - } - } - - - /** - * Fires a profileCreated event. - * - * @param profile the created profile - */ - public static void fireProfileCreatedEvent(Profile profile) - { - for (ProfileListener listener : profileListeners) - { - listener.profileCreated(profile); - } - } - - - /** - * Fires a profileDirectoryChanged event. - */ - public static void fireProfileDirectoryChangedEvent(Game game) - { - for (ProfileListener listener : profileListeners) - { - listener.profileDirectoryChanged(game); - } - } - - - /** - * Fires an entryCreated event. - * - * @param entry the entry that was created - */ - public static void fireEntryCreatedEvent(SaveListEntry entry) - { - for (SaveListener saveListener : saveListeners) - { - saveListener.entryCreated(entry); - } - } - - - /** - * Fires an entryRenamed event. - * - * @param entry the entry that was renamed - */ - public static void fireEntryRenamedEvent(SaveListEntry entry) - { - for (SaveListener saveListener : saveListeners) - { - saveListener.entryRenamed(entry); - } - } - - - /** - * Fires a changedToProfile event. - * - * @param profile the profile that was changed to - */ - public static void fireChangedToProfileEvent(Profile profile) - { - for (ProfileListener listener : profileListeners) - { - listener.changedToProfile(profile); - } - } - - - /** - * Fires a changedToGame event. - * - * @param game the game that was changed to - */ - public static void fireChangedToGameEvent(Game game) - { - for (ProfileListener listener : profileListeners) - { - listener.changedToGame(game); - } - } - - - /** - * Fires an entrySelected event. - * - * @param entry the entry that was selected - */ - public static void fireEntrySelectedEvent(SaveListEntry entry) - { - for (SaveListener listener : saveListeners) - { - listener.entrySelected(entry); - } - } - - - /** - * Fires a saveLoadStarted event. - * - * @param save the save that is loaded - */ - public static void fireSaveLoadStartedEvent(Save save) - { - for (SaveListener listener : saveListeners) - { - listener.saveLoadStarted(save); - } - } - - - /** - * Fires a saveLoadFinished event. - * - * @param save the save that was loaded - */ - public static void fireSaveLoadFinishedEvent(Save save) - { - for (SaveListener listener : saveListeners) - { - listener.saveLoadFinished(save); - } - } - - - /** - * Fires a gameFileWritableStateChanged event. - * - * @param save the save that was loaded - */ - public static void fireGameFileWritableStateChangedEvent(boolean writeable) - { - for (SaveListener listener : saveListeners) - { - listener.gameFileWritableStateChanged(writeable); - } - } - - - /** - * Checks whether the given file contains the given string in its name, and if not checks its subcontents for such a file if - * the given file is a directory. - * - * @param directory the file/directory to check - * @param name the name to check for - * @return whether a file containing the name was found or not - */ - public static boolean containsFileWithName(File directory, String name) - { - if (directory.exists()) - { - if (directory.getName().toLowerCase().contains(name.toLowerCase())) - return true; - File[] files = directory.listFiles(); - if (files != null) - { - for (int i = 0; i < files.length; i++) - { - if (files[i].getName().toLowerCase().contains(name.toLowerCase())) - return true; - else if (files[i].isDirectory()) - if (containsFileWithName(files[i], name)) - return true; - } - } - } - return false; - } - - - /** - * Copies the source directory and its contents into the destination directory. - * - * @param src the source directory - * @param dest the destination directory - * @throws IOException - */ - public static void copyDirectory(File src, File dest) throws IOException - { - if (src.isDirectory()) - { - if (!dest.exists()) - dest.mkdir(); - File[] files = src.listFiles(); - for (File file : files) - { - File srcFile = new File(src.getPath(), file.getName()); - File destFile = new File(dest.getPath(), file.getName()); - copyDirectory(srcFile, destFile); - } - return; - } - Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - - - /** - * Deletes the given directory and all of its sub folders, or simply deletes the given file if its not a directory. - * - * @param directory the directory to delete - * @return whether the deletion was successful or not - */ - public static boolean deleteDirectory(File directory) - { - if (directory.exists()) - { - File[] files = directory.listFiles(); - if (files != null) - { - for (int i = 0; i < files.length; i++) - { - if (files[i].isDirectory()) - { - deleteDirectory(files[i]); - } - else - { - files[i].delete(); - } - } - } - } - return (directory.delete()); - } - - - /** - * Checks the given string for illegal characters. - * - * @param toExamine the string to examine - * @return true if the string contains illegal characters. False otherwise. - */ - public static boolean containsIllegals(String toExamine) - { - String[] arr = toExamine.split(ILLEGAL_CHARACTERS_REGEX, 2); - return arr.length > 1; - } - - - /** - * Checks whether the local Save Organizer version is outdated compared to the latest GitHub release. - * - * @return whether the local version is outdated - */ - public static boolean isVersionOutdated() - { - String[] vals1 = VERSION.split("\\."); - String[] vals2 = getLatestReleaseVersion().split("\\."); - int i = 0; - // set index to first non-equal ordinal or length of shortest version string - while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) - { - i++; - } - // compare first non-equal ordinal number - if (i < vals1.length && i < vals2.length) - { - int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); - return Integer.signum(diff) == -1; - } - // the strings are equal or one string is a substring of the other - // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" - return Integer.signum(vals1.length - vals2.length) == -1; - } - - - /** - * Checks the latest release version on GitHub and returns it. - * - * @return the latest release version on GitHub - */ - public static String getLatestReleaseVersion() - { - JSONObject latestReleaseJSON = getLatestReleaseJSON(); - if (latestReleaseJSON != null) - return latestReleaseJSON.getString("tag_name").substring(2); - return "0.0"; - } - - - /** - * Retrieves the description of the latest release from GitHub. - * - * @return the latest release description - */ - public static String getLatestReleaseDescription() - { - JSONObject latestReleaseJSON = getLatestReleaseJSON(); - if (latestReleaseJSON != null) - return latestReleaseJSON.getString("body"); - return ""; - } - - - /** - * Builds the download URL based on the latest release version. - * - * @return the download URL for the latest release - */ - public static String getLatestReleaseDownloadURL() - { - String latestVersion = getLatestReleaseVersion(); - return "https://github.com/Kahmul/SpeedSouls-Save-Organizer/releases/download/v." + latestVersion + "SpeedSouls.-.Save.Organizer." - + latestVersion + ".zip"; - } - - - /** - * Creates a JSONObject of the latest release on GitHub. - * - * @return the JSONObject of the latest release - */ - private static JSONObject getLatestReleaseJSON() - { - try (InputStream is = new URL(LATEST_RELEASE_JSON_URL).openStream()) - { - BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); - String jsonText = readAll(rd); - JSONObject json = new JSONObject(jsonText); - return json; - } - catch (Exception e) - { - } - return null; - } - - - /** - * Reads all the input from a Reader and returns it in a single String. - * - * @param rd the reader - * @return the input - * @throws IOException - */ - private static String readAll(Reader rd) throws IOException - { - StringBuilder sb = new StringBuilder(); - int cp; - while ((cp = rd.read()) != -1) - { - sb.append((char) cp); - } - return sb.toString(); - } - -} +package com.speedsouls.organizer.data; + + +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.Image; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.imageio.ImageIO; +import javax.swing.JOptionPane; + +import org.jnativehook.NativeHookException; +import org.json.JSONObject; + +import com.speedsouls.organizer.games.Game; +import com.speedsouls.organizer.hotkeys.GlobalHotkey; +import com.speedsouls.organizer.hotkeys.GlobalKeyboardHook; +import com.speedsouls.organizer.listeners.NavigationListener; +import com.speedsouls.organizer.listeners.ProfileListener; +import com.speedsouls.organizer.listeners.SaveListener; +import com.speedsouls.organizer.listeners.SearchListener; +import com.speedsouls.organizer.listeners.SortingListener; +import com.speedsouls.organizer.main.OrganizerWindow; +import com.speedsouls.organizer.messages.AbstractMessage; +import com.speedsouls.organizer.profileconfig.Profile; +import com.speedsouls.organizer.savelist.Folder; +import com.speedsouls.organizer.savelist.Save; +import com.speedsouls.organizer.savelist.SaveListEntry; +import com.speedsouls.organizer.savelist.SortingCategory; + +import jiconfont.icons.Elusive; +import jiconfont.icons.Entypo; +import jiconfont.icons.FontAwesome; +import jiconfont.icons.Iconic; +import jiconfont.icons.Typicons; +import jiconfont.swing.IconFontSwing; + + +/** + * OrganizerManager. + *

+ * Manages storing and retrieving of the used data (e.g. profiles, saves, images). Handles listener events for profiles, saves and + * games. Offers utility methods. + * + * @author Kahmul (www.twitch.tv/kahmul78) + * @date 27 Sep 2015 + */ +public class OrganizerManager +{ + + public static final String VERSION = "1.4.2"; + + /** + * Constants defining various URLs. + */ + public static final String WEB_PAGE_URL = "www.speedsouls.com/SpeedSouls_-_Save_Organizer"; + public static final String GITHUB_REPO_URL = "www.github.com/Kahmul/SpeedSouls-Save-Organizer"; + public static final String TWITTER_URL = "www.twitter.com/Kahmul78"; + public static final String LATEST_RELEASE_JSON_URL = "https://api.github.com/repos/Kahmul/SpeedSouls-Save-Organizer/releases/latest"; + public static final String LATEST_RELEASE_URL = "https://github.com/Kahmul/SpeedSouls-Save-Organizer/releases"; + + /** + * Constants for paths to preferences and resources. + */ + private static final String RESOURCE_PATH = "/com/speedsouls/organizer/resources/"; + private static final String PREFERENCES_PATH = "/com/speedsouls/organizer/prefs"; + + /** + * Constants for the keys used to access preferences. + */ + private static final String PREFS_KEY_INITIAL_STARTUP = "initStartup"; + private static final String PREFS_KEY_VERSION = "Version"; + + private static final String PREFS_KEY_WIN_WIDTH = "WindowWidth"; + private static final String PREFS_KEY_WIN_HEIGHT = "WindowHeight"; + + private static final String PREFS_KEY_SELECTED_GAME = "selectedGame"; + private static final String PREFS_KEY_SELECTED_PROFILE = "selectedProfile"; + private static final String PREFS_KEY_SELECTED_SORTING = "selectedSorting"; + + private static final String PREFS_KEY_SETTING_ALWAYS_ON_TOP = "alwaysOnTop"; + private static final String PREFS_KEY_SETTING_GLOBAL_HOTKEYS = "globalHotkeys"; + + public static final String PREFS_KEY_GLOBAL_HOTKEY_LOAD = "hotkeyLoad"; + public static final String PREFS_KEY_GLOBAL_HOTKEY_READ_ONLY = "hotkeyReadOnly"; + public static final String PREFS_KEY_GLOBAL_HOTKEY_PREV_SAVE = "hotkeyPrevSave"; + public static final String PREFS_KEY_GLOBAL_HOTKEY_NEXT_SAVE = "hotkeyNextSave"; + public static final String PREFS_KEY_GLOBAL_HOTKEY_TOGGLE = "hotkeyToggle"; + + public static final String PREFS_MODIFIER_GAME_DIR = "Path"; + public static final String PREFS_MODIFIER_GAME_SAVEFILE = "Savefile"; + + public static final String PREFS_ERROR_ON_RETRIEVE = "ERROR"; + + public static final String ILLEGAL_CHARACTERS = "~, @, *, {, }, <, >, [, ], |, \u201C, \u201D, \\, /, ^"; + private static final String ILLEGAL_CHARACTERS_REGEX = "[~#@*{}<>\\[\\]|\"\\^\\\\\\/]"; + + private static Preferences prefs; + + private static GlobalKeyboardHook keyboardHook; + + public static Image speedsoulsIcon; + public static Image speedsoulsIconMedium; + public static Image readOnlyIconMedium; + public static Image readOnlyIconSmall; + public static Image settingsIcon; + + private static List profileListeners; + private static List saveListeners; + private static List searchListeners; + private static List sortingListeners; + private static List navigationListeners; + + private static SaveListEntry selectedEntry; + + private static OrganizerWindow mainWindow; + + private static boolean isReady; + + static + { + try + { + initialize(); + } + catch (IOException e) + { + JOptionPane.showMessageDialog(null, "Error when trying to initialize the data. Could not start the Save Organizer.", + "Error occured", JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + } + + + /** + * Initializes the data. Required to be called before using any other methods of this class. + * + * @throws IOException + */ + private static void initialize() throws IOException + { + importImages(); + initListeners(); + initPreferenceData(); + initKeyboardHook(); + mapGamesWithProfiles(); + + isReady = true; + } + + + /** + * Imports all the images and icons used in the program. + * + * @throws IOException + */ + private static void importImages() throws IOException + { + speedsoulsIcon = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SpeedSoulsFlameSmall.png")); + speedsoulsIconMedium = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SpeedSoulsFlameSmall.png")); + readOnlyIconSmall = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "ReadOnlyIconSmall.png")); + readOnlyIconMedium = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "ReadOnlyIconMedium.png")); + settingsIcon = ImageIO.read(OrganizerManager.class.getResourceAsStream(RESOURCE_PATH + "SettingsIcon.png")); + + IconFontSwing.register(FontAwesome.getIconFont()); + IconFontSwing.register(Elusive.getIconFont()); + IconFontSwing.register(Entypo.getIconFont()); + IconFontSwing.register(Iconic.getIconFont()); + IconFontSwing.register(Typicons.getIconFont()); + } + + + /** + * Inits the listener lists. + */ + private static void initListeners() + { + profileListeners = new ArrayList<>(); + saveListeners = new ArrayList<>(); + searchListeners = new ArrayList<>(); + sortingListeners = new ArrayList<>(); + navigationListeners = new ArrayList<>(); + } + + + /** + * Inits the preferences. + */ + private static void initPreferenceData() + { + prefs = Preferences.userRoot().node(PREFERENCES_PATH); + prefs.put(PREFS_KEY_VERSION, VERSION); + + // reset global hotkeys if this is the first time the organizer is started to avoid incompatibility with older versions + boolean initStartup = prefs.getBoolean(PREFS_KEY_INITIAL_STARTUP, true); + if (initStartup) + { + prefs.remove(PREFS_KEY_SETTING_GLOBAL_HOTKEYS); + prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_LOAD); + prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_READ_ONLY); + prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_PREV_SAVE); + prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_NEXT_SAVE); + prefs.remove(PREFS_KEY_GLOBAL_HOTKEY_TOGGLE); + + prefs.putBoolean(PREFS_KEY_INITIAL_STARTUP, false); + } + } + + + /** + * Inits the global hotkey hook. + */ + private static void initKeyboardHook() + { + try + { + keyboardHook = new GlobalKeyboardHook(); + keyboardHook.setHotkeysEnabled(prefs.getBoolean(PREFS_KEY_SETTING_GLOBAL_HOTKEYS, false)); + } + catch (NativeHookException e) + { + JOptionPane.showMessageDialog(mainWindow, "Error when trying to establish the keyboard hook. Global hotkeys will be disabled.", + "Error occured", JOptionPane.ERROR_MESSAGE); + keyboardHook.setHotkeysEnabled(false); + } + } + + + /** + * Maps all the existing games with their profiles. + */ + private static void mapGamesWithProfiles() + { + if (prefs == null) + return; + Game[] games = Game.values(); + for (Game game : games) + importProfiles(game); + } + + + /** + * Searches for all the profiles of the given game. + * + * @param game the game to import the profiles for + */ + private static void importProfiles(Game game) + { + String gameDirectoryPath = prefs.get(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR, PREFS_ERROR_ON_RETRIEVE); + if (PREFS_ERROR_ON_RETRIEVE.equals(gameDirectoryPath)) + return; + File gameDirectory = new File(gameDirectoryPath); + if (!gameDirectory.exists()) + { + prefs.remove(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR); + return; + } + game.setDirectory(gameDirectory); + String saveLocationPath = prefs.get(game.getAbbreviation() + PREFS_MODIFIER_GAME_SAVEFILE, PREFS_ERROR_ON_RETRIEVE); + if (!PREFS_ERROR_ON_RETRIEVE.equals(saveLocationPath)) + { + game.setSaveFileLocation(new File(saveLocationPath)); + return; + } + // If the user used an old version, then a savefile location might not have been explicitly specified. + // In that case, use the profile directory + saveName as the savefile location + File defaultSaveFileLocation = new File(gameDirectoryPath + File.separator + game.getSaveName()); + if (defaultSaveFileLocation.exists()) + game.setSaveFileLocation(defaultSaveFileLocation); + } + + + public static boolean isApplicationReady() + { + return isReady; + } + + + /** + * Refreshes all profiles and games. + */ + public static void refreshProfiles() + { + mapGamesWithProfiles(); + } + + + /** + * Saves the properties of this game to the preferences. + * + * @param game the game to update + */ + public static void saveProperties(Game game) + { + prefs.put(game.getAbbreviation() + PREFS_MODIFIER_GAME_DIR, game.getDirectory().getPath()); + prefs.put(game.getAbbreviation() + PREFS_MODIFIER_GAME_SAVEFILE, game.getSaveFileLocation().getPath()); + importProfiles(game); + } + + + /** + * Adds a profile listener to send events to. + * + * @param listener the listener to add + */ + public static void addProfileListener(ProfileListener listener) + { + if (listener != null) + profileListeners.add(listener); + } + + + /** + * Adds a save listener to send events to. + * + * @param listener the listener to add + */ + public static void addSaveListener(SaveListener listener) + { + if (listener != null) + saveListeners.add(listener); + } + + + /** + * Adds a search listener to send events to. + * + * @param listener the listener to add + */ + public static void addSearchListener(SearchListener listener) + { + if (listener != null) + searchListeners.add(listener); + } + + + /** + * Adds a sorting listener to send events to. + * + * @param listener the listener to add + */ + public static void addSortingListener(SortingListener listener) + { + if (listener != null) + sortingListeners.add(listener); + } + + + /** + * Adds a navigation listener to send events to. + * + * @param listener the listener to add + */ + public static void addNavigationListener(NavigationListener listener) + { + if (listener != null) + navigationListeners.add(listener); + } + + + /** + * Switches the currently selected profile. + * + * @param profile the profile to switch to + */ + public static void switchToProfile(Profile profile) + { + prefs.put(PREFS_KEY_SELECTED_PROFILE, profile.getName()); + fireChangedToProfileEvent(profile); + } + + + /** + * Switches the currently selected game. + * + * @param game the game to switch to + */ + public static void switchToGame(Game game) + { + prefs.put(PREFS_KEY_SELECTED_GAME, game.getCaption()); + fireChangedToGameEvent(game); + } + + + /** + * Sets the currently selected entry in the SaveList. + * + * @param entry the selected entry + */ + public static void setSelectedEntry(SaveListEntry entry) + { + selectedEntry = entry; + fireEntrySelectedEvent(entry); + } + + + /** + * Returns the currently selected entry in the SaveList. + * + * @return the entry selected in the SaveList + */ + public static SaveListEntry getSelectedEntry() + { + return selectedEntry; + } + + + /** + * Returns the currently selected game. + * + * @return the game that is currently selected + */ + public static Game getSelectedGame() + { + String gameName = prefs.get(PREFS_KEY_SELECTED_GAME, ""); + Game[] games = Game.values(); + for (Game game : games) + { + if (game.getCaption().equals(gameName)) + { + return game; + } + } + return games.length > 0 ? games[0] : null; + } + + + /** + * Returns the currently selected profile. + * + * @return the profile that is currently selected + */ + public static Profile getSelectedProfile() + { + String profileName = prefs.get(PREFS_KEY_SELECTED_PROFILE, ""); + Game game = getSelectedGame(); + List profiles = game.getProfiles(); + for (Profile profile : profiles) + { + if (profile.getName().equals(profileName)) + return profile; + } + // if a profile with the saved name doesn't exist, return either the first existing one, or an empty one. + return profiles.size() > 0 ? profiles.get(0) : new Profile("", game); + } + + + /** + * Imports the given directories as profiles into the given game. + * + * @param files the files to import as profiles + * @param game the game the profiles will be imported into + */ + public static void importAsProfiles(File[] files, Game game) + { + if (files == null) + return; + for (File file : files) + { + try + { + if (!file.isDirectory()) + continue; + copyDirectory(file, new File(game.getDirectory() + File.separator + file.getName())); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(mainWindow, "Error when trying to import the profiles!", "Error occured", + JOptionPane.ERROR_MESSAGE); + } + } + } + + + /** + * Imports a new savefile. If a parent is given, it will be imported into that folder. Otherwise the parent will be determined + * based on the selection in the save list. + * + * @param parentFolder the folder to import the savefile into + * @return the imported save + */ + public static Save importSavefile(Folder parentFolder) + { + SaveListEntry parent = getSelectedEntry(); + if (parent instanceof Save) + parent = parent.getParent(); + if (parentFolder != null) + parent = parentFolder; + if (parent == null) + parent = getSelectedProfile().getRoot(); + File saveFile = createFileForNewSave((Folder) parent); + if (saveFile == null) + return null; + Save newSave = new Save((Folder) parent, saveFile); + parent.addChild(newSave); + AbstractMessage.display(AbstractMessage.SUCCESSFUL_IMPORT); + fireEntryCreatedEvent(newSave); + return newSave; + } + + + /** + * Imports a new savefile and replaces an existing one in the list. + * + * @param saveToReplace the save to be replaced by the imported one + */ + public static void importAndReplaceSavefile(Save saveToReplace) + { + Folder parent = saveToReplace.getParent(); + String name = saveToReplace.getName(); + saveToReplace.delete(); + File saveFile = createFileForNewSave((Folder) parent); + if (saveFile == null) + return; + Save newSave = new Save(parent, saveFile); + newSave.rename(name); + parent.addChild(newSave); + fireEntryCreatedEvent(newSave); + AbstractMessage.display(AbstractMessage.SUCCESSFUL_REPLACE); + } + + + public static void createFolder(String name) + { + SaveListEntry parent = getSelectedEntry(); + if (parent == null) + parent = getSelectedProfile().getRoot(); + if (parent instanceof Save) + parent = parent.getParent(); + File dir = new File(parent.getFile().getPath() + File.separator + name); + if (dir.exists()) + { + JOptionPane.showMessageDialog(mainWindow, "This folder already exists!", "Error occured", JOptionPane.ERROR_MESSAGE); + return; + } + dir.mkdirs(); + Folder newFolder = new Folder((Folder) parent, dir); + parent.addChild(newFolder); + fireEntryCreatedEvent(newFolder); + } + + + /** + * Creates the File object and the actual file in the file system for a new save in the given parent folder. + * + * @param parent the parent of the new save + * @return the file object + */ + private static File createFileForNewSave(Folder parent) + { + if (getSelectedGame().getSaveFileLocation() == null) + { + JOptionPane.showMessageDialog(mainWindow, + "To import a savefile you need to set the savefile location in the profile configuration settings!", "Error occured", + JOptionPane.WARNING_MESSAGE); + return null; + } + String parentPath = parent != null ? parent.getFile().getPath() : getSelectedProfile().getRoot().getFile().getPath(); + String name = getSelectedGame().getSaveName(); + File newFile = new File(parentPath + File.separator + name); + for (int i = 0; newFile.exists(); i++) + newFile = new File(parentPath + File.separator + name + "_" + i); + try + { + Files.copy(getSelectedGame().getSaveFileLocation().toPath(), newFile.toPath(), StandardCopyOption.COPY_ATTRIBUTES); + } + catch (IOException e) + { + JOptionPane.showMessageDialog(mainWindow, "Error when trying to import the savefile!", "Error occured", + JOptionPane.ERROR_MESSAGE); + } + return newFile; + } + + + /** + * Loads the given save and overwrites the current gamefile. + * + * @param save the save to load + */ + public static void loadSave(Save save) + { + if (save == null) + return; + fireSaveLoadStartedEvent(save); + Game game = getSelectedGame(); + File gameFile = game.getSaveFileLocation(); + File saveFile = save.getFile(); + boolean canWriteSaveFile = saveFile.canWrite(); + try + { + gameFile.setWritable(true); + saveFile.setWritable(true); + Files.copy(saveFile.toPath(), gameFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + AbstractMessage.display(AbstractMessage.SUCCESSFUL_LOAD); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(mainWindow, "Error when trying to load the savefile!", "Error occured", + JOptionPane.ERROR_MESSAGE); + } + gameFile.setWritable(canWriteSaveFile); + saveFile.setWritable(canWriteSaveFile); + fireSaveLoadFinishedEvent(save); + } + + + /** + * Opens the SpeedSouls webpage for the Save Organizer in the default browser. + */ + public static void openWebPage() + { + try + { + Desktop.getDesktop().browse(new URI(WEB_PAGE_URL)); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(mainWindow, e.getMessage(), "Error occured", JOptionPane.ERROR_MESSAGE); + } + } + + + /** + * Opens the GitHub latest release page. + */ + public static void openLatestReleasePage() + { + try + { + Desktop.getDesktop().browse(new URI(LATEST_RELEASE_URL)); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(mainWindow, e.getMessage(), "Error occured", JOptionPane.ERROR_MESSAGE); + } + } + + + /** + * Enables/disables global hotkeys. + * + * @param flag True to enable, false to disable + */ + public static void setGlobalHotkeysEnabled(boolean flag) + { + prefs.putBoolean(PREFS_KEY_SETTING_GLOBAL_HOTKEYS, flag); + keyboardHook.setHotkeysEnabled(flag); + } + + + /** + * Returns whether global hotkeys are enabled. + * + * @return whether global hotkeys are enabled + */ + public static boolean areGlobalHotkeysEnabled() + { + return keyboardHook.areHotkeysEnabled(); + } + + + /** + * Sets the main window to always be on top or not. + * + * @param flag True for the window to always be on top + */ + public static void setAlwaysOnTop(boolean flag) + { + prefs.putBoolean(PREFS_KEY_SETTING_ALWAYS_ON_TOP, flag); + mainWindow.setAlwaysOnTop(flag); + } + + + /** + * Returns whether the window should always be on top. + * + * @return whether the window should always be on top + */ + public static boolean isAlwaysOnTop() + { + return prefs.getBoolean(PREFS_KEY_SETTING_ALWAYS_ON_TOP, false); + } + + + /** + * Switches the gamefile of the currently selected game between read-only and writeable. + */ + public static void switchCurrentGameFileWritableState() + { + if (getSelectedGame().equals(Game.DARK_SOULS_REMASTERED)) + return; + File gameFile = getSelectedGame().getSaveFileLocation(); + gameFile.setWritable(!gameFile.canWrite()); + fireGameFileWritableStateChangedEvent(gameFile.canWrite()); + } + + + /** + * Navigates upwards in the savefile list + */ + public static void navigateToPrevious() + { + for(NavigationListener listener : navigationListeners) { + listener.navigatedToPrevious(); + } + } + + + /** + * Navigates downwards in the savefile list + */ + public static void navigateToNext() + { + for(NavigationListener listener : navigationListeners) { + listener.navigatedToNext(); + } + } + + + /** + * Returns the window size stored in the preferences. + * + * @return the window size as a Dimension object + */ + public static Dimension getStoredWindowSize() + { + int width = prefs.getInt(PREFS_KEY_WIN_WIDTH, -1); + int height = prefs.getInt(PREFS_KEY_WIN_HEIGHT, -1); + + return new Dimension(width, height); + } + + + /** + * Sets the window size variables stored in the preferences. + * + * @param size the size as a Dimension object + */ + public static void setStoredWindowSize(Dimension size) + { + prefs.putInt(PREFS_KEY_WIN_WIDTH, size.width); + prefs.putInt(PREFS_KEY_WIN_HEIGHT, size.height); + } + + + public static String getStoredHotkeyCode(GlobalHotkey hotkey) + { + return prefs.get(hotkey.getPrefsKey(), ""); + } + + + /** + * Stores the given code for the given hotkey in the preferences. + * + * @param hotkey the hotkey + * @param keyCode the new key code + */ + public static void setStoredHotkeyCode(GlobalHotkey hotkey, String keyCode) + { + prefs.put(hotkey.getPrefsKey(), keyCode); + } + + + public static SortingCategory getSelectedSortingCategory() + { + String caption = prefs.get(PREFS_KEY_SELECTED_SORTING, "ERROR"); + for (SortingCategory category : SortingCategory.values()) + { + if (category.getCaption().equals(caption)) + return category; + } + return SortingCategory.ALPHABET; + } + + + public static void setSelectedSortingCategory(SortingCategory category) + { + prefs.put(PREFS_KEY_SELECTED_SORTING, category.getCaption()); + fireSortingChangedEvent(category); + } + + + /** + * Returns the keyboard hook. + * + * @return the keyboard hook + */ + public static GlobalKeyboardHook getKeyboardHook() + { + return keyboardHook; + } + + + /** + * Sets the main window for the manager. + * + * @param window the main window + */ + public static void setMainWindow(OrganizerWindow window) + { + mainWindow = window; + } + + + /** + * @return the main window + */ + public static OrganizerWindow getMainWindow() + { + return mainWindow; + } + + + /** + * Fires a searchRequested event. + * + * @param input the search input + */ + public static void fireSearchRequestedEvent(String input) + { + for (SearchListener listener : searchListeners) + { + listener.searchRequested(input); + } + } + + + /** + * Fires a sortingChanged event. + * + * @param category the category that was changed to + */ + public static void fireSortingChangedEvent(SortingCategory category) + { + for (SortingListener listener : sortingListeners) + { + listener.sortingChanged(category); + } + } + + + /** + * Fires a profileDeleted event. + * + * @param profile the deleted profile + */ + public static void fireProfileDeletedEvent(Profile profile) + { + for (ProfileListener listener : profileListeners) + { + listener.profileDeleted(profile); + } + } + + + /** + * Fires a profileCreated event. + * + * @param profile the created profile + */ + public static void fireProfileCreatedEvent(Profile profile) + { + for (ProfileListener listener : profileListeners) + { + listener.profileCreated(profile); + } + } + + + /** + * Fires a profileDirectoryChanged event. + */ + public static void fireProfileDirectoryChangedEvent(Game game) + { + for (ProfileListener listener : profileListeners) + { + listener.profileDirectoryChanged(game); + } + } + + + /** + * Fires an entryCreated event. + * + * @param entry the entry that was created + */ + public static void fireEntryCreatedEvent(SaveListEntry entry) + { + for (SaveListener saveListener : saveListeners) + { + saveListener.entryCreated(entry); + } + } + + + /** + * Fires an entryRenamed event. + * + * @param entry the entry that was renamed + */ + public static void fireEntryRenamedEvent(SaveListEntry entry) + { + for (SaveListener saveListener : saveListeners) + { + saveListener.entryRenamed(entry); + } + } + + + /** + * Fires a changedToProfile event. + * + * @param profile the profile that was changed to + */ + public static void fireChangedToProfileEvent(Profile profile) + { + for (ProfileListener listener : profileListeners) + { + listener.changedToProfile(profile); + } + } + + + /** + * Fires a changedToGame event. + * + * @param game the game that was changed to + */ + public static void fireChangedToGameEvent(Game game) + { + for (ProfileListener listener : profileListeners) + { + listener.changedToGame(game); + } + } + + + /** + * Fires an entrySelected event. + * + * @param entry the entry that was selected + */ + public static void fireEntrySelectedEvent(SaveListEntry entry) + { + for (SaveListener listener : saveListeners) + { + listener.entrySelected(entry); + } + } + + + /** + * Fires a saveLoadStarted event. + * + * @param save the save that is loaded + */ + public static void fireSaveLoadStartedEvent(Save save) + { + for (SaveListener listener : saveListeners) + { + listener.saveLoadStarted(save); + } + } + + + /** + * Fires a saveLoadFinished event. + * + * @param save the save that was loaded + */ + public static void fireSaveLoadFinishedEvent(Save save) + { + for (SaveListener listener : saveListeners) + { + listener.saveLoadFinished(save); + } + } + + + /** + * Fires a gameFileWritableStateChanged event. + * + * @param save the save that was loaded + */ + public static void fireGameFileWritableStateChangedEvent(boolean writeable) + { + for (SaveListener listener : saveListeners) + { + listener.gameFileWritableStateChanged(writeable); + } + } + + + /** + * Checks whether the given file contains the given string in its name, and if not checks its subcontents for such a file if + * the given file is a directory. + * + * @param directory the file/directory to check + * @param name the name to check for + * @return whether a file containing the name was found or not + */ + public static boolean containsFileWithName(File directory, String name) + { + if (directory.exists()) + { + if (directory.getName().toLowerCase().contains(name.toLowerCase())) + return true; + File[] files = directory.listFiles(); + if (files != null) + { + for (int i = 0; i < files.length; i++) + { + if (files[i].getName().toLowerCase().contains(name.toLowerCase())) + return true; + else if (files[i].isDirectory()) + if (containsFileWithName(files[i], name)) + return true; + } + } + } + return false; + } + + + /** + * Copies the source directory and its contents into the destination directory. + * + * @param src the source directory + * @param dest the destination directory + * @throws IOException + */ + public static void copyDirectory(File src, File dest) throws IOException + { + if (src.isDirectory()) + { + if (!dest.exists()) + dest.mkdir(); + File[] files = src.listFiles(); + for (File file : files) + { + File srcFile = new File(src.getPath(), file.getName()); + File destFile = new File(dest.getPath(), file.getName()); + copyDirectory(srcFile, destFile); + } + return; + } + Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + + /** + * Deletes the given directory and all of its sub folders, or simply deletes the given file if its not a directory. + * + * @param directory the directory to delete + * @return whether the deletion was successful or not + */ + public static boolean deleteDirectory(File directory) + { + if (directory.exists()) + { + File[] files = directory.listFiles(); + if (files != null) + { + for (int i = 0; i < files.length; i++) + { + if (files[i].isDirectory()) + { + deleteDirectory(files[i]); + } + else + { + files[i].delete(); + } + } + } + } + return (directory.delete()); + } + + + /** + * Checks the given string for illegal characters. + * + * @param toExamine the string to examine + * @return true if the string contains illegal characters. False otherwise. + */ + public static boolean containsIllegals(String toExamine) + { + String[] arr = toExamine.split(ILLEGAL_CHARACTERS_REGEX, 2); + return arr.length > 1; + } + + + /** + * Checks whether the local Save Organizer version is outdated compared to the latest GitHub release. + * + * @return whether the local version is outdated + */ + public static boolean isVersionOutdated() + { + String[] vals1 = VERSION.split("\\."); + String[] vals2 = getLatestReleaseVersion().split("\\."); + int i = 0; + // set index to first non-equal ordinal or length of shortest version string + while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) + { + i++; + } + // compare first non-equal ordinal number + if (i < vals1.length && i < vals2.length) + { + int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); + return Integer.signum(diff) == -1; + } + // the strings are equal or one string is a substring of the other + // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" + return Integer.signum(vals1.length - vals2.length) == -1; + } + + + /** + * Checks the latest release version on GitHub and returns it. + * + * @return the latest release version on GitHub + */ + public static String getLatestReleaseVersion() + { + JSONObject latestReleaseJSON = getLatestReleaseJSON(); + if (latestReleaseJSON != null) + return latestReleaseJSON.getString("tag_name").substring(2); + return "0.0"; + } + + + /** + * Retrieves the description of the latest release from GitHub. + * + * @return the latest release description + */ + public static String getLatestReleaseDescription() + { + JSONObject latestReleaseJSON = getLatestReleaseJSON(); + if (latestReleaseJSON != null) + return latestReleaseJSON.getString("body"); + return ""; + } + + + /** + * Builds the download URL based on the latest release version. + * + * @return the download URL for the latest release + */ + public static String getLatestReleaseDownloadURL() + { + String latestVersion = getLatestReleaseVersion(); + return "https://github.com/Kahmul/SpeedSouls-Save-Organizer/releases/download/v." + latestVersion + "SpeedSouls.-.Save.Organizer." + + latestVersion + ".zip"; + } + + + /** + * Creates a JSONObject of the latest release on GitHub. + * + * @return the JSONObject of the latest release + */ + private static JSONObject getLatestReleaseJSON() + { + try (InputStream is = new URL(LATEST_RELEASE_JSON_URL).openStream()) + { + BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); + String jsonText = readAll(rd); + JSONObject json = new JSONObject(jsonText); + return json; + } + catch (Exception e) + { + } + return null; + } + + + /** + * Reads all the input from a Reader and returns it in a single String. + * + * @param rd the reader + * @return the input + * @throws IOException + */ + private static String readAll(Reader rd) throws IOException + { + StringBuilder sb = new StringBuilder(); + int cp; + while ((cp = rd.read()) != -1) + { + sb.append((char) cp); + } + return sb.toString(); + } + +} From bef846e4128f0e5adc56d80ce2fa5b2dd7a7af6d Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 23:02:19 +0300 Subject: [PATCH 20/36] Remove travis --- .travis.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 984db6b..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -os: windows -language: shell - -install: -- choco install openjdk11 -y -- choco install maven -y - -script: -- mvn package - -notifications: - email: false - -deploy: - - provider: releases - api_key: - secure: fYIKgl8EvLBYTG8ovd5P9LZVZIR/m3MnYMIPYQtoxYfiPeCTDzJxtGj+gRf5VbX9BgImvr3pWArOT09SCndjBlB63df4szGeuGXPTZMZzKPeaxZhyGo/OTMI2WiMoicrrkt3O024oWr719HL1Hd8Wa9FrV8isRS+bCy2WrTLa8PsclBsPy2onahrK8aAU3hvO0IogPpQz2mxgQ/KuZHdf0N7Xv0E2Qf9zyBFOZoJ5XSff8d3dJMofng7NoUsc8pFdCJmFuA+VlP61677R2OCNu2S4anoOX8g6PNHPD9SR/Itm8uQM7/Vcp4xo9Hn22h6D+kXVcJ0PaeKGctIC7JTNYrOziSORvyC8vHeUDt0u0s2WdOfju+76WN640Tz2EMLsuyIWDG7kyvTYdSUCp6ibQQLBXcZIpuVPfyd8dKjAkoItiuBKCIoN78CZfxRUs6fDFmxT73W6vCHOK+nsUVQseL2cCnn1MR9nGjTdQzXkRqCg/X6A1G8Qnmts9M1rg6kCTDoUo9dTAY2kDJ1wcXWjD28BKpxX16ya5NnMifkt6CGrS9zr+6VI0MgLdpsAj7W8AoVcCvquuaby0vpI/nGWo72hvrz/DDkp6m6MAWP2p+zNUaydouKSiGchs/QAEBrxGR53mWTZM2RqCxo+ycFQ7ofNZyy16IEc+e1twQol4o= - file_glob: true - file: - - $TRAVIS_BUILD_DIR/target/SaveOrganizer.exe - skip_cleanup: true - on: - tags: true - branch: master \ No newline at end of file From b1688df33990ce148fe7152acb35c5ef9931a2a8 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 23:03:30 +0300 Subject: [PATCH 21/36] Update maven-pr.yml --- .github/workflows/maven-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index 6f6741c..5c844b1 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -1,7 +1,7 @@ # This workflow will build a Java project with Maven # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: [Maven] Pull Request build and merge +name: Maven Pull Request build and merge on: pull_request: From 91ea78284d44195de40a7674a2b4c6e3ed8aaefc Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 23:03:43 +0300 Subject: [PATCH 22/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index dd8c0f8..c52e7b2 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -1,7 +1,7 @@ # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created # For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path -name: [Maven] Package Release +name: Maven Package Release on: push: From 528c8dfadacc3d24c4afd20f53e94c96bd67545f Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 23:15:10 +0300 Subject: [PATCH 23/36] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c85137..c0ea2dc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # SpeedSouls - Save Organizer -The SpeedSouls - Save Organizer is a tool designed to manage savefiles for Dark Souls, Dark Souls II, Dark Souls II: Scholar of the First Sin and Dark Souls III. +The SpeedSouls - Save Organizer is a tool designed to manage savefiles for Dark Souls, Dark Souls II, Dark Souls II: Scholar of the First Sin, Dark Souls III and Sekiro: Shadows Die Twice. ## Functionality From e0b2f8a2929163efc85a34fe1f59cb59cb486fd7 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 23:30:18 +0300 Subject: [PATCH 24/36] Update tagging.yml --- .github/workflows/tagging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index 6e8e4ea..f944868 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -37,7 +37,7 @@ jobs: with: # JSON string json: ${{ steps.xml2json.outputs.data }} - version: "project.version" + version: "project._.version" - name: Commit tagger uses: tvdias/github-tagger@v0.0.2 From 0de43a2c0984811c230cdbb3a548ee593b74b998 Mon Sep 17 00:00:00 2001 From: mckunda Date: Wed, 17 Jun 2020 23:38:56 +0300 Subject: [PATCH 25/36] Fix actions --- .github/workflows/maven-pr.yml | 2 +- .github/workflows/maven-publish.yml | 4 ++-- .github/workflows/tagging.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index 5c844b1..a7d74e0 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -30,7 +30,7 @@ jobs: - name: Merge me! uses: ridedott/merge-me-action@v1.2.62 with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MEH }} GITHUB_LOGIN: mckunda MERGE_METHOD: MERGE diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index c52e7b2..57fe5a2 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -32,7 +32,7 @@ jobs: id: create_release uses: actions/create-release@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MEH }} with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} @@ -42,7 +42,7 @@ jobs: id: upload-release-asset uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MEH }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps asset_path: ./SaveOrganizer-${{ github.ref }}.zip diff --git a/.github/workflows/tagging.yml b/.github/workflows/tagging.yml index f944868..4e17429 100644 --- a/.github/workflows/tagging.yml +++ b/.github/workflows/tagging.yml @@ -43,6 +43,6 @@ jobs: uses: tvdias/github-tagger@v0.0.2 with: # The GITHUB_TOKEN secret - repo-token: ${{ secrets.GITHUB_TOKEN }} + repo-token: ${{ secrets.MEH }} # Tag text tag: v${{ steps.jsondata.outputs.version }} From 6b2a5eaf92ae426d117b4c0d21f9a0c3cdbbb816 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Wed, 17 Jun 2020 23:57:53 +0300 Subject: [PATCH 26/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 57fe5a2..b22bc7f 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -25,9 +25,7 @@ jobs: shell: bash run: mvn -B package --file pom.xml - name: Create Zip File - uses: montudor/action-zip@v0.1.0 - with: - args: zip -qq -r ./SaveOrganizer-${{ github.ref }}.zip ./target/SaveOrganizer.exe + run: 7z -a -tzip SaveOrganizer-${{ github.ref }}.zip target/SaveOrganizer.exe - name: Create Release id: create_release uses: actions/create-release@v1 From 4a5d460fef5ab8c9a36de12f707a7d2a964a8ecf Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Thu, 18 Jun 2020 00:01:18 +0300 Subject: [PATCH 27/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index b22bc7f..1fcc194 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -25,7 +25,7 @@ jobs: shell: bash run: mvn -B package --file pom.xml - name: Create Zip File - run: 7z -a -tzip SaveOrganizer-${{ github.ref }}.zip target/SaveOrganizer.exe + run: 7z a -tzip SaveOrganizer-${{ github.ref }}.zip target/SaveOrganizer.exe - name: Create Release id: create_release uses: actions/create-release@v1 From 9e3e92bd554b7fbe214f62da9d520578a6631b46 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Thu, 18 Jun 2020 00:06:44 +0300 Subject: [PATCH 28/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 1fcc194..3665057 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -26,6 +26,10 @@ jobs: run: mvn -B package --file pom.xml - name: Create Zip File run: 7z a -tzip SaveOrganizer-${{ github.ref }}.zip target/SaveOrganizer.exe + - name: Get the version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} + shell: bash - name: Create Release id: create_release uses: actions/create-release@v1 @@ -43,6 +47,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.MEH }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./SaveOrganizer-${{ github.ref }}.zip - asset_name: SaveOrganizer-${{ github.ref }}.zip + asset_path: ./SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip + asset_name: SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip asset_content_type: application/zip From d07f6c5d3ec5ebb0829c198985e3d861f9eb81d9 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Thu, 18 Jun 2020 00:09:48 +0300 Subject: [PATCH 29/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 3665057..4090eac 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -16,7 +16,11 @@ jobs: run: "git config --global core.autocrlf false" shell: bash - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v2 + - name: Get the version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} + shell: bash - name: Set up JDK 12 uses: actions/setup-java@v1 with: @@ -25,11 +29,7 @@ jobs: shell: bash run: mvn -B package --file pom.xml - name: Create Zip File - run: 7z a -tzip SaveOrganizer-${{ github.ref }}.zip target/SaveOrganizer.exe - - name: Get the version - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - shell: bash + run: 7z a -tzip SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip target/SaveOrganizer.exe - name: Create Release id: create_release uses: actions/create-release@v1 From a40f527bff7fa617a5f6b0a5c36b48d2a5db45d6 Mon Sep 17 00:00:00 2001 From: mckunda Date: Thu, 18 Jun 2020 00:24:35 +0300 Subject: [PATCH 30/36] Fix deploy --- .github/workflows/maven-publish.yml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 4090eac..1dfceb7 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -29,7 +29,7 @@ jobs: shell: bash run: mvn -B package --file pom.xml - name: Create Zip File - run: 7z a -tzip SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip target/SaveOrganizer.exe + run: 7z a -tzip SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip target/*.exe - name: Create Release id: create_release uses: actions/create-release@v1 diff --git a/pom.xml b/pom.xml index 67fc94e..885b038 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ gui target/${project.name}.exe - src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico + src/com/speedsouls/organizer/resources/SpeedSoulsFlameSmall.png target/${project.name}-${project.version}-jar-with-dependencies.jar ${project.name} From 256eb993b6ef9aa951297649941f87e1390f55ee Mon Sep 17 00:00:00 2001 From: mckunda Date: Thu, 18 Jun 2020 00:58:03 +0300 Subject: [PATCH 31/36] Fix icon --- pom.xml | 2 +- .../organizer/resources/SpeedSoulsIcon.ico | Bin 16694 -> 13054 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 885b038..67fc94e 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ gui target/${project.name}.exe - src/com/speedsouls/organizer/resources/SpeedSoulsFlameSmall.png + src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico target/${project.name}-${project.version}-jar-with-dependencies.jar ${project.name} diff --git a/src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico b/src/com/speedsouls/organizer/resources/SpeedSoulsIcon.ico index 92ed31aa285961be45d66686f566ce17ca5bdbc0..4f4d74a08eb03b38027283955b448249a7b1d827 100644 GIT binary patch literal 13054 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 d;~OK_Q6G-p-@aQ5S9q9(8cR`S%(xn6l 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 E0R564djJ3c From e5bc946292bf84dcbf596e3141151702ba0cb4e9 Mon Sep 17 00:00:00 2001 From: Ilya Enin Date: Thu, 18 Jun 2020 01:10:47 +0300 Subject: [PATCH 32/36] Update maven-publish.yml --- .github/workflows/maven-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 1dfceb7..f21f086 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -29,7 +29,7 @@ jobs: shell: bash run: mvn -B package --file pom.xml - name: Create Zip File - run: 7z a -tzip SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip target/*.exe + run: 7z a -tzip SaveOrganizer-${{ steps.get_version.outputs.VERSION }}.zip .\target\SaveOrganizer.exe - name: Create Release id: create_release uses: actions/create-release@v1 From 6c0ea4580a56ed699c9eb549c854ae4a90489fad Mon Sep 17 00:00:00 2001 From: Foxi <293639+noxifoxi@users.noreply.github.com> Date: Sun, 12 Dec 2021 15:12:35 +0100 Subject: [PATCH 33/36] Add ELDEN RING --- src/com/speedsouls/organizer/games/Game.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/speedsouls/organizer/games/Game.java b/src/com/speedsouls/organizer/games/Game.java index 8728c15..964cf72 100644 --- a/src/com/speedsouls/organizer/games/Game.java +++ b/src/com/speedsouls/organizer/games/Game.java @@ -25,6 +25,7 @@ public enum Game DARK_SOULS_II_SOTFS("Dark Souls II: SotFS", "DS2SOTFS", "DS2SOFS0000.sl2"), DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"), SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"); + ELDEN_RING("ELDEN RING", "ER", "ER0000.sl2"); private String caption; private String abbr; From 4827487951a331eed6ac0114e738668e6dec428e Mon Sep 17 00:00:00 2001 From: Foxi <293639+noxifoxi@users.noreply.github.com> Date: Sun, 12 Dec 2021 15:17:25 +0100 Subject: [PATCH 34/36] fix er --- src/com/speedsouls/organizer/games/Game.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/speedsouls/organizer/games/Game.java b/src/com/speedsouls/organizer/games/Game.java index 964cf72..43ee958 100644 --- a/src/com/speedsouls/organizer/games/Game.java +++ b/src/com/speedsouls/organizer/games/Game.java @@ -24,7 +24,7 @@ public enum Game DARK_SOULS_II("Dark Souls II", "DS2", "DARKSII0000.sl2"), DARK_SOULS_II_SOTFS("Dark Souls II: SotFS", "DS2SOTFS", "DS2SOFS0000.sl2"), DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"), - SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"); + SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"), ELDEN_RING("ELDEN RING", "ER", "ER0000.sl2"); private String caption; From 5cb432132d44e63515d8f6552cc848a05d1e5718 Mon Sep 17 00:00:00 2001 From: noxifoxi <293639+noxifoxi@users.noreply.github.com> Date: Sat, 25 Nov 2023 12:27:01 +0100 Subject: [PATCH 35/36] Elden Ring Seamless Co-op support --- README.md | 9 +++------ pom.xml | 10 +++++----- .../speedsouls/organizer/data/OrganizerManager.java | 2 +- src/com/speedsouls/organizer/games/Game.java | 3 ++- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c0ea2dc..ef4aaa2 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,11 @@ -[![Build Status](https://travis-ci.org/Kahmul/SpeedSouls-Save-Organizer.svg?branch=master)](https://travis-ci.org/Kahmul/SpeedSouls-Save-Organizer) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/0f60ad59931c4b6e9dc237286a386e36)](https://www.codacy.com/app/kahmul78/SpeedSouls-Save-Organizer?utm_source=github.com&utm_medium=referral&utm_content=Kahmul/SpeedSouls-Save-Organizer&utm_campaign=Badge_Grade) - -# SpeedSouls - Save Organizer +# SpeedSouls - Save Organizer The SpeedSouls - Save Organizer is a tool designed to manage savefiles for Dark Souls, Dark Souls II, Dark Souls II: Scholar of the First Sin, Dark Souls III and Sekiro: Shadows Die Twice. ## Functionality

- +

**1.** Choose your game. @@ -35,7 +32,7 @@ The SpeedSouls - Save Organizer is a tool designed to manage savefiles for Dark ## Download -[Latest Release](https://github.com/Kahmul/SpeedSouls-Save-Organizer/releases) +[Latest Release](https://github.com/noxifoxi/SpeedSouls-Save-Organizer/releases) ## Getting Started diff --git a/pom.xml b/pom.xml index 67fc94e..b9dee13 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 SpeedSouls SaveOrganizer - 1.4.2 + 1.4.4 @@ -113,12 +113,12 @@ 1.8 - 1.4.2.0 - 1.4.2.0 + 1.4.4.0 + 1.4.4.0 ${project.name} N/A - 1.4.2.0 - 1.4.2.0 + 1.4.4.0 + 1.4.4.0 ${project.name} ${project.name} ${project.name}.exe diff --git a/src/com/speedsouls/organizer/data/OrganizerManager.java b/src/com/speedsouls/organizer/data/OrganizerManager.java index 0a49422..1cc24ff 100644 --- a/src/com/speedsouls/organizer/data/OrganizerManager.java +++ b/src/com/speedsouls/organizer/data/OrganizerManager.java @@ -61,7 +61,7 @@ public class OrganizerManager { - public static final String VERSION = "1.4.2"; + public static final String VERSION = "1.4.4"; /** * Constants defining various URLs. diff --git a/src/com/speedsouls/organizer/games/Game.java b/src/com/speedsouls/organizer/games/Game.java index 43ee958..9c7ef2d 100644 --- a/src/com/speedsouls/organizer/games/Game.java +++ b/src/com/speedsouls/organizer/games/Game.java @@ -25,7 +25,8 @@ public enum Game DARK_SOULS_II_SOTFS("Dark Souls II: SotFS", "DS2SOTFS", "DS2SOFS0000.sl2"), DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"), SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"), - ELDEN_RING("ELDEN RING", "ER", "ER0000.sl2"); + ELDEN_RING("ELDEN RING", "ER", "ER0000.sl2"), + ELDEN_RING_CO("ELDEN RING Seamless Co-op", "ER", "ER0000.co2"); private String caption; private String abbr; From a058ab999264cf2f7758b734b0ec3544374221ac Mon Sep 17 00:00:00 2001 From: CB Bailey Date: Sun, 10 Dec 2023 17:51:30 +0000 Subject: [PATCH 36/36] Add support for Armored Core VI --- src/com/speedsouls/organizer/games/Game.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/speedsouls/organizer/games/Game.java b/src/com/speedsouls/organizer/games/Game.java index 9c7ef2d..bd18001 100644 --- a/src/com/speedsouls/organizer/games/Game.java +++ b/src/com/speedsouls/organizer/games/Game.java @@ -26,7 +26,8 @@ public enum Game DARK_SOULS_III("Dark Souls III", "DS3", "DS30000.sl2"), SEKIRO_SHADOWS_DIE_TWICE("Sekiro: Shadows Die Twice", "SSDT", "S0000.sl2"), ELDEN_RING("ELDEN RING", "ER", "ER0000.sl2"), - ELDEN_RING_CO("ELDEN RING Seamless Co-op", "ER", "ER0000.co2"); + ELDEN_RING_CO("ELDEN RING Seamless Co-op", "ER", "ER0000.co2"), + ARMORED_CORE_VI("Armored Core VI: Fires of Rubicon", "AC6", "AC60000.sl2"); private String caption; private String abbr;