Added very basic exporting, preview and a test map

This commit is contained in:
Anuken
2018-03-21 00:31:43 -04:00
parent e330b28e49
commit 23e6f89eef
14 changed files with 207 additions and 101 deletions

View File

@@ -86,7 +86,8 @@ public class Logic extends Module {
if(!Net.client())
world.pathfinder().update();
if(world.getAllyCores().size == 0 && !state.gameOver){
if(world.getAllyCores().size == 0 && !state.gameOver && false){ //TODO gameover state
state.gameOver = true;
if(Net.server()) NetEvents.handleGameOver();
Events.fire(GameOverEvent.class);

View File

@@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.ai.Pathfind;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.io.Maps;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
@@ -174,7 +175,7 @@ public class World extends Module{
Entities.resizeTree(0, 0, width * tilesize, height * tilesize);
WorldGenerator.generate(tiles, maps.readTileData(map));
WorldGenerator.generate(tiles, MapIO.readTileData(map));
}
void set(int x, int y, Block type, int rot){

View File

@@ -2,7 +2,7 @@ package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.Disposable;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import java.nio.ByteBuffer;
@@ -11,11 +11,11 @@ public class DrawOperation implements Disposable{
MapTileData data;
/**Format:
* position (int)
* packed data FROM (use TileDataWriter's read/write methods)
* packed data TO (use TileDataWriter's read/write methods)
* packed data FROM (use TileDataMarker's read/write methods)
* packed data TO (use TileDataMarker's read/write methods)
*/
ByteBuffer operation;
TileDataWriter writer = new TileDataWriter();
TileDataMarker writer = new TileDataMarker();
public DrawOperation(MapTileData data){
this.data = data;

View File

@@ -2,7 +2,7 @@ package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.types.Floor;
@@ -11,7 +11,7 @@ import static io.anuke.mindustry.Vars.ui;
public enum EditorTool{
pick{
public void touched(MapEditor editor, int x, int y){
TileDataWriter writer = editor.getMap().readAt(x, y);
TileDataMarker writer = editor.getMap().readAt(x, y);
Block block = Block.getByID(writer.wall == 0 ? writer.floor : writer.wall);
editor.setDrawBlock(block);
ui.editor.updateSelectedBlock();
@@ -42,7 +42,7 @@ public enum EditorTool{
//TODO select floor/block properly instead of using this method!
boolean floor = editor.getDrawBlock() instanceof Floor;
TileDataWriter writer = editor.getMap().readAt(x, y);
TileDataMarker writer = editor.getMap().readAt(x, y);
byte dest = floor ? writer.floor : writer.wall;

View File

@@ -1,7 +1,7 @@
package io.anuke.mindustry.editor;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.Floor;
@@ -53,7 +53,7 @@ public class MapEditor{
return;
}
TileDataWriter writer = map.readAt(dx, dy);
TileDataMarker writer = map.readAt(dx, dy);
if(drawBlock instanceof Floor){
writer.floor = (byte)drawBlock.id;
}else{

View File

@@ -1,10 +1,15 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.Platform;
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.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
@@ -20,9 +25,11 @@ import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Strings;
import static io.anuke.mindustry.Vars.gwt;
import static io.anuke.mindustry.Vars.ui;
import static io.anuke.mindustry.Vars.*;
public class MapEditorDialog extends Dialog{
private MapEditor editor;
@@ -32,7 +39,9 @@ public class MapEditorDialog extends Dialog{
private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog;
private ScrollPane pane;
//private FileChooser openFile, saveFile;
private FloatingDialog menu;
private FileChooser openFile, saveFile;
private ObjectMap<String, String> tags = new ObjectMap<>();
private boolean saved = false;
private ButtonGroup<ImageButton> blockgroup;
@@ -44,6 +53,44 @@ public class MapEditorDialog extends Dialog{
editor = new MapEditor();
dialog = new MapGenerateDialog(editor);
view = new MapView(editor);
saveFile = new FileChooser("$saveimage", false, file -> {
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file;
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
MapIO.writeMap(result, tags, editor.getMap());
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
}
ui.loadfrag.hide();
});
});
menu = new FloatingDialog("$text.menu");
menu.addCloseButton();
menu.content().defaults().size(240f, 60f).padBottom(5);
float isize = 16*2f;
menu.content().addImageButton("icon-back", isize, () -> {
if(!saved){
ui.showConfirm("$text.confirm", "$text.editor.unsaved", this::hide);
}else{
hide();
}
});
menu.content().row();
menu.content().addImageButton("icon-save", isize, () -> {
saveFile.show();
});
/*
openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
ui.loadfrag.show();
@@ -64,22 +111,7 @@ public class MapEditorDialog extends Dialog{
});
});
saveFile = new FileChooser("$saveimage", false, file -> {
if(!file.extension().toLowerCase().equals(".png")){
file = file.parent().child(file.nameWithoutExtension() + ".png");
}
FileHandle result = file;
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
Pixmaps.write(editor.pixmap(), result);
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
if(!android) Log.err(e);
}
ui.loadfrag.hide();
});
});*/
*/
/*
loadDialog = new MapLoadDialog(map -> {
saveDialog.setFieldText(map.name);
@@ -173,7 +205,7 @@ public class MapEditorDialog extends Dialog{
@Override
public Dialog show(){
return super.show(Core.scene, Actions.sequence(Actions.alpha(0f), Actions.fadeIn(0.3f)));
return super.show(Core.scene, Actions.sequence(Actions.scaleTo(1f, 1f), Actions.alpha(0f), Actions.fadeIn(0.3f)));
}
public MapView getView() {
@@ -215,6 +247,12 @@ public class MapEditorDialog extends Dialog{
tools.defaults().size(60f, 64f).padBottom(-5.1f);
tools.addImageButton("icon-arrow-left", 14*3f, () -> hide());
tools.addImageButton("icon-menu", 14*3f, menu::show);
tools.row();
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).get();

View File

@@ -3,7 +3,7 @@ package io.anuke.mindustry.editor;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.IntSet.IntSetIterator;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.core.Core;
@@ -11,7 +11,6 @@ import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.IndexedRenderer;
import io.anuke.ucore.util.Log;
import static io.anuke.mindustry.Vars.tilesize;
@@ -50,8 +49,6 @@ public class MapRenderer {
public void draw(float tx, float ty, float tw, float th){
Timers.mark();
Graphics.end();
IntSetIterator it = updates.iterator();
@@ -78,8 +75,6 @@ public class MapRenderer {
Graphics.begin();
long i = Timers.elapsed();
if(i > 2) Log.info("Time to render: {0}", i);
}
public void updatePoint(int x, int y){
@@ -98,7 +93,7 @@ public class MapRenderer {
private void render(int wx, int wy){
int x = wx/chunksize, y = wy/chunksize;
IndexedRenderer mesh = chunks[x][y];
TileDataWriter data = editor.getMap().readAt(wx, wy);
TileDataMarker data = editor.getMap().readAt(wx, wy);
Block floor = Block.getByID(data.floor);
Block wall = Block.getByID(data.wall);

View File

@@ -1,8 +1,119 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectMap.Entry;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static io.anuke.mindustry.Vars.customMapDirectory;
import static io.anuke.mindustry.Vars.mapExtension;
/**Reads and writes map files.*/
//TODO GWT support
public class MapIO {
//TODO implementation
private static final int version = 0;
public static Pixmap generatePixmap(MapTileData data){
Pixmap pixmap = new Pixmap(data.width(), data.height(), Format.RGBA8888);
for(int x = 0; x < data.width(); x ++){
for(int y = 0; y < data.height(); y ++){
TileDataMarker marker = data.read();
Block floor = Block.getByID(marker.floor);
Block wall = Block.getByID(marker.wall);
int wallc = ColorMapper.getColor(wall);
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, wallc == 0 ? ColorMapper.getColor(floor) : wallc);
}
}
return pixmap;
}
public static void writeMap(FileHandle file, ObjectMap<String, String> tags, MapTileData data) throws IOException{
MapMeta meta = new MapMeta(version, tags, data.width(), data.height());
DataOutputStream ds = new DataOutputStream(file.write(false));
writeMapMeta(ds, meta);
ds.write(data.toArray());
ds.close();
}
/**Reads tile data, skipping meta.*/
public static MapTileData readTileData(DataInputStream stream) throws IOException {
MapMeta meta = readMapMeta(stream);
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
return new MapTileData(bytes, meta.width, meta.height);
}
/**Does not skip meta. Call after reading meta.*/
public static MapTileData readTileData(DataInputStream stream, MapMeta meta) throws IOException {
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
return new MapTileData(bytes, meta.width, meta.height);
}
/**Reads tile data, skipping meta tags.*/
public static MapTileData readTileData(Map map){
try {
InputStream stream;
if (!map.custom) {
stream = Gdx.files.local("maps/" + map.name + "." + mapExtension).read();
} else {
stream = customMapDirectory.child(map.name + "." + mapExtension).read();
}
DataInputStream ds = new DataInputStream(stream);
MapTileData data = MapIO.readTileData(ds);
ds.close();
return data;
}catch (IOException e){
throw new RuntimeException(e);
}
}
public static MapMeta readMapMeta(DataInputStream stream) throws IOException{
ObjectMap<String, String> tags = new ObjectMap<>();
int version = stream.readInt();
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i ++){
String name = stream.readUTF();
String value = stream.readUTF();
tags.put(name, value);
}
int width = stream.readShort();
int height = stream.readShort();
return new MapMeta(version, tags, width, height);
}
public static void writeMapMeta(DataOutputStream stream, MapMeta meta) throws IOException{
stream.writeInt(meta.version);
stream.writeByte((byte)meta.tags.size);
for(Entry<String, String> entry : meta.tags.entries()){
stream.writeUTF(entry.key);
stream.writeUTF(entry.value);
}
stream.writeShort(meta.width);
stream.writeShort(meta.height);
}
}

View File

@@ -12,7 +12,7 @@ public class MapTileData {
private final static int TILE_SIZE = 3;
private final ByteBuffer buffer;
private final TileDataWriter tile = new TileDataWriter();
private final TileDataMarker tile = new TileDataMarker();
private final int width, height;
public MapTileData(int width, int height){
@@ -27,6 +27,10 @@ public class MapTileData {
this.height = height;
}
public byte[] toArray(){
return buffer.array();
}
public int width(){
return width;
}
@@ -36,20 +40,20 @@ public class MapTileData {
}
/**Reads and returns the next tile data.*/
public TileDataWriter read(){
public TileDataMarker read(){
tile.read(buffer);
return tile;
}
/**Reads and returns the next tile data.*/
public TileDataWriter readAt(int x, int y){
public TileDataMarker readAt(int x, int y){
position(x, y);
tile.read(buffer);
return tile;
}
/**Writes tile data at a specified position.*/
public void write(int x, int y, TileDataWriter writer){
public void write(int x, int y, TileDataMarker writer){
position(x, y);
writer.write(buffer);
}
@@ -59,7 +63,7 @@ public class MapTileData {
buffer.position((x + width * y) * TILE_SIZE);
}
public static class TileDataWriter {
public static class TileDataMarker {
public byte floor, wall;
public byte rotation;
public byte team;

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.io;
import com.badlogic.gdx.Gdx;
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.ObjectMap;
@@ -9,14 +10,15 @@ import io.anuke.ucore.util.Log;
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.mapExtension;
public class Maps implements Disposable{
/**List of all built-in maps.*/
private static final String[] defaultMapNames = {};
private static final String[] defaultMapNames = {"test"};
/**Tile format version.*/
private static final int version = 0;
private ObjectMap<String, Map> maps = new ObjectMap<>();
private Array<Map> allMaps = new Array<>();
@@ -50,27 +52,6 @@ public class Maps implements Disposable{
return maps.get(name);
}
//TODO GWT support: read from prefs string if custom
/**Reads all tile data from a map. Should be used sparingly.*/
public MapTileData readTileData(Map map){
try {
InputStream stream;
if (map.custom) {
stream = Gdx.files.local("maps/" + map.name + "." + mapExtension).read();
} else {
stream = customMapDirectory.child(map.name + "." + mapExtension).read();
}
DataInputStream ds = new DataInputStream(stream);
MapTileData data = readTileData(ds);
ds.close();
return data;
}catch (IOException e){
throw new RuntimeException(e);
}
}
/**Load all maps. Should be called at application start.*/
public void load(){
try {
@@ -93,39 +74,14 @@ public class Maps implements Disposable{
private void loadMap(FileHandle file, boolean custom) throws IOException{
DataInputStream ds = new DataInputStream(file.read());
MapMeta meta = readMapMeta(ds);
MapMeta meta = MapIO.readMapMeta(ds);
Map map = new Map(file.nameWithoutExtension(), meta, custom);
map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta)));
maps.put(map.name, map);
allMaps.add(map);
}
private MapTileData readTileData(DataInputStream stream) throws IOException{
MapMeta meta = readMapMeta(stream);
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
return new MapTileData(bytes, meta.width, meta.height);
}
private MapMeta readMapMeta(DataInputStream stream) throws IOException{
ObjectMap<String, String> tags = new ObjectMap<>();
int version = stream.readInt();
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i ++){
String name = stream.readUTF();
String value = stream.readUTF();
tags.put(name, value);
}
int width = stream.readShort();
int height = stream.readShort();
return new MapMeta(version, tags, width, height);
}
@Override
public void dispose() {

View File

@@ -2,7 +2,7 @@ package io.anuke.mindustry.world;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.noise.Noise;
@@ -23,7 +23,7 @@ public class WorldGenerator {
for(int x = 0; x < data.width(); x ++){
for(int y = 0; y < data.height(); y ++){
TileDataWriter tile = data.read();
TileDataMarker tile = data.read();
tiles[x][y] = new Tile(x, y, tile.floor, tile.wall, tile.rotation, tile.team);
//TODO ores, plants, extra decoration?

View File

@@ -10,9 +10,6 @@ import io.anuke.mindustry.world.blocks.types.*;
public class Blocks{
public static final Block
//player/enemy spawnpoint
spawn = new Block("spawn"){},
air = new Block("air"){
//no drawing here
@@ -21,6 +18,9 @@ public class Blocks{
//update floor blocks for effects, if needed
public void draw(Tile tile){}
},
//player/enemy spawnpoint
spawn = new Block("spawn"){},
blockpart = new BlockPart(){