Compare commits

..

2 Commits

Author SHA1 Message Date
OMGeeky
dc5ea97ddb Created Worlds 2022-11-11 16:23:28 +01:00
OMGeeky
74c19de010 Create worlds scripts 2022-11-11 16:20:06 +01:00
432 changed files with 16797 additions and 625378 deletions

View File

@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 31
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.gpl.rpg.AndorsTrail"
minSdkVersion 14
targetSdkVersion 31
targetSdkVersion 30
}
buildTypes {

View File

@@ -3,11 +3,15 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gpl.rpg.AndorsTrail"
android:versionCode="70"
android:versionName="0.8.5"
android:versionCode="67"
android:versionName="0.8.3dev"
android:installLocation="auto"
>
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="30"
/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
@@ -33,7 +37,6 @@
>
<activity
android:name="com.gpl.rpg.AndorsTrail.activity.StartScreenActivity"
android:exported="true"
android:clearTaskOnLaunch="true"
>
<intent-filter>

View File

@@ -28,11 +28,11 @@ public final class AndorsTrailApplication extends Application {
public static final boolean DEVELOPMENT_FASTSPEED = false;
public static final boolean DEVELOPMENT_VALIDATEDATA = false;
public static final boolean DEVELOPMENT_DEBUGMESSAGES = false;
public static final String CURRENT_VERSION_DISPLAY = "0.8.5";
public static final String CURRENT_VERSION_DISPLAY = "0.8.3dev";
public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*");
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED || !IS_RELEASE_VERSION;
public static final int DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION = 999;
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 71;
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 67;
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
private WorldContext world = new WorldContext();

View File

@@ -78,7 +78,7 @@ public final class AndorsTrailPreferences {
dest.dpadTransparency = Integer.parseInt(prefs.getString("dpadtransparency", Integer.toString(DPAD_TRANSPARENCY_50_PERCENT)));
dest.dpadMinimizeable = prefs.getBoolean("dpadMinimizeable", true);
dest.optimizedDrawing = prefs.getBoolean("optimized_drawing", false);
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", false);
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", true);
dest.enableUiAnimations = prefs.getBoolean("enableUiAnimations", true);
dest.displayOverwriteSavegame = Integer.parseInt(prefs.getString("display_overwrite_savegame", Integer.toString(CONFIRM_OVERWRITE_SAVEGAME_ALWAYS)));
dest.quickslotsPosition = Integer.parseInt(prefs.getString("quickslots_placement", Integer.toString(QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM)));

View File

@@ -134,9 +134,8 @@ public final class WorldSetup {
onSceneLoadedListener = null;
if (o == null) return;
if (loadResult == Savegames.LoadSavegameResult.success
|| loadResult == Savegames.LoadSavegameResult.editDetected) {
o.onSceneLoaded(loadResult);
if (loadResult == Savegames.LoadSavegameResult.success) {
o.onSceneLoaded();
} else {
o.onSceneLoadFailed(loadResult);
}
@@ -162,7 +161,7 @@ public final class WorldSetup {
public static interface OnSceneLoadedListener {
void onSceneLoaded(Savegames.LoadSavegameResult loadResult);
void onSceneLoaded();
void onSceneLoadFailed(Savegames.LoadSavegameResult loadResult);
}
public interface OnResourcesLoadedListener {

View File

@@ -11,7 +11,9 @@ 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;
@@ -120,7 +122,8 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
boolean hasSavegames = !Savegames.getUsedSavegameSlots(this).isEmpty();
exportSaves.setEnabled(hasSavegames);
} else {
}
else{
exportImportContainer.setVisibility(View.GONE);
}
}
@@ -130,17 +133,12 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
private static final int WRITE_EXTERNAL_STORAGE_REQUEST = 2;
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 (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);
if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@@ -154,15 +152,11 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
}
private void addSavegameSlotButtons(ViewGroup parent,
LayoutParams params,
List<Integer> usedSavegameSlots) {
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;
}
if (header == null) continue;
while (unused < slot) {
Button b = new Button(this);
@@ -186,76 +180,65 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
}
private void cancelLoadSaveActivity(int slot) {
private void cancelLoadSaveActivity(int slot){
completeLoadSaveActivity(slot, false);
}
private void completeLoadSaveActivity(int slot) {
completeLoadSaveActivity(slot, true);
}
private void completeLoadSaveActivity(int slot, boolean success) {
Intent i = new Intent();
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
slot = getFirstFreeSlot();
} else if (slot == SLOT_NUMBER_EXPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
|| slot == SLOT_NUMBER_IMPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
i.putExtra("import_export", true);
if (slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
if(slot == SLOT_NUMBER_IMPORT_WORLDMAP){
i.putExtra("import_worldmap", true);
}
if (slot == SLOT_NUMBER_IMPORT_SAVEGAMES) {
if(slot == SLOT_NUMBER_IMPORT_SAVEGAMES){
i.putExtra("import_savegames", true);
}
if (slot == SLOT_NUMBER_EXPORT_SAVEGAMES) {
if(slot == SLOT_NUMBER_EXPORT_SAVEGAMES){
i.putExtra("export", true);
}
} else if (slot < SLOT_NUMBER_FIRST_SLOT) {
} else if (slot < SLOT_NUMBER_FIRST_SLOT)
slot = SLOT_NUMBER_FIRST_SLOT;
}
i.putExtra("slot", slot);
if (success) {
setResult(Activity.RESULT_OK, i);
} else {
setResult(Activity.RESULT_CANCELED, i);
}
if(success) setResult(Activity.RESULT_OK, i);
else setResult(Activity.RESULT_CANCELED, i);
LoadSaveActivity.this.finish();
}
private int getFirstFreeSlot() {
int slot;
List<Integer> usedSlots = Savegames.getUsedSavegameSlots(this);
if (usedSlots.isEmpty()) {
if (usedSlots.isEmpty())
slot = SLOT_NUMBER_FIRST_SLOT;
} else {
slot = Collections.max(usedSlots) + 1;
}
else slot = Collections.max(usedSlots) + 1;
return slot;
}
private String getConfirmOverwriteQuestion(int slot) {
if (isLoading) {
if (isLoading)
return null;
}
return getConfirmOverwriteQuestionIgnoringLoading(slot);
}
private String getConfirmOverwriteQuestionIgnoringLoading(int slot) {
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT)
return null;//creating a new savegame
}
if (!Savegames.getSlotFile(slot, this).exists()) {
if (!Savegames.getSlotFile(slot, this).exists())
return null;//nothing in slot to overwrite
}
if (preferences.displayOverwriteSavegame
== AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_ALWAYS) {
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) {
@@ -264,14 +247,10 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
final String currentPlayerName = model.player.getName();
final FileHeader header = Savegames.quickload(this, slot);
if (header == null) {
return null;
}
if (header == null) return null;
final String savedPlayerName = header.playerName;
if (currentPlayerName.equals(savedPlayerName)) {
return null; //if the names match
}
if (currentPlayerName.equals(savedPlayerName)) return null; //if the names match
return getString(R.string.loadsave_save_overwrite_confirmation, savedPlayerName, currentPlayerName);
}
@@ -280,7 +259,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
public void onClick(View view) {
final int slot = (Integer) view.getTag();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
switch (slot) {
case SLOT_NUMBER_IMPORT_WORLDMAP:
clickImportWorldmap();
@@ -294,9 +273,8 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
}
if (!isLoading
&& slot != SLOT_NUMBER_CREATE_NEW_SLOT
&& AndorsTrailApplication.CURRENT_VERSION
== AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
&& slot != SLOT_NUMBER_CREATE_NEW_SLOT
&& AndorsTrailApplication.CURRENT_VERSION == AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
if (!isOverwriteTargetInIncompatibleVersion(slot)) {
saveOrOverwriteSavegame(slot);
}
@@ -310,7 +288,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
private void saveOrOverwriteSavegame(int slot) {
final String message = getConfirmOverwriteQuestion(slot);
if (message != null) {
showConfirmOverwriteQuestion(slot, message);
showConfirmoverwriteQuestion(slot, message);
} else {
completeLoadSaveActivity(slot);
}
@@ -318,11 +296,8 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
private boolean isOverwriteTargetInIncompatibleVersion(int slot) {
final FileHeader header = Savegames.quickload(this, slot);
if (header != null
&& header.fileversion != AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
final CustomDialog 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.");
if (header != null && header.fileversion != AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
final CustomDialog 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;
}
@@ -331,32 +306,28 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
//region Imports/Exports
//region Export
@RequiresApi(api = Build.VERSION_CODES.P)
private void exportSaveGames(Intent data) {
Uri uri = data.getData();
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this)
.getContentResolver();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this).getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context,
Constants.FILENAME_SAVEGAME_DIRECTORY);
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile source = DocumentFile.fromFile(storageDir);
DocumentFile target = DocumentFile.fromTreeUri(context, uri);
if (target == null) {
return;
}
File[] files = storageDir.listFiles();
if (files == null) {
showErrorExportingSaveGamesUnknown();
return;
}
DocumentFile[] files = source.listFiles();
boolean hasExistingFiles = false;
for (File file : files) {
for (DocumentFile file :
files) {
String fileName = file.getName();
if (fileName == null)
continue;
DocumentFile existingFile = target.findFile(fileName);
if (existingFile != null) {
@@ -368,70 +339,45 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
if (hasExistingFiles) {
showConfirmOverwriteByExportQuestion(resolver, target, files);
} else {
exportSaveGamesFolderContentToFolder(target, files);
exportSaveGamesFolderContentToFolder(resolver, target, files);
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void exportSaveGamesFolderContentToFolder(DocumentFile target, File[] files) {
private void exportSaveGamesFolderContentToFolder(ContentResolver resolver, DocumentFile target, DocumentFile[] files) {
DocumentFile[] sourceFiles = new DocumentFile[files.length];
File[] worldmapFiles = null;
DocumentFile[] worldmapFiles = null;
for (int i = 0; i < files.length; i++) {
File file = files[i];
DocumentFile file = files[i];
if (file.isFile()) {
sourceFiles[i] = DocumentFile.fromFile(file);
} else if (file.isDirectory() && Objects.equals(file.getName(),
Constants.FILENAME_WORLDMAP_DIRECTORY)) {
sourceFiles[i] = file;
} else if (file.isDirectory() && Objects.equals(file.getName(), Constants.FILENAME_WORLDMAP_DIRECTORY)) {
worldmapFiles = file.listFiles();
}
}
Context context = this;
File[] finalWorldmapFiles = worldmapFiles;
CopyFilesToExternalFolder(target, sourceFiles, context, finalWorldmapFiles);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void CopyFilesToExternalFolder(DocumentFile target,
DocumentFile[] sourceFiles,
Context context,
File[] finalWorldmapFiles) {
Context context =this;
DocumentFile[] finalWorldmapFiles = worldmapFiles;
AndroidStorage.copyDocumentFilesToDirAsync(sourceFiles,
context,
target,
getString(R.string.loadsave_exporting_savegames),
(success) -> {
if (success) {
CopyWorldmapFilesAsZip(target,
context,
finalWorldmapFiles);
} else {
completeLoadSaveActivity(
SLOT_NUMBER_EXPORT_SAVEGAMES,
false);
}
});
context,
target,
(sucess) -> {
if (sucess) {
DocumentFile worldmapFolder = target.createDirectory(Constants.FILENAME_WORLDMAP_DIRECTORY);
AndroidStorage.copyDocumentFilesToDirAsync(finalWorldmapFiles,
context,
worldmapFolder,
(sucessWorldmap) -> completeLoadSaveActivity(SLOT_NUMBER_EXPORT_SAVEGAMES, sucessWorldmap));
} else {
completeLoadSaveActivity(SLOT_NUMBER_EXPORT_SAVEGAMES, false);
}
});
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void CopyWorldmapFilesAsZip(DocumentFile target,
Context context,
File[] finalWorldmapFiles) {
AndroidStorage.createZipDocumentFileFromFilesAsync(finalWorldmapFiles,
context,
target,
Constants.FILENAME_WORLDMAP_DIRECTORY,
getString(R.string.loadsave_exporting_worldmap),
(successWorldmap) -> completeLoadSaveActivity(
SLOT_NUMBER_EXPORT_SAVEGAMES,
successWorldmap));
}
//endregion
@RequiresApi(api = Build.VERSION_CODES.P)
@RequiresApi(api = Build.VERSION_CODES.N)
private void importSaveGames(Intent data) {
Uri uri = data.getData();
ClipData uris = data.getClipData();
@@ -442,8 +388,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this)
.getContentResolver();
ContentResolver resolver = context.getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile appSavegameFolder = DocumentFile.fromFile(storageDir);
@@ -452,18 +397,14 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
if (uri != null) {
uriList.add(uri);
} else {
for (int i = 0; i < uris.getItemCount(); i++) {
for (int i = 0; i < uris.getItemCount(); i++)
uriList.add(uris.getItemAt(i).getUri());
}
}
importSaveGamesFromUris(context, resolver, appSavegameFolder, uriList);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void importSaveGamesFromUris(Context context,
ContentResolver resolver,
DocumentFile appSavegameFolder,
List<Uri> uriList) {
@RequiresApi(api = Build.VERSION_CODES.N)
private void importSaveGamesFromUris(Context context, ContentResolver resolver, DocumentFile appSavegameFolder, List<Uri> uriList) {
int count = uriList.size();
ArrayList<DocumentFile> alreadyExistingFiles = new ArrayList<>();
@@ -473,11 +414,10 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
Uri item = uriList.get(i);
DocumentFile itemFile = DocumentFile.fromSingleUri(context, item);
boolean fileAlreadyExists = getExistsSavegameInOwnFiles(itemFile, appSavegameFolder);
if (fileAlreadyExists) {
if (fileAlreadyExists)
alreadyExistingFiles.add(itemFile);
} else {
else
newFiles.add(itemFile);
}
}
if (alreadyExistingFiles.size() > 0) {
@@ -487,10 +427,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void importSaveGames(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> saveFiles) {
private void importSaveGames(ContentResolver resolver, DocumentFile appSavegameFolder, List<DocumentFile> saveFiles) {
int size = saveFiles.size();
DocumentFile[] sources = new DocumentFile[size];
DocumentFile[] targets = new DocumentFile[size];
@@ -520,18 +457,21 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
AndroidStorage.copyDocumentFilesFromToAsync(sources,
this,
targets,
getString(R.string.loadsave_importing_savegames),
(sucess) -> completeLoadSaveActivity(
SLOT_NUMBER_IMPORT_SAVEGAMES,
sucess));
this,
targets,
(sucess) -> completeLoadSaveActivity(SLOT_NUMBER_IMPORT_SAVEGAMES, sucess));
}
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) {
if (savegameFile == null)
return false;
}
DocumentFile foundFile = appSavegameFolder.findFile(Objects.requireNonNull(savegameFile.getName()));
return foundFile != null && foundFile.exists();
@@ -539,6 +479,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
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());
@@ -548,16 +489,32 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
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;
}
@@ -565,87 +522,72 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
private void importWorldmap(Intent data) {
Uri uri = data.getData();
Context context = AndorsTrailApplication.getApplicationFromActivity(this).getApplicationContext();
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this).getContentResolver();
DocumentFile chosenZip = DocumentFile.fromSingleUri(context, uri);
if (chosenZip == null || !chosenZip.isFile()) {
showErrorImportingWorldmapWrongDirectory();
return;
}
String chosenZipName = chosenZip.getName();
if (!chosenZipName.startsWith(Constants.FILENAME_WORLDMAP_DIRECTORY)) {
showErrorImportingWorldmapWrongDirectory();
return;
}
File ownWorldmapFolder = getOwnWorldmapFolder(context);
AndroidStorage.unzipDocumentFileToDirectoryAsync(chosenZip,
this,
ownWorldmapFolder,
false,
getString(R.string.loadsave_importing_worldmap),
(success) -> completeLoadSaveActivity(
SLOT_NUMBER_IMPORT_WORLDMAP,
success));
}
private File getOwnWorldmapFolder(Context context) {
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
File ownWorldmapFolder = null;
for (File f : storageDir.listFiles()) {
if (f.getName().equals(Constants.FILENAME_WORLDMAP_DIRECTORY)) {
ownWorldmapFolder = f;
break;
}
}
DocumentFile storageFolder = DocumentFile.fromFile(storageDir);
DocumentFile ownWorldmapFolder = storageFolder.findFile(Constants.FILENAME_WORLDMAP_DIRECTORY);
if (ownWorldmapFolder == null) {
ownWorldmapFolder = new File(storageDir, Constants.FILENAME_WORLDMAP_DIRECTORY);
ownWorldmapFolder.mkdir();
ownWorldmapFolder = storageFolder.createDirectory(Constants.FILENAME_WORLDMAP_DIRECTORY);
}
return ownWorldmapFolder;
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;
}
AndroidStorage.copyDocumentFilesToDirAsync(chosenFolder.listFiles(),
this,
ownWorldmapFolder,
(success) -> completeLoadSaveActivity(SLOT_NUMBER_IMPORT_WORLDMAP, success));
}
@RequiresApi(api = Build.VERSION_CODES.P)
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickExportSaveGames() {
showStartExportInfo(view -> startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(),
-SLOT_NUMBER_EXPORT_SAVEGAMES));
startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(), -SLOT_NUMBER_EXPORT_SAVEGAMES);
}
@RequiresApi(api = Build.VERSION_CODES.P)
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickImportSaveGames() {
showStartImportSavesInfo(view -> startActivityForResult(AndroidStorage.getNewSelectMultipleSavegameFilesIntent(),
-SLOT_NUMBER_IMPORT_SAVEGAMES));
startActivityForResult(AndroidStorage.getNewSelectMultipleSavegameFilesIntent(), -SLOT_NUMBER_IMPORT_SAVEGAMES);
}
@RequiresApi(api = Build.VERSION_CODES.P)
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void clickImportWorldmap() {
showStartImportWorldmapInfo(view -> startActivityForResult(AndroidStorage.getNewSelectZipIntent(),
-SLOT_NUMBER_IMPORT_WORLDMAP));
startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(), -SLOT_NUMBER_IMPORT_WORLDMAP);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showConfirmOverwriteByExportQuestion(ContentResolver resolver,
DocumentFile targetFolder,
File[] files) {
private void showConfirmOverwriteByExportQuestion(ContentResolver resolver, DocumentFile targetFolder, DocumentFile[] files) {
final CustomDialog 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);
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(targetFolder, files));
CustomDialogFactory.addButton(d, android.R.string.yes, v -> exportSaveGamesFolderContentToFolder(resolver, targetFolder, files));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
@RequiresApi(api = Build.VERSION_CODES.N)
private void showConfirmOverwriteByImportQuestion(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> alreadyExistingFiles,
@@ -659,9 +601,9 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
Context context = AndorsTrailApplication.getApplicationFromActivity(this).getApplicationContext();
ArrayList<CustomDialog> dialogs = new ArrayList<>(amount);
ArrayList<CustomDialog> dialogs = new ArrayList<CustomDialog>(amount) ;
for (int i = 0; i < amount; i++) {
for (int i = 0; i < amount ; i++) {
DocumentFile alreadyExistingFile = alreadyExistingFiles.get(i);
int slot = getSlotFromSavegameFileName(alreadyExistingFile.getName());
FileHeader existingFileHeader = Savegames.quickload(context, slot);
@@ -678,26 +620,20 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
}
StringBuilder messageSb = new StringBuilder();
String existingFileDescription = getString(R.string.loadsave_import_existing_description,
Integer.toString(slot),
existingFileHeader.describe());
String importedFileDescription = getString(R.string.loadsave_import_imported_description,
Integer.toString(slot),
importedFileHeader.describe());
messageSb.append(getString(R.string.loadsave_import_file_exists_question,
existingFileDescription,
importedFileDescription));
String existingFileDescription = getString(R.string.loadsave_import_existing_description, slot, existingFileHeader.describe());
String importedFileDescription = getString(R.string.loadsave_import_imported_description, slot, importedFileHeader.describe());
messageSb.append(getString(R.string.loadsave_import_file_exists_question, existingFileDescription, importedFileDescription));
String m = messageSb.toString();
CustomDialog dialog = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
m,
null,
true,
false,
true);
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
m,
null,
true,
false,
true);
CustomDialogFactory.addButton(dialog, R.string.loadsave_import_option_keep_existing, v -> {
//do nothing
@@ -710,8 +646,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
});
CustomDialogFactory.addButton(dialog, R.string.loadsave_import_option_add_as_new, v -> {
newFiles.add(null);//add a null element as marker to know later if the next file
// should be imported as new or overwrite the existing one
newFiles.add(null);//add a null element as marker to know later if the next file should be imported as new or overwrite the existing one
newFiles.add(alreadyExistingFile);
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
});
@@ -727,15 +662,13 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void GoToNextConflictOrFinish(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> newFiles,
ArrayList<CustomDialog> dialogs) {
if (dialogs.stream().count() > 0) {
@RequiresApi(api = Build.VERSION_CODES.N)
private void GoToNextConflictOrFinish(ContentResolver resolver, DocumentFile appSavegameFolder, List<DocumentFile> newFiles, ArrayList<CustomDialog> dialogs) {
if(dialogs.stream().count() > 0){
CustomDialog d = dialogs.remove(0);
CustomDialogFactory.show(d);
} else {
}
else{
importSaveGames(resolver, appSavegameFolder, newFiles);
}
}
@@ -744,9 +677,8 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {
if (resultCode != Activity.RESULT_OK)
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
switch (-requestCode) {
@@ -781,90 +713,48 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
//region show Dialogs
//region Import/Export
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartExportInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_export),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_export_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartImportSavesInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_import_save),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_import_save_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartImportWorldmapInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_import_worldmap),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_import_worldmap_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
private void showErrorImportingWorldmapWrongDirectory() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_import_worldmap_unsuccessfull),
getString(R.string.loadsave_import_worldmap_wrong_file));
getString(R.string.loadsave_import_worldmap_unsuccessfull),
getString(R.string.loadsave_import_worldmap_wrong_directory));
CustomDialogFactory.show(d);
}
private void showErrorExportingSaveGamesUnknown() {
private void showErrorImportingSaveGameUnknown() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_export_unsuccessfull),
getString(R.string.loadsave_export_error_unknown));
getString(R.string.loadsave_import_save_unsuccessfull),
getString(R.string.loadsave_import_save_error_unknown));
CustomDialogFactory.show(d);
}
//endregion
private void showErrorLoadingEmptySlot() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.startscreen_error_loading_game),
getString(R.string.startscreen_error_loading_empty_slot));
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 CustomDialog 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);
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);
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 CustomDialog d = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
message,
null,
true);
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);

View File

@@ -141,18 +141,13 @@ public final class LoadingActivity extends AndorsTrailBaseActivity implements On
@Override
public void onSceneLoaded(Savegames.LoadSavegameResult loadResult) {
public void onSceneLoaded() {
synchronized (semaphore) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
if (loadResult == Savegames.LoadSavegameResult.editDetected) {
showLoadingWarnDialog(R.string.dialog_loading_warning_edit);
}else{
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
@Override
@@ -170,19 +165,6 @@ public final class LoadingActivity extends AndorsTrailBaseActivity implements On
}
}
private void showLoadingWarnDialog(int messageResourceID) {
final CustomDialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_warning_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
startActivity(new Intent(LoadingActivity.this, MainActivity.class));
LoadingActivity.this.finish();
}
});
CustomDialogFactory.show(d);
}
private void showLoadingFailedDialog(int messageResourceID) {
final CustomDialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);

View File

@@ -1,8 +1,5 @@
package com.gpl.rpg.AndorsTrail.context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionTypeCollection;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
@@ -15,10 +12,6 @@ import com.gpl.rpg.AndorsTrail.model.quest.QuestCollection;
import com.gpl.rpg.AndorsTrail.resource.ConversationLoader;
import com.gpl.rpg.AndorsTrail.resource.VisualEffectCollection;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class WorldContext {
//Objectcollections
@@ -69,13 +62,4 @@ public final class WorldContext {
public void resetForNewGame() {
maps.resetForNewGame();
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public String createHash() throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("MD5");
this.maps.createHash(digest);
this.model.createHash(digest);
byte[] hash = digest.digest();
return ByteUtils.toHexString(hash);
}
}

View File

@@ -7,7 +7,7 @@ import com.gpl.rpg.AndorsTrail.util.ConstRange;
import com.gpl.rpg.AndorsTrail.util.Range;
public final class Constants {
public static final int PERCENT_EXP_LOST_WHEN_DIED = 20;
public static final int PERCENT_EXP_LOST_WHEN_DIED = 30;
public static final int LEVELUP_EFFECT_HEALTH = 5;
public static final int LEVELUP_EFFECT_ATK_CH = 5;
public static final int LEVELUP_EFFECT_ATK_DMG = 1;

View File

@@ -3,7 +3,6 @@ package com.gpl.rpg.AndorsTrail.model;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -13,8 +12,6 @@ import java.util.Map.Entry;
import java.util.Set;
import android.content.res.Resources;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
@@ -22,7 +19,6 @@ import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.quest.Quest;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.HashMapHelper;
public final class GameStatistics {
@@ -218,21 +214,4 @@ public final class GameStatistics {
dest.writeInt(startLives);
dest.writeBoolean(unlimitedSaves);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(deaths));
for (Entry<String, Integer> e : killedMonstersByTypeID.entrySet()) {
digest.update(ByteUtils.toBytes(e.getKey()));
digest.update(ByteUtils.toBytes(e.getValue()));
}
for (Entry<String, Integer> e : usedItems.entrySet()) {
digest.update(ByteUtils.toBytes(e.getKey()));
digest.update(ByteUtils.toBytes(e.getValue()));
}
digest.update(ByteUtils.toBytes(spentGold));
digest.update(ByteUtils.toBytes(startLives));
digest.update(ByteUtils.toBytes(unlimitedSaves));
}
}

View File

@@ -3,10 +3,8 @@ package com.gpl.rpg.AndorsTrail.model;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
public final class InterfaceData {
@@ -53,12 +51,4 @@ public final class InterfaceData {
}
dest.writeUTF(selectedTabHeroInfo);
}
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(isMainActivityVisible));
digest.update(ByteUtils.toBytes(isInCombat));
if(selectedPosition != null){
selectedPosition.createHash(digest);
}
}
}

View File

@@ -1,17 +1,12 @@
package com.gpl.rpg.AndorsTrail.model;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
public final class ModelContainer {
@@ -54,14 +49,4 @@ public final class ModelContainer {
statistics.writeToParcel(dest);
worldData.writeToParcel(dest);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
player.createHash(digest);
digest.update(ByteUtils.toBytes(currentMaps.map.name));
uiSelections.createHash(digest);
statistics.createHash(digest);
worldData.createHash(digest);
}
}

View File

@@ -1,14 +1,8 @@
package com.gpl.rpg.AndorsTrail.model;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
@@ -62,13 +56,4 @@ public final class WorldData {
dest.writeLong(e.getValue());
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(worldTime));
for (Map.Entry<String, Long> e: timers.entrySet() ) {
digest.update(ByteUtils.toBytes(e.getKey()));
digest.update(ByteUtils.toBytes(e.getValue()));
}
}
}

View File

@@ -1,15 +1,10 @@
package com.gpl.rpg.AndorsTrail.model.ability;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
public final class ActorCondition {
public static final int MAGNITUDE_REMOVE_ALL = -99;
@@ -50,12 +45,4 @@ public final class ActorCondition {
dest.writeInt(magnitude);
dest.writeInt(duration);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(conditionType.conditionTypeID));
digest.update(ByteUtils.toBytes(magnitude));
digest.update(ByteUtils.toBytes(duration));
}
}

View File

@@ -83,7 +83,7 @@ public final class SkillCollection {
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_CHANCE_PERCENT = 30;
public static final int PER_SKILLPOINT_INCREASE_MAGICFINDER_CHANCE_PERCENT = 50;
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_QUANTITY_PERCENT = 50;
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 10;
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 5;
public static final int PER_SKILLPOINT_INCREASE_CLEAVE_AP = 3;
public static final int PER_SKILLPOINT_INCREASE_EATER_HEALTH = 1;
public static final int PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH = 1;

View File

@@ -1,12 +1,8 @@
package com.gpl.rpg.AndorsTrail.model.actor;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
@@ -17,7 +13,6 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea;
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForMonster;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.Range;
@@ -198,28 +193,4 @@ public final class Monster extends Actor {
dest.writeBoolean(false);
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(getMonsterTypeID()));
digest.update(ByteUtils.toBytes(attackCost));
digest.update(ByteUtils.toBytes(attackChance));
digest.update(ByteUtils.toBytes(criticalSkill));
digest.update(ByteUtils.toBytes(criticalMultiplier));
damagePotential.createHash(digest);
digest.update(ByteUtils.toBytes(blockChance));
digest.update(ByteUtils.toBytes(damageResistance));
ap.createHash(digest);
health.createHash(digest);
position.createHash(digest);
for (ActorCondition c: conditions){
c.createHash(digest);
}
digest.update(ByteUtils.toBytes(moveCost));
digest.update(ByteUtils.toBytes(forceAggressive));
if (shopItems != null) {
shopItems.createHash(digest);
}
}
}

View File

@@ -3,7 +3,6 @@ package com.gpl.rpg.AndorsTrail.model.actor;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -14,8 +13,6 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.SparseIntArray;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
@@ -30,7 +27,6 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.quest.Quest;
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForPlayer;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.Range;
import com.gpl.rpg.AndorsTrail.util.Size;
@@ -59,11 +55,9 @@ public final class Player extends Actor {
public String id = UUID.randomUUID().toString();
public long savedVersion = 1; // the version get's increased for cheat detection everytime a player with limited saves is saved
public boolean wasEditingDetected;
public String hash;
// Unequipped stats
// Unequipped stats
public static final class PlayerBaseTraits {
public int iconID;
public int maxAP;
@@ -117,7 +111,7 @@ public final class Player extends Actor {
baseTraits.criticalSkill = 0;
baseTraits.criticalMultiplier = 1;
baseTraits.damagePotential.set(1, 1);
baseTraits.blockChance = 9;
baseTraits.blockChance = 0;
baseTraits.damageResistance = 0;
baseTraits.useItemCost = 5;
baseTraits.reequipCost = 5;
@@ -422,13 +416,6 @@ public final class Player extends Actor {
this.id = src.readUTF();
this.savedVersion = src.readLong();
}
if (fileversion >= 71){
this.hash = src.readUTF();
this.wasEditingDetected = src.readBoolean();
}else{
this.hash = "";
this.wasEditingDetected = false;
}
}
public void writeToParcel(DataOutputStream dest) throws IOException {
@@ -487,58 +474,6 @@ public final class Player extends Actor {
}
dest.writeUTF(id);
dest.writeLong(savedVersion);
dest.writeUTF(hash);
dest.writeBoolean(wasEditingDetected);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
//skipping icon ID so that it can be changed without hash difference
digest.update(ByteUtils.toBytes(baseTraits.maxAP));
digest.update(ByteUtils.toBytes(baseTraits.maxHP));
//skipping name so that it can be changed without hash difference
digest.update(ByteUtils.toBytes(moveCost));
digest.update(ByteUtils.toBytes(baseTraits.attackCost));
digest.update(ByteUtils.toBytes(baseTraits.attackChance));
digest.update(ByteUtils.toBytes(baseTraits.criticalSkill));
digest.update(ByteUtils.toBytes(baseTraits.criticalMultiplier));
baseTraits.damagePotential.createHash(digest);
digest.update(ByteUtils.toBytes(baseTraits.blockChance));
digest.update(ByteUtils.toBytes(baseTraits.damageResistance));
digest.update(ByteUtils.toBytes(baseTraits.moveCost));
ap.createHash(digest);
health.createHash(digest);
position.createHash(digest);
for(ActorCondition c : conditions){
c.createHash(digest);
}
lastPosition.createHash(digest);
nextPosition.createHash(digest);
digest.update(ByteUtils.toBytes(level));
digest.update(ByteUtils.toBytes(totalExperience));
inventory.createHash(digest);
digest.update(ByteUtils.toBytes(baseTraits.useItemCost));
digest.update(ByteUtils.toBytes(baseTraits.reequipCost));
for (int i = 0; i<skillLevels.size(); i++){
digest.update(ByteUtils.toBytes(skillLevels.keyAt(i)));
digest.update(ByteUtils.toBytes(skillLevels.valueAt(i)));
}
digest.update(ByteUtils.toBytes(spawnMap));
digest.update(ByteUtils.toBytes(spawnPlace));
for (Entry<String, LinkedHashSet<Integer> > e:questProgress.entrySet() ) {
digest.update(ByteUtils.toBytes(e.getKey()));
for(int progress: e.getValue()){
digest.update(ByteUtils.toBytes(progress));
}
}
digest.update(ByteUtils.toBytes(availableSkillIncreases));
for (Entry<String, Integer> e:alignments.entrySet() ) {
digest.update(ByteUtils.toBytes(e.getKey()));
digest.update(ByteUtils.toBytes(e.getValue()));
}
digest.update(ByteUtils.toBytes(id));
// digest.update(ByteUtils.toBytes(savedVersion));
// digest.update(ByteUtils.toBytes(wasEditingDetected));
}
}

View File

@@ -1,19 +1,14 @@
package com.gpl.rpg.AndorsTrail.model.item;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
public class ItemContainer {
public final ArrayList<ItemEntry> items = new ArrayList<ItemEntry>();
@@ -28,8 +23,7 @@ public class ItemContainer {
return result;
}
public static final class ItemEntry {
public static final class ItemEntry {
public final ItemType itemType;
public int quantity;
public ItemEntry(ItemType itemType, int initialQuantity) {
@@ -48,12 +42,6 @@ public class ItemContainer {
dest.writeUTF(itemType.id);
dest.writeInt(quantity);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(itemType.id));
digest.update(ByteUtils.toBytes(quantity));
}
}
public void addItem(ItemType itemType, int quantity) {
@@ -292,12 +280,4 @@ public class ItemContainer {
e.writeToParcel(dest);
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
for (ItemEntry e :
items) {
e.createHash(digest);
}
}
}

View File

@@ -1,16 +1,11 @@
package com.gpl.rpg.AndorsTrail.model.item;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForItemContainer;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
public final class Loot {
@@ -93,13 +88,4 @@ public final class Loot {
position.writeToParcel(dest);
dest.writeBoolean(isVisible);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(exp));
digest.update(ByteUtils.toBytes(exp));
items.createHash(digest);
position.createHash(digest);
digest.update(ByteUtils.toBytes(isVisible));
}
}

View File

@@ -1,12 +1,8 @@
package com.gpl.rpg.AndorsTrail.model.map;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -92,27 +88,15 @@ public final class MapCollection {
return false;
}
private List<PredefinedMap> getAllSavedMaps(WorldContext world) {
public void writeToParcel(DataOutputStream dest, WorldContext world) throws IOException {
List<PredefinedMap> mapsToExport = new ArrayList<PredefinedMap>();
for(PredefinedMap map : getAllMaps()) {
if (shouldSaveMap(world, map)) mapsToExport.add(map);
}
return mapsToExport;
}
public void writeToParcel(DataOutputStream dest, WorldContext world) throws IOException {
List<PredefinedMap> mapsToExport = getAllSavedMaps(world);
dest.writeInt(mapsToExport.size());
for(PredefinedMap map : mapsToExport) {
dest.writeUTF(map.name);
map.writeToParcel(dest, world);
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
for (PredefinedMap map : getAllMaps()) {
map.createHash(digest);
}
}
}

View File

@@ -1,12 +1,8 @@
package com.gpl.rpg.AndorsTrail.model.map;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -14,7 +10,6 @@ import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.Range;
@@ -145,13 +140,4 @@ public final class MonsterSpawnArea {
m.writeToParcel(dest);
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(isSpawning));
for (Monster m :
monsters) {
m.createHash(digest);
}
}
}

View File

@@ -1,12 +1,8 @@
package com.gpl.rpg.AndorsTrail.model.map;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -20,7 +16,6 @@ import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.MapObject.MapObjectType;
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
@@ -345,7 +340,6 @@ public final class PredefinedMap {
}
}
} else {
currentColorFilter = null;
activeMapObjectGroups.clear();
activeMapObjectGroups.addAll(initiallyActiveMapObjectGroups);
activateMapObjects();
@@ -366,20 +360,16 @@ public final class PredefinedMap {
}
public boolean shouldSaveMapData(WorldContext world) {
if (this == world.model.currentMaps.map) return true;
return mapDataNeedsToBeSaved();
}
private boolean mapDataNeedsToBeSaved() {
if (!hasResetTemporaryData()) return true;
if (this == world.model.currentMaps.map) return true;
if (!groundBags.isEmpty()) return true;
for (MonsterSpawnArea a : spawnAreas) {
if (this.visited && a.isUnique) return true;
if (a.isSpawning != a.isSpawningForNewGame) return true;
}
if (!activeMapObjectGroups.containsAll(initiallyActiveMapObjectGroups)
|| !initiallyActiveMapObjectGroups.containsAll(activeMapObjectGroups)) return true;
if (currentColorFilter != null && !currentColorFilter.equals(initialColorFilter)) return true;
if (!activeMapObjectGroups.containsAll(initiallyActiveMapObjectGroups)
|| !initiallyActiveMapObjectGroups.containsAll(activeMapObjectGroups)) return true;
if (currentColorFilter != null) return true;
return false;
}
@@ -408,23 +398,4 @@ public final class PredefinedMap {
dest.writeBoolean(visited);
dest.writeUTF(lastSeenLayoutHash);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void createHash(MessageDigest digest) {
if (mapDataNeedsToBeSaved()) {
for (MonsterSpawnArea a : spawnAreas) {
a.createHash(digest);
}
for (String g : activeMapObjectGroups) {
digest.update(ByteUtils.toBytes(g));
}
for (Loot l : groundBags) {
l.createHash(digest);
}
digest.update(ByteUtils.toBytes(currentColorFilter));
//skip lastVisitTime since it is too volatile
}
digest.update( ByteUtils.toBytes(visited));
digest.update( ByteUtils.toBytes(lastSeenLayoutHash));
}
}

View File

@@ -12,7 +12,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -21,7 +20,6 @@ import java.util.regex.Pattern;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.os.SystemClock;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
@@ -44,7 +42,6 @@ public final class Savegames {
public static enum LoadSavegameResult {
success
, editDetected
, unknownError
, savegameIsFromAFutureVersion
, cheatingDetected
@@ -81,7 +78,7 @@ public final class Savegames {
}
return true;
} catch (IOException | NoSuchAlgorithmException e) {
} catch (IOException e) {
L.log("Error saving world: " + e.toString());
return false;
}
@@ -213,18 +210,14 @@ public final class Savegames {
}
public static void saveWorld(WorldContext world, OutputStream outStream, String displayInfo) throws IOException, NoSuchAlgorithmException {
public static void saveWorld(WorldContext world, OutputStream outStream, String displayInfo) throws IOException {
DataOutputStream dest = new DataOutputStream(outStream);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
world.model.player.hash = world.createHash();
}
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.model.player.wasEditingDetected);
world.model.player.savedVersion);
world.maps.writeToParcel(dest, world);
world.model.writeToParcel(dest);
dest.close();
@@ -246,15 +239,6 @@ public final class Savegames {
onWorldLoaded(res, world, controllers);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
String worldHash = world.createHash();
if(!worldHash.equals(world.model.player.hash)){
world.model.player.wasEditingDetected = true;
return LoadSavegameResult.editDetected;
}
} catch (NoSuchAlgorithmException ignored) { }
}
return LoadSavegameResult.success;
}
@@ -350,7 +334,6 @@ public final class Savegames {
public final boolean hasUnlimitedSaves;
public final String playerId;
public final long savedVersion;
public final boolean wasEditingDetected;
public String describe() {
return (fileversion == AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION ? "(D) " : "") + playerName + ", " + displayInfo;
@@ -395,14 +378,9 @@ public final class Savegames {
this.playerId = "";
this.savedVersion = 0;
}
if (fileversion >= 70){
this.wasEditingDetected = src.readBoolean();
}else{
this.wasEditingDetected = false;
}
}
public static void writeToParcel(DataOutputStream dest, String playerName, String displayInfo, int iconID, boolean isDead, boolean hasUnlimitedSaves, String playerId, long savedVersion, boolean wasEditingDetected) throws IOException {
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);
@@ -411,7 +389,6 @@ public final class Savegames {
dest.writeBoolean(hasUnlimitedSaves);
dest.writeUTF(playerId);
dest.writeLong(savedVersion);
dest.writeBoolean(wasEditingDetected);
}
}
}

View File

@@ -6,12 +6,14 @@ 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.os.Handler;
import android.os.Looper;
import android.webkit.MimeTypeMap;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.controller.Constants;
@@ -20,22 +22,19 @@ import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CancellationException;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public final class AndroidStorage {
public static File getStorageDirectory(Context context, String name) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return context.getExternalFilesDir(name);
} else {
}
else {
File root = Environment.getExternalStorageDirectory();
return new File(root, name);
}
@@ -43,16 +42,16 @@ public final class AndroidStorage {
public static boolean shouldMigrateToInternalStorage(Context context) {
boolean ret = false;
File externalSaveGameDirectory = new File(Environment.getExternalStorageDirectory(),
Constants.FILENAME_SAVEGAME_DIRECTORY);
File externalSaveGameDirectory = new File(Environment.getExternalStorageDirectory(), Constants.FILENAME_SAVEGAME_DIRECTORY);
File internalSaveGameDirectory = getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
if (externalSaveGameDirectory.exists()
&& externalSaveGameDirectory.isDirectory()
&& externalSaveGameDirectory.listFiles().length > 0
&& (!internalSaveGameDirectory.exists()
|| internalSaveGameDirectory.isDirectory()
&& internalSaveGameDirectory.listFiles().length < 2)) {
&& externalSaveGameDirectory.isDirectory()
&& externalSaveGameDirectory.listFiles().length > 0
&& (
!internalSaveGameDirectory.exists()
|| internalSaveGameDirectory.isDirectory() && internalSaveGameDirectory.listFiles().length < 2)
) {
ret = true;
}
return ret;
@@ -61,11 +60,11 @@ public final class AndroidStorage {
public static boolean migrateToInternalStorage(Context context) {
try {
copy(new File(Environment.getExternalStorageDirectory(), Constants.CHEAT_DETECTION_FOLDER),
getStorageDirectory(context, Constants.CHEAT_DETECTION_FOLDER));
getStorageDirectory(context, Constants.CHEAT_DETECTION_FOLDER));
copy(new File(Environment.getExternalStorageDirectory(), Constants.FILENAME_SAVEGAME_DIRECTORY),
getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY));
getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY));
} catch (IOException e) {
L.log("Error migrating data: " + e);
L.log("Error migrating data: " + e.toString());
return false;
}
return true;
@@ -106,174 +105,54 @@ public final class AndroidStorage {
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
public static void createZipDocumentFileFromFilesAsync(File[] files,
Context context,
DocumentFile targetDirectory,
String fileName,
String loadingMessage,
Consumer<Boolean> callback) {
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
progressDialog.setOnCancelListener(dialog -> worker.cancel());
ContentResolver resolver = context.getContentResolver();
Handler handler = Handler.createAsync(Looper.getMainLooper());
worker.setTask(workerCallback -> {
try {
workerCallback.onInitialize();
//region create zip file
File zip = File.createTempFile("temp_worldmap", ".zip");
try (OutputStream out = new FileOutputStream(zip)) {
ZipOutputStream zipOut = new ZipOutputStream(out);
for (int i = 0; i < files.length; i++) {
File file = files[i];
try (FileInputStream fis = new FileInputStream(file)) {
workerCallback.onProgress((float) i / files.length);
zipOut.putNextEntry(new ZipEntry(file.getName()));
copyStream(fis, zipOut);
zipOut.closeEntry();
}
}
zipOut.close();
}
//endregion
DocumentFile worldmapZip = DocumentFile.fromFile(zip);
DocumentFile worldmapTarget = targetDirectory.createFile("application/zip", fileName);
if (worldmapTarget != null && worldmapTarget.exists()) {
AndroidStorage.copyDocumentFile(worldmapZip, resolver, worldmapTarget);
workerCallback.onComplete(true);
} else {
throw new FileNotFoundException("Could not create File");
}
} catch (NullPointerException e) {
if (worker.isCancelled()) {
workerCallback.onFailure(new CancellationException("Cancelled"));
} else {
workerCallback.onFailure(e);
}
} catch (Exception e) {
workerCallback.onFailure(e);
}
});
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
worker.run();
}
public static void unzipToDirectory(File zipFile,
File targetDirectory,
boolean overwriteNotSkip) throws IOException {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
unzipStreamToDirectory(targetDirectory, overwriteNotSkip, zis);
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
public static void unzipDocumentFileToDirectoryAsync(DocumentFile zipFile,
Context context,
File targetDirectory,
boolean overwriteNotSkip,
String loadingMessage,
Consumer<Boolean> callback) {
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
progressDialog.setOnCancelListener(dialog -> worker.cancel());
ContentResolver resolver = context.getContentResolver();
Handler handler = Handler.createAsync(Looper.getMainLooper());
worker.setTask(workerCallback -> {
try {
workerCallback.onInitialize();
workerCallback.onProgress(-1);//set dummy progress since we don't know the
// progress of the unzip
unzipDocumentFileToDirectory(zipFile, resolver, targetDirectory, overwriteNotSkip);
workerCallback.onComplete(true);
} catch (IOException e) {
workerCallback.onFailure(e);
}
});
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
worker.run();
}
public static void unzipDocumentFileToDirectory(DocumentFile zipFile,
ContentResolver resolver,
File targetDirectory,
boolean overwriteNotSkip) throws IOException {
try (ZipInputStream zis = new ZipInputStream(resolver.openInputStream(zipFile.getUri()))) {
unzipStreamToDirectory(targetDirectory, overwriteNotSkip, zis);
}
}
private static void unzipStreamToDirectory(File targetDirectory,
boolean overwriteNotSkip,
ZipInputStream zis) throws IOException {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
file.getParentFile().mkdirs();
if (file.exists() && !overwriteNotSkip) {
continue;
}
try (FileOutputStream fos = new FileOutputStream(file)) {
copyStream(zis, fos);
}
}
}
}
public static void copyDocumentFileToNewOrExistingFile(DocumentFile sourceFile,
ContentResolver resolver,
DocumentFile targetFolder) throws IOException {
copyDocumentFileToNewOrExistingFile(sourceFile,
resolver,
targetFolder,
Constants.NO_FILE_EXTENSION_MIME_TYPE);
public static void copyDocumentFileToNewOrExistingFile(DocumentFile sourceFile, ContentResolver resolver, DocumentFile targetFolder) 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 {
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) {
if (file == null)
file = targetFolder.createFile(mimeType, fileName);
}
if (file == null) {
if (file == null)
return;
}
AndroidStorage.copyDocumentFile(sourceFile, resolver, file);
}
public static void copyDocumentFile(DocumentFile sourceFile,
ContentResolver resolver,
DocumentFile targetFile) throws IOException {
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) {
String applicationId = context.getPackageName();
@@ -284,9 +163,11 @@ public final class AndroidStorage {
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static Intent getNewOpenDirectoryIntent() {
return new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
return intent;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@@ -298,59 +179,50 @@ public final class AndroidStorage {
return intent;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static Intent getNewSelectZipIntent() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/zip");
return intent;
}
@RequiresApi(api = Build.VERSION_CODES.P)
public static void copyDocumentFilesFromToAsync(DocumentFile[] sources,
Context context,
DocumentFile[] targets,
String loadingMessage,
Consumer<Boolean> callback) {
if (sources.length != targets.length) {
public static void copyDocumentFilesFromToAsync(DocumentFile[] sources, Context context, DocumentFile[] targets, Consumer<Boolean> callback) {
if(sources.length != targets.length)
{
throw new IllegalArgumentException("Both arrays, target & source have to have the same size");
}
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
BackgroundWorker worker = new BackgroundWorker();
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context);
progressDialog.setOnCancelListener(dialog -> worker.cancel());
ContentResolver resolver = context.getContentResolver();
Handler handler = Handler.createAsync(Looper.getMainLooper());
worker.setTask(workerCallback -> {
try {
workerCallback.onInitialize();
for (int i = 0; i < sources.length; i++) {
worker.setTask(new BackgroundWorker.worker() {
@Override
public void doWork(BackgroundWorkerCallback callback) {
try {
callback.onInitialize();
for (int i = 0; i < sources.length ; i++) {
if (worker.isCancelled()) {
callback.onFailure(new CancellationException("Cancelled"));
return;
}
DocumentFile source = sources[i];
DocumentFile target = targets[i];
if(source == null || target == null)
{
continue;
}
copyDocumentFile(source, resolver,target);
float progress = i /(float) sources.length;
callback.onProgress(progress);
}
callback.onComplete(true);
} catch (NullPointerException e) {
if (worker.isCancelled()) {
workerCallback.onFailure(new CancellationException("Cancelled"));
callback.onFailure(new CancellationException("Cancelled"));
return;
}
DocumentFile source = sources[i];
DocumentFile target = targets[i];
if (source == null || target == null) {
continue;
}
copyDocumentFile(source, resolver, target);
float progress = i / (float) sources.length;
workerCallback.onProgress(progress);
} catch (Exception e) {
callback.onFailure(e);
}
workerCallback.onComplete(true);
} catch (NullPointerException e) {
if (worker.isCancelled()) {
workerCallback.onFailure(new CancellationException("Cancelled"));
return;
}
} catch (Exception e) {
workerCallback.onFailure(e);
}
});
worker.setCallback(getDefaultBackgroundWorkerCallback(handler, progressDialog, callback));
@@ -361,10 +233,9 @@ public final class AndroidStorage {
public static void copyDocumentFilesToDirAsync(DocumentFile[] files,
Context context,
DocumentFile targetDirectory,
String loadingMessage,
Consumer<Boolean> callback) {
BackgroundWorker<Boolean> worker = new BackgroundWorker<>();
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context, loadingMessage);
CustomDialogFactory.CustomDialog progressDialog = getLoadingDialog(context);
progressDialog.setOnCancelListener(dialog -> worker.cancel());
ContentResolver resolver = context.getContentResolver();
Handler handler = Handler.createAsync(Looper.getMainLooper());
@@ -378,12 +249,11 @@ public final class AndroidStorage {
return;
}
DocumentFile file = files[i];
if (file == null) {
if(file == null)
continue;
}
copyDocumentFileToNewOrExistingFile(file, resolver, targetDirectory);
float progress = i / (float) files.length;
float progress = i /(float) files.length;
workerCallback.onProgress(progress);
}
workerCallback.onComplete(true);
@@ -400,11 +270,10 @@ public final class AndroidStorage {
}
private static BackgroundWorkerCallback<Boolean> getDefaultBackgroundWorkerCallback(Handler handler,
CustomDialogFactory.CustomDialog progressDialog,
Consumer<Boolean> callback) {
CustomDialogFactory.CustomDialog progressDialog,
Consumer<Boolean> callback) {
return new BackgroundWorkerCallback<Boolean>() {
private int progress = -1;
private int progress = -1;
@Override
public void onInitialize() {
handler.post(() -> {
@@ -416,17 +285,10 @@ public final class AndroidStorage {
public void onProgress(float progress) {
handler.post(() -> {
int intProgress = (int) (progress * 100);
if (this.progress == intProgress) {
if(this.progress == intProgress)
return;
}
this.progress = intProgress;
if (progress == -1) {
CustomDialogFactory.setDesc(progressDialog, null);
return;
}
CustomDialogFactory.setDesc(progressDialog, intProgress + "%");
});
}
@@ -434,7 +296,10 @@ public final class AndroidStorage {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onFailure(Exception e) {
this.onComplete(false);
handler.post(() -> {
progressDialog.dismiss();
callback.accept(false);
});
}
@RequiresApi(api = Build.VERSION_CODES.N)
@@ -442,31 +307,20 @@ public final class AndroidStorage {
public void onComplete(Boolean result) {
handler.post(() -> {
progressDialog.dismiss();
callback.accept(result);
callback.accept(true);
});
}
};
}
private static CustomDialogFactory.CustomDialog getLoadingDialog(Context context) {
return getLoadingDialog(context, null);
}
private static CustomDialogFactory.CustomDialog getLoadingDialog(Context context, String message) {
if (message == null) {
message = context.getResources().getString(R.string.dialog_loading_message);
}
CustomDialogFactory.CustomDialog dialog = CustomDialogFactory.createDialog(context,
message,
context.getResources()
.getDrawable(R.drawable.loading_anim),
null,
null,
true,
false);
CustomDialogFactory.addCancelButton(dialog, android.R.string.no);
return dialog;
return CustomDialogFactory.createDialog(context,
context.getResources().getString(R.string.dialog_loading_message),
context.getResources().getDrawable(R.drawable.loading_anim),
null,
null,
false,
false);
}
}

View File

@@ -4,14 +4,14 @@ import java.util.concurrent.Executors;
public final class BackgroundWorker<T> {
boolean cancelled = false;
worker<T> task;
BackgroundWorkerCallback<T> callback;
worker task;
BackgroundWorkerCallback callback;
public void setTask(worker<T> task) {
public void setTask(worker task) {
this.task = task;
}
public void setCallback(BackgroundWorkerCallback<T> callback) {
public void setCallback(BackgroundWorkerCallback callback) {
this.callback = callback;
}
@@ -20,7 +20,7 @@ public final class BackgroundWorker<T> {
}
interface worker<T> {
void doWork(BackgroundWorkerCallback<T> callback);
void doWork(BackgroundWorkerCallback callback);
}
interface BackgroundWorkerCallback<T> {

View File

@@ -1,17 +1,6 @@
package com.gpl.rpg.AndorsTrail.util;
import android.os.Build;
import android.support.annotation.RequiresApi;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
public final class ByteUtils {
private static int bytes;
public static String toHexString(byte[] bytes) { return toHexString(bytes, bytes.length); }
public static String toHexString(byte[] bytes, int numBytes) {
if (bytes == null) return "";
@@ -32,57 +21,4 @@ public final class ByteUtils {
array[i] ^= mask[i];
}
}
public static byte[] toBytes(long l){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
bytes = Long.BYTES;
}else{
bytes = 8;
}
ByteBuffer buffer = ByteBuffer.allocate(bytes);
buffer.putLong(l);
return buffer.array();
}
public static byte[] toBytes(int i){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
bytes = Integer.BYTES;
}else{
bytes = 4;
}
ByteBuffer buffer = ByteBuffer.allocate(bytes);
buffer.putInt(i);
return buffer.array();
}
public static byte[] toBytes(float f) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
bytes = Float.BYTES;
}else{
bytes = 4;
}
ByteBuffer buffer = ByteBuffer.allocate(bytes);
buffer.putFloat(f);
return buffer.array();
}
public static byte[] toBytes(boolean bool){
byte b;
if(bool){
b = 0;
}else{
b = 1;
}
return new byte[] {b};
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static byte[] toBytes(String x) {
if (x == null) {
return new byte[]{};
}
return x.getBytes(StandardCharsets.UTF_8);
}
}

View File

@@ -3,7 +3,6 @@ package com.gpl.rpg.AndorsTrail.util;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
public final class Coord {
public int x;
@@ -48,9 +47,4 @@ public final class Coord {
dest.writeInt(x);
dest.writeInt(y);
}
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(x));
digest.update(ByteUtils.toBytes(y));
}
}

View File

@@ -1,11 +1,8 @@
package com.gpl.rpg.AndorsTrail.util;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
public final class Range {
public int max;
@@ -102,9 +99,4 @@ public final class Range {
dest.writeInt(max);
dest.writeInt(current);
}
public void createHash(MessageDigest digest) {
digest.update(ByteUtils.toBytes(max));
digest.update(ByteUtils.toBytes(current));
}
}

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

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

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

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

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

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

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

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

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

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

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