From b20f026c7bf3771f59f7dad99b8c0601d05c5415 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 22 May 2018 17:28:21 -0400 Subject: [PATCH] Added dialogs for saving/loading maps directly, work on web support --- core/assets/bundles/bundle.properties | 2 + core/src/io/anuke/mindustry/core/UI.java | 9 ++ .../mindustry/editor/MapEditorDialog.java | 106 +++++++----------- core/src/io/anuke/mindustry/io/Map.java | 8 +- core/src/io/anuke/mindustry/io/Maps.java | 83 ++++++++++---- .../mindustry/ui/fragments/DebugFragment.java | 2 +- 6 files changed, 123 insertions(+), 87 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 774b6760da..fa563d3683 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -164,6 +164,8 @@ text.editor.generate=Generate text.editor.resize=Resize text.editor.loadmap=Load Map text.editor.savemap=Save Map +text.editor.importmap=Import Map +text.editor.exportmap=Export Map text.editor.loadimage=Import Terrain text.editor.saveimage=Export Terrain text.editor.unsaved=[scarlet]You have unsaved changes![]\nAre you sure you want to exit? diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 0f6fe70a64..a4bc1378f7 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -16,6 +16,7 @@ import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.function.Callable; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Listenable; import io.anuke.ucore.graphics.Draw; @@ -211,6 +212,14 @@ public class UI extends SceneModule{ } } + public void loadAnd(Callable call){ + loadfrag.show(); + Timers.run(6f, () -> { + call.run(); + loadfrag.hide(); + }); + } + public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer confirmed){ new Dialog(title, "dialog"){{ content().margin(30).add(text).padRight(6f); diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index 49867518a2..751e930f82 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -8,10 +8,7 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.ObjectMap; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.io.MapIO; -import io.anuke.mindustry.io.MapMeta; -import io.anuke.mindustry.io.MapTileData; -import io.anuke.mindustry.io.Platform; +import io.anuke.mindustry.io.*; import io.anuke.mindustry.ui.dialogs.FileChooser; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; @@ -38,6 +35,7 @@ import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; import java.io.DataInputStream; +import java.io.IOException; import static io.anuke.mindustry.Vars.*; @@ -68,8 +66,7 @@ public class MapEditorDialog extends Dialog{ saveFile = new FileChooser("$text.saveimage", false, file -> { file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); FileHandle result = file; - ui.loadfrag.show(); - Timers.run(3f, () -> { + ui.loadAnd(() -> { try{ if(!editor.getTags().containsKey("name")){ @@ -80,13 +77,11 @@ public class MapEditorDialog extends Dialog{ ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); Log.err(e); } - ui.loadfrag.hide(); }); }); openFile = new FileChooser("$text.loadimage", FileChooser.mapFilter, true, file -> { - ui.loadfrag.show(); - Timers.run(3f, () -> { + ui.loadAnd(() -> { try{ DataInputStream stream = new DataInputStream(file.read()); @@ -99,28 +94,24 @@ public class MapEditorDialog extends Dialog{ ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } - ui.loadfrag.hide(); }); }); saveImage = new FileChooser("$text.saveimage", false, file -> { file = file.parent().child(file.nameWithoutExtension() + ".png"); FileHandle result = file; - ui.loadfrag.show(); - Timers.run(3f, () -> { + ui.loadAnd(() -> { try{ Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result); }catch (Exception e){ ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); Log.err(e); } - ui.loadfrag.hide(); }); }); openImage = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> { - ui.loadfrag.show(); - Timers.run(3f, () -> { + ui.loadAnd(() -> { try{ MapTileData data = MapIO.readPixmap(new Pixmap(file)); @@ -130,7 +121,6 @@ public class MapEditorDialog extends Dialog{ ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } - ui.loadfrag.hide(); }); }); @@ -155,11 +145,23 @@ public class MapEditorDialog extends Dialog{ t.row(); t.addImageTextButton("$text.editor.savemap", "icon-save-map", isize, () -> { - saveFile.show(); + saveDialog.show(); menu.hide(); }); t.addImageTextButton("$text.editor.loadmap", "icon-load-map", isize, () -> { + loadDialog.show(); + menu.hide(); + }); + + t.row(); + + t.addImageTextButton("$text.editor.importmap", "icon-save-map", isize, () -> { + saveFile.show(); + menu.hide(); + }); + + t.addImageTextButton("$text.editor.exportmap", "icon-load-map", isize, () -> { openFile.show(); menu.hide(); }); @@ -189,65 +191,41 @@ public class MapEditorDialog extends Dialog{ } menu.hide(); }).size(470f, 60f); - - - /* - loadDialog = new MapLoadDialog(map -> { - saveDialog.setFieldText(map.name); - ui.loadfrag.show(); - - Timers.run(3f, () -> { - Map copy = new Map(); - copy.name = map.name; - copy.id = -1; - copy.pixmap = Pixmaps.copy(map.pixmap); - copy.texture = new Texture(copy.pixmap); - copy.oreGen = map.oreGen; - editor.beginEdit(copy); - ui.loadfrag.hide(); - view.clearStack(); - }); - });*/ resizeDialog = new MapResizeDialog(editor, (x, y) -> { if(!(editor.getMap().width() == x && editor.getMap().height() == y)){ - ui.loadfrag.show(); - Timers.run(10f, () -> { + ui.loadAnd(() -> { editor.resize(x, y); view.clearStack(); - ui.loadfrag.hide(); }); } }); - /* - saveDialog = new MapSaveDialog(name -> { - ui.loadfrag.show(); - if(verifyMap()){ - saved = true; - String before = editor.getMap().name; - editor.getMap().name = name; - Timers.run(10f, () -> { - world.maps().saveAndReload(editor.getMap(), editor.pixmap()); - loadDialog.rebuild(); - ui.loadfrag.hide(); + loadDialog = new MapLoadDialog(map -> { + saveDialog.setFieldText(map.name); + + ui.loadAnd(() -> { + try (DataInputStream stream = new DataInputStream(map.stream.get())){ + MapMeta meta = MapIO.readMapMeta(stream); + MapTileData data = MapIO.readTileData(stream, meta, false); + + editor.beginEdit(data, meta.tags); view.clearStack(); + }catch (IOException e){ + ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false))); + Log.err(e); + } + }); + }); - if(!name.equals(before)) { - Map map = new Map(); - map.name = editor.getMap().name; - map.oreGen = editor.getMap().oreGen; - map.pixmap = Pixmaps.copy(editor.getMap().pixmap); - map.texture = new Texture(map.pixmap); - map.custom = true; - editor.beginEdit(map); - } - }); - }else{ - ui.loadfrag.hide(); - } - });*/ + saveDialog = new MapSaveDialog(name -> { + ui.loadAnd(() -> { + saved = true; + world.maps().saveAndReload(editor.getTags().get("name", name), editor.getMap(), editor.getTags()); + loadDialog.rebuild(); + }); + }); setFillParent(true); diff --git a/core/src/io/anuke/mindustry/io/Map.java b/core/src/io/anuke/mindustry/io/Map.java index 2f15f897d3..4182bf1916 100644 --- a/core/src/io/anuke/mindustry/io/Map.java +++ b/core/src/io/anuke/mindustry/io/Map.java @@ -1,6 +1,9 @@ package io.anuke.mindustry.io; import com.badlogic.gdx.graphics.Texture; +import io.anuke.ucore.function.Supplier; + +import java.io.InputStream; public class Map { /**Internal map name. This is the filename, without any extensions.*/ @@ -9,12 +12,15 @@ public class Map { public final boolean custom; /**Metadata. Author description, display name, etc.*/ public final MapMeta meta; + /**Supplies a new input stream with the data of this map.*/ + public final Supplier stream; /**Preview texture.*/ public Texture texture; - public Map(String name, MapMeta meta, boolean custom){ + public Map(String name, MapMeta meta, boolean custom, Supplier streamSupplier){ this.name = name; this.custom = custom; this.meta = meta; + this.stream = streamSupplier; } } diff --git a/core/src/io/anuke/mindustry/io/Maps.java b/core/src/io/anuke/mindustry/io/Maps.java index 6a69bed0f5..7189bb5a8f 100644 --- a/core/src/io/anuke/mindustry/io/Maps.java +++ b/core/src/io/anuke/mindustry/io/Maps.java @@ -5,15 +5,18 @@ import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.function.Supplier; import io.anuke.ucore.util.Log; +import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; +import java.io.InputStream; -import static io.anuke.mindustry.Vars.customMapDirectory; -import static io.anuke.mindustry.Vars.headless; -import static io.anuke.mindustry.Vars.mapExtension; +import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ /**List of all built-in maps.*/ @@ -21,16 +24,25 @@ public class Maps implements Disposable{ /**Tile format version.*/ private static final int version = 0; + /**Maps map names to the real maps.*/ private ObjectMap maps = new ObjectMap<>(); + /**All maps stored in an ordered array.*/ private Array allMaps = new Array<>(); + /**Temporary array used for returning things.*/ private Array returnArray = new Array<>(); + /**Used for writing a list of custom map names on GWT.*/ + private Json json = new Json(); + + public Maps(){ + + } /**Returns a list of all maps, including custom ones.*/ public Array all(){ return allMaps; } - /**Returns a list of only custo maps.*/ + /**Returns a list of only custom maps.*/ public Array customMaps(){ returnArray.clear(); for(Map map : allMaps){ @@ -57,32 +69,61 @@ public class Maps implements Disposable{ public void load(){ try { for (String name : defaultMapNames) { - loadMap(Gdx.files.internal("maps/" + name + "." + mapExtension), false); + FileHandle file = Gdx.files.internal("maps/" + name + "." + mapExtension); + loadMap(file.nameWithoutExtension(), file::read, false); } }catch (IOException e){ throw new RuntimeException(e); } - for(FileHandle file : customMapDirectory.list()){ - try{ - if(file.extension().toLowerCase().equals(mapExtension)) loadMap(file, true); - }catch (IOException e){ - Log.err("Failed to load custom map file '{0}'!", file); - Log.err(e); - } - } + loadCustomMaps(); } - private void loadMap(FileHandle file, boolean custom) throws IOException{ - DataInputStream ds = new DataInputStream(file.read()); - MapMeta meta = MapIO.readMapMeta(ds); - Map map = new Map(file.nameWithoutExtension(), meta, custom); - if(!headless) map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true))); - - maps.put(map.name, map); - allMaps.add(map); + public void saveAndReload(String name, MapTileData data, ObjectMap tags){ + FileHandle file = customMapDirectory.child(name + "." + mapExtension); + //todo implement } + private void loadMap(String name, Supplier supplier, boolean custom) throws IOException{ + try(DataInputStream ds = new DataInputStream(supplier.get())) { + MapMeta meta = MapIO.readMapMeta(ds); + Map map = new Map(name, meta, custom, supplier); + if (!headless) map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true))); + + maps.put(map.name, map); + allMaps.add(map); + } + } + + private void loadCustomMaps(){ + if(!gwt){ + for(FileHandle file : customMapDirectory.list()){ + try{ + if(file.extension().equalsIgnoreCase(mapExtension)){ + loadMap(file.nameWithoutExtension(), file::read, true); + } + }catch (Exception e){ + Log.err("Failed to load custom map file '{0}'!", file); + Log.err(e); + } + } + + }else{ + Array maps = json.fromJson(Array.class, Settings.getString("custom-maps", "{}")); + + for(String name : maps){ + try{ + String data = Settings.getString("map-data-" + name); + byte[] bytes = data.getBytes(); + loadMap(name, () -> new ByteArrayInputStream(bytes), true); + }catch (Exception e){ + Log.err("Failed to load custom map '{0}'!", name); + Log.err(e); + } + } + } + } + @Override public void dispose() { diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index a1adb05a6d..ac4baeb127 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -51,7 +51,7 @@ public class DebugFragment implements Fragment { abottom().aleft(); new table("pane"){{ - defaults().fillX(); + defaults().fillX().width(100f); new label("Debug"); row();