mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-02 03:00:29 +03:00
Android file chooser fixes & support for save loading from file browser
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="user"
|
android:screenOrientation="user"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout">
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -39,6 +40,25 @@
|
|||||||
<data android:scheme="mindustry"/>
|
<data android:scheme="mindustry"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:mimeType="application/octet-stream" />
|
||||||
|
<data android:mimeType="application/x-msav" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:host="*" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
<data android:pathPattern=".*\\.msav" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import arc.struct.*;
|
|||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import dalvik.system.*;
|
import dalvik.system.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
@@ -222,7 +223,9 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
hideStatusBar = true;
|
hideStatusBar = true;
|
||||||
useGL30 = true;
|
useGL30 = true;
|
||||||
}});
|
}});
|
||||||
checkFiles(getIntent());
|
|
||||||
|
var intent = getIntent();
|
||||||
|
Events.on(ClientLoadEvent.class, u -> handleFiles(intent));
|
||||||
|
|
||||||
try{
|
try{
|
||||||
//new external folder
|
//new external folder
|
||||||
@@ -280,54 +283,49 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkFiles(Intent intent){
|
@Override
|
||||||
|
protected void onNewIntent(Intent intent){
|
||||||
|
super.onNewIntent(intent);
|
||||||
|
|
||||||
|
handleFiles(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFiles(Intent intent){
|
||||||
|
if(intent == null) return;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
if(uri != null){
|
if(uri != null){
|
||||||
File myFile = null;
|
|
||||||
String scheme = uri.getScheme();
|
Fi file = Core.files.cache("temp-save." + saveExtension);
|
||||||
if(scheme.equals("file")){
|
file.write(getContentResolver().openInputStream(uri), false);
|
||||||
String fileName = uri.getEncodedPath();
|
//TODO: how to check if it's a server URL? e.g: mindustry://myserver.com or mindustry://127.0.0.1
|
||||||
myFile = new File(fileName);
|
|
||||||
}else if(!scheme.equals("content")){
|
//may run on a different thread
|
||||||
//error
|
Core.app.post(() -> {
|
||||||
return;
|
try{
|
||||||
}
|
SaveMeta meta = SaveIO.getMeta(file);
|
||||||
boolean save = uri.getPath().endsWith(saveExtension);
|
if(!meta.isMap()){ //open save
|
||||||
boolean map = uri.getPath().endsWith(mapExtension);
|
SaveSlot slot = control.saves.importSave(file);
|
||||||
InputStream inStream;
|
ui.load.runLoadSave(slot);
|
||||||
if(myFile != null) inStream = new FileInputStream(myFile);
|
}else{ //open map
|
||||||
else inStream = getContentResolver().openInputStream(uri);
|
if(!ui.maps.isShown()){
|
||||||
Core.app.post(() -> Core.app.post(() -> {
|
ui.maps.show();
|
||||||
if(save){ //open save
|
|
||||||
System.out.println("Opening save.");
|
|
||||||
Fi file = Core.files.local("temp-save." + saveExtension);
|
|
||||||
file.write(inStream, false);
|
|
||||||
if(SaveIO.isSaveValid(file)){
|
|
||||||
try{
|
|
||||||
SaveSlot slot = control.saves.importSave(file);
|
|
||||||
ui.load.runLoadSave(slot);
|
|
||||||
}catch(IOException e){
|
|
||||||
ui.showException("@save.import.fail", e);
|
|
||||||
}
|
}
|
||||||
}else{
|
ui.maps.tryImportMap(file, result -> ui.maps.showMap(result));
|
||||||
ui.showErrorMessage("@save.import.invalid");
|
|
||||||
}
|
}
|
||||||
}else if(map){ //open map
|
}catch(Throwable e){
|
||||||
Fi file = Core.files.local("temp-map." + mapExtension);
|
Log.err("Failed to load save", e);
|
||||||
file.write(inStream, false);
|
ui.showException("@save.import.invalid", e);
|
||||||
Core.app.post(() -> {
|
|
||||||
System.out.println("Opening map.");
|
|
||||||
if(!ui.editor.isShown()){
|
|
||||||
ui.editor.show();
|
|
||||||
}
|
|
||||||
ui.editor.beginEditMap(file);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
//clear data (not sure if necessary?)
|
||||||
|
intent.setAction(Intent.ACTION_MAIN);
|
||||||
|
intent.setData(null);
|
||||||
}
|
}
|
||||||
}catch(IOException e){
|
}catch(Throwable e){
|
||||||
e.printStackTrace();
|
Log.err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,4 +28,8 @@ public class SaveMeta{
|
|||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
this.mods = JsonIO.read(String[].class, tags.get("mods", "[]"));
|
this.mods = JsonIO.read(String[].class, tags.get("mods", "[]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMap(){
|
||||||
|
return tags.containsKey("name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,8 +267,8 @@ public class Maps{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Import a map, then save it. This updates all values and stored data necessary. */
|
/** Imports a map, then saves it. This updates all values and stored data necessary. */
|
||||||
public void importMap(Fi file) throws IOException{
|
public Map importMap(Fi file) throws IOException{
|
||||||
Fi dest = findFile(file.name());
|
Fi dest = findFile(file.name());
|
||||||
file.copyTo(dest);
|
file.copyTo(dest);
|
||||||
|
|
||||||
@@ -288,6 +288,8 @@ public class Maps{
|
|||||||
if(error[0] != null){
|
if(error[0] != null){
|
||||||
throw new IOException(error[0]);
|
throw new IOException(error[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempts to run the following code;
|
/** Attempts to run the following code;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class FileChooser{
|
|||||||
|
|
||||||
public static void export(String name, String extension, FileWriter writer){
|
public static void export(String name, String extension, FileWriter writer){
|
||||||
if(!ios){
|
if(!ios){
|
||||||
FileChooser.save(extension).name(name).submit(file -> {
|
FileChooser.save(extension).name(name.endsWith("." + extension) ? name : name + "." + extension).submit(file -> {
|
||||||
ui.loadAnd(() -> {
|
ui.loadAnd(() -> {
|
||||||
try{
|
try{
|
||||||
writer.write(file);
|
writer.write(file);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package mindustry.ui.dialogs;
|
|||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
|
import arc.func.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
@@ -44,53 +45,60 @@ public class EditorMapsDialog extends MapListDialog{
|
|||||||
FileChooser.open(mapExtension).submitMulti(files -> {
|
FileChooser.open(mapExtension).submitMulti(files -> {
|
||||||
ui.loadAnd(() -> {
|
ui.loadAnd(() -> {
|
||||||
for(Fi file : files){
|
for(Fi file : files){
|
||||||
maps.tryCatchMapError(() -> {
|
tryImportMap(file, null);
|
||||||
if(MapIO.isImage(file)){
|
|
||||||
ui.showErrorMessage("@editor.errorimage");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map map = MapIO.createMap(file, true);
|
|
||||||
|
|
||||||
//when you attempt to import a save, it will have no name, so generate one
|
|
||||||
String name = map.tags.get("name", () -> {
|
|
||||||
String result = "unknown";
|
|
||||||
int number = 0;
|
|
||||||
while(maps.byName(result + number++) != null) ;
|
|
||||||
return result + number;
|
|
||||||
});
|
|
||||||
|
|
||||||
//this will never actually get called, but it remains just in case
|
|
||||||
if(name == null){
|
|
||||||
ui.showErrorMessage("@editor.errorname");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map conflict = maps.all().find(m -> m.name().equalsIgnoreCase(name));
|
|
||||||
|
|
||||||
if(conflict != null && !conflict.custom){
|
|
||||||
ui.showInfo(Core.bundle.format("editor.import.exists", name));
|
|
||||||
}else if(conflict != null){
|
|
||||||
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
|
|
||||||
maps.tryCatchMapError(() -> {
|
|
||||||
maps.removeMap(conflict);
|
|
||||||
maps.importMap(map.file);
|
|
||||||
setup();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
maps.importMap(map.file);
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void tryImportMap(Fi file, @Nullable Cons<Map> success){
|
||||||
|
maps.tryCatchMapError(() -> {
|
||||||
|
if(MapIO.isImage(file)){
|
||||||
|
ui.showErrorMessage("@editor.errorimage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map map = MapIO.createMap(file, true);
|
||||||
|
|
||||||
|
//when you attempt to import a save, it will have no name, so generate one
|
||||||
|
String name = map.tags.get("name", () -> {
|
||||||
|
String result = "unknown";
|
||||||
|
int number = 0;
|
||||||
|
while(maps.byName(result + number++) != null) ;
|
||||||
|
return result + number;
|
||||||
|
});
|
||||||
|
|
||||||
|
//this will never actually get called, but it remains just in case
|
||||||
|
if(name == null){
|
||||||
|
ui.showErrorMessage("@editor.errorname");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map conflict = maps.all().find(m -> m.name().equalsIgnoreCase(name));
|
||||||
|
|
||||||
|
if(conflict != null && !conflict.custom){
|
||||||
|
ui.showInfo(Core.bundle.format("editor.import.exists", name));
|
||||||
|
}else if(conflict != null){
|
||||||
|
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
|
||||||
|
maps.tryCatchMapError(() -> {
|
||||||
|
maps.removeMap(conflict);
|
||||||
|
var imported = maps.importMap(map.file);
|
||||||
|
setup();
|
||||||
|
|
||||||
|
if(success != null) success.get(imported);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
var imported = maps.importMap(map.file);
|
||||||
|
setup();
|
||||||
|
if(success != null) success.get(imported);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void showMap(Map map){
|
public void showMap(Map map){
|
||||||
BaseDialog dialog = activeDialog = new BaseDialog("@editor.mapinfo");
|
BaseDialog dialog = activeDialog = new BaseDialog("@editor.mapinfo");
|
||||||
dialog.addCloseButton();
|
dialog.addCloseButton();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user