.mmap file importing / Better exception parsing
This commit is contained in:
@@ -105,6 +105,8 @@ public class Vars{
|
||||
public static FileHandle screenshotDirectory;
|
||||
/** data subdirectory used for custom mmaps */
|
||||
public static FileHandle customMapDirectory;
|
||||
/** tmp subdirectory for map conversion */
|
||||
public static FileHandle tmpDirectory;
|
||||
/** data subdirectory used for saves */
|
||||
public static FileHandle saveDirectory;
|
||||
/** old map file extension, for conversion */
|
||||
@@ -206,5 +208,6 @@ public class Vars{
|
||||
screenshotDirectory = dataDirectory.child("screenshots/");
|
||||
customMapDirectory = dataDirectory.child("maps/");
|
||||
saveDirectory = dataDirectory.child("saves/");
|
||||
tmpDirectory = dataDirectory.child("tmp/");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public class Control implements ApplicationListener{
|
||||
Net.host(port);
|
||||
player.isAdmin = true;
|
||||
}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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.anuke.arc.Core;
|
||||
import io.anuke.arc.Input.TextInput;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.function.Consumer;
|
||||
import io.anuke.arc.function.Predicate;
|
||||
import io.anuke.arc.math.RandomXS128;
|
||||
import io.anuke.arc.scene.ui.TextField;
|
||||
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 content Description of the type of files to be loaded
|
||||
* @param cons Selection listener
|
||||
* @param open Whether to open or save files
|
||||
* @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. */
|
||||
|
||||
@@ -25,8 +25,7 @@ import io.anuke.mindustry.ui.dialogs.*;
|
||||
import io.anuke.mindustry.ui.fragments.*;
|
||||
|
||||
import static io.anuke.arc.scene.actions.Actions.*;
|
||||
import static io.anuke.mindustry.Vars.control;
|
||||
import static io.anuke.mindustry.Vars.disableUI;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class UI implements ApplicationListener{
|
||||
private FreeTypeFontGenerator generator;
|
||||
@@ -244,8 +243,17 @@ public class UI implements ApplicationListener{
|
||||
}
|
||||
|
||||
public void showError(String text){
|
||||
new Dialog("$error.title", "dialog"){{
|
||||
cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
||||
new Dialog("", "dialog"){{
|
||||
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);
|
||||
}}.show();
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.game.*;
|
||||
import io.anuke.mindustry.io.JsonIO;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.io.*;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
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.importfile", "$editor.importfile.description", "icon-file", (Runnable)() ->
|
||||
Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> {
|
||||
try{
|
||||
//TODO what if it's an image? users should be warned for their stupidity
|
||||
editor.beginEdit(MapIO.createMap(file, true));
|
||||
}catch(Exception e){
|
||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
}), true, mapExtension),
|
||||
world.maps.tryCatchMapError(() -> {
|
||||
if(MapIO.isImage(file)){
|
||||
ui.showInfo("$editor.errorimage");
|
||||
}else if(file.extension().equalsIgnoreCase(oldMapExtension)){
|
||||
editor.beginEdit(world.maps.makeLegacyMap(file));
|
||||
}else{
|
||||
editor.beginEdit(MapIO.createMap(file, true));
|
||||
}
|
||||
});
|
||||
}), true, FileChooser.anyMapFiles),
|
||||
|
||||
"$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() ->
|
||||
Platform.instance.showFileChooser("$loadimage", "Image Files", file ->
|
||||
@@ -110,10 +112,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
editor.beginEdit(pixmap);
|
||||
pixmap.dispose();
|
||||
}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);
|
||||
}
|
||||
}), true, "png"))
|
||||
}), true, FileChooser.pngFiles))
|
||||
);
|
||||
|
||||
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));
|
||||
}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);
|
||||
}
|
||||
});
|
||||
}, false, mapExtension));
|
||||
}, false, FileChooser.mapFiles));
|
||||
});
|
||||
|
||||
menu.cont.row();
|
||||
@@ -158,7 +160,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
try{
|
||||
editor.beginEdit(map);
|
||||
}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);
|
||||
}
|
||||
}));
|
||||
@@ -336,7 +338,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
show();
|
||||
}catch(Exception 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)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ public class LegacyMapIO{
|
||||
|
||||
//meta is uncompressed
|
||||
int version = stream.readInt();
|
||||
if(version != 1){
|
||||
throw new IOException("Outdated legacy map format");
|
||||
}
|
||||
int build = stream.readInt();
|
||||
short width = stream.readShort(), height = stream.readShort();
|
||||
byte tagAmount = stream.readByte();
|
||||
|
||||
@@ -3,12 +3,13 @@ package io.anuke.mindustry.maps;
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.function.ExceptionRunnable;
|
||||
import io.anuke.arc.graphics.Texture;
|
||||
import io.anuke.arc.util.Disposable;
|
||||
import io.anuke.arc.util.Log;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.arc.util.serialization.Json;
|
||||
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.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. */
|
||||
public void importMap(FileHandle file) throws IOException{
|
||||
FileHandle dest = findFile();
|
||||
@@ -124,6 +133,24 @@ public class Maps implements Disposable{
|
||||
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. */
|
||||
public void removeMap(Map map){
|
||||
if(map.texture != null){
|
||||
|
||||
@@ -6,8 +6,7 @@ import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.function.BiConsumer;
|
||||
import io.anuke.arc.function.Consumer;
|
||||
import io.anuke.arc.net.HttpRequestBuilder;
|
||||
import io.anuke.arc.util.Log;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.arc.util.pooling.Pools;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
@@ -67,7 +66,7 @@ public class Net{
|
||||
}else if(error.equals("alreadyconnected")){
|
||||
error = Core.bundle.get("error.alreadyconnected");
|
||||
}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));
|
||||
|
||||
@@ -12,6 +12,7 @@ import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.arc.scene.ui.layout.Unit;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.arc.util.pooling.Pools;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -31,6 +32,11 @@ public class FileChooser extends FloatingDialog{
|
||||
private boolean open;
|
||||
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){
|
||||
super(title);
|
||||
this.open = open;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class HostDialog extends FloatingDialog{
|
||||
Net.host(Vars.port);
|
||||
player.isAdmin = true;
|
||||
}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();
|
||||
hide();
|
||||
|
||||
@@ -90,16 +90,16 @@ public class LoadDialog extends FloatingDialog{
|
||||
slot.exportFile(file);
|
||||
setup();
|
||||
}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{
|
||||
try{
|
||||
FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
|
||||
slot.exportFile(file);
|
||||
Platform.instance.shareFile(file);
|
||||
}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();
|
||||
@@ -155,12 +155,12 @@ public class LoadDialog extends FloatingDialog{
|
||||
setup();
|
||||
}catch(IOException e){
|
||||
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{
|
||||
ui.showError("$save.import.invalid");
|
||||
}
|
||||
}, true, saveExtension);
|
||||
}, true, FileChooser.saveFiles);
|
||||
}).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.scene.event.Touchable;
|
||||
import io.anuke.arc.scene.ui.*;
|
||||
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.core.Platform;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
@@ -23,8 +23,19 @@ public class MapsDialog extends FloatingDialog{
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> {
|
||||
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
|
||||
try{
|
||||
Map map = MapIO.createMap(file, true);
|
||||
world.maps.tryCatchMapError(() -> {
|
||||
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");
|
||||
if(name == null){
|
||||
ui.showError("$editor.errorname");
|
||||
@@ -34,27 +45,21 @@ public class MapsDialog extends FloatingDialog{
|
||||
Map conflict = world.maps.all().find(m -> m.name().equals(name));
|
||||
|
||||
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){
|
||||
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
|
||||
try{
|
||||
world.maps.tryCatchMapError(() -> {
|
||||
world.maps.importMap(file);
|
||||
setup();
|
||||
}catch(Exception e){
|
||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}else{
|
||||
world.maps.importMap(file);
|
||||
world.maps.importMap(map.file);
|
||||
setup();
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
}, true, mapExtension);
|
||||
});
|
||||
}, true, FileChooser.anyMapFiles);
|
||||
}).size(230f, 64f);
|
||||
|
||||
shown(this::setup);
|
||||
|
||||
Reference in New Issue
Block a user