Compare commits
319 Commits
compressed
...
v0.8.7_com
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3db80216a4 | ||
|
|
ee3b82c0b1 | ||
|
|
8988f37896 | ||
|
|
09b4324873 | ||
|
|
a5a2764cb4 | ||
|
|
6de4d0c374 | ||
|
|
48c33d766b | ||
|
|
22493ee0e9 | ||
|
|
8afc3133c6 | ||
|
|
d0cfa29929 | ||
|
|
6a51d462d7 | ||
|
|
4f7cc4942c | ||
|
|
6631e01b64 | ||
|
|
133dffe330 | ||
|
|
6e5d17173f | ||
|
|
7463d15159 | ||
|
|
beff0f1b71 | ||
|
|
867ed36419 | ||
|
|
387c1e126f | ||
|
|
c9d7cda233 | ||
|
|
b75521da59 | ||
|
|
5f9ee8a410 | ||
|
|
296c3b453c | ||
|
|
6e2da63308 | ||
|
|
445cd9fe8e | ||
|
|
a0cc567694 | ||
|
|
70d084fba7 | ||
|
|
5236aa0bf9 | ||
|
|
0eccb511db | ||
|
|
88c17db72b | ||
|
|
098fb95653 | ||
|
|
21d6bb7b7d | ||
|
|
ce91c5c7c8 | ||
|
|
613ab9101e | ||
|
|
3fbc7cf65f | ||
|
|
dc18289d18 | ||
|
|
6473e231e4 | ||
|
|
33a61b7a57 | ||
|
|
c070a39f7c | ||
|
|
995ec0f697 | ||
|
|
6cba6872c9 | ||
|
|
8812f664e7 | ||
|
|
d9113b2dab | ||
|
|
ad0025ba03 | ||
|
|
984aa17cc0 | ||
|
|
4cad05ce6b | ||
|
|
197ab946be | ||
|
|
e4cdbc1840 | ||
|
|
04f00553ae | ||
|
|
0c02902ceb | ||
|
|
aba93fb15b | ||
|
|
1c8330b99a | ||
|
|
a8de7c2860 | ||
|
|
4ca8bbfc12 | ||
|
|
a5c004e4d4 | ||
|
|
e957e409e0 | ||
|
|
70d6340c11 | ||
|
|
bbbb69b175 | ||
|
|
4d5b7d8667 | ||
|
|
43da08f57d | ||
|
|
7b97367bdd | ||
|
|
e6fb647b99 | ||
|
|
5e4d7aba18 | ||
|
|
a96086b9af | ||
|
|
0566cf899c | ||
|
|
c8e87fb3d0 | ||
|
|
0a56a0ba86 | ||
|
|
026ccde2ff | ||
|
|
7813994b81 | ||
|
|
d3b070844f | ||
|
|
7a879f99b1 | ||
|
|
e810cdb3cb | ||
|
|
398be07c31 | ||
|
|
6db4c7bb3c | ||
|
|
c402824641 | ||
|
|
abc020e8f5 | ||
|
|
82caf260ce | ||
|
|
cbcf5ff8ca | ||
|
|
39d07bf8a8 | ||
|
|
93174f0d65 | ||
|
|
6afbeb9a2a | ||
|
|
a7cbd644f3 | ||
|
|
f674aff07c | ||
|
|
07b89a288c | ||
|
|
0264c418ca | ||
|
|
494b9c47cc | ||
|
|
6ff6c6dd6c | ||
|
|
00ab587265 | ||
|
|
67fa480805 | ||
|
|
91db56e7a7 | ||
|
|
36d52bedad | ||
|
|
c36b676720 | ||
|
|
5e0a999249 | ||
|
|
8fff4aff60 | ||
|
|
8c5344ff37 | ||
|
|
91e49b6c4a | ||
|
|
52cfb37b21 | ||
|
|
87886f08bb | ||
|
|
a31d7f9589 | ||
|
|
5600957f32 | ||
|
|
d6840a83c9 | ||
|
|
06fdd39648 | ||
|
|
b5763e7f76 | ||
|
|
75f01f20b9 | ||
|
|
dd366ab69e | ||
|
|
6ab443ec2c | ||
|
|
e0056cbf5c | ||
|
|
9f9397e1f3 | ||
|
|
d5a43cc7e1 | ||
|
|
408d8aa8b8 | ||
|
|
1e663069e8 | ||
|
|
dbcec1a199 | ||
|
|
04b4193548 | ||
|
|
058803184f | ||
|
|
5b5912c5bc | ||
|
|
759e632c07 | ||
|
|
6e311ecb64 | ||
|
|
b480fd9173 | ||
|
|
226459ddb8 | ||
|
|
92de033bc8 | ||
|
|
faf0dd061c | ||
|
|
9eaf9ea2ed | ||
|
|
00c4f77251 | ||
|
|
96ef9eedbb | ||
|
|
a5d94c03e2 | ||
|
|
9d15d380a3 | ||
|
|
bff780c837 | ||
|
|
0c493952c8 | ||
|
|
a1f6e1d29c | ||
|
|
fc71f43755 | ||
|
|
16afcf4886 | ||
|
|
b64a3c2109 | ||
|
|
5c0dc66183 | ||
|
|
3047f653bd | ||
|
|
393a478d13 | ||
|
|
560cb326f9 | ||
|
|
3fe2d7260f | ||
|
|
2cd4bc7ee5 | ||
|
|
19468b591d | ||
|
|
903117d32f | ||
|
|
f5bfc98c62 | ||
|
|
3274feb1e9 | ||
|
|
392b4d8577 | ||
|
|
92e4afde4b | ||
|
|
0c7724fe33 | ||
|
|
ca5be34fc2 | ||
|
|
28c3c7a0ec | ||
|
|
7f39cf1a6f | ||
|
|
365839571a | ||
|
|
5c3a04ca77 | ||
|
|
758a580063 | ||
|
|
ad5dbc9f9d | ||
|
|
4a86680928 | ||
|
|
ece63cf442 | ||
|
|
b487140a1b | ||
|
|
ad72bf8895 | ||
|
|
5919c429d2 | ||
|
|
0b6580e7c9 | ||
|
|
6efb2b3860 | ||
|
|
7ae084073f | ||
|
|
36df0b1732 | ||
|
|
b8fb100bd5 | ||
|
|
82b904d176 | ||
|
|
111aca868c | ||
|
|
2171c16d47 | ||
|
|
acd4d84783 | ||
|
|
cc25cc97f1 | ||
|
|
93ecebc448 | ||
|
|
f5713a3eb2 | ||
|
|
90001bb4d6 | ||
|
|
357cab9b1e | ||
|
|
5ea272f286 | ||
|
|
0c876bd1c5 | ||
|
|
0ac2999694 | ||
|
|
49af3c4b6d | ||
|
|
2a54b31d31 | ||
|
|
64766ce50a | ||
|
|
311accfdd3 | ||
|
|
2b5bf2fa4a | ||
|
|
64342c96d7 | ||
|
|
f8649bb0a5 | ||
|
|
fde6608c26 | ||
|
|
3f339c14a2 | ||
|
|
922db05c4d | ||
|
|
b849de8b66 | ||
|
|
f798b29729 | ||
|
|
e58e7a2588 | ||
|
|
a1ef339831 | ||
|
|
2002d51f6b | ||
|
|
025283b70b | ||
|
|
577b1aa034 | ||
|
|
da637c0cc8 | ||
|
|
d026ff690a | ||
|
|
d14ed56669 | ||
|
|
64cfacb7ff | ||
|
|
98a800e070 | ||
|
|
35219c8e88 | ||
|
|
b636cad347 | ||
|
|
733328cd29 | ||
|
|
36db28f805 | ||
|
|
6d4c1c3c14 | ||
|
|
eadb95f8e8 | ||
|
|
014f67f270 | ||
|
|
cd8657adb4 | ||
|
|
c007fc4d1c | ||
|
|
7e6c864ba3 | ||
|
|
f2da8f767a | ||
|
|
bd856541d6 | ||
|
|
bdde2176d9 | ||
|
|
171893a2c1 | ||
|
|
c6c1d6d03d | ||
|
|
ec8b114782 | ||
|
|
aaecb8ae4a | ||
|
|
4e2e3b370c | ||
|
|
c14f8f84a0 | ||
|
|
13c8012710 | ||
|
|
3806d77b26 | ||
|
|
af94220715 | ||
|
|
af07c47832 | ||
|
|
322007e5ac | ||
|
|
af5cdb9d49 | ||
|
|
3ada8ceaa7 | ||
|
|
68fa0068dc | ||
|
|
7b5fc79375 | ||
|
|
5dfa750227 | ||
|
|
cbe0773310 | ||
|
|
72a19eeb80 | ||
|
|
a993cc5a08 | ||
|
|
83724ba408 | ||
|
|
a4cd8f7460 | ||
|
|
7a52bbb9f3 | ||
|
|
3552ff8a9f | ||
|
|
0e081f3319 | ||
|
|
1d94519e1c | ||
|
|
0bbc6adb4b | ||
|
|
b48ddd4999 | ||
|
|
be8dad981d | ||
|
|
f9708f48a4 | ||
|
|
155b01bdea | ||
|
|
19810b2099 | ||
|
|
c6886f7a3e | ||
|
|
3bea24f9cc | ||
|
|
4b8f5c4908 | ||
|
|
66d9618b1b | ||
|
|
488d6347d0 | ||
|
|
51fd0d0994 | ||
|
|
50833af145 | ||
|
|
ca7c2388aa | ||
|
|
8e7d6adca5 | ||
|
|
17edb96ff8 | ||
|
|
3f3869916c | ||
|
|
1d2fc7ade7 | ||
|
|
aa84e5a73d | ||
|
|
4ecf7d2dda | ||
|
|
dca1cb676c | ||
|
|
9a4f41eac2 | ||
|
|
23012b0d40 | ||
|
|
916134bd9b | ||
|
|
1d6777daae | ||
|
|
4793751ba8 | ||
|
|
185c0eaf7c | ||
|
|
4b50d13149 | ||
|
|
23b58c3e7c | ||
|
|
2d5ebc3b13 | ||
|
|
59e2e3035c | ||
|
|
6d5ddfdbfa | ||
|
|
f8ae18721f | ||
|
|
63bc7c3a4e | ||
|
|
8e72763314 | ||
|
|
9310d53362 | ||
|
|
a71dcc13a3 | ||
|
|
ea95f4ff87 | ||
|
|
f35167d112 | ||
|
|
9f935190f2 | ||
|
|
c11430cf6b | ||
|
|
8f97a27ab7 | ||
|
|
9e36f848dc | ||
|
|
b24d52b1da | ||
|
|
e2a9307560 | ||
|
|
e3ac804f61 | ||
|
|
fd504d2df5 | ||
|
|
0e615d3f11 | ||
|
|
47646457ab | ||
|
|
8e393b93d8 | ||
|
|
3289bd6fb1 | ||
|
|
23a331d655 | ||
|
|
112301c444 | ||
|
|
f50e4f1d38 | ||
|
|
d623c22b38 | ||
|
|
d11bf5b0aa | ||
|
|
e30f67e327 | ||
|
|
6946b1f2b3 | ||
|
|
96a1a5760a | ||
|
|
58b802e911 | ||
|
|
f9b095565b | ||
|
|
19817eb97d | ||
|
|
f46d2aedbf | ||
|
|
913b651953 | ||
|
|
5283eed28e | ||
|
|
deb824d50e | ||
|
|
6841d862e4 | ||
|
|
f94723b0cd | ||
|
|
ab41168736 | ||
|
|
2d73c4687a | ||
|
|
e454deb8b1 | ||
|
|
074891805a | ||
|
|
d2d32bc4ed | ||
|
|
22daeb0c33 | ||
|
|
db30253baf | ||
|
|
312cb7dec7 | ||
|
|
7befd27951 | ||
|
|
c1e3bfa7ed | ||
|
|
ddec991082 | ||
|
|
79e6fe7b65 | ||
|
|
25e36dc535 | ||
|
|
83c579a929 | ||
|
|
0c694115ee | ||
|
|
bf9723b0c1 | ||
|
|
b81bacb1fe |
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/AndorsTrail/.idea/workspace.xml
|
||||
6
AndorsTrail/.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
20
AndorsTrail/.idea/gradle.xml
generated
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.8" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
25
AndorsTrail/.idea/jarRepositories.xml
generated
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
10
AndorsTrail/.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
6
AndorsTrail/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
166
AndorsTrail/.idea/workspace.xml
generated
@@ -1,166 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="NONE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="fb7bf33b-30cf-40b9-a238-3e2f6f604a8f" name="Changes" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[AQ8PSW4DBUZPMZOR]" />
|
||||
<component name="ExternalProjectsData">
|
||||
<projectState path="$PROJECT_DIR$">
|
||||
<ProjectState />
|
||||
</projectState>
|
||||
</component>
|
||||
<component name="ExternalProjectsManager">
|
||||
<system id="GRADLE">
|
||||
<state>
|
||||
<projects_view>
|
||||
<tree_state>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||
<item name="AndorsTrail" type="f1a62948:ProjectNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</tree_state>
|
||||
</projects_view>
|
||||
</state>
|
||||
</system>
|
||||
</component>
|
||||
<component name="GenerateSignedApkSettings">
|
||||
<option name="KEY_STORE_PATH" value="C:\AT\sec\AndorsTrail.keystore" />
|
||||
<option name="KEY_ALIAS" value="andorstrail" />
|
||||
<option name="REMEMBER_PASSWORDS" value="true" />
|
||||
<option name="BUILD_TARGET_KEY" value="apk" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||
</component>
|
||||
<component name="ProjectId" id="2FG0LqADbxm6Q1t3yQ9BlX5APzJ" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="ApkExportedModule" value="AndorsTrail.app" />
|
||||
<property name="ExportApk.ApkPath" value="C:\AT\AndorsTrailRelease\andors-trail\AndorsTrail\app" />
|
||||
<property name="ExportApk.BuildVariants" value="release" />
|
||||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="RunOnceActivity.cidr.known.project.marker" value="true" />
|
||||
<property name="android.sdk.path" value="$USER_HOME$/AppData/Local/Android/Sdk" />
|
||||
<property name="cidr.known.project.marker" value="true" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../sec/AndorsTrail.keystore" />
|
||||
<property name="settings.editor.selected.configurable" value="device.file.explorer" />
|
||||
<property name="show.inlinked.gradle.project.popup" value="false" />
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="<template>" type="Applet" default="true" selected="false">
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="HTML_FILE_NAME" />
|
||||
<option name="HTML_USED" value="false" />
|
||||
<option name="WIDTH" value="400" />
|
||||
<option name="HEIGHT" value="300" />
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
</configuration>
|
||||
<configuration name="<template>" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false">
|
||||
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
|
||||
</configuration>
|
||||
<configuration name="app" type="AndroidRunConfigurationType" factoryName="Android App">
|
||||
<module name="AndorsTrail.app" />
|
||||
<option name="DEPLOY" value="true" />
|
||||
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
|
||||
<option name="DEPLOY_AS_INSTANT" value="false" />
|
||||
<option name="ARTIFACT_NAME" value="" />
|
||||
<option name="PM_INSTALL_OPTIONS" value="" />
|
||||
<option name="ALL_USERS" value="false" />
|
||||
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
|
||||
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
|
||||
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
|
||||
<option name="MODE" value="default_activity" />
|
||||
<option name="CLEAR_LOGCAT" value="false" />
|
||||
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
|
||||
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
|
||||
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
|
||||
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
|
||||
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
|
||||
<option name="DEBUGGER_TYPE" value="Auto" />
|
||||
<Auto>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
</Auto>
|
||||
<Hybrid>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
</Hybrid>
|
||||
<Java />
|
||||
<Native>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
</Native>
|
||||
<Profilers>
|
||||
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
|
||||
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
|
||||
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
|
||||
</Profilers>
|
||||
<option name="DEEP_LINK" value="" />
|
||||
<option name="ACTIVITY_CLASS" value="" />
|
||||
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
|
||||
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration default="true" type="Application" factoryName="Application">
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="JUnit" factoryName="JUnit">
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="TestNG">
|
||||
<option name="TEST_OBJECT" value="CLASS" />
|
||||
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
|
||||
<properties />
|
||||
<listeners />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="fb7bf33b-30cf-40b9-a238-3e2f6f604a8f" name="Changes" comment="" />
|
||||
<created>1664103080085</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1664103080085</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,23 +1,52 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.gpl.rpg.AndorsTrail"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
manifestPlaceholders icon_name: 'icon', fileproviderPath: 'AndorsTrail'
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
debug {
|
||||
manifestPlaceholders icon_name: 'icon_beta', fileproviderPath: 'AndorsTrail.beta2'
|
||||
applicationIdSuffix 'beta2'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
}
|
||||
|
||||
task copyRes(type: Copy) {
|
||||
description "Copies the res folder to the modules res folder (& renames .tmx to .xml)"
|
||||
from "${rootDir}/res"
|
||||
into "${projectDir}/src/main/res"
|
||||
rename "(.*)\\.tmx", "\$1.xml"
|
||||
}
|
||||
|
||||
task copyTranslation(type: Copy) {
|
||||
description("Copies the translation files to the modules translations folder")
|
||||
from "${rootDir}/assets/translation"
|
||||
into "${projectDir}/src/main/assets/translation"
|
||||
}
|
||||
|
||||
task cleanup(type: Delete) {
|
||||
description("Deletes the assets/translation and the res folder from the modules folder")
|
||||
delete "${projectDir}/src/main/res", "${projectDir}/src/main/assets/translation"
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
preBuild.dependsOn project.tasks.copyRes
|
||||
preBuild.dependsOn project.tasks.copyTranslation
|
||||
clean.dependsOn project.tasks.cleanup
|
||||
}
|
||||
|
||||
@@ -3,15 +3,11 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.gpl.rpg.AndorsTrail"
|
||||
android:versionCode="65"
|
||||
android:versionName="0.8.1"
|
||||
android:versionCode="72"
|
||||
android:versionName="0.8.6.1"
|
||||
android:installLocation="auto"
|
||||
>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="4"
|
||||
android:targetSdkVersion="30"
|
||||
/>
|
||||
|
||||
|
||||
<supports-screens
|
||||
android:smallScreens="true"
|
||||
android:normalScreens="true"
|
||||
@@ -27,7 +23,7 @@
|
||||
<application
|
||||
android:name="com.gpl.rpg.AndorsTrail.AndorsTrailApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:icon="@drawable/${icon_name}"
|
||||
android:description="@string/app_description"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AndorsTrailTheme_Blue"
|
||||
@@ -37,6 +33,7 @@
|
||||
>
|
||||
<activity
|
||||
android:name="com.gpl.rpg.AndorsTrail.activity.StartScreenActivity"
|
||||
android:exported="true"
|
||||
android:clearTaskOnLaunch="true"
|
||||
>
|
||||
<intent-filter>
|
||||
@@ -67,7 +64,7 @@
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="com.gpl.rpg.AndorsTrail.fileprovider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
|
||||
@@ -28,11 +28,11 @@ public final class AndorsTrailApplication extends Application {
|
||||
public static final boolean DEVELOPMENT_FASTSPEED = false;
|
||||
public static final boolean DEVELOPMENT_VALIDATEDATA = false;
|
||||
public static final boolean DEVELOPMENT_DEBUGMESSAGES = false;
|
||||
public static final String CURRENT_VERSION_DISPLAY = "0.8.1";
|
||||
public static final String CURRENT_VERSION_DISPLAY = "0.8.6.1";
|
||||
public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*");
|
||||
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED || !IS_RELEASE_VERSION;
|
||||
public static final int DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION = 999;
|
||||
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 65;
|
||||
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 72;
|
||||
|
||||
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
|
||||
private WorldContext world = new WorldContext();
|
||||
|
||||
@@ -78,7 +78,7 @@ public final class AndorsTrailPreferences {
|
||||
dest.dpadTransparency = Integer.parseInt(prefs.getString("dpadtransparency", Integer.toString(DPAD_TRANSPARENCY_50_PERCENT)));
|
||||
dest.dpadMinimizeable = prefs.getBoolean("dpadMinimizeable", true);
|
||||
dest.optimizedDrawing = prefs.getBoolean("optimized_drawing", false);
|
||||
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", true);
|
||||
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", false);
|
||||
dest.enableUiAnimations = prefs.getBoolean("enableUiAnimations", true);
|
||||
dest.displayOverwriteSavegame = Integer.parseInt(prefs.getString("display_overwrite_savegame", Integer.toString(CONFIRM_OVERWRITE_SAVEGAME_ALWAYS)));
|
||||
dest.quickslotsPosition = Integer.parseInt(prefs.getString("quickslots_placement", Integer.toString(QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM)));
|
||||
|
||||
@@ -46,14 +46,15 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
|
||||
|
||||
public final class Dialogs {
|
||||
|
||||
private static void showDialogAndPause(Dialog d, final ControllerContext context) {
|
||||
private static void showDialogAndPause(CustomDialog d, final ControllerContext context) {
|
||||
showDialogAndPause(d, context, null);
|
||||
}
|
||||
private static void showDialogAndPause(Dialog d, final ControllerContext context, final OnDismissListener onDismiss) {
|
||||
private static void showDialogAndPause(CustomDialog d, final ControllerContext context, final OnDismissListener onDismiss) {
|
||||
context.gameRoundController.pause();
|
||||
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
|
||||
@Override
|
||||
@@ -195,7 +196,7 @@ public final class Dialogs {
|
||||
// itemList.setPadding(20, 0, 20, 20);
|
||||
itemList.setAdapter(new ItemContainerAdapter(mainActivity, world.tileManager, combinedLoot.items, world.model.player));
|
||||
|
||||
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
mainActivity.getResources().getString(title),
|
||||
mainActivity.getResources().getDrawable(R.drawable.ui_icon_equipment),
|
||||
msg,
|
||||
@@ -249,7 +250,7 @@ public final class Dialogs {
|
||||
}
|
||||
|
||||
public static void showHeroDied(final MainActivity mainActivity, final ControllerContext controllers) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
mainActivity.getResources().getString(R.string.dialog_game_over_title),
|
||||
mainActivity.getResources().getDrawable(R.drawable.ui_icon_combat),
|
||||
mainActivity.getResources().getString(R.string.dialog_game_over_text),
|
||||
@@ -286,7 +287,7 @@ public final class Dialogs {
|
||||
}
|
||||
|
||||
public static void showConfirmRest(final Activity currentActivity, final ControllerContext controllerContext, final MapObject area) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
currentActivity.getResources().getString(R.string.dialog_rest_title),
|
||||
null,
|
||||
currentActivity.getResources().getString(R.string.dialog_rest_confirm_message),
|
||||
@@ -310,7 +311,7 @@ public final class Dialogs {
|
||||
// .setMessage(R.string.dialog_rest_message)
|
||||
// .setNeutralButton(android.R.string.ok, null)
|
||||
// .create();
|
||||
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
currentActivity.getResources().getString(R.string.dialog_rest_title),
|
||||
null,
|
||||
currentActivity.getResources().getString(R.string.dialog_rest_message),
|
||||
@@ -336,7 +337,7 @@ public final class Dialogs {
|
||||
text += currentActivity.getResources().getString(R.string.dialog_newversion_permission_information);
|
||||
}
|
||||
|
||||
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
|
||||
currentActivity.getResources().getString(R.string.dialog_newversion_title),
|
||||
null,
|
||||
text,
|
||||
@@ -371,7 +372,7 @@ public final class Dialogs {
|
||||
}
|
||||
|
||||
if (!world.model.statistics.hasUnlimitedSaves()) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
|
||||
mainActivity.getResources().getString(R.string.menu_save_switch_character_title),
|
||||
null,
|
||||
mainActivity.getResources().getString(R.string.menu_save_switch_character),
|
||||
@@ -460,7 +461,7 @@ public final class Dialogs {
|
||||
itemList.setAdapter(new ArrayAdapter<String>(context, R.layout.combatlog_row, android.R.id.text1, combatLogMessages));
|
||||
view = itemList;
|
||||
|
||||
final Dialog d = CustomDialogFactory.createDialog(context,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(context,
|
||||
context.getResources().getString(R.string.combat_log_title),
|
||||
context.getResources().getDrawable(R.drawable.ui_icon_combat),
|
||||
null,
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.gpl.rpg.AndorsTrail.controller.ItemController;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
|
||||
/**
|
||||
* @author ejwessel
|
||||
@@ -206,7 +207,7 @@ public final class BulkSelectionInterface extends AndorsTrailBaseActivity implem
|
||||
// })
|
||||
// .setNegativeButton(android.R.string.no, null)
|
||||
// .show();
|
||||
final Dialog d = CustomDialogFactory.createDialog(v.getContext(),
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(v.getContext(),
|
||||
v.getContext().getResources().getString(R.string.bulkselection_sell_confirmation_title),
|
||||
v.getContext().getResources().getDrawable(android.R.drawable.ic_dialog_info),
|
||||
message,
|
||||
|
||||
@@ -20,11 +20,12 @@ import com.gpl.rpg.AndorsTrail.savegames.Savegames;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
|
||||
public final class LoadingActivity extends AndorsTrailBaseActivity implements OnResourcesLoadedListener, OnSceneLoadedListener {
|
||||
|
||||
private WorldSetup setup;
|
||||
private Dialog progressDialog;
|
||||
private CustomDialog progressDialog;
|
||||
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
|
||||
boolean loaded = false;
|
||||
|
||||
@@ -165,7 +166,7 @@ public final class LoadingActivity extends AndorsTrailBaseActivity implements On
|
||||
}
|
||||
|
||||
private void showLoadingFailedDialog(int messageResourceID) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
|
||||
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
|
||||
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
|
||||
@Override
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CombatView;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
import com.gpl.rpg.AndorsTrail.view.DisplayActiveActorConditionIcons;
|
||||
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
|
||||
import com.gpl.rpg.AndorsTrail.view.MainView;
|
||||
@@ -247,7 +248,7 @@ public final class MainActivity
|
||||
final ItemContainerAdapter inventoryListAdapter = new QuickslotsItemContainerAdapter(lv.getContext(), world.tileManager, world.model.player.inventory.usableItems(), world.model.player, wornTiles);
|
||||
lv.setAdapter(inventoryListAdapter);
|
||||
|
||||
final Dialog d = CustomDialogFactory.createDialog(v.getContext(),
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(v.getContext(),
|
||||
v.getResources().getString(R.string.inventory_assign),
|
||||
v.getResources().getDrawable(R.drawable.ui_icon_equipment),
|
||||
v.getResources().getString(R.string.inventory_selectitem), view, false);
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
@@ -114,7 +115,7 @@ public final class StartScreenActivity extends AndorsTrailBaseFragmentActivity i
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
final Dialog d = CustomDialogFactory.createDialog(this,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(this,
|
||||
getResources().getString(R.string.dialog_permission_information_title),
|
||||
getResources().getDrawable(android.R.drawable.ic_dialog_info),
|
||||
getResources().getString(R.string.dialog_permission_information),
|
||||
|
||||
@@ -38,25 +38,26 @@ import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
|
||||
public class StartScreenActivity_MainMenu extends Fragment {
|
||||
|
||||
private static final int INTENTREQUEST_PREFERENCES = 7;
|
||||
public static final int INTENTREQUEST_LOADGAME = 9;
|
||||
private static final int INTENTREQUEST_PREFERENCES = 7;
|
||||
public static final int INTENTREQUEST_LOADGAME = 9;
|
||||
|
||||
private boolean hasExistingGame = false;
|
||||
private Button startscreen_continue;
|
||||
private Button startscreen_newgame;
|
||||
private Button startscreen_load;
|
||||
private ViewGroup save_preview_holder;
|
||||
private ImageView save_preview_hero_icon;
|
||||
private TextView save_preview_hero_desc;
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
updatePreferences(false);
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
private boolean hasExistingGame = false;
|
||||
private Button startscreen_continue;
|
||||
private Button startscreen_newgame;
|
||||
private Button startscreen_load;
|
||||
private ViewGroup save_preview_holder;
|
||||
private ImageView save_preview_hero_icon;
|
||||
private TextView save_preview_hero_desc;
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
updatePreferences(false);
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
|
||||
if (container != null) {
|
||||
@@ -64,11 +65,11 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
}
|
||||
|
||||
View root = inflater.inflate(R.layout.startscreen_mainmenu, container, false);
|
||||
|
||||
|
||||
save_preview_holder = (ViewGroup) root.findViewById(R.id.save_preview_holder);
|
||||
save_preview_hero_icon = (ImageView) root.findViewById(R.id.save_preview_hero_icon);
|
||||
save_preview_hero_desc = (TextView) root.findViewById(R.id.save_preview_hero_desc);
|
||||
|
||||
|
||||
|
||||
startscreen_continue = (Button) root.findViewById(R.id.startscreen_continue);
|
||||
startscreen_continue.setOnClickListener(new OnClickListener() {
|
||||
@@ -114,7 +115,7 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
|
||||
if (hasExistingGame && app != null && app.getWorld() != null && app.getWorld().model != null
|
||||
&& app.getWorld().model.statistics != null && !app.getWorld().model.statistics.hasUnlimitedSaves()) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(getActivity(),
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(getActivity(),
|
||||
getString(R.string.startscreen_load_game),
|
||||
getResources().getDrawable(android.R.drawable.ic_delete),
|
||||
getString(R.string.startscreen_load_game_confirm),
|
||||
@@ -134,7 +135,7 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (AndorsTrailApplication.DEVELOPMENT_FORCE_STARTNEWGAME) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) {
|
||||
@@ -152,14 +153,14 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
checkAndRequestPermissions(getActivity());
|
||||
migrateDataOnDemand(getActivity());
|
||||
}
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
String playerName;
|
||||
String displayInfo = null;
|
||||
int iconID = TileManager.CHAR_HERO;
|
||||
@@ -189,14 +190,10 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
setCurrentVersionForVersionCheck();
|
||||
checkAndRequestPermissions(getActivity());
|
||||
migrateDataOnDemand(getActivity());
|
||||
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
|
||||
startscreen_load.setEnabled(hasSavegames);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
|
||||
startscreen_load.setEnabled(hasSavegames);
|
||||
}
|
||||
|
||||
@TargetApi(29)
|
||||
@@ -204,23 +201,16 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
if (AndroidStorage.shouldMigrateToInternalStorage(activity.getApplicationContext())) {
|
||||
final Dialog d = CustomDialogFactory.createDialog(activity,
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(activity,
|
||||
getString(R.string.startscreen_migration_title),
|
||||
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
|
||||
getString(R.string.startscreen_migration_text),
|
||||
null,
|
||||
true);
|
||||
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
|
||||
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface arg0) {
|
||||
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
|
||||
startscreen_load.setEnabled(hasSavegames);
|
||||
}
|
||||
});
|
||||
CustomDialogFactory.show(d);
|
||||
if (!AndroidStorage.migrateToInternalStorage(activity.getApplicationContext())) {
|
||||
final Dialog errorDlg = CustomDialogFactory.createDialog(activity,
|
||||
final CustomDialog errorDlg = CustomDialogFactory.createDialog(activity,
|
||||
getString(R.string.startscreen_migration_title),
|
||||
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
|
||||
getString(R.string.startscreen_migration_failure),
|
||||
@@ -259,13 +249,13 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
super.onAttach(activity);
|
||||
listener = (OnNewGameRequestedListener) activity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
listener = null;
|
||||
}
|
||||
|
||||
|
||||
private void setButtonState(final String playerName, final String displayInfo, int iconID, boolean isDead) {
|
||||
startscreen_continue.setEnabled(hasExistingGame && !isDead);
|
||||
startscreen_newgame.setEnabled(true);
|
||||
@@ -305,9 +295,9 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
// .create().show();
|
||||
//
|
||||
//
|
||||
final Dialog d = CustomDialogFactory.createDialog(getActivity(),
|
||||
getString(R.string.startscreen_newgame),
|
||||
getResources().getDrawable(android.R.drawable.ic_delete),
|
||||
final CustomDialog d = CustomDialogFactory.createDialog(getActivity(),
|
||||
getString(R.string.startscreen_newgame),
|
||||
getResources().getDrawable(android.R.drawable.ic_delete),
|
||||
getResources().getString(R.string.startscreen_newgame_confirm),
|
||||
null,
|
||||
true);
|
||||
@@ -318,9 +308,9 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
}
|
||||
});
|
||||
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
|
||||
|
||||
|
||||
CustomDialogFactory.show(d);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static final String versionCheck = "lastversion";
|
||||
@@ -337,64 +327,90 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
e.putInt(versionCheck, AndorsTrailApplication.CURRENT_VERSION);
|
||||
e.commit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case INTENTREQUEST_LOADGAME:
|
||||
if (resultCode != Activity.RESULT_OK) break;
|
||||
final int slot = data.getIntExtra("slot", 1);
|
||||
continueGame(false, slot, null);
|
||||
break;
|
||||
case INTENTREQUEST_PREFERENCES:
|
||||
updatePreferences(true);
|
||||
break;
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case INTENTREQUEST_LOADGAME:
|
||||
boolean unsuccessful = resultCode != Activity.RESULT_OK;
|
||||
if(data == null) break;
|
||||
|
||||
final boolean wasImportOrExport = data.getBooleanExtra("import_export", false);
|
||||
if (wasImportOrExport) {
|
||||
String message = getImportExportMessage(!unsuccessful, data);
|
||||
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
}
|
||||
if (unsuccessful) break;
|
||||
final int slot = data.getIntExtra("slot", 1);
|
||||
continueGame(false, slot, null);
|
||||
break;
|
||||
case INTENTREQUEST_PREFERENCES:
|
||||
updatePreferences(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String getImportExportMessage(boolean successful, Intent data) {
|
||||
String message = "";
|
||||
boolean isImportWorldmap = data.getBooleanExtra("import_worldmap", false);
|
||||
boolean isImportSaves = data.getBooleanExtra("import_savegames", false);
|
||||
boolean isExport = data.getBooleanExtra("export", false);
|
||||
|
||||
if(isImportWorldmap) {
|
||||
message = getString(successful ? R.string.loadsave_import_worldmap_successfull : R.string.loadsave_import_worldmap_unsuccessfull);
|
||||
} else if(isImportSaves) {
|
||||
message = getString(successful ? R.string.loadsave_import_save_successfull : R.string.loadsave_import_save_unsuccessfull);
|
||||
} else if(isExport) {
|
||||
message = getString(successful ? R.string.loadsave_export_successfull : R.string.loadsave_export_unsuccessfull);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
private void updatePreferences(boolean alreadyStartedLoadingResources) {
|
||||
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
|
||||
AndorsTrailPreferences preferences = app.getPreferences();
|
||||
preferences.read(getActivity());
|
||||
if (app.setLocale(getActivity())) {
|
||||
if (alreadyStartedLoadingResources) {
|
||||
// Changing the locale after having loaded the game requires resources to
|
||||
// be re-loaded. Therefore, we just exit here.
|
||||
Toast.makeText(getActivity(), R.string.change_locale_requires_restart, Toast.LENGTH_LONG).show();
|
||||
doFinish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ThemeHelper.changeTheme(preferences.selectedTheme)) {
|
||||
// Changing the theme requires a restart to re-create all activities.
|
||||
Toast.makeText(getActivity(), R.string.change_theme_requires_restart, Toast.LENGTH_LONG).show();
|
||||
doFinish();
|
||||
return;
|
||||
}
|
||||
app.getWorld().tileManager.updatePreferences(preferences);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void doFinish() {
|
||||
//For Lollipop and above
|
||||
((AndorsTrailApplication)getActivity().getApplication()).discardWorld();
|
||||
getActivity().finish();
|
||||
}
|
||||
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
|
||||
AndorsTrailPreferences preferences = app.getPreferences();
|
||||
preferences.read(getActivity());
|
||||
if (app.setLocale(getActivity())) {
|
||||
if (alreadyStartedLoadingResources) {
|
||||
// Changing the locale after having loaded the game requires resources to
|
||||
// be re-loaded. Therefore, we just exit here.
|
||||
Toast.makeText(getActivity(), R.string.change_locale_requires_restart, Toast.LENGTH_LONG).show();
|
||||
doFinish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ThemeHelper.changeTheme(preferences.selectedTheme)) {
|
||||
// Changing the theme requires a restart to re-create all activities.
|
||||
Toast.makeText(getActivity(), R.string.change_theme_requires_restart, Toast.LENGTH_LONG).show();
|
||||
doFinish();
|
||||
return;
|
||||
}
|
||||
app.getWorld().tileManager.updatePreferences(preferences);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void doFinish() {
|
||||
//For Lollipop and above
|
||||
((AndorsTrailApplication) getActivity().getApplication()).discardWorld();
|
||||
getActivity().finish();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface OnNewGameRequestedListener {
|
||||
public void onNewGameRequested();
|
||||
}
|
||||
|
||||
|
||||
private OnNewGameRequestedListener listener = null;
|
||||
|
||||
|
||||
private void createNewGame() {
|
||||
if (listener != null) {
|
||||
listener.onNewGameRequested();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
public final class Constants {
|
||||
public static final int PERCENT_EXP_LOST_WHEN_DIED = 30;
|
||||
public static final int PERCENT_EXP_LOST_WHEN_DIED = 20;
|
||||
public static final int LEVELUP_EFFECT_HEALTH = 5;
|
||||
public static final int LEVELUP_EFFECT_ATK_CH = 5;
|
||||
public static final int LEVELUP_EFFECT_ATK_DMG = 1;
|
||||
@@ -51,6 +51,10 @@ public final class Constants {
|
||||
public static final String CHEAT_DETECTION_FOLDER = "dEAGyGE3YojqXjI3x4x7";
|
||||
public static final String PASSIVE_ACHIEVEMENT_CHECK_PHRASE = "passive_achievement_check";
|
||||
|
||||
public static final String SAVEGAME_FILE_MIME_TYPE = "application/octet-stream";
|
||||
public static final String WORLDMAP_FILE_MIME_TYPE = "image/png";
|
||||
public static final String NO_FILE_EXTENSION_MIME_TYPE = "application/no_file_extension_mime_type";
|
||||
|
||||
public static final Random rnd = new Random();
|
||||
public static int rollValue(final ConstRange r) { return rollValue(r.max, r.current); }
|
||||
public static int rollValue(final ConstRange r, int bias) { return rollValue((r.max + 1) * 100 -1, r.current * 100 + bias)/100; }
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gpl.rpg.AndorsTrail.controller;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@@ -98,28 +99,36 @@ public final class InputController implements OnClickListener, OnLongClickListen
|
||||
|
||||
// Keys mapping to UP_LEFT
|
||||
key = KEY_MOVE_UP_LEFT;
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_LEFT, key);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_LEFT, key);
|
||||
}
|
||||
keyMap.put(KeyEvent.KEYCODE_NUMPAD_7, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_7, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_MOVE_HOME, key);
|
||||
|
||||
// Keys mapping to UP_RIGHT
|
||||
key = KEY_MOVE_UP_RIGHT;
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_RIGHT, key);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_RIGHT, key);
|
||||
}
|
||||
keyMap.put(KeyEvent.KEYCODE_NUMPAD_9, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_9, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_PAGE_UP, key);
|
||||
|
||||
// Keys mapping to DOWN_LEFT
|
||||
key = KEY_MOVE_DOWN_LEFT;
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_LEFT, key);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_LEFT, key);
|
||||
}
|
||||
keyMap.put(KeyEvent.KEYCODE_NUMPAD_1, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_1, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_MOVE_END, key);
|
||||
|
||||
// Keys mapping to DOWN_RIGHT
|
||||
key = KEY_MOVE_DOWN_RIGHT;
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, key);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, key);
|
||||
}
|
||||
keyMap.put(KeyEvent.KEYCODE_NUMPAD_3, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_3, key);
|
||||
keyMap.put(KeyEvent.KEYCODE_PAGE_DOWN, key);
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.Quest;
|
||||
import com.gpl.rpg.AndorsTrail.util.HashMapHelper;
|
||||
|
||||
public final class GameStatistics {
|
||||
private int deaths = 0;
|
||||
@@ -36,10 +37,10 @@ public final class GameStatistics {
|
||||
|
||||
public void addMonsterKill(MonsterType monsterType) {
|
||||
// Track monster kills by type ID, for savegame file
|
||||
killedMonstersByTypeID.put(monsterType.id, killedMonstersByTypeID.getOrDefault((monsterType.id), 0) + 1);
|
||||
killedMonstersByTypeID.put(monsterType.id, getNumberOfKillsForMonsterType(monsterType.id) + 1);
|
||||
|
||||
// Also track by name, for statistics display (multiple IDs w/same name don't matter to player)
|
||||
killedMonstersByName.put(monsterType.name, killedMonstersByName.getOrDefault(monsterType.name, 0) + 1);
|
||||
killedMonstersByName.put(monsterType.name, getNumberOfKillsForMonsterName(monsterType.name) + 1);
|
||||
}
|
||||
|
||||
public void addPlayerDeath(int lostExp) {
|
||||
@@ -50,8 +51,7 @@ public final class GameStatistics {
|
||||
}
|
||||
public void addItemUsage(ItemType type) {
|
||||
final String n = type.id;
|
||||
if (!usedItems.containsKey(n)) usedItems.put(n, 1);
|
||||
else usedItems.put(n, usedItems.get(n) + 1);
|
||||
usedItems.put(n, HashMapHelper.getOrDefault(usedItems, n,0) + 1);
|
||||
}
|
||||
|
||||
public int getDeaths() {
|
||||
@@ -73,15 +73,11 @@ public final class GameStatistics {
|
||||
public boolean isDead() { return !hasUnlimitedLives() && getLivesLeft() < 1; }
|
||||
|
||||
public int getNumberOfKillsForMonsterType(String monsterTypeID) {
|
||||
Integer v = killedMonstersByTypeID.get(monsterTypeID);
|
||||
if (v == null) return 0;
|
||||
return v;
|
||||
return HashMapHelper.getOrDefault(killedMonstersByTypeID, monsterTypeID, 0);
|
||||
}
|
||||
|
||||
public int getNumberOfKillsForMonsterName(String monsterName) {
|
||||
Integer v = killedMonstersByName.get(monsterName);
|
||||
if (v == null) return 0;
|
||||
return v;
|
||||
return HashMapHelper.getOrDefault(killedMonstersByName, monsterName, 0);
|
||||
}
|
||||
|
||||
public String getTop5MostCommonlyKilledMonsters(WorldContext world, Resources res) {
|
||||
@@ -144,20 +140,15 @@ public final class GameStatistics {
|
||||
}
|
||||
|
||||
public int getNumberOfUsedItems() {
|
||||
int result = 0;
|
||||
for (int v : usedItems.values()) result += v;
|
||||
return result;
|
||||
return HashMapHelper.sumIntegerValues(usedItems);
|
||||
}
|
||||
|
||||
public int getNumberOfTimesItemHasBeenUsed(String itemId) {
|
||||
if (!usedItems.containsKey(itemId)) return 0;
|
||||
return usedItems.get(itemId);
|
||||
return HashMapHelper.getOrDefault(usedItems, itemId, 0);
|
||||
}
|
||||
|
||||
public int getNumberOfKilledMonsters() {
|
||||
int result = 0;
|
||||
for (int v : killedMonstersByTypeID.values()) result += v;
|
||||
return result;
|
||||
return HashMapHelper.sumIntegerValues(killedMonstersByTypeID);
|
||||
}
|
||||
|
||||
private static final Comparator<Entry<String, Integer>> descendingValueComparator = new Comparator<Entry<String, Integer>>() {
|
||||
@@ -186,7 +177,7 @@ public final class GameStatistics {
|
||||
// Also track by name, for statistics display (multiple IDs w/same name don't matter to player)
|
||||
MonsterType t = world.monsterTypes.getMonsterType(id);
|
||||
|
||||
if (t != null) killedMonstersByName.put(t.name, killedMonstersByName.getOrDefault(t.name, 0) + value);
|
||||
if (t != null) killedMonstersByName.put(t.name, getNumberOfKillsForMonsterName(t.name) + value);
|
||||
}
|
||||
|
||||
if (fileversion <= 17) return;
|
||||
|
||||
@@ -83,7 +83,7 @@ public final class SkillCollection {
|
||||
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_CHANCE_PERCENT = 30;
|
||||
public static final int PER_SKILLPOINT_INCREASE_MAGICFINDER_CHANCE_PERCENT = 50;
|
||||
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_QUANTITY_PERCENT = 50;
|
||||
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 5;
|
||||
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 10;
|
||||
public static final int PER_SKILLPOINT_INCREASE_CLEAVE_AP = 3;
|
||||
public static final int PER_SKILLPOINT_INCREASE_EATER_HEALTH = 1;
|
||||
public static final int PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH = 1;
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class Player extends Actor {
|
||||
baseTraits.criticalSkill = 0;
|
||||
baseTraits.criticalMultiplier = 1;
|
||||
baseTraits.damagePotential.set(1, 1);
|
||||
baseTraits.blockChance = 0;
|
||||
baseTraits.blockChance = 9;
|
||||
baseTraits.damageResistance = 0;
|
||||
baseTraits.useItemCost = 5;
|
||||
baseTraits.reequipCost = 5;
|
||||
|
||||
@@ -274,6 +274,7 @@ public final class ResourceLoader {
|
||||
loader.prepareTileset(R.drawable.ui_icon_immunity, "ui_icon_immunity", sz1x1, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_dynamic_placeholders, "map_dynamic_placeholders", new Size(10, 2), sz1x1, mTileSize);
|
||||
|
||||
loader.prepareTileset(R.drawable.monsters_cyclops, "monsters_cyclops", sz1x1, sz2x3, mTileSize);
|
||||
loader.prepareTileset(R.drawable.monsters_demon1, "monsters_demon1", sz1x1, sz2x2, mTileSize);
|
||||
loader.prepareTileset(R.drawable.monsters_demon2, "monsters_demon2", sz1x1, sz2x2, mTileSize);
|
||||
loader.prepareTileset(R.drawable.monsters_eye4, "monsters_eye4", sz1x1, sz1x1, mTileSize);
|
||||
@@ -331,11 +332,13 @@ public final class ResourceLoader {
|
||||
loader.prepareTileset(R.drawable.map_52, "map_52", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_53, "map_53", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_54, "map_54", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_55, "map_55", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_56, "map_56", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_57, "map_57", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_6, "map_6", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_7, "map_7", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_8, "map_8", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.map_9, "map_9", sz8x8, sz1x1, mTileSize);
|
||||
|
||||
loader.prepareTileset(R.drawable.obj_0, "obj_0", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_1, "obj_1", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_10, "obj_10", sz8x8, sz1x1, mTileSize);
|
||||
@@ -343,6 +346,8 @@ public final class ResourceLoader {
|
||||
loader.prepareTileset(R.drawable.obj_12, "obj_12", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_13, "obj_13", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_14, "obj_14", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_15, "obj_15", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_16, "obj_16", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_2, "obj_2", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_3, "obj_3", sz8x8, sz1x1, mTileSize);
|
||||
loader.prepareTileset(R.drawable.obj_4, "obj_4", sz8x8, sz1x1, mTileSize);
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class Savegames {
|
||||
|
||||
private static void writeBackup(Context androidContext, byte[] savegame, String playerId) throws IOException {
|
||||
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
ensureDirExists(cheatDetectionFolder);
|
||||
File backupFile = new File(cheatDetectionFolder, playerId + "X");
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
|
||||
fileOutputStream.write(savegame);
|
||||
@@ -127,34 +127,33 @@ public final class Savegames {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean triedToCheat(Context androidContext, FileHeader fh) throws IOException {
|
||||
long savedVersionToCheck = 0;
|
||||
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, fh.playerId);
|
||||
if (cheatDetectionFile.exists()) {
|
||||
FileInputStream fileInputStream = new FileInputStream(cheatDetectionFile);
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
final CheatDetection cheatDetection = new CheatDetection(dataInputStream);
|
||||
savedVersionToCheck = cheatDetection.savedVersion;
|
||||
dataInputStream.close();
|
||||
fileInputStream.close();
|
||||
}
|
||||
private static boolean triedToCheat(Context androidContext, FileHeader fh) throws IOException {
|
||||
long savedVersionToCheck = 0;
|
||||
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
ensureDirExists(cheatDetectionFolder);
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, fh.playerId);
|
||||
if (cheatDetectionFile.exists()) {
|
||||
FileInputStream fileInputStream = new FileInputStream(cheatDetectionFile);
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
final CheatDetection cheatDetection = new CheatDetection(dataInputStream);
|
||||
savedVersionToCheck = cheatDetection.savedVersion;
|
||||
dataInputStream.close();
|
||||
fileInputStream.close();
|
||||
}
|
||||
|
||||
if (savedVersionToCheck == DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (androidContext.getFileStreamPath(fh.playerId).exists()) {
|
||||
FileInputStream fileInputStream = androidContext.openFileInput(fh.playerId);
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
final CheatDetection cheatDetection = new CheatDetection(dataInputStream);
|
||||
if (cheatDetection.savedVersion == DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED) {
|
||||
savedVersionToCheck = DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED;
|
||||
}
|
||||
else if (cheatDetection.savedVersion > savedVersionToCheck) {
|
||||
savedVersionToCheck = cheatDetection.savedVersion;
|
||||
}
|
||||
if (androidContext.getFileStreamPath(fh.playerId).exists()) {
|
||||
FileInputStream fileInputStream = androidContext.openFileInput(fh.playerId);
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
final CheatDetection cheatDetection = new CheatDetection(dataInputStream);
|
||||
if (cheatDetection.savedVersion == DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED) {
|
||||
savedVersionToCheck = DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED;
|
||||
} else if (cheatDetection.savedVersion > savedVersionToCheck) {
|
||||
savedVersionToCheck = cheatDetection.savedVersion;
|
||||
}
|
||||
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("Internal cheatcheck file savedVersion: " + cheatDetection.savedVersion);
|
||||
@@ -167,31 +166,48 @@ public final class Savegames {
|
||||
return (savedVersionToCheck == DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED || fh.savedVersion < savedVersionToCheck);
|
||||
}
|
||||
|
||||
private static FileOutputStream getOutputFile(Context androidContext, int slot) throws IOException {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileOutput(Constants.FILENAME_SAVEGAME_QUICKSAVE, Context.MODE_PRIVATE);
|
||||
} else {
|
||||
ensureSavegameDirectoryExists(androidContext);
|
||||
return new FileOutputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
private static void ensureSavegameDirectoryExists(Context context) {
|
||||
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
}
|
||||
private static FileInputStream getInputFile(Context androidContext, int slot) throws IOException {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileInput(Constants.FILENAME_SAVEGAME_QUICKSAVE);
|
||||
} else {
|
||||
return new FileInputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
private static FileOutputStream getOutputFile(Context androidContext, int slot) throws IOException {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileOutput(Constants.FILENAME_SAVEGAME_QUICKSAVE, Context.MODE_PRIVATE);
|
||||
} else {
|
||||
ensureSavegameDirectoryExists(androidContext);
|
||||
return new FileOutputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
|
||||
public static File getSlotFile(int slot, Context context) {
|
||||
File root = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return new File(root, Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + slot);
|
||||
}
|
||||
private static void ensureSavegameDirectoryExists(Context context) {
|
||||
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
ensureDirExists(dir);
|
||||
}
|
||||
|
||||
public static boolean ensureDirExists(File dir) {
|
||||
if (!dir.exists()) {
|
||||
boolean worked = dir.mkdir();
|
||||
return worked;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static FileInputStream getInputFile(Context androidContext, int slot) throws IOException {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileInput(Constants.FILENAME_SAVEGAME_QUICKSAVE);
|
||||
} else {
|
||||
return new FileInputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
|
||||
public static File getSlotFile(int slot, Context context) {
|
||||
File root = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return getSlotFile(slot, root);
|
||||
}
|
||||
|
||||
public static File getSlotFile(int slot, File directory) {
|
||||
return new File(directory, getSlotFileName(slot));
|
||||
}
|
||||
|
||||
public static String getSlotFileName(int slot) {
|
||||
return Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + slot;
|
||||
}
|
||||
|
||||
|
||||
public static void saveWorld(WorldContext world, OutputStream outStream, String displayInfo) throws IOException {
|
||||
@@ -207,10 +223,11 @@ public final class Savegames {
|
||||
dest.close();
|
||||
}
|
||||
|
||||
public static LoadSavegameResult loadWorld(Resources res, WorldContext world, ControllerContext controllers, InputStream inState, FileHeader fh) throws IOException {
|
||||
DataInputStream src = new DataInputStream(inState);
|
||||
final FileHeader header = new FileHeader(src, fh.skipIcon);
|
||||
if (header.fileversion > AndorsTrailApplication.CURRENT_VERSION) return LoadSavegameResult.savegameIsFromAFutureVersion;
|
||||
public static LoadSavegameResult loadWorld(Resources res, WorldContext world, ControllerContext controllers, InputStream inState, FileHeader fh) throws IOException {
|
||||
DataInputStream src = new DataInputStream(inState);
|
||||
final FileHeader header = new FileHeader(src, fh.skipIcon);
|
||||
if (header.fileversion > AndorsTrailApplication.CURRENT_VERSION)
|
||||
return LoadSavegameResult.savegameIsFromAFutureVersion;
|
||||
|
||||
world.maps.readFromParcel(src, world, controllers, header.fileversion);
|
||||
world.model = new ModelContainer(src, world, controllers, header.fileversion);
|
||||
@@ -249,15 +266,15 @@ public final class Savegames {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeCheatCheck(Context androidContext, long savedVersion, String playerId) throws IOException {
|
||||
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, playerId);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(cheatDetectionFile);
|
||||
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
|
||||
CheatDetection.writeToParcel(dataOutputStream, savedVersion);
|
||||
dataOutputStream.close();
|
||||
fileOutputStream.close();
|
||||
private static void writeCheatCheck(Context androidContext, long savedVersion, String playerId) throws IOException {
|
||||
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
ensureDirExists(cheatDetectionFolder);
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, playerId);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(cheatDetectionFile);
|
||||
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
|
||||
CheatDetection.writeToParcel(dataOutputStream, savedVersion);
|
||||
dataOutputStream.close();
|
||||
fileOutputStream.close();
|
||||
|
||||
fileOutputStream = androidContext.openFileOutput(playerId, Context.MODE_PRIVATE);
|
||||
dataOutputStream = new DataOutputStream(fileOutputStream);
|
||||
@@ -268,26 +285,26 @@ public final class Savegames {
|
||||
|
||||
private static final Pattern savegameFilenamePattern = Pattern.compile(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + "(\\d+)");
|
||||
|
||||
public static List<Integer> getUsedSavegameSlots(Context context) {
|
||||
try {
|
||||
final List<Integer> result = new ArrayList<Integer>();
|
||||
AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File f, String filename) {
|
||||
Matcher m = savegameFilenamePattern.matcher(filename);
|
||||
if (m != null && m.matches()) {
|
||||
result.add(Integer.parseInt(m.group(1)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static List<Integer> getUsedSavegameSlots(Context context) {
|
||||
try {
|
||||
final List<Integer> result = new ArrayList<Integer>();
|
||||
AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File f, String filename) {
|
||||
Matcher m = savegameFilenamePattern.matcher(filename);
|
||||
if (m != null && m.matches()) {
|
||||
result.add(Integer.parseInt(m.group(1)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CheatDetection {
|
||||
public final int fileversion;
|
||||
@@ -307,17 +324,16 @@ public final class Savegames {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final class FileHeader {
|
||||
public final int fileversion;
|
||||
public final String playerName;
|
||||
public final String displayInfo;
|
||||
public final int iconID;
|
||||
public boolean skipIcon = false;
|
||||
public final boolean isDead;
|
||||
public final boolean hasUnlimitedSaves;
|
||||
public final String playerId;
|
||||
public final long savedVersion;
|
||||
public static final class FileHeader {
|
||||
public final int fileversion;
|
||||
public final String playerName;
|
||||
public final String displayInfo;
|
||||
public final int iconID;
|
||||
public boolean skipIcon = false;
|
||||
public final boolean isDead;
|
||||
public final boolean hasUnlimitedSaves;
|
||||
public final String playerId;
|
||||
public final long savedVersion;
|
||||
|
||||
public String describe() {
|
||||
return (fileversion == AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION ? "(D) " : "") + playerName + ", " + displayInfo;
|
||||
@@ -326,17 +342,18 @@ public final class Savegames {
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public FileHeader(DataInputStream src, boolean skipIcon) throws IOException {
|
||||
int fileversion = src.readInt();
|
||||
if (fileversion == 11) fileversion = 5; // Fileversion 5 had no version identifier, but the first byte was 11.
|
||||
this.fileversion = fileversion;
|
||||
if (fileversion >= 14) { // Before fileversion 14 (0.6.7), we had no file header.
|
||||
this.playerName = src.readUTF();
|
||||
this.displayInfo = src.readUTF();
|
||||
} else {
|
||||
this.playerName = null;
|
||||
this.displayInfo = null;
|
||||
}
|
||||
public FileHeader(DataInputStream src, boolean skipIcon) throws IOException {
|
||||
int fileversion = src.readInt();
|
||||
if (fileversion == 11)
|
||||
fileversion = 5; // Fileversion 5 had no version identifier, but the first byte was 11.
|
||||
this.fileversion = fileversion;
|
||||
if (fileversion >= 14) { // Before fileversion 14 (0.6.7), we had no file header.
|
||||
this.playerName = src.readUTF();
|
||||
this.displayInfo = src.readUTF();
|
||||
} else {
|
||||
this.playerName = null;
|
||||
this.displayInfo = null;
|
||||
}
|
||||
|
||||
if (fileversion >= 43) {
|
||||
int id = src.readInt();
|
||||
|
||||
@@ -1,42 +1,58 @@
|
||||
package com.gpl.rpg.AndorsTrail.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.util.BackgroundWorker.BackgroundWorkerCallback;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public final class AndroidStorage {
|
||||
public static File getStorageDirectory(Context context, String name) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
return context.getExternalFilesDir(name);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
return new File(root, name);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldMigrateToInternalStorage(Context context) {
|
||||
boolean ret = false;
|
||||
File externalSaveGameDirectory = new File(Environment.getExternalStorageDirectory(), Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
File externalSaveGameDirectory = new File(Environment.getExternalStorageDirectory(),
|
||||
Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
File internalSaveGameDirectory = getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
|
||||
if (externalSaveGameDirectory.exists()
|
||||
&& externalSaveGameDirectory.isDirectory()
|
||||
&& externalSaveGameDirectory.listFiles().length > 0
|
||||
&& (
|
||||
!internalSaveGameDirectory.exists()
|
||||
|| internalSaveGameDirectory.isDirectory() && internalSaveGameDirectory.listFiles().length < 2)
|
||||
) {
|
||||
&& externalSaveGameDirectory.isDirectory()
|
||||
&& externalSaveGameDirectory.listFiles().length > 0
|
||||
&& (!internalSaveGameDirectory.exists()
|
||||
|| internalSaveGameDirectory.isDirectory()
|
||||
&& internalSaveGameDirectory.listFiles().length < 2)) {
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
@@ -45,11 +61,11 @@ public final class AndroidStorage {
|
||||
public static boolean migrateToInternalStorage(Context context) {
|
||||
try {
|
||||
copy(new File(Environment.getExternalStorageDirectory(), Constants.CHEAT_DETECTION_FOLDER),
|
||||
getStorageDirectory(context, Constants.CHEAT_DETECTION_FOLDER));
|
||||
getStorageDirectory(context, Constants.CHEAT_DETECTION_FOLDER));
|
||||
copy(new File(Environment.getExternalStorageDirectory(), Constants.FILENAME_SAVEGAME_DIRECTORY),
|
||||
getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY));
|
||||
getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY));
|
||||
} catch (IOException e) {
|
||||
L.log("Error migrating data: " + e.toString());
|
||||
L.log("Error migrating data: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -76,33 +92,381 @@ public final class AndroidStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFile(File source, File target) throws IOException {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
in = new FileInputStream(source);
|
||||
out = new FileOutputStream(target);
|
||||
byte[] buf = new byte[1024];
|
||||
int length;
|
||||
while ((length = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, length);
|
||||
public static void copyFile(File source, File target) throws IOException {
|
||||
try (InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(target)) {
|
||||
copyStream(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buf = new byte[1024];
|
||||
int length;
|
||||
while ((length = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.P)
|
||||
public static void createZipDocumentFileFromFilesAsync(File[] files,
|
||||
Context context,
|
||||
DocumentFile targetDirectory,
|
||||
String fileName,
|
||||
String loadingMessage,
|
||||
Consumer<Boolean> callback) {
|
||||
|
||||
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
|
||||
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
|
||||
progressDialog.setOnCancelListener(dialog -> worker.cancel());
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Handler handler = Handler.createAsync(Looper.getMainLooper());
|
||||
|
||||
|
||||
worker.setTask(workerCallback -> {
|
||||
try {
|
||||
workerCallback.onInitialize();
|
||||
|
||||
//region create zip file
|
||||
File zip = File.createTempFile("temp_worldmap", ".zip");
|
||||
try (OutputStream out = new FileOutputStream(zip)) {
|
||||
ZipOutputStream zipOut = new ZipOutputStream(out);
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = files[i];
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
workerCallback.onProgress((float) i / files.length);
|
||||
zipOut.putNextEntry(new ZipEntry(file.getName()));
|
||||
copyStream(fis, zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
}
|
||||
zipOut.close();
|
||||
}
|
||||
//endregion
|
||||
|
||||
DocumentFile worldmapZip = DocumentFile.fromFile(zip);
|
||||
DocumentFile worldmapTarget = targetDirectory.createFile("application/zip", fileName);
|
||||
if (worldmapTarget != null && worldmapTarget.exists()) {
|
||||
AndroidStorage.copyDocumentFile(worldmapZip, resolver, worldmapTarget);
|
||||
workerCallback.onComplete(true);
|
||||
} else {
|
||||
throw new FileNotFoundException("Could not create File");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
if (worker.isCancelled()) {
|
||||
workerCallback.onFailure(new CancellationException("Cancelled"));
|
||||
} else {
|
||||
workerCallback.onFailure(e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
workerCallback.onFailure(e);
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
});
|
||||
|
||||
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
|
||||
worker.run();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void unzipToDirectory(File zipFile,
|
||||
File targetDirectory,
|
||||
boolean overwriteNotSkip) throws IOException {
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
|
||||
unzipStreamToDirectory(targetDirectory, overwriteNotSkip, zis);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.P)
|
||||
public static void unzipDocumentFileToDirectoryAsync(DocumentFile zipFile,
|
||||
Context context,
|
||||
File targetDirectory,
|
||||
boolean overwriteNotSkip,
|
||||
String loadingMessage,
|
||||
Consumer<Boolean> callback) {
|
||||
|
||||
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
|
||||
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
|
||||
progressDialog.setOnCancelListener(dialog -> worker.cancel());
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Handler handler = Handler.createAsync(Looper.getMainLooper());
|
||||
|
||||
worker.setTask(workerCallback -> {
|
||||
try {
|
||||
workerCallback.onInitialize();
|
||||
workerCallback.onProgress(-1);//set dummy progress since we don't know the
|
||||
// progress of the unzip
|
||||
unzipDocumentFileToDirectory(zipFile, resolver, targetDirectory, overwriteNotSkip);
|
||||
workerCallback.onComplete(true);
|
||||
} catch (IOException e) {
|
||||
workerCallback.onFailure(e);
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
});
|
||||
|
||||
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
|
||||
worker.run();
|
||||
|
||||
}
|
||||
|
||||
public static void unzipDocumentFileToDirectory(DocumentFile zipFile,
|
||||
ContentResolver resolver,
|
||||
File targetDirectory,
|
||||
boolean overwriteNotSkip) throws IOException {
|
||||
try (ZipInputStream zis = new ZipInputStream(resolver.openInputStream(zipFile.getUri()))) {
|
||||
unzipStreamToDirectory(targetDirectory, overwriteNotSkip, zis);
|
||||
}
|
||||
}
|
||||
|
||||
private static void unzipStreamToDirectory(File targetDirectory,
|
||||
boolean overwriteNotSkip,
|
||||
ZipInputStream zis) throws IOException {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
File file = new File(targetDirectory, entry.getName());
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
file.mkdirs();
|
||||
} else {
|
||||
file.getParentFile().mkdirs();
|
||||
if (file.exists() && !overwriteNotSkip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||
copyStream(zis, fos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyDocumentFileToNewOrExistingFile(DocumentFile sourceFile,
|
||||
ContentResolver resolver,
|
||||
DocumentFile targetFolder) throws IOException {
|
||||
copyDocumentFileToNewOrExistingFile(sourceFile,
|
||||
resolver,
|
||||
targetFolder,
|
||||
Constants.NO_FILE_EXTENSION_MIME_TYPE);
|
||||
}
|
||||
|
||||
|
||||
public static void copyDocumentFileToNewOrExistingFile(DocumentFile sourceFile,
|
||||
ContentResolver resolver,
|
||||
DocumentFile targetFolder,
|
||||
String mimeType) throws IOException {
|
||||
String fileName = sourceFile.getName();
|
||||
DocumentFile file = targetFolder.findFile(fileName);
|
||||
if (file == null) {
|
||||
file = targetFolder.createFile(mimeType, fileName);
|
||||
}
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AndroidStorage.copyDocumentFile(sourceFile, resolver, file);
|
||||
}
|
||||
|
||||
public static void copyDocumentFile(DocumentFile sourceFile,
|
||||
ContentResolver resolver,
|
||||
DocumentFile targetFile) throws IOException {
|
||||
try (OutputStream outputStream = resolver.openOutputStream(targetFile.getUri());
|
||||
InputStream inputStream = resolver.openInputStream(sourceFile.getUri())) {
|
||||
copyStream(inputStream, outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrlForFile(Context context, File worldmap) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
Uri uri = FileProvider.getUriForFile(context, "com.gpl.rpg.AndorsTrail.fileprovider", worldmap);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
String applicationId = context.getPackageName();
|
||||
Uri uri = FileProvider.getUriForFile(context, applicationId + ".fileprovider", worldmap);
|
||||
return uri.toString();
|
||||
} else {
|
||||
return "file://" + worldmap.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public static Intent getNewOpenDirectoryIntent() {
|
||||
return new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public static Intent getNewSelectMultipleSavegameFilesIntent() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
intent.setType(Constants.SAVEGAME_FILE_MIME_TYPE);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public static Intent getNewSelectZipIntent() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("application/zip");
|
||||
return intent;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.P)
|
||||
public static void copyDocumentFilesFromToAsync(DocumentFile[] sources,
|
||||
Context context,
|
||||
DocumentFile[] targets,
|
||||
String loadingMessage,
|
||||
Consumer<Boolean> callback) {
|
||||
if (sources.length != targets.length) {
|
||||
throw new IllegalArgumentException("Both arrays, target & source have to have the same size");
|
||||
}
|
||||
|
||||
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
|
||||
|
||||
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
|
||||
progressDialog.setOnCancelListener(dialog -> worker.cancel());
|
||||
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Handler handler = Handler.createAsync(Looper.getMainLooper());
|
||||
|
||||
worker.setTask(workerCallback -> {
|
||||
try {
|
||||
workerCallback.onInitialize();
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
if (worker.isCancelled()) {
|
||||
workerCallback.onFailure(new CancellationException("Cancelled"));
|
||||
return;
|
||||
}
|
||||
DocumentFile source = sources[i];
|
||||
DocumentFile target = targets[i];
|
||||
|
||||
if (source == null || target == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
copyDocumentFile(source, resolver, target);
|
||||
float progress = i / (float) sources.length;
|
||||
workerCallback.onProgress(progress);
|
||||
}
|
||||
workerCallback.onComplete(true);
|
||||
} catch (NullPointerException e) {
|
||||
if (worker.isCancelled()) {
|
||||
workerCallback.onFailure(new CancellationException("Cancelled"));
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
workerCallback.onFailure(e);
|
||||
}
|
||||
});
|
||||
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
|
||||
worker.run();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.P)
|
||||
public static void copyDocumentFilesToDirAsync(DocumentFile[] files,
|
||||
Context context,
|
||||
DocumentFile targetDirectory,
|
||||
String loadingMessage,
|
||||
Consumer<Boolean> callback) {
|
||||
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
|
||||
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
|
||||
progressDialog.setOnCancelListener(dialog -> worker.cancel());
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Handler handler = Handler.createAsync(Looper.getMainLooper());
|
||||
|
||||
worker.setTask(workerCallback -> {
|
||||
try {
|
||||
workerCallback.onInitialize();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (worker.isCancelled()) {
|
||||
workerCallback.onFailure(new CancellationException("Cancelled"));
|
||||
return;
|
||||
}
|
||||
DocumentFile file = files[i];
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
copyDocumentFileToNewOrExistingFile(file, resolver, targetDirectory);
|
||||
float progress = i / (float) files.length;
|
||||
workerCallback.onProgress(progress);
|
||||
}
|
||||
workerCallback.onComplete(true);
|
||||
} catch (NullPointerException e) {
|
||||
if (worker.isCancelled()) {
|
||||
workerCallback.onFailure(new CancellationException("Cancelled"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
workerCallback.onFailure(e);
|
||||
}
|
||||
});
|
||||
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
|
||||
worker.run();
|
||||
}
|
||||
|
||||
private static BackgroundWorkerCallback<Boolean> getDefaultBackgroundWorkerCallback(Handler handler,
|
||||
CustomDialogFactory.CustomDialog progressDialog,
|
||||
Consumer<Boolean> callback) {
|
||||
return new BackgroundWorkerCallback<Boolean>() {
|
||||
private int progress = -1;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
handler.post(() -> {
|
||||
CustomDialogFactory.show(progressDialog);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(float progress) {
|
||||
handler.post(() -> {
|
||||
int intProgress = (int) (progress * 100);
|
||||
if (this.progress == intProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.progress = intProgress;
|
||||
|
||||
if (progress == -1) {
|
||||
CustomDialogFactory.setDesc(progressDialog, null);
|
||||
return;
|
||||
}
|
||||
|
||||
CustomDialogFactory.setDesc(progressDialog, intProgress + "%");
|
||||
});
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
this.onComplete(false);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public void onComplete(Boolean result) {
|
||||
handler.post(() -> {
|
||||
progressDialog.dismiss();
|
||||
callback.accept(result);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static CustomDialogFactory.CustomDialog getLoadingDialog(Context context) {
|
||||
return getLoadingDialog(context, null);
|
||||
}
|
||||
|
||||
private static CustomDialogFactory.CustomDialog getLoadingDialog(Context context, String message) {
|
||||
if (message == null) {
|
||||
message = context.getResources().getString(R.string.dialog_loading_message);
|
||||
}
|
||||
|
||||
CustomDialogFactory.CustomDialog dialog = CustomDialogFactory.createDialog(context,
|
||||
message,
|
||||
context.getResources()
|
||||
.getDrawable(R.drawable.loading_anim),
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
false);
|
||||
CustomDialogFactory.addCancelButton(dialog, android.R.string.no);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.gpl.rpg.AndorsTrail.util;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public final class BackgroundWorker<T> {
|
||||
boolean cancelled = false;
|
||||
worker<T> task;
|
||||
BackgroundWorkerCallback<T> callback;
|
||||
|
||||
public void setTask(worker<T> task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public void setCallback(BackgroundWorkerCallback<T> callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
interface worker<T> {
|
||||
void doWork(BackgroundWorkerCallback<T> callback);
|
||||
}
|
||||
|
||||
interface BackgroundWorkerCallback<T> {
|
||||
void onInitialize();
|
||||
|
||||
default void onProgress(float progress) {
|
||||
}
|
||||
|
||||
void onFailure(Exception e);
|
||||
|
||||
void onComplete(T result);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Executors.newSingleThreadExecutor().execute(() -> {
|
||||
task.doWork(callback);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.gpl.rpg.AndorsTrail.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public final class HashMapHelper {
|
||||
public static <K,V> V getOrDefault(HashMap<K,V> map, K key, V defaultValue) {
|
||||
V v = map.get(key);
|
||||
return v == null ? defaultValue : v;
|
||||
}
|
||||
public static <K> Integer sumIntegerValues(HashMap<K,Integer> map) {
|
||||
int sum = 0;
|
||||
for (Integer v : map.values()) sum += v;
|
||||
return sum;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -22,25 +22,33 @@ import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
|
||||
public class CustomDialogFactory {
|
||||
|
||||
public static class CustomDialog extends Dialog {
|
||||
|
||||
public static class CustomDialog extends android.app.Dialog {
|
||||
public CustomDialog(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
boolean verticalButtons = false;
|
||||
}
|
||||
|
||||
public static CustomDialog createDialog(final Context context, String title, Drawable icon, String desc, View content, boolean hasButtons) {
|
||||
|
||||
public static CustomDialog createDialog(final Context context, String title, Drawable icon,
|
||||
String desc, View content, boolean hasButtons, boolean canDismiss) {
|
||||
return createDialog(context, title, icon, desc, content, hasButtons, canDismiss, false);
|
||||
}
|
||||
|
||||
public static CustomDialog createDialog(final Context context, String title, Drawable icon,
|
||||
String desc, View content, boolean hasButtons) {
|
||||
return createDialog(context, title, icon, desc, content, hasButtons, true);
|
||||
}
|
||||
|
||||
public static CustomDialog createDialog(final Context context, String title, Drawable icon, String desc, View content, boolean hasButtons, final boolean canDismiss) {
|
||||
|
||||
public static CustomDialog createDialog(final Context context, String title, Drawable icon,
|
||||
String desc, View content, boolean hasButtons,
|
||||
final boolean canDismiss, final boolean verticalButtons) {
|
||||
final CustomDialog dialog = new CustomDialog(new ContextThemeWrapper(context, ThemeHelper.getDialogTheme())) {
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
Rect r = new Rect();
|
||||
this.getWindow().getDecorView().findViewById(R.id.dialog_hitrect).getHitRect(r);
|
||||
|
||||
|
||||
if (r.contains((int)event.getX(), (int)event.getY())) {
|
||||
return super.onTouchEvent(event);
|
||||
} else {
|
||||
@@ -51,7 +59,7 @@ public class CustomDialogFactory {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
@@ -63,7 +71,8 @@ public class CustomDialogFactory {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dialog.verticalButtons = verticalButtons;
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(R.layout.custom_dialog_title_icon);
|
||||
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
@@ -72,23 +81,37 @@ public class CustomDialogFactory {
|
||||
} else {
|
||||
dialog.getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
|
||||
|
||||
setTitle(dialog, title, icon);
|
||||
|
||||
|
||||
setDesc(dialog, desc);
|
||||
|
||||
|
||||
setContent(dialog, content);
|
||||
|
||||
ViewGroup buttonsHolder = (ViewGroup) dialog.findViewById(R.id.dialog_button_container);
|
||||
|
||||
ViewGroup buttonsHolder = getButtonContainer(dialog);
|
||||
ViewGroup unusedButtonsHolder = getUnusedButtonContainer(dialog);
|
||||
|
||||
unusedButtonsHolder.setVisibility(View.GONE);
|
||||
if (hasButtons) {
|
||||
buttonsHolder.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
buttonsHolder.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
public static CustomDialog createErrorDialog(final Context context, String title, String description) {
|
||||
final CustomDialog d = createDialog(context,
|
||||
title,
|
||||
context.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
|
||||
description,
|
||||
null,
|
||||
true);
|
||||
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
|
||||
return d;
|
||||
}
|
||||
|
||||
public static CustomDialog setTitle(final CustomDialog dialog, String title, Drawable icon) {
|
||||
TextView titleView = (TextView) dialog.findViewById(R.id.dialog_title);
|
||||
if (title != null || icon != null) {
|
||||
@@ -100,7 +123,7 @@ public class CustomDialogFactory {
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
public static CustomDialog setDesc(final CustomDialog dialog, String desc) {
|
||||
TextView descView = (TextView) dialog.findViewById(R.id.dialog_description);
|
||||
ViewGroup descHolder = (ViewGroup) dialog.findViewById(R.id.dialog_description_container);
|
||||
@@ -113,7 +136,7 @@ public class CustomDialogFactory {
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
public static CustomDialog setContent(final CustomDialog dialog, View content) {
|
||||
ViewGroup contentHolder = (ViewGroup) dialog.findViewById(R.id.dialog_content_container);
|
||||
if (content != null) {
|
||||
@@ -124,54 +147,101 @@ public class CustomDialogFactory {
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog addButton(final Dialog dialog, int textId, final OnClickListener listener) {
|
||||
|
||||
Button template = (Button) dialog.findViewById(R.id.dialog_template_button);
|
||||
|
||||
public static CustomDialog addButton(final CustomDialog dialog, String text, final OnClickListener listener) {
|
||||
return addButton(dialog, -1, text, listener);
|
||||
}
|
||||
public static CustomDialog addButton(final CustomDialog dialog, int textId, final OnClickListener listener) {
|
||||
return addButton(dialog, textId, null, listener);
|
||||
}
|
||||
public static CustomDialog addButton(final CustomDialog dialog, int textId, String text, final OnClickListener listener) {
|
||||
Button template = getButtonTemplate(dialog);
|
||||
LayoutParams params = template.getLayoutParams();
|
||||
ViewGroup buttonsHolder = (ViewGroup) dialog.findViewById(R.id.dialog_button_container);
|
||||
|
||||
ViewGroup buttonsHolder = getButtonContainer(dialog);
|
||||
|
||||
Button b = new Button(dialog.getContext());
|
||||
b.setLayoutParams(params);
|
||||
//Old android versions need this "reminder"
|
||||
b.setBackgroundDrawable(ThemeHelper.getThemeDrawable(dialog.getContext(), R.attr.ui_theme_textbutton_drawable));
|
||||
b.setTextColor(ThemeHelper.getThemeColor(dialog.getContext(), R.attr.ui_theme_dialogue_light_color));
|
||||
|
||||
b.setText(textId);
|
||||
|
||||
if(textId != -1) {
|
||||
b.setText(textId);
|
||||
} else {
|
||||
b.setText(text);
|
||||
}
|
||||
|
||||
b.setOnClickListener(new OnClickListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onClick(v);
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
buttonsHolder.addView(b, params);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog addDismissButton(final Dialog dialog, int textId) {
|
||||
|
||||
public static CustomDialog addDismissButton(final CustomDialog dialog, int textId) {
|
||||
return CustomDialogFactory.addButton(dialog, textId, new OnClickListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Dialog setDismissListener(Dialog dialog, OnDismissListener listener) {
|
||||
public static CustomDialog addCancelButton(final CustomDialog dialog, int textId) {
|
||||
return CustomDialogFactory.addButton(dialog, textId, new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static CustomDialog setDismissListener(CustomDialog dialog, OnDismissListener listener) {
|
||||
dialog.setOnDismissListener(listener);
|
||||
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void show(Dialog dialog) {
|
||||
|
||||
|
||||
public static CustomDialog setCancelListener(CustomDialog dialog, OnCancelListener listener) {
|
||||
dialog.setOnCancelListener(listener);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void show(CustomDialog dialog) {
|
||||
|
||||
dialog.findViewById(R.id.dialog_template_button).setVisibility(View.GONE);
|
||||
dialog.findViewById(R.id.dialog_template_button_vertical).setVisibility(View.GONE);
|
||||
dialog.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static ViewGroup getUnusedButtonContainer(CustomDialog dialog) {
|
||||
if (dialog.verticalButtons)
|
||||
return (ViewGroup) dialog.findViewById(R.id.dialog_button_container);
|
||||
else
|
||||
return (ViewGroup) dialog.findViewById(R.id.dialog_button_container_vertical);
|
||||
}
|
||||
|
||||
private static ViewGroup getButtonContainer(CustomDialog dialog) {
|
||||
if (dialog.verticalButtons)
|
||||
return (ViewGroup) dialog.findViewById(R.id.dialog_button_container_vertical);
|
||||
else
|
||||
return (ViewGroup) dialog.findViewById(R.id.dialog_button_container);
|
||||
}
|
||||
|
||||
private static Button getButtonTemplate(CustomDialog dialog) {
|
||||
if (dialog.verticalButtons)
|
||||
return (Button) dialog.findViewById(R.id.dialog_template_button_vertical);
|
||||
else
|
||||
return (Button) dialog.findViewById(R.id.dialog_template_button);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,13 +9,15 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
|
||||
|
||||
/**
|
||||
* Simply instantiate this class, implement abstract methods in an anonymous type, and tada, your Button is a Spinner!
|
||||
*/
|
||||
public abstract class SpinnerEmulator {
|
||||
|
||||
private Button spinnerButton;
|
||||
private Dialog spinnerDialog = null;
|
||||
private CustomDialog spinnerDialog = null;
|
||||
private ListView choicesList;
|
||||
private Context context;
|
||||
|
||||
|
||||
BIN
AndorsTrail/assets/translation/da.mo
Normal file
BIN
AndorsTrail/assets/translation/lzh.mo
Normal file
BIN
AndorsTrail/assets/translation/sr.mo
Normal file
BIN
AndorsTrail/assets/translation/vi.mo
Normal file
@@ -1,7 +0,0 @@
|
||||
## This file must *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
#
|
||||
#Sun Sep 25 12:50:59 CEST 2022
|
||||
sdk.dir=C\:\\Users\\chris\\AppData\\Local\\Android\\Sdk
|
||||
@@ -21,6 +21,46 @@ Visit our forums on www.andorstrail.com for help, hints, tips and general discus
|
||||
|
||||
Changelog:
|
||||
|
||||
v0.8.5
|
||||
New quest 'Ratdom' with 139 new maps and 2 sub quests
|
||||
The loss of XP in case of death is now 20% instead of 30%
|
||||
Having raw meat cooked
|
||||
Translation updates and many minor bug fixes and enhancements
|
||||
|
||||
v0.8.4.1
|
||||
Export/Import: The worldmap, which consists of many small png files, is handled now as a zip file.
|
||||
Translation updates and many minor bug fixes and map enhancements
|
||||
|
||||
v0.8.3
|
||||
New quest "The Dead are Walking" with 38 new maps
|
||||
Export/Import function for savegames
|
||||
|
||||
v0.8.2
|
||||
Fix of a lost traveler in certain conditions
|
||||
Support of older mobiles again
|
||||
|
||||
v0.8.1
|
||||
New city Sullengard
|
||||
71 new maps and 6 new quests
|
||||
Monster kill count
|
||||
Controller support
|
||||
Translations updated
|
||||
Engine changes to support actual Android Studio
|
||||
|
||||
v0.7.17
|
||||
Fix of unloadable savegames in certain conditions
|
||||
|
||||
v0.7.16
|
||||
New quest 'Delivery'
|
||||
Fix of Killed-by-Kamelio bug, postman bug and typos
|
||||
Translations updated (Chinese 99%)
|
||||
|
||||
v0.7.15
|
||||
Fix of a notification crash bug
|
||||
Fix of missing scout and of a non disappearing Ortholion and Ehrenfest in certain conditions
|
||||
Various small changes and bug fixes
|
||||
Translations updated
|
||||
|
||||
v0.7.14
|
||||
2 new quests:
|
||||
"Climbing up is forbidden"
|
||||
|
||||
@@ -1,35 +1,231 @@
|
||||
I put both (release notes + forum announcement) into this source, so it will be easier to maintain them parallel:
|
||||
|
||||
|
||||
APK 72 (0.8.6.1) Another Ratdom bug fix
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* Fixed: Not able to complete quest "More rats!"
|
||||
* Translation updates
|
||||
|
||||
|
||||
Forum announcement //2023-05-21
|
||||
==================
|
||||
Hello adventurers,
|
||||
|
||||
we had to create another bug fix version (v0.8.6.1)
|
||||
|
||||
[list]In certain cases the quest "More rats!" could not be completed.
|
||||
[/list]
|
||||
|
||||
|
||||
Here is is the link on our server: [url]https://andorstrail.com/static/AndorsTrail_v0.8.7.apk[/url]
|
||||
Google Play, F-Droid and Itch will follow soon.
|
||||
|
||||
|
||||
|
||||
APK 71 (0.8.6) Ratdom bug fixes
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* Missing chest content fixed
|
||||
* Translation updates and other minor bug fixes
|
||||
|
||||
|
||||
Forum announcement //2023-05-14
|
||||
==================
|
||||
Hello adventurers,
|
||||
|
||||
we have another new version for you (v0.8.6)
|
||||
|
||||
[list]The chests near Flora's fountain are filled now, the crash is fixed.
|
||||
[/list]
|
||||
|
||||
[list]Clevred now offers his help with the four wells with endless patience.[/list]
|
||||
|
||||
[list]And some fixes of minor bugs and updates of the translations (Chinese is 100% again 8)).[/list]
|
||||
|
||||
|
||||
Here is is the link on our server: [url]https://andorstrail.com/static/AndorsTrail_v0.8.6.apk[/url]
|
||||
Google Play, F-Droid and Itch will follow soon.
|
||||
|
||||
|
||||
|
||||
APK 70 (0.8.5) Ratdom
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* The new Ratdom area with 3 quests and 139 new maps
|
||||
* Translation updates and many minor bug fixes and enhancements
|
||||
|
||||
|
||||
Forum announcement //2023-01-29
|
||||
==================
|
||||
Hello adventurers,
|
||||
|
||||
we have another new version for you (v0.8.5 Ratdom)
|
||||
|
||||
[list]We have a huge new area with 139 new maps and 3 new quests:
|
||||
A big quest in a rat world and two other small quests you will find on your way.
|
||||
|
||||
This section is more for high-level players: the quests Lodar, Charwood, Colonel Lutarc and the starter quests Prohibited Substance and Rat Infestation are mandatory.
|
||||
Do you have these and also 9000 gold pieces with you, then you can dive into the new adventure.
|
||||
Just go home and take a nap - it's not really going to be refreshing...
|
||||
|
||||
You will find many new maps arranged as a maze. This area looks and feels different than the rest of Andor's path. It will also be a challenge for the high-level players who just run through new areas with no effort.
|
||||
(The scope took a long time to create, so don't expect to finish it in a few hours.)
|
||||
|
||||
A rat named Clevred will accompany you even though you don't see it. It's small enough to hide in your pocket or carry around. But he will talk to you, sometimes randomly, sometimes giving advice.
|
||||
[/list]
|
||||
|
||||
[list]The loss of XP in case of death is now 20% instead of 30%[/list]
|
||||
|
||||
[list]It is now possible to have your raw meat cooked by Gison's son Gael and in Remgard.[/list]
|
||||
|
||||
[list]We added the new Polished ring of the Protector in Remgard, and flipped the places of sale of the Guardian and Protector rings.[/list]
|
||||
|
||||
[list]Several other adjustments, not worth to list them all here[/list]
|
||||
|
||||
[list]And as always, we've fixed some minor bugs and updated the translations.[/list]
|
||||
|
||||
|
||||
Here is is the link on our server: [url]https://andorstrail.com/static/AndorsTrail_v0.8.5.apk[/url]
|
||||
Google Play, F-Droid and Itch will follow soon.
|
||||
|
||||
Have fun!
|
||||
|
||||
|
||||
PS
|
||||
I might be too harsh, so we added an early exit to the quest so you can come out and complete the quest even if you didn't actually reach the end.
|
||||
|
||||
|
||||
|
||||
|
||||
APK 69 (0.8.4.1) //Mostly harmless
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* Export/Import: The worldmap, which consists of many small png files, is handled now as a zip file.
|
||||
* Translation updates and many minor bug fixes and map enhancements
|
||||
|
||||
|
||||
Forum announcement //2023-01-29
|
||||
==================
|
||||
Hello fellow adventurers,
|
||||
|
||||
Here is the actual release v0.8.4.1 with bugfixes, translations and little enhancements:
|
||||
|
||||
[list]The export/import is enhanced: The worldmap, which consists of many small png files, is handled now as a zip file. This is more convenient and much quicker.[/list]
|
||||
|
||||
[list]Fixes of several little bugs and typos[/list]
|
||||
[list]Especially the Pangitain break should be fixed now[/list]
|
||||
[list]Many map fixes and changes, most of them in the new area towards Sullengard and the haunted forest[/list]
|
||||
|
||||
[list]And as always we actualized the translations[/list]
|
||||
|
||||
Here is is the link on our server: [url]https://andorstrail.com/static/AndorsTrail_v0.8.4.1.apk[/url]
|
||||
Google Play, F-Droid and Itch will follow soon.
|
||||
|
||||
Have fun!
|
||||
|
||||
|
||||
|
||||
|
||||
APK 68 (0.8.4) //Mostly harmless (unneeded files - immediatly replaced by 69)
|
||||
|
||||
|
||||
APK 67 (0.8.3) //Haunted Forest 2022-11-04
|
||||
|
||||
Release notes (Google/Itch)
|
||||
=============
|
||||
Content
|
||||
* 38 new maps
|
||||
* A new quest "The Dead are Walking"
|
||||
|
||||
Engine
|
||||
* Export / Import function for savegames (Android 11+ devices only)
|
||||
* Beta versions come now as a different APK
|
||||
|
||||
|
||||
|
||||
Forum announcement
|
||||
==================
|
||||
Hello fellow adventurers,
|
||||
|
||||
we have another new release for you 8-)
|
||||
It would have been nice if we had been some days faster. Then it would have come out in time for Halloween.
|
||||
But we won't delay the release for an extra year because of that...
|
||||
|
||||
[list]We have 38 new maps and 1 new quest "The Dead are Walking" created by Antison - thanks for all the work 8-)
|
||||
You start at the church in Vilegard. But beware - similar to Sullengard, this release is no walk in the park![/list]
|
||||
|
||||
[list]In addition, the game now has the long-awaited export / import function, so that savegames can now be conveniently copied to another device.
|
||||
This feature was brought to us by OMGeeky, which we're taking as an opportunity to welcome him as the newest member of the development team!
|
||||
|
||||
There are now 3 more choices in the load menu:
|
||||
[list]Export: Writes all savegames and the world map to any directory.[/list]
|
||||
[list]Import: Loads individually selected saved games. If the slot is already occupied, you can choose between overwriting, canceling or saving in a new slot.[/list]
|
||||
[list]Import world map: Loads missing parts of the world maps, e.g. if saves were copied from another device.[/list]
|
||||
(This export/import is only available for Android 11+, older devices can be copied as usual.)
|
||||
[/list]
|
||||
|
||||
[list]This Beta version is released with a different APK name, so you won't have to deinstall the product version any more. You can install and play both APK's independently.[/list]
|
||||
[list]And as always we fixed some minor bugs and actualized the translations.[/list]
|
||||
|
||||
|
||||
Here is is the link: [url]https://andorstrail.com/static/AndorsTrail_v0.8.3_beta.apk[/url]
|
||||
|
||||
Have fun trying!
|
||||
If you encounter bugs or strange things, please post them. This will help us to fix it before publishing the release.
|
||||
|
||||
|
||||
APK 66 (0.8.2) //Sullengard Bugfix
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* Fix of a lost traveler in certain conditions
|
||||
* support of older mobiles again
|
||||
|
||||
|
||||
Forum announcement //2022-10-09
|
||||
==================
|
||||
Hello fellow adventurers,
|
||||
|
||||
we have a new release for you 8-)
|
||||
|
||||
[list]Some of you had encountered a serious bug so that the quest "Recovering stolen property" could not be completed.
|
||||
(If you miss a certain traveler, you should talk to Sullengard's innkeeper in this new release)[/list]
|
||||
|
||||
[list]Then we increased XP for quests a bit and ensured one diamond ring.[/list]
|
||||
|
||||
[list]And we fixed some maps, added a long missed little map near Fallhaven, and actualized the translations.[/list]
|
||||
|
||||
[list]Also we tried to support older mobiles again.[/list]
|
||||
|
||||
[list]And last but not least: hopefully F-Droid supports our sources again.[/list]
|
||||
|
||||
There is no new content, but this list of fixes is enough reason to publish a new release.
|
||||
Here is is the link: [url]https://andorstrail.com/static/AndorsTrail_v0.8.2.apk[/url]
|
||||
|
||||
Google Play and Itch will follow soon, and hopefully F-Droid too.
|
||||
|
||||
Cheers!
|
||||
|
||||
|
||||
|
||||
APK 65 (0.8.1) //Engine modernization + Sullengard
|
||||
|
||||
Release notes
|
||||
=============
|
||||
* Reorginization of the engine! It can be compiled by actual AS versions, as well as go to F-Droid at last.
|
||||
This is worth a new release number 0.8!
|
||||
* The content files stay in their usual directories, so Weblate and ATCS projects needn't be changed.
|
||||
|
||||
* New quest: "Hunting the hunter"
|
||||
* New quest: "Getting home on time"
|
||||
You find these quests on your way to Sullengard.
|
||||
|
||||
* New quest: "Pond safety"
|
||||
* New quest: "Recovering stolen property"
|
||||
Look for these in Sullengard.
|
||||
|
||||
* New quest: "Beer Bootlegging"
|
||||
Starts at the Foaming flask.
|
||||
|
||||
* New quest: "Another ruthless Crackshot"
|
||||
Sound like thieves affairs, so ask at the Guild.
|
||||
|
||||
* Two more achievements
|
||||
* 72 new maps
|
||||
|
||||
* Various small changes and bug fixes
|
||||
* Translations actualized
|
||||
* New city Sullengard
|
||||
* 71 new maps and 6 new quests
|
||||
* Monster kill count
|
||||
* Controller support
|
||||
* Translation updates
|
||||
* Engine changes to support actual Android Studio
|
||||
|
||||
|
||||
Forum beta announcement //2022-08-27
|
||||
Forum beta announcement //2022-09-28
|
||||
=======================
|
||||
Hello fellow adventurers,
|
||||
|
||||
@@ -37,7 +233,7 @@ it took a while - much longer than we planned - but it was worth the wait:
|
||||
|
||||
[list]We have a big update with 71 new maps and 6 new quests for you![/list]
|
||||
|
||||
[list]3 Additions from Guro-meditation-No42:
|
||||
[list]3 Additions from Guru-meditation-No42:
|
||||
[list]Kill count summed up for monsters with same name (a minor irritation)[/list]
|
||||
[list]Show kills of monsters in monster stat view (often requested)[/list]
|
||||
[list]Controller support (not yet tested)[/list]
|
||||
@@ -62,23 +258,20 @@ The following two quests are found elsewhere:
|
||||
[list]"Beer Bootlegging" starts at the Foaming flask[/list]
|
||||
[list]"Another ruthless Crackshot" not only sounds like thieves affairs, so ask at the Guild.[/list]
|
||||
|
||||
|
||||
I won't tell more about the quests, I trust you to find out yourself - it's more fun after all.
|
||||
|
||||
|
||||
In good tradition we first publish a beta here in the forum.
|
||||
What do you think of the new parts? What is good and what is not so good? Can you play properly with a console?
|
||||
Of course let us know if you find any errors or inconsistencies (preferably with a screenshot).
|
||||
Translations are actualized, many languages are at 93% now. That would have been 100%, if we hadn't added the new quests.
|
||||
This is great - Thanks to all the translators!
|
||||
|
||||
Maybe you will notice that a few already translated texts are now in English again. This has technical reasons which I couldn't avoid - sorry for the inconvenience.
|
||||
|
||||
|
||||
Keep in mind that savegames of a beta version will not work later in any product version!
|
||||
The beta is a separate APK now, so you can have both (beta and product version) parallel in your device. New Android versions will keep the savegames of beta and prod.version separate too.
|
||||
Here is the link to the productive version: [url]https://andorstrail.com/static/AndorsTrail_v0.8.1.apk[/url]
|
||||
|
||||
Google Play and Itch will follow soon, and hopefully this version can also be provided by F-Droid again.
|
||||
|
||||
Here now is the link to v0.8.1 beta version: [url]https://andorstrail.com/static/AndorsTrail_v0.8.1beta.apk[/url]
|
||||
As always: Best make a backup of your savegames first to be sure.
|
||||
|
||||
Thx for your patience - have fun with the beta!
|
||||
Thx for your patience - have fun with the new release!
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 100 KiB |
BIN
AndorsTrail/res/drawable/map_55.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
AndorsTrail/res/drawable/map_56.png
Normal file
|
After Width: | Height: | Size: 78 KiB |