Compare commits

..

1 Commits

Author SHA1 Message Date
Chriz76
08a54c5635 Typo 2020-01-18 12:59:32 +01:00
1166 changed files with 100964 additions and 1749974 deletions

View File

@@ -1,14 +0,0 @@
dist: bionic
sudo: required
cache:
directories:
- $HOME/pbuilder-bases
matrix:
include:
- env: TARGET_OS=stretch
before_install:
- "$TRAVIS_BUILD_DIR/travis/$TRAVIS_OS_NAME.$TARGET_OS.before_install"
install:
- "$TRAVIS_BUILD_DIR/travis/$TRAVIS_OS_NAME.$TARGET_OS.install"
script:
- "$TRAVIS_BUILD_DIR/travis/$TRAVIS_OS_NAME.$TARGET_OS.script"

9
AndorsTrail/.classpath Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@@ -1,15 +1,8 @@
# Android ignores
app/src/main/res
app/src/main/assets
gen/
bin/
target/
local.properties
app/build/intermediates/
build/
debug/
release/
.gradle/
#IntelliJ
.idea/
@@ -21,35 +14,3 @@ out/test/
# Other
.metadata
.svn/
#copied from https://github.com/github/gitignore/blob/main/Gradle.gitignore
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
#copied from https://github.com/github/gitignore/blob/main/Gradle.gitignore
/AndorsTrail/.gradle
/AndorsTrail/gradle/wrapper
/AndorsTrail/app/build/
/AndorsTrail/app/debug/
/AndorsTrail/app/release/

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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[C:\Users\chris\.android\avd\Nexus_5_API_30.avd]" />
<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="&lt;template&gt;" 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="&lt;template&gt;" 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>

33
AndorsTrail/.project Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>AndorsTrail</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="EclipseModuleManager" forced_jdk="true">
<conelement value="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK" />
<conelement value="com.android.ide.eclipse.adt.LIBRARIES" />
<src_description expected_position="1">
<src_folder value="file://$MODULE_DIR$/src" expected_position="0" />
<src_folder value="file://$MODULE_DIR$/gen" expected_position="1" />
</src_description>
</component>
<component name="FacetManager">
<facet type="android" name="Android">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/bin/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/libs/android-support-v4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View File

@@ -1,78 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gpl.rpg.AndorsTrail"
android:versionCode="66"
android:versionName="0.8.2"
android:installLocation="auto"
>
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="30"
/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".AndorsTrailApplication"
android:label="@string/app_name"
android:icon="@drawable/icon"
android:description="@string/app_description"
android:allowBackup="true"
android:theme="@style/AndorsTrailTheme_Blue"
android:requestLegacyExternalStorage="true"
android:hasFragileUserData="true"
android:preserveLegacyExternalStorage="true"
>
<activity
android:name=".activity.StartScreenActivity"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AndorsTrailTheme_Blue.NoBackground"
/>
<activity android:name=".activity.HeroinfoActivity" />
<activity android:name=".activity.MonsterInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ItemInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.LevelUpActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.MonsterEncounterActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ConversationActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ShopActivity" />
<activity android:name=".activity.AboutActivity" />
<activity android:name=".activity.LoadingActivity" />
<activity android:name=".activity.Preferences" />
<activity android:name=".activity.LoadSaveActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ActorConditionInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.BulkSelectionInterface" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.SkillInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.DisplayWorldMapActivity" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.gpl.rpg.AndorsTrail.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider" />
</provider>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gpl.rpg.AndorsTrail"
android:versionCode="49"
android:versionName="0.7.8"
android:installLocation="auto"
>
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="28"
/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_LOGS"/>
<application
android:name=".AndorsTrailApplication"
android:label="@string/app_name"
android:icon="@drawable/icon"
android:description="@string/app_description"
android:allowBackup="true"
android:theme="@style/AndorsTrailTheme_Blue"
>
<activity
android:name=".activity.StartScreenActivity"
android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AndorsTrailTheme_Blue.NoBackground"
/>
<activity android:name=".activity.HeroinfoActivity" />
<activity android:name=".activity.MonsterInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ItemInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.LevelUpActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.MonsterEncounterActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ConversationActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ShopActivity" />
<activity android:name=".activity.AboutActivity" />
<activity android:name=".activity.LoadingActivity" />
<activity android:name=".activity.Preferences" />
<activity android:name=".activity.LoadSaveActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ActorConditionInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.BulkSelectionInterface" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.SkillInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.DisplayWorldMapActivity" />
</application>
</manifest>

View File

@@ -1,23 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.gpl.rpg.AndorsTrail"
minSdkVersion 14
targetSdkVersion 30
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
implementation 'com.android.support:support-v4:28.0.0'
}

View File

@@ -1,341 +0,0 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.view.MainView;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;
public final class DebugInterface {
private final ControllerContext controllerContext;
private final MainActivity mainActivity;
private final Resources res;
private final WorldContext world;
private DebugButton[] buttons;
private List<DebugButton> tpButtons = new ArrayList<DebugButton>();
private List<DebugButton> tpButtons2 = new ArrayList<DebugButton>();
public DebugInterface(ControllerContext controllers, WorldContext world, MainActivity mainActivity) {
this.controllerContext = controllers;
this.world = world;
this.res = mainActivity.getResources();
this.mainActivity = mainActivity;
}
public void addDebugButtons() {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
List<DebugButton> buttonList = new ArrayList<DebugButton>();
buttonList.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("dbg", new OnClickListener() {
boolean hidden = false;
@Override
public void onClick(View arg0) {
hidden = !hidden;
for (int i = 1; i < buttons.length; i++) {
buttons[i].b.setVisibility(hidden ? View.GONE : View.VISIBLE);
}
for (DebugButton b : tpButtons) {
b.b.setVisibility(View.GONE);
}
for (DebugButton b : tpButtons2) {
b.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("teleport", new OnClickListener() {
public void onClick(View arg0) {
for (int i = 0; i < buttons.length; i++) {
buttons[i].b.setVisibility(View.GONE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.VISIBLE);
}
}
})
,new DebugButton("dmg", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.damagePotential.set(500, 500);
world.model.player.attackChance = 500;
world.model.player.attackCost = 1;
showToast(mainActivity, "DEBUG: damagePotential=500, chance=500%, cost=1", Toast.LENGTH_SHORT);
}
})
/*,new DebugButton("dmg=1", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.damagePotential.set(1, 1);
showToast(mainActivity, "DEBUG: damagePotential=1", Toast.LENGTH_SHORT);
}
})*/
,new DebugButton("itm", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (ItemType item : world.itemTypes.UNITTEST_getAllItemTypes().values()) {
world.model.player.inventory.addItem(item, 10);
}
world.model.player.inventory.gold += 50000;
showToast(mainActivity, "DEBUG: added items", Toast.LENGTH_SHORT);
}
})
,new DebugButton("xp", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.actorStatsController.addExperience(10000);
showToast(mainActivity, "DEBUG: given 10000 exp", Toast.LENGTH_SHORT);
}
})
,new DebugButton("rst", new OnClickListener() {
@Override
public void onClick(View arg0) {
for(PredefinedMap map : world.maps.getAllMaps()) {
map.resetTemporaryData();
}
showToast(mainActivity, "DEBUG: maps respawned", Toast.LENGTH_SHORT);
}
})
,new DebugButton("hp", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.baseTraits.maxHP = 500;
world.model.player.health.max = world.model.player.baseTraits.maxHP;
controllerContext.actorStatsController.setActorMaxHealth(world.model.player);
world.model.player.conditions.clear();
showToast(mainActivity, "DEBUG: hp set to max", Toast.LENGTH_SHORT);
}
})
,new DebugButton("skl", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.availableSkillIncreases += 10;
showToast(mainActivity, "DEBUG: 10 skill points", Toast.LENGTH_SHORT);
}
})
,new DebugButton("spd", new OnClickListener() {
boolean fast = Constants.MINIMUM_INPUT_INTERVAL == Constants.MINIMUM_INPUT_INTERVAL_FAST;
@Override
public void onClick(View arg0) {
fast = !fast;
if (fast) {
Constants.MINIMUM_INPUT_INTERVAL = Constants.MINIMUM_INPUT_INTERVAL_FAST;
} else {
Constants.MINIMUM_INPUT_INTERVAL = Constants.MINIMUM_INPUT_INTERVAL_STD;
}
MainView.SCROLL_DURATION = Constants.MINIMUM_INPUT_INTERVAL;
AndorsTrailApplication.getApplicationFromActivity(mainActivity).getControllerContext().movementController.resetMovementHandler();
}
})
,new DebugButton("map", new OnClickListener() {
@Override
public void onClick(View arg0) {
showToast(mainActivity, "DEBUG: map=" + world.model.currentMaps.map.name , Toast.LENGTH_SHORT);
}
})
}));
tpButtons.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("teleport", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (DebugButton tpButton : tpButtons2) {
tpButton.b.setVisibility(View.VISIBLE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("cg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "crossglen", "hall", 0, 0);
}
})
,new DebugButton("vg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "vilegard_s", "tavern", 0, 0);
}
})
,new DebugButton("cr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "houseatcrossroads4", "down", 0, 0);
}
})
,new DebugButton("lf", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "loneford9", "south", 0, 0);
}
})
,new DebugButton("fh", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "fallhaven_ne", "clothes", 0, 0);
}
})
,new DebugButton("prm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "blackwater_mountain29", "south", 0, 0);
}
})
,new DebugButton("bwm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "blackwater_mountain43", "south", 0, 0);
}
})
,new DebugButton("rmg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "remgard0", "east", 0, 0);
}
})
,new DebugButton("chr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "waytolostmine2", "minerhouse4", 0, 0);
}
})
,new DebugButton("ldr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "lodarhouse0", "lodarhouse", 0, 0);
}
})
,new DebugButton("sf", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "wild20", "south2", 0, 0);
}
})
,new DebugButton("gm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "guynmart_wood_1", "farmhouse", 0, 0);
}
})
}));
buttonList.addAll(tpButtons);
tpButtons2.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("teleport", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (int i = 0; i < buttons.length; i++) {
buttons[i].b.setVisibility(View.VISIBLE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.GONE);
}
for (DebugButton tpButton : tpButtons2) {
tpButton.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("brv", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "brimhaven4", "south2", 0, 0);
}
})
,new DebugButton("aru", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "mountainlake5", "north", 0, 0);
}
})
,new DebugButton("ws", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "woodsettlement0", "east", 0, 0);
}
})
,new DebugButton("sul", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "sullengard2", "south", 0, 0);
}
})
}));
buttonList.addAll(tpButtons2);
buttons = buttonList.toArray(new DebugButton[buttonList.size()]);
addDebugButtons(buttons);
for (DebugButton b : tpButtons) {
b.b.setVisibility(View.GONE);
}
for (DebugButton b : tpButtons2) {
b.b.setVisibility(View.GONE);
}
}
private void showToast(Context context, String msg, int duration) {
Toast.makeText(context, msg, duration).show();
}
private static class DebugButton {
public final String text;
public final OnClickListener listener;
public Button b = null;
public DebugButton(String text, OnClickListener listener) {
this.text = text;
this.listener = listener;
}
public void makeButton(Context c, int id) {
b = new Button(c);
b.setText(text);
b.setTextSize(10);//res.getDimension(R.dimen.actionbar_text));
b.setId(id);
b.setOnClickListener(listener);
}
}
private void addDebugButton(DebugButton button, int id, RelativeLayout layout) {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, res.getDimensionPixelSize(R.dimen.smalltext_buttonheight));
if (id == 1)
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
else
lp.addRule(RelativeLayout.RIGHT_OF, id - 1);
lp.addRule(RelativeLayout.ABOVE, R.id.main_statusview);
button.makeButton(mainActivity, id);
button.b.setLayoutParams(lp);
layout.addView(button.b);
}
private void addDebugButtons(DebugButton[] buttons) {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
if (buttons == null || buttons.length <= 0) return;
RelativeLayout layout = (RelativeLayout) mainActivity.findViewById(R.id.main_container);
int id = 1;
for (DebugButton b : buttons) {
addDebugButton(b, id, layout);
++id;
}
}
}

View File

@@ -1,684 +0,0 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.provider.DocumentFile;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
public final class LoadSaveActivity extends AndorsTrailBaseActivity implements OnClickListener {
private boolean isLoading = true;
//region special slot numbers
private static final int SLOT_NUMBER_CREATE_NEW_SLOT = -1;
public static final int SLOT_NUMBER_EXPORT_SAVEGAMES = -2;
public static final int SLOT_NUMBER_IMPORT_SAVEGAMES = -3;
public static final int SLOT_NUMBER_IMPORT_WORLDMAP = -4;
private static final int SLOT_NUMBER_FIRST_SLOT = 1;
//endregion
private ModelContainer model;
private TileManager tileManager;
private AndorsTrailPreferences preferences;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getDialogTheme());
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
this.model = app.getWorld().model;
this.preferences = app.getPreferences();
this.tileManager = app.getWorld().tileManager;
String loadsave = getIntent().getData().getLastPathSegment();
isLoading = (loadsave.equalsIgnoreCase("load"));
setContentView(R.layout.loadsave);
TextView tv = (TextView) findViewById(R.id.loadsave_title);
if (isLoading) {
tv.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_menu_search, 0, 0, 0);
tv.setText(R.string.loadsave_title_load);
} else {
tv.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_menu_save, 0, 0, 0);
tv.setText(R.string.loadsave_title_save);
}
ViewGroup slotList = (ViewGroup) findViewById(R.id.loadsave_slot_list);
Button slotTemplateButton = (Button) findViewById(R.id.loadsave_slot_n);
LayoutParams params = slotTemplateButton.getLayoutParams();
slotList.removeView(slotTemplateButton);
ViewGroup newSlotContainer = (ViewGroup) findViewById(R.id.loadsave_save_to_new_slot_container);
Button createNewSlot = (Button) findViewById(R.id.loadsave_save_to_new_slot);
Button exportSaves = (Button) findViewById(R.id.loadsave_export_save);
Button importSaves = (Button) findViewById(R.id.loadsave_import_save);
Button importWorldmap = (Button) findViewById(R.id.loadsave_import_worldmap);
exportSaves.setTag(SLOT_NUMBER_EXPORT_SAVEGAMES);
importSaves.setTag(SLOT_NUMBER_IMPORT_SAVEGAMES);
importWorldmap.setTag(SLOT_NUMBER_IMPORT_WORLDMAP);
ViewGroup exportContainer = (ViewGroup) findViewById(R.id.loadsave_export_save_container);
ViewGroup importContainer = (ViewGroup) findViewById(R.id.loadsave_import_save_container);
ViewGroup importWorldmapContainer = (ViewGroup) findViewById(R.id.loadsave_import_worldmap_container);
addSavegameSlotButtons(slotList, params, Savegames.getUsedSavegameSlots(this));
checkAndRequestPermissions();
if (!isLoading) {
createNewSlot.setTag(SLOT_NUMBER_CREATE_NEW_SLOT);
createNewSlot.setOnClickListener(this);
newSlotContainer.setVisibility(View.VISIBLE);
exportContainer.setVisibility(View.GONE);
importContainer.setVisibility(View.GONE);
importWorldmapContainer.setVisibility(View.GONE);
} else {
newSlotContainer.setVisibility(View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
exportSaves.setOnClickListener(this);
importSaves.setOnClickListener(this);
importWorldmap.setOnClickListener(this);
exportContainer.setVisibility(View.VISIBLE);
importContainer.setVisibility(View.VISIBLE);
importWorldmapContainer.setVisibility(View.VISIBLE);
}
}
}
private static final int READ_EXTERNAL_STORAGE_REQUEST = 1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST = 2;
@TargetApi(23)
private void checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST);
}
if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.storage_permissions_mandatory, Toast.LENGTH_LONG).show();
((AndorsTrailApplication) getApplication()).discardWorld();
finish();
}
}
private void addSavegameSlotButtons(ViewGroup parent, LayoutParams params, List<Integer> usedSavegameSlots) {
int unused = 1;
for (int slot : usedSavegameSlots) {
final FileHeader header = Savegames.quickload(this, slot);
if (header == null) continue;
while (unused < slot) {
Button b = new Button(this);
b.setLayoutParams(params);
b.setTag(unused);
b.setOnClickListener(this);
b.setText(getString(R.string.loadsave_empty_slot, unused));
tileManager.setImageViewTileForPlayer(getResources(), b, header.iconID);
parent.addView(b, params);
unused++;
}
unused++;
Button b = new Button(this);
b.setLayoutParams(params);
b.setTag(slot);
b.setOnClickListener(this);
b.setText(slot + ". " + header.describe());
tileManager.setImageViewTileForPlayer(getResources(), b, header.iconID);
parent.addView(b, params);
}
}
private void completeLoadSaveActivity(int slot) {
Intent i = new Intent();
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
List<Integer> usedSlots = Savegames.getUsedSavegameSlots(this);
if (usedSlots.isEmpty())
slot = SLOT_NUMBER_FIRST_SLOT;
else slot = Collections.max(usedSlots) + 1;
} else if (slot == SLOT_NUMBER_EXPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
i.putExtra("import_export", true);
} else if (slot < SLOT_NUMBER_FIRST_SLOT)
slot = SLOT_NUMBER_FIRST_SLOT;
i.putExtra("slot", slot);
setResult(Activity.RESULT_OK, i);
LoadSaveActivity.this.finish();
}
private String getConfirmOverwriteQuestion(int slot) {
if (isLoading)
return null;
return getConfirmOverwriteQuestionIgnoringLoading(slot);
}
private String getConfirmOverwriteQuestionIgnoringLoading(int slot) {
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT)
return null;//creating a new savegame
if (!Savegames.getSlotFile(slot, this).exists())
return null;//nothing in slot to overwrite
if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_ALWAYS) {
return getString(R.string.loadsave_save_overwrite_confirmation_all);
}
if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_NEVER) {
return null;
}
final String currentPlayerName = model.player.getName();
final FileHeader header = Savegames.quickload(this, slot);
if (header == null) return null;
final String savedPlayerName = header.playerName;
if (currentPlayerName.equals(savedPlayerName)) return null; //if the names match
return getString(R.string.loadsave_save_overwrite_confirmation, savedPlayerName, currentPlayerName);
}
@Override
public void onClick(View view) {
final int slot = (Integer) view.getTag();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
switch (slot) {
case SLOT_NUMBER_IMPORT_WORLDMAP:
clickImportWorldmap();
return;
case SLOT_NUMBER_IMPORT_SAVEGAMES:
clickImportSaveGames();
return;
case SLOT_NUMBER_EXPORT_SAVEGAMES:
clickExportSaveGames();
return;
}
}
if (!isLoading
&& slot != SLOT_NUMBER_CREATE_NEW_SLOT
&& AndorsTrailApplication.CURRENT_VERSION == AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
if (!isOverwriteTargetInIncompatibleVersion(slot)) {
saveOrOverwriteSavegame(slot);
}
} else if (isLoading) {
loadSaveGame(slot);
} else {
saveOrOverwriteSavegame(slot);
}
}
private void saveOrOverwriteSavegame(int slot) {
final String message = getConfirmOverwriteQuestion(slot);
if (message != null) {
showConfirmoverwriteQuestion(slot, message);
} else {
completeLoadSaveActivity(slot);
}
}
private boolean isOverwriteTargetInIncompatibleVersion(int slot) {
final FileHeader header = Savegames.quickload(this, slot);
if (header != null && header.fileversion != AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
final Dialog d = CustomDialogFactory.createErrorDialog(this, "Overwriting not allowed", "You are currently using a development version of Andor's trail. Overwriting a regular savegame is not allowed in development mode.");
CustomDialogFactory.show(d);
return true;
}
return false;
}
//region Imports/Exports
private void exportSaveGames(Intent data) {
Uri uri = data.getData();
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this).getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile source = DocumentFile.fromFile(storageDir);
DocumentFile target = DocumentFile.fromTreeUri(context, uri);
if (target == null) {
return;
}
DocumentFile[] files = source.listFiles();
boolean hasExistingFiles = false;
for (DocumentFile file :
files) {
String fileName = file.getName();
if (fileName == null)
continue;
DocumentFile existingFile = target.findFile(fileName);
if (existingFile != null) {
hasExistingFiles = true;
break;
}
}
if (hasExistingFiles) {
showConfirmOverwriteByExportQuestion(resolver, target, files);
} else {
exportSaveGamesFolderContentToFolder(resolver, target, files);
}
}
private void exportSaveGamesFolderContentToFolder(ContentResolver resolver, DocumentFile target, DocumentFile[] files) {
for (DocumentFile file : files) {
String fileName = file.getName();
DocumentFile existingFile = target.findFile(fileName);
boolean hasExistingFile = existingFile != null && existingFile.exists();
if (file.isFile()) {
try {
if (hasExistingFile)
existingFile.delete();
AndroidStorage.copyDocumentFileToNewOrExistingFile(file, resolver, target);
} catch (IOException e) {
e.printStackTrace();
}
} else if (file.isDirectory()) {
DocumentFile targetWorlmap = existingFile;
//if the folder exists already, put the files in the existing folder. (should not happen because of check earlier)
if (!hasExistingFile)
//create a new folder for the worldmap-files
targetWorlmap = target.createDirectory(Constants.FILENAME_WORLDMAP_DIRECTORY);
if (targetWorlmap == null)//Unable to create worldmap folder for some reason
continue;
DocumentFile[] worldmapFiles = file.listFiles();
for (DocumentFile f : worldmapFiles) {
try {
AndroidStorage.copyDocumentFileToNewOrExistingFile(f, resolver, targetWorlmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
completeLoadSaveActivity(SLOT_NUMBER_EXPORT_SAVEGAMES);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void importSaveGames(Intent data) {
Uri uri = data.getData();
ClipData uris = data.getClipData();
if (uri == null && uris == null) {
//no file was selected
return;
}
Context context = getApplicationContext();
ContentResolver resolver = context.getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile appSavegameFolder = DocumentFile.fromFile(storageDir);
List<Uri> uriList = new ArrayList<>();
if (uri != null) {
uriList.add(uri);
} else {
for (int i = 0; i < uris.getItemCount(); i++)
uriList.add(uris.getItemAt(i).getUri());
}
importSaveGamesFromUris(context, resolver, appSavegameFolder, uriList);
}
private void importSaveGamesFromUris(Context context, ContentResolver resolver, DocumentFile appSavegameFolder, List<Uri> uriList) {
int count = uriList.size();
ArrayList<DocumentFile> alreadyExistingFiles = new ArrayList<>();
ArrayList<DocumentFile> newFiles = new ArrayList<>();
for (int i = 0; i < count; i++) {
Uri item = uriList.get(i);
DocumentFile itemFile = DocumentFile.fromSingleUri(context, item);
boolean fileAlreadyExists = getExistsSavegameInOwnFiles(itemFile, appSavegameFolder);
if (fileAlreadyExists)
alreadyExistingFiles.add(itemFile);
else
newFiles.add(itemFile);
}
if (alreadyExistingFiles.size() > 0) {
showConfirmOverwriteByImportQuestion(resolver, appSavegameFolder, alreadyExistingFiles, newFiles);
} else {
importSaveGames(resolver, appSavegameFolder, newFiles);
}
}
private void importSaveGames(ContentResolver resolver, DocumentFile appSavegameFolder, List<DocumentFile> saveFiles) {
for (DocumentFile file : saveFiles) {
int slot = getSlotFromSavegameFileName(file.getName());
importSaveGameFile(resolver, appSavegameFolder, file, slot);
}
}
private void completeSavegameImportAndCheckIfDone(List<Integer> importsNeedingConfirmation, int slot) {
importsNeedingConfirmation.remove((Object) slot);
if (importsNeedingConfirmation.isEmpty()) {
completeLoadSaveActivity(SLOT_NUMBER_IMPORT_SAVEGAMES);
}
}
private boolean getExistsSavegameInOwnFiles(DocumentFile savegameFile, DocumentFile appSavegameFolder) {
if (savegameFile == null)
return false;
DocumentFile foundFile = appSavegameFolder.findFile(Objects.requireNonNull(savegameFile.getName()));
return foundFile != null && foundFile.exists();
}
private int getSlotFromSavegameFileName(String fileName) {
if (fileName == null || !fileName.startsWith(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX)) {
//TODO: Maybe output a message that the file didn't have the right name?
return -1;
}
String slotStr = fileName.substring(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX.length());
int slot;
try {
slot = Integer.parseInt(slotStr);
return slot;
} catch (NumberFormatException e) {
//TODO: Maybe output a message that the file didn't have the right name?
return -1;
}
}
private void importSaveGameFile(ContentResolver resolver, DocumentFile appSavegameFolder, DocumentFile itemFile, int slot) {
String targetName = Savegames.getSlotFileName(slot);
DocumentFile targetFile = getOrCreateDocumentFile(appSavegameFolder, targetName);
if (targetFile == null || !targetName.equals(targetFile.getName())) {
showErrorImportingSaveGameUnknown();//TODO: maybe replace with a more specific error message
return;
}
try {
AndroidStorage.copyDocumentFile(itemFile, resolver, targetFile);
} catch (IOException e) {
showErrorImportingSaveGameUnknown();
e.printStackTrace();
}
}
private DocumentFile getOrCreateDocumentFile(DocumentFile folder, String targetName) {
DocumentFile targetFile = folder.findFile(targetName);//try finding the file
if (targetFile == null)//no file found, creating new one
targetFile = folder.createFile(Constants.NO_FILE_EXTENSION_MIME_TYPE, targetName);
return targetFile;
}
private void importWorldmap(Intent data) {
Uri uri = data.getData();
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this).getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile storageFolder = DocumentFile.fromFile(storageDir);
DocumentFile ownWorldmapFolder = storageFolder.findFile(Constants.FILENAME_WORLDMAP_DIRECTORY);
if (ownWorldmapFolder == null) {
ownWorldmapFolder = storageFolder.createDirectory(Constants.FILENAME_WORLDMAP_DIRECTORY);
}
DocumentFile chosenFolder = DocumentFile.fromTreeUri(context, uri);
if (chosenFolder == null || !chosenFolder.isDirectory()) {
showErrorImportingWorldmapWrongDirectory();
return;
}
if (!Constants.FILENAME_WORLDMAP_DIRECTORY.equals(chosenFolder.getName())) {
//user did not select the worldmap folder directly
DocumentFile file = chosenFolder.findFile(Constants.FILENAME_WORLDMAP_DIRECTORY);
if (file == null || !file.isDirectory() || !Constants.FILENAME_WORLDMAP_DIRECTORY.equals(file.getName())) {
//could not find a worldmap folder in the users selection
showErrorImportingWorldmapWrongDirectory();
return;
}
chosenFolder = file;
}
DocumentFile[] files = chosenFolder.listFiles();
for (DocumentFile file : files) {
if (file.isFile()) {
try {
AndroidStorage.copyDocumentFileToNewOrExistingFile(file, resolver, ownWorldmapFolder);
} catch (IOException e) {
e.printStackTrace();
}
}
}
completeLoadSaveActivity(SLOT_NUMBER_IMPORT_WORLDMAP);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickExportSaveGames() {
startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(), -SLOT_NUMBER_EXPORT_SAVEGAMES);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickImportSaveGames() {
startActivityForResult(AndroidStorage.getNewSelectMultipleSavegameFilesIntent(), -SLOT_NUMBER_IMPORT_SAVEGAMES);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickImportWorldmap() {
startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(), -SLOT_NUMBER_IMPORT_WORLDMAP);
}
private void showConfirmOverwriteByExportQuestion(ContentResolver resolver, DocumentFile targetFolder, DocumentFile[] files) {
final Dialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_export_overwrite_confirmation_title),
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.loadsave_export_overwrite_confirmation),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, v -> exportSaveGamesFolderContentToFolder(resolver, targetFolder, files));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
private void showConfirmOverwriteByImportQuestion(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> alreadyExistingFiles,
List<DocumentFile> newFiles) {
final String title = getString(R.string.loadsave_import_overwrite_confirmation_title);
String message = getString(R.string.loadsave_import_overwrite_confirmation);
StringBuilder sb = new StringBuilder();
sb.append('\n');
int amount = alreadyExistingFiles.size();
Context context = AndorsTrailApplication.getApplicationFromActivity(this).getApplicationContext();
for (int i = 0; i < amount && i < 3; i++) {
DocumentFile alreadyExistingFile = alreadyExistingFiles.get(i);
String alreadyExistingFileName = alreadyExistingFile.getName();
FileHeader fileHeader = Savegames.quickload(context, getSlotFromSavegameFileName(alreadyExistingFileName));
sb.append('\n');
String fileHeaderDesription = "";
if (fileHeader != null)
fileHeaderDesription = fileHeader.describe();
sb.append(getString(R.string.loadsave_import_overwrite_confirmation_file_pattern, alreadyExistingFileName, fileHeaderDesription));
// sb.append(alreadyExistingFile.getName());
}
if (amount > 3) {
sb.append("\n...");
}
message = message + sb;
final Dialog d = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
message,
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, v -> newFiles.addAll(alreadyExistingFiles));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.setDismissListener(d, dialog -> {
importSaveGames(resolver, appSavegameFolder, newFiles);
completeLoadSaveActivity(SLOT_NUMBER_IMPORT_SAVEGAMES);
});
CustomDialogFactory.show(d);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK)
return;
// Uri uri = data.getData();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
switch (-requestCode) {
case SLOT_NUMBER_EXPORT_SAVEGAMES:
exportSaveGames(data);
return;
case SLOT_NUMBER_IMPORT_SAVEGAMES:
importSaveGames(data);
return;
case SLOT_NUMBER_IMPORT_WORLDMAP:
importWorldmap(data);
return;
}
}
}
//endregion
private void loadSaveGame(int slot) {
if (!Savegames.getSlotFile(slot, this).exists()) {
showErrorLoadingEmptySlot();
} else {
final FileHeader header = Savegames.quickload(this, slot);
if (header != null && !header.hasUnlimitedSaves) {
showSlotGetsDeletedOnLoadWarning(slot);
} else {
completeLoadSaveActivity(slot);
}
}
}
//region show Dialogs
private void showErrorImportingWorldmapWrongDirectory() {
final Dialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_import_worldmap_unsuccessfull),
getString(R.string.loadsave_import_worldmap_unsuccessfull_wrong_directory));
CustomDialogFactory.show(d);
}
private void showErrorImportingSaveGameUnknown() {
final Dialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_import_save_unsuccessfull),
getString(R.string.loadsave_import_save_unsuccessfull_unknown));
CustomDialogFactory.show(d);
}
private void showErrorLoadingEmptySlot() {
final Dialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.startscreen_error_loading_game),
getString(R.string.startscreen_error_loading_empty_slot));
CustomDialogFactory.show(d);
}
private void showSlotGetsDeletedOnLoadWarning(final int slot) {
final Dialog d = CustomDialogFactory.createDialog(this,
getString(R.string.startscreen_attention_slot_gets_delete_on_load),
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_attention_message_slot_gets_delete_on_load),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, v -> completeLoadSaveActivity(slot));
CustomDialogFactory.show(d);
}
private void showConfirmoverwriteQuestion(final int slot, String message) {
final String title =
getString(R.string.loadsave_save_overwrite_confirmation_title) + ' '
+ getString(R.string.loadsave_save_overwrite_confirmation_slot, slot);
final Dialog d = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
message,
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, v -> completeLoadSaveActivity(slot));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
//endregion
}

View File

@@ -1,414 +0,0 @@
package com.gpl.rpg.AndorsTrail.activity.fragment;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.activity.AboutActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadSaveActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadingActivity;
import com.gpl.rpg.AndorsTrail.activity.Preferences;
import com.gpl.rpg.AndorsTrail.activity.StartScreenActivity;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader;
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;
public class StartScreenActivity_MainMenu extends Fragment {
private static final int INTENTREQUEST_PREFERENCES = 7;
public static final int INTENTREQUEST_LOADGAME = 9;
public static final int INTENTREQUEST_EXPORT_SAVE = 11;
public static final int INTENTREQUEST_IMPORT_SAVE = 13;
private boolean hasExistingGame = false;
private Button startscreen_continue;
private Button startscreen_newgame;
private Button startscreen_load;
private Button startscreen_import;
private Button startscreen_export;
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) {
container.removeAllViews();
}
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() {
@Override
public void onClick(View arg0) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
});
startscreen_newgame = (Button) root.findViewById(R.id.startscreen_newgame);
startscreen_newgame.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (hasExistingGame) {
comfirmNewGame();
} else {
createNewGame();
}
}
});
Button b = (Button) root.findViewById(R.id.startscreen_about);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(getActivity(), AboutActivity.class));
}
});
b = (Button) root.findViewById(R.id.startscreen_preferences);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(getActivity(), Preferences.class);
StartScreenActivity_MainMenu.this.startActivityForResult(intent, INTENTREQUEST_PREFERENCES);
}
});
startscreen_load = (Button) root.findViewById(R.id.startscreen_load);
startscreen_load.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
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(),
getString(R.string.startscreen_load_game),
getResources().getDrawable(android.R.drawable.ic_delete),
getString(R.string.startscreen_load_game_confirm),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
} else {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
}
});
if (AndorsTrailApplication.DEVELOPMENT_FORCE_STARTNEWGAME) {
if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) {
continueGame(true, 0, "Debug player");
} else {
continueGame(true, 0, "Player");
}
} else if (AndorsTrailApplication.DEVELOPMENT_FORCE_CONTINUEGAME) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
// if it is a new version we first fire a welcome screen in onResume
// and afterwards check the permissions
if (!isNewVersion()) {
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
}
return root;
}
@Override
public void onResume() {
super.onResume();
String playerName;
String displayInfo = null;
int iconID = TileManager.CHAR_HERO;
boolean isDead = false;
FileHeader header = Savegames.quickload(getActivity(), Savegames.SLOT_QUICKSAVE);
if (header != null && header.playerName != null) {
playerName = header.playerName;
displayInfo = header.displayInfo;
iconID = header.iconID;
isDead = header.isDead;
} else {
// Before fileversion 14 (v0.6.7), quicksave was stored in Shared preferences
SharedPreferences p = getActivity().getSharedPreferences("quicksave", Activity.MODE_PRIVATE);
playerName = p.getString("playername", null);
if (playerName != null) {
displayInfo = "level " + p.getInt("level", -1);
}
}
hasExistingGame = (playerName != null);
setButtonState(playerName, displayInfo, iconID, isDead);
if (isNewVersion()) {
Dialogs.showNewVersion(getActivity(), new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
setCurrentVersionForVersionCheck();
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
startscreen_load.setEnabled(true);
}
});
}
startscreen_load.setEnabled(true);
}
@TargetApi(29)
public void migrateDataOnDemand(final Activity activity) {
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,
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) {
startscreen_load.setEnabled(true);
}
});
CustomDialogFactory.show(d);
if (!AndroidStorage.migrateToInternalStorage(activity.getApplicationContext())) {
final Dialog 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),
null,
true);
CustomDialogFactory.addDismissButton(errorDlg, android.R.string.ok);
d.cancel();
CustomDialogFactory.show(errorDlg);
}
} else {
L.log("INFO: No external files or destination folder ist not empty. No data migration.");
}
} else {
L.log("INFO: No read permission on external folder. No data migration.");
}
}
}
private static final int READ_EXTERNAL_STORAGE_REQUEST = 1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST = 2;
@TargetApi(23)
public static void checkAndRequestPermissions(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST);
}
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@Override
public void onAttach(Activity activity) {
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);
if (hasExistingGame) {
TileManager tm = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorld().tileManager;
tm.setImageViewTileForPlayer(getResources(), save_preview_hero_icon, iconID);
save_preview_hero_desc.setText((isDead ? getString(R.string.rip_startscreen) : "") + playerName + ", " + displayInfo);
save_preview_holder.setVisibility(View.VISIBLE);
} else {
save_preview_holder.setVisibility(View.GONE);
}
}
private void continueGame(boolean createNewCharacter, int loadFromSlot, String name) {
final WorldSetup setup = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorldSetup();
setup.createNewCharacter = createNewCharacter;
setup.loadFromSlot = loadFromSlot;
setup.newHeroName = name;
startActivity(new Intent(getActivity(), LoadingActivity.class));
}
private void comfirmNewGame() {
// new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.AndorsTrailStyle_Dialog))
// .setTitle(R.string.startscreen_newgame)
// .setMessage(R.string.startscreen_newgame_confirm)
// .setIcon(android.R.drawable.ic_delete)
// .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// //continueGame(true);
//// hasExistingGame = false;
//// setButtonState(null, null, 0);
// createNewGame();
// }
// })
// .setNegativeButton(android.R.string.cancel, null)
// .create().show();
//
//
final Dialog 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);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
createNewGame();
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
}
private static final String versionCheck = "lastversion";
private boolean isNewVersion() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
int lastversion = s.getInt(versionCheck, 0);
if (lastversion >= AndorsTrailApplication.CURRENT_VERSION) return false;
return true;
}
private void setCurrentVersionForVersionCheck() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
Editor e = s.edit();
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 boolean wasImportOrExport = data.getBooleanExtra("import_export", false);
final int slot = data.getIntExtra("slot", 1);
if (wasImportOrExport) {
if(slot == LoadSaveActivity.SLOT_NUMBER_EXPORT_SAVEGAMES)
Toast.makeText(getActivity(),R.string.loadsave_export_save_successfull, Toast.LENGTH_LONG).show();
else if(slot == LoadSaveActivity.SLOT_NUMBER_IMPORT_SAVEGAMES)
Toast.makeText(getActivity(),R.string.loadsave_import_save_successfull, Toast.LENGTH_LONG).show();
else if(slot == LoadSaveActivity.SLOT_NUMBER_IMPORT_WORLDMAP)
Toast.makeText(getActivity(),R.string.loadsave_import_worldmap_successfull, Toast.LENGTH_LONG).show();
break;
}
continueGame(false, slot, null);
break;
case INTENTREQUEST_PREFERENCES:
updatePreferences(true);
break;
}
}
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();
}
public interface OnNewGameRequestedListener {
public void onNewGameRequested();
}
private OnNewGameRequestedListener listener = null;
private void createNewGame() {
if (listener != null) {
listener.onNewGameRequested();
}
}
}

View File

@@ -1,333 +0,0 @@
package com.gpl.rpg.AndorsTrail.controller;
import android.content.Context;
import android.content.Intent;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.L;
public final class InputController implements OnClickListener, OnLongClickListener{
private final ControllerContext controllers;
private final WorldContext world;
private final Coord lastTouchPosition_tileCoords = new Coord();
private int lastTouchPosition_dx = 0;
private int lastTouchPosition_dy = 0;
private long lastTouchEventTime = 0;
private boolean isDpadActive = false;
private int keyState_dx = 0;
private int keyState_dy = 0;
private boolean keyState_attack = false;
private boolean keyState_flee = false;
private boolean keyState_endturn = false;
final private int KEY_UNHANDLED = 0; // Default, for unhandled keycodes
final private int KEY_MOVE_UP = 1;
final private int KEY_MOVE_DOWN = 2;
final private int KEY_MOVE_LEFT = 3;
final private int KEY_MOVE_RIGHT = 4;
final private int KEY_MOVE_UP_LEFT = 5;
final private int KEY_MOVE_UP_RIGHT = 6;
final private int KEY_MOVE_DOWN_LEFT = 7;
final private int KEY_MOVE_DOWN_RIGHT = 8;
final private int KEY_ATTACK = 9;
final private int KEY_FLEE = 10;
final private int KEY_END_TURN = 11;
final private int KEY_HERO_INFO = 12;
final private int KEY_TOOLBOX = 13;
private SparseIntArray keyMap = new SparseIntArray(); // Android keycode to internal key event mapping. TODO: Configure via preferences
public InputController(ControllerContext controllers, WorldContext world) {
this.controllers = controllers;
this.world = world;
initializeKeyMap();
}
/* New keyboard handler. Both Key Down and Key Up events handled here to allow conditional behaviours.
On 4-way dpad controllers, cursor keys, and WASD, diagonals are generated by chording two keys.
Single-key diagonals are supported on numeric keypad and 8-way dpads (not seen/tested in the wild).
Because two-key combos initially generate a ordinal movement (one key comes in first), which can
be dangerous in tight spaces, modifiers are provided to "lock" the input until both keys are down.
TODO: Use delay timer to enable chorded diagonals on first move without locking kludge?
*/
// Map key codes to spectic internal actions
// TODO: Move mapping out of code to JSON/XML file, or maybe player prefs
private void initializeKeyMap() {
int key;
// Keys mapping to UP
key = KEY_MOVE_UP;
keyMap.put(KeyEvent.KEYCODE_DPAD_UP, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_8, key);
keyMap.put(KeyEvent.KEYCODE_8, key);
keyMap.put(KeyEvent.KEYCODE_W, key);
// Keys mapping to DOWN
key = KEY_MOVE_DOWN;
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_2, key);
keyMap.put(KeyEvent.KEYCODE_2, key);
keyMap.put(KeyEvent.KEYCODE_S, key);
// Keys mapping to LEFT
key = KEY_MOVE_LEFT;
keyMap.put(KeyEvent.KEYCODE_DPAD_LEFT, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_4, key);
keyMap.put(KeyEvent.KEYCODE_4, key);
keyMap.put(KeyEvent.KEYCODE_A, key);
// Keys mapping to RIGHT
key = KEY_MOVE_RIGHT;
keyMap.put(KeyEvent.KEYCODE_DPAD_RIGHT, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_6, key);
keyMap.put(KeyEvent.KEYCODE_6, key);
keyMap.put(KeyEvent.KEYCODE_D, key);
// Keys mapping to UP_LEFT
key = KEY_MOVE_UP_LEFT;
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);
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);
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);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_3, key);
keyMap.put(KeyEvent.KEYCODE_3, key);
keyMap.put(KeyEvent.KEYCODE_PAGE_DOWN, key);
// Keys mapping to ATTACK
key = KEY_ATTACK;
keyMap.put(KeyEvent.KEYCODE_DPAD_CENTER, key);
keyMap.put(KeyEvent.KEYCODE_BUTTON_A, key);
keyMap.put(KeyEvent.KEYCODE_SPACE, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_5, key);
// Keys mapping to FLEE
key = KEY_FLEE;
keyMap.put(KeyEvent.KEYCODE_BUTTON_X, key);
keyMap.put(KeyEvent.KEYCODE_F, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_ENTER, key);
keyMap.put(KeyEvent.KEYCODE_ENTER, key);
// Keys mapping to END_TURN
key = KEY_END_TURN;
keyMap.put(KeyEvent.KEYCODE_BUTTON_Y, key);
keyMap.put(KeyEvent.KEYCODE_E, key);
keyMap.put(KeyEvent.KEYCODE_FORWARD_DEL, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_DOT, key);
// Keys mapping to HERO_INFO
key = KEY_HERO_INFO;
//keyMap.put(KeyEvent.KEYCODE_BUTTON_SELECT, key);
keyMap.put(KeyEvent.KEYCODE_BUTTON_L1, key);
keyMap.put(KeyEvent.KEYCODE_NUM_LOCK, key);
keyMap.put(KeyEvent.KEYCODE_C, key);
// Keys mapping to TOOLBOX
key = KEY_TOOLBOX;
keyMap.put(KeyEvent.KEYCODE_BUTTON_R1, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, key);
keyMap.put(KeyEvent.KEYCODE_B, key);
}
// Generate game actions based on mapped keys
public boolean onKeyboardAction(Context context, KeyEvent event, boolean acceptInput) {
//L.log("onKeyboardAction(): Processing action " + event.getAction() + " for keyCode " + event.getKeyCode());
if (event.getAction() != KeyEvent.ACTION_DOWN && event.getAction() != KeyEvent.ACTION_UP) return false; // don't handle other actions
boolean keydown = (event.getAction() == KeyEvent.ACTION_DOWN);
boolean inihbit = (keyState_attack || keyState_flee); // used to inhibit movement if an action key is held down
switch (keyMap.get(event.getKeyCode())) {
// Ordinal directional keys - only modify one direction register; registers are combined when
// keys used simultaneously to create synthetic diagonals
case KEY_MOVE_UP:
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN:
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_LEFT:
keyState_dx = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_RIGHT:
keyState_dx = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
// Diagonal directional keys. Modify both direction registers, can't be combined
// TODO: store individual key position to allow combinations. May not be worth the trouble.
case KEY_MOVE_UP_LEFT:
keyState_dx = keydown ? -1 : 0;
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_UP_RIGHT:
keyState_dx = keydown ? 1 : 0;
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN_LEFT:
keyState_dx = keydown ? -1 : 0;
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN_RIGHT:
keyState_dx = keydown ? 1 : 0;
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
// Special key handling below - some combat/movement stuff done here because it's too
// specific for logic in onRelativeMovement
// "Attack" shortcut - freeze movement to allow chorded direction when key is released.
// if in combat, executes an attack on key release
case KEY_ATTACK:
if (keydown && !keyState_attack) { // key pressed - pause any movement
if(!world.model.uiSelections.isInCombat) controllers.movementController.stopMovement();
} else if (!keydown && keyState_attack) { // key released - execute attack / move in direction
if (acceptInput) onRelativeMovement(keyState_dx, keyState_dy);
}
keyState_attack = keydown;
break;
// "Flee" shortcut. Intitiates flee when pressed. If a direction is held, moves in chosen direction when released
case KEY_FLEE:
if (world.model.uiSelections.isInCombat) {
if (keydown && !keyState_flee) { // button pressed - set flee; movement locked while pressed
if(acceptInput) controllers.combatController.startFlee();
} else if (!keydown && keyState_flee) { // button released - move flee direction, if held
// We need to do a special call because the movement key may already be down, and if the device
// doesn't generate repeat keystrokes, this handler won't get another event
if ((keyState_dx != 0 || keyState_dy != 0) && allowInputInterval()) {
if(acceptInput) controllers.combatController.executeMoveAttack(keyState_dx, keyState_dy);
}
}
}
keyState_flee = keydown;
break;
// "End Turn" shortcut. Flag prevents repeated end turn if key is held down.
case KEY_END_TURN:
if (acceptInput && keydown && !keyState_endturn) {
if (world.model.uiSelections.isInCombat) controllers.combatController.endPlayerTurn();
}
keyState_endturn = keydown;
break;
// "Hero Info" screen shortcut. New activity takes focus, so we don't need to worry about repeats.
case KEY_HERO_INFO:
if (acceptInput && keydown) context.startActivity(new Intent(context, HeroinfoActivity.class));
break;
case KEY_TOOLBOX:
// ??? ToolboxView toolboxview = context.getApplicationContext(). findViewById(R.id.main_toolboxview);
break;
case KEY_UNHANDLED: // Unhandled keycode
return false;
default: // unhandled keymap code entry (should not happen)
L.log("onKeyboardAction(): Unhandled keyMap code constant " + keyMap.get(event.getKeyCode()) + " for keyCode " + event.getKeyCode());
return false;
}
return true;
}
public void onRelativeMovement(int dx, int dy) {
//L.log("onRelativeMovement(): dx=" + dx + " dy=" + dy + " combat: " + world.model.uiSelections.isInCombat);
if (world.model.uiSelections.isInCombat) {
if (allowInputInterval()) controllers.combatController.executeMoveAttack(dx, dy);
} else if (dx == 0 && dy == 0) {
controllers.movementController.stopMovement();
} else {
controllers.movementController.startMovement(dx, dy, null);
}
}
public void onKeyboardCancel() {
controllers.movementController.stopMovement();
}
@Override
public void onClick(View arg0) {
if (!world.model.uiSelections.isInCombat) return;
onRelativeMovement(lastTouchPosition_dx, lastTouchPosition_dy);
}
@Override
public boolean onLongClick(View arg0) {
if (world.model.uiSelections.isInCombat) {
//TODO: Should be able to mark positions far away (mapwalk / ranged combat)
if (lastTouchPosition_dx == 0 && lastTouchPosition_dy == 0) return false;
if (Math.abs(lastTouchPosition_dx) > 1) return false;
if (Math.abs(lastTouchPosition_dy) > 1) return false;
controllers.combatController.setCombatSelection(lastTouchPosition_tileCoords);
return true;
}
return false;
}
private boolean allowInputInterval() {
final long now = System.currentTimeMillis();
if ((now - lastTouchEventTime) < Constants.MINIMUM_INPUT_INTERVAL) return false;
lastTouchEventTime = now;
return true;
}
public void setDpadActive(boolean isDpadActive) {
this.isDpadActive = isDpadActive;
}
public void onTouchCancel() {
controllers.movementController.stopMovement();
}
public boolean onTouchedTile(int tile_x, int tile_y) {
lastTouchPosition_tileCoords.set(tile_x, tile_y);
lastTouchPosition_dx = tile_x - world.model.player.position.x;
lastTouchPosition_dy = tile_y - world.model.player.position.y;
if (world.model.uiSelections.isInCombat || isDpadActive) return false;
controllers.movementController.startMovement(lastTouchPosition_dx, lastTouchPosition_dy, lastTouchPosition_tileCoords);
return true;
}
}

View File

@@ -1,11 +0,0 @@
package com.gpl.rpg.AndorsTrail.model;
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
public final class MapBundle {
public PredefinedMap map;
public LayeredTileMap tileMap;
public TileCollection tiles;
}

View File

@@ -1,391 +0,0 @@
package com.gpl.rpg.AndorsTrail.savegames;
import java.io.ByteArrayOutputStream;
import java.io.Console;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.content.res.Resources;
import android.os.SystemClock;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.L;
public final class Savegames {
public static final int SLOT_QUICKSAVE = 0;
public static final long DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED = -1;
private static long lastBackup = 0;
public static enum LoadSavegameResult {
success, unknownError, savegameIsFromAFutureVersion, cheatingDetected
}
public static boolean saveWorld(WorldContext world, Context androidContext, int slot) {
try {
final String displayInfo = androidContext.getString(R.string.savegame_currenthero_displayinfo, world.model.player.getLevel(), world.model.player.getTotalExperience(), world.model.player.getGold());
if (slot != SLOT_QUICKSAVE && !world.model.statistics.hasUnlimitedSaves()) {
world.model.player.savedVersion++;
}
String id = world.model.player.id;
long savedVersion = world.model.player.savedVersion;
// Create the savegame in a temporary memorystream first to ensure that the savegame can
// be created correctly. We don't want to trash the user's file unneccessarily if there is an error.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
saveWorld(world, bos, displayInfo);
byte[] savegame = bos.toByteArray();
bos.close();
FileOutputStream fos = getOutputFile(androidContext, slot);
fos.write(savegame);
fos.close();
if (!world.model.statistics.hasUnlimitedSaves()) {
if (slot != SLOT_QUICKSAVE) {
androidContext.deleteFile(Constants.FILENAME_SAVEGAME_QUICKSAVE);
writeCheatCheck(androidContext, savedVersion, id);
} else if (SystemClock.uptimeMillis() > lastBackup + 120000) {
writeBackup(androidContext, savegame, id);
lastBackup = SystemClock.uptimeMillis();
}
}
return true;
} catch (IOException e) {
L.log("Error saving world: " + e.toString());
return false;
}
}
private static void writeBackup(Context androidContext, byte[] savegame, String playerId) throws IOException {
File cheatDetectionFolder = AndroidStorage.getStorageDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
ensureDirExists(cheatDetectionFolder);
File backupFile = new File(cheatDetectionFolder, playerId + "X");
FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
fileOutputStream.write(savegame);
fileOutputStream.close();
}
public static LoadSavegameResult loadWorld(WorldContext world, ControllerContext controllers, Context androidContext, int slot) {
try {
FileHeader fh = quickload(androidContext, slot);
if (fh == null) {
return LoadSavegameResult.unknownError;
}
if (!fh.hasUnlimitedSaves && slot != SLOT_QUICKSAVE && triedToCheat(androidContext, fh)) {
return LoadSavegameResult.cheatingDetected;
}
FileInputStream fos = getInputFile(androidContext, slot);
LoadSavegameResult result = loadWorld(androidContext.getResources(), world, controllers, fos, fh);
fos.close();
if (result == LoadSavegameResult.success && slot != SLOT_QUICKSAVE && !world.model.statistics.hasUnlimitedSaves()) {
// save to the quicksave slot before deleting the file
if (!saveWorld(world, androidContext, SLOT_QUICKSAVE)) {
return LoadSavegameResult.unknownError;
}
getSlotFile(slot, androidContext).delete();
writeCheatCheck(androidContext, DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED, fh.playerId);
}
return result;
} catch (IOException e) {
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
L.log("Error loading world: " + e.toString());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
L.log("Load error: " + sw.toString());
}
return LoadSavegameResult.unknownError;
}
}
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 (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
L.log("Internal cheatcheck file savedVersion: " + cheatDetection.savedVersion);
}
dataInputStream.close();
fileInputStream.close();
}
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);
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 {
DataOutputStream dest = new DataOutputStream(outStream);
FileHeader.writeToParcel(dest, world.model.player.getName(),
displayInfo, world.model.player.iconID,
world.model.statistics.isDead(),
world.model.statistics.hasUnlimitedSaves(),
world.model.player.id,
world.model.player.savedVersion);
world.maps.writeToParcel(dest, world);
world.model.writeToParcel(dest);
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;
world.maps.readFromParcel(src, world, controllers, header.fileversion);
world.model = new ModelContainer(src, world, controllers, header.fileversion);
src.close();
if (header.fileversion < 45) {
LegacySavegamesContentAdaptations.adaptToNewContentForVersion45(world, controllers, res);
}
onWorldLoaded(res, world, controllers);
return LoadSavegameResult.success;
}
private static void onWorldLoaded(Resources res, WorldContext world, ControllerContext controllers) {
controllers.actorStatsController.recalculatePlayerStats(world.model.player);
controllers.mapController.resetMapsNotRecentlyVisited();
controllers.movementController.prepareMapAsCurrentMap(world.model.currentMaps.map, res, false);
controllers.gameRoundController.resetRoundTimers();
}
public static FileHeader quickload(Context androidContext, int slot) {
try {
if (slot != SLOT_QUICKSAVE) {
File f = getSlotFile(slot, androidContext);
if (!f.exists()) return null;
}
FileInputStream fos = getInputFile(androidContext, slot);
DataInputStream src = new DataInputStream(fos);
final FileHeader header = new FileHeader(src, false);
src.close();
fos.close();
return header;
} catch (Exception e) {
return null;
}
}
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);
CheatDetection.writeToParcel(dataOutputStream, savedVersion);
dataOutputStream.close();
fileOutputStream.close();
}
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 new ArrayList<Integer>();
}
}
private static final class CheatDetection {
public final int fileversion;
public final long savedVersion;
// ====== PARCELABLE ===================================================================
public CheatDetection(DataInputStream src) throws IOException {
this.fileversion = src.readInt();
this.savedVersion = src.readLong();
}
public static void writeToParcel(DataOutputStream dest, long savedVersion) throws IOException {
dest.writeInt(AndorsTrailApplication.CURRENT_VERSION);
dest.writeLong(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;
}
// ====== 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;
}
if (fileversion >= 43) {
int id = src.readInt();
if (skipIcon || id > TileManager.LAST_HERO) {
this.iconID = TileManager.CHAR_HERO_0;
this.skipIcon = true;
} else {
this.iconID = id;
}
} else {
this.iconID = TileManager.CHAR_HERO_0;
}
if (fileversion >= 49) {
this.isDead = src.readBoolean();
this.hasUnlimitedSaves = src.readBoolean();
this.playerId = src.readUTF();
this.savedVersion = src.readLong();
} else {
this.isDead = false;
this.hasUnlimitedSaves = true;
this.playerId = "";
this.savedVersion = 0;
}
}
public static void writeToParcel(DataOutputStream dest, String playerName, String displayInfo, int iconID, boolean isDead, boolean hasUnlimitedSaves, String playerId, long savedVersion) throws IOException {
dest.writeInt(AndorsTrailApplication.CURRENT_VERSION);
dest.writeUTF(playerName);
dest.writeUTF(displayInfo);
dest.writeInt(iconID);
dest.writeBoolean(isDead);
dest.writeBoolean(hasUnlimitedSaves);
dest.writeUTF(playerId);
dest.writeLong(savedVersion);
}
}
}

View File

@@ -1,171 +0,0 @@
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.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v4.content.FileProvider;
import android.support.v4.provider.DocumentFile;
import android.webkit.MimeTypeMap;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public final class AndroidStorage {
public static File getStorageDirectory(Context context, String name) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return context.getExternalFilesDir(name);
} 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 internalSaveGameDirectory = getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
if (externalSaveGameDirectory.exists()
&& externalSaveGameDirectory.isDirectory()
&& externalSaveGameDirectory.listFiles().length > 0
&& (
!internalSaveGameDirectory.exists()
|| internalSaveGameDirectory.isDirectory() && internalSaveGameDirectory.listFiles().length < 2)
) {
ret = true;
}
return ret;
}
public static boolean migrateToInternalStorage(Context context) {
try {
copy(new File(Environment.getExternalStorageDirectory(), 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));
} catch (IOException e) {
L.log("Error migrating data: " + e.toString());
return false;
}
return true;
}
private static void copy(File sourceLocation, File targetLocation) throws IOException {
if (!sourceLocation.exists()) {
return;
}
if (sourceLocation.isDirectory()) {
copyDirectory(sourceLocation, targetLocation);
} else {
copyFile(sourceLocation, targetLocation);
}
}
private static void copyDirectory(File source, File target) throws IOException {
if (!target.exists()) {
target.mkdir();
}
for (String f : source.list()) {
copy(new File(source, f), new File(target, f));
}
}
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);
}
}
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);
}
}
/**
* Gets the MIME-Type for a file.<p/>
* Fallback value is '* / *' (without spaces) <p/>
* Mostly copied together from: <a href="https://stackoverflow.com/q/8589645/17292289">StackOverflow</a>
*/
@NonNull
public static String getMimeType(ContentResolver resolver, Uri uri) {
String type = null;
if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
type = resolver.getType(uri);
return type;
}
final String extension = MimeTypeMap.getFileExtensionFromUrl(uri.getPath());
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
}
if (type == null) {
type = "*/*"; // fallback type.
}
return type;
}
public static String getUrlForFile(Context context, File worldmap) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Uri uri = FileProvider.getUriForFile(context, "com.gpl.rpg.AndorsTrail_beta2.fileprovider", worldmap);
return uri.toString();
} else {
return "file://" + worldmap.getAbsolutePath();
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static Intent getNewOpenDirectoryIntent() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
return intent;
}
@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;
}
}

View File

@@ -1,188 +0,0 @@
package com.gpl.rpg.AndorsTrail.view;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.Rect;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.view.ContextThemeWrapper;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
public class CustomDialogFactory {
public static class CustomDialog extends Dialog {
public CustomDialog(Context context) {
super(context);
}
}
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) {
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 {
if (canDismiss) {
this.dismiss();
return true;
}
return false;
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
TextView title = (TextView) this.getWindow().getDecorView().findViewById(R.id.dialog_title);
if (title != null && title.getCompoundDrawables() != null && title.getCompoundDrawables()[0] != null) {
if (title.getCompoundDrawables()[0] instanceof AnimationDrawable) {
((AnimationDrawable) title.getCompoundDrawables()[0]).start();
}
}
}
};
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.custom_dialog_title_icon);
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
if (((AndorsTrailApplication) context.getApplicationContext()).getPreferences().fullscreen) {
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} 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);
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) {
titleView.setText(title);
titleView.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
titleView.setVisibility(View.VISIBLE);
} else {
titleView.setVisibility(View.GONE);
}
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);
if (desc != null) {
descView.setText(desc);
descHolder.setVisibility(View.VISIBLE);
descView.setVisibility(View.VISIBLE);
} else {
descHolder.setVisibility(View.GONE);
}
return dialog;
}
public static CustomDialog setContent(final CustomDialog dialog, View content) {
ViewGroup contentHolder = (ViewGroup) dialog.findViewById(R.id.dialog_content_container);
if (content != null) {
contentHolder.addView(content);
contentHolder.setVisibility(View.VISIBLE);
} else {
contentHolder.setVisibility(View.GONE);
}
return dialog;
}
public static Dialog addButton(final Dialog dialog, int textId, final OnClickListener listener) {
Button template = (Button) dialog.findViewById(R.id.dialog_template_button);
LayoutParams params = template.getLayoutParams();
ViewGroup buttonsHolder = (ViewGroup) dialog.findViewById(R.id.dialog_button_container);
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);
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) {
return CustomDialogFactory.addButton(dialog, textId, new OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
public static Dialog setDismissListener(Dialog dialog, OnDismissListener listener) {
dialog.setOnDismissListener(listener);
return dialog;
}
public static void show(Dialog dialog) {
dialog.findViewById(R.id.dialog_template_button).setVisibility(View.GONE);
dialog.show();
}
}

View File

@@ -1,30 +0,0 @@
package com.gpl.rpg.AndorsTrail.controller;
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
import org.junit.Test;
import static org.junit.Assert.*;
public class CombatControllerTest {
@Test
public void getAverageDamagePerHit() throws Exception {
Actor attacker = new Actor(null, false, false);
attacker.attackChance = 100;
attacker.damagePotential.set(5, 3);
Actor target = new Actor(null, false, false);
target.damageResistance = 3;
target.blockChance = 50;
float averageDamagePerHit = CombatController.getAverageDamagePerHit(attacker, target);
assertEquals(0.5, averageDamagePerHit, 0.01);
attacker.criticalSkill = 30;
attacker.criticalMultiplier = 2.5f;
averageDamagePerHit = CombatController.getAverageDamagePerHit(attacker, target);
assertEquals(1.038, averageDamagePerHit, 0.01);
}
}

View File

@@ -0,0 +1 @@
*.mo

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

0
AndorsTrail/assets/translation/createMo.sh Normal file → Executable file
View File

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

21792
AndorsTrail/assets/translation/fi.po Normal file → Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

21790
AndorsTrail/assets/translation/gl.po Normal file → Executable file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More