├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── kotlinc.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── PAL_LAUNCHER
└── PAL_Launcher.cs
├── PoE-Addon-Launcher-Core.iml
├── README.md
├── pom.xml
└── src
├── main
├── java
│ ├── Data
│ │ └── PALsettings.java
│ └── GUI
│ │ └── PopUp
│ │ ├── Updated_HTML_Popup.java
│ │ └── Updated_HTML_Popup_Controller.java
├── kotlin
│ └── PAL2
│ │ ├── Addons
│ │ └── Externals.kt
│ │ ├── Database
│ │ └── DataBaseHandler.kt
│ │ ├── Filters
│ │ ├── FilterBlast.kt
│ │ ├── FilterContainer.kt
│ │ └── FilterDownloader.kt
│ │ ├── FunStuff
│ │ └── FunStuff.kt
│ │ ├── GUI
│ │ ├── AddonAnchor.kt
│ │ ├── Configurator
│ │ │ └── Configurator.kt
│ │ ├── CoreApplication.kt
│ │ ├── CoreController.kt
│ │ ├── CustomAddonAnchor.kt
│ │ ├── DownloadsAnchor.kt
│ │ ├── FilterAnchor.kt
│ │ ├── InstalledAnchor.kt
│ │ ├── LightningEffects.kt
│ │ ├── Loader
│ │ │ └── Loader.kt
│ │ └── UtilityAnchor.kt
│ │ ├── Github
│ │ ├── GH_Connector.kt
│ │ ├── ReadMeConverter.kt
│ │ └── UpdateGrabber.kt
│ │ ├── GlobalData.kt
│ │ ├── Launcher.kt
│ │ ├── PAL_DataClasses
│ │ └── PALData.kt
│ │ └── SystemHandling
│ │ ├── AddonRemover.kt
│ │ ├── AddonUpdater.kt
│ │ ├── FileHandling.kt
│ │ ├── Init.kt
│ │ ├── InstallHandler.kt
│ │ ├── LaunchHandling.kt
│ │ └── WebHandling.kt
└── resources
│ ├── Configurator.fxml
│ ├── CoreUI.fxml
│ ├── FiltersTab.fxml
│ ├── Loader.fxml
│ ├── Settings.fxml
│ ├── bk
│ ├── CoreUI.bk
│ └── CoreUIPREPAL2.bk
│ ├── config.fxml
│ ├── downloadAsker.fxml
│ ├── fxml_previews
│ ├── addonDisplay.fxml
│ ├── downloadsAnchor.fxml
│ └── installedList.fxml
│ ├── icons
│ ├── NoIcon.png
│ ├── Web.pdn
│ ├── Web.png
│ ├── ahk.png
│ ├── cancel.png
│ ├── cancel0.png
│ ├── colors
│ ├── cross.png
│ ├── down.png
│ ├── downArrow.pdn
│ ├── downArrow.png
│ ├── down_hl.png
│ ├── download.png
│ ├── download_all.pdn
│ ├── download_all.png
│ ├── download_darker.png
│ ├── edit.png
│ ├── emptyStar.png
│ ├── filledStar.png
│ ├── gggAprove.png
│ ├── gggAproveQ.png
│ ├── gggMark.pdn
│ ├── info.png
│ ├── main_quest_item.png
│ ├── minimize.png
│ ├── minimize_hl.png
│ ├── minus.png
│ ├── part.png
│ ├── play.png
│ ├── q.png
│ ├── refresh_icon.png
│ ├── remove.png
│ ├── respecbook.png
│ ├── settings.png
│ ├── settings_hl.png
│ ├── skillbook.png
│ ├── star25.png
│ ├── star50.png
│ ├── star75.png
│ ├── thumbsDown.png
│ ├── thumbsUp.png
│ ├── trash.png
│ ├── trayIcon.png
│ ├── trial.png
│ ├── upArrow.pdn
│ ├── upArrow.png
│ └── waypoint.png
│ ├── legion.png
│ ├── log4j2.xml
│ ├── new_in_this_release.fxml
│ ├── overlay
│ ├── GridDisplay.fxml
│ └── WebAddonUI.fxml
│ ├── overlayidea.png
│ ├── popup.fxml
│ ├── popup_import.fxml
│ ├── settings
│ ├── Twitch_icon.png
│ ├── YouTube-icon.png
│ ├── discord.jpg
│ ├── discord.png
│ ├── github-512.png
│ ├── patreon.png
│ ├── patreon_small.png
│ ├── reddit.png
│ ├── twitchsmall.png
│ ├── twitter.png
│ ├── twittersmaller.png
│ └── utubesmall.png
│ ├── test.fxml
│ ├── tray
│ ├── animation.gif
│ ├── baseTray.png
│ └── paused.png
│ ├── update_notes.fxml
│ ├── update_notes.html
│ ├── updatepls.fxml
│ └── witch.png
└── test
└── kotlin
└── PAL2
├── Filters
└── FilterBlastTest.kt
└── Github
└── ReadMeConverterTest.kt
/.gitignore:
--------------------------------------------------------------------------------
1 | src/main/kotlin/PAL2/Client/*
2 |
3 | #Ignore CSS files
4 | src/main/resources/*.css
5 |
6 | # Compiled class file
7 | *.class
8 |
9 | # Log file
10 | *.log
11 |
12 | # BlueJ files
13 | *.ctxt
14 |
15 | # Mobile Tools for Java (J2ME)
16 | .mtj.tmp/
17 |
18 | # Package Files #
19 | *.jar
20 | *.war
21 | *.nar
22 | *.ear
23 | *.zip
24 | *.tar.gz
25 | *.rar
26 |
27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
28 | hs_err_pid*
29 |
30 |
31 | # Created by https://www.gitignore.io/api/java,maven,intellij
32 |
33 | ### Intellij ###
34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
36 |
37 | # User-specific stuff
38 | .idea/**/workspace.xml
39 | .idea/**/tasks.xml
40 | .idea/**/usage.statistics.xml
41 | .idea/**/dictionaries
42 | .idea/**/shelf
43 |
44 | # Generated files
45 | .idea/**/contentModel.xml
46 |
47 | # Sensitive or high-churn files
48 | .idea/**/dataSources/
49 | .idea/**/dataSources.ids
50 | .idea/**/dataSources.local.xml
51 | .idea/**/sqlDataSources.xml
52 | .idea/**/dynamic.xml
53 | .idea/**/uiDesigner.xml
54 | .idea/**/dbnavigator.xml
55 |
56 | # Gradle
57 | .idea/**/gradle.xml
58 | .idea/**/libraries
59 |
60 | # Gradle and Maven with auto-import
61 | # When using Gradle or Maven with auto-import, you should exclude module files,
62 | # since they will be recreated, and may cause churn. Uncomment if using
63 | # auto-import.
64 | # .idea/modules.xml
65 | # .idea/*.iml
66 | # .idea/modules
67 |
68 | # CMake
69 | cmake-build-*/
70 |
71 | # Mongo Explorer plugin
72 | .idea/**/mongoSettings.xml
73 |
74 | # File-based project format
75 | *.iws
76 |
77 | # IntelliJ
78 | out/
79 |
80 | # mpeltonen/sbt-idea plugin
81 | .idea_modules/
82 |
83 | # JIRA plugin
84 | atlassian-ide-plugin.xml
85 |
86 | # Cursive Clojure plugin
87 | .idea/replstate.xml
88 |
89 | # Crashlytics plugin (for Android Studio and IntelliJ)
90 | com_crashlytics_export_strings.xml
91 | crashlytics.properties
92 | crashlytics-build.properties
93 | fabric.properties
94 |
95 | # Editor-based Rest Client
96 | .idea/httpRequests
97 |
98 | ### Intellij Patch ###
99 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
100 |
101 | # *.iml
102 | # modules.xml
103 | # .idea/misc.xml
104 | # *.ipr
105 |
106 | # Sonarlint plugin
107 | .idea/sonarlint
108 |
109 | ### Java ###
110 | # Compiled class file
111 | *.class
112 |
113 | # Log file
114 | *.log
115 |
116 | # BlueJ files
117 | *.ctxt
118 |
119 | # Mobile Tools for Java (J2ME)
120 | .mtj.tmp/
121 |
122 | # Package Files #
123 | *.jar
124 | *.war
125 | *.nar
126 | *.ear
127 | *.zip
128 | *.tar.gz
129 | *.rar
130 |
131 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
132 | hs_err_pid*
133 |
134 | ### Maven ###
135 | target/
136 | pom.xml.tag
137 | pom.xml.releaseBackup
138 | pom.xml.versionsBackup
139 | pom.xml.next
140 | release.properties
141 | dependency-reduced-pom.xml
142 | buildNumber.properties
143 | .mvn/timing.properties
144 | .mvn/wrapper/maven-wrapper.jar
145 |
146 |
147 | # End of https://www.gitignore.io/api/java,maven,intellij
148 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | PoE-Addon-Launcher-Core
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/PAL_LAUNCHER/PAL_Launcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Threading;
8 | using System.Runtime.InteropServices;
9 | using System.Net;
10 | using System.Windows;
11 | using System.IO;
12 | using System.IO.Compression;
13 |
14 | namespace PAL_Launcher
15 | {
16 | class Program
17 | {
18 | [DllImport("kernel32.dll")]
19 | static extern IntPtr GetConsoleWindow();
20 |
21 | [DllImport("user32.dll")]
22 | static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
23 |
24 | const int SW_HIDE = 0;
25 | const int SW_SHOW = 5;
26 |
27 | static void Main(string[] args)
28 | {
29 | // Check if the folder "new" exists
30 | // If new exists replace the current JAR with the one in "new"
31 |
32 | applyUpdate();
33 |
34 |
35 | Console.WriteLine("===========================");
36 | Console.WriteLine("Welcome to the PAL Launcher");
37 | Console.WriteLine("===========================");
38 | Console.WriteLine("");
39 | Console.WriteLine("Preparing to launch PAL2\n");
40 |
41 | Console.WriteLine("Detecting PAL2...");
42 | if (checkPAL())
43 | {
44 | Console.WriteLine("PAL2 found! Attempting to launch...");
45 | }
46 | else
47 | {
48 | Console.WriteLine("PAL2 not found!");
49 | Console.WriteLine("Downloading PAL2.jar!");
50 | FileDownloader.DownloadFile("https://github.com/POE-Addon-Launcher/PALRelease/raw/master/PAL2.jar", Path.Combine(Environment.CurrentDirectory, "PAL2.jar"), int.MaxValue);
51 | }
52 |
53 | Console.WriteLine("Searching for Java...");
54 |
55 | if (checkJava())
56 | {
57 | Thread t = new Thread(() =>
58 | {
59 | var handle = GetConsoleWindow();
60 | Console.WriteLine("Java found! Launching PAL2");
61 | Process process = new Process();
62 | process.StartInfo.FileName = "cmd.exe";
63 | process.StartInfo.Arguments = "/c java -jar PAL2.jar";
64 | process.StartInfo.UseShellExecute = false;
65 | process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
66 | ShowWindow(handle, SW_HIDE);
67 | process.Start();
68 | });
69 | t.Start();
70 | }
71 | else
72 | {
73 | // if ojdk folder exists, launch instead!
74 | string cdir = Path.Combine(Environment.CurrentDirectory, "jre");
75 | if (Directory.Exists(cdir))
76 | {
77 | Console.WriteLine("Launching PAL2");
78 | launchPAL2();
79 | }
80 | else
81 | {
82 | Console.Clear();
83 | Console.WriteLine("Java not found, downloading the Java Runtime...");
84 |
85 | string jreZip = Path.Combine(Environment.CurrentDirectory, "jre.zip");
86 |
87 | var success = FileDownloader.DownloadFile("https://github.com/POE-Addon-Launcher/PALRelease/releases/download/jre/jre.zip", jreZip, int.MaxValue);
88 |
89 | if (success)
90 | {
91 | ZipStorer zip = ZipStorer.Open(jreZip, FileAccess.Read);
92 | List files = zip.ReadCentralDir();
93 |
94 | Console.WriteLine("Extracting Zip Archive this may take some time...\nDO NOT CLOSE THE PROGRAM IT IS NOT STUCK!");
95 |
96 | foreach (ZipStorer.ZipFileEntry entry in files)
97 | {
98 | zip.ExtractFile(entry, Path.Combine(Environment.CurrentDirectory, entry.FilenameInZip));
99 | };
100 | zip.Close();
101 | Console.WriteLine("Deleting Archive...");
102 | // TODO Delete zip
103 | if (File.Exists(jreZip))
104 | {
105 | File.Delete(jreZip);
106 | }
107 |
108 | Console.WriteLine("Extracting Completed, launching PAL2");
109 | launchPAL2();
110 | }
111 | else
112 | {
113 | Console.WriteLine("Download failed for some reason! Download java yourself instead.");
114 | }
115 | }
116 | }
117 |
118 | }
119 |
120 | static void launchPAL2()
121 | {
122 | Thread t = new Thread(() =>
123 | {
124 | Console.WriteLine("Launching PAL2");
125 | var javaEXE = Path.Combine(Environment.CurrentDirectory, @"jre\bin\java.exe");
126 | string cmd = "/c ";
127 | cmd += javaEXE;
128 | cmd += " -jar PAL2.jar";
129 | var handle = GetConsoleWindow();
130 | Process process = new Process();
131 | process.StartInfo.FileName = "cmd.exe";
132 | process.StartInfo.Arguments = cmd;
133 | process.StartInfo.UseShellExecute = false;
134 | process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
135 | ShowWindow(handle, SW_HIDE);
136 | process.Start();
137 | });
138 | t.Start();
139 | }
140 |
141 | static void killJava()
142 | {
143 | Process.Start("taskkill", "/F /IM java.exe");
144 | Process.Start("taskkill", "/F /IM javaw.exe");
145 | Console.WriteLine("Waiting for java to exit...");
146 | Thread.Sleep(3000);
147 | }
148 |
149 | /**
150 | * Overwrites PAL2.jar with the one in the "new" folder.
151 | */
152 | static void applyUpdate()
153 | {
154 | var newest = Path.Combine(@Environment.CurrentDirectory, @"new\PAL2.jar");
155 | if (File.Exists(newest))
156 | {
157 | // Taskkill java & javaw
158 | killJava();
159 |
160 | string pal2jar = Path.Combine(Environment.CurrentDirectory, "PAL2.jar");
161 | if (checkPAL())
162 | {
163 | File.Delete(pal2jar);
164 | }
165 | File.Move(newest, pal2jar);
166 |
167 | string pal2log = Path.Combine(Environment.CurrentDirectory, @"new\PAL_Logger.log");
168 | if (File.Exists(pal2log))
169 | {
170 | File.Delete(pal2log);
171 | }
172 |
173 |
174 | string dir = Path.Combine(Environment.CurrentDirectory, @"new");
175 | if (Directory.Exists(dir))
176 | {
177 | Directory.Delete(dir);
178 | }
179 | }
180 | }
181 |
182 | /**
183 | * Checks if PAL2.jar is in our root directory.
184 | */
185 | static bool checkPAL()
186 | {
187 | string pal2jar = Path.Combine(Environment.CurrentDirectory, "PAL2.jar");
188 | return File.Exists(pal2jar);
189 | }
190 |
191 | static Process process = new Process();
192 | static bool foundJava = false;
193 |
194 | /**
195 | * Checks if Java is installed.
196 | */
197 | static bool checkJava()
198 | {
199 | process.EnableRaisingEvents = true;
200 | process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
201 | process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
202 | process.Exited += new EventHandler(process_Exited);
203 |
204 | process.StartInfo.FileName = "cmd.exe";
205 | process.StartInfo.Arguments = "/c java -version";
206 | process.StartInfo.UseShellExecute = false;
207 | process.StartInfo.RedirectStandardError = true;
208 | process.StartInfo.RedirectStandardOutput = true;
209 |
210 | process.Start();
211 | process.BeginErrorReadLine();
212 | process.BeginOutputReadLine();
213 |
214 | process.WaitForExit();
215 |
216 | return foundJava;
217 | }
218 |
219 | static void process_Exited(object sender, EventArgs e)
220 | {
221 | //Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
222 | }
223 |
224 | static void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
225 | {
226 | if (e.Data != null)
227 | {
228 | if (e.Data.Contains("java version"))
229 | foundJava = true;
230 | }
231 |
232 | }
233 |
234 | static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
235 | {
236 | //Console.WriteLine("Output: " + e.Data + "\n");
237 | }
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/PoE-Addon-Launcher-Core.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PoE Addon Launcher 2 (PAL2)
2 |
3 | 
4 |
5 | # HOW DO I DOWNLOAD THIS?
6 | # Go to the releases tab or click on this useful link: [v1.12.2](https://github.com/POE-Addon-Launcher/PAL2/releases/download/1.12.2/PAL2.exe)
7 |
8 | # HOW DO I USE THIS?
9 | # [User-Guide v1.11](https://docs.google.com/document/d/1iV6BpndAaENhWc6hcCYI3hINjxi1FAa8bdbeSUXrKFo/edit?usp=sharing)
10 |
11 |
12 | PAL2 is PAL but completely rewritten from the ground up in Kotlin, it also no longer requires you to install the java runtime for it to be used.
13 |
14 | It's to be used to eliminate manual tracking of programs and their updates, and also launches all your addons prior to launching Path of Exile!
15 |
16 | Stay up to date with all your favourite addons!
17 |
18 | 
19 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | RizlimDev
8 | PoE-Addon-Launcher-Core
9 | 1.12
10 |
11 |
12 | 1.3.0
13 |
14 |
15 |
16 |
17 |
18 |
19 | org.apache.maven.plugins
20 | maven-jar-plugin
21 | 3.0.2
22 |
23 |
24 |
25 | true
26 | Launcher2
27 |
28 |
29 | .
30 |
31 |
32 |
33 |
34 |
35 | maven-assembly-plugin
36 |
37 |
38 |
39 | true
40 | Launcher2
41 |
42 |
43 | .
44 |
45 |
46 |
47 | jar-with-dependencies
48 |
49 |
50 |
51 |
52 | org.jetbrains.kotlin
53 | kotlin-maven-plugin
54 | ${kotlin.version}
55 |
56 |
57 | compile
58 | compile
59 |
60 | compile
61 |
62 |
63 |
64 | test-compile
65 | test-compile
66 |
67 | test-compile
68 |
69 |
70 |
71 |
72 | 1.8
73 |
74 |
75 |
76 | org.apache.maven.plugins
77 | maven-compiler-plugin
78 | 3.8.0
79 |
80 |
81 | compile
82 | compile
83 |
84 | compile
85 |
86 |
87 |
88 | testCompile
89 | test-compile
90 |
91 | testCompile
92 |
93 |
94 |
95 |
96 | 8
97 | 8
98 |
99 |
100 |
101 | org.jetbrains.kotlin
102 | kotlin-maven-plugin
103 | ${kotlin.version}
104 |
105 |
106 | compile
107 | process-sources
108 |
109 | compile
110 |
111 |
112 |
113 | src/main/java
114 | src/main/kotlin
115 | src/main/resources
116 |
117 |
118 |
119 |
120 | test-compile
121 | process-test-sources
122 |
123 | test-compile
124 |
125 |
126 |
127 | src/test/java
128 | src/test/kotlin
129 | src/test/resources
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | com.atlassian.commonmark
141 | commonmark
142 | 0.12.1
143 |
144 |
145 | com.fasterxml.jackson.core
146 | jackson-databind
147 | 2.9.10.1
148 |
149 |
150 | com.fasterxml.jackson.module
151 | jackson-module-kotlin
152 | 2.9.4.1
153 |
154 |
155 | junit
156 | junit
157 | 4.12
158 |
159 |
160 | net.lingala.zip4j
161 | zip4j
162 | 1.3.2
163 |
164 |
165 | org.kohsuke
166 | github-api
167 | 1.93
168 |
169 |
170 | org.jetbrains.kotlin
171 | kotlin-stdlib-jdk8
172 | ${kotlin.version}
173 |
174 |
175 | org.jetbrains.kotlin
176 | kotlin-test-junit
177 | ${kotlin.version}
178 | test
179 |
180 |
181 | org.jetbrains.kotlinx
182 | kotlinx-coroutines-core
183 | 1.0.1
184 |
185 |
186 | org.jetbrains.kotlinx
187 | kotlinx-coroutines-javafx
188 | 1.0.1
189 |
190 |
191 | org.jetbrains.kotlin
192 | kotlin-stdlib-jdk8
193 | ${kotlin.version}
194 |
195 |
196 | org.jetbrains.kotlin
197 | kotlin-test
198 | ${kotlin.version}
199 | test
200 |
201 |
202 | org.jetbrains.kotlin
203 | kotlin-reflect
204 | 1.3.0
205 |
206 |
207 | com.fasterxml.jackson.datatype
208 | jackson-datatype-jsr310
209 | 2.9.9
210 |
211 |
212 | io.github.microutils
213 | kotlin-logging
214 | 1.6.22
215 |
216 |
217 | org.slf4j
218 | slf4j-api
219 | 1.7.25
220 |
221 |
222 | org.apache.logging.log4j
223 | log4j-slf4j-impl
224 | 2.9.1
225 |
226 |
227 | org.apache.logging.log4j
228 | log4j-api
229 | 2.9.1
230 |
231 |
232 | org.apache.logging.log4j
233 | log4j-core
234 | 2.9.1
235 |
236 |
237 | org.xerial
238 | sqlite-jdbc
239 | 3.25.2
240 |
241 |
242 | commons-io
243 | commons-io
244 | 2.6
245 |
246 |
247 |
248 |
--------------------------------------------------------------------------------
/src/main/java/Data/PALsettings.java:
--------------------------------------------------------------------------------
1 | package Data;
2 |
3 | /**
4 | *
5 | */
6 | public class PALsettings
7 | {
8 | private boolean wait_for_updates = false;
9 | private String loot_filter_dir = "";
10 | private boolean github_api_enabled = true;
11 | private String pref_version = "";
12 | private boolean filterblast_api = true;
13 | private boolean down_on_launch = false;
14 | private String AHK_Folder = "";
15 | private String github_token = "";
16 | private boolean github_api_token_enabled = false;
17 | private boolean run_poe_on_launch = false;
18 |
19 | private PALsettings()
20 | {}
21 |
22 | public PALsettings(boolean wait_for_updates, String loot_filter_dir, boolean github_api_enabled, String pref_version, boolean filterblast_api, boolean down_on_launch, String AHK_Folder, String github_token, boolean github_api_token_enabled, boolean run_poe_on_launch)
23 | {
24 | this.wait_for_updates = wait_for_updates;
25 | this.loot_filter_dir = loot_filter_dir;
26 | this.github_api_enabled = github_api_enabled;
27 | this.pref_version = pref_version;
28 | this.filterblast_api = filterblast_api;
29 | this.down_on_launch = down_on_launch;
30 | this.AHK_Folder = AHK_Folder;
31 | this.github_token = github_token;
32 | this.github_api_token_enabled = github_api_token_enabled;
33 | this.run_poe_on_launch = run_poe_on_launch;
34 | }
35 |
36 | public boolean isWait_for_updates()
37 | {
38 | return wait_for_updates;
39 | }
40 |
41 | public void setWait_for_updates(boolean wait_for_updates)
42 | {
43 | this.wait_for_updates = wait_for_updates;
44 | }
45 |
46 | public String getLoot_filter_dir()
47 | {
48 | return loot_filter_dir;
49 | }
50 |
51 | public void setLoot_filter_dir(String loot_filter_dir)
52 | {
53 | this.loot_filter_dir = loot_filter_dir;
54 | }
55 |
56 | public boolean isGithub_api_enabled()
57 | {
58 | return github_api_enabled;
59 | }
60 |
61 | public void setGithub_api_enabled(boolean github_api_enabled)
62 | {
63 | this.github_api_enabled = github_api_enabled;
64 | }
65 |
66 | public String getPref_version()
67 | {
68 | return pref_version;
69 | }
70 |
71 | public void setPref_version(String pref_version)
72 | {
73 | this.pref_version = pref_version;
74 | }
75 |
76 | public boolean isFilterblast_api()
77 | {
78 | return filterblast_api;
79 | }
80 |
81 | public void setFilterblast_api(boolean filterblast_api)
82 | {
83 | this.filterblast_api = filterblast_api;
84 | }
85 |
86 | public boolean isDown_on_launch()
87 | {
88 | return down_on_launch;
89 | }
90 |
91 | public void setDown_on_launch(boolean down_on_launch)
92 | {
93 | this.down_on_launch = down_on_launch;
94 | }
95 |
96 | public String getAHK_Folder()
97 | {
98 | return AHK_Folder;
99 | }
100 |
101 | public void setAHK_Folder(String AHK_Folder)
102 | {
103 | this.AHK_Folder = AHK_Folder;
104 | }
105 |
106 | public String getGithub_token()
107 | {
108 | return github_token;
109 | }
110 |
111 | public void setGithub_token(String github_token)
112 | {
113 | this.github_token = github_token;
114 | }
115 |
116 | public boolean isGithub_api_token_enabled()
117 | {
118 | return github_api_token_enabled;
119 | }
120 |
121 | public void setGithub_api_token_enabled(boolean github_api_token_enabled)
122 | {
123 | this.github_api_token_enabled = github_api_token_enabled;
124 | }
125 |
126 | public boolean isRun_poe_on_launch()
127 | {
128 | return run_poe_on_launch;
129 | }
130 |
131 | public void setRun_poe_on_launch(boolean run_poe_on_launch)
132 | {
133 | this.run_poe_on_launch = run_poe_on_launch;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/GUI/PopUp/Updated_HTML_Popup.java:
--------------------------------------------------------------------------------
1 | package GUI.PopUp;
2 |
3 | import javafx.application.Application;
4 | import javafx.fxml.FXMLLoader;
5 | import javafx.scene.Parent;
6 | import javafx.scene.Scene;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 | import javafx.stage.StageStyle;
10 |
11 | /**
12 | *
13 | */
14 | public class Updated_HTML_Popup
15 | extends Application
16 | {
17 | public static Stage stage;
18 |
19 | public void start(Stage primaryStage) throws Exception
20 | {
21 | primaryStage = new Stage();
22 | FXMLLoader fxmlLoader = new FXMLLoader();
23 | primaryStage.initStyle(StageStyle.UNDECORATED);
24 | primaryStage.setAlwaysOnTop(true);
25 | Parent root = fxmlLoader.load(getClass().getResource("/update_notes.fxml"));
26 | primaryStage.setTitle("PAL: NEW!");
27 | primaryStage.getIcons().add(new Image(getClass().getResource("/witch.png").toString()));
28 | Scene scene = new Scene(root, 499, 300);
29 | primaryStage.setScene(scene);
30 | stage = primaryStage;
31 | primaryStage.show();
32 | }
33 |
34 | public void activate(String[] args)
35 | {
36 | launch(args);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/GUI/PopUp/Updated_HTML_Popup_Controller.java:
--------------------------------------------------------------------------------
1 | package GUI.PopUp;
2 |
3 | import javafx.application.Platform;
4 | import javafx.fxml.FXML;
5 | import javafx.fxml.Initializable;
6 | import javafx.scene.image.Image;
7 | import javafx.scene.image.ImageView;
8 | import javafx.scene.input.MouseEvent;
9 | import javafx.scene.web.WebView;
10 |
11 | import java.io.File;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.net.MalformedURLException;
15 | import java.net.URL;
16 | import java.nio.file.Files;
17 | import java.nio.file.Paths;
18 | import java.util.ResourceBundle;
19 |
20 | public class Updated_HTML_Popup_Controller
21 | implements Initializable
22 | {
23 | @FXML
24 | private ImageView topbar_image_closeWindow;
25 |
26 | @FXML
27 | private WebView HTML_Viewer;
28 |
29 |
30 | private double xOffset = 0;
31 | private double yOffset = 0;
32 |
33 | public void onMouseDragged(MouseEvent mouseEvent)
34 | {
35 | Updated_HTML_Popup.stage.setX(mouseEvent.getScreenX() + xOffset);
36 | Updated_HTML_Popup.stage.setY(mouseEvent.getScreenY() + yOffset);
37 | }
38 | public void onMousePressed(MouseEvent mouseEvent)
39 | {
40 | xOffset = Updated_HTML_Popup.stage.getX() - mouseEvent.getScreenX();
41 | yOffset = Updated_HTML_Popup.stage.getY() - mouseEvent.getScreenY();
42 | }
43 |
44 | public void topbar_closeWIndow_onMouseClicked()
45 | {
46 | Updated_HTML_Popup.stage.close();
47 | }
48 |
49 | public void topbar_closeWindow_onMouseEntered()
50 | {
51 | changeImage(topbar_image_closeWindow, "/icons/cancel.png");
52 | }
53 |
54 | public void topbar_closeWindow_onMouseExited()
55 | {
56 | changeImage(topbar_image_closeWindow, "/icons/cancel0.png");
57 | }
58 |
59 | private void changeImage(ImageView imageView, String s)
60 | {
61 | Platform.runLater(() -> imageView.setImage(new Image(getClass().getResource(s).toString())));
62 | }
63 |
64 | @Override
65 | public void initialize(URL location, ResourceBundle resources)
66 | {
67 | try
68 | {
69 | String folder = System.getenv("LOCALAPPDATA");
70 |
71 | File f = new File(folder + File.separator + "PAL" + File.separator + "update_notes.html");
72 |
73 | if (f.exists())
74 | f.delete();
75 |
76 | InputStream inputStream = new URL("https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/master/src/main/resources/update_notes.html").openStream();
77 | Files.copy(inputStream, Paths.get(f.getPath() ));
78 | Platform.runLater(() ->
79 | {
80 | try
81 | {
82 | HTML_Viewer.getEngine().load(f.toURI().toURL().toString());
83 | }
84 | catch (MalformedURLException e)
85 | {
86 | e.printStackTrace();
87 | }
88 | });
89 |
90 | }
91 | catch (IOException e)
92 | {
93 | e.printStackTrace();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Addons/Externals.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Addons
2 |
3 | import GlobalData
4 | import PAL2.Database.countAHKs
5 | import PAL2.Database.countExternalAddon
6 | import PAL2.Database.getAHKScriptsArray
7 | import PAL2.Database.nukeAHK
8 | import PAL2.GUI.CoreApplication
9 | import PAL2.SystemHandling.FileDownloader
10 | import PAL2.SystemHandling.InstallHandlerHelpers
11 | import PAL_DataClasses.PAL_External_Addon
12 | import SystemHandling.deleteFile
13 | import java.io.File
14 | import java.net.URL
15 | import java.nio.file.Files
16 | import java.nio.file.Paths
17 | import java.util.zip.CRC32
18 |
19 | /**
20 | *
21 | */
22 | object Externals
23 | {
24 | val LUTBOT_DL = "http://lutbot.com/ahk/macro.ahk"
25 | val SIC_DL = "https://synthesisparser.herokuapp.com/SynthesisParser.ahk"
26 |
27 | fun calcCRC32(bytes: ByteArray): String
28 | {
29 | val hash = CRC32()
30 | hash.update(bytes)
31 | return hash.value.toString(16)
32 | }
33 |
34 | fun calcCRC32(file: File): String
35 | {
36 | val bytes = Files.readAllBytes(Paths.get(file.toURI()))
37 | val hash = CRC32()
38 | hash.update(bytes)
39 | return hash.value.toString(16)
40 | }
41 |
42 | fun determineCMD(file: File): String
43 | {
44 | return when (file.extension.toLowerCase())
45 | {
46 | "exe" -> InstallHandlerHelpers.createExeLaunchCommandWithElevation(file.path)
47 | "ahk" -> InstallHandlerHelpers.createAHKLaunchCommand(file.path)
48 | "jar" -> InstallHandlerHelpers.createJARLaunchCommand(file.path)
49 | else -> ""
50 | }
51 | }
52 |
53 | // Checks if Externals Table Exists, if it doesn't creates it.
54 | fun determineDBID(): Int
55 | {
56 | return countExternalAddon()+1
57 | }
58 |
59 | fun syncAHKsWithExternals()
60 | {
61 | val ahks = countAHKs()
62 |
63 | if (ahks == 0)
64 | return
65 |
66 | // Retrieve AHKs
67 | val scripts = getAHKScriptsArray()
68 |
69 | for (ahk in scripts)
70 | {
71 | val file = File(ahk.location)
72 | if (file.exists() && !file.isDirectory)
73 | {
74 | val crc32 = Externals.calcCRC32(file)
75 | val cmd = Externals.determineCMD(file)
76 | val dbid = Externals.determineDBID()
77 | val name = file.nameWithoutExtension
78 | val path = file.path
79 | val ea = PAL_External_Addon(dbid, name, crc32, "", "", "", "", cmd, path, ahk.runOnLaunch)
80 | CoreApplication.controller.saveExternal(ea)
81 |
82 | }
83 | }
84 |
85 | // Delete AHKs from DB
86 | nukeAHK()
87 | }
88 |
89 | fun checkForUpdatesAndUpdateExternals()
90 | {
91 | //TODO: This
92 | // Check for updates
93 |
94 |
95 | // If update found back up current file
96 |
97 |
98 | //
99 | }
100 |
101 | /**
102 | * Returns AID for setting installed, matches based on "website_source"
103 | */
104 | fun isMajorAddon(string: String): Int
105 | {
106 | return when (string)
107 | {
108 | LUTBOT_DL -> 9
109 | SIC_DL -> 17
110 | else -> 0
111 | }
112 | }
113 |
114 | fun isExternal(aid: Int): Boolean
115 | {
116 | return when (aid)
117 | {
118 | 17 -> true // Synthesized-Implicit-Calculator
119 | 9 -> true // Lutbot
120 | else -> false
121 | }
122 | }
123 |
124 | fun addLutBot()
125 | {
126 | if (!GlobalData.addonFolder.exists())
127 | GlobalData.addonFolder.mkdir()
128 |
129 | var install = GlobalData.addonFolder.path + File.separator + "lutbot"
130 |
131 | if (!File(install).exists())
132 | File(install).mkdir()
133 |
134 | install += File.separator + "macro.ahk"
135 |
136 | val ea = PAL_External_Addon(-1, "Lutbot", "", "", null, "", LUTBOT_DL, determineCMD(File(install)), install, false)
137 |
138 | // Download
139 | CoreApplication.controller.showDownloadPopup(File(ea.webSource).name)
140 | val location = FileDownloader().downloadFile(URL(ea.webSource), GlobalData.temp_down_folder, 1024, GlobalData.noIcon)
141 | val dest = File(ea.path)
142 | deleteFile(dest)
143 | Files.copy(location.toPath(), dest.toPath())
144 | ea.checksum = calcCRC32(dest)
145 |
146 | CoreApplication.controller.saveExternal(ea)
147 | }
148 |
149 | fun addSIC()
150 | {
151 | if (!GlobalData.addonFolder.exists())
152 | GlobalData.addonFolder.mkdir()
153 |
154 | var install = GlobalData.addonFolder.path + File.separator + "Synthesized-Implicit-Calculator"
155 |
156 | if (!File(install).exists())
157 | File(install).mkdir()
158 |
159 | install += File.separator + "SynthesisParser.ahk"
160 |
161 | val ea = PAL_External_Addon(-1, "Synthesized Implicit Calculator", "", "", null, "", SIC_DL, determineCMD(File(install)), install, false)
162 |
163 | CoreApplication.controller.showDownloadPopup(File(ea.webSource).name)
164 | val location = FileDownloader().downloadFile(URL(ea.webSource), GlobalData.temp_down_folder, 1024, GlobalData.noIcon)
165 | val dest = File(ea.path)
166 | deleteFile(dest)
167 | Files.copy(location.toPath(), dest.toPath())
168 | ea.checksum = calcCRC32(dest)
169 |
170 | CoreApplication.controller.saveExternal(ea)
171 | }
172 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Filters/FilterBlast.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Filters
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper
4 | import java.io.IOException
5 | import java.io.InputStream
6 | import java.net.HttpURLConnection
7 | import java.net.URL
8 | import java.util.ArrayList
9 |
10 | /**
11 | *
12 | */
13 | data class FilterBlastFilter(
14 | val name: String,
15 | val version: String,
16 | val lastUpdate: String,
17 | val poe_version: String,
18 | val forumThread: String,
19 | val variations: ArrayList
20 | )
21 | {
22 | override fun toString(): String
23 | {
24 | return name
25 | }
26 | }
27 |
28 | data class FilterBlastVariation(val key: String, val fileName: String)
29 |
30 |
31 | object FilterBlast
32 | {
33 | private val FILTER_LIST = "https://filterblast.oversoul.xyz/api/ListFilters/"
34 |
35 | private fun create(input: String): FilterBlastVariation
36 | {
37 | var process = input.replace("{", "")
38 | process = process.replace("}", "")
39 | process = process.replace("\"", "")
40 | val splits = process.split(":")
41 | return FilterBlastVariation(splits[0], splits[1])
42 | }
43 |
44 | fun downloadListOfFilters(): ArrayList
45 | {
46 | val list = ArrayList()
47 |
48 | val url = URL(FILTER_LIST)
49 |
50 | val httpcon = url.openConnection() as HttpURLConnection
51 | httpcon.addRequestProperty("User-Agent", "Mozilla/4.0")
52 |
53 | var foo = convertStreamToString(httpcon.inputStream)
54 | // Remove hidden character from the start.
55 | foo = findValidString(foo)
56 |
57 | //System.out.println(foo);
58 |
59 | val objectMapper = ObjectMapper()
60 | val node = objectMapper.readTree(foo)
61 | val elements = node.elements()
62 | while (elements.hasNext())
63 | {
64 | val variations = ArrayList()
65 | val n = elements.next()
66 | val parts = n.get("Presets").toString().split(",")
67 | val arr = ArrayList()
68 |
69 | for (str in parts)
70 | {
71 | arr.add(create(str))
72 | }
73 |
74 |
75 | val presets = n.get("Presets").elements()
76 | while (presets.hasNext())
77 | {
78 | val no = presets.next()
79 | variations.add(no.toString().replace("\"", ""))
80 | }
81 |
82 | val f = FilterBlastFilter(findKey(n.get("Name").toString().replace("\"", "")), n.get("Version").toString(), n.get("LastUpdate").toString(), n.get("PoEVersion").toString(), n.get("ForumThread").toString(), arr)
83 | list.add(f)
84 | }
85 | return list
86 | }
87 |
88 | private fun findKey(name: String): String
89 | {
90 | return if (name.split("'")[0] == "Highwind")
91 | "ffhighwind"
92 | else if (name.split("'")[0] == "Lumpa")
93 | "Lumpaa"
94 | else if (name.split("'")[0] == "Dsgreat")
95 | "Dsgreat3"
96 | else if (name.split("'")[0] == "Ment")
97 | "ment2008"
98 | else if (name.split("'")[0] == "Vexi")
99 | "Vexivian"
100 | else if (name == "Sayk Loot Filters")
101 | "Sayk"
102 | else if (name == "PoE Default Filter")
103 | "Default"
104 | else
105 | name.split("'")[0]
106 | }
107 |
108 | /**
109 | * Filterblast has some weird things where it adds some weird characters we're gonna try to attempt to remove them.
110 | * @return
111 | */
112 | fun findValidString(`in`: String): String
113 | {
114 | var count = 0
115 | for (c in 0 until `in`.length)
116 | {
117 | if (`in`[c] == '{')
118 | {
119 | break
120 | }
121 | else
122 | {
123 | count++
124 | }
125 | }
126 | return `in`.substring(count)
127 | }
128 |
129 | fun convertStreamToString(`is`: java.io.InputStream): String
130 | {
131 | val s = java.util.Scanner(`is`).useDelimiter("\\A")
132 | return if (s.hasNext()) s.next() else ""
133 | }
134 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Filters/FilterContainer.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Filters
2 |
3 | import PAL2.Addons.Externals
4 | import PAL2.Database.addFilter
5 | import PAL_DataClasses.Filter
6 | import PAL_DataClasses.PAL_External_Addon
7 | import java.io.File
8 |
9 | /**
10 | *
11 | */
12 | object FilterContainer
13 | {
14 | val filters = ArrayList()
15 |
16 | fun makeAnchorData(f: FilterBlastFilter, location: File, web: String, variation: String): Filter
17 | {
18 | val crc32 = Externals.calcCRC32(location)
19 | val db_filter = addFilter(Filter(-1, f.name, crc32, web, location.path, variation))
20 |
21 | return db_filter
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Filters/FilterDownloader.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Filters
2 |
3 | import PAL_DataClasses.Filter
4 | import SystemHandling.deleteFile
5 | import mu.KotlinLogging
6 | import java.io.File
7 | import java.net.HttpURLConnection
8 | import java.net.URL
9 | import java.nio.file.Files
10 |
11 | /**
12 | *
13 | */
14 | private val logger = KotlinLogging.logger {}
15 |
16 | object FilterDownloader
17 | {
18 | val URL_FB_API = "https://filterblast.xyz/api/FilterFile/?filter=!K&preset=!P"
19 |
20 | fun updateFilter(filter: Filter): File?
21 | {
22 | val url = URL(filter.webSource)
23 | val httpConnection = url.openConnection() as HttpURLConnection
24 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
25 | val f = File(filter.path)
26 |
27 | if (f.exists())
28 | {
29 | deleteFile(f)
30 | Files.copy(httpConnection.inputStream, f.toPath())
31 | return f
32 | }
33 | logger.error {"Attempting to update a filter that doesn't exist. ${filter.name}"}
34 | return null
35 | }
36 |
37 | fun downloadFilter(filterVar: String, name: String, filterBlastFilter: FilterBlastFilter): Filter
38 | {
39 | val url_safe = filterVar.replace(" ", "%20")
40 | val sub_url = URL_FB_API.replace("!P", url_safe).replace("!K", name)
41 | val url = URL(sub_url)
42 | val httpConnection = url.openConnection() as HttpURLConnection
43 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
44 | val f = File(GlobalData.loot_filter_path + File.separator + buildFileName(name, filterVar))
45 |
46 | if (f.exists())
47 | deleteFile(f)
48 |
49 | Files.copy(httpConnection.inputStream, f.toPath())
50 | return FilterContainer.makeAnchorData(filterBlastFilter, f, sub_url, filterVar)
51 | }
52 |
53 | fun buildFileName(name: String, key: String): String
54 | {
55 | return "$name - $key.filter"
56 | }
57 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/FunStuff/FunStuff.kt:
--------------------------------------------------------------------------------
1 | package PAL2.FunStuff
2 |
3 | import java.time.LocalDateTime
4 | import java.time.ZoneId
5 | import java.time.ZonedDateTime
6 | import java.time.temporal.ChronoUnit
7 |
8 | /**
9 | *
10 | */
11 | object FunStuff
12 | {
13 | val europe_release = LocalDateTime.of(2019, 6, 7, 22, 0)
14 | val zdt = ZonedDateTime.of(europe_release, ZoneId.of("UTC+2"))
15 | val local_release = zdt.toLocalDateTime()
16 |
17 | fun legionCountDownTimer()
18 | {
19 | // Add Legion Countdowner if it's not yet at the date of the release!
20 | val now = LocalDateTime.now()
21 |
22 | println("days: ${now.until(local_release, ChronoUnit.DAYS)}")
23 |
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/AddonAnchor.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import GlobalData
4 | import PAL2.Addons.Externals
5 | import PAL_DataClasses.PAL_AddonFullData
6 | import SystemHandling.checkForUseableDownloads
7 | import javafx.event.EventHandler
8 | import javafx.scene.image.Image
9 | import javafx.scene.image.ImageView
10 | import javafx.scene.input.MouseButton
11 | import javafx.scene.layout.AnchorPane
12 | import javafx.scene.paint.Color
13 | import javafx.scene.shape.Rectangle
14 | import javafx.scene.text.Text
15 | import javafx.scene.text.TextAlignment
16 | import mu.KotlinLogging
17 | import java.net.URL
18 |
19 | /**
20 | *
21 | */
22 | private val logger = KotlinLogging.logger {}
23 |
24 | class AddonAnchor(var name: String, var version: String, var repo: String, var iconUrl: String, var addonID: Int)
25 | {
26 | lateinit var anchorPane: AnchorPane
27 | lateinit var anchorButtonRight: AnchorPane
28 | lateinit var anchorButtonLeft: AnchorPane
29 | lateinit var icon: ImageView
30 | lateinit var versionText: Text
31 | lateinit var addonText: Text
32 | var rectButtonRight = Rectangle(75.0, 25.0)
33 | var buttonRightText = Text()
34 | var buttonLeftText = Text()
35 | var rectButtonLeft = Rectangle(75.0, 25.0)
36 |
37 | lateinit var repoText: Text
38 |
39 | var activeIcon = ""
40 | var isWebIcon = true
41 |
42 |
43 | init
44 | {
45 | createAnchor()
46 | initImage()
47 | initCreatorText()
48 | initAddonText()
49 | initVersionText()
50 | initButton("Download", anchorButtonLeft, buttonLeftText, rectButtonLeft)
51 | initButton("Info", anchorButtonRight, buttonRightText, rectButtonRight)
52 |
53 | // Attach Listeners
54 | setListners()
55 |
56 |
57 | rectButtonLeft.id = "buttonRect"
58 | buttonLeftText.id = "buttonText"
59 | }
60 |
61 | private fun initButton(arg: String, anchor: AnchorPane, text: Text, rect: Rectangle)
62 | {
63 | text.text = arg
64 | anchor.children.add(text)
65 | text.textAlignment = TextAlignment.CENTER
66 | text.layoutX = 0.0
67 | text.layoutY = 30.0
68 | text.wrappingWidth = 75.0
69 | text.fill = Color.WHITE
70 |
71 | anchor.children.add(rect)
72 | rect.layoutX = 0.0
73 | rect.layoutY = 12.5
74 | rect.stroke = Color.WHITE
75 | rect.fill = Color(1.0, 1.0, 1.0, 0.0)
76 | }
77 |
78 | private fun initVersionText()
79 | {
80 | versionText = Text()
81 | versionText.text = version
82 | anchorPane.children.add(versionText)
83 | versionText.wrappingWidth = 200.0
84 | versionText.fill = Color.WHITE
85 | versionText.layoutY = 38.5
86 | versionText.layoutX = 50.0
87 | }
88 |
89 | private fun initAddonText()
90 | {
91 | addonText = Text()
92 | addonText.text = name
93 | anchorPane.children.add(addonText)
94 | addonText.wrappingWidth = 200.0
95 | addonText.layoutX = 50.0
96 | addonText.layoutY = 22.5
97 | addonText.fill = Color.WHITE
98 | addonText.style = "-fx-font-weight: Bold"
99 | }
100 |
101 | private fun initCreatorText()
102 | {
103 | repoText = Text()
104 | repoText.text = repo
105 | anchorPane.children.add(repoText)
106 | repoText.wrappingWidth = 175.0
107 | repoText.layoutX = 325.0
108 | repoText.layoutY = 22.5
109 | repoText.textAlignment = TextAlignment.CENTER
110 | repoText.fill = Color.WHITE
111 | }
112 |
113 | private fun initImage()
114 | {
115 | icon = ImageView()
116 | anchorPane.children.add(icon)
117 | icon.fitWidth = 40.0
118 | icon.fitHeight = 40.0
119 | icon.layoutX = 4.0
120 | icon.layoutY = 7.5
121 |
122 |
123 | if (iconUrl == "")
124 | {
125 | setImage(icon, "/icons/NoIcon.png")
126 | isWebIcon = false
127 | }
128 | else
129 | {
130 | setURLImage(icon, iconUrl)
131 | isWebIcon = true
132 | }
133 | }
134 |
135 | private fun createAnchor()
136 | {
137 | anchorPane = AnchorPane()
138 | anchorPane.id = "$addonID"
139 | anchorPane.prefWidth = 575.0
140 | anchorButtonRight = AnchorPane()
141 | anchorButtonRight.prefWidth = 75.0
142 | anchorButtonRight.prefHeight = 50.0
143 | anchorButtonRight.layoutX = 500.0
144 | anchorButtonRight.layoutY = 0.0
145 |
146 | anchorButtonLeft = AnchorPane()
147 | anchorButtonLeft.prefHeight = 50.0
148 | anchorButtonLeft.prefWidth = 75.0
149 | anchorButtonLeft.layoutX = 250.0
150 | anchorButtonLeft.layoutY = 0.0
151 |
152 | anchorPane.children.add(anchorButtonLeft)
153 | anchorPane.children.add(anchorButtonRight)
154 | }
155 |
156 | private fun setImage(imageView: ImageView, s: String)
157 | {
158 | activeIcon = s
159 | imageView.image = Image(javaClass.getResource(s).toString())
160 | }
161 |
162 | private fun setURLImage(imageView: ImageView, s: String)
163 | {
164 | imageView.image = Image(s)
165 | }
166 |
167 | private fun setListners()
168 | {
169 | leftButtonListners()
170 | rightButtonListners()
171 | }
172 |
173 |
174 |
175 | fun leftButtonListners()
176 | {
177 | rectButtonLeft.onMouseClicked = EventHandler()
178 | {
179 | if(it.button == MouseButton.PRIMARY)
180 | {
181 | rectButtonLeft.isVisible = false
182 | buttonLeftText.text = "Downloading"
183 | if (Externals.isExternal(addonID))
184 | {
185 | // TODO: Hide download button
186 | when (addonID)
187 | {
188 | 17 -> Externals.addSIC()
189 | 9 -> Externals.addLutBot()
190 | }
191 | buttonLeftText.text = "Installed"
192 | }
193 | else
194 | {
195 | val a = GlobalData.getAddonByID(addonID)
196 | if (a != null)
197 | {
198 | val download_urls = checkForUseableDownloads(a.download_urls, addonID)
199 | if (download_urls.size == 1)
200 | {
201 | CoreApplication.controller.startDownload(download_urls[0], a.aid, icon.image)
202 | }
203 | else
204 | {
205 | var desc = "No description has been set, sorry."
206 |
207 | if (a.description != null)
208 | {
209 | if (a.description is String)
210 | {
211 | desc = a.description!!
212 | }
213 |
214 | }
215 |
216 | CoreApplication.controller.setDescInfo(icon.image, name, desc, addonID)
217 | CoreApplication.controller.showDownloadsPage(download_urls)
218 | }
219 | }
220 | }
221 | }
222 | }
223 |
224 | rectButtonLeft.onMouseEntered = EventHandler()
225 | {
226 | rectButtonLeft.stroke = Color(1.0, 0.0, 1.0, 1.0)
227 | }
228 |
229 | rectButtonLeft.onMouseExited = EventHandler()
230 | {
231 | rectButtonLeft.stroke = Color.WHITE
232 | }
233 | }
234 |
235 | fun rightButtonListners()
236 | {
237 | rectButtonRight.onMouseClicked = EventHandler()
238 | {
239 | if (it.button == MouseButton.PRIMARY)
240 | {
241 | val a = GlobalData.getAddonByID(addonID)
242 | var desc = "No description has been set, sorry."
243 | if (a is PAL_AddonFullData)
244 | {
245 | if (a.description != null)
246 | {
247 | if (a.description is String)
248 | {
249 | desc = a.description!!
250 | }
251 |
252 | }
253 | }
254 | CoreApplication.controller.setDescInfo(icon.image, name, desc, addonID)
255 | }
256 | }
257 |
258 | rectButtonRight.onMouseEntered = EventHandler()
259 | {
260 | rectButtonRight.stroke = Color(1.0, 0.0, 1.0, 1.0)
261 | }
262 |
263 | rectButtonRight.onMouseExited = EventHandler()
264 | {
265 | rectButtonRight.stroke = Color.WHITE
266 | }
267 | }
268 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/CoreApplication.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import javafx.application.Application
4 | import javafx.fxml.FXMLLoader
5 | import javafx.scene.Parent
6 | import javafx.scene.Scene
7 | import javafx.scene.image.Image
8 | import javafx.stage.Stage
9 | import javafx.stage.StageStyle
10 |
11 | /**
12 | *
13 | */
14 | class CoreApplication : Application()
15 | {
16 | companion object
17 | {
18 | lateinit var stage: Stage
19 | lateinit var controller: CoreController
20 | }
21 |
22 | override fun start(primaryStage: Stage?)
23 | {
24 | stage = Stage()
25 | val fxmlLoader = FXMLLoader()
26 | stage.initStyle(StageStyle.UNDECORATED)
27 | val root = fxmlLoader.load(javaClass.getResource("/CoreUI.fxml").openStream())
28 |
29 | controller = fxmlLoader.getController() as CoreController
30 |
31 | stage.title = "PAL: Core"
32 | stage.icons.add(Image(javaClass.getResource("/witch.png").toString()))
33 | val scene = Scene(root, 600.0, 500.0)
34 | scene.stylesheets.add("layout_settings.css")
35 | stage.scene = scene
36 | stage.show()
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/CustomAddonAnchor.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import GlobalData
4 | import PAL2.Addons.Externals
5 | import PAL2.Database.hideExternalAddon
6 | import PAL2.Database.updateExternalAddon
7 | import PAL2.Database.updateRunOnLaunchExternal
8 | import PAL2.SystemHandling.FileDownloader
9 | import PAL2.SystemHandling.taskKill
10 | import PAL_DataClasses.PAL_External_Addon
11 | import SystemHandling.deleteFile
12 | import javafx.application.Platform
13 | import javafx.event.EventHandler
14 | import javafx.scene.control.CheckBox
15 | import javafx.scene.control.ContextMenu
16 | import javafx.scene.control.MenuItem
17 | import javafx.scene.effect.Lighting
18 | import javafx.scene.image.Image
19 | import javafx.scene.image.ImageView
20 | import javafx.scene.input.MouseButton
21 | import javafx.scene.layout.AnchorPane
22 | import javafx.scene.paint.Color
23 | import javafx.scene.shape.Rectangle
24 | import javafx.scene.text.Text
25 | import javafx.scene.text.TextAlignment
26 | import kotlinx.coroutines.GlobalScope
27 | import kotlinx.coroutines.launch
28 | import mu.KotlinLogging
29 | import java.io.BufferedInputStream
30 | import java.io.File
31 | import java.net.HttpURLConnection
32 | import java.net.URL
33 | import java.nio.file.Files
34 |
35 | /**
36 | *
37 | */
38 | private val logger = KotlinLogging.logger {}
39 |
40 | class ExternalAnchor(val externalAddon: PAL_External_Addon)
41 | {
42 | var anchorPane = AnchorPane()
43 | var displayImage = ImageView()
44 | lateinit var textAddonName: Text
45 | lateinit var textNewestVersion: Text
46 | lateinit var textLastCheck: Text
47 | lateinit var textEnabled: Text
48 |
49 | lateinit var bTextVersion: Text
50 | lateinit var bTextLastCheck: Text
51 | lateinit var bTextNewVersion: Text
52 |
53 | lateinit var checkBox: CheckBox
54 |
55 | //var imageViewInfo = ImageView()
56 |
57 | var anchorButton = AnchorPane()
58 | var rectButton = Rectangle(75.0, 25.0)
59 | var textButton = Text()
60 |
61 | // Context Menu
62 | val cUpdate = MenuItem("Check for update")
63 | val update = MenuItem("Update")
64 | val settings = MenuItem("Settings")
65 | val remove = MenuItem("Remove")
66 | val editMenu = ContextMenu(cUpdate, update, settings, remove)
67 |
68 | init
69 | {
70 | anchorPane.id = externalAddon.eid.toString()
71 | initImg()
72 | initTopText()
73 | initBottomText()
74 | initButton()
75 | initCheckBox()
76 | initEditMenu()
77 |
78 | setListners()
79 | updateChecker()
80 | }
81 |
82 | private fun initEditMenu()
83 | {
84 | editMenu.onHidden = EventHandler{GlobalData.contextMenuOpen = false}
85 | cUpdate.onAction = EventHandler{ GlobalScope.launch { updateChecker() } }
86 | settings.onAction = EventHandler { CoreApplication.controller.showSettingsOfExternal(externalAddon) }
87 | update.onAction = EventHandler { updateExternal() }
88 | remove.onAction = EventHandler {
89 | val aid = Externals.isMajorAddon(externalAddon.webSource)
90 | if (aid != 0)
91 | CoreApplication.controller.setDownloadableAddon(aid)
92 | hideExternalAddon(externalAddon.eid)
93 | CoreApplication.controller.removeExternalSelected()
94 | }
95 | }
96 |
97 | private fun updateExternal()
98 | {
99 | // TaskKill
100 | val ext = File(externalAddon.path).extension
101 |
102 | when (ext)
103 | {
104 | "ahk" -> taskKill("autohotkey.exe").waitFor()
105 | "jar" -> taskKill("java").waitFor()
106 | "exe" -> taskKill(File(externalAddon.path).name).waitFor()
107 | }
108 |
109 |
110 | GlobalScope.launch {
111 | CoreApplication.controller.showDownloadPopup(File(externalAddon.webSource).name)
112 | val location = FileDownloader().downloadFile(URL(externalAddon.webSource), GlobalData.temp_down_folder, 1024, GlobalData.noIcon)
113 | val dest = File(externalAddon.path)
114 | deleteFile(dest)
115 | Files.copy(location.toPath(), dest.toPath())
116 |
117 | // Set new CRC32
118 | GlobalScope.launch {
119 | val crc32 = Externals.calcCRC32(dest)
120 | externalAddon.checksum = crc32
121 | bTextNewVersion.text = crc32
122 | updateExternalAddon(externalAddon)
123 | }
124 |
125 |
126 | // Set Icon to green
127 | Platform.runLater { displayImage.effect = LightningEffects.noUpdateLighting() }
128 | }
129 | }
130 |
131 | private fun updateChecker()
132 | {
133 | if (externalAddon.webSource.isEmpty())
134 | return
135 |
136 | Platform.runLater { displayImage.effect = Lighting() }
137 |
138 | val httpConnection = URL(externalAddon.webSource).openConnection() as HttpURLConnection
139 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
140 | val input = BufferedInputStream(httpConnection.inputStream)
141 | val crc32 = Externals.calcCRC32(input.readBytes())
142 |
143 | if (crc32 == externalAddon.checksum)
144 | {
145 | Platform.runLater { displayImage.effect = LightningEffects.noUpdateLighting() }
146 | }
147 | else
148 | {
149 | Platform.runLater { displayImage.effect = LightningEffects.updateAvailLighting() }
150 | }
151 | }
152 |
153 | private fun initCheckBox()
154 | {
155 | checkBox = CheckBox("")
156 | anchorPane.children.add(checkBox)
157 | checkBox.layoutX = 542.5
158 | checkBox.layoutY = 20.0
159 | checkBox.isSelected = externalAddon.runOnLaunch
160 | }
161 |
162 | private fun setListners()
163 | {
164 | anchorListner()
165 | setDownloadUpdateListner()
166 | checkBoxListener()
167 | }
168 |
169 | private fun checkBoxListener()
170 | {
171 | checkBox.onMouseClicked = EventHandler()
172 | {
173 | updateRunOnLaunchExternal(externalAddon.eid, checkBox.isSelected)
174 | }
175 | }
176 |
177 |
178 | fun anchorListner()
179 | {
180 | // TODO: Create Rollbock Update Option
181 |
182 | anchorPane.onMouseClicked = EventHandler()
183 | {
184 | if (it.button == MouseButton.PRIMARY)
185 | {
186 | if (it.clickCount == 2)
187 | {
188 | // TODO: If no launch command show a popup that says that there is no launch command.
189 | GlobalScope.launch {
190 | Runtime.getRuntime().exec(externalAddon.launchCMD)
191 | }
192 | }
193 | }
194 | }
195 | anchorPane.onContextMenuRequested = EventHandler()
196 | {
197 | if (!GlobalData.contextMenuOpen)
198 | {
199 | GlobalData.contextMenuOpen = true
200 | editMenu.show(anchorPane, it.screenX, it.screenY)
201 | }
202 | }
203 | }
204 |
205 | fun setDownloadUpdateListner()
206 | {
207 |
208 | rectButton.onMouseEntered = EventHandler()
209 | {
210 | rectButton.stroke = Color(1.0, 0.0, 1.0, 1.0)
211 | }
212 | rectButton.onMouseExited = EventHandler()
213 | {
214 | rectButton.stroke = Color.WHITE
215 | }
216 | rectButton.onMouseClicked = EventHandler()
217 | {
218 | Platform.runLater {
219 | CoreApplication.controller.showSettingsOfExternal(externalAddon)
220 | }
221 | }
222 | }
223 |
224 |
225 | private fun initButton()
226 | {
227 | textButton.id = "textButton"
228 | rectButton.id = "rectButton"
229 | initButton("Settings", anchorButton, textButton, rectButton)
230 | anchorPane.children.add(anchorButton)
231 | }
232 |
233 | private fun initButton(arg: String, anchor: AnchorPane, text: Text, rect: Rectangle)
234 | {
235 | anchor.layoutX = 240.0
236 | anchor.layoutY = 0.0
237 |
238 | text.text = arg
239 | anchor.children.add(text)
240 | text.textAlignment = TextAlignment.CENTER
241 | text.layoutX = 0.0
242 | text.layoutY = 25.0
243 | text.wrappingWidth = 75.0
244 | text.fill = Color.WHITE
245 |
246 | anchor.children.add(rect)
247 | rect.layoutX = 0.0
248 | rect.layoutY = 7.5
249 | rect.stroke = Color.WHITE
250 | rect.fill = Color(1.0, 1.0, 1.0, 0.0)
251 | }
252 |
253 | // Drive letter :/ FileName.ext
254 | fun shortner(maxChars: Int, string: String): String
255 | {
256 | if (string.length < maxChars)
257 | return string
258 |
259 | val f = File(string)
260 | val splits = string.split(File.separator)
261 |
262 | return if (splits[0].length + splits[splits.size-1].length < maxChars - 5)
263 | {
264 | "${splits[0]}${File.separator}...${File.separator}${splits[splits.size-1]}"
265 | }
266 | else
267 | {
268 | when
269 | {
270 | f.name.length < maxChars -> f.name
271 | f.nameWithoutExtension.length < maxChars -> f.nameWithoutExtension
272 | else -> ""
273 | }
274 | }
275 |
276 | }
277 |
278 | private fun initBottomText()
279 | {
280 | // TODO: middle ... for x size
281 | bTextVersion = bottomTextFactory(shortner(50, externalAddon.path), 40.0, 200.0)
282 | bTextVersion.textAlignment = TextAlignment.LEFT
283 | bTextVersion.id = "bTextVersion"
284 | bTextLastCheck = bottomTextFactory(monthToNum(externalAddon.eid.toString()), 425.0, 100.0)
285 | bTextLastCheck.id = "bTextLastCheck"
286 |
287 | bTextNewVersion = bottomTextFactory(externalAddon.checksum, 325.0, 100.0)
288 |
289 | anchorPane.children.addAll(bTextVersion, bTextLastCheck, bTextNewVersion)
290 | }
291 |
292 | private fun monthToNum(arg: String): String
293 | {
294 | when (true)
295 | {
296 | arg.toLowerCase().contains("january") -> return arg.replace("JANUARY", "01")
297 | arg.toLowerCase().contains("february") -> return arg.replace("FEBRUARY", "02")
298 | arg.toLowerCase().contains("march") -> return arg.replace("MARCH", "03")
299 | arg.toLowerCase().contains("april") -> return arg.replace("APRIL", "04")
300 | arg.toLowerCase().contains("may") -> return arg.replace("MAY", "05")
301 | arg.toLowerCase().contains("june") -> return arg.replace("JUNE", "06")
302 | arg.toLowerCase().contains("july") -> return arg.replace("july", "07")
303 | arg.toLowerCase().contains("august") -> return arg.replace("AUGUST", "08")
304 | arg.toLowerCase().contains("september") -> return arg.replace("SEPTEMBER", "09")
305 | arg.toLowerCase().contains("october") -> return arg.replace("OCTOBER", "10")
306 | arg.toLowerCase().contains("november") -> return arg.replace("NOVEMBER", "11")
307 | arg.toLowerCase().contains("december") -> return arg.replace("DECEMBER", "12")
308 | else -> return arg
309 | }
310 | }
311 |
312 |
313 | private fun initTopText()
314 | {
315 | textAddonName = textTopFactory(externalAddon.name, 40.0, 200.0)
316 | textAddonName.id = "textAddonName"
317 | textAddonName.textAlignment = TextAlignment.LEFT
318 | textNewestVersion = textTopFactory("CRC32", 325.0, 100.0)
319 | textLastCheck = textTopFactory("EID", 425.0, 100.0)
320 | textEnabled = textTopFactory("Enabled", 525.0, 50.0)
321 |
322 | anchorPane.children.addAll(textAddonName, textNewestVersion, textLastCheck, textEnabled)
323 | }
324 |
325 | fun bottomTextFactory(arg: String, x: Double, ww: Double): Text
326 | {
327 | val text = Text()
328 | text.layoutX = x
329 | text.layoutY = 32.5
330 | text.wrappingWidth = ww
331 | text.textAlignment = TextAlignment.CENTER
332 | text.text = arg
333 | text.fill = Color.WHITE
334 | return text
335 | }
336 |
337 | fun textTopFactory(arg: String, x: Double, ww: Double): Text
338 | {
339 | val text = Text()
340 | text.fill = Color.WHITE
341 | text.layoutX = x
342 | text.layoutY = 15.0
343 | text.style = "-fx-font-weight: Bold;"
344 | text.text = arg
345 | text.wrappingWidth = ww
346 | text.textAlignment = TextAlignment.CENTER
347 | return text
348 | }
349 |
350 | fun initImg()
351 | {
352 | /*
353 | imageViewInfo.layoutX = 530.0
354 | imageViewInfo.layoutY = 2.5
355 | imageViewInfo.fitHeight = 35.0
356 | imageViewInfo.fitWidth = 35.0
357 | imageViewInfo.image = Image(javaClass.getResource("/icons/gggAproveQ.png").openStream())
358 | anchorPane.children.add(imageViewInfo)*/
359 |
360 | displayImage.layoutX = 2.5
361 | displayImage.layoutY = 2.5
362 | displayImage.fitWidth = 35.0
363 | displayImage.fitHeight = 35.0
364 | displayImage.id = "imageInfo"
365 |
366 | logger.debug{"${externalAddon.name} | ${externalAddon.iconUrl}"}
367 |
368 | // TODO: Use IconURL
369 |
370 | displayImage.image = Image(javaClass.getResource("/icons/NoIcon.png").openStream())
371 | anchorPane.children.add(displayImage)
372 | }
373 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/DownloadsAnchor.kt:
--------------------------------------------------------------------------------
1 | package GUI
2 |
3 | import PAL2.GUI.CoreApplication
4 | import javafx.application.Application
5 | import javafx.application.Platform
6 | import javafx.fxml.FXML
7 | import javafx.fxml.FXMLLoader
8 | import javafx.fxml.Initializable
9 | import javafx.scene.Parent
10 | import javafx.scene.Scene
11 | import javafx.scene.control.ListView
12 | import javafx.scene.control.ProgressBar
13 | import javafx.scene.image.Image
14 | import javafx.scene.image.ImageView
15 | import javafx.scene.layout.AnchorPane
16 | import javafx.scene.paint.Color
17 | import javafx.scene.text.Font
18 | import javafx.scene.text.Text
19 | import javafx.stage.Stage
20 | import javafx.stage.StageStyle
21 | import mu.KotlinLogging
22 | import java.net.URL
23 | import java.util.*
24 |
25 | private val logger = KotlinLogging.logger {}
26 | /**
27 | *
28 | */
29 | class DownloadsAnchor(val text: String)
30 | {
31 | init
32 | {
33 | createAnchor()
34 | createImageView()
35 | createProgressBar()
36 | createAddonText()
37 | createSideImages()
38 | }
39 |
40 | private fun createSideImages()
41 | {
42 | upArrowImg = ImageView()
43 | hideImg = ImageView()
44 | downArrowImg = ImageView()
45 |
46 | anchorPane.children.addAll(upArrowImg, hideImg, downArrowImg)
47 |
48 | upArrowImg.layoutY = 2.5
49 | upArrowImg.layoutX = 2.0
50 | upArrowImg.fitHeight = 15.0
51 | upArrowImg.fitWidth = 15.0
52 |
53 | downArrowImg.layoutY = 37.5
54 | downArrowImg.layoutX = 2.0
55 | downArrowImg.fitHeight = 15.0
56 | downArrowImg.fitWidth = 15.0
57 |
58 | hideImg.layoutY = 20.0
59 | hideImg.layoutX = 2.0
60 | hideImg.fitHeight = 15.0
61 | hideImg.fitWidth = 15.0
62 |
63 | upArrowImg.image = Image(javaClass.getResource("/icons/upArrow.png").openStream())
64 | downArrowImg.image = Image(javaClass.getResource("/icons/downArrow.png").openStream())
65 | hideImg.image = Image(javaClass.getResource("/icons/minus.png").openStream())
66 | }
67 |
68 | lateinit var anchorPane: AnchorPane
69 | lateinit var imageView: ImageView
70 | lateinit var progressBar: ProgressBar
71 | lateinit var addonText: Text
72 | lateinit var upArrowImg: ImageView
73 | lateinit var downArrowImg: ImageView
74 | lateinit var hideImg: ImageView
75 | val template = "%n | %p"
76 | val font = Font("System Bold", 14.0)
77 |
78 | fun createAnchor()
79 | {
80 | anchorPane = AnchorPane()
81 | }
82 |
83 | fun createAddonText()
84 | {
85 | addonText = Text()
86 | addonText.style = "-fx-font-size: 14; -fx-font-weight: Bold;"
87 | anchorPane.children.add(addonText)
88 | addonText.text = text
89 | addonText.layoutX = 75.0
90 | addonText.layoutY = 22.0
91 | addonText.wrappingWidth = 520.0
92 | addonText.fill = Color.WHITE
93 | }
94 |
95 | fun createProgressBar()
96 | {
97 | progressBar = ProgressBar()
98 | anchorPane.children.add(progressBar)
99 | progressBar.layoutX = 75.0
100 | progressBar.layoutY = 32.0
101 | progressBar.prefWidth = 500.0
102 | progressBar.prefHeight = 18.0
103 | }
104 |
105 | fun createImageView()
106 | {
107 | imageView = ImageView()
108 | anchorPane.children.add(imageView)
109 | imageView.fitWidth = 50.0
110 | imageView.fitHeight = 50.0
111 | imageView.layoutX = 20.0
112 | imageView.layoutY = 2.5
113 | }
114 |
115 | fun setProgress(d: Double)
116 | {
117 | Platform.runLater { progressBar.progress = d }
118 | }
119 |
120 | fun addDownloadText(str: String)
121 | {
122 | Platform.runLater { addonText.text = template.replace("%n", text).replace("%p", str) }
123 | }
124 |
125 | fun setImg(image: Image)
126 | {
127 | Platform.runLater { imageView.image = image }
128 | }
129 |
130 | fun attachToListView()
131 | {
132 | CoreApplication.controller.addActiveDownload(this)
133 | }
134 |
135 | fun setName(str: String)
136 | {
137 | Platform.runLater { addonText.text = str }
138 | }
139 | }
140 |
141 | class DownloadTemplateController: Initializable
142 | {
143 | override fun initialize(location: URL?, resources: ResourceBundle?)
144 | {
145 |
146 | }
147 |
148 | fun updateProgressbar(d: Double)
149 | {
150 | Platform.runLater { progressBarDownload.progress = d }
151 | }
152 |
153 | @FXML
154 | private lateinit var anchor: AnchorPane
155 |
156 | @FXML
157 | private lateinit var addonIcon: ImageView
158 |
159 | @FXML
160 | private lateinit var addonName: Text
161 |
162 | @FXML
163 | private lateinit var progressBarDownload: ProgressBar
164 | }
165 |
166 | class AnchorTest : Application()
167 | {
168 | companion object
169 | {
170 | lateinit var stage: Stage
171 | lateinit var controller: DownloadTemplateController
172 | lateinit var listView: ListView
173 | }
174 | override fun start(primaryStage: Stage?)
175 | {
176 | val fxmlLoader = FXMLLoader()
177 | controller = DownloadTemplateController()
178 |
179 | /*
180 | val arrayList = ArrayList()
181 | fxmlLoader.setController(controller)
182 | for (c in 0..4)
183 | {
184 | arrayList.add(fxmlLoader.load(javaClass.getResource("/downloadTemplate.fxml").openStream()))
185 | }*/
186 |
187 | var anchorPane = AnchorPane()
188 | listView = ListView()
189 |
190 | anchorPane.children.add(listView)
191 | listView.prefWidth = 600.0
192 |
193 | stage = Stage()
194 | stage.initStyle(StageStyle.UNDECORATED)
195 | stage.icons.add(Image(javaClass.getResource("/witch.png").toString()))
196 | val scene = Scene(anchorPane, 600.0, 500.0)
197 | scene.stylesheets.add("layout_settings.css")
198 | stage.initStyle(StageStyle.TRANSPARENT)
199 | scene.fill = Color.TRANSPARENT
200 | stage.scene = scene
201 | stage.isAlwaysOnTop = true
202 | stage.x = 0.0
203 | stage.show()
204 | }
205 |
206 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/FilterAnchor.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import PAL2.Addons.Externals
4 | import PAL2.Database.*
5 | import PAL2.Filters.FilterDownloader
6 | import PAL2.SystemHandling.FileDownloader
7 | import PAL2.SystemHandling.taskKill
8 | import PAL_DataClasses.Filter
9 | import PAL_DataClasses.PAL_External_Addon
10 | import SystemHandling.deleteFile
11 | import javafx.application.Platform
12 | import javafx.event.EventHandler
13 | import javafx.scene.control.CheckBox
14 | import javafx.scene.control.ContextMenu
15 | import javafx.scene.control.MenuItem
16 | import javafx.scene.effect.Lighting
17 | import javafx.scene.image.Image
18 | import javafx.scene.image.ImageView
19 | import javafx.scene.input.MouseButton
20 | import javafx.scene.layout.AnchorPane
21 | import javafx.scene.paint.Color
22 | import javafx.scene.shape.Rectangle
23 | import javafx.scene.text.Text
24 | import javafx.scene.text.TextAlignment
25 | import kotlinx.coroutines.GlobalScope
26 | import kotlinx.coroutines.launch
27 | import mu.KotlinLogging
28 | import java.io.BufferedInputStream
29 | import java.io.File
30 | import java.net.HttpURLConnection
31 | import java.net.URL
32 | import java.nio.file.Files
33 |
34 | /**
35 | *
36 | */
37 | private val logger = KotlinLogging.logger {}
38 |
39 | class FilterAnchor(val filter: Filter)
40 | {
41 | var anchorPane = AnchorPane()
42 | var displayImage = ImageView()
43 | lateinit var textAddonName: Text
44 | lateinit var textNewestVersion: Text
45 | lateinit var textLastCheck: Text
46 |
47 | lateinit var bTextVersion: Text
48 | lateinit var bTextLastCheck: Text
49 | lateinit var bTextNewVersion: Text
50 |
51 | //var imageViewInfo = ImageView()
52 |
53 | var anchorButton = AnchorPane()
54 | var rectButton = Rectangle(75.0, 25.0)
55 | var textButton = Text()
56 |
57 | // Context Menu
58 | val cUpdate = MenuItem("Check for update")
59 | val update = MenuItem("Update")
60 | val remove = MenuItem("Remove")
61 | val editMenu = ContextMenu(cUpdate, update, remove)
62 |
63 | init
64 | {
65 | anchorPane.id = filter.fid.toString()
66 | initImg()
67 | initTopText()
68 | initBottomText()
69 | initButton()
70 | initEditMenu()
71 |
72 | setListners()
73 | updateChecker()
74 | }
75 |
76 | private fun initEditMenu()
77 | {
78 | editMenu.onHidden = EventHandler{GlobalData.contextMenuOpen = false}
79 | cUpdate.onAction = EventHandler{ GlobalScope.launch { updateChecker() } }
80 | update.onAction = EventHandler { updateExternal() }
81 | remove.onAction = EventHandler { removeFilter() }
82 | }
83 |
84 | fun updateExternal()
85 | {
86 | logger.debug { "Syncing ${filter.name} - ${filter.variation}" }
87 | GlobalScope.launch {
88 | CoreApplication.controller.showDownloadPopup(File(filter.path).name)
89 |
90 | val dest = FilterDownloader.updateFilter(filter) ?: return@launch
91 |
92 | // Set new CRC32
93 | GlobalScope.launch {
94 | val crc32 = Externals.calcCRC32(dest)
95 | filter.crc32 = crc32
96 | updateFilter(filter)
97 | }
98 |
99 |
100 | // Set Icon to green
101 | Platform.runLater { displayImage.effect = LightningEffects.noUpdateLighting() }
102 | }
103 | }
104 |
105 | private fun updateChecker()
106 | {
107 | if (filter.webSource.isEmpty())
108 | return
109 |
110 | Platform.runLater { displayImage.effect = Lighting() }
111 |
112 | val httpConnection = URL(filter.webSource).openConnection() as HttpURLConnection
113 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
114 | val input = BufferedInputStream(httpConnection.inputStream)
115 | val crc32 = Externals.calcCRC32(input.readBytes())
116 |
117 | if (crc32 == filter.crc32)
118 | {
119 | Platform.runLater { displayImage.effect = LightningEffects.noUpdateLighting() }
120 | }
121 | else
122 | {
123 | Platform.runLater { displayImage.effect = LightningEffects.updateAvailLighting() }
124 | }
125 | }
126 |
127 |
128 | private fun setListners()
129 | {
130 | anchorListner()
131 | setDownloadUpdateListner()
132 | }
133 |
134 |
135 | fun anchorListner()
136 | {
137 | /*
138 | anchorPane.onMouseClicked = EventHandler()
139 | {
140 | if (it.button == MouseButton.PRIMARY)
141 | {
142 | if (it.clickCount == 2)
143 | {
144 | // TODO: If no launch command show a popup that says that there is no launch command.
145 | GlobalScope.launch {
146 | Runtime.getRuntime().exec(externalAddon.launchCMD)
147 | }
148 | }
149 | }
150 | }*/
151 | anchorPane.onContextMenuRequested = EventHandler()
152 | {
153 | if (!GlobalData.contextMenuOpen)
154 | {
155 | GlobalData.contextMenuOpen = true
156 | editMenu.show(anchorPane, it.screenX, it.screenY)
157 | }
158 | }
159 | }
160 |
161 | fun setDownloadUpdateListner()
162 | {
163 |
164 | rectButton.onMouseEntered = EventHandler()
165 | {
166 | rectButton.stroke = Color(1.0, 0.0, 1.0, 1.0)
167 | }
168 | rectButton.onMouseExited = EventHandler()
169 | {
170 | rectButton.stroke = Color.WHITE
171 | }
172 | rectButton.onMouseClicked = EventHandler()
173 | {
174 | removeFilter()
175 | }
176 | }
177 |
178 | private fun removeFilter()
179 | {
180 | // Delete from DB
181 | deleteFilterFromDB(filter.fid)
182 |
183 | // Delete from Harddrive
184 | val file = File(filter.path)
185 | if (file.isDirectory)
186 | logger.error { "SEVERE ERROR, FILTER PATH IS A DIRECTORY!" }
187 | else if (file.isFile)
188 | deleteFile(File(filter.path))
189 |
190 | // Delete from UI
191 | CoreApplication.controller.removeFilterAnchor()
192 | }
193 |
194 |
195 | private fun initButton()
196 | {
197 | textButton.id = "textButton"
198 | rectButton.id = "rectButton"
199 | initButton("Remove", anchorButton, textButton, rectButton)
200 | anchorPane.children.add(anchorButton)
201 | }
202 |
203 | private fun initButton(arg: String, anchor: AnchorPane, text: Text, rect: Rectangle)
204 | {
205 | anchor.layoutX = 490.0
206 | anchor.layoutY = 0.0
207 |
208 | text.text = arg
209 | anchor.children.add(text)
210 | text.textAlignment = TextAlignment.CENTER
211 | text.layoutX = 0.0
212 | text.layoutY = 25.0
213 | text.wrappingWidth = 75.0
214 | text.fill = Color.WHITE
215 |
216 | anchor.children.add(rect)
217 | rect.layoutX = 0.0
218 | rect.layoutY = 7.5
219 | rect.stroke = Color.WHITE
220 | rect.fill = Color(1.0, 1.0, 1.0, 0.0)
221 | }
222 |
223 | // Drive letter :/ FileName.ext
224 | fun shortner(maxChars: Int, string: String): String
225 | {
226 | if (string.length < maxChars)
227 | return string
228 |
229 | val f = File(string)
230 | val splits = string.split(File.separator)
231 |
232 | return if (splits[0].length + splits[splits.size-1].length < maxChars - 5)
233 | {
234 | "${splits[0]}${File.separator}...${File.separator}${splits[splits.size-1]}"
235 | }
236 | else
237 | {
238 | when
239 | {
240 | f.name.length < maxChars -> f.name
241 | f.nameWithoutExtension.length < maxChars -> f.nameWithoutExtension
242 | else -> ""
243 | }
244 | }
245 |
246 | }
247 |
248 | private fun initBottomText()
249 | {
250 | // TODO: middle ... for x size
251 | bTextVersion = bottomTextFactory(shortner(50, filter.path), 40.0, 300.0)
252 | bTextVersion.textAlignment = TextAlignment.LEFT
253 | bTextVersion.id = "bTextVersion"
254 | bTextLastCheck = bottomTextFactory(monthToNum(filter.fid.toString()), 395.0, 100.0)
255 | bTextLastCheck.id = "bTextLastCheck"
256 |
257 | bTextNewVersion = bottomTextFactory(filter.crc32, 325.0, 100.0)
258 |
259 | anchorPane.children.addAll(bTextVersion, bTextLastCheck, bTextNewVersion)
260 | }
261 |
262 | private fun monthToNum(arg: String): String
263 | {
264 | when (true)
265 | {
266 | arg.toLowerCase().contains("january") -> return arg.replace("JANUARY", "01")
267 | arg.toLowerCase().contains("february") -> return arg.replace("FEBRUARY", "02")
268 | arg.toLowerCase().contains("march") -> return arg.replace("MARCH", "03")
269 | arg.toLowerCase().contains("april") -> return arg.replace("APRIL", "04")
270 | arg.toLowerCase().contains("may") -> return arg.replace("MAY", "05")
271 | arg.toLowerCase().contains("june") -> return arg.replace("JUNE", "06")
272 | arg.toLowerCase().contains("july") -> return arg.replace("july", "07")
273 | arg.toLowerCase().contains("august") -> return arg.replace("AUGUST", "08")
274 | arg.toLowerCase().contains("september") -> return arg.replace("SEPTEMBER", "09")
275 | arg.toLowerCase().contains("october") -> return arg.replace("OCTOBER", "10")
276 | arg.toLowerCase().contains("november") -> return arg.replace("NOVEMBER", "11")
277 | arg.toLowerCase().contains("december") -> return arg.replace("DECEMBER", "12")
278 | else -> return arg
279 | }
280 | }
281 |
282 |
283 | private fun initTopText()
284 | {
285 | textAddonName = textTopFactory(filter.name + " - " + filter.variation, 40.0, 300.0)
286 | textAddonName.id = "textAddonName"
287 | textAddonName.textAlignment = TextAlignment.LEFT
288 | textNewestVersion = textTopFactory("CRC32", 325.0, 100.0)
289 | textLastCheck = textTopFactory("FID", 395.0, 100.0)
290 |
291 | anchorPane.children.addAll(textAddonName, textNewestVersion, textLastCheck)
292 | }
293 |
294 | fun bottomTextFactory(arg: String, x: Double, ww: Double): Text
295 | {
296 | val text = Text()
297 | text.layoutX = x
298 | text.layoutY = 32.5
299 | text.wrappingWidth = ww
300 | text.textAlignment = TextAlignment.CENTER
301 | text.text = arg
302 | text.fill = Color.WHITE
303 | return text
304 | }
305 |
306 | fun textTopFactory(arg: String, x: Double, ww: Double): Text
307 | {
308 | val text = Text()
309 | text.fill = Color.WHITE
310 | text.layoutX = x
311 | text.layoutY = 15.0
312 | text.style = "-fx-font-weight: Bold;"
313 | text.text = arg
314 | text.wrappingWidth = ww
315 | text.textAlignment = TextAlignment.CENTER
316 | return text
317 | }
318 |
319 | fun initImg()
320 | {
321 | /*
322 | imageViewInfo.layoutX = 530.0
323 | imageViewInfo.layoutY = 2.5
324 | imageViewInfo.fitHeight = 35.0
325 | imageViewInfo.fitWidth = 35.0
326 | imageViewInfo.image = Image(javaClass.getResource("/icons/gggAproveQ.png").openStream())
327 | anchorPane.children.add(imageViewInfo)*/
328 |
329 | displayImage.layoutX = 2.5
330 | displayImage.layoutY = 2.5
331 | displayImage.fitWidth = 35.0
332 | displayImage.fitHeight = 35.0
333 | displayImage.id = "imageInfo"
334 |
335 | displayImage.image = Image(javaClass.getResource("/icons/NoIcon.png").openStream())
336 | anchorPane.children.add(displayImage)
337 | }
338 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/InstalledAnchor.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import GlobalData
4 | import PAL2.Database.getRunAddonOnLaunch
5 | import PAL2.Database.updateRunAddonWhenLaunching
6 | import PAL2.SystemHandling.launchAddon
7 | import PAL2.SystemHandling.updateAddon
8 | import javafx.application.Platform
9 | import javafx.event.EventHandler
10 | import javafx.scene.control.CheckBox
11 | import javafx.scene.image.Image
12 | import javafx.scene.image.ImageView
13 | import javafx.scene.input.MouseButton
14 | import javafx.scene.layout.AnchorPane
15 | import javafx.scene.paint.Color
16 | import javafx.scene.shape.Rectangle
17 | import javafx.scene.text.Text
18 | import javafx.scene.text.TextAlignment
19 | import mu.KotlinLogging
20 |
21 | /**
22 | *
23 | */
24 | private val logger = KotlinLogging.logger {}
25 |
26 | class InstalledAnchor(var aid: Int, var iconUrl: String?, var addonName: String, var version: String, var newestVersion: String, var lastCheck: String, var website: String)
27 | {
28 | var anchorPane = AnchorPane()
29 | var displayImage = ImageView()
30 | lateinit var textAddonName: Text
31 | lateinit var textNewestVersion: Text
32 | lateinit var textLastCheck: Text
33 | lateinit var textEnabled: Text
34 |
35 | lateinit var bTextVersion: Text
36 | lateinit var bTextLastCheck: Text
37 | lateinit var bTextNewVersion: Text
38 |
39 | lateinit var checkBox: CheckBox
40 |
41 | //var imageViewInfo = ImageView()
42 |
43 | var anchorButton = AnchorPane()
44 | var rectButton = Rectangle(75.0, 25.0)
45 | var textButton = Text()
46 |
47 | init
48 | {
49 | anchorPane.id = aid.toString()
50 | initImg()
51 | initTopText()
52 | initBottomText()
53 | initButton()
54 | initCheckBox()
55 |
56 | // Check up to date
57 | if (version == newestVersion)
58 | {
59 | this.isUpToDate()
60 | }
61 | else
62 | {
63 | this.canBeUpdated()
64 | }
65 |
66 | setListners()
67 | }
68 |
69 | private fun initCheckBox()
70 | {
71 | checkBox = CheckBox("")
72 | anchorPane.children.add(checkBox)
73 | checkBox.layoutX = 542.5
74 | checkBox.layoutY = 20.0
75 | checkBox.isSelected = getRunAddonOnLaunch(aid)
76 | }
77 |
78 | private fun setListners()
79 | {
80 | anchorListner()
81 | setDownloadUpdateListner()
82 | checkBoxListener()
83 | }
84 |
85 | private fun checkBoxListener()
86 | {
87 | checkBox.onMouseClicked = EventHandler()
88 | {
89 | updateRunAddonWhenLaunching(checkBox.isSelected, aid)
90 | }
91 | }
92 |
93 | fun anchorListner()
94 | {
95 | anchorPane.onMouseClicked = EventHandler()
96 | {
97 | if (it.button == MouseButton.PRIMARY)
98 | {
99 | if (it.clickCount == 2)
100 | {
101 | launchAddon(aid)
102 | }
103 | }
104 | }
105 | }
106 |
107 | fun setDownloadUpdateListner()
108 | {
109 | rectButton.onMouseEntered = EventHandler()
110 | {
111 | rectButton.stroke = Color(1.0, 0.0, 1.0, 1.0)
112 | }
113 | rectButton.onMouseExited = EventHandler()
114 | {
115 | rectButton.stroke = Color.WHITE
116 | }
117 | rectButton.onMouseClicked = EventHandler()
118 | {
119 | Platform.runLater {
120 | rectButton.isVisible = false
121 | textButton.text = "Downloading"
122 | updateAddon(aid, displayImage.image)
123 | }
124 | }
125 | }
126 |
127 | fun checkUpdateAble()
128 | {
129 | val most_recent = GlobalData.getAddonByID(aid)?: return
130 | if (most_recent.version_text != version)
131 | {
132 | canBeUpdated()
133 | }
134 | else
135 | {
136 | isUpToDate()
137 | }
138 | }
139 |
140 | fun isUpToDate()
141 | {
142 | Platform.runLater {
143 | rectButton.isVisible = false
144 | textButton.text = "Up-to-date"
145 | textButton.textAlignment = TextAlignment.CENTER
146 | textButton.layoutY = 25.0
147 | }
148 | }
149 |
150 | fun canBeUpdated()
151 | {
152 | Platform.runLater {
153 | rectButton.isVisible = true
154 | textButton.text = "Update"
155 | textButton.layoutY = 25.0
156 | }
157 | }
158 | /*
159 | fun isGGGAproved()
160 | {
161 | Platform.runLater {
162 | imageViewInfo.image = Image(javaClass.getResource("/icons/gggAprove.png").openStream())
163 | }
164 | }
165 |
166 | fun isGGGunknown()
167 | {
168 | Platform.runLater {
169 | imageViewInfo.image = Image(javaClass.getResource("/icons/gggAproveQ.png").openStream())
170 | }
171 | }*/
172 |
173 | private fun initButton()
174 | {
175 | textButton.id = "textButton"
176 | rectButton.id = "rectButton"
177 | initButton("Update", anchorButton, textButton, rectButton)
178 | anchorPane.children.add(anchorButton)
179 | }
180 |
181 | private fun initButton(arg: String, anchor: AnchorPane, text: Text, rect: Rectangle)
182 | {
183 | anchor.layoutX = 240.0
184 | anchor.layoutY = 0.0
185 |
186 | text.text = arg
187 | anchor.children.add(text)
188 | text.textAlignment = TextAlignment.CENTER
189 | text.layoutX = 0.0
190 | text.layoutY = 25.0
191 | text.wrappingWidth = 75.0
192 | text.fill = Color.WHITE
193 |
194 | anchor.children.add(rect)
195 | rect.layoutX = 0.0
196 | rect.layoutY = 7.5
197 | rect.stroke = Color.WHITE
198 | rect.fill = Color(1.0, 1.0, 1.0, 0.0)
199 | }
200 |
201 | private fun initBottomText()
202 | {
203 | bTextVersion = bottomTextFactory(version, 40.0, 200.0)
204 | bTextVersion.textAlignment = TextAlignment.LEFT
205 | bTextVersion.id = "bTextVersion"
206 | bTextLastCheck = bottomTextFactory(monthToNum(lastCheck), 425.0, 100.0)
207 | bTextLastCheck.id = "bTextLastCheck"
208 |
209 | bTextNewVersion = bottomTextFactory(newestVersion, 325.0, 100.0)
210 |
211 | anchorPane.children.addAll(bTextVersion, bTextLastCheck, bTextNewVersion)
212 | }
213 |
214 | private fun monthToNum(arg: String): String
215 | {
216 | when (true)
217 | {
218 | arg.toLowerCase().contains("january") -> return arg.replace("JANUARY", "01")
219 | arg.toLowerCase().contains("february") -> return arg.replace("FEBRUARY", "02")
220 | arg.toLowerCase().contains("march") -> return arg.replace("MARCH", "03")
221 | arg.toLowerCase().contains("april") -> return arg.replace("APRIL", "04")
222 | arg.toLowerCase().contains("may") -> return arg.replace("MAY", "05")
223 | arg.toLowerCase().contains("june") -> return arg.replace("JUNE", "06")
224 | arg.toLowerCase().contains("july") -> return arg.replace("july", "07")
225 | arg.toLowerCase().contains("august") -> return arg.replace("AUGUST", "08")
226 | arg.toLowerCase().contains("september") -> return arg.replace("SEPTEMBER", "09")
227 | arg.toLowerCase().contains("october") -> return arg.replace("OCTOBER", "10")
228 | arg.toLowerCase().contains("november") -> return arg.replace("NOVEMBER", "11")
229 | arg.toLowerCase().contains("december") -> return arg.replace("DECEMBER", "12")
230 | else -> return arg
231 | }
232 | }
233 |
234 |
235 | private fun initTopText()
236 | {
237 | textAddonName = textTopFactory(addonName, 40.0, 200.0)
238 | textAddonName.id = "textAddonName"
239 | textAddonName.textAlignment = TextAlignment.LEFT
240 | textNewestVersion = textTopFactory("Newest Version", 325.0, 100.0)
241 | textLastCheck = textTopFactory("Last Check", 425.0, 100.0)
242 | textEnabled = textTopFactory("Enabled", 525.0, 50.0)
243 |
244 | anchorPane.children.addAll(textAddonName, textNewestVersion, textLastCheck, textEnabled)
245 | }
246 |
247 | fun bottomTextFactory(arg: String, x: Double, ww: Double): Text
248 | {
249 | val text = Text()
250 | text.layoutX = x
251 | text.layoutY = 32.5
252 | text.wrappingWidth = ww
253 | text.textAlignment = TextAlignment.CENTER
254 | text.text = arg
255 | text.fill = Color.WHITE
256 | return text
257 | }
258 |
259 | fun textTopFactory(arg: String, x: Double, ww: Double): Text
260 | {
261 | val text = Text()
262 | text.fill = Color.WHITE
263 | text.layoutX = x
264 | text.layoutY = 15.0
265 | text.style = "-fx-font-weight: Bold;"
266 | text.text = arg
267 | text.wrappingWidth = ww
268 | text.textAlignment = TextAlignment.CENTER
269 | return text
270 | }
271 |
272 | fun initImg()
273 | {
274 | /*
275 | imageViewInfo.layoutX = 530.0
276 | imageViewInfo.layoutY = 2.5
277 | imageViewInfo.fitHeight = 35.0
278 | imageViewInfo.fitWidth = 35.0
279 | imageViewInfo.image = Image(javaClass.getResource("/icons/gggAproveQ.png").openStream())
280 | anchorPane.children.add(imageViewInfo)*/
281 |
282 | displayImage.layoutX = 2.5
283 | displayImage.layoutY = 2.5
284 | displayImage.fitWidth = 35.0
285 | displayImage.fitHeight = 35.0
286 | displayImage.id = "imageInfo"
287 |
288 | logger.debug{"$addonName | $iconUrl"}
289 |
290 | if (iconUrl == null)
291 | {
292 | displayImage.image = Image(javaClass.getResource("/icons/NoIcon.png").openStream())
293 | }
294 | else
295 | {
296 | if (iconUrl == "")
297 | {
298 | displayImage.image = Image(javaClass.getResource("/icons/NoIcon.png").openStream())
299 | }
300 | else
301 | {
302 | displayImage.image = Image(iconUrl)
303 | }
304 | }
305 | anchorPane.children.add(displayImage)
306 | }
307 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/LightningEffects.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import javafx.scene.effect.Light
4 | import javafx.scene.effect.Lighting
5 | import javafx.scene.paint.Color
6 |
7 | /**
8 | *
9 | */
10 | object LightningEffects
11 | {
12 | fun noUpdateLighting(): Lighting
13 | {
14 | val l = Lighting()
15 | l.diffuseConstant = 2.0
16 | l.specularConstant = 0.0
17 | l.specularExponent = 0.0
18 | l.surfaceScale = 0.0
19 | l.light = Light.Distant()
20 | l.light.color = Color.color(0.0/255.0, 119.0/255.0, 42.0/255.0)
21 | return l
22 | }
23 |
24 | fun updateAvailLighting(): Lighting
25 | {
26 | val l = Lighting()
27 | l.diffuseConstant = 2.0
28 | l.specularConstant = 0.0
29 | l.specularExponent = 0.0
30 | l.surfaceScale = 0.0
31 | l.light = Light.Distant()
32 | l.light.color = Color.color(141.0/255.0, 100.0/255.0, 47.0/255.0)
33 | return l
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/Loader/Loader.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI.Loader
2 |
3 | import javafx.application.Application
4 | import javafx.application.Platform
5 | import javafx.fxml.FXML
6 | import javafx.fxml.FXMLLoader
7 | import javafx.scene.Parent
8 | import javafx.scene.Scene
9 | import javafx.scene.control.ProgressBar
10 | import javafx.scene.image.Image
11 | import javafx.scene.text.Text
12 | import javafx.stage.Stage
13 | import javafx.stage.StageStyle
14 |
15 | /**
16 | *
17 | */
18 | class Loader : Application()
19 | {
20 | companion object
21 | {
22 | lateinit var stage: Stage
23 | lateinit var controller: LoaderController
24 | }
25 |
26 | override fun start(primaryStage: Stage?)
27 | {
28 | stage = Stage()
29 | val fxmlLoader = FXMLLoader()
30 | stage.initStyle(StageStyle.UNDECORATED)
31 | val root = fxmlLoader.load(javaClass.getResource("/Loader.fxml").openStream())
32 |
33 | controller = fxmlLoader.getController() as LoaderController
34 |
35 | stage.title = "PAL: Loader"
36 | stage.icons.add(Image(javaClass.getResource("/witch.png").toString()))
37 | val scene = Scene(root, 400.0, 80.0)
38 | scene.stylesheets.add("layout_settings.css")
39 | stage.scene = scene
40 | stage.show()
41 | }
42 | }
43 |
44 | class LoaderController
45 | {
46 | @FXML
47 | lateinit var loggerText: Text
48 |
49 | @FXML
50 | lateinit var loadingProgress: ProgressBar
51 |
52 | fun updateProgressbar(d: Double)
53 | {
54 | Platform.runLater { loadingProgress.progress = d }
55 | }
56 |
57 | fun setText(str: String)
58 | {
59 | Platform.runLater { loggerText.text = str }
60 | }
61 |
62 | fun close()
63 | {
64 | Platform.runLater { Loader.stage.close() }
65 | }
66 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GUI/UtilityAnchor.kt:
--------------------------------------------------------------------------------
1 | package PAL2.GUI
2 |
3 | import javafx.event.EventHandler
4 | import javafx.scene.image.Image
5 | import javafx.scene.image.ImageView
6 | import javafx.scene.layout.AnchorPane
7 | import javafx.scene.paint.Color
8 | import javafx.scene.text.Text
9 |
10 |
11 | /**
12 | *
13 | */
14 | class UtilityAnchor
15 | {
16 | lateinit var anchorPane: AnchorPane
17 |
18 | var refresh = Text()
19 | var update= Text()
20 | var updateAll = Text()
21 | var editConfig = Text()
22 | var removeAddon = Text()
23 |
24 | var _refresh = Text()
25 | var _update = Text()
26 | var _updateAll = Text()
27 | var _editConfig = Text()
28 | var _removeAddon = Text()
29 |
30 | init
31 | {
32 | createAnchor()
33 | createImages()
34 | createTexts()
35 |
36 | setListners()
37 | }
38 |
39 | private fun setListners()
40 | {
41 | baseTextListner(refresh)
42 | baseTextListner(updateAll)
43 | baseTextListner(update)
44 | baseTextListner(editConfig)
45 | baseTextListner(removeAddon)
46 | baseTextListner(_refresh)
47 | baseTextListner(_updateAll)
48 | baseTextListner(_update)
49 | baseTextListner(_editConfig)
50 | baseTextListner(_removeAddon)
51 | }
52 |
53 | private fun baseTextListner(text: Text)
54 | {
55 | text.onMouseEntered = EventHandler()
56 | {
57 | text.isVisible = !text.isVisible
58 | }
59 |
60 | text.onMouseExited = EventHandler()
61 | {
62 | text.isVisible = !text.isVisible
63 | }
64 | }
65 |
66 |
67 | private fun createTexts()
68 | {
69 | shadowedText(refresh, _refresh, "Refresh", 32.0, 20.0, Color.WHITE, Color(0.192, 0.671, 0.776, 1.0))
70 | shadowedText(updateAll, _updateAll, "Update All", 220.0, 20.0, Color.WHITE, Color(0.192, 0.671, 0.776, 1.0))
71 | shadowedText(update, _update, "Update", 130.0, 20.0, Color.WHITE, Color(0.192, 0.671, 0.776, 1.0))
72 | shadowedText(editConfig, _editConfig, "Edit Configuration", 340.0, 20.0, Color.WHITE, Color(0.192, 0.671, 0.776, 1.0))
73 | shadowedText(removeAddon, _removeAddon, "Remove Addon", 500.0, 20.0, Color((196.0/255.0), (49.0/255.0), (49.0/255.0), 1.0), Color.WHITE)
74 |
75 | anchorPane.children.addAll(refresh, update, updateAll, editConfig, removeAddon,
76 | _refresh, _update, _updateAll, _editConfig, _removeAddon)
77 | }
78 |
79 | fun shadowedText(text: Text, _text: Text, s: String, x: Double, y: Double, c: Color, _c: Color)
80 | {
81 | subShadow(text, s, x, y)
82 | subShadow(_text, s, x, y)
83 | text.fill = c
84 | _text.fill = _c
85 | _text.isVisible = false
86 | }
87 |
88 | fun subShadow(text: Text, s:String, x: Double, y: Double)
89 | {
90 | text.text = s
91 | text.style = "-fx-font-weight: Bold"
92 | text.layoutY = y
93 | text.layoutX = x
94 | }
95 |
96 | private fun createImages()
97 | {
98 | val refresh = ImageView()
99 | val update = ImageView()
100 | val updateAll = ImageView()
101 | val editConfig = ImageView()
102 | val removeAddon = ImageView()
103 |
104 | anchorPane.children.addAll(refresh, update, updateAll, editConfig, removeAddon)
105 |
106 | setWidthHeight(refresh)
107 | setWidthHeight(update)
108 | setWidthHeight(updateAll)
109 | setWidthHeight(editConfig)
110 | setWidthHeight(removeAddon)
111 |
112 | setXY(refresh, 2.5, 2.5)
113 | setXY(update, 100.0, 2.5)
114 | setXY(updateAll, 190.0, 2.5)
115 | setXY(editConfig, 310.0, 2.5)
116 | setXY(removeAddon, 470.0, 2.5)
117 |
118 | setImg(refresh, "/icons/refresh_icon.png")
119 | setImg(update, "/icons/down.png")
120 | setImg(updateAll, "/icons/download_all.png")
121 | setImg(editConfig, "/icons/edit.png")
122 | setImg(removeAddon, "/icons/remove.png")
123 | }
124 |
125 | private fun setImg(imageView: ImageView, s: String)
126 | {
127 | imageView.image = Image(javaClass.getResource(s).toString())
128 | }
129 |
130 | private fun setXY(imageView: ImageView, x: Double, y: Double)
131 | {
132 | imageView.layoutY = y
133 | imageView.layoutX = x
134 | }
135 |
136 | private fun setWidthHeight(imageView: ImageView)
137 | {
138 | imageView.fitWidth = 25.0
139 | imageView.fitHeight = 25.0
140 | }
141 |
142 | private fun createAnchor()
143 | {
144 | anchorPane = AnchorPane()
145 | }
146 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Github/GH_Connector.kt:
--------------------------------------------------------------------------------
1 | package Github
2 |
3 | import GlobalData
4 | import PAL_DataClasses.PAL_AddonFullData
5 | import PAL_DataClasses.initObjectMapper
6 | import mu.KotlinLogging
7 | import org.kohsuke.github.GHRelease
8 | import org.kohsuke.github.GitHub
9 | import java.io.BufferedInputStream
10 | import java.net.HttpURLConnection
11 | import java.net.URL
12 |
13 | /**
14 | *
15 | */
16 | private val logger = KotlinLogging.logger {}
17 | var attempts = 0
18 |
19 | fun connect(): GitHub
20 | {
21 | val token = GlobalData.github_token
22 | if (token != "")
23 | {
24 | return try
25 | {
26 | GitHub.connectUsingOAuth(token)
27 | }
28 | catch (ex: Exception)
29 | {
30 | if (attempts == 3)
31 | {
32 | logger.error { "GitHub API is offline" }
33 | // TODO: Use fallback
34 | }
35 | attempts++
36 | logger.error { "Github API is likely offline, retrying in 5 seconds!" }
37 | Thread.sleep(5 * 1000)
38 | return connect()
39 | }
40 | }
41 | return try
42 | {
43 | GitHub.connectAnonymously()
44 | }
45 | catch (ex: Exception)
46 | {
47 | if (attempts == 3)
48 | {
49 | logger.error { "GitHub API is offline" }
50 | // TODO: Use fallback
51 | }
52 | attempts++
53 | logger.error { "Github API is likely offline, retrying in 5 seconds!" }
54 | Thread.sleep(5 * 1000)
55 | return connect()
56 | }
57 | }
58 |
59 | /**
60 | * Checks Repo for an addons.json and parses it.
61 | * Returns null if no addons.json is found.
62 | */
63 | fun getAddonsFromGHRepo(repo: String): Array?
64 | {
65 | val connection = connect()
66 | val repository = connection.getRepository(repo)
67 | for (a in repository.latestRelease.assets)
68 | {
69 | if (a.name == "addons.json")
70 | {
71 | val httpConnection = URL(a.browserDownloadUrl).openConnection() as HttpURLConnection
72 | val input = BufferedInputStream(httpConnection.inputStream)
73 |
74 | val om = initObjectMapper()
75 | return om.readValue(input, Array::class.java)
76 | }
77 | }
78 | return null
79 | }
80 |
81 | /**
82 | * Checking greater than 5 to keep the user with some GitHub requests in case of special cases.
83 | */
84 | fun canRequest(gitHub: GitHub): Boolean
85 | {
86 | return if (gitHub.rateLimit.remaining > 5)
87 | {
88 | true
89 | }
90 | else
91 | {
92 | logger.error { "Only ${gitHub.rateLimit.remaining} requests remaining; which reset at: ${gitHub.rateLimit.resetDate}" }
93 | false
94 | }
95 | }
96 |
97 | fun getLatestRelease(gitHub: GitHub, username:String, reponame: String): GHRelease?
98 | {
99 | if (canRequest(gitHub))
100 | {
101 | return gitHub.getRepository("$username/$reponame").latestRelease
102 | }
103 | return null
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Github/ReadMeConverter.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Github
2 |
3 | import PAL_DataClasses.PAL_AddonFullData
4 | import org.commonmark.parser.Parser
5 | import org.commonmark.renderer.html.HtmlRenderer
6 | import java.io.BufferedInputStream
7 | import java.net.HttpURLConnection
8 | import java.net.URL
9 |
10 | /**
11 | *
12 | */
13 | object ReadMeConverter
14 | {
15 | fun exceptions(a: PAL_AddonFullData): String
16 | {
17 | return when (a.aid)
18 | {
19 | 6 -> "https://raw.githubusercontent.com/PoE-TradeMacro/POE-TradeMacro/master/README.markdown"
20 | 8 -> "https://raw.githubusercontent.com/klayveR/xenontrade/master/readme.md"
21 | 9 -> "https://gist.githubusercontent.com/POE-Addon-Launcher/2687293a2e255d394e16895a5bcd180d/raw/685db0260292a175270f1ca3922ee07acc73ab6c/lutbot.md"
22 | 12 -> "https://gist.githubusercontent.com/POE-Addon-Launcher/0db7512cdfc44afdca3a66b6c8c240d8/raw/dc463bc87006fe5913c8ddd94c384b5be1bf9298/nope.md"
23 | 17 -> "https://gist.githubusercontent.com/POE-Addon-Launcher/0db7512cdfc44afdca3a66b6c8c240d8/raw/dc463bc87006fe5913c8ddd94c384b5be1bf9298/nope.md"
24 | else -> "https://raw.githubusercontent.com/${a.gh_username}/${a.gh_reponame}/master/README.md"
25 | }
26 | }
27 |
28 | fun convert(a: PAL_AddonFullData): String
29 | {
30 | val url = exceptions(a)
31 | val httpConnection = URL(url).openConnection() as HttpURLConnection
32 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
33 | val input = BufferedInputStream(httpConnection.inputStream)
34 | val str = String(input.readBytes())
35 | val parser = Parser.builder().build()
36 | val doc = parser.parse(str)
37 | val renderer = HtmlRenderer.builder().build()
38 | val html = renderer.render(doc)
39 | return html
40 | }
41 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Github/UpdateGrabber.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Github
2 |
3 | import Github.connect
4 | import SystemHandling.deleteFile
5 | import SystemHandling.unzip
6 | import SystemHandling.verifyFolder
7 | import mu.KotlinLogging
8 | import org.apache.commons.io.FileUtils
9 | import java.io.File
10 | import java.net.URL
11 |
12 | private val logger = KotlinLogging.logger {}
13 |
14 | /**
15 | *
16 | */
17 | fun checkUpdate()
18 | {
19 | if (!GlobalData.debugging)
20 | {
21 | val gh = connect()
22 | if (gh.rateLimit.remaining > 3)
23 | {
24 | val repo = gh.getRepository("")
25 | }
26 | }
27 | }
28 |
29 | fun getUpdate()
30 | {
31 | // Get Token from DB if DB exists and if token is != ""
32 | if (!GlobalData.debugging)
33 | {
34 | val gh = connect()
35 | if (gh.rateLimit.remaining > 3)
36 | {
37 | val repo = gh.getRepository("POE-Addon-Launcher/PALRelease")
38 | val latest = repo.latestRelease
39 | val latest_tag = latest.tagName
40 | if(latest_tag != GlobalData.version)
41 | {
42 | val down_folder = File("${GlobalData.pal_folder}")
43 | verifyFolder(down_folder)
44 |
45 | val dest = File("${GlobalData.install_dir}${File.separator}new${File.separator}PAL2.jar")
46 | val destFolder = File("${GlobalData.install_dir}${File.separator}new")
47 | if (dest.exists())
48 | deleteFile(dest)
49 |
50 | if (!destFolder.exists())
51 | destFolder.mkdir()
52 |
53 | val download_url = latest.assets[0].browserDownloadUrl
54 | FileUtils.copyURLToFile(URL(download_url), dest)
55 |
56 | logger.debug { "Downloaded update [$latest_tag] to: $dest" }
57 |
58 | //rundll32 url.dll,FileProtocolHandler
59 | println(">>> \"${GlobalData.install_dir}${File.separator}PAL2.exe\" <<")
60 | Runtime.getRuntime().exec("\"${GlobalData.install_dir}${File.separator}PAL2.exe\"")
61 |
62 | System.exit(99)
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/GlobalData.kt:
--------------------------------------------------------------------------------
1 | import PAL_DataClasses.PAL_AddonFullData
2 | import javafx.scene.image.Image
3 | import java.io.File
4 | import javax.swing.filechooser.FileSystemView
5 |
6 | /**
7 | *
8 | */
9 | class GlobalData
10 | {
11 | companion object
12 | {
13 | var version = "1.12.2"
14 | var debugging = false
15 | var install_dir = ""
16 | var github_token = ""
17 | var list_of_addons = ArrayList()
18 | var set_of_addons = HashSet()
19 | var list_of_repos = ArrayList()
20 | var pal_folder = File("${System.getenv("LOCALAPPDATA")}${File.separator}PAL")
21 | var pal_data_folder = File("${pal_folder.path}${File.separator}Data")
22 | var db_file = File("${pal_data_folder}${File.separator}PALData.db")
23 | var server_enabled = false
24 | var first_launch = true
25 | var first_launch_after_update = true
26 | var primaryPoEFile: File? = null
27 | var poeLocations = ArrayList()
28 | var logFile = ""
29 | val noIcon = Image(GlobalData::class.java.getResource("/icons/NoIcon.png").openStream())
30 |
31 | var loot_filter_path = FileSystemView.getFileSystemView().defaultDirectory.path + File.separator + "My Games" + File.separator + "Path of Exile"
32 | var show_update_note = false
33 | var launch_addons = true
34 | var contextMenuOpen = false
35 | var filterblastApiInProgress = true
36 |
37 | /**
38 | * DB Data
39 | */
40 | //var poePaths = HashSet()
41 | var addonFolder = File("${pal_folder}${File.separator}Addons")
42 | var ahkFolder = File("")
43 | var launchPOEonLaunch = false
44 | var gitHubAPIEnabled = true
45 | var showUpdateNotesOnUpdate = true
46 | var ahk_scripts = HashSet()
47 |
48 | var temp_down_folder = File("${pal_folder.path}${File.separator}temp_downloads")
49 | var launchList = ArrayList()
50 | var steam_poe = false
51 | var launch_externals = true
52 | var allowTaskKill = true
53 |
54 | fun addToListOfAddons(arr: Array)
55 | {
56 | for (a in arr)
57 | {
58 | if (!list_of_addons.contains(a))
59 | {
60 | list_of_addons.add(a)
61 | }
62 | }
63 | }
64 |
65 | fun getAddonByID(aid: Int): PAL_AddonFullData?
66 | {
67 | for (a in set_of_addons)
68 | {
69 | if (a.aid == aid)
70 | {
71 | return a
72 | }
73 | }
74 | return null
75 | }
76 |
77 | fun checkAddonListForDuplicates()
78 | {
79 | set_of_addons.addAll(list_of_addons)
80 | }
81 |
82 | fun addToRepoList(repo: String)
83 | {
84 | if (!list_of_repos.contains(repo))
85 | {
86 | list_of_repos.add(repo)
87 | }
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/Launcher.kt:
--------------------------------------------------------------------------------
1 | import PAL2.GUI.CoreApplication
2 | import SystemHandling.deleteFile
3 | import javafx.application.Application
4 | import org.apache.commons.io.FileUtils
5 | import java.io.File
6 | import java.util.*
7 |
8 | /**
9 | * Reads Data
10 | * Creates Data
11 | * Launches everything
12 | */
13 | class Launcher2
14 | {
15 | companion object
16 | {
17 | @JvmStatic
18 | fun main(args: Array)
19 | {
20 | // TODO: Allow users to add existing addons
21 |
22 | // Set Locale to US to avoid any locale issues.
23 | Locale.setDefault(Locale.US)
24 |
25 | if (!GlobalData.debugging)
26 | {
27 | var fInstall = File(Launcher2::class.java.protectionDomain.codeSource.location.toURI())
28 |
29 | if (fInstall.isFile)
30 | {
31 | fInstall = fInstall.parentFile
32 | }
33 | GlobalData.install_dir = fInstall.path
34 |
35 |
36 | }
37 |
38 |
39 | /*
40 | if (!GlobalData.debugging)
41 | {
42 | var fInstall = File(Launcher2::class.java.protectionDomain.codeSource.location.toURI())
43 |
44 | if (fInstall.isFile)
45 | {
46 | fInstall = fInstall.parentFile
47 | }
48 | GlobalData.install_dir = fInstall.path
49 |
50 | val stateONE = File("${GlobalData.pal_folder.path}${File.separator}1.state")
51 | val stateTWO = File("${GlobalData.pal_folder.path}${File.separator}2.state")
52 | val newest_update = File("${GlobalData.install_dir}${File.separator}latest")
53 |
54 | if (stateONE.exists())
55 | {
56 | val install_dir = File(GlobalData.install_dir)
57 | FileUtils.copyDirectory(install_dir, install_dir.parentFile)
58 |
59 | deleteFile(stateONE)
60 | stateTWO.createNewFile()
61 | // Launch PAL2.exe in the parent file.
62 | Runtime.getRuntime().exec("\"${install_dir.parentFile.path}${File.separator}PAL2.exe\"")
63 | return
64 | }
65 | else if (stateTWO.exists())
66 | {
67 | deleteFile(newest_update)
68 | deleteFile(stateTWO)
69 | }
70 | }*/
71 |
72 | try
73 | {
74 | Application.launch(CoreApplication::class.java, *args)
75 | }
76 | catch (ex: Exception)
77 | {
78 | ex.printStackTrace()
79 | }
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/PAL_DataClasses/PALData.kt:
--------------------------------------------------------------------------------
1 | package PAL_DataClasses
2 |
3 | import com.fasterxml.jackson.core.JsonFactory
4 | import com.fasterxml.jackson.core.JsonGenerator
5 | import com.fasterxml.jackson.core.JsonParser
6 | import com.fasterxml.jackson.databind.ObjectMapper
7 | import com.fasterxml.jackson.module.kotlin.KotlinModule
8 | import javafx.beans.property.SimpleStringProperty
9 | import java.time.LocalDate
10 | import java.util.*
11 |
12 | /**
13 | * PAL Data Classes; mimic database entries.
14 | */
15 | data class FilterSettings
16 | (
17 | var updateEvery: Int,
18 | var dontCheckWhenPoERunning: Boolean,
19 | var autoUpdateFilters: Boolean
20 | )
21 |
22 |
23 | data class Filter
24 | (
25 | var fid: Int,
26 | val name: String,
27 | var crc32: String,
28 | val webSource: String,
29 | val path: String,
30 | val variation: String
31 | )
32 |
33 | data class PAL_External_Addon
34 | (
35 | var eid: Int,
36 | var name: String,
37 | var checksum: String,
38 | var newCheckSum: String,
39 | var iconUrl: String?,
40 | var lastCheck: String,
41 | var webSource: String,
42 | var launchCMD: String,
43 | var path: String,
44 | var runOnLaunch: Boolean
45 | )
46 |
47 | data class PAL_Addon
48 | (
49 | var id: Int,
50 | var name: String,
51 | var gh_username: String?,
52 | var gh_reponame: String?,
53 | var icon: String?,
54 | var description: String?
55 | )
56 |
57 | data class PAL_DownloadInfo
58 | (
59 | var id: Int,
60 | var download_url: String
61 | )
62 |
63 | data class PAL_AddonVersion
64 | (
65 | var id: Int,
66 | var version_text: String,
67 | var addon: PAL_Addon,
68 | var downloadInfo: PAL_DownloadInfo,
69 | var launch_command: String,
70 | var last_update: LocalDate,
71 | var html_description: String?
72 | )
73 |
74 | data class PAL_AddonFullData
75 | (
76 | var name: String,
77 | var aid: Int,
78 | var gh_username: String?,
79 | var gh_reponame: String?,
80 | var icon_url: String?,
81 | var description: String?,
82 | var download_urls: Array,
83 | var avid: Int,
84 | var version_text: String,
85 | var last_update: String,
86 | var html_description: String?,
87 | var extra_flags: Array
88 | )
89 | {
90 |
91 |
92 | override fun hashCode(): Int
93 | {
94 | var result = name.hashCode()
95 | result = 31 * result + (gh_username?.hashCode() ?: 0)
96 | result = 31 * result + (gh_reponame?.hashCode() ?: 0)
97 | result = 31 * result + (icon_url?.hashCode() ?: 0)
98 | result = 31 * result + (description?.hashCode() ?: 0)
99 | result = 31 * result + download_urls.contentHashCode()
100 | result = 31 * result + version_text.hashCode()
101 | result = 31 * result + last_update.hashCode()
102 | result = 31 * result + (html_description?.hashCode() ?: 0)
103 | result = 31 * result + extra_flags.contentHashCode()
104 | return result
105 | }
106 |
107 | override fun equals(other: Any?): Boolean
108 | {
109 | if (this === other) return true
110 | if (javaClass != other?.javaClass) return false
111 |
112 | other as PAL_AddonFullData
113 |
114 | if (name != other.name) return false
115 | if (aid != other.aid) return false
116 | if (gh_username != other.gh_username) return false
117 | if (gh_reponame != other.gh_reponame) return false
118 | if (icon_url != other.icon_url) return false
119 | if (description != other.description) return false
120 | if (!download_urls.contentEquals(other.download_urls)) return false
121 | if (avid != other.avid) return false
122 | if (version_text != other.version_text) return false
123 | if (last_update != other.last_update) return false
124 | if (html_description != other.html_description) return false
125 | if (!extra_flags.contentEquals(other.extra_flags)) return false
126 |
127 | return true
128 | }
129 |
130 | fun toAddonTableRow(): PAL_AddonTableRow
131 | {
132 | return PAL_AddonTableRow(SimpleStringProperty(name), SimpleStringProperty(version_text), SimpleStringProperty(last_update), SimpleStringProperty(gh_reponame), SimpleStringProperty(gh_reponame), SimpleStringProperty(description))
133 | }
134 | }
135 |
136 | data class PAL_Creator
137 | (
138 | var id: Int,
139 | var name: String
140 | )
141 |
142 | data class PAL_Ownership
143 | (
144 | var creator: PAL_Creator,
145 | var addon: PAL_Addon
146 | )
147 |
148 | data class PAL_FilterVariation
149 | (
150 | var id: Int,
151 | var key: String,
152 | var name: String,
153 | var filter: PAL_Filter
154 | )
155 |
156 | data class PAL_Filter
157 | (
158 | var name: String,
159 | var version: String,
160 | var PoE_version: String,
161 | var forumthread: String,
162 | var description: String,
163 | var html_description: String,
164 | var variations: Array,
165 | var key: String
166 | )
167 | {
168 | override fun toString(): String
169 | {
170 | return "PAL_Filter(name='$name', version='$version', PoE_version='$PoE_version', forumthread='$forumthread', description='$description', html_description='$html_description', variations=${Arrays.toString(variations)}, key='$key')"
171 | }
172 | }
173 |
174 | data class PAL_GH_Info
175 | (
176 | var id: Int,
177 | var username: String,
178 | var reponame: String,
179 | var addon: PAL_Addon
180 | )
181 |
182 | data class PAL_InstalledAddon
183 | (
184 | var id: Int,
185 | var install_location: String,
186 | var local_version: String,
187 | var install_date: LocalDate,
188 | var executable_location: String,
189 | var addonVersion: PAL_AddonVersion
190 | )
191 |
192 | data class PAL_InstalledFilter
193 | (
194 | var id: Int,
195 | var filter: PAL_Filter,
196 | var install_date: LocalDate,
197 | var local_version: String
198 | )
199 |
200 | data class PAL_User(val username: String, val poe_account_name: String, val displayName: String, val email:String, val registeredAt: String,
201 | var account_desc: String)
202 |
203 | data class PAL_AddonMetaData
204 | (
205 | var aid: Int,
206 | var likes: Int,
207 | var dislikes: Int,
208 | var downloads: Int,
209 | var description: String,
210 | var html_description: String,
211 | var icon_url: String,
212 | var ggg_aproved: Boolean,
213 | var creators: String
214 | )
215 |
216 |
217 | fun initObjectMapper(): ObjectMapper
218 | {
219 | return ObjectMapper()
220 | .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
221 | .registerModule(KotlinModule())
222 | }
223 |
224 | fun initObjectMapperWithoutStreamClose(): ObjectMapper
225 | {
226 | val mpf = JsonFactory()
227 | mpf.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
228 | return ObjectMapper(mpf)
229 | .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
230 | .registerModule(KotlinModule())
231 | }
232 |
233 | /**
234 | * Addon Data
235 | */
236 | data class Releases
237 | (
238 | var name: String,
239 | var release_list: Array<*>,
240 | var release_date: LocalDate,
241 | var tag: String
242 | )
243 | {
244 | override fun toString(): String
245 | {
246 | val str = StringBuilder()
247 | str.append("$name | $tag | $release_date\n")
248 |
249 | for (r in release_list)
250 | {
251 | if (r != null)
252 | {
253 | str.append("\t> $r\n")
254 | }
255 | else
256 | {
257 | str.append("\t> NULL\n")
258 | }
259 | }
260 |
261 | return str.toString()
262 | }
263 | }
264 |
265 | data class Release
266 | (
267 | var name: String,
268 | var dl_link: String,
269 | var content_type: String,
270 | var download_size: Long
271 | )
272 | {
273 | override fun toString(): String
274 | {
275 | // Magic Number to convert download size to MB: 1048576
276 | return "$name $content_type ${converToMB(download_size)}"
277 | }
278 |
279 | fun converToMB(bits: Long): String
280 | {
281 | return "${String.format("%.1f", bits/1048576.0)} MB"
282 | }
283 | }
284 |
285 | fun createAFD(a: PAL_Addon, di: Array, av: PAL_AddonVersion, ef: Array): PAL_AddonFullData
286 | {
287 | return PAL_AddonFullData(
288 | a.name,
289 | a.id,
290 | a.gh_username,
291 | a.gh_reponame,
292 | a.icon,
293 | a.description,
294 | di,
295 | av.id,
296 | av.version_text,
297 | createDate(av.last_update),
298 | av.html_description,
299 | ef
300 | )
301 | }
302 |
303 | fun createDate(arg:LocalDate):String
304 | {
305 | return "${arg.year}-${arg.month}-${arg.dayOfMonth}"
306 | }
307 |
308 | /**
309 | * DEPRECATED DATA CLASSES
310 | */
311 |
312 | @Deprecated("Used for compatibility with old PAL")
313 | data class PAL_AddonJson
314 | (
315 | var name :String,
316 | var version :String,
317 | var creators :String,
318 | var gh_username :String,
319 | var gh_reponame :String,
320 | var download_url :String,
321 | var icon_url :String,
322 | var description :String,
323 | var file_launch :String,
324 | var programming_language :String
325 | )
326 |
327 | /**
328 | * FXML
329 | */
330 | data class PAL_AddonTableRow
331 | (
332 | var name: SimpleStringProperty,
333 | var version: SimpleStringProperty,
334 | var last_update: SimpleStringProperty,
335 | var gh_reponame: SimpleStringProperty,
336 | var gh_username: SimpleStringProperty,
337 | var description: SimpleStringProperty
338 | )
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/AddonRemover.kt:
--------------------------------------------------------------------------------
1 | package PAL2.SystemHandling
2 |
3 | import PAL2.Database.getInstallDir
4 | import PAL2.Database.removeInstalledAddon
5 | import SystemHandling.deleteFile
6 | import kotlinx.coroutines.GlobalScope
7 | import kotlinx.coroutines.launch
8 | import java.io.File
9 |
10 | /**
11 | *
12 | */
13 | fun removeAddon(aid: Int)
14 | {
15 | val install_dir = findInstall(aid)
16 | if (install_dir != null)
17 | {
18 | if (install_dir.exists() && install_dir.isDirectory)
19 | {
20 | GlobalScope.launch {
21 | deleteFile(install_dir)
22 | }
23 | removeInstalledAddon(aid)
24 | }
25 | }
26 | }
27 |
28 | fun findInstall(aid :Int): File?
29 | {
30 | return getInstallDir(aid)
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/AddonUpdater.kt:
--------------------------------------------------------------------------------
1 | package PAL2.SystemHandling
2 |
3 | import GlobalData
4 | import SystemHandling.checkForUseableDownloads
5 | import javafx.scene.image.Image
6 | import kotlinx.coroutines.GlobalScope
7 | import kotlinx.coroutines.launch
8 | import java.net.URL
9 |
10 | /**
11 | *
12 | */
13 | fun updateAddon(aid: Int, image: Image)
14 | {
15 | closeAllAddons()
16 | GlobalScope.launch {
17 | val addon = GlobalData.getAddonByID(aid) ?: return@launch
18 | val download_urls = checkForUseableDownloads(addon.download_urls, addon.aid)
19 |
20 | if (download_urls.size == 1)
21 | {
22 | val fd = FileDownloader()
23 | fd.downloadFileAndInstall(URL(download_urls[0]), GlobalData.temp_down_folder, 1024, image, aid)
24 | }
25 | }
26 | }
27 |
28 | fun closeAllAddons()
29 | {
30 | if (GlobalData.allowTaskKill)
31 | {
32 | taskKill("autohotkey.exe /F")
33 | taskKill("Path of Maps Client.exe")
34 | taskKill("TraderForPoe.exe")
35 | taskKill("javaw.exe")
36 | taskKill("java.exe")
37 | taskKill("POE-Trades-Companion.exe")
38 | taskKill("XenonTrade.exe")
39 | taskKill("LabCompass.exe")
40 | taskKill("Exilence.exe")
41 | taskKill("CurrencyCop.exe")
42 | taskKill("PoE Custom Soundtrack.exe")
43 | }
44 | }
45 |
46 | fun taskKill(name: String): Process
47 | {
48 | if (name == "java")
49 | {
50 | taskKill("javaw.exe").waitFor()
51 | return taskKill("java.exe")
52 | }
53 | return Runtime.getRuntime().exec("taskkill /IM \"$name\"")
54 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/FileHandling.kt:
--------------------------------------------------------------------------------
1 | package SystemHandling
2 |
3 | import GlobalData
4 | import mu.KotlinLogging
5 | import net.lingala.zip4j.core.ZipFile
6 | import java.io.File
7 |
8 | private val logger = KotlinLogging.logger {}
9 |
10 | /**
11 | * Verify if a folder exists if it doesn't deletes it.
12 | */
13 | fun verifyFolder(file: File)
14 | {
15 | if (!file.exists())
16 | {
17 | logger.debug { "Creating folder: \"${file.path}\"" }
18 | file.mkdir()
19 | }
20 | }
21 |
22 | /**
23 | * WARNING: Recursively deletes all underlying folders aswell!
24 | */
25 | fun deleteFile(file: File)
26 | {
27 | if (file.isDirectory)
28 | logger.debug { "Deleting: ${file.path} and all ${file.listFiles().size} files within" }
29 | else
30 | logger.debug { "Deleting: ${file.path}"}
31 | if (file.exists())
32 | {
33 | if (file.isDirectory)
34 | {
35 | for (f in file.listFiles())
36 | {
37 | deleteFile(f)
38 | }
39 | }
40 | file.delete()
41 | }
42 | }
43 |
44 | fun checkForUseableDownloads(download_urls: Array, aid: Int): Array
45 | {
46 | when (aid)
47 | {
48 | 2 -> return usableDownloadsWithExtension(download_urls, "zip")
49 | 5 -> return usableDownloadsWithExtension(download_urls, "zip")
50 | 8 -> return usableDownloadsWithExtension(download_urls, "exe")
51 | 10 -> return usableDownloadsWithExtension(download_urls, "exe")
52 | 11 -> return usableDownloadsWithExtension(download_urls, "exe")
53 | else -> return defaultUsableDownloads(download_urls)
54 | }
55 | }
56 |
57 | fun removeTempDownloads()
58 | {
59 | if (GlobalData.temp_down_folder.exists() && GlobalData.temp_down_folder.isDirectory)
60 | {
61 | deleteFile(GlobalData.temp_down_folder)
62 | GlobalData.temp_down_folder.mkdir()
63 | }
64 | }
65 |
66 | fun usableDownloadsWithExtension(download_urls: Array, extension_format: String): Array
67 | {
68 | val arr = ArrayList()
69 |
70 | for (dl in download_urls)
71 | {
72 | val splits = dl.split(".")
73 | val extension = splits[splits.size-1]
74 |
75 | when (extension)
76 | {
77 | extension_format -> arr.add(dl)
78 | }
79 |
80 | }
81 | return arr.toTypedArray()
82 | }
83 |
84 | fun unzip(archive: File, destination: File)
85 | {
86 | val zip = ZipFile(archive)
87 | zip.extractAll(destination.path)
88 | deleteFile(archive)
89 | }
90 |
91 | fun defaultUsableDownloads(download_urls: Array): Array
92 | {
93 | val arr = ArrayList()
94 |
95 | for (dl in download_urls)
96 | {
97 | val splits = dl.split(".")
98 | val extension = splits[splits.size-1]
99 |
100 | when (extension)
101 | {
102 | "exe" -> arr.add(dl)
103 | "zip" -> arr.add(dl)
104 | "jar" -> arr.add(dl)
105 | "ahk" -> arr.add(dl)
106 | "msi" -> arr.add(dl)
107 | }
108 |
109 | }
110 | return arr.toTypedArray()
111 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/Init.kt:
--------------------------------------------------------------------------------
1 | package SystemHandling
2 |
3 | import Github.getAddonsFromGHRepo
4 | import GlobalData
5 | import PAL2.Database.*
6 | import PAL2.GUI.Configurator.ConfiguratorApplication
7 | import PAL2.GUI.CoreApplication
8 | import PAL2.GUI.Loader.Loader
9 | import PAL2.Github.checkUpdate
10 | import PAL2.Github.getUpdate
11 | import PAL_DataClasses.PAL_AddonFullData
12 | import PAL_DataClasses.initObjectMapper
13 | import javafx.application.Platform
14 | import javafx.stage.Stage
15 | import mu.KotlinLogging
16 | import org.apache.commons.io.FileUtils
17 | import java.io.File
18 | import java.net.URL
19 |
20 | private val logger = KotlinLogging.logger {}
21 | /**
22 | *
23 | */
24 | var configurating = false
25 |
26 | fun loader(arg: String, d: Double)
27 | {
28 | Loader.controller.setText(arg)
29 | Loader.controller.updateProgressbar(d)
30 | }
31 |
32 | fun init()
33 | {
34 | Platform.runLater { CoreApplication.stage.opacity = 0.01 }
35 |
36 | loader("Initializing Folders", 0.0)
37 | logger.debug { "Init: Folders" }
38 | initFolders()
39 | logger.debug { "Init: DB" }
40 | loader("Initializing Database", 0.1)
41 | initDB()
42 |
43 | logger.debug { "Init: Misc" }
44 | loader("Initializing User Data", 0.33)
45 | moreInit()
46 |
47 |
48 | //CoreApplication.controller.addInstalledAnchorTEST()
49 | }
50 |
51 | fun initFolders()
52 | {
53 | verifyFolder(GlobalData.pal_folder)
54 | verifyFolder(GlobalData.pal_data_folder)
55 | }
56 |
57 | fun initDB()
58 | {
59 | if (!GlobalData.db_file.exists())
60 | {
61 | configurating = true
62 | createDB()
63 |
64 | // Ask user to enter information we need.
65 | // Launch simple UI to ask for it.
66 | Platform.runLater {
67 | val c = ConfiguratorApplication()
68 | c.start(Stage())
69 | }
70 |
71 | }
72 | GlobalData.first_launch = false
73 | }
74 |
75 | // TODO: MORE INIT STUFF, IN TERMS OF DB SETTINGS AND FINISH CONFIGURATOR
76 |
77 | fun moreInit()
78 | {
79 | loader("Waiting on configurator", 0.34)
80 | while (configurating)
81 | {
82 | Thread.sleep(250)
83 | }
84 | //TODO: Read data from database
85 | if (!GlobalData.first_launch)
86 | {
87 | if (GlobalData.showUpdateNotesOnUpdate)
88 | {
89 | if (getLastPALVersion() != GlobalData.version)
90 | {
91 | setPALVersion()
92 | GlobalData.show_update_note = true
93 | }
94 | }
95 |
96 | loader("Getting previous configuration", 0.4)
97 | retreiveConfig()
98 | //Get AHK Scripts
99 | loader("Getting AHK Scripts", 0.5)
100 | getAHKScripts()
101 |
102 | val f = getPrimaryPoE()
103 | if (f != "")
104 | {
105 | GlobalData.primaryPoEFile = File(f)
106 | }
107 | }
108 |
109 | loader("Checking for Updates to PAL", 0.5)
110 | //getUpdate(GlobalData.install_dir)
111 |
112 | getUpdate()
113 |
114 | loader("No updates to PAL!", 0.6)
115 |
116 |
117 | loader("Downloading Addons from Repository", 0.6)
118 | // Check if a Token has been set
119 | if (GlobalData.github_token == "" || !GlobalData.gitHubAPIEnabled)
120 | {
121 | staticRepoAddons()
122 | }
123 | else
124 | {
125 | // TODO: Parse repos from DB
126 | // Use GitHub repo
127 | val addons = getAddonsFromGHRepo("POE-Addon-Launcher/server")
128 | if (addons == null)
129 | {
130 | staticRepoAddons()
131 | }
132 | else
133 | {
134 | GlobalData.set_of_addons.addAll(addons)
135 | }
136 | }
137 | loader("Initializing: Addon List", 0.8)
138 | CoreApplication.controller.initAddonListView()
139 |
140 | // Get Installed Addons
141 | loader("Checking for your installed addons", 0.9)
142 | getInstalledAddons()
143 |
144 | loader("Initialization done!", 1.0)
145 | Loader.controller.close()
146 | Platform.runLater { CoreApplication.stage.opacity = 1.0 }
147 | }
148 |
149 | fun staticRepoAddons()
150 | {
151 | logger.debug { "Getting addons from static file!" }
152 | // Use static repo
153 | // https://raw.githubusercontent.com/POE-Addon-Launcher/server/master/addons.json
154 | val addonsJson = File("${GlobalData.pal_folder}${File.separator}addons.json")
155 | deleteFile(addonsJson)
156 |
157 | FileUtils.copyURLToFile(URL("https://raw.githubusercontent.com/POE-Addon-Launcher/server/master/addons.json"), addonsJson)
158 |
159 | val objectMapper = initObjectMapper()
160 | GlobalData.addToListOfAddons(objectMapper.readValue(addonsJson, Array::class.java))
161 | deleteFile(addonsJson)
162 |
163 | // Extra sanity check!
164 | GlobalData.checkAddonListForDuplicates()
165 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/LaunchHandling.kt:
--------------------------------------------------------------------------------
1 | package PAL2.SystemHandling
2 |
3 | import GlobalData
4 | import PAL2.Database.getExternalsOnLaunchCommands
5 | import PAL2.Database.getInstallDir
6 | import PAL2.Database.getLaunchCommand
7 | import PAL2.Database.getRunOnLaunchCommands
8 | import kotlinx.coroutines.GlobalScope
9 | import kotlinx.coroutines.launch
10 | import mu.KotlinLogging
11 | import java.awt.Desktop.getDesktop
12 | import java.io.File
13 | import java.io.IOException
14 | import java.net.URI
15 |
16 |
17 | private val logger = KotlinLogging.logger {}
18 | /**
19 | *
20 | */
21 | fun launchAddon(aid: Int)
22 | {
23 | // Grab launch command from DB
24 | val lc = getLaunchCommand(aid)
25 |
26 | when (aid)
27 | {
28 | 14 -> procurementHandler(aid)
29 | 12 -> runPathOfMaps(lc)
30 | 15 -> leagueOverlayHandler(aid, lc)
31 | else -> defaultHandler(aid, lc)
32 | }
33 | }
34 |
35 | fun defaultHandler(aid: Int, lc: String)
36 | {
37 | GlobalScope.launch {
38 | // Check for exceptions: ? "SET_AHK_FOLDER" etc
39 | if (lc == "?")
40 | {
41 | logger.error { "NO LAUNCH COMMAND SET!" }
42 | }
43 | else if (lc == "SET_AHK_FOLDER")
44 | {
45 | logger.error { "SET AHK FOLDER!" }
46 | }
47 | else
48 | {
49 | val dir = getInstallDir(aid)
50 | if (dir != null)
51 | {
52 | Runtime.getRuntime().exec(lc, null, dir)
53 | }
54 | else
55 | {
56 | Runtime.getRuntime().exec(lc)
57 | }
58 |
59 | }
60 | }
61 |
62 |
63 | }
64 |
65 | fun runPathOfMaps(lc: String)
66 | {
67 | GlobalScope.launch {
68 | Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler $lc")
69 | }
70 |
71 | }
72 |
73 | fun leagueOverlayHandler(aid: Int, launch_command: String)
74 | {
75 | GlobalScope.launch {
76 | val dir = getInstallDir(aid)
77 | if (dir != null)
78 | {
79 | Runtime.getRuntime().exec(launch_command, null, dir)
80 | }
81 | }
82 | }
83 |
84 | fun procurementHandler(aid: Int)
85 | {
86 | GlobalScope.launch {
87 | val f = getInstallDir(aid)
88 |
89 | if (f != null)
90 | {
91 | var exe = ""
92 | for (_f in f.listFiles())
93 | {
94 | if (_f.name == "Procurement.exe")
95 | {
96 | exe = _f.path
97 | }
98 | }
99 |
100 | if (exe != "")
101 | Runtime.getRuntime().exec("\"$exe\"", null, f)
102 | }
103 |
104 | }
105 | }
106 |
107 | private fun launch_poe(exe: String)
108 | {
109 | logger.debug { "CALLED: LAUNCH_POE(exe) | exe = \'$exe\'" }
110 |
111 | if (exe.contains("PathOfExileSteam.exe") || exe.contains("PathOfExile_x64Steam.exe"))
112 | {
113 | logger.debug { "Attempting to run Steam PoE" }
114 | runSteamPoE()
115 | }
116 | else if (exe.contains("PathOfExile.exe") || exe.contains("PathOfExile_x64.exe"))
117 | {
118 | val dir: String
119 | val executable: String
120 | if (exe.contains("PathOfExile_x64.exe"))
121 | {
122 | logger.debug { "Found PathOfExile_x64.exe" }
123 | executable = "PathOfExile_x64.exe"
124 | dir = exe.replace(executable, "")
125 | logger.debug { "dir = $dir" }
126 | }
127 | else
128 | {
129 | logger.debug { "ELSE case" }
130 | executable = "PathOfExile.exe"
131 | dir = exe.replace(executable, "")
132 | logger.debug { "dir = $dir" }
133 | }
134 | try
135 | {
136 | logger.debug { "Runtime command: \"$exe\", NULL, ${File(dir)}" }
137 | logger.debug { "dir = $dir" }
138 | Runtime.getRuntime().exec("\"$exe\"", null, File(dir))
139 | }
140 | catch (e: IOException)
141 | {
142 | logger.error { e.printStackTrace() }
143 | }
144 |
145 | }
146 | }
147 |
148 | fun runSteamPoE()
149 | {
150 | val desktop = getDesktop()
151 | val steamProtocol = URI("steam://run/238960")
152 | desktop.browse(steamProtocol)
153 | }
154 |
155 | fun launchAddons()
156 | {
157 | if (GlobalData.launch_addons)
158 | {
159 | val arr = getRunOnLaunchCommands()
160 | if (arr != null)
161 | {
162 | for (lc in arr)
163 | {
164 | GlobalScope.launch {
165 | Runtime.getRuntime().exec(lc)
166 | }
167 | }
168 | }
169 | GlobalData.launch_addons = false
170 | }
171 | }
172 |
173 | @Deprecated("Uses different method to launch AHKs now.")
174 | fun launchAHKScripts()
175 | {
176 | var arr = GlobalData.ahk_scripts
177 | for (ahk in arr)
178 | {
179 | GlobalScope.launch {
180 | Runtime.getRuntime().exec(createAHKLaunchCommand(ahk))
181 | }
182 | }
183 | }
184 |
185 | fun createAHKLaunchCommand(ahk_file: String): String
186 | {
187 | val ahk_folder = GlobalData.ahkFolder
188 | if (ahk_folder.path != "")
189 | {
190 | if (ahk_folder.exists())
191 | {
192 | val stringBuilder = StringBuilder()
193 | stringBuilder.append("\"")
194 | stringBuilder.append(ahk_folder.path)
195 | stringBuilder.append(File.separator)
196 | stringBuilder.append("autohotkey.exe")
197 | stringBuilder.append("\" ")
198 |
199 | stringBuilder.append("\"")
200 | stringBuilder.append(ahk_file)
201 | stringBuilder.append("\" ")
202 |
203 | logger.debug { stringBuilder.toString() }
204 | return stringBuilder.toString()
205 | }
206 | else
207 | {
208 | return "SET_AHK_FOLDER"
209 | }
210 | }
211 | return "SET_AHK_FOLDER"
212 | }
213 |
214 | fun launchPoE()
215 | {
216 | if (GlobalData.steam_poe)
217 | {
218 | GlobalScope.launch {
219 | GlobalScope.launch {
220 | launchAddons()
221 | }
222 | GlobalScope.launch {
223 | launchExternals()
224 | }
225 | GlobalScope.launch {
226 | runSteamPoE()
227 | }
228 | }
229 | return
230 | }
231 |
232 | if (GlobalData.poeLocations.size == 0)
233 | {
234 | logger.error { "No path of exile directories are known." }
235 | }
236 | else if (GlobalData.poeLocations.size == 1)
237 | {
238 | GlobalScope.launch {
239 | GlobalScope.launch {
240 | launchAddons()
241 | }
242 | GlobalScope.launch {
243 | launchExternals()
244 | }
245 | GlobalScope.launch {
246 | launch_poe(GlobalData.poeLocations[0])
247 | }
248 | }
249 | }
250 | else
251 | {
252 | val f = GlobalData.primaryPoEFile
253 | if (f != null)
254 | {
255 | if (f.exists())
256 | {
257 | GlobalScope.launch {
258 | GlobalScope.launch {
259 | launchAddons()
260 | }
261 | GlobalScope.launch {
262 | launchExternals()
263 | }
264 | GlobalScope.launch {
265 | launch_poe(f.path)
266 | }
267 | }
268 | }
269 | }
270 | }
271 | }
272 |
273 | fun launchExternals()
274 | {
275 | if (!GlobalData.launch_externals)
276 | return
277 |
278 | val arr = getExternalsOnLaunchCommands() ?: return
279 |
280 | if (arr.isEmpty())
281 | return
282 |
283 | for (str in arr)
284 | {
285 | GlobalScope.launch { Runtime.getRuntime().exec(str) }
286 | }
287 |
288 | GlobalData.launch_externals = false
289 | }
290 |
--------------------------------------------------------------------------------
/src/main/kotlin/PAL2/SystemHandling/WebHandling.kt:
--------------------------------------------------------------------------------
1 | package PAL2.SystemHandling
2 |
3 | import GUI.DownloadsAnchor
4 | import GlobalData
5 | import SystemHandling.deleteFile
6 | import javafx.scene.image.Image
7 | import kotlinx.coroutines.GlobalScope
8 | import kotlinx.coroutines.delay
9 | import kotlinx.coroutines.launch
10 | import java.io.BufferedInputStream
11 | import java.io.BufferedOutputStream
12 | import java.io.File
13 | import java.io.FileOutputStream
14 | import java.net.HttpURLConnection
15 | import java.net.URL
16 |
17 | /**
18 | *
19 | */
20 | class FileDownloader
21 | {
22 | private var maxSize = 0
23 | private var currSize = 0
24 | private lateinit var downloadBar: DownloadsAnchor
25 | private var blockSize = 128
26 |
27 | fun downloadFile(url: URL, temp_download_dir: File, block: Int, image: Image): File
28 | {
29 | var store_location = temp_download_dir
30 | if (store_location.isDirectory)
31 | {
32 | val splits = url.file.split("/")
33 | store_location = File("${store_location.path}${File.separator}${splits[splits.size-1]}")
34 | }
35 |
36 | if (store_location.exists())
37 | deleteFile(store_location)
38 |
39 | blockSize = block
40 |
41 | val httpConnection = url.openConnection() as HttpURLConnection
42 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
43 | val filesize = httpConnection.contentLength
44 | maxSize = filesize
45 |
46 | val input = BufferedInputStream(httpConnection.inputStream)
47 | val output = FileOutputStream(store_location)
48 |
49 | val buff = BufferedOutputStream(output, blockSize)
50 |
51 | val data = ByteArray(blockSize)
52 | var downloadedFileSize = 0
53 | var x: Int
54 |
55 | val splits = url.file.split("/")
56 | downloadBar = DownloadsAnchor(splits[splits.size-1])
57 | downloadBar.setImg(image)
58 | downloadBar.attachToListView()
59 | updateProgress(0, maxSize, 0.0)
60 | functionCallerOnDelay()
61 |
62 | while (true)
63 | {
64 | x = input.read(data, 0, blockSize)
65 |
66 | if (x < 0)
67 | break
68 |
69 | downloadedFileSize += x
70 | currSize = downloadedFileSize
71 |
72 | buff.write(data, 0, x)
73 | }
74 |
75 | input.close()
76 | buff.close()
77 | output.close()
78 |
79 | return store_location
80 | }
81 |
82 | fun downloadFileAndInstall(url: URL, temp_download_dir: File, block: Int, image: Image, aid: Int)
83 | {
84 | var store_location = temp_download_dir
85 | if (store_location.isDirectory)
86 | {
87 | val splits = url.file.split("/")
88 | store_location = File("${store_location.path}${File.separator}${splits[splits.size-1]}")
89 | }
90 |
91 | if (store_location.exists())
92 | deleteFile(store_location)
93 |
94 | blockSize = block
95 |
96 | val httpConnection = url.openConnection() as HttpURLConnection
97 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
98 | val filesize = httpConnection.contentLength
99 | maxSize = filesize
100 |
101 | val input = BufferedInputStream(httpConnection.inputStream)
102 | val output = FileOutputStream(store_location)
103 |
104 | val buff = BufferedOutputStream(output, blockSize)
105 |
106 | val data = ByteArray(blockSize)
107 | var downloadedFileSize = 0
108 | var x: Int
109 |
110 | val splits = url.file.split("/")
111 | downloadBar = DownloadsAnchor(splits[splits.size-1])
112 | downloadBar.setImg(image)
113 | downloadBar.attachToListView()
114 | updateProgress(0, maxSize, 0.0)
115 | functionCallerOnDelay()
116 |
117 | while (true)
118 | {
119 | x = input.read(data, 0, blockSize)
120 |
121 | if (x < 0)
122 | break
123 |
124 | downloadedFileSize += x
125 | currSize = downloadedFileSize
126 |
127 | buff.write(data, 0, x)
128 | }
129 |
130 | input.close()
131 | buff.close()
132 | output.close()
133 |
134 |
135 | // Download finished run installation.
136 | val addon = GlobalData.getAddonByID(aid)
137 | if (addon != null)
138 | {
139 | val installer = InstallHandler(addon, store_location)
140 | }
141 | }
142 |
143 | fun functionCallerOnDelay()
144 | {
145 | GlobalScope.launch {
146 | var timeSpent = 0.0
147 | while (currSize < maxSize)
148 | {
149 | val down_speed = (currSize/1024/1024/timeSpent)
150 | updateProgress(currSize, maxSize, Math.round(down_speed * 100.0) / 100.0)
151 | delay(250)
152 | timeSpent += 0.25
153 | }
154 | updateProgress(maxSize, maxSize, 0.0)
155 | }
156 | }
157 |
158 | fun updateProgress(min_size: Int, maxSize: Int, downSpeed: Double)
159 | {
160 | //AnchorTest.controller.updateProgressbar(d / 100.0)
161 | downloadBar.setProgress((min_size.toDouble() / maxSize.toDouble()))
162 | downloadBar.addDownloadText("[${min_size/1024/1024}MB / ${maxSize/1024/1024}MB] ~${downSpeed}MB/s")
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/main/resources/Configurator.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/src/main/resources/FiltersTab.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/main/resources/Loader.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/resources/config.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/resources/downloadAsker.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/main/resources/fxml_previews/addonDisplay.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/fxml_previews/downloadsAnchor.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/resources/fxml_previews/installedList.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/icons/NoIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/NoIcon.png
--------------------------------------------------------------------------------
/src/main/resources/icons/Web.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/Web.pdn
--------------------------------------------------------------------------------
/src/main/resources/icons/Web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/Web.png
--------------------------------------------------------------------------------
/src/main/resources/icons/ahk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/ahk.png
--------------------------------------------------------------------------------
/src/main/resources/icons/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/cancel.png
--------------------------------------------------------------------------------
/src/main/resources/icons/cancel0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/cancel0.png
--------------------------------------------------------------------------------
/src/main/resources/icons/colors:
--------------------------------------------------------------------------------
1 | #515658 <-- Highlight Grey
2 | #3C3F41 <-- Normal Topbar Grey
3 | #2B2B2B <-- Dark Grey
4 |
5 |
6 | #2B91AF <-- Text Color
7 | #C43131 <-- Red Color
--------------------------------------------------------------------------------
/src/main/resources/icons/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/cross.png
--------------------------------------------------------------------------------
/src/main/resources/icons/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/down.png
--------------------------------------------------------------------------------
/src/main/resources/icons/downArrow.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/downArrow.pdn
--------------------------------------------------------------------------------
/src/main/resources/icons/downArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/downArrow.png
--------------------------------------------------------------------------------
/src/main/resources/icons/down_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/down_hl.png
--------------------------------------------------------------------------------
/src/main/resources/icons/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/download.png
--------------------------------------------------------------------------------
/src/main/resources/icons/download_all.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/download_all.pdn
--------------------------------------------------------------------------------
/src/main/resources/icons/download_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/download_all.png
--------------------------------------------------------------------------------
/src/main/resources/icons/download_darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/download_darker.png
--------------------------------------------------------------------------------
/src/main/resources/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/edit.png
--------------------------------------------------------------------------------
/src/main/resources/icons/emptyStar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/emptyStar.png
--------------------------------------------------------------------------------
/src/main/resources/icons/filledStar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/filledStar.png
--------------------------------------------------------------------------------
/src/main/resources/icons/gggAprove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/gggAprove.png
--------------------------------------------------------------------------------
/src/main/resources/icons/gggAproveQ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/gggAproveQ.png
--------------------------------------------------------------------------------
/src/main/resources/icons/gggMark.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/gggMark.pdn
--------------------------------------------------------------------------------
/src/main/resources/icons/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/info.png
--------------------------------------------------------------------------------
/src/main/resources/icons/main_quest_item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/main_quest_item.png
--------------------------------------------------------------------------------
/src/main/resources/icons/minimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/minimize.png
--------------------------------------------------------------------------------
/src/main/resources/icons/minimize_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/minimize_hl.png
--------------------------------------------------------------------------------
/src/main/resources/icons/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/minus.png
--------------------------------------------------------------------------------
/src/main/resources/icons/part.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/part.png
--------------------------------------------------------------------------------
/src/main/resources/icons/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/play.png
--------------------------------------------------------------------------------
/src/main/resources/icons/q.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/q.png
--------------------------------------------------------------------------------
/src/main/resources/icons/refresh_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/refresh_icon.png
--------------------------------------------------------------------------------
/src/main/resources/icons/remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/remove.png
--------------------------------------------------------------------------------
/src/main/resources/icons/respecbook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/respecbook.png
--------------------------------------------------------------------------------
/src/main/resources/icons/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/settings.png
--------------------------------------------------------------------------------
/src/main/resources/icons/settings_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/settings_hl.png
--------------------------------------------------------------------------------
/src/main/resources/icons/skillbook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/skillbook.png
--------------------------------------------------------------------------------
/src/main/resources/icons/star25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/star25.png
--------------------------------------------------------------------------------
/src/main/resources/icons/star50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/star50.png
--------------------------------------------------------------------------------
/src/main/resources/icons/star75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/star75.png
--------------------------------------------------------------------------------
/src/main/resources/icons/thumbsDown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/thumbsDown.png
--------------------------------------------------------------------------------
/src/main/resources/icons/thumbsUp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/thumbsUp.png
--------------------------------------------------------------------------------
/src/main/resources/icons/trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/trash.png
--------------------------------------------------------------------------------
/src/main/resources/icons/trayIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/trayIcon.png
--------------------------------------------------------------------------------
/src/main/resources/icons/trial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/trial.png
--------------------------------------------------------------------------------
/src/main/resources/icons/upArrow.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/upArrow.pdn
--------------------------------------------------------------------------------
/src/main/resources/icons/upArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/upArrow.png
--------------------------------------------------------------------------------
/src/main/resources/icons/waypoint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/icons/waypoint.png
--------------------------------------------------------------------------------
/src/main/resources/legion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/legion.png
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/new_in_this_release.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/resources/overlay/GridDisplay.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/main/resources/overlay/WebAddonUI.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/main/resources/overlayidea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/overlayidea.png
--------------------------------------------------------------------------------
/src/main/resources/popup.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/resources/popup_import.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/main/resources/settings/Twitch_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/Twitch_icon.png
--------------------------------------------------------------------------------
/src/main/resources/settings/YouTube-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/YouTube-icon.png
--------------------------------------------------------------------------------
/src/main/resources/settings/discord.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/discord.jpg
--------------------------------------------------------------------------------
/src/main/resources/settings/discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/discord.png
--------------------------------------------------------------------------------
/src/main/resources/settings/github-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/github-512.png
--------------------------------------------------------------------------------
/src/main/resources/settings/patreon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/patreon.png
--------------------------------------------------------------------------------
/src/main/resources/settings/patreon_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/patreon_small.png
--------------------------------------------------------------------------------
/src/main/resources/settings/reddit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/reddit.png
--------------------------------------------------------------------------------
/src/main/resources/settings/twitchsmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/twitchsmall.png
--------------------------------------------------------------------------------
/src/main/resources/settings/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/twitter.png
--------------------------------------------------------------------------------
/src/main/resources/settings/twittersmaller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/twittersmaller.png
--------------------------------------------------------------------------------
/src/main/resources/settings/utubesmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/settings/utubesmall.png
--------------------------------------------------------------------------------
/src/main/resources/test.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/resources/tray/animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/tray/animation.gif
--------------------------------------------------------------------------------
/src/main/resources/tray/baseTray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/tray/baseTray.png
--------------------------------------------------------------------------------
/src/main/resources/tray/paused.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/tray/paused.png
--------------------------------------------------------------------------------
/src/main/resources/update_notes.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/resources/update_notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
62 |
63 | Version 1.12
64 |
65 | - No longer uses Excelsior JET!
66 | - License issue won't happen anymore.
67 | - Readme's now use Markdown.md from their github repos.
68 |
69 |
70 | Version 1.11
71 |
72 | - Fix some bugs with Externals
73 | - FilterBlast Loot Filters support
74 | - Generally Code enhancements
75 | - Taskkill properly kills AHKs now
76 | - Added checkbox for closing addons on close ON BY DEFAULT
77 | - Hotfix: SQL sux ok
78 | - Hotfix-2: File extension checking
79 | - Hotfix-3: More SQL issues
80 | - Hotfix-4: Disabled auto-deltion of temp_downloads due to improper explination of temp_downloads
81 |
82 |
83 | Version 1.0.10
84 |
85 | - Fix POE-Trades-Companion (Uses AHK version now)
86 | - Fix Text on some ultra-wide monitors
87 | - Removed some unused code
88 | - Improved custom AHK support through "externals"
89 | - Added support for: Exiled-Presence & Synthesized Implicit Calculator
90 |
91 |
92 | Version 1.0.9
93 |
94 | - Update to dependencies
95 |
96 |
97 | Version 1.0.8
98 |
99 | - Renewed Excelsior JET License
100 |
101 |
102 | Version 1.0.7
103 |
104 | - Changed addon launch commands, this should fix some issues people had with addons not launching.
105 | - Fixed typo to "recommended" in configurator
106 |
107 |
108 | Version 1.0.6
109 |
110 | - Added an extra disclaimer
111 | - Added support for 2 new addons
112 | - Procurement (C# / EXE)
113 | - League Overlay (AHK)
114 |
115 |
116 | Version 1.0.5
117 |
118 | - Potential Fix for addons not launching.
119 | - Added a log to the settings page.
120 | - Still investigating PoE not launching upon click.
121 |
122 |
123 | Version 1.0.4
124 |
125 | - You can now set the addons on launch by selecting them in the installed tab and clicking to enable.
126 | - When clicking "Launch Path of Exile" with the RIGHT mouse button it will launch your addons instead.
127 |
128 |
129 | Version 1.0.3
130 |
131 | - Fix download bug
132 |
133 |
134 | Version 1.0.2
135 |
136 | - Tidied up some server code
137 | - Removed some unused maven dependencies
138 |
139 |
140 | Version 1.0.1
141 |
142 | - First Public Release
143 | - Fixed About page links
144 | - Added a version display to the about page
145 | - Added a boolean to only launch addons upon first launch
146 | - Added the update notes to the repo
147 |
148 |
149 |
150 | Version 1.0
151 |
152 | - Brand New PoE Addon Launcher Interface and functions!
153 |
154 |
155 |
--------------------------------------------------------------------------------
/src/main/resources/updatepls.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/resources/witch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PAL2/af4e7ade6a7751b019e112dffb7e0605dfd11a6e/src/main/resources/witch.png
--------------------------------------------------------------------------------
/src/test/kotlin/PAL2/Filters/FilterBlastTest.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Filters
2 |
3 | import org.junit.Assert.*
4 | import org.junit.Test
5 |
6 | /**
7 | *
8 | */
9 | class FilterBlastTest
10 | {
11 | @Test
12 | fun testGettingList()
13 | {
14 | //val list = FilterBlast.downloadListOfFilters()
15 |
16 | //val res = FilterDownloader.downloadFilter(list[11].variations[0].key, list[11].name)
17 | //println(res)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/test/kotlin/PAL2/Github/ReadMeConverterTest.kt:
--------------------------------------------------------------------------------
1 | package PAL2.Github
2 |
3 | import org.commonmark.parser.Parser
4 | import org.commonmark.renderer.html.HtmlRenderer
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import java.io.BufferedInputStream
8 | import java.net.HttpURLConnection
9 | import java.net.URL
10 |
11 | /**
12 | *
13 | */
14 | class ReadMeConverterTest
15 | {
16 | @Test
17 | fun testReadMeDownloading()
18 | {
19 | val url = "https://raw.githubusercontent.com/Exslims/MercuryTrade/master/README.md"
20 | val httpConnection = URL(url).openConnection() as HttpURLConnection
21 | httpConnection.addRequestProperty("User-Agent", "Mozilla/4.0")
22 | val input = BufferedInputStream(httpConnection.inputStream)
23 | val str = String(input.readBytes())
24 | val parser = Parser.builder().build()
25 | val doc = parser.parse(str)
26 | val renderer = HtmlRenderer.builder().build()
27 | val html = renderer.render(doc)
28 | println(html)
29 | }
30 | }
--------------------------------------------------------------------------------