├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── .path
├── .travis.yml
├── LICENSE
├── PoE-Addon-Manager-Launcher.iml
├── README.md
├── pom.xml
└── src
├── PRE-2.0
├── main
│ ├── java
│ │ ├── API
│ │ │ └── GithubHandler.java
│ │ ├── GUI
│ │ │ ├── Configurator.java
│ │ │ ├── Configurator2Controller.java
│ │ │ ├── Configurator_Controller.java
│ │ │ ├── Data.java
│ │ │ ├── Data2.java
│ │ │ ├── LauncherUI.java
│ │ │ ├── LauncherUI_Controller.java
│ │ │ ├── PopUp
│ │ │ │ ├── PopUp_Controller.java
│ │ │ │ └── Popup.java
│ │ │ └── launcher_data.java
│ │ ├── Helper
│ │ │ ├── QuickSorter.java
│ │ │ ├── Release.java
│ │ │ └── UpdateCheckerClient.java
│ │ ├── Launcher.java
│ │ └── PAL
│ │ │ └── PALsettings.java
│ └── resources
│ │ ├── Configurator2.fxml
│ │ ├── Launcher.fxml
│ │ ├── Path.fxml
│ │ ├── bgi_big.png
│ │ ├── cancel.png
│ │ ├── cancel0.png
│ │ ├── gear0.png
│ │ ├── gear1.png
│ │ ├── popup.fxml
│ │ └── witch.png
├── pom.xml
└── test
│ └── java
│ └── Helper
│ ├── QuickSorterTest.java
│ └── ReleaseTest.java
└── main
├── kotlin
├── Constants.kt
├── Controller.kt
├── GithubHandler.kt
├── Launcher.kt
└── PoEScanner.kt
└── resources
├── Untitled-2.psd
├── bgi_big.png
├── cancel.png
├── cancel0.png
├── cu0.png
├── cu1.png
├── lp0.png
├── lp1.png
├── minimize.png
├── minimize_hl.png
├── mu0.png
├── mu1.png
├── settings.png
├── settings_hl.png
├── text.css
├── ui.fxml
└── witch.png
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/java,maven,eclipse,intellij
3 |
4 | ### Eclipse ###
5 |
6 | .metadata
7 | bin/
8 | tmp/
9 | *.tmp
10 | *.bak
11 | *.swp
12 | *~.nib
13 | local.properties
14 | .settings/
15 | .loadpath
16 | .recommenders
17 |
18 | # External tool builders
19 | .externalToolBuilders/
20 |
21 | # Locally stored "Eclipse launch configurations"
22 | *.launch
23 |
24 | # PyDev specific (Python IDE for Eclipse)
25 | *.pydevproject
26 |
27 | # CDT-specific (C/C++ Development Tooling)
28 | .cproject
29 |
30 | # CDT- autotools
31 | .autotools
32 |
33 | # Java annotation processor (APT)
34 | .factorypath
35 |
36 | # PDT-specific (PHP Development Tools)
37 | .buildpath
38 |
39 | # sbteclipse plugin
40 | .target
41 |
42 | # Tern plugin
43 | .tern-project
44 |
45 | # TeXlipse plugin
46 | .texlipse
47 |
48 | # STS (Spring Tool Suite)
49 | .springBeans
50 |
51 | # Code Recommenders
52 | .recommenders/
53 |
54 | # Annotation Processing
55 | .apt_generated/
56 |
57 | # Scala IDE specific (Scala & Java development for Eclipse)
58 | .cache-main
59 | .scala_dependencies
60 | .worksheet
61 |
62 | ### Eclipse Patch ###
63 | # Eclipse Core
64 | .project
65 |
66 | # JDT-specific (Eclipse Java Development Tools)
67 | .classpath
68 |
69 | # Annotation Processing
70 | .apt_generated
71 |
72 | ### Intellij ###
73 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
74 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
75 |
76 | # User-specific stuff
77 | .idea/**/workspace.xml
78 | .idea/**/tasks.xml
79 | .idea/**/usage.statistics.xml
80 | .idea/**/dictionaries
81 | .idea/**/shelf
82 |
83 | # Sensitive or high-churn files
84 | .idea/**/dataSources/
85 | .idea/**/dataSources.ids
86 | .idea/**/dataSources.local.xml
87 | .idea/**/sqlDataSources.xml
88 | .idea/**/dynamic.xml
89 | .idea/**/uiDesigner.xml
90 | .idea/**/dbnavigator.xml
91 |
92 | # Gradle
93 | .idea/**/gradle.xml
94 | .idea/**/libraries
95 |
96 | # Gradle and Maven with auto-import
97 | # When using Gradle or Maven with auto-import, you should exclude module files,
98 | # since they will be recreated, and may cause churn. Uncomment if using
99 | # auto-import.
100 | # .idea/modules.xml
101 | # .idea/*.iml
102 | # .idea/modules
103 |
104 | # CMake
105 | cmake-build-*/
106 |
107 | # Mongo Explorer plugin
108 | .idea/**/mongoSettings.xml
109 |
110 | # File-based project format
111 | *.iws
112 |
113 | # IntelliJ
114 | out/
115 |
116 | # mpeltonen/sbt-idea plugin
117 | .idea_modules/
118 |
119 | # JIRA plugin
120 | atlassian-ide-plugin.xml
121 |
122 | # Cursive Clojure plugin
123 | .idea/replstate.xml
124 |
125 | # Crashlytics plugin (for Android Studio and IntelliJ)
126 | com_crashlytics_export_strings.xml
127 | crashlytics.properties
128 | crashlytics-build.properties
129 | fabric.properties
130 |
131 | # Editor-based Rest Client
132 | .idea/httpRequests
133 |
134 | ### Intellij Patch ###
135 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
136 |
137 | # *.iml
138 | # modules.xml
139 | # .idea/misc.xml
140 | # *.ipr
141 |
142 | # Sonarlint plugin
143 | .idea/sonarlint
144 |
145 | ### Java ###
146 | # Compiled class file
147 | *.class
148 |
149 | # Log file
150 | *.log
151 |
152 | # BlueJ files
153 | *.ctxt
154 |
155 | # Mobile Tools for Java (J2ME)
156 | .mtj.tmp/
157 |
158 | # Package Files #
159 | *.jar
160 | *.war
161 | *.nar
162 | *.ear
163 | *.zip
164 | *.tar.gz
165 | *.rar
166 |
167 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
168 | hs_err_pid*
169 |
170 | ### Maven ###
171 | target/
172 | pom.xml.tag
173 | pom.xml.releaseBackup
174 | pom.xml.versionsBackup
175 | pom.xml.next
176 | release.properties
177 | dependency-reduced-pom.xml
178 | buildNumber.properties
179 | .mvn/timing.properties
180 | .mvn/wrapper/maven-wrapper.jar
181 |
182 |
183 | # End of https://www.gitignore.io/api/java,maven,eclipse,intellij
184 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | PoE-Addon-Manager-Launcher
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.path:
--------------------------------------------------------------------------------
1 | #Only change this if you know what you are doing!
2 | #Mon Sep 24 20:20:06 CEST 2018
3 | steam=
4 | standalone=
5 | version_folder=
6 | addon_folder=
7 | beta=
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/PoE-Addon-Manager-Launcher.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # USE THIS VERSION INSTEAD IS MORE UP TO DATE:
2 |
3 |
4 | [](https://travis-ci.org/POE-Addon-Launcher/PoE-Addon-Launcher)
5 |
6 | # PoE Addon Launcher (PAL)
7 | 
8 |
9 |
10 | Is a java based program, used for updating and managing several addons that are commonly used in Path of Exile.
11 |
12 | 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!
13 |
14 | Stay up to date with all your favourite addons.
15 |
16 | Currently Planned:
17 | - Most common addons available for downloading and updating.
18 | - Launching all addons and path of exile with one click.
19 |
20 | Work in Progress:
21 | - Overlay to be used in-game that will allow you to use browser based tools such as the Vorici Calc by Siveran.
22 | - Community Repositories
23 | - And much more?
24 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | PAL-Launcher
8 | rewrite
9 | 2.0.1
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 | Launcher
27 |
28 |
29 |
30 |
31 |
32 | maven-assembly-plugin
33 |
34 |
35 |
36 | Launcher
37 |
38 |
39 |
40 | jar-with-dependencies
41 |
42 |
43 |
44 |
45 | org.jetbrains.kotlin
46 | kotlin-maven-plugin
47 | ${kotlin.version}
48 |
49 |
50 | compile
51 | compile
52 |
53 | compile
54 |
55 |
56 |
57 | test-compile
58 | test-compile
59 |
60 | test-compile
61 |
62 |
63 |
64 |
65 | 1.8
66 |
67 |
68 |
69 | org.apache.maven.plugins
70 | maven-compiler-plugin
71 | 3.8.0
72 |
73 |
74 | compile
75 | compile
76 |
77 | compile
78 |
79 |
80 |
81 | testCompile
82 | test-compile
83 |
84 | testCompile
85 |
86 |
87 |
88 |
89 | 8
90 | 8
91 |
92 |
93 |
94 | org.jetbrains.kotlin
95 | kotlin-maven-plugin
96 | ${kotlin.version}
97 |
98 |
99 | compile
100 | process-sources
101 |
102 | compile
103 |
104 |
105 |
106 | src/main/java
107 | src/main/kotlin
108 | src/main/resources
109 |
110 |
111 |
112 |
113 | test-compile
114 | process-test-sources
115 |
116 | test-compile
117 |
118 |
119 |
120 | src/test/java
121 | src/test/kotlin
122 | src/test/resources
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | com.fasterxml.jackson.core
134 | jackson-databind
135 | 2.9.6
136 |
137 |
138 | com.fasterxml.jackson.module
139 | jackson-module-kotlin
140 | 2.9.4.1
141 |
142 |
143 | org.kohsuke
144 | github-api
145 | 1.93
146 |
147 |
148 | org.jetbrains.kotlin
149 | kotlin-stdlib-jdk8
150 | ${kotlin.version}
151 |
152 |
153 | org.jetbrains.kotlin
154 | kotlin-test-junit
155 | ${kotlin.version}
156 | test
157 |
158 |
159 | org.jetbrains.kotlinx
160 | kotlinx-coroutines-core
161 | 1.0.1
162 |
163 |
164 | org.jetbrains.kotlinx
165 | kotlinx-coroutines-javafx
166 | 1.0.1
167 |
168 |
169 | org.jetbrains.kotlin
170 | kotlin-stdlib-jdk8
171 | ${kotlin.version}
172 |
173 |
174 | org.jetbrains.kotlin
175 | kotlin-test
176 | ${kotlin.version}
177 | test
178 |
179 |
180 | org.jetbrains.kotlin
181 | kotlin-reflect
182 | 1.3.0
183 |
184 |
185 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/API/GithubHandler.java:
--------------------------------------------------------------------------------
1 | package API;
2 |
3 | import GUI.Data;
4 | import org.kohsuke.github.GitHub;
5 |
6 | import java.io.IOException;
7 |
8 | /**
9 | *
10 | */
11 | public class GithubHandler
12 | {
13 | public static boolean canQuerry(GitHub gitHub)
14 | {
15 | try
16 | {
17 | return gitHub.getRateLimit().remaining > 2;
18 | }
19 | catch (IOException e)
20 | {
21 | e.printStackTrace();
22 | }
23 | return false;
24 | }
25 |
26 | public static GitHub connect(String token)
27 | {
28 | if (token == null)
29 | {
30 | try
31 | {
32 | Data.setStatus("Connecting to GitHub anonymously");
33 | return GitHub.connectAnonymously();
34 | }
35 | catch (IOException e)
36 | {
37 | e.printStackTrace();
38 | }
39 | }
40 | if (token.equals(""))
41 | {
42 | try
43 | {
44 | Data.setStatus("Connecting to GitHub anonymously");
45 | return GitHub.connectAnonymously();
46 | }
47 | catch (IOException e)
48 | {
49 | e.printStackTrace();
50 | }
51 | }
52 | else
53 | {
54 | try
55 | {
56 | Data.setStatus("Connecting to GitHub using your token");
57 | return GitHub.connectUsingOAuth(token);
58 | }
59 | catch (IOException e)
60 | {
61 | e.printStackTrace();
62 | }
63 | }
64 | return null;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/Configurator.java:
--------------------------------------------------------------------------------
1 | package 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 |
10 | /**
11 | * Just a JavaFX class, nothing special.
12 | */
13 | public class Configurator extends Application
14 | {
15 | public static Stage stage;
16 |
17 | public void start(Stage primaryStage) throws Exception
18 | {
19 | primaryStage = new Stage();
20 | FXMLLoader fxmlLoader = new FXMLLoader();
21 | Parent root = fxmlLoader.load(getClass().getResource("/Configurator2.fxml"));
22 | primaryStage.setTitle("PAL: Configurator");
23 | primaryStage.getIcons().add(new Image(getClass().getResource("/witch.png").toString()));
24 | primaryStage.setResizable(false);
25 | primaryStage.setScene(new Scene(root, 308, 200));
26 | Configurator.stage = primaryStage;
27 | primaryStage.show();
28 | }
29 |
30 | public void ui_launch(String[] args)
31 | {
32 | launch(args);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/Configurator2Controller.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | import javafx.application.Platform;
4 | import javafx.collections.FXCollections;
5 | import javafx.collections.ObservableList;
6 | import javafx.event.ActionEvent;
7 | import javafx.fxml.FXML;
8 | import javafx.fxml.Initializable;
9 | import javafx.scene.control.Button;
10 | import javafx.scene.control.ListView;
11 | import javafx.scene.control.RadioButton;
12 | import javafx.scene.control.TextArea;
13 | import javafx.scene.control.ToggleGroup;
14 | import javafx.scene.layout.AnchorPane;
15 | import javafx.scene.text.Text;
16 | import javafx.stage.DirectoryChooser;
17 | import javafx.stage.Stage;
18 |
19 | import java.io.File;
20 | import java.net.URISyntaxException;
21 | import java.net.URL;
22 | import java.util.ResourceBundle;
23 |
24 | public class Configurator2Controller implements Initializable
25 | {
26 |
27 | @FXML
28 | private AnchorPane page3;
29 |
30 | @FXML
31 | private ListView PoEsList;
32 |
33 | @FXML
34 | private AnchorPane page1;
35 |
36 | @FXML
37 | private AnchorPane page2;
38 | @FXML
39 | private RadioButton rCustom;
40 |
41 | @FXML
42 | private Text label_path_install;
43 |
44 | @FXML
45 | private AnchorPane page4;
46 |
47 | @FXML
48 | private TextArea txtDump;
49 |
50 | private int curr_page = 1;
51 |
52 | @FXML
53 | void nextPage()
54 | {
55 | switch (curr_page)
56 | {
57 | case 1 : page2_show(); break;
58 | case 2 : page3_show(); break;
59 | case 3 : page4_show(); break;
60 | case 4 : launch_launcher(); break;
61 | }
62 | }
63 |
64 | private void launch_launcher()
65 | {
66 | // Save Settings
67 | Data2.getINSTANCE().setPoe_paths(poe_paths);
68 | try
69 | {
70 | Data2.getINSTANCE().setData(new launcher_data(install_dir, Configurator.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()));
71 | }
72 | catch (URISyntaxException e)
73 | {
74 | System.err.println("Can't find launcher location");
75 | Data2.getINSTANCE().setData(new launcher_data(install_dir, "0"));
76 | }
77 | Data2.getINSTANCE().saveLauncherData();
78 | Data2.getINSTANCE().savePoEpaths();
79 | Data2.getINSTANCE().createFolders();
80 |
81 | Configurator.stage.close();
82 | LauncherUI launcherUI = new LauncherUI();
83 | try
84 | {
85 | launcherUI.start(new Stage());
86 | }
87 | catch (Exception e)
88 | {
89 | e.printStackTrace();
90 | }
91 | }
92 |
93 | private void page4_show()
94 | {
95 | if (poe_paths.size() > 0)
96 | {
97 | showAndHide(page3, page4);
98 | txtDump.setText(genTextDump());
99 | curr_page++;
100 | }
101 | }
102 |
103 | private String genTextDump()
104 | {
105 | StringBuilder stringBuilder = new StringBuilder();
106 | stringBuilder.append("This data will be saved:\n\nInstall Directory: ");
107 | stringBuilder.append(install_dir);
108 | stringBuilder.append("\n\n");
109 | stringBuilder.append("PoE Executables:\n");
110 | for (String s : poe_paths)
111 | {
112 | stringBuilder.append(s);
113 | stringBuilder.append("\n");
114 | }
115 | return stringBuilder.toString();
116 | }
117 |
118 | private void page3_show()
119 | {
120 | if (rCustom.isSelected())
121 | {
122 | if (label_path_install.getText().equals("Directory has not been set!"))
123 | {
124 | label_path_install.setVisible(true);
125 | return;
126 | }
127 | }
128 | showAndHide(page2, page3);
129 | curr_page++;
130 | }
131 |
132 | private void page2_show()
133 | {
134 | Platform.runLater(() -> showAndHide(page1, page2));
135 | curr_page++;
136 | }
137 |
138 | private void showAndHide(AnchorPane from, AnchorPane to)
139 | {
140 | from.setVisible(false);
141 | to.setVisible(true);
142 | }
143 |
144 | /**
145 | * Method for Opening the DirectoryChooser.
146 | */
147 | public File browse(String title)
148 | {
149 | DirectoryChooser directoryChooser = new DirectoryChooser();
150 | directoryChooser.setTitle(title);
151 | return directoryChooser.showDialog(Configurator.stage);
152 | }
153 |
154 | private String install_dir = System.getenv("LOCALAPPDATA") + File.separator + "PAL";
155 |
156 | public void browseCustom()
157 | {
158 | File f = browse("Select a folder to install PAL to.");
159 | if (f.exists())
160 | {
161 | if (f.canWrite())
162 | {
163 | install_dir = f.getPath();
164 | Platform.runLater(() -> label_path_install.setText(install_dir));
165 | label_path_install.setVisible(true);
166 | }
167 | else
168 | {
169 | System.err.println("ERROR: CAN'T WRITE IN THIS FOLDER");
170 | }
171 | }
172 | }
173 |
174 | public void remove()
175 | {
176 | String selected = PoEsList.getSelectionModel().getSelectedItem();
177 | assert selected != null;
178 |
179 | PoEsList.getItems().remove(selected);
180 | }
181 |
182 | public void add()
183 | {
184 | File dir = browse("Select a Path of Exile Folder");
185 | if (dir.exists())
186 | {
187 | if (dir.isDirectory())
188 | {
189 | File[] filesInDir = dir.listFiles();
190 | checkDir(filesInDir);
191 | }
192 | }
193 | }
194 |
195 | private void checkDir(File[] filesInDir)
196 | {
197 | for (File f : filesInDir)
198 | {
199 | final String filename = f.getName();
200 | if (filename.equals("PathOfExile_x64Steam.exe"))
201 | {
202 | addToList(f.getPath());
203 | }
204 | else if (filename.equals("PathOfExile_x64.exe"))
205 | {
206 | addToList(f.getPath());
207 | }
208 | else if (filename.contains(".exe") && filename.contains("PathOfExile"))
209 | {
210 | addToList(f.getPath());
211 | }
212 | else
213 | {
214 | // No PoE Dir.
215 | }
216 | }
217 | }
218 |
219 | private ObservableList poe_paths = FXCollections.observableArrayList();
220 |
221 | private void addToList(String path)
222 | {
223 | //Concat
224 | poe_paths.add(path);
225 | PoEsList.refresh();
226 | }
227 |
228 | @Override
229 | public void initialize(URL location, ResourceBundle resources)
230 | {
231 | PoEsList.setItems(poe_paths);
232 | }
233 | }
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/Configurator_Controller.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | import javafx.application.Platform;
4 | import javafx.fxml.FXML;
5 | import javafx.scene.control.TextArea;
6 | import javafx.scene.control.TextField;
7 | import javafx.scene.layout.AnchorPane;
8 | import javafx.stage.DirectoryChooser;
9 | import javafx.stage.Stage;
10 |
11 | import java.io.File;
12 | import java.util.ArrayList;
13 | import java.util.Objects;
14 |
15 | /**
16 | * Controller for the Configurator.
17 | */
18 | @Deprecated
19 | public class Configurator_Controller
20 | {
21 | @FXML
22 | private AnchorPane step1;
23 |
24 | @FXML
25 | private AnchorPane step2;
26 |
27 | @FXML
28 | private TextField addon_text;
29 |
30 | @FXML
31 | private TextField text_versions;
32 |
33 | @FXML
34 | private AnchorPane step3;
35 |
36 | @FXML
37 | private TextField steam_path;
38 |
39 | @FXML
40 | private TextField path_standalone;
41 |
42 | @FXML
43 | private TextField path_beta;
44 |
45 | @FXML
46 | private AnchorPane step4;
47 |
48 | @FXML
49 | private TextArea txtDump;
50 |
51 | /**
52 | * Simple method for asking what the currently visible anchor pane is.
53 | * @return
54 | */
55 | private int visibleAnchorPane()
56 | {
57 | if (step1.isVisible())
58 | return 1;
59 | else if (step2.isVisible())
60 | return 2;
61 | else if (step3.isVisible())
62 | return 3;
63 | return 4;
64 | }
65 |
66 | /**
67 | * Handles what the next button does.
68 | */
69 | public void ButtonNext() throws Exception
70 | {
71 | int vis = visibleAnchorPane();
72 |
73 | switch (vis)
74 | {
75 | case 1 :
76 | Platform.runLater(() -> step1()); break;
77 | case 2 : step2(); break;
78 | case 3 : step3(); break;
79 | case 4 : step4(); break;
80 | }
81 | }
82 |
83 | /**
84 | * Shows step2 and hides step1.
85 | */
86 | public void step1()
87 | {
88 | step1.setVisible(false);
89 | step2.setVisible(true);
90 | }
91 |
92 | /**
93 | * Hides step 2, and shows step 3.
94 | * IF the path locations of Addons and Versions have been set by the user.
95 | */
96 | public void step2()
97 | {
98 | String addon_location = addon_text.getText();
99 | String version_location = text_versions.getText();
100 | boolean one_not_filled = false;
101 |
102 | File checker = new File(addon_location);
103 | if (!checker.exists())
104 | {
105 | updateText(addon_text, "This field must be filled in!");
106 | one_not_filled = true;
107 | }
108 | checker = new File(version_location);
109 | if (!checker.exists())
110 | {
111 | updateText(text_versions, "This field must be filled in!");
112 | one_not_filled = true;
113 | }
114 |
115 | if (one_not_filled)
116 | return;
117 |
118 | step2.setVisible(false);
119 | step3.setVisible(true);
120 | }
121 |
122 | /**
123 | * Helper method because I grew tired of typing this line.
124 | * It updates the text in a textfield.
125 | */
126 | public void updateText(TextField t, String s)
127 | {
128 | Platform.runLater(() -> t.setText(s));
129 | }
130 |
131 | /**
132 | * Hides step 3 and shows Step 4.
133 | * IF a user has provided at least one Path for Path of Exile.
134 | */
135 | public void step3()
136 | {
137 | ArrayList filled_in = new ArrayList<>();
138 | String p_steam = steam_path.getText();
139 | String p_standalone = path_standalone.getText();
140 | String p_beta = path_beta.getText();
141 |
142 | int init = 0;
143 |
144 | if (checkIfFilledIn(p_steam))
145 | {
146 | init++;
147 | filled_in.add(steam_path);
148 | }
149 | if (checkIfFilledIn(p_standalone))
150 | {
151 | init++;
152 | filled_in.add(path_standalone);
153 | }
154 | if (checkIfFilledIn(p_beta))
155 | {
156 | init++;
157 | filled_in.add(path_beta);
158 | }
159 |
160 | if (init < 1)
161 | return;
162 |
163 | boolean stopper = false;
164 |
165 | for (TextField field : filled_in)
166 | {
167 | File f = new File(field.getText());
168 | if (!f.exists())
169 | {
170 | updateText(field, "ERROR, TRY AGAIN");
171 | stopper = true;
172 | }
173 | }
174 |
175 | if (stopper)
176 | return;
177 |
178 | // Finally check for a runnable .exe
179 | for (TextField field : filled_in)
180 | {
181 | if (!dirChecker(Objects.requireNonNull(new File(field.getText()).listFiles())))
182 | {
183 | updateText(field, "No PoE Executable was found.");
184 | stopper = true;
185 | }
186 | }
187 |
188 | if (stopper)
189 | return;
190 |
191 | Platform.runLater(() -> txtDump.setText(textDump()));
192 |
193 | step3.setVisible(false);
194 | step4.setVisible(true);
195 | }
196 |
197 | /**
198 | * Checks a Dir for being a valid Path of Exile installation Folder.
199 | */
200 | public boolean dirChecker(File[] listOfFiles)
201 | {
202 | for (File f : listOfFiles)
203 | {
204 | String name = f.getName();
205 | switch (name)
206 | {
207 | case "Client.exe":
208 | return true;
209 | case "PathOfExile.exe":
210 | return true;
211 | case "PathOfExileSteam.exe":
212 | return true;
213 | case "PathOfExile_x64.exe":
214 | return true;
215 | case "PathOfExile_x64Steam.exe":
216 | return true;
217 | }
218 | }
219 | return false;
220 | }
221 |
222 | /**
223 | * Method for generating the text dump during Step 4.
224 | */
225 | public String textDump()
226 | {
227 | StringBuilder stringBuilder = new StringBuilder();
228 | stringBuilder.append("This data will be stored:\n\nAddons Folder:\n");
229 | stringBuilder.append(addon_text.getText());
230 | stringBuilder.append("\n\nVersions Folder:\n");
231 | stringBuilder.append(text_versions.getText());
232 | stringBuilder.append("\n\nPath of Exile Folder(s):\nSteam->");
233 | stringBuilder.append(steam_path.getText());
234 | stringBuilder.append("\nStand Alone->");
235 | stringBuilder.append(path_standalone.getText());
236 | stringBuilder.append("\nBETA Client->");
237 | stringBuilder.append(path_beta.getText());
238 | return stringBuilder.toString();
239 | }
240 |
241 | /**
242 | * Helper method for Step 3.
243 | */
244 | public boolean checkIfFilledIn(String string)
245 | {
246 | return !string.equals("") && !string.equals("ERROR, TRY AGAIN") && !string.equals("No PoE Executable was found.");
247 | }
248 |
249 | /**
250 | * Commits the Paths to a .path file.
251 | * Hides the Configurator and launches the LauncherUI.
252 | */
253 | public void step4() throws Exception
254 | {
255 | // Save Settings
256 | Data.getINSTANCE().setAddon_path(addon_text.getText());
257 | Data.getINSTANCE().setProgram_path(text_versions.getText());
258 | Data.getINSTANCE().setBeta_path(path_beta.getText());
259 | Data.getINSTANCE().setStand_alone(path_standalone.getText());
260 | Data.getINSTANCE().setSteam_path(steam_path.getText());
261 |
262 | Data.getINSTANCE().createProperties();
263 |
264 | Configurator.stage.close();
265 | LauncherUI launcherUI = new LauncherUI();
266 | launcherUI.start(new Stage());
267 | }
268 |
269 | /**
270 | * Opens the Browser, method defined in Path.fxml
271 | */
272 | public void browseAddonFolder()
273 | {
274 | File f = browse("Browse for a folder to download addons to:");
275 | if (f==null)
276 | return;
277 | Platform.runLater(() -> addon_text.setText(f.getPath()));
278 | }
279 |
280 | /**
281 | * Opens the Browser, method defined in Path.fxml
282 | */
283 | public void browseVersionFolder()
284 | {
285 | File f = browse("Browse for a folder to install PAL to:");
286 | if (f==null)
287 | return;
288 | Platform.runLater(() -> text_versions.setText(f.getPath()));
289 | }
290 |
291 | /**
292 | * Opens the Browser, method defined in Path.fxml
293 | */
294 | public void browseBetaVersion()
295 | {
296 | File f = browse("Browse for your steam version of Path of Exile");
297 | if (f==null)
298 | return;
299 | Platform.runLater(() -> path_beta.setText(f.getPath()));
300 | }
301 |
302 | /**
303 | * Opens the Browser, method defined in Path.fxml
304 | */
305 | public void browseStandAloneVersion()
306 | {
307 | File f = browse("Browse for your stand-alone version of Path of Exile");
308 | if (f==null)
309 | return;
310 | Platform.runLater(() -> path_standalone.setText(f.getPath()));
311 | }
312 |
313 | /**
314 | * Opens the Browser, method defined in Path.fxml
315 | */
316 | public void browseSteamFolder()
317 | {
318 | File f = browse("Browse for a beta version of Path of Exile");
319 | if (f==null)
320 | return;
321 | Platform.runLater(() -> steam_path.setText(f.getPath()));
322 | }
323 |
324 | /**
325 | * Method for Opening the DirectoryChooser.
326 | */
327 | public File browse(String title)
328 | {
329 | DirectoryChooser directoryChooser = new DirectoryChooser();
330 | directoryChooser.setTitle(title);
331 | return directoryChooser.showDialog(Configurator.stage);
332 | }
333 |
334 |
335 | }
336 |
337 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/Data.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | import java.io.*;
4 | import java.util.ArrayList;
5 | import java.util.Properties;
6 |
7 | /**
8 | * PAL Class.
9 | * *gasp* That's not proper coding!
10 | * Yes, but it is so much easier than doing it proper :).
11 | */
12 | @Deprecated
13 | public final class Data
14 | {
15 | private static final Data INSTANCE = new Data();
16 | private static double progress = 0;
17 | private static String status = "";
18 | private String addon_path = "";
19 | private String program_path = "";
20 | private String steam_path = "";
21 | private String stand_alone = "";
22 | private String beta_path = "";
23 | private String jar_filepath = "";
24 |
25 | private Data()
26 | {}
27 |
28 | public static Data getINSTANCE()
29 | {
30 | return INSTANCE;
31 | }
32 |
33 | public static double getProgress()
34 | {
35 | return progress;
36 | }
37 |
38 | public static void setProgress(double progress)
39 | {
40 | Data.progress = progress;
41 | }
42 |
43 | public static String getStatus()
44 | {
45 | return status;
46 | }
47 |
48 | public static void setStatus(String status)
49 | {
50 | System.out.println(status);
51 | Data.status = status;
52 | }
53 |
54 | /**
55 | * Create properies.
56 | */
57 | public void createProperties()
58 | {
59 | Properties poe_paths = new Properties();
60 | OutputStream out = null;
61 | OutputStream secondary = null;
62 |
63 | File f = new File(program_path + "/.settings");
64 |
65 | try
66 | {
67 | out = new FileOutputStream(".path");
68 | poe_paths.setProperty("addon_folder", addon_path);
69 | poe_paths.setProperty("version_folder", program_path);
70 | poe_paths.setProperty("steam", steam_path);
71 | poe_paths.setProperty("standalone", stand_alone);
72 | poe_paths.setProperty("beta", beta_path);
73 | poe_paths.store(out, "Only change this if you know what you are doing!");
74 |
75 | if (!f.exists())
76 | {
77 | secondary = new FileOutputStream(f.getPath());
78 | poe_paths.store(secondary, "Only change this if you know what you are doing!");
79 | }
80 |
81 | }
82 | catch (IOException ex)
83 | {
84 | ex.printStackTrace();
85 | }
86 | finally
87 | {
88 | if (out != null)
89 | {
90 | try
91 | {
92 | out.close();
93 | }
94 | catch (IOException ex)
95 | {
96 | ex.printStackTrace();
97 | }
98 | }
99 | if (secondary != null)
100 | {
101 | try
102 | {
103 | secondary.close();
104 | }
105 | catch (IOException e)
106 | {
107 | e.printStackTrace();
108 | }
109 | }
110 | }
111 | }
112 |
113 | /**
114 | * Creates a list of Dirs.
115 | */
116 | public ArrayList createListOfDirs(String... args)
117 | {
118 | ArrayList check_locations = new ArrayList<>();
119 | for (String s : args)
120 | {
121 | if (!s.equals(""))
122 | {
123 | check_locations.add(s);
124 | }
125 | }
126 | return check_locations;
127 | }
128 |
129 | /**
130 | * Checks if we have more than 2 Dirs in the .path file.
131 | * (Final safety check)
132 | */
133 | public boolean checkDirs()
134 | {
135 | ArrayList dirs = createListOfDirs(addon_path, program_path, steam_path, stand_alone, beta_path);
136 |
137 | // Versions & Addons are set, but no game path.
138 | if (dirs.size() <= 2)
139 | return false;
140 |
141 | for (String s : dirs)
142 | {
143 | File f = new File(s);
144 | // One of the paths no longer exists.
145 | if (!f.exists())
146 | {
147 | return false;
148 | }
149 | }
150 | return true;
151 | }
152 |
153 | /**
154 | * Reads from the .path properties file.
155 | */
156 | public void readProperties()
157 | {
158 | if (!checkProperties())
159 | {
160 | createProperties();
161 | }
162 | Properties poe_paths = new Properties();
163 | InputStream in = null;
164 |
165 | try
166 | {
167 | in = new FileInputStream(".path");
168 | poe_paths.load(in);
169 | addon_path = poe_paths.getProperty("addon_folder");
170 | program_path = poe_paths.getProperty("version_folder");
171 | steam_path = poe_paths.getProperty("steam");
172 | stand_alone = poe_paths.getProperty("standalone");
173 | beta_path = poe_paths.getProperty("beta");
174 | }
175 | catch (FileNotFoundException e)
176 | {
177 | e.printStackTrace();
178 | } catch (IOException e)
179 | {
180 | e.printStackTrace();
181 | }
182 | finally
183 | {
184 | if (in != null)
185 | {
186 | try
187 | {
188 | in.close();
189 | } catch (IOException e)
190 | {
191 | e.printStackTrace();
192 | }
193 | }
194 | }
195 | }
196 |
197 | /**
198 | * Check if the .path properties file exists.
199 | */
200 | public boolean checkProperties()
201 | {
202 | File f = new File(".path");
203 | return f.exists();
204 | }
205 |
206 | public String getAddon_path()
207 | {
208 | return addon_path;
209 | }
210 |
211 | public void setAddon_path(String addon_path)
212 | {
213 | this.addon_path = addon_path;
214 | }
215 |
216 | public String getProgram_path()
217 | {
218 | return program_path;
219 | }
220 |
221 | public void setProgram_path(String program_path)
222 | {
223 | this.program_path = program_path;
224 | }
225 |
226 | public String getSteam_path()
227 | {
228 | return steam_path;
229 | }
230 |
231 | public void setSteam_path(String steam_path)
232 | {
233 | this.steam_path = steam_path;
234 | }
235 |
236 | public String getStand_alone()
237 | {
238 | return stand_alone;
239 | }
240 |
241 | public void setStand_alone(String stand_alone)
242 | {
243 | this.stand_alone = stand_alone;
244 | }
245 |
246 | public String getBeta_path()
247 | {
248 | return beta_path;
249 | }
250 |
251 | public void setBeta_path(String beta_path)
252 | {
253 | this.beta_path = beta_path;
254 | }
255 |
256 | public String getJar_filepath()
257 | {
258 | return jar_filepath;
259 | }
260 |
261 | public void setJar_filepath(String jar_filepath)
262 | {
263 | this.jar_filepath = jar_filepath;
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/Data2.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import javafx.collections.ObservableList;
5 |
6 | import java.io.*;
7 | import java.util.Properties;
8 |
9 | /**
10 | * .data
11 | */
12 | public final class Data2
13 | {
14 | private static final Data2 INSTANCE = new Data2();
15 |
16 | private Data2()
17 | {}
18 |
19 | public static Data2 getINSTANCE()
20 | {
21 | return INSTANCE;
22 | }
23 |
24 | private ObservableList poe_paths;
25 | private launcher_data data;
26 | private String local = System.getenv("LOCALAPPDATA");
27 | private String jar_name_to_launch;
28 |
29 | public void savePoEpaths()
30 | {
31 | File f = new File(local + File.separator + "PAL" + File.separator + "poe_paths.pal");
32 | if (f.exists())
33 | {
34 | f.delete();
35 | }
36 |
37 | String[] array = new String[poe_paths.size()];
38 | for (int c = 0; c < array.length; c++)
39 | {
40 | array[c] = poe_paths.get(c);
41 | }
42 |
43 | ObjectMapper objectMapper = new ObjectMapper();
44 | if (array.length > 0)
45 | {
46 | try
47 | {
48 | objectMapper.writeValue(f, array);
49 | }
50 | catch (IOException e)
51 | {
52 | e.printStackTrace();
53 | }
54 | }
55 | }
56 |
57 | public void saveLauncherData()
58 | {
59 | File f = new File(local + File.separator + "PAL" + File.separator + "launcher_data.pal");
60 | if (f.exists())
61 | {
62 | f.delete();
63 | }
64 |
65 | ObjectMapper objectMapper = new ObjectMapper();
66 | try
67 | {
68 | objectMapper.writeValue(f, data);
69 | }
70 | catch (IOException e)
71 | {
72 | e.printStackTrace();
73 | }
74 | }
75 |
76 |
77 | /**
78 | * Read launcher data.
79 | */
80 | public boolean readLauncherData()
81 | {
82 | String local = System.getenv("LOCALAPPDATA");
83 | File f = new File(local + File.separator + "PAL" + File.separator + "launcher_data.pal");
84 | if (f.exists())
85 | {
86 | ObjectMapper objectMapper = new ObjectMapper();
87 | try
88 | {
89 | data = objectMapper.readValue(f, launcher_data.class);
90 | return true;
91 | }
92 | catch (IOException e)
93 | {
94 | e.printStackTrace();
95 | }
96 | }
97 | return false;
98 | }
99 |
100 | public ObservableList getPoe_paths()
101 | {
102 | return poe_paths;
103 | }
104 |
105 | public void setPoe_paths(ObservableList poe_paths)
106 | {
107 | this.poe_paths = poe_paths;
108 | }
109 |
110 | public launcher_data getData()
111 | {
112 | return data;
113 | }
114 |
115 | public void setData(launcher_data data)
116 | {
117 | this.data = data;
118 | }
119 |
120 | public String getLocal()
121 | {
122 | return local;
123 | }
124 |
125 | public void setLocal(String local)
126 | {
127 | this.local = local;
128 | }
129 |
130 | public String getCoreFolder()
131 | {
132 | return data.getInstall_dir() + File.separator + "Core";
133 | }
134 |
135 | public String getAddonFolder()
136 | {
137 | return data.getInstall_dir() + File.separator + "Addons";
138 | }
139 |
140 | public void createFolders()
141 | {
142 | createFolder("Addons");
143 | createFolder("Core");
144 | createFolder("temp_downloads");
145 | }
146 |
147 | public void createFolder(String name)
148 | {
149 | File file = new File(data.getInstall_dir() + File.separator + name);
150 | if (file.exists())
151 | {
152 | System.err.println("Trying to create " + name + "folder but it already exists this shouldn't happen!");
153 |
154 | }
155 | else
156 | {
157 | boolean mkdir = file.mkdir();
158 | if (!mkdir)
159 | {
160 | System.err.println("Can't make directory: " + file.getPath());
161 | }
162 | }
163 | }
164 |
165 | public void createPALfolder()
166 | {
167 | File pal_folder = new File(local + File.separator + "PAL");
168 | if (!pal_folder.exists())
169 | {
170 | pal_folder.mkdir();
171 | }
172 | }
173 |
174 | public String getJar_name_to_launch()
175 | {
176 | return jar_name_to_launch;
177 | }
178 |
179 | public void setJar_name_to_launch(String jar_name_to_launch)
180 | {
181 | this.jar_name_to_launch = jar_name_to_launch;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/LauncherUI.java:
--------------------------------------------------------------------------------
1 | package 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 | * Just a JavaFX class, nothing special.
13 | */
14 | public class LauncherUI extends Application
15 | {
16 | public static Stage stage;
17 |
18 | public void start(Stage primaryStage) throws Exception
19 | {
20 | primaryStage = new Stage();
21 | FXMLLoader fxmlLoader = new FXMLLoader();
22 | primaryStage.initStyle(StageStyle.UNDECORATED);
23 | Parent root = fxmlLoader.load(getClass().getResource("/Launcher.fxml"));
24 | primaryStage.setTitle("PAL: Launcher");
25 | primaryStage.getIcons().add(new Image(getClass().getResource("/witch.png").toString()));
26 | primaryStage.setScene(new Scene(root, 400, 250));
27 | stage = primaryStage;
28 | primaryStage.show();
29 | }
30 |
31 | public void ui_launch(String[] args)
32 | {
33 | launch(args);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/LauncherUI_Controller.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | import API.GithubHandler;
4 | import GUI.PopUp.Popup;
5 | import Helper.QuickSorter;
6 | import Helper.Release;
7 | import Helper.UpdateCheckerClient;
8 | import PAL.*;
9 | import com.fasterxml.jackson.databind.ObjectMapper;
10 | import javafx.application.Platform;
11 | import javafx.fxml.FXML;
12 | import javafx.fxml.Initializable;
13 | import javafx.scene.text.Text;
14 | import javafx.stage.Stage;
15 | import org.kohsuke.github.GHRepository;
16 | import org.kohsuke.github.GitHub;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.net.URL;
21 | import java.util.ArrayList;
22 | import java.util.ResourceBundle;
23 |
24 | /**
25 | * LauncherUI_Controller does the following:
26 | * Shows a graphical splash screen that shows some information.
27 | * Creates a list of @{Release} from the github API.
28 | * Checks the versions folder (pre-selected by user) for the available versions.
29 | * Downloads a new version if one is available.
30 | * Launches the the most recent jar.
31 | */
32 | public class LauncherUI_Controller implements Initializable
33 | {
34 | @FXML
35 | private Text status_text;
36 |
37 | /**
38 | * Initialize the daemons.
39 | */
40 | public void initialize(URL location, ResourceBundle resources)
41 | {
42 | cleanUp();
43 | daemon_progress();
44 | daemon_checker();
45 | daemon_launch();
46 | }
47 |
48 | private boolean isNewer(String _old, String _new)
49 | {
50 | _old = _old.replace("b", "");
51 | _old = _old.replace(".jar", "");
52 | _new = _new.replace("b", "");
53 | _new =_new.replace(".jar", "");
54 |
55 | int num_old = Integer.parseInt(_old);
56 | int num_new = Integer.parseInt(_new);
57 |
58 | return num_new > num_old;
59 | }
60 |
61 | private File mr_jar;
62 | private void cleanUp()
63 | {
64 | File f = new File(Data2.getINSTANCE().getCoreFolder());
65 | if (f.exists())
66 | {
67 | if (f.isDirectory())
68 | {
69 | File[] files = f.listFiles();
70 | File most_recent_jar = new File("b0.jar");
71 | for (File file : files)
72 | {
73 | if (file.getName().contains(".jar"))
74 | {
75 | if (isNewer(most_recent_jar.getName(), file.getName()))
76 | {
77 | most_recent_jar = file;
78 | }
79 | }
80 | }
81 | mr_jar = most_recent_jar;
82 | for (File file : files)
83 | {
84 | if (file.getName().contains(".jar"))
85 | {
86 | if (!file.getName().equals(most_recent_jar.getName()))
87 | {
88 | file.delete();
89 | }
90 | }
91 | }
92 | }
93 | }
94 | }
95 |
96 | /**
97 | * This daemon will terminate the launcher and launch the core program.
98 | */
99 | private void daemon_launch()
100 | {
101 | Runnable r = () ->
102 | {
103 | while (true)
104 | {
105 | try
106 | {
107 | Thread.sleep(300L);
108 | } catch (InterruptedException e)
109 | {
110 | e.printStackTrace();
111 | }
112 | if (Data.getProgress() == 1.0d)
113 | {
114 | // Launch and close current UI.
115 | Runtime runtime = Runtime.getRuntime();
116 | try
117 | {
118 | runtime.exec("java -jar " + Data2.getINSTANCE().getJar_name_to_launch());
119 | } catch (IOException e)
120 | {
121 | e.printStackTrace();
122 | }
123 |
124 | Stage s = LauncherUI.stage;
125 | Platform.runLater(() -> s.close());
126 | break;
127 | }
128 | }
129 | };
130 | Thread t_launch = new Thread(r);
131 | t_launch.setDaemon(true);
132 | t_launch.start();
133 | }
134 |
135 | private String github_token = null;
136 |
137 | public boolean readCoreSettings()
138 | {
139 | File core_settings_pal = new File(Data2.getINSTANCE().getLocal() + File.separator + "PAL" + File.separator + "core_settings.pal");
140 |
141 | PALsettings palsettings = new PALsettings(false, "", true, "", true, false, "", "", false, false);
142 |
143 | if (core_settings_pal.exists())
144 | {
145 | ObjectMapper objectMapper = new ObjectMapper();
146 | try
147 | {
148 | palsettings = objectMapper.readValue(core_settings_pal, PALsettings.class);
149 | github_token = palsettings.getGithub_token();
150 | return true;
151 | }
152 | catch (IOException e)
153 | {
154 | e.printStackTrace();
155 | }
156 | }
157 | return false;
158 | }
159 |
160 | private void noAPIrequests()
161 | {
162 | File f = new File(Data2.getINSTANCE().getCoreFolder());
163 | if (f.exists())
164 | {
165 | if (f.isDirectory())
166 | {
167 | Popup popup = new Popup();
168 | for (File f_ : f.listFiles())
169 | {
170 | if (f_.getName().matches("b(\\d){0,9999999}(.jar)"))
171 | {
172 | Popup.files.add(f_);
173 | }
174 | }
175 |
176 | Platform.runLater(() ->
177 | {
178 | try
179 | {
180 | popup.start(new Stage());
181 | }
182 | catch (Exception e)
183 | {
184 | e.printStackTrace();
185 | }
186 | });
187 | final String wait = "Waiting for user to select an option...";
188 | while (true)
189 | {
190 | if (!Data.getStatus().equals(wait))
191 | Data.setStatus(wait);
192 |
193 | try
194 | {
195 | Thread.sleep(300L);
196 | }
197 | catch (InterruptedException e)
198 | {
199 | e.printStackTrace();
200 | }
201 | if (Popup.jar != null)
202 | {
203 | Data.setStatus("Attempting to launch: " + Popup.jar.getName());
204 | Platform.runLater(() -> Popup.stage.close());
205 | runSpecificVersion(Popup.jar);
206 | break;
207 | }
208 |
209 | if (!Popup.url.equals("NOTSET"))
210 | {
211 | Platform.runLater(() -> Popup.stage.close());
212 | Data.setStatus("Attempting to download from: " + Popup.url);
213 | // Download and run.
214 | String jar = UpdateCheckerClient.getINSTANCE().downloadUpdate(Popup.url);
215 | if (jar.equals("NO_DOWNLOAD"))
216 | {
217 | Platform.runLater(() ->
218 | {
219 | try
220 | {
221 | popup.start(new Stage());
222 | }
223 | catch (Exception e)
224 | {
225 | e.printStackTrace();
226 | }
227 | });
228 | }
229 | else
230 | {
231 | runSpecificVersion(new File(jar));
232 | break;
233 | }
234 | }
235 | }
236 | }
237 | else
238 | {
239 | System.out.println("Core folder is not a directory?");
240 | }
241 | }
242 | else
243 | {
244 | System.out.println("Core folder doesn't exist!");
245 | }
246 | }
247 |
248 | /**
249 | * Core checking thread.
250 | */
251 | private void daemon_checker()
252 | {
253 | Runnable r = () ->
254 | {
255 | Data.setProgress(0.0);
256 |
257 | // Check if core_settings.pal exists and get Github API Token.
258 | Data.setStatus("Attempting to read core_settings.pal");
259 | readCoreSettings();
260 |
261 | boolean canConnect;
262 | GitHub gitHub = GithubHandler.connect(github_token);
263 | assert gitHub != null;
264 | canConnect = GithubHandler.canQuerry(gitHub);
265 |
266 | if (canConnect)
267 | {
268 | try
269 | {
270 | GHRepository repository = gitHub.getRepository("POE-Addon-Launcher/Core");
271 |
272 | String current_most_recent = repository.getLatestRelease().getTagName() + ".jar";
273 |
274 | File f = new File(Data2.getINSTANCE().getCoreFolder());
275 |
276 | if (!f.exists())
277 | {
278 | f.mkdir();
279 | }
280 |
281 | if (f.listFiles() != null)
282 | {
283 | for (File f_ : f.listFiles())
284 | {
285 | if (f_.getName().equals(current_most_recent))
286 | {
287 | Data.setStatus("You have " + current_most_recent + " which is the most recent build!");
288 | runSpecificVersion(f_);
289 | return;
290 | }
291 | }
292 | }
293 |
294 | Data.setStatus("You are out of date! Downloading new version...");
295 | String jar = UpdateCheckerClient.getINSTANCE().downloadUpdate(repository.getLatestRelease().getAssets().get(0).getBrowserDownloadUrl());
296 | runSpecificVersion(new File(jar));
297 | }
298 | catch (IOException e)
299 | {
300 | e.printStackTrace();
301 | }
302 | }
303 | else
304 | {
305 | Data.setStatus("You have no GitHub API requests left; Get yourself a GitHub API Token!");
306 | noAPIrequests();
307 | }
308 |
309 |
310 | //PAL.getINSTANCE().createProperties();
311 | /*
312 | // Create Releases Array
313 | Data.setStatus("Accessing github for releases");
314 | ArrayList releases = UpdateCheckerClient.getINSTANCE().getReleases();
315 | if (releases == null)
316 | {
317 | // Check dir for files.
318 |
319 | }
320 | else
321 | {
322 | Data.setStatus("Got all " + releases.size() + " releases!");
323 |
324 | Data.setStatus("Checking if we're up to date");
325 | // Launch Checker
326 | UpdateCheckerClient.getINSTANCE().downloadUpdate(getMostRecentRelease(releases));
327 | }
328 | */
329 | Data.setStatus("Up to date, launching program!");
330 | Data.setProgress(1.0);
331 | };
332 | Thread t = new Thread(r);
333 | t.setDaemon(true);
334 | t.start();
335 | }
336 |
337 | private void runSpecificVersion(File file)
338 | {
339 | Runtime runtime = Runtime.getRuntime();
340 | try
341 | {
342 | runtime.exec("java -jar " + "\"" + file.getPath() + "\"");
343 | } catch (IOException e)
344 | {
345 | e.printStackTrace();
346 | }
347 |
348 | Stage s = LauncherUI.stage;
349 | Platform.runLater(() -> s.close());
350 |
351 | }
352 |
353 | /**
354 | * Retrieves the most recent release from an ArrayList.
355 | * (*Probably shouldn't be in this class)
356 | */
357 | private Release getMostRecentRelease(ArrayList releases)
358 | {
359 | QuickSorter quickSorter = new QuickSorter();
360 |
361 | Release[] array = new Release[releases.size()];
362 |
363 | for (int c = 0; c < releases.size(); c++)
364 | {
365 | if (releases.get(c) != null)
366 | {
367 | array[c] = releases.get(c);
368 | }
369 | }
370 | System.out.println(array[0].toString());
371 | // Sort by Highest Number (latest release)
372 | quickSorter.sort(array);
373 | return array[0];
374 | }
375 |
376 | /**
377 | * Handles updating the progressbar and the status text.
378 | */
379 | private void daemon_progress()
380 | {
381 | Runnable r = () ->
382 | {
383 | while (true)
384 | {
385 | if (!status_text.getText().equals(Data.getStatus()))
386 | {
387 | Platform.runLater(() -> status_text.setText(Data.getStatus()));
388 | }
389 | try
390 | {
391 | Thread.sleep(300L);
392 | } catch (InterruptedException e)
393 | {
394 | e.printStackTrace();
395 | }
396 | }
397 | // Launch Main UI.
398 | };
399 | Thread t = new Thread(r);
400 | t.setDaemon(true);
401 | t.start();
402 | }
403 | }
404 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/PopUp/PopUp_Controller.java:
--------------------------------------------------------------------------------
1 | package GUI.PopUp;
2 |
3 | import javafx.application.Platform;
4 | import javafx.event.ActionEvent;
5 | import javafx.fxml.FXML;
6 | import javafx.fxml.Initializable;
7 | import javafx.scene.control.Button;
8 | import javafx.scene.control.ChoiceBox;
9 | import javafx.scene.control.RadioButton;
10 | import javafx.scene.control.TextField;
11 | import javafx.scene.image.Image;
12 | import javafx.scene.image.ImageView;
13 | import javafx.scene.input.MouseEvent;
14 | import javafx.scene.text.Text;
15 |
16 | import java.awt.*;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.net.URI;
20 | import java.net.URISyntaxException;
21 | import java.net.URL;
22 | import java.util.ResourceBundle;
23 |
24 | public class PopUp_Controller implements Initializable
25 | {
26 |
27 | @FXML
28 | private Text bold_text;
29 |
30 | @FXML
31 | private ImageView topbar_image_closeWindow;
32 |
33 | @FXML
34 | private Text topbar_text;
35 |
36 | @FXML
37 | private ChoiceBox comboFiles;
38 |
39 | @FXML
40 | private Text topbar_text1;
41 |
42 | @FXML
43 | private Text topbar_text11;
44 |
45 | @FXML
46 | private Text topbar_text111;
47 |
48 | @FXML
49 | private Button bOpenBrowser;
50 |
51 | @FXML
52 | private TextField fieldDL_Link;
53 |
54 | @FXML
55 | private Text topbar_text1111;
56 |
57 | @FXML
58 | private Button bContinue;
59 |
60 | @FXML
61 | private RadioButton rDL;
62 |
63 | @FXML
64 | private RadioButton rLocal;
65 |
66 | @FXML
67 | void continue_program(ActionEvent event)
68 | {
69 | if (rLocal.isSelected())
70 | {
71 | File f = comboFiles.getSelectionModel().getSelectedItem();
72 | if (f != null)
73 | {
74 | if (f.exists())
75 | {
76 | Popup.jar = f;
77 | }
78 | }
79 | }
80 | else
81 | {
82 | // Check DL link.
83 | String str = fieldDL_Link.getText();
84 | if (str.matches("(https://github.com/POE-Addon-Launcher/Core/releases/download/b)(\\d){1,9999999}(/b)(\\d){1,9999999}(.jar)"))
85 | {
86 | Popup.url = str;
87 | }
88 | else
89 | {
90 | Platform.runLater(() -> topbar_text1111.setText("ERROR: Your download link is not valid!"));
91 | }
92 | }
93 | }
94 |
95 |
96 | @FXML
97 | void openBrowser()
98 | {
99 | if (Desktop.isDesktopSupported())
100 | {
101 | try
102 | {
103 | Desktop.getDesktop().browse(new URI("https://github.com/POE-Addon-Launcher/Core/releases"));
104 | }
105 | catch (IOException e)
106 | {
107 | e.printStackTrace();
108 | Platform.runLater(() -> topbar_text1111.setText("Can't open browser, please go to https://github.com/POE-Addon-Launcher/Core/releases"));
109 |
110 | }
111 | catch (URISyntaxException e)
112 | {
113 | e.printStackTrace();
114 | Platform.runLater(() -> topbar_text1111.setText("Can't open browser, please go to https://github.com/POE-Addon-Launcher/Core/releases"));
115 | }
116 | }
117 | else
118 | {
119 | Platform.runLater(() -> topbar_text1111.setText("Can't open browser, please go to https://github.com/POE-Addon-Launcher/Core/releases"));
120 | }
121 | }
122 |
123 | private double xOffset = 0;
124 | private double yOffset = 0;
125 |
126 | @FXML
127 | public void onMouseDragged(MouseEvent mouseEvent)
128 | {
129 | Popup.stage.setX(mouseEvent.getScreenX() + xOffset);
130 | Popup.stage.setY(mouseEvent.getScreenY() + yOffset);
131 | }
132 |
133 | @FXML
134 | public void onMousePressed(MouseEvent mouseEvent)
135 | {
136 | xOffset = Popup.stage.getX() - mouseEvent.getScreenX();
137 | yOffset = Popup.stage.getY() - mouseEvent.getScreenY();
138 | }
139 |
140 | @FXML
141 | public void topbar_closeWIndow_onMouseClicked()
142 | {
143 | Popup.stage.close();
144 | Popup.jar = Popup.files.get(Popup.files.size()-1);
145 | }
146 |
147 | @FXML
148 | public void topbar_closeWindow_onMouseEntered()
149 | {
150 | changeImage(topbar_image_closeWindow, "/cancel.png");
151 | }
152 |
153 | @FXML
154 | public void topbar_closeWindow_onMouseExited()
155 | {
156 | changeImage(topbar_image_closeWindow, "/cancel0.png");
157 | }
158 |
159 | private void changeImage(ImageView imageView, String s)
160 | {
161 | Platform.runLater(() -> imageView.setImage(new Image(getClass().getResource(s).toString())));
162 | }
163 |
164 | @Override
165 | public void initialize(URL location, ResourceBundle resources)
166 | {
167 | Platform.runLater(() -> comboFiles.setItems(Popup.files));
168 | daemon_radio();
169 | }
170 |
171 | public void daemon_radio()
172 | {
173 | Runnable r = () ->
174 | {
175 | while (true)
176 | {
177 | if (fieldDL_Link.isFocused() && !rDL.isSelected())
178 | {
179 | rDL.fire();
180 | }
181 | else if (comboFiles.isFocused() && !rLocal.isSelected())
182 | {
183 | rLocal.fire();
184 | }
185 | try
186 | {
187 | Thread.sleep(300L);
188 | }
189 | catch (InterruptedException e)
190 | {
191 | e.printStackTrace();
192 | }
193 | }
194 | };
195 | Thread t = new Thread(r);
196 | t.setDaemon(true);
197 | t.start();
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/PopUp/Popup.java:
--------------------------------------------------------------------------------
1 | package GUI.PopUp;
2 |
3 | import javafx.application.Application;
4 | import javafx.collections.FXCollections;
5 | import javafx.collections.ObservableList;
6 | import javafx.fxml.FXMLLoader;
7 | import javafx.scene.Parent;
8 | import javafx.scene.Scene;
9 | import javafx.scene.image.Image;
10 | import javafx.stage.Stage;
11 | import javafx.stage.StageStyle;
12 |
13 | import java.io.File;
14 | import java.util.ArrayList;
15 |
16 | /**
17 | *
18 | */
19 | public class Popup extends Application
20 | {
21 | public static Stage stage;
22 | public static ObservableList files = FXCollections.observableArrayList();
23 | public static String url = "NOTSET";
24 | public static File jar = null;
25 |
26 | public void start(Stage primaryStage) throws Exception
27 | {
28 | primaryStage = new Stage();
29 | FXMLLoader fxmlLoader = new FXMLLoader();
30 | primaryStage.initStyle(StageStyle.UNDECORATED);
31 | primaryStage.setAlwaysOnTop(true);
32 | Parent root = fxmlLoader.load(getClass().getResource("/popup.fxml"));
33 | primaryStage.setTitle("PAL: Launcher");
34 | primaryStage.getIcons().add(new Image(getClass().getResource("/witch.png").toString()));
35 | Scene scene = new Scene(root, 338, 250);
36 | primaryStage.setScene(scene);
37 | stage = primaryStage;
38 | primaryStage.show();
39 | }
40 |
41 | public void activate(String[] args)
42 | {
43 | launch(args);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/GUI/launcher_data.java:
--------------------------------------------------------------------------------
1 | package GUI;
2 |
3 | /**
4 | *
5 | */
6 | public class launcher_data
7 | {
8 | private String install_dir;
9 | private String launcher_location;
10 | private String version = "1.4";
11 |
12 | private launcher_data()
13 | {}
14 |
15 | public launcher_data(String install, String launcher)
16 | {
17 | install_dir = install;
18 | launcher_location = launcher;
19 | }
20 |
21 | public String getInstall_dir()
22 | {
23 | return install_dir;
24 | }
25 |
26 | public void setInstall_dir(String install_dir)
27 | {
28 | this.install_dir = install_dir;
29 | }
30 |
31 | public String getLauncher_location()
32 | {
33 | return launcher_location;
34 | }
35 |
36 | public void setLauncher_location(String launcher_location)
37 | {
38 | this.launcher_location = launcher_location;
39 | }
40 |
41 | public String getVersion()
42 | {
43 | return version;
44 | }
45 |
46 | public void setVersion(String version)
47 | {
48 | this.version = version;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/Helper/QuickSorter.java:
--------------------------------------------------------------------------------
1 | package Helper;
2 |
3 | /**
4 | * A quick sort method.
5 | * Sorts highest number to lowest number. ex: [3,1,5,22] -> [22,5,3,1]
6 | * Based on: http://www.java2novice.com/java-sorting-algorithms/quick-sort/
7 | */
8 | public class QuickSorter
9 | {
10 | private Release[] array;
11 |
12 | public void sort(Release[] inputArr)
13 | {
14 | if (inputArr == null || inputArr.length == 0)
15 | {
16 | return;
17 | }
18 | this.array = inputArr;
19 | int length = inputArr.length;
20 | quickSort(0, length - 1);
21 | }
22 |
23 | private void quickSort(int lowerIndex, int higherIndex)
24 | {
25 |
26 | int i = lowerIndex;
27 | int j = higherIndex;
28 | Release pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];
29 | while (i <= j)
30 | {
31 | while (array[i].getNum() > pivot.getNum())
32 | {
33 | i++;
34 | }
35 | while (array[j].getNum() < pivot.getNum())
36 | {
37 | j--;
38 | }
39 | if (i <= j) {
40 | swap(i, j);
41 | i++;
42 | j--;
43 | }
44 | }
45 | if (lowerIndex < j)
46 | quickSort(lowerIndex, j);
47 | if (i < higherIndex)
48 | quickSort(i, higherIndex);
49 | }
50 |
51 | private void swap(int i, int j)
52 | {
53 | Release temp = array[i];
54 | array[i] = array[j];
55 | array[j] = temp;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/Helper/Release.java:
--------------------------------------------------------------------------------
1 | package Helper;
2 |
3 | import com.fasterxml.jackson.databind.JsonNode;
4 |
5 | import java.util.Iterator;
6 | import java.util.Objects;
7 |
8 | /**
9 | * Object that holds relevant info from the github api.
10 | */
11 | public class Release
12 | {
13 | private String name = "";
14 | private String version = "";
15 | private String download_url = "";
16 | private int num = 0;
17 |
18 | public Release()
19 | {}
20 |
21 | /**
22 | * Release object.
23 | * @param jsonNode Input a jsonNode (gotten from Github API)
24 | */
25 | public Release(JsonNode jsonNode)
26 | {
27 | if (jsonNode == null)
28 | return;
29 |
30 | JsonNode name = jsonNode.get("name");
31 | this.version = name.toString().replace("\"", "");
32 | JsonNode assets = jsonNode.get("assets");
33 | Iterator elements = assets.elements();
34 |
35 | if (elements.hasNext())
36 | {
37 | JsonNode zero = elements.next();
38 | this.name = zero.get("name").toString().replace("\"", "");
39 | download_url = zero.get("browser_download_url").toString().replace("\"", "");
40 | }
41 |
42 | String temp = this.name;
43 | num = Integer.parseInt(temp.replace("b", "").replace(".jar", ""));
44 | }
45 |
46 | public String getVersion()
47 | {
48 | return version;
49 | }
50 |
51 | public void setVersion(String version)
52 | {
53 | this.version = version;
54 | }
55 |
56 | public String getDownload_url()
57 | {
58 | return download_url;
59 | }
60 |
61 | public void setDownload_url(String download_url)
62 | {
63 | this.download_url = download_url;
64 | }
65 |
66 | public String getName()
67 | {
68 | return name;
69 | }
70 |
71 | public void setName(String name)
72 | {
73 | this.name = name;
74 | }
75 |
76 | @Override
77 | public String toString()
78 | {
79 | StringBuilder stringBuilder = new StringBuilder();
80 | stringBuilder.append(name);
81 | stringBuilder.append(" | ");
82 | stringBuilder.append(version);
83 | stringBuilder.append(" | ");
84 | stringBuilder.append(download_url);
85 | return stringBuilder.toString();
86 | }
87 |
88 | public int getNum()
89 | {
90 | return num;
91 | }
92 |
93 | public void setNum(int num)
94 | {
95 | this.num = num;
96 | }
97 |
98 | @Override
99 | public boolean equals(Object o)
100 | {
101 | if (this == o) return true;
102 | if (o == null || getClass() != o.getClass()) return false;
103 | Release release = (Release) o;
104 | return num == release.num &&
105 | Objects.equals(name, release.name) &&
106 | Objects.equals(version, release.version) &&
107 | Objects.equals(download_url, release.download_url);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/Helper/UpdateCheckerClient.java:
--------------------------------------------------------------------------------
1 | package Helper;
2 |
3 | import GUI.Data;
4 | import GUI.Data2;
5 | import com.fasterxml.jackson.databind.JsonNode;
6 | import com.fasterxml.jackson.databind.ObjectMapper;
7 | import org.kohsuke.github.GitHub;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.net.MalformedURLException;
13 | import java.net.URI;
14 | import java.net.URL;
15 | import java.nio.file.Files;
16 | import java.nio.file.Paths;
17 | import java.util.ArrayList;
18 | import java.util.Date;
19 | import java.util.Iterator;
20 |
21 | /**
22 | * Class handles github API requests.
23 | */
24 | public final class UpdateCheckerClient
25 | {
26 | private static final UpdateCheckerClient INSTANCE = new UpdateCheckerClient();
27 | private final String RELEASE_URL = "https://api.github.com/repos/POE-Addon-Launcher/Core/releases";
28 |
29 | private UpdateCheckerClient()
30 | {}
31 |
32 | public static UpdateCheckerClient getINSTANCE()
33 | {
34 | return INSTANCE;
35 | }
36 |
37 | /**
38 | * Downloads an update from the github servers and puts it in the Versions folder.
39 | * Creates a folder aswell.
40 | * @param most_recent The most recent release that has to be downloaded.
41 | */
42 | @Deprecated
43 | public void downloadUpdate(Release most_recent)
44 | {
45 | File versions_dir = new File(Data2.getINSTANCE().getCoreFolder());
46 |
47 | if (versions_dir.isDirectory())
48 | {
49 | File[] directories = versions_dir.listFiles();
50 | File mr_dir = new File(Data2.getINSTANCE().getCoreFolder());
51 | for (File dir : directories)
52 | {
53 | if (dir.getName().equals(most_recent.getName()))
54 | {
55 | //PAL.getINSTANCE().setJar_filepath(mr_dir.toString() + "\\" + most_recent.getName());
56 | Data2.getINSTANCE().setJar_name_to_launch(Data2.getINSTANCE().getCoreFolder() + File.separator + most_recent.getName());
57 | Data.setStatus("Up to date, launching program!");
58 | return;
59 | }
60 | }
61 | // Create DIR
62 | try
63 | {
64 | InputStream in = URI.create(most_recent.getDownload_url()).toURL().openStream();
65 | Files.copy(in, Paths.get(mr_dir.toString() + "/" + most_recent.getName()));
66 | Data.setStatus("Downloaded: " + most_recent.getName());
67 | Data2.getINSTANCE().setJar_name_to_launch(Data2.getINSTANCE().getCoreFolder() + File.separator + most_recent.getName());
68 | //PAL.getINSTANCE().setJar_filepath(mr_dir.toString() + "\\" + most_recent.getName());
69 | }
70 | catch (MalformedURLException e)
71 | {
72 | e.printStackTrace();
73 | }
74 | catch (IOException e)
75 | {
76 | e.printStackTrace();
77 | }
78 | }
79 |
80 | }
81 |
82 | /**
83 | * Downloads an update from the github servers and puts it in the Versions folder.
84 | * Creates a folder aswell.
85 | * @return returns a String to be executed.
86 | */
87 | public String downloadUpdate(String URL)
88 | {
89 | File core_dir = new File(Data2.getINSTANCE().getCoreFolder());
90 | String[] parts = URL.split("/");
91 | String jarname = parts[parts.length-1];
92 |
93 | a:if (!jarname.matches("(b)(\\d){1,9999999}(.jar)"))
94 | {
95 | jarname = null;
96 | // Attempt to get it through bruteforce.
97 | for (String str : parts)
98 | {
99 | if (str.matches("(b)(\\d){1,9999999}(.jar)"))
100 | {
101 | jarname = str;
102 | break;
103 | }
104 | }
105 | }
106 |
107 | File file = new File(core_dir.getPath() + File.separator + jarname);
108 |
109 | if (file.exists())
110 | {
111 | return file.getPath();
112 | }
113 |
114 | if (jarname != null)
115 | {
116 | if (core_dir.isDirectory())
117 | {
118 | try
119 | {
120 | InputStream in = URI.create(URL).toURL().openStream();
121 | Files.copy(in, file.toPath());
122 | return file.getPath();
123 | }
124 | catch (IOException e)
125 | {
126 | e.printStackTrace();
127 | }
128 | }
129 | }
130 | return "NO_DOWNLOAD";
131 | }
132 |
133 | /**
134 | * Genereates an ArrayList of releases.
135 | * @return Returns an ArrayList of releases.
136 | */
137 | @Deprecated
138 | public ArrayList getReleases()
139 | {
140 | if (!canCheckGithub())
141 | {
142 | return null;
143 | }
144 |
145 |
146 | ArrayList releases = new ArrayList<>();
147 | try
148 | {
149 | URL url = new URL(RELEASE_URL);
150 | ObjectMapper objectMapper = new ObjectMapper();
151 | JsonNode node = objectMapper.readTree(url);
152 | // Collection of all releases.
153 | Iterator elements = node.elements();
154 | for (Iterator it = elements; it.hasNext(); )
155 | {
156 | JsonNode n = it.next();
157 | Release r = new Release(n);
158 | releases.add(r);
159 | }
160 | }
161 | catch (MalformedURLException e)
162 | {
163 | e.printStackTrace();
164 | } catch (IOException e)
165 | {
166 | e.printStackTrace();
167 | }
168 | return releases;
169 | }
170 |
171 | @Deprecated
172 | private boolean canCheckGithub()
173 | {
174 | try
175 | {
176 | GitHub github = GitHub.connectAnonymously();
177 | return github.getRateLimit().remaining > 0;
178 | }
179 | catch (IOException e)
180 | {
181 | e.printStackTrace();
182 | }
183 | return false;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/Launcher.java:
--------------------------------------------------------------------------------
1 | import GUI.Configurator;
2 | import GUI.Data;
3 | import GUI.Data2;
4 | import GUI.LauncherUI;
5 |
6 | import java.net.URISyntaxException;
7 |
8 | /**
9 | * Launches the UI.
10 | */
11 | public class Launcher
12 | {
13 | public static void main(String[] args) throws URISyntaxException
14 | {
15 | boolean succesful_read = Data2.getINSTANCE().readLauncherData();
16 |
17 | if (succesful_read)
18 | {
19 | Data2.getINSTANCE().getData().setLauncher_location(Configurator.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
20 | LauncherUI launcherUI = new LauncherUI();
21 | launcherUI.ui_launch(args);
22 | }
23 | else
24 | {
25 | Data2.getINSTANCE().createPALfolder();
26 | Configurator configurator = new Configurator();
27 | configurator.ui_launch(args);
28 | }
29 | }
30 |
31 | @Deprecated
32 | public static void deprecated_main(String[] args)
33 | {
34 | // Read properties, will create an emptied properties file if none exist.
35 | Data.getINSTANCE().readProperties();
36 |
37 | // Check for .path file
38 | if (checkForIni(args))
39 | return;
40 |
41 |
42 | // Check if Paths are still valid / not changed. If they have changed run configurator again.
43 | if (checkDirs(args))
44 | return;
45 |
46 | // Run the launcher.
47 | LauncherUI launcherUI = new LauncherUI();
48 | launcherUI.ui_launch(args);
49 | }
50 |
51 | private static boolean checkForIni(String[] args)
52 | {
53 | if (Data.getINSTANCE().getAddon_path().equals("") || Data.getINSTANCE().getProgram_path().equals(""))
54 | {
55 | // Run Path setter.
56 | Configurator configurator = new Configurator();
57 | configurator.ui_launch(args);
58 | return true;
59 | }
60 | return false;
61 | }
62 |
63 | private static boolean checkDirs(String[] args)
64 | {
65 | if (!Data.getINSTANCE().checkDirs())
66 | {
67 | Configurator configurator = new Configurator();
68 | configurator.ui_launch(args);
69 | return true;
70 | }
71 | return false;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/java/PAL/PALsettings.java:
--------------------------------------------------------------------------------
1 | package PAL;
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/PRE-2.0/main/resources/Configurator2.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 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/Launcher.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 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/Path.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 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/bgi_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/bgi_big.png
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/cancel.png
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/cancel0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/cancel0.png
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/gear0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/gear0.png
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/gear1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/gear1.png
--------------------------------------------------------------------------------
/src/PRE-2.0/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 |
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 |
--------------------------------------------------------------------------------
/src/PRE-2.0/main/resources/witch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/PRE-2.0/main/resources/witch.png
--------------------------------------------------------------------------------
/src/PRE-2.0/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | RizlimDev
8 | PoE-Addon-Manager-Launcher
9 | 1.7
10 |
11 |
12 |
13 | com.fasterxml.jackson.core
14 | jackson-databind
15 | 2.9.6
16 |
17 |
18 | junit
19 | junit
20 | 4.12
21 |
22 |
23 | org.kohsuke
24 | github-api
25 | 1.93
26 |
27 |
28 |
29 |
30 |
31 |
32 | org.apache.maven.plugins
33 | maven-compiler-plugin
34 |
35 | 8
36 | 8
37 |
38 |
39 |
40 | org.apache.maven.plugins
41 | maven-jar-plugin
42 | 3.0.2
43 |
44 |
45 |
46 | true
47 | Launcher
48 |
49 |
50 |
51 |
52 |
53 | maven-assembly-plugin
54 |
55 |
56 |
57 | Launcher
58 |
59 |
60 |
61 | jar-with-dependencies
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/PRE-2.0/test/java/Helper/QuickSorterTest.java:
--------------------------------------------------------------------------------
1 | package Helper;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.*;
7 |
8 | /**
9 | *
10 | */
11 | public class QuickSorterTest
12 | {
13 | QuickSorter quickSorter;
14 | private Release[] test_array_random_order;
15 | private Release[] test_array_sorted_l_h;
16 | private Release[] test_array_sorted_h_l;
17 | private Release[] test_array_one_element;
18 | private Release[] empty_array;
19 | private Release r1,r2,r3,r4,r5,r6,r7,r8,r9,r10;
20 |
21 | @Before
22 | public void init()
23 | {
24 | quickSorter = new QuickSorter();
25 |
26 | r1 = new Release(null);
27 | r2 = new Release(null);
28 | r3 = new Release(null);
29 | r4 = new Release(null);
30 | r5 = new Release(null);
31 | r6 = new Release(null);
32 | r7 = new Release(null);
33 | r8 = new Release(null);
34 | r9 = new Release(null);
35 | r10 = new Release(null);
36 |
37 | r1.setNum(1);
38 | r2.setNum(38);
39 | r3.setNum(83);
40 | r4.setNum(0);
41 | r5.setNum(-1);
42 | r6.setNum(3821);
43 | r7.setNum(12);
44 | r8.setNum(38);
45 | r9.setNum(93);
46 | r10.setNum(29);
47 |
48 | test_array_random_order = new Release[]{r1,r5,r9,r6,r10,r4,r2,r8,r7,r3};
49 | test_array_one_element = new Release[]{r2};
50 | test_array_sorted_h_l = new Release[]{r6,r9,r3,r2,r8,r10,r7,r1,r4,r5};
51 | test_array_sorted_l_h = new Release[]{r5,r4,r1,r7,r10,r8,r2,r3,r9,r6};
52 | }
53 |
54 |
55 | @Test
56 | public void simpleSortTest()
57 | {
58 |
59 | quickSorter.sort(test_array_random_order);
60 | assertArrayEquals(test_array_sorted_h_l, test_array_random_order);
61 | }
62 |
63 | @Test
64 | public void sortOneElement()
65 | {
66 | quickSorter.sort(test_array_one_element);
67 | assertArrayEquals(new Release[]{r8}, test_array_one_element);
68 | }
69 |
70 | @Test
71 | public void sortLowToHighArray()
72 | {
73 | quickSorter.sort(test_array_sorted_l_h);
74 | assertArrayEquals(test_array_sorted_h_l, test_array_sorted_l_h);
75 | }
76 |
77 | @Test
78 | public void sortEmptyArray()
79 | {
80 | quickSorter.sort(empty_array);
81 | assertArrayEquals(empty_array, empty_array);
82 | }
83 | }
--------------------------------------------------------------------------------
/src/PRE-2.0/test/java/Helper/ReleaseTest.java:
--------------------------------------------------------------------------------
1 | package Helper;
2 |
3 | import com.fasterxml.jackson.databind.JsonNode;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 | import java.net.URL;
10 | import java.util.Iterator;
11 |
12 | import static org.junit.Assert.*;
13 |
14 | /**
15 | *
16 | */
17 | public class ReleaseTest
18 | {
19 | Release r1;
20 | final String JSON = "[{\"url\":\"https://api.github.com/repos/POE-Addon-Launcher/Core/releases/12614169\",\"assets_url\":\"https://api.github.com/repos/POE-Addon-Launcher/Core/releases/12614169/assets\",\"upload_url\":\"https://uploads.github.com/repos/POE-Addon-Launcher/Core/releases/12614169/assets{?name,label}\",\"html_url\":\"https://github.com/POE-Addon-Launcher/Core/releases/tag/b1\",\"id\":12614169,\"node_id\":\"MDc6UmVsZWFzZTEyNjE0MTY5\",\"tag_name\":\"b1\",\"target_commitish\":\"master\",\"name\":\"b1\",\"draft\":false,\"author\":{\"login\":\"POE-Addon-Launcher\",\"id\":42203962,\"node_id\":\"MDQ6VXNlcjQyMjAzOTYy\",\"avatar_url\":\"https://avatars2.githubusercontent.com/u/42203962?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/POE-Addon-Launcher\",\"html_url\":\"https://github.com/POE-Addon-Launcher\",\"followers_url\":\"https://api.github.com/users/POE-Addon-Launcher/followers\",\"following_url\":\"https://api.github.com/users/POE-Addon-Launcher/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/POE-Addon-Launcher/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/POE-Addon-Launcher/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/POE-Addon-Launcher/subscriptions\",\"organizations_url\":\"https://api.github.com/users/POE-Addon-Launcher/orgs\",\"repos_url\":\"https://api.github.com/users/POE-Addon-Launcher/repos\",\"events_url\":\"https://api.github.com/users/POE-Addon-Launcher/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/POE-Addon-Launcher/received_events\",\"type\":\"User\",\"site_admin\":false},\"prerelease\":false,\"created_at\":\"2018-08-28T15:25:00Z\",\"published_at\":\"2018-08-28T15:25:34Z\",\"assets\":[{\"url\":\"https://api.github.com/repos/POE-Addon-Launcher/Core/releases/assets/8426547\",\"id\":8426547,\"node_id\":\"MDEyOlJlbGVhc2VBc3NldDg0MjY1NDc=\",\"name\":\"b1.jar\",\"label\":null,\"uploader\":{\"login\":\"POE-Addon-Launcher\",\"id\":42203962,\"node_id\":\"MDQ6VXNlcjQyMjAzOTYy\",\"avatar_url\":\"https://avatars2.githubusercontent.com/u/42203962?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/POE-Addon-Launcher\",\"html_url\":\"https://github.com/POE-Addon-Launcher\",\"followers_url\":\"https://api.github.com/users/POE-Addon-Launcher/followers\",\"following_url\":\"https://api.github.com/users/POE-Addon-Launcher/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/POE-Addon-Launcher/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/POE-Addon-Launcher/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/POE-Addon-Launcher/subscriptions\",\"organizations_url\":\"https://api.github.com/users/POE-Addon-Launcher/orgs\",\"repos_url\":\"https://api.github.com/users/POE-Addon-Launcher/repos\",\"events_url\":\"https://api.github.com/users/POE-Addon-Launcher/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/POE-Addon-Launcher/received_events\",\"type\":\"User\",\"site_admin\":false},\"content_type\":\"application/octet-stream\",\"state\":\"uploaded\",\"size\":808,\"download_count\":2,\"created_at\":\"2018-08-28T15:25:30Z\",\"updated_at\":\"2018-08-28T15:25:31Z\",\"browser_download_url\":\"https://github.com/POE-Addon-Launcher/Core/releases/download/b1/b1.jar\"}],\"tarball_url\":\"https://api.github.com/repos/POE-Addon-Launcher/Core/tarball/b1\",\"zipball_url\":\"https://api.github.com/repos/POE-Addon-Launcher/Core/zipball/b1\",\"body\":\"b1\"}]\n";
21 |
22 | @Before
23 | public void before() throws IOException
24 | {
25 | ObjectMapper objectMapper = new ObjectMapper();
26 | JsonNode node = objectMapper.readTree(JSON);
27 | Iterator elements = node.elements();
28 | JsonNode jason_element = elements.next();
29 | r1 = new Release(jason_element);
30 | }
31 |
32 | @Test
33 | public void constructorNull()
34 | {
35 | r1 = new Release(null);
36 | assertEquals("", r1.getVersion());
37 | assertEquals("", r1.getName());
38 | assertEquals("", r1.getDownload_url());
39 | assertEquals(0, r1.getNum());
40 | }
41 |
42 | @Test
43 | public void getVersion()
44 | {
45 | assertEquals("b1", r1.getVersion());
46 | }
47 |
48 | @Test
49 | public void setVersion()
50 | {
51 | r1.setVersion("b2");
52 | assertEquals("b2", r1.getVersion());
53 | }
54 |
55 | @Test
56 | public void getDownload_url()
57 | {
58 | r1.setDownload_url("test");
59 | assertEquals("test", r1.getDownload_url());
60 | }
61 |
62 | @Test
63 | public void getName()
64 | {
65 | r1.setName("test");
66 | assertEquals("test", r1.getName());
67 | }
68 |
69 | @Test
70 | public void testtoString()
71 | {
72 | assertEquals("b1.jar | b1 | https://github.com/POE-Addon-Launcher/Core/releases/download/b1/b1.jar", r1.toString());
73 | }
74 |
75 | @Test
76 | public void getNum()
77 | {
78 | r1.setNum(0);
79 | assertEquals(0, r1.getNum());
80 | }
81 |
82 | @Test
83 | public void equalsTest()
84 | {
85 | r1 = new Release(null);
86 | Release r2 = new Release(null);
87 | assertTrue(r2.equals(r1));
88 | }
89 | }
--------------------------------------------------------------------------------
/src/main/kotlin/Constants.kt:
--------------------------------------------------------------------------------
1 | import Constants.Companion.BASE_DIR
2 | import Constants.Companion.objectMapper
3 | import com.fasterxml.jackson.core.JsonParser
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.KotlinModule
6 | import org.kohsuke.github.GHRelease
7 | import java.io.File
8 | import java.util.concurrent.CopyOnWriteArrayList
9 |
10 | /**
11 | *
12 | */
13 | class Constants
14 | {
15 | companion object
16 | {
17 | var LOG_LEVEL = 5
18 | var BASE_DIR = "${System.getenv("LOCALAPPDATA")}${File.separator}PAL"
19 | var INSTALL_DIR = ""
20 | var LAUNCHER_LOCATION = ""
21 | var LAUNCHER_VERSION = ""
22 | var SCAN_LOG = CopyOnWriteArrayList()
23 | var POE_PATHS_FOUND = CopyOnWriteArrayList()
24 | var FRESH_INSTALL = false
25 | val ADDITIONAL_LOCATIONS = ArrayList()
26 | val REPOSITORY = "POE-Addon-Launcher/Core"
27 | val GH_RELEASES = ArrayList()
28 | var JAR_TO_RUN: File? = null
29 |
30 | lateinit var POE_PATHS: Array
31 | lateinit var PAL_SETTINGS: PALSettings
32 |
33 | var palSettingsExists = false
34 |
35 |
36 | lateinit var objectMapper: ObjectMapper
37 |
38 | fun addToScanLog(textToAdd: String)
39 | {
40 | SCAN_LOG.add(textToAdd)
41 | }
42 |
43 | fun findReleaseByName(arg: String): GHRelease?
44 | {
45 | for (r in GH_RELEASES)
46 | {
47 | if (r.name == arg)
48 | {
49 | return r
50 | }
51 | }
52 | return null
53 | }
54 |
55 | fun addToPoePaths(arg: String)
56 | {
57 | println("Found: $arg")
58 |
59 | if (!POE_PATHS_FOUND.contains(arg))
60 | {
61 | POE_PATHS_FOUND.add(arg)
62 | }
63 | }
64 |
65 | fun removeFromPoePaths(arg: String)
66 | {
67 | if (POE_PATHS_FOUND.contains(arg))
68 | {
69 | POE_PATHS_FOUND.remove(arg)
70 | }
71 | }
72 |
73 | fun initJackson()
74 | {
75 | println("Jackson")
76 | objectMapper = ObjectMapper()
77 | .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
78 | .registerModule(KotlinModule())
79 | }
80 |
81 | fun initLdPAL()
82 | {
83 | println("LauncherData.pal")
84 | var ldPAL = LauncherDataPAL.read()
85 | INSTALL_DIR = ldPAL.install_dir
86 | }
87 |
88 | fun initPoePaths()
89 | {
90 | println("Parsing PoE Paths")
91 | val file = File("${Constants.BASE_DIR}${File.separator}poe_paths.pal")
92 | POE_PATHS = objectMapper.readValue(file, Array::class.java)
93 | for (str in POE_PATHS)
94 | {
95 | addToPoePaths(str)
96 | }
97 | }
98 |
99 | fun savePoePaths()
100 | {
101 | println("Saving PoE Paths")
102 | val file = File("${Constants.BASE_DIR}${File.separator}poe_paths.pal")
103 |
104 | if (file.exists())
105 | delete(file)
106 |
107 | objectMapper.writeValue(file, POE_PATHS_FOUND)
108 | }
109 |
110 | fun initCoreSettings()
111 | {
112 | println("Parsing Core Settings")
113 | val file = File("${Constants.BASE_DIR}${File.separator}core_settings.pal")
114 |
115 | if (file.exists())
116 | {
117 | var ps = objectMapper.readValue(file, PALSettings::class.java)
118 | PAL_SETTINGS = ps
119 | palSettingsExists = true
120 | }
121 | else
122 | {
123 | palSettingsExists = false
124 | }
125 |
126 | }
127 |
128 | fun saveCoreSettings()
129 | {
130 | println("Saving Core Settings")
131 | val file = File("${Constants.BASE_DIR}${File.separator}core_settings.pal")
132 |
133 | if (file.exists())
134 | delete(file)
135 |
136 | objectMapper.writeValue(file, PAL_SETTINGS)
137 | }
138 |
139 | fun init()
140 | {
141 | println("Initializing...")
142 | initJackson()
143 |
144 | var file = File("${Constants.BASE_DIR}${File.separator}launcher_data.pal")
145 |
146 | // Previous Install Exists
147 | if (file.exists())
148 | {
149 | initLdPAL()
150 | initPoePaths()
151 | initCoreSettings()
152 | }
153 | else
154 | {
155 | FRESH_INSTALL = true
156 | setDefaultLauncherSetting()
157 | println("Fresh Install Detected!")
158 | }
159 |
160 |
161 | }
162 |
163 | private fun setDefaultLauncherSetting()
164 | {
165 | INSTALL_DIR = Constants.BASE_DIR
166 | }
167 |
168 | fun createBaseFolders()
169 | {
170 | val pal = File(BASE_DIR)
171 | if (!pal.exists())
172 | pal.mkdir()
173 |
174 | val addons = File("${INSTALL_DIR}${File.separator}Addons")
175 |
176 | if (!addons.exists())
177 | addons.mkdir()
178 |
179 | val addonsTemp = File("${INSTALL_DIR}${File.separator}Addons${File.separator}temp")
180 |
181 | if (!addonsTemp.exists())
182 | addonsTemp.mkdir()
183 |
184 | val core = File("${INSTALL_DIR}${File.separator}Core")
185 |
186 | if (!core.exists())
187 | core.mkdir()
188 |
189 | }
190 | }
191 | }
192 |
193 | data class LauncherDataPAL(val install_dir: String, val launcher_location: String, val version: String)
194 | {
195 | companion object
196 | {
197 | fun read(): LauncherDataPAL
198 | {
199 | val file = File("${Constants.BASE_DIR}${File.separator}launcher_data.pal")
200 | return Constants.objectMapper.readValue(file, LauncherDataPAL::class.java)
201 | }
202 |
203 | fun save(arg: LauncherDataPAL)
204 | {
205 | val f = File("$BASE_DIR${File.separator}launcher_data.pal")
206 |
207 | if (f.exists())
208 | delete(f)
209 |
210 | objectMapper.writeValue(f, arg)
211 | }
212 | }
213 | }
214 |
215 |
216 | data class PALSettings
217 | (
218 | var wait_for_updates : Boolean,
219 | var loot_filter_dir : String,
220 | var github_api_enabled : Boolean,
221 | var pref_version : String,
222 | var filterblast_api : Boolean,
223 | var down_on_launch : Boolean,
224 | var github_token : String,
225 | var github_api_token_enabled : Boolean,
226 | var run_poe_on_launch : Boolean,
227 | var ahk_Folder : String
228 | )
--------------------------------------------------------------------------------
/src/main/kotlin/Controller.kt:
--------------------------------------------------------------------------------
1 | import javafx.application.Application
2 | import javafx.application.Platform
3 | import javafx.event.ActionEvent
4 | import javafx.fxml.Initializable
5 | import javafx.stage.Stage
6 | import javafx.fxml.FXML
7 | import javafx.fxml.FXMLLoader
8 | import javafx.scene.Parent
9 | import javafx.scene.Scene
10 | import javafx.scene.control.*
11 | import javafx.scene.image.Image
12 | import javafx.scene.image.ImageView
13 | import javafx.scene.input.MouseEvent
14 | import javafx.scene.text.Text
15 | import javafx.stage.StageStyle
16 | import java.net.URL
17 | import java.util.*
18 | import javafx.stage.DirectoryChooser
19 | import kotlinx.coroutines.GlobalScope
20 | import kotlinx.coroutines.delay
21 | import kotlinx.coroutines.launch
22 | import java.io.File
23 | import javafx.scene.control.CheckBox
24 | import javafx.scene.layout.AnchorPane
25 | import org.kohsuke.github.GHAsset
26 | import org.kohsuke.github.GHRelease
27 | import org.kohsuke.github.GitHub
28 | import java.net.URI
29 | import java.nio.file.Files
30 | import java.nio.file.Paths
31 |
32 |
33 | /**
34 | *
35 | */
36 | class LaunchUI: Application()
37 | {
38 | companion object
39 | {
40 | lateinit var stage: Stage
41 | }
42 |
43 | override fun start(primaryStage: Stage?)
44 | {
45 | val fxmlLoader = FXMLLoader()
46 | primaryStage!!.initStyle(StageStyle.UNDECORATED)
47 | val root = fxmlLoader.load(javaClass.getResource("/ui.fxml").openStream())
48 | root.stylesheets.add(javaClass.getResource("/text.css").openStream().toString())
49 | primaryStage.title = "PAL Updater"
50 | primaryStage.isResizable = false
51 | val scene = Scene(root, 600.0, 338.0)
52 | scene.stylesheets.add("text.css")
53 | primaryStage.scene = scene
54 | primaryStage.icons.add(Image(javaClass.getResource("/witch.png").toString()))
55 | stage = primaryStage
56 | primaryStage.show()
57 | }
58 |
59 | }
60 |
61 | class LaunchController: Initializable
62 | {
63 | private var xOffset = 0.0
64 | private var yOffset = 0.0
65 |
66 | fun onMouseDragged(mouseEvent: MouseEvent)
67 | {
68 | LaunchUI.stage.x = mouseEvent.screenX + xOffset
69 | LaunchUI.stage.y = mouseEvent.screenY + yOffset
70 | }
71 |
72 | fun onMousePressed(mouseEvent: MouseEvent)
73 | {
74 | xOffset = LaunchUI.stage.x - mouseEvent.screenX
75 | yOffset = LaunchUI.stage.y - mouseEvent.screenY
76 | }
77 |
78 | override fun initialize(location: URL?, resources: ResourceBundle?)
79 | {
80 | Constants.INSTALL_DIR = Constants.BASE_DIR
81 | Platform.runLater { sInstallField.text = Constants.BASE_DIR }
82 |
83 | updateLog()
84 | PoEPathsUpdater()
85 | writeCheckboxFromConstants()
86 |
87 | if (Constants.FRESH_INSTALL)
88 | {
89 | firstRunSetup(true, 0.15)
90 | }
91 | else
92 | {
93 | lsRead()
94 | }
95 |
96 | Platform.runLater {
97 | lpStatus.text = "Welcome Back to PAL!"
98 | lpStatus.isVisible = true
99 | }
100 | }
101 |
102 | fun firstRunSetup(b: Boolean, opacity: Double)
103 | {
104 | Platform.runLater {
105 | mainButtonsScreen.isVisible = !b
106 | settingsTabPane.isVisible = b
107 | launchPALimageview.opacity = opacity
108 | manualUpdateImageView.opacity = opacity
109 | checkForUpdatesImageView.opacity = opacity
110 | }
111 | }
112 |
113 | var cachedLogSize: Int = 0
114 |
115 | fun updateLog()
116 | {
117 | GlobalScope.launch {
118 | while (true)
119 | {
120 | delay(50)
121 | val _scan_log = Constants.SCAN_LOG
122 |
123 | if (cachedLogSize != _scan_log.size)
124 | {
125 | Platform.runLater { scanActiveText.text = _scan_log[_scan_log.size-1] }
126 | cachedLogSize = _scan_log.size
127 | }
128 | }
129 | }
130 | }
131 |
132 | fun PoEPathsUpdater()
133 | {
134 | GlobalScope.launch {
135 | var size = 0
136 | while (true)
137 | {
138 | delay(50)
139 | val _PoePaths = Constants.POE_PATHS_FOUND
140 |
141 | if (_PoePaths.size != size)
142 | {
143 | for (c in size until _PoePaths.size)
144 | {
145 | println(_PoePaths[c])
146 | Platform.runLater { poeList.items.add(_PoePaths[c]) }
147 | }
148 | size = _PoePaths.size
149 | }
150 | }
151 | }
152 | }
153 |
154 | /**
155 | * Change the image of an image view.
156 | * @param imageView ImageView to be changed.
157 | * @param s String location of the image. [(resources)/{your_folder}/your_file.ext]
158 | */
159 | private fun changeImage(imageView: ImageView, s: String)
160 | {
161 | log(0, "Changing ${imageView.id} -> $s")
162 | Platform.runLater { imageView.image = Image(javaClass.getResource(s).toString()) }
163 | }
164 |
165 | fun pressed(mouseEvent: MouseEvent)
166 | {
167 | if (mouseEvent.source is ImageView)
168 | {
169 | val imgView: ImageView = mouseEvent.source as ImageView
170 | when (imgView.id)
171 | {
172 | "imgViewminimize" -> LaunchUI.stage.isIconified = true
173 | "imgviewExit" -> System.exit(42)
174 | "imgviewsettings" -> showHideSettings()
175 | "launchPALimageview" -> launch_jar()
176 | "manualUpdateImageView" -> manualUpdate(true)
177 | "checkForUpdatesImageView" -> checkForUpdates()
178 | }
179 | }
180 | else
181 | {
182 | System.err.println("Mouse Click property on something that shouldn't be there, report to rizlim!")
183 | log(1, "$mouseEvent")
184 | }
185 | }
186 |
187 | private fun manualUpdate(b: Boolean)
188 | {
189 | if (!Constants.FRESH_INSTALL)
190 | {
191 | Platform.runLater {
192 | settingsTabPane.isVisible = false
193 | mainButtonsScreen.isVisible = true
194 | lpStatus.text = "Manual Update\nPlease, enter the download URL of\nthe jar you wish to manually update to.\n\n\nor type dbg to open the info window"
195 | bManUpdateField.isVisible = b
196 | bManUse.isVisible = b
197 | txtDump.isVisible = !b
198 | lpStatus.isVisible = b
199 | }
200 | }
201 | }
202 |
203 | private fun checkForUpdates()
204 | {
205 | if (!Constants.FRESH_INSTALL)
206 | {
207 | Platform.runLater {
208 | settingsTabPane.isVisible = false
209 | mainButtonsScreen.isVisible = true
210 | lpStatus.text = "Checking for updates...\nPAL will launch when we're done checking/updating!"
211 | bManUpdateField.isVisible = false
212 | bManUse.isVisible = false
213 | txtDump.isVisible = false
214 | lpStatus.isVisible = true
215 | }
216 |
217 | GlobalScope.launch {
218 | lateinit var gh: GitHub
219 |
220 | gh = if (pcGithubToken.text != "")
221 | {
222 | connect(pcGithubToken.text)
223 | }
224 | else
225 | {
226 | connect()
227 | }
228 |
229 |
230 | if (canQuerry(gh))
231 | {
232 | lpStatusAdd("\n\nConnect Succesful\nYou have ${gh.rateLimit.remaining} requests left which reset at:\n${gh.rateLimit.resetDate}")
233 | val repo = gh.getRepository(Constants.REPOSITORY)
234 | val mr = repo.latestRelease
235 | val asset = find_jarAsset(mr.assets)
236 | if (asset != null)
237 | {
238 | val file = File("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}${asset.name}")
239 | if (file.exists())
240 | {
241 | lpStatusAdd("\nYou're up to date!")
242 | Constants.JAR_TO_RUN = file
243 | }
244 | else
245 | {
246 | lpStatusAdd("\nDownload in progress!")
247 | ghDownloadbyURL(asset.browserDownloadUrl, asset.name)
248 | lpStatusAdd("\nDownload done!")
249 | }
250 |
251 |
252 |
253 | lpStatusAdd("\n" +
254 | "Launching PAL hf mapping!")
255 | launch_jar()
256 | }
257 | }
258 | else
259 | {
260 | lpStatusAdd("\n" +
261 | "You're out of Github requests get an API token or wait until\n" +
262 | "${gh.rateLimit.resetDate}")
263 | }
264 | }
265 | }
266 | }
267 |
268 | private fun lpStatusAdd(arg: String)
269 | {
270 | Platform.runLater {
271 | lpStatus.text += arg
272 | }
273 | }
274 |
275 | private fun launch_jar()
276 | {
277 | if (!Constants.FRESH_INSTALL)
278 | {
279 | val jar_to_run = Constants.JAR_TO_RUN
280 |
281 | if (jar_to_run == null)
282 | {
283 | // Check for updates
284 | checkForUpdates()
285 | }
286 | else
287 | {
288 | Runtime.getRuntime().exec("java -jar \"${jar_to_run.path}\"")
289 | System.exit(1)
290 | }
291 | }
292 | }
293 |
294 | private fun showHideSettings()
295 | {
296 | Platform.runLater {
297 | val mod = settingsTabPane.isVisible
298 | settingsTabPane.isVisible = !mod
299 | mainButtonsScreen.isVisible = mod
300 | }
301 | }
302 |
303 | fun hide(mouseEvent: MouseEvent)
304 | {
305 | if (mouseEvent.source is ImageView)
306 | {
307 | val imgView: ImageView = mouseEvent.source as ImageView
308 | when (imgView.id)
309 | {
310 | "imgViewminimize" -> changeImage(imgView, "minimize.png")
311 | "imgviewExit" -> changeImage(imgView, "cancel0.png")
312 | "imgviewsettings" -> changeImage(imgView, "settings.png")
313 | "launchPALimageview" -> changeImage(imgView, "lp0.png")
314 | "manualUpdateImageView" -> changeImage(imgView, "mu0.png")
315 | "checkForUpdatesImageView" -> changeImage(imgView, "cu0.png")
316 | }
317 | }
318 | else
319 | {
320 | System.err.println("Mouse Exit property on something that shouldn't be there, report to rizlim!")
321 | log(1, "$mouseEvent")
322 | }
323 | }
324 |
325 | fun show(mouseEvent: MouseEvent)
326 | {
327 | if (mouseEvent.source is ImageView)
328 | {
329 | val imgView: ImageView = mouseEvent.source as ImageView
330 | when (imgView.id)
331 | {
332 | "imgViewminimize" -> changeImage(imgView, "minimize_hl.png")
333 | "imgviewExit" -> changeImage(imgView, "cancel.png")
334 | "imgviewsettings" -> changeImage(imgView, "settings_hl.png")
335 | "launchPALimageview" -> changeImage(imgView, "lp1.png")
336 | "manualUpdateImageView" -> changeImage(imgView, "mu1.png")
337 | "checkForUpdatesImageView" -> changeImage(imgView, "cu1.png")
338 | }
339 | }
340 | else
341 | {
342 | System.err.println("Mouse Over property on something that shouldn't be there, report to rizlim!")
343 | log(1, "$mouseEvent")
344 | }
345 | }
346 |
347 | fun log(errcode: Int, arg: String)
348 | {
349 | Platform.runLater {
350 | val log_lvl = Constants.LOG_LEVEL
351 | if (log_lvl <= errcode)
352 | {
353 | txtDump.text = "${txtDump.text}\n$arg"
354 | txtDump.scrollTop = Double.MAX_VALUE
355 | }
356 |
357 | }
358 | }
359 |
360 | fun AutoScan(actionEvent: ActionEvent)
361 | {
362 | GlobalScope.launch {
363 |
364 | Platform.runLater {
365 | scanCommonLocations()
366 | settingsTabPane.selectionModel.select(0)
367 | }
368 | }
369 | }
370 |
371 | fun changeInstallDir(actionEvent: ActionEvent)
372 | {
373 | GlobalScope.launch {
374 | Platform.runLater {
375 | var file:File? = browse("Browse for a PAL install directory, must be empty!")
376 |
377 | if (file == null)
378 | {
379 | Constants.INSTALL_DIR = Constants.BASE_DIR
380 | Platform.runLater { sInstallField.text = Constants.BASE_DIR }
381 | }
382 | else
383 | {
384 | var f = File("${file.path}${File.separator}PAL")
385 | if (!f.exists())
386 | {
387 | f.mkdir()
388 | }
389 | else
390 | {
391 | f = mkdirUntilEmpty(f)
392 | }
393 | Constants.INSTALL_DIR = f.path
394 | Platform.runLater { sInstallField.text = f.path }
395 | }
396 | }
397 | }
398 | }
399 |
400 | /**
401 | * Method for Opening the DirectoryChooser.
402 | */
403 | fun browse(title: String): File?
404 | {
405 | val directoryChooser = DirectoryChooser()
406 | directoryChooser.title = title
407 | return directoryChooser.showDialog(LaunchUI.stage)
408 | }
409 |
410 | fun lsReset(actionEvent: ActionEvent)
411 | {
412 | Platform.runLater {
413 | lsInstallDir.text = Constants.BASE_DIR
414 | lsLauncherLoc.text = Launcher::class.java.protectionDomain.codeSource.location.toURI().path
415 | lsVersion.text = "2.0"
416 | }
417 | }
418 |
419 | fun lsSave(actionEvent: ActionEvent)
420 | {
421 | LauncherDataPAL.save(LauncherDataPAL(lsInstallDir.text, lsLauncherLoc.text, lsVersion.text))
422 | }
423 |
424 | fun lsRead()
425 | {
426 | Platform.runLater {
427 | lsInstallDir.text = Constants.INSTALL_DIR
428 | lsLauncherLoc.text = Constants.LAUNCHER_LOCATION
429 | lsVersion.text = Constants.LAUNCHER_VERSION
430 | }
431 | }
432 |
433 | fun showLog(actionEvent: ActionEvent)
434 | {
435 | Platform.runLater { settingsTabPane.selectionModel.select(4) }
436 | }
437 |
438 | fun writeCheckboxFromConstants()
439 | {
440 | if (Constants.palSettingsExists)
441 | {
442 | GlobalScope.launch {
443 | Platform.runLater {
444 | pcAHKFOlder.text = Constants.PAL_SETTINGS.ahk_Folder
445 | pcDownOnLaunch.isSelected = Constants.PAL_SETTINGS.down_on_launch
446 | pcGithubAPIEnabled.isSelected = Constants.PAL_SETTINGS.github_api_enabled
447 | pcGithubApiTokenEnabled.isSelected = Constants.PAL_SETTINGS.github_api_token_enabled
448 | pcGithubToken.text = Constants.PAL_SETTINGS.github_token
449 | pcLootFilterDir.text = Constants.PAL_SETTINGS.loot_filter_dir
450 | pcPrefVersion.text = Constants.PAL_SETTINGS.pref_version
451 | pcRunPoeOnLaunch.isSelected = Constants.PAL_SETTINGS.run_poe_on_launch
452 | pcUseFilterblastAPI.isSelected = Constants.PAL_SETTINGS.filterblast_api
453 | pcWaitForUpdates.isSelected = Constants.PAL_SETTINGS.wait_for_updates
454 | }
455 | }
456 | }
457 | }
458 |
459 | fun syncPALSettings()
460 | {
461 | if (Constants.palSettingsExists)
462 | {
463 | Constants.PAL_SETTINGS.ahk_Folder = pcAHKFOlder.text
464 | Constants.PAL_SETTINGS.down_on_launch = pcDownOnLaunch.isSelected
465 | Constants.PAL_SETTINGS.github_api_enabled = pcGithubAPIEnabled.isSelected
466 | Constants.PAL_SETTINGS.github_api_token_enabled = pcGithubApiTokenEnabled.isSelected
467 | Constants.PAL_SETTINGS.github_token = pcGithubToken.text
468 | Constants.PAL_SETTINGS.loot_filter_dir = pcLootFilterDir.text
469 | Constants.PAL_SETTINGS.pref_version = pcPrefVersion.text
470 | Constants.PAL_SETTINGS.run_poe_on_launch = pcRunPoeOnLaunch.isSelected
471 | Constants.PAL_SETTINGS.filterblast_api = pcUseFilterblastAPI.isSelected
472 | Constants.PAL_SETTINGS.wait_for_updates = pcWaitForUpdates.isSelected
473 | }
474 | }
475 |
476 | fun addscanlocation(actionEvent: ActionEvent)
477 | {
478 | val res = browse("Select a folder to add to the auto scan!")
479 | if (res != null)
480 | {
481 | Constants.ADDITIONAL_LOCATIONS.add(res)
482 | Platform.runLater { txtScanLocations.text = "${txtScanLocations.text} & ${res.path}" }
483 | }
484 | }
485 |
486 | fun addPoeFolder(actionEvent: ActionEvent)
487 | {
488 | val f = browse("Browse to your PoE Folder")
489 | if (f != null)
490 | {
491 | recursiveScan(f)
492 | }
493 | }
494 |
495 | fun removePoeFolder(actionEvent: ActionEvent)
496 | {
497 | if (poeList.selectionModel.selectedItem != null)
498 | {
499 | Constants.removeFromPoePaths(poeList.selectionModel.selectedItem)
500 | poeList.items.remove(poeList.selectionModel.selectedItem)
501 | }
502 | }
503 |
504 | fun saveMainSettings(actionEvent: ActionEvent)
505 | {
506 | if (Constants.FRESH_INSTALL)
507 | {
508 | if (Constants.POE_PATHS_FOUND.size == 0)
509 | {
510 | return
511 | }
512 | else
513 | {
514 | firstRunSetup(false, 1.0)
515 | Constants.FRESH_INSTALL = false
516 | }
517 | }
518 | Constants.createBaseFolders()
519 | Constants.INSTALL_DIR = sInstallField.text
520 | LauncherDataPAL.save(LauncherDataPAL(Constants.INSTALL_DIR, Constants.LAUNCHER_LOCATION, Constants.LAUNCHER_VERSION))
521 | Constants.savePoePaths()
522 |
523 | }
524 |
525 | fun savePALsettings(actionEvent: ActionEvent)
526 | {
527 | syncPALSettings()
528 | Constants.saveCoreSettings()
529 | }
530 |
531 | /**
532 | * Also saves to Constants
533 | */
534 | fun displayReleases(arg: MutableList?)
535 | {
536 | if (arg != null)
537 | {
538 | for (r in arg)
539 | {
540 | sListViewOlderVersions.items.add(r.name)
541 | Constants.GH_RELEASES.add(r)
542 | }
543 | }
544 | }
545 |
546 |
547 | fun ghSearch(actionEvent: ActionEvent)
548 | {
549 | val gh = connect()
550 | if (canQuerry(gh))
551 | {
552 | Platform.runLater {
553 | sButtonErrorText.text = "You have ${gh.rateLimit.remaining} GitHub API requests left\nThese reset at: ${gh.rateLimit.resetDate}"
554 | sButtonErrorText.isVisible = true
555 | }
556 | val releases = checkReleases(gh)
557 | displayReleases(releases)
558 | }
559 | else
560 | {
561 | Platform.runLater {
562 | sButtonErrorText.text = "You are out of GitHub API requests!\nGet an API token or wait until: ${gh.rateLimit.resetDate}"
563 | sButtonErrorText.isVisible = true
564 | }
565 | }
566 | }
567 |
568 | fun downloadSelectedFromGithub()
569 | {
570 | GlobalScope.launch {
571 | val sel = sListViewOlderVersions.selectionModel.selectedItem
572 | log(1, sel)
573 | log(3, "Called downloadSelectedFromGithub() with selected item: $sel")
574 |
575 | if (sel != null)
576 | {
577 | val release = Constants.findReleaseByName(sel)
578 | log(1, release.toString())
579 | if (release != null)
580 | {
581 | // Start download
582 | val asset = find_jarAsset(release.assets)
583 | log(1, asset.toString())
584 |
585 | if (asset != null)
586 | {
587 | val checkFile = File("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}${asset.name}")
588 |
589 | if (checkFile.exists())
590 | {
591 | log(5, "Deleting ${asset.name} from ${Constants.INSTALL_DIR}${File.separator}Core because it already exists.")
592 | delete(checkFile)
593 | }
594 |
595 | log(5, "Found: ${asset.name} with download url: ${asset.browserDownloadUrl}")
596 | val inputStream = URI.create(asset.browserDownloadUrl).toURL().openStream()
597 | log(5, "Downloading: ${asset.name} with url: ${asset.browserDownloadUrl}")
598 | Files.copy(inputStream, Paths.get("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}${asset.name}"))
599 | log(5, "Download completed file saved to: ${Constants.INSTALL_DIR}${File.separator}Core${File.separator}${asset.name}")
600 | Constants.JAR_TO_RUN = File("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}${asset.name}")
601 | }
602 |
603 | }
604 | }
605 | }
606 | }
607 |
608 | fun find_jarAsset(assets: MutableList): GHAsset?
609 | {
610 | for (a in assets)
611 | {
612 | if (a.name.contains(".jar"))
613 | return a
614 | }
615 | return null
616 | }
617 |
618 | fun manUpdate(actionEvent: ActionEvent)
619 | {
620 | if (bManUpdateField.text == "dbg")
621 | {
622 | manualUpdate(false)
623 | }
624 | else
625 | {
626 | val txt = bManUpdateField.text.split("/")
627 | lateinit var name: String
628 | for (s in txt)
629 | {
630 | if (s.contains(".jar"))
631 | {
632 | name = s
633 | }
634 | }
635 | ghDownloadbyURL(bManUpdateField.text, name)
636 | launch_jar()
637 | }
638 | }
639 |
640 | @FXML
641 | private lateinit var sInstallField: TextField
642 |
643 | @FXML
644 | private lateinit var scanActiveText: Text
645 |
646 | @FXML
647 | private lateinit var launchPALimageview: ImageView
648 |
649 | @FXML
650 | private lateinit var manualUpdateImageView: ImageView
651 |
652 | @FXML
653 | private lateinit var checkForUpdatesImageView: ImageView
654 |
655 | @FXML
656 | private lateinit var imgviewsettings: ImageView
657 |
658 | @FXML
659 | private lateinit var imgviewExit: ImageView
660 |
661 | @FXML
662 | private lateinit var imgViewminimize: ImageView
663 |
664 | @FXML
665 | private lateinit var settingsText: Text
666 |
667 | @FXML
668 | private lateinit var sLog: Button
669 |
670 | @FXML
671 | private lateinit var sScanForMe: Button
672 |
673 |
674 | @FXML
675 | private lateinit var poeList: ListView
676 |
677 | @FXML
678 | private lateinit var sListViewOlderVersions: ListView
679 |
680 | @FXML
681 | private lateinit var bSearchGithub: Button
682 |
683 | @FXML
684 | private lateinit var sButtonErrorText: Text
685 |
686 | @FXML
687 | private lateinit var sThisVersionWillBeUsed: Text
688 |
689 | @FXML
690 | private lateinit var sDownloadProgressText: Text
691 |
692 | @FXML
693 | private lateinit var scanLog: Tab
694 |
695 | @FXML
696 | private lateinit var sAddScanLocation: Button
697 |
698 | @FXML
699 | private lateinit var sScanAgain: Button
700 |
701 | @FXML
702 | private lateinit var txtDump: TextArea
703 |
704 | @FXML
705 | private lateinit var lsInstallDir: TextField
706 |
707 | @FXML
708 | private lateinit var lsLauncherLoc: TextField
709 |
710 | @FXML
711 | private lateinit var lsVersion: TextField
712 |
713 | @FXML
714 | private lateinit var lsSave: Button
715 |
716 | @FXML
717 | private lateinit var lsReset: Button
718 |
719 | @FXML
720 | private lateinit var txtScanLocations: Text
721 |
722 | @FXML
723 | private lateinit var settingsTabPane: TabPane
724 |
725 | @FXML
726 | private lateinit var pcWaitForUpdates: CheckBox
727 |
728 | @FXML
729 | private lateinit var pcGithubAPIEnabled: CheckBox
730 |
731 | @FXML
732 | private lateinit var pcUseFilterblastAPI: CheckBox
733 |
734 | @FXML
735 | private lateinit var pcDownOnLaunch: CheckBox
736 |
737 | @FXML
738 | private lateinit var pcGithubApiTokenEnabled: CheckBox
739 |
740 | @FXML
741 | private lateinit var pcRunPoeOnLaunch: CheckBox
742 |
743 | @FXML
744 | private lateinit var pcGithubToken: TextField
745 |
746 | @FXML
747 | private lateinit var pcAHKFOlder: TextField
748 |
749 | @FXML
750 | private lateinit var pcPrefVersion: TextField
751 |
752 | @FXML
753 | private lateinit var pcLootFilterDir: TextField
754 |
755 | @FXML
756 | private lateinit var pcSave: Button
757 |
758 | @FXML
759 | private lateinit var mainButtonsScreen: AnchorPane
760 |
761 | @FXML
762 | private lateinit var lpStatus: Text
763 |
764 | @FXML
765 | private lateinit var bManUpdateField: TextField
766 |
767 | @FXML
768 | private lateinit var bManUse: Button
769 |
770 | }
--------------------------------------------------------------------------------
/src/main/kotlin/GithubHandler.kt:
--------------------------------------------------------------------------------
1 | import org.kohsuke.github.GHRelease
2 | import org.kohsuke.github.GitHub
3 | import java.io.File
4 | import java.net.URI
5 | import java.nio.file.Files
6 | import java.nio.file.Paths
7 |
8 | /**
9 | *
10 | */
11 | fun canQuerry(gitHub: GitHub): Boolean
12 | {
13 | println("${gitHub.rateLimit} requests left.")
14 | return gitHub.rateLimit.remaining > 3
15 | }
16 |
17 | fun connect(): GitHub
18 | {
19 | if (Constants.palSettingsExists)
20 | {
21 | if (Constants.PAL_SETTINGS.github_api_token_enabled)
22 | {
23 | if (Constants.PAL_SETTINGS.github_token != "")
24 | {
25 | return GitHub.connectUsingOAuth(Constants.PAL_SETTINGS.github_token)
26 | }
27 | }
28 | }
29 | return GitHub.connectAnonymously()
30 | }
31 |
32 | fun connect(arg: String): GitHub
33 | {
34 | return GitHub.connectUsingOAuth(arg)
35 | }
36 |
37 | fun checkReleases(github: GitHub): MutableList?
38 | {
39 | val repo = github.getRepository(Constants.REPOSITORY)
40 | val releases = repo.releases
41 | return releases
42 | }
43 |
44 | fun ghDownloadbyURL(url: String, name: String)
45 | {
46 | val checkFile = File("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}$name")
47 |
48 | if (checkFile.exists())
49 | {
50 | delete(checkFile)
51 | }
52 |
53 | val inputStream = URI.create(url).toURL().openStream()
54 | Files.copy(inputStream, Paths.get("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}$name"))
55 | Constants.JAR_TO_RUN = File("${Constants.INSTALL_DIR}${File.separator}Core${File.separator}$name")
56 | }
--------------------------------------------------------------------------------
/src/main/kotlin/Launcher.kt:
--------------------------------------------------------------------------------
1 | import javafx.application.Application
2 | import kotlinx.coroutines.GlobalScope
3 | import kotlinx.coroutines.launch
4 |
5 | /**
6 | *
7 | */
8 | class Launcher
9 | {
10 |
11 | companion object
12 | {
13 | @JvmStatic
14 | fun main(args: Array)
15 | {
16 | // These must be up to date.
17 | Constants.LAUNCHER_LOCATION = Launcher::class.java.protectionDomain.codeSource.location.toURI().path
18 | Constants.LAUNCHER_VERSION = "2.0"
19 |
20 | Constants.init()
21 |
22 | GlobalScope.launch { scanCommonLocations() }
23 |
24 | if (args.isNotEmpty())
25 | {
26 | for (str in args)
27 | {
28 | Constants.LOG_LEVEL = str.toInt()
29 | }
30 | }
31 |
32 | //FirstPdf.main(args)
33 | Application.launch(LaunchUI::class.java, *args)
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/kotlin/PoEScanner.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.GlobalScope
2 | import kotlinx.coroutines.launch
3 | import java.io.File
4 | import java.util.regex.Pattern
5 |
6 |
7 | /**
8 | *
9 | */
10 | fun recursiveScan(location: File)
11 | {
12 | val pattern: Pattern = Pattern.compile("pathofexile.*\\.exe", Pattern.CASE_INSENSITIVE)
13 | location.walkTopDown().forEach {
14 | Constants.SCAN_LOG.add(it.path)
15 | GlobalScope.launch {
16 | if (pattern.matcher(it.name).matches())
17 | {
18 | Constants.addToPoePaths(it.path)
19 | }
20 | }
21 |
22 | }
23 | /*
24 | for (file in location.listFiles())
25 | {
26 | if (file != null)
27 | {
28 | Constants.SCAN_LOG.add(file.path)
29 |
30 | //println(file.name)
31 | if (file.isDirectory)
32 | {
33 | if (!file.name.contains("$"))
34 | recursiveScan(file)
35 | }
36 | else
37 | {
38 | val pattern: Pattern = Pattern.compile("pathofexile.*\\.exe", Pattern.CASE_INSENSITIVE)
39 | if (pattern.matcher(file.name).matches())
40 | {
41 | // TODO: Store found
42 | println(file.name)
43 |
44 | }
45 | }
46 | }
47 |
48 | }*/
49 | }
50 |
51 | fun scanCommonLocations()
52 | {
53 | val PROGRAM_FILES_GGG = File("C:\\Program Files\\GGG")
54 | val PROGRAM_FILES_X86_GGG = File("C:\\Program Files (x86)\\GGG")
55 | val PROGRAM_FILES = File("C:\\Program Files\\Steam")
56 | val PROGRAM_FILES_X86 = File("C:\\Program Files (x86)\\Steam")
57 | val GAMES = File("C:\\Games")
58 |
59 | when (true)
60 | {
61 | PROGRAM_FILES_GGG.exists() -> GlobalScope.launch { recursiveScan(PROGRAM_FILES) }
62 | PROGRAM_FILES_X86_GGG.exists() -> GlobalScope.launch { recursiveScan(PROGRAM_FILES_X86) }
63 | PROGRAM_FILES.exists() -> GlobalScope.launch { recursiveScan(PROGRAM_FILES) }
64 | PROGRAM_FILES_X86.exists() -> GlobalScope.launch { recursiveScan(PROGRAM_FILES_X86) }
65 | GAMES.exists() -> GlobalScope.launch { recursiveScan(GAMES) }
66 | }
67 |
68 | for (file in Constants.ADDITIONAL_LOCATIONS)
69 | when (true)
70 | {
71 | file.exists() -> GlobalScope.launch { recursiveScan(file) }
72 | }
73 |
74 | }
75 |
76 | fun mkdirUntilEmpty(file: File): File
77 | {
78 | if (file.exists())
79 | {
80 | // Empty Directory
81 | if (file.listFiles().isEmpty())
82 | {
83 | return file
84 | }
85 | else
86 | {
87 | val f = File("${file.path}${File.separator}PAL")
88 | if (!f.exists())
89 | f.mkdir()
90 | return mkdirUntilEmpty(f)
91 | }
92 | }
93 | return File(Constants.BASE_DIR)
94 | }
95 |
96 | fun rm(name: String)
97 | {
98 | rm(File(name))
99 | }
100 |
101 | fun rm(file: File)
102 | {
103 | if (file.exists())
104 | if (file.isDirectory)
105 | for (f in file.listFiles())
106 | rm(f)
107 | delete(file)
108 | }
109 |
110 | fun delete(file: File)
111 | {
112 | System.err.println("Deleting: ${file.path}")
113 | file.delete()
114 | }
--------------------------------------------------------------------------------
/src/main/resources/Untitled-2.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/Untitled-2.psd
--------------------------------------------------------------------------------
/src/main/resources/bgi_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/bgi_big.png
--------------------------------------------------------------------------------
/src/main/resources/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/cancel.png
--------------------------------------------------------------------------------
/src/main/resources/cancel0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/cancel0.png
--------------------------------------------------------------------------------
/src/main/resources/cu0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/cu0.png
--------------------------------------------------------------------------------
/src/main/resources/cu1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/cu1.png
--------------------------------------------------------------------------------
/src/main/resources/lp0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/lp0.png
--------------------------------------------------------------------------------
/src/main/resources/lp1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/lp1.png
--------------------------------------------------------------------------------
/src/main/resources/minimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/minimize.png
--------------------------------------------------------------------------------
/src/main/resources/minimize_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/minimize_hl.png
--------------------------------------------------------------------------------
/src/main/resources/mu0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/mu0.png
--------------------------------------------------------------------------------
/src/main/resources/mu1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/mu1.png
--------------------------------------------------------------------------------
/src/main/resources/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/settings.png
--------------------------------------------------------------------------------
/src/main/resources/settings_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/settings_hl.png
--------------------------------------------------------------------------------
/src/main/resources/ui.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 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
--------------------------------------------------------------------------------
/src/main/resources/witch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/POE-Addon-Launcher/PoE-Addon-Launcher/8c8cab786ce96ed4a88e1c6a0910fc038c710118/src/main/resources/witch.png
--------------------------------------------------------------------------------