.mmap file importing / Better exception parsing

This commit is contained in:
Anuken
2019-05-31 10:24:51 -04:00
parent 30a254e9be
commit 940965f03d
16 changed files with 119 additions and 66 deletions

View File

@@ -15,16 +15,15 @@ import io.anuke.arc.backends.android.surfaceview.AndroidApplication;
import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration; import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration;
import io.anuke.arc.files.FileHandle; import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Consumer;
import io.anuke.arc.function.Predicate;
import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.util.Strings; import io.anuke.arc.util.Strings;
import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.arc.util.serialization.Base64Coder;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.*;
import io.anuke.mindustry.ui.dialogs.FileChooser; import io.anuke.mindustry.ui.dialogs.FileChooser;
import io.anuke.mindustry.net.ArcNetClient;
import io.anuke.mindustry.net.ArcNetServer;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
@@ -72,10 +71,10 @@ public class AndroidLauncher extends AndroidApplication{
} }
@Override @Override
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){ public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons); chooser = new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){ checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
chooser.show(); chooser.show();
chooser = null; chooser = null;
}else{ }else{
@@ -157,7 +156,7 @@ public class AndroidLauncher extends AndroidApplication{
SaveSlot slot = control.saves.importSave(file); SaveSlot slot = control.saves.importSave(file);
ui.load.runLoadSave(slot); ui.load.runLoadSave(slot);
}catch(IOException e){ }catch(IOException e){
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
} }
}else{ }else{
ui.showError("$save.import.invalid"); ui.showError("$save.import.invalid");

View File

@@ -219,6 +219,9 @@ editor.teams = Teams
editor.elevation = Elevation editor.elevation = Elevation
editor.errorload = Error loading file:\n[accent]{0} editor.errorload = Error loading file:\n[accent]{0}
editor.errorsave = Error saving file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0}
editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor.
editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported.
editor.errorheader = This map file is either not valid or corrupt.
editor.errorname = Map has no name defined. editor.errorname = Map has no name defined.
editor.update = Update editor.update = Update
editor.randomize = Randomize editor.randomize = Randomize

View File

@@ -105,6 +105,8 @@ public class Vars{
public static FileHandle screenshotDirectory; public static FileHandle screenshotDirectory;
/** data subdirectory used for custom mmaps */ /** data subdirectory used for custom mmaps */
public static FileHandle customMapDirectory; public static FileHandle customMapDirectory;
/** tmp subdirectory for map conversion */
public static FileHandle tmpDirectory;
/** data subdirectory used for saves */ /** data subdirectory used for saves */
public static FileHandle saveDirectory; public static FileHandle saveDirectory;
/** old map file extension, for conversion */ /** old map file extension, for conversion */
@@ -206,5 +208,6 @@ public class Vars{
screenshotDirectory = dataDirectory.child("screenshots/"); screenshotDirectory = dataDirectory.child("screenshots/");
customMapDirectory = dataDirectory.child("maps/"); customMapDirectory = dataDirectory.child("maps/");
saveDirectory = dataDirectory.child("saves/"); saveDirectory = dataDirectory.child("saves/");
tmpDirectory = dataDirectory.child("tmp/");
} }
} }

View File

@@ -135,7 +135,7 @@ public class Control implements ApplicationListener{
Net.host(port); Net.host(port);
player.isAdmin = true; player.isAdmin = true;
}catch(IOException e){ }catch(IOException e){
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false))); ui.showError(Core.bundle.format("server.error", Strings.parseException(e, true)));
Core.app.post(() -> state.set(State.menu)); Core.app.post(() -> state.set(State.menu));
} }
} }

View File

@@ -4,6 +4,7 @@ import io.anuke.arc.Core;
import io.anuke.arc.Input.TextInput; import io.anuke.arc.Input.TextInput;
import io.anuke.arc.files.FileHandle; import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Consumer;
import io.anuke.arc.function.Predicate;
import io.anuke.arc.math.RandomXS128; import io.anuke.arc.math.RandomXS128;
import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.scene.ui.TextField;
import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.arc.util.serialization.Base64Coder;
@@ -66,14 +67,14 @@ public abstract class Platform{
} }
/** /**
* Show a file chooser. Desktop only. * Show a file chooser.
* @param text File chooser title text * @param text File chooser title text
* @param content Description of the type of files to be loaded * @param content Description of the type of files to be loaded
* @param cons Selection listener * @param cons Selection listener
* @param open Whether to open or save files * @param open Whether to open or save files
* @param filetype File extension to filter * @param filetype File extension to filter
*/ */
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){ public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
} }
/** Hide the app. Android only. */ /** Hide the app. Android only. */

View File

@@ -25,8 +25,7 @@ import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.ui.fragments.*; import io.anuke.mindustry.ui.fragments.*;
import static io.anuke.arc.scene.actions.Actions.*; import static io.anuke.arc.scene.actions.Actions.*;
import static io.anuke.mindustry.Vars.control; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.disableUI;
public class UI implements ApplicationListener{ public class UI implements ApplicationListener{
private FreeTypeFontGenerator generator; private FreeTypeFontGenerator generator;
@@ -244,8 +243,17 @@ public class UI implements ApplicationListener{
} }
public void showError(String text){ public void showError(String text){
new Dialog("$error.title", "dialog"){{ new Dialog("", "dialog"){{
cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); setFillParent(true);
cont.add("$error.title");
cont.row();
cont.margin(15).pane(t -> {
Label l = t.add(text).pad(14f).get();
l.setAlignment(Align.center, Align.left);
if(mobile){
t.getCell(l).wrap().width(400f);
}
});
buttons.addButton("$ok", this::hide).size(90, 50).pad(4); buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
}}.show(); }}.show();
} }

View File

@@ -21,9 +21,9 @@ import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.io.JsonIO; import io.anuke.mindustry.io.*;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.ui.dialogs.FileChooser;
import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Block.Icon;
@@ -93,14 +93,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
"$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show, "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show,
"$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() -> "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() ->
Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> { Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> {
try{ world.maps.tryCatchMapError(() -> {
//TODO what if it's an image? users should be warned for their stupidity if(MapIO.isImage(file)){
editor.beginEdit(MapIO.createMap(file, true)); ui.showInfo("$editor.errorimage");
}catch(Exception e){ }else if(file.extension().equalsIgnoreCase(oldMapExtension)){
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); editor.beginEdit(world.maps.makeLegacyMap(file));
Log.err(e); }else{
} editor.beginEdit(MapIO.createMap(file, true));
}), true, mapExtension), }
});
}), true, FileChooser.anyMapFiles),
"$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() -> "$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() ->
Platform.instance.showFileChooser("$loadimage", "Image Files", file -> Platform.instance.showFileChooser("$loadimage", "Image Files", file ->
@@ -110,10 +112,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.beginEdit(pixmap); editor.beginEdit(pixmap);
pixmap.dispose(); pixmap.dispose();
}catch(Exception e){ }catch(Exception e){
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
Log.err(e); Log.err(e);
} }
}), true, "png")) }), true, FileChooser.pngFiles))
); );
t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> t.addImageTextButton("$editor.export", "icon-save-map", isize, () ->
@@ -127,11 +129,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
} }
MapIO.writeMap(result, editor.createMap(result)); MapIO.writeMap(result, editor.createMap(result));
}catch(Exception e){ }catch(Exception e){
ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, false))); ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, true)));
Log.err(e); Log.err(e);
} }
}); });
}, false, mapExtension)); }, false, FileChooser.mapFiles));
}); });
menu.cont.row(); menu.cont.row();
@@ -158,7 +160,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
try{ try{
editor.beginEdit(map); editor.beginEdit(map);
}catch(Exception e){ }catch(Exception e){
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
Log.err(e); Log.err(e);
} }
})); }));
@@ -336,7 +338,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
show(); show();
}catch(Exception e){ }catch(Exception e){
Log.err(e); Log.err(e);
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
} }
}); });
} }

View File

@@ -55,6 +55,9 @@ public class LegacyMapIO{
//meta is uncompressed //meta is uncompressed
int version = stream.readInt(); int version = stream.readInt();
if(version != 1){
throw new IOException("Outdated legacy map format");
}
int build = stream.readInt(); int build = stream.readInt();
short width = stream.readShort(), height = stream.readShort(); short width = stream.readShort(), height = stream.readShort();
byte tagAmount = stream.readByte(); byte tagAmount = stream.readByte();

View File

@@ -3,12 +3,13 @@ package io.anuke.mindustry.maps;
import io.anuke.arc.Core; import io.anuke.arc.Core;
import io.anuke.arc.collection.*; import io.anuke.arc.collection.*;
import io.anuke.arc.files.FileHandle; import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.ExceptionRunnable;
import io.anuke.arc.graphics.Texture; import io.anuke.arc.graphics.Texture;
import io.anuke.arc.util.Disposable; import io.anuke.arc.util.*;
import io.anuke.arc.util.Log;
import io.anuke.arc.util.serialization.Json; import io.anuke.arc.util.serialization.Json;
import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.io.*; import io.anuke.mindustry.io.LegacyMapIO;
import io.anuke.mindustry.io.MapIO;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
@@ -116,6 +117,14 @@ public class Maps implements Disposable{
} }
} }
/** Creates a legacy map by converting it to a non-legacy map and pasting it in a temp directory.
* Should be followed up by {@link #importMap(FileHandle)} .*/
public Map makeLegacyMap(FileHandle file) throws IOException{
FileHandle dst = tmpDirectory.child("conversion_map." + mapExtension);
LegacyMapIO.convertMap(file, dst);
return MapIO.createMap(dst, true);
}
/** Import a map, then save it. This updates all values and stored data necessary. */ /** Import a map, then save it. This updates all values and stored data necessary. */
public void importMap(FileHandle file) throws IOException{ public void importMap(FileHandle file) throws IOException{
FileHandle dest = findFile(); FileHandle dest = findFile();
@@ -124,6 +133,24 @@ public class Maps implements Disposable{
loadMap(dest, true); loadMap(dest, true);
} }
/** Attempts to run the following code;
* catches any errors and attempts to display them in a readable way.*/
public void tryCatchMapError(ExceptionRunnable run){
try{
run.run();
}catch(Exception e){
Log.err(e);
if("Outdated legacy map format".equals(e.getMessage())){
ui.showError("$editor.errorlegacy");
}else if(e.getMessage() != null && e.getMessage().contains("Incorrect header!")){
ui.showError("$editor.errorheader");
}else{
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
}
}
}
/** Removes a map completely. */ /** Removes a map completely. */
public void removeMap(Map map){ public void removeMap(Map map){
if(map.texture != null){ if(map.texture != null){

View File

@@ -6,8 +6,7 @@ import io.anuke.arc.collection.*;
import io.anuke.arc.function.BiConsumer; import io.anuke.arc.function.BiConsumer;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Consumer;
import io.anuke.arc.net.HttpRequestBuilder; import io.anuke.arc.net.HttpRequestBuilder;
import io.anuke.arc.util.Log; import io.anuke.arc.util.*;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.pooling.Pools; import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.Call;
@@ -67,7 +66,7 @@ public class Net{
}else if(error.equals("alreadyconnected")){ }else if(error.equals("alreadyconnected")){
error = Core.bundle.get("error.alreadyconnected"); error = Core.bundle.get("error.alreadyconnected");
}else if(!error.isEmpty()){ }else if(!error.isEmpty()){
error = Core.bundle.get("error.any") + "\n" + t.getClass().getSimpleName() + "\n" + (t.getMessage() == null ? "" : t.getMessage()); error = Core.bundle.get("error.any") + "\n" + Strings.parseException(e, true);
} }
ui.showText("", Core.bundle.format("connectfail", error)); ui.showText("", Core.bundle.format("connectfail", error));

View File

@@ -12,6 +12,7 @@ import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pools; import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import java.util.Arrays; import java.util.Arrays;
@@ -31,6 +32,11 @@ public class FileChooser extends FloatingDialog{
private boolean open; private boolean open;
private int lastWidth = Core.graphics.getWidth(), lastHeight = Core.graphics.getHeight(); private int lastWidth = Core.graphics.getWidth(), lastHeight = Core.graphics.getHeight();
public static final Predicate<String> pngFiles = str -> str.equals("png");
public static final Predicate<String> anyMapFiles = str -> str.equals(Vars.oldMapExtension) || str.equals(Vars.mapExtension);
public static final Predicate<String> mapFiles = str -> str.equals(Vars.mapExtension);
public static final Predicate<String> saveFiles = str -> str.equals(Vars.saveExtension);
public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){ public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){
super(title); super(title);
this.open = open; this.open = open;

View File

@@ -56,7 +56,7 @@ public class HostDialog extends FloatingDialog{
Net.host(Vars.port); Net.host(Vars.port);
player.isAdmin = true; player.isAdmin = true;
}catch(IOException e){ }catch(IOException e){
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false))); ui.showError(Core.bundle.format("server.error", Strings.parseException(e, true)));
} }
ui.loadfrag.hide(); ui.loadfrag.hide();
hide(); hide();

View File

@@ -90,16 +90,16 @@ public class LoadDialog extends FloatingDialog{
slot.exportFile(file); slot.exportFile(file);
setup(); setup();
}catch(IOException e){ }catch(IOException e){
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false))); ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, true)));
} }
}, false, saveExtension); }, false, FileChooser.saveFiles);
}else{ }else{
try{ try{
FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension); FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
slot.exportFile(file); slot.exportFile(file);
Platform.instance.shareFile(file); Platform.instance.shareFile(file);
}catch(Exception e){ }catch(Exception e){
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false))); ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, true)));
} }
} }
}).size(14 * 3).right(); }).size(14 * 3).right();
@@ -155,12 +155,12 @@ public class LoadDialog extends FloatingDialog{
setup(); setup();
}catch(IOException e){ }catch(IOException e){
e.printStackTrace(); e.printStackTrace();
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
} }
}else{ }else{
ui.showError("$save.import.invalid"); ui.showError("$save.import.invalid");
} }
}, true, saveExtension); }, true, FileChooser.saveFiles);
}).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); }).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4);
} }

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.*; import io.anuke.arc.util.Scaling;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.io.MapIO;
@@ -23,8 +23,19 @@ public class MapsDialog extends FloatingDialog{
addCloseButton(); addCloseButton();
buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> { buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> {
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> { Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
try{ world.maps.tryCatchMapError(() -> {
Map map = MapIO.createMap(file, true); if(MapIO.isImage(file)){
ui.showError("$editor.errorimage");
return;
}
Map map;
if(file.extension().equalsIgnoreCase(mapExtension)){
map = MapIO.createMap(file, true);
}else{
map = world.maps.makeLegacyMap(file);
}
String name = map.tags.get("name"); String name = map.tags.get("name");
if(name == null){ if(name == null){
ui.showError("$editor.errorname"); ui.showError("$editor.errorname");
@@ -34,27 +45,21 @@ public class MapsDialog extends FloatingDialog{
Map conflict = world.maps.all().find(m -> m.name().equals(name)); Map conflict = world.maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){ if(conflict != null && !conflict.custom){
ui.showError(Core.bundle.format("editor.import.exists", name)); ui.showInfo(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){ }else if(conflict != null){
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> { ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
try{ world.maps.tryCatchMapError(() -> {
world.maps.importMap(file); world.maps.importMap(file);
setup(); setup();
}catch(Exception e){ });
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
Log.err(e);
}
}); });
}else{ }else{
world.maps.importMap(file); world.maps.importMap(map.file);
setup(); setup();
} }
}catch(Exception e){ });
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); }, true, FileChooser.anyMapFiles);
Log.err(e);
}
}, true, mapExtension);
}).size(230f, 64f); }).size(230f, 64f);
shown(this::setup); shown(this::setup);

View File

@@ -1,14 +1,11 @@
package io.anuke.mindustry.desktop; package io.anuke.mindustry.desktop;
import club.minnced.discord.rpc.DiscordEventHandlers; import club.minnced.discord.rpc.*;
import club.minnced.discord.rpc.DiscordRPC;
import club.minnced.discord.rpc.DiscordRichPresence;
import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Array;
import io.anuke.arc.files.FileHandle; import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Consumer;
import io.anuke.arc.util.Log; import io.anuke.arc.function.Predicate;
import io.anuke.arc.util.OS; import io.anuke.arc.util.*;
import io.anuke.arc.util.Strings;
import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.arc.util.serialization.Base64Coder;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
@@ -69,8 +66,8 @@ public class DesktopPlatform extends Platform{
} }
@Override @Override
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filter){ public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
new FileChooser(text, file -> file.extension().equalsIgnoreCase(filter), open, cons).show(); new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons).show();
} }
@Override @Override

View File

@@ -103,7 +103,7 @@ public class IOSLauncher extends IOSApplication.Delegate{
SaveSlot slot = control.saves.importSave(file); SaveSlot slot = control.saves.importSave(file);
ui.load.runLoadSave(slot); ui.load.runLoadSave(slot);
}catch(IOException e){ }catch(IOException e){
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
} }
}else{ }else{
ui.showError("save.import.invalid"); ui.showError("save.import.invalid");