Add activity to import game assets on Android

Fixes #105
This commit is contained in:
Alexander Batalov 2022-07-31 22:52:26 +03:00
parent 307b032118
commit 0d5aa705f0
5 changed files with 131 additions and 12 deletions

View File

@ -38,15 +38,11 @@ $ sudo apt install libsdl2-2.0-0
> **NOTE**: Fallout 2 was designed with mouse in mind. There are many controls that require precise cursor positioning, which is not possible with fingers. When playing on Android you'll use fingers to move mouse cursor, not a character, or a map. Double tap to "click" left mouse button in the current cursor position, triple tap to "click" right mouse button. It might feel awkward at first, but it's super handy - you can play with just a thumb. This is not set in stone and might change in the future.
- Use Windows installation as a base - it contains data assets needed to play. Copy `Fallout2` folder to your device, for example to `Downloads`. You need `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder.
- Download `fallout2-ce.apk` and copy it to your device. Open it with file explorer, follow instructions (install from unknown source).
- Run the game once, it will say `Couldn't find/load text fonts` and create a folder for data assets.
- Open file explorer, navigate to `Android/data/com.alexbatalov.fallout2ce/files`, delete junk folders inside (they will be named as game files, just delete them).
- Copy `master.dat`, `critter.dat`, `patch000.dat` and `data` folder from your Windows/macOS installation to the folder above.
- Run the game again.
- When you run the game for the first time it will immediately present file picker. Select the folder from the first step. Wait until this data is copied. There is no fancy importing interface (yet), just wait for about 30 seconds. The game will start automatically.
## Contributing

View File

@ -96,4 +96,5 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.documentfile:documentfile:1.0.1'
}

View File

@ -92,6 +92,10 @@
</intent-filter>
-->
</activity>
<activity android:name=".ImportActivity"
android:theme="@style/AppTheme">
</activity>
</application>
</manifest>

View File

@ -0,0 +1,89 @@
package com.alexbatalov.fallout2ce;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.documentfile.provider.DocumentFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ImportActivity extends Activity {
private static final int IMPORT_REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, IMPORT_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (requestCode == IMPORT_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
final Uri treeUri = resultData.getData();
if (treeUri != null) {
final DocumentFile treeDocument = DocumentFile.fromTreeUri(this, treeUri);
if (treeDocument != null) {
copyRecursively(treeDocument, getExternalFilesDir(null));
final Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
}
}
finish();
} else {
super.onActivityResult(requestCode, resultCode, resultData);
}
}
private boolean copyRecursively(DocumentFile src, File dest) {
final DocumentFile[] documentFiles = src.listFiles();
for (final DocumentFile documentFile : documentFiles) {
if (documentFile.isFile()) {
if (!copyFile(documentFile, new File(dest, documentFile.getName()))) {
return false;
}
} else if (documentFile.isDirectory()) {
final File subdirectory = new File(dest, documentFile.getName());
if (!subdirectory.exists()) {
subdirectory.mkdir();
}
if (!copyRecursively(documentFile, subdirectory)) {
return false;
}
}
}
return true;
}
private boolean copyFile(DocumentFile src, File dest) {
try {
final InputStream inputStream = getContentResolver().openInputStream(src.getUri());
final OutputStream outputStream = new FileOutputStream(dest);
final byte[] buffer = new byte[16384];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
}

View File

@ -1,18 +1,47 @@
package com.alexbatalov.fallout2ce;
import android.content.Intent;
import android.os.Bundle;
import org.libsdl.app.SDLActivity;
public class MainActivity extends SDLActivity {
protected void onCreate(Bundle savedInstanceState) {
// Needed to initialize `files` folder (and make it publicly accessible
// for file managers) for user to upload assets.
getExternalFilesDir(null);
import java.io.File;
public class MainActivity extends SDLActivity {
private boolean noExit = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final File externalFilesDir = getExternalFilesDir(null);
final File configFile = new File(externalFilesDir, "fallout2.cfg");
if (!configFile.exists()) {
final File masterDatFile = new File(externalFilesDir, "master.dat");
final File critterDatFile = new File(externalFilesDir, "critter.dat");
if (!masterDatFile.exists() || !critterDatFile.exists()) {
final Intent intent = new Intent(this, ImportActivity.class);
startActivity(intent);
noExit = true;
finish();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!noExit) {
// Needed to make sure libc calls exit handlers, which releases
// in-game resources.
System.exit(0);
}
}
@Override
protected String[] getLibraries() {
return new String[]{
"fallout2-ce",