mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-10 02:37:12 +07:00
Removed useless name mapping / Cleanup
This commit is contained in:
parent
ad059cbc38
commit
6c8d80777c
@ -1,7 +1,7 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.annotations.Annotations.Struct;
|
||||
import io.anuke.arc.collection.LongArray;
|
||||
import io.anuke.arc.util.Pack;
|
||||
|
||||
public class DrawOperation{
|
||||
private LongArray array = new LongArray();
|
||||
@ -10,8 +10,8 @@ public class DrawOperation{
|
||||
return array.isEmpty();
|
||||
}
|
||||
|
||||
public void addOperation(int xy, byte type, byte from, byte to){
|
||||
array.add(Pack.longInt(xy, Pack.intBytes(type, from, to, (byte)0)));
|
||||
public void addOperation(long op){
|
||||
array.add(op);
|
||||
}
|
||||
|
||||
public void undo(MapEditor editor){
|
||||
@ -25,4 +25,13 @@ public class DrawOperation{
|
||||
long l = array.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Struct
|
||||
class TileOpStruct{
|
||||
short x;
|
||||
short y;
|
||||
byte type;
|
||||
byte from;
|
||||
byte to;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.arc.collection.GridBits;
|
||||
import io.anuke.arc.collection.ObjectMap;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.Pack;
|
||||
@ -7,6 +8,7 @@ import io.anuke.arc.util.Structs;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.TileOp;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
@ -19,11 +21,16 @@ public class MapEditor{
|
||||
|
||||
private ObjectMap<String, String> tags = new ObjectMap<>();
|
||||
private MapRenderer renderer = new MapRenderer(this);
|
||||
private Tile[][] tiles;
|
||||
|
||||
private int brushSize = 1;
|
||||
private int rotation;
|
||||
private Block drawBlock = Blocks.stone;
|
||||
private Team drawTeam = Team.blue;
|
||||
private OperationStack stack = new OperationStack();
|
||||
private DrawOperation op;
|
||||
private GridBits used;
|
||||
|
||||
public int brushSize = 1;
|
||||
public int rotation;
|
||||
public Block drawBlock = Blocks.stone;
|
||||
public Team drawTeam = Team.blue;
|
||||
|
||||
public ObjectMap<String, String> getTags(){
|
||||
return tags;
|
||||
@ -46,36 +53,16 @@ public class MapEditor{
|
||||
renderer.resize(map.length, map[0].length);
|
||||
}
|
||||
|
||||
public int getDrawRotation(){
|
||||
return rotation;
|
||||
public Tile[][] tiles(){
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public void setDrawRotation(int rotation){
|
||||
this.rotation = rotation;
|
||||
public int width(){
|
||||
return tiles.length;
|
||||
}
|
||||
|
||||
public Team getDrawTeam(){
|
||||
return drawTeam;
|
||||
}
|
||||
|
||||
public void setDrawTeam(Team team){
|
||||
this.drawTeam = team;
|
||||
}
|
||||
|
||||
public Block getDrawBlock(){
|
||||
return drawBlock;
|
||||
}
|
||||
|
||||
public void setDrawBlock(Block block){
|
||||
this.drawBlock = block;
|
||||
}
|
||||
|
||||
public int getBrushSize(){
|
||||
return brushSize;
|
||||
}
|
||||
|
||||
public void setBrushSize(int size){
|
||||
this.brushSize = size;
|
||||
public int height(){
|
||||
return tiles[0].length;
|
||||
}
|
||||
|
||||
public void draw(int x, int y, boolean paint){
|
||||
@ -229,23 +216,47 @@ public class MapEditor{
|
||||
}
|
||||
|
||||
public void resize(int width, int height){
|
||||
MapTileData previous = map;
|
||||
int offsetX = -(width - previous.width())/2, offsetY = -(height - previous.height())/2;
|
||||
Tile[][] previous = tiles;
|
||||
int offsetX = -(width - width())/2, offsetY = -(height - height())/2;
|
||||
|
||||
map = new MapTileData(width, height);
|
||||
for(int x = 0; x < map.width(); x++){
|
||||
for(int y = 0; y < map.height(); y++){
|
||||
tiles = new Tile[width][height];
|
||||
for(int x = 0; x < width; x++){
|
||||
for(int y = 0; y < height; y++){
|
||||
int px = offsetX + x, py = offsetY + y;
|
||||
if(Structs.inBounds(px, py, previous.width(), previous.height())){
|
||||
map.write(x, y, DataPosition.floor, previous.read(px, py, DataPosition.floor));
|
||||
map.write(x, y, DataPosition.wall, previous.read(px, py, DataPosition.wall));
|
||||
map.write(x, y, DataPosition.link, previous.read(px, py, DataPosition.link));
|
||||
map.write(x, y, DataPosition.rotationTeam, previous.read(px, py, DataPosition.rotationTeam));
|
||||
if(Structs.inBounds(px, py, previous.length, previous[0].length)){
|
||||
tiles[x][y] = previous[px][py];
|
||||
tiles[x][y].x = (short)x;
|
||||
tiles[x][y].y = (short)y;
|
||||
}else{
|
||||
map.write(x, y, DataPosition.floor, Blocks.stone.id);
|
||||
tiles[x][y] = new Tile(x, y, Blocks.stone.id, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
renderer.resize(width, height);
|
||||
}
|
||||
|
||||
public void undo(){
|
||||
if(stack.canUndo()){
|
||||
stack.undo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void redo(){
|
||||
if(stack.canRedo()){
|
||||
stack.redo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTileOp(long data){
|
||||
used.set(TileOp.x(data), TileOp.y(data));
|
||||
op.addOperation(data);
|
||||
}
|
||||
|
||||
public boolean checkUsed(short x, short y){
|
||||
if(used == null || used.width() != width() || used.height() != height()){
|
||||
used = new GridBits(world.width(), world.height());
|
||||
}
|
||||
|
||||
return used.get(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -291,14 +291,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
editor.renderer().dispose();
|
||||
}
|
||||
|
||||
public void beginEditMap(InputStream is){
|
||||
public void beginEditMap(FileHandle file){
|
||||
ui.loadAnd(() -> {
|
||||
try{
|
||||
shownWithMap = true;
|
||||
DataInputStream stream = new DataInputStream(is);
|
||||
MapMeta meta = MapIO.readMapMeta(stream);
|
||||
editor.beginEdit(MapIO.readTileData(stream, meta, false), meta.tags, false);
|
||||
is.close();
|
||||
editor.beginEdit(MapIO.readTiles(file));
|
||||
show();
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
@ -316,9 +313,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
}
|
||||
|
||||
public void updateSelectedBlock(){
|
||||
Block block = editor.getDrawBlock();
|
||||
for(int j = 0; j < Vars.content.blocks().size; j++){
|
||||
if(block.id == j && j < blockgroup.getButtons().size){
|
||||
if(editor.drawBlock.id == j && j < blockgroup.getButtons().size){
|
||||
blockgroup.getButtons().get(j).setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
@ -1,22 +1,20 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.arc.function.BiConsumer;
|
||||
import io.anuke.arc.function.IntPositionConsumer;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.mindustry.maps.MapTileData;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
|
||||
public class MapResizeDialog extends FloatingDialog{
|
||||
private static final int minSize = 50, maxSize = 500, increment = 50;
|
||||
int width, height;
|
||||
|
||||
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
|
||||
public MapResizeDialog(MapEditor editor, IntPositionConsumer cons){
|
||||
super("$editor.resizemap");
|
||||
shown(() -> {
|
||||
cont.clear();
|
||||
MapTileData data = editor.getMap();
|
||||
width = data.width();
|
||||
height = data.height();
|
||||
width = editor.width();
|
||||
height = editor.height();
|
||||
|
||||
Table table = new Table();
|
||||
|
||||
|
@ -19,6 +19,7 @@ import io.anuke.arc.scene.event.Touchable;
|
||||
import io.anuke.arc.scene.ui.TextField;
|
||||
import io.anuke.arc.scene.ui.layout.Unit;
|
||||
import io.anuke.arc.util.Tmp;
|
||||
import io.anuke.mindustry.graphics.Pal;
|
||||
import io.anuke.mindustry.input.Binding;
|
||||
import io.anuke.mindustry.ui.GridImage;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
@ -28,8 +29,8 @@ import static io.anuke.mindustry.Vars.*;
|
||||
public class MapView extends Element implements GestureListener{
|
||||
private MapEditor editor;
|
||||
private EditorTool tool = EditorTool.pencil;
|
||||
private OperationStack stack = new OperationStack();
|
||||
private DrawOperation op;
|
||||
//private OperationStack stack = new OperationStack();
|
||||
//private DrawOperation op;
|
||||
private GridBits used;
|
||||
private Bresenham2 br = new Bresenham2();
|
||||
private boolean updated = false;
|
||||
|
@ -5,6 +5,7 @@ import io.anuke.arc.collection.ObjectMap.Entry;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.graphics.Pixmap;
|
||||
import io.anuke.arc.graphics.Pixmap.Format;
|
||||
import io.anuke.arc.util.Pack;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.game.MappableContent;
|
||||
@ -41,10 +42,21 @@ public class MapIO{
|
||||
}
|
||||
|
||||
//TODO implement
|
||||
public static Pixmap unfinished_generatePreview(Map map){
|
||||
public static Pixmap generatePreview(Map map){
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Pixmap generatePreview(Tile[][] tiles){
|
||||
Pixmap pixmap = new Pixmap(tiles.length, tiles[0].length, Format.RGBA8888);
|
||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||
Tile tile = tiles[x][y];
|
||||
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.getTeam()));
|
||||
}
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
//TODO implement
|
||||
/**Reads a pixmap in the 3.5 pixmap format.*/
|
||||
public static Tile[][] unfinished_readLegacyPixmap(Pixmap pixmap){
|
||||
@ -64,7 +76,7 @@ public class MapIO{
|
||||
return Color.rgba8888(wall.solid ? wall.color : floor.color);
|
||||
}
|
||||
|
||||
public static void writeMap(Map map, Tile[][] tiles, OutputStream output) throws IOException{
|
||||
public static void writeMap(OutputStream output, Map map, Tile[][] tiles) throws IOException{
|
||||
try(DataOutputStream stream = new DataOutputStream(output)){
|
||||
stream.writeInt(version);
|
||||
stream.writeInt(Version.build);
|
||||
@ -103,7 +115,7 @@ public class MapIO{
|
||||
i += consecutives;
|
||||
}
|
||||
|
||||
//blocks
|
||||
//then blocks
|
||||
for(int i = 0; i < tiles.length * tiles[0].length; i++){
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
stream.writeByte(tile.getBlockID());
|
||||
@ -135,8 +147,8 @@ public class MapIO{
|
||||
}
|
||||
}
|
||||
|
||||
public static Map readMap(String useName, InputStream input) throws IOException{
|
||||
try(DataInputStream stream = new DataInputStream(input)){
|
||||
public static Map readMap(FileHandle file, boolean custom) throws IOException{
|
||||
try(DataInputStream stream = new DataInputStream(file.read())){
|
||||
ObjectMap<String, String> tags = new ObjectMap<>();
|
||||
|
||||
//meta is uncompressed
|
||||
@ -151,34 +163,53 @@ public class MapIO{
|
||||
tags.put(name, value);
|
||||
}
|
||||
|
||||
return new Map(useName, width, height);
|
||||
return new Map(file, width, height, tags, custom);
|
||||
}
|
||||
}
|
||||
|
||||
public static Tile[][] readTiles(Map map, Tile[][] tiles) throws IOException{
|
||||
return readTiles(map.stream.get(), map.width, map.height, tiles);
|
||||
return readTiles(map.file, map.width, map.height, tiles);
|
||||
}
|
||||
|
||||
public static Tile[][] readTiles(InputStream input, int width, int height, Tile[][] tiles) throws IOException{
|
||||
readMap("this map name is utterly irrelevant", input);
|
||||
public static Tile[][] readTiles(FileHandle file, int width, int height, Tile[][] tiles) throws IOException{
|
||||
readMap(file, false);
|
||||
|
||||
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
|
||||
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(file.read()))){
|
||||
|
||||
MappableContent[][] c = SaveIO.getSaveWriter().readContentHeader(stream);
|
||||
|
||||
try{
|
||||
content.setTemporaryMapper(c);
|
||||
//TODO 2-phase rle
|
||||
|
||||
//read floor and create tiles first
|
||||
for(int i = 0; i < width * height; i++){
|
||||
int x = i % width, y = i / width;
|
||||
byte floorid = stream.readByte();
|
||||
byte wallid = stream.readByte();
|
||||
byte oreid = stream.readByte();
|
||||
int consecutives = stream.readUnsignedByte();
|
||||
|
||||
Tile tile = new Tile(x, y, floorid, wallid);
|
||||
tiles[x][y] = new Tile(x, y, floorid, (byte)0);
|
||||
tiles[x][y].setOre(oreid);
|
||||
|
||||
if(wallid == Blocks.part.id){
|
||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
||||
int newx = j % width, newy = j / width;
|
||||
Tile newTile = new Tile(newx, newy, floorid, (byte)0);
|
||||
newTile.setOre(oreid);
|
||||
tiles[newx][newy] = newTile;
|
||||
}
|
||||
|
||||
i += consecutives;
|
||||
}
|
||||
|
||||
//read blocks
|
||||
for(int i = 0; i < width * height; i++){
|
||||
int x = i % width, y = i / width;
|
||||
Block block = content.block(stream.readByte());
|
||||
|
||||
Tile tile = tiles[x][y];
|
||||
tile.setBlock(block);
|
||||
|
||||
if(block == Blocks.part){
|
||||
tile.link = stream.readByte();
|
||||
}else if(tile.entity != null){
|
||||
byte tr = stream.readByte();
|
||||
@ -192,20 +223,16 @@ public class MapIO{
|
||||
tile.setRotation(rotation);
|
||||
|
||||
tile.entity.readConfig(stream);
|
||||
}else if(wallid == 0){
|
||||
}else{ //no entity/part, read consecutives
|
||||
int consecutives = stream.readUnsignedByte();
|
||||
|
||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
||||
int newx = j % width, newy = j / width;
|
||||
Tile newTile = new Tile(newx, newy, floorid, wallid);
|
||||
newTile.setOre(oreid);
|
||||
tiles[newx][newy] = newTile;
|
||||
tiles[newx][newy].setBlock(block);
|
||||
}
|
||||
|
||||
i += consecutives;
|
||||
}
|
||||
|
||||
tiles[x][y] = tile;
|
||||
}
|
||||
|
||||
return tiles;
|
||||
|
@ -14,6 +14,7 @@ import io.anuke.mindustry.game.Rules;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.Serialization;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||
|
||||
@ -42,17 +43,36 @@ public abstract class SaveFileVersion{
|
||||
return new SaveMeta(version, time, playtime, build, map, wave, rules);
|
||||
}
|
||||
|
||||
//TODO 2-phase rle
|
||||
public void writeMap(DataOutputStream stream) throws IOException{
|
||||
|
||||
//write world size
|
||||
stream.writeShort(world.width());
|
||||
stream.writeShort(world.height());
|
||||
|
||||
//floor first
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
|
||||
stream.writeByte(tile.getFloorID());
|
||||
stream.writeByte(tile.getOre());
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getOre() != tile.getOre()){
|
||||
break;
|
||||
}
|
||||
|
||||
consecutives++;
|
||||
}
|
||||
|
||||
stream.writeByte(consecutives);
|
||||
i += consecutives;
|
||||
}
|
||||
|
||||
//blocks
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
stream.writeByte(tile.getBlockID());
|
||||
|
||||
if(tile.block() instanceof BlockPart){
|
||||
@ -68,13 +88,14 @@ public abstract class SaveFileVersion{
|
||||
|
||||
tile.entity.writeConfig(stream);
|
||||
tile.entity.write(stream);
|
||||
}else if(tile.block() == Blocks.air){
|
||||
}else{
|
||||
//write consecutive non-entity blocks
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air){
|
||||
if(nextTile.block() != tile.block()){
|
||||
break;
|
||||
}
|
||||
|
||||
@ -87,7 +108,6 @@ public abstract class SaveFileVersion{
|
||||
}
|
||||
}
|
||||
|
||||
//TODO 2-phase rle
|
||||
public void readMap(DataInputStream stream) throws IOException{
|
||||
short width = stream.readShort();
|
||||
short height = stream.readShort();
|
||||
@ -96,14 +116,33 @@ public abstract class SaveFileVersion{
|
||||
|
||||
Tile[][] tiles = world.createTiles(width, height);
|
||||
|
||||
//read floor and create tiles first
|
||||
for(int i = 0; i < width * height; i++){
|
||||
int x = i % width, y = i / width;
|
||||
byte floorid = stream.readByte();
|
||||
byte wallid = stream.readByte();
|
||||
byte oreid = stream.readByte();
|
||||
int consecutives = stream.readUnsignedByte();
|
||||
|
||||
Tile tile = new Tile(x, y, floorid, wallid);
|
||||
tiles[x][y] = new Tile(x, y, floorid, (byte)0);
|
||||
tiles[x][y].setOre(oreid);
|
||||
|
||||
if(wallid == Blocks.part.id){
|
||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
||||
int newx = j % width, newy = j / width;
|
||||
Tile newTile = new Tile(newx, newy, floorid, (byte)0);
|
||||
newTile.setOre(oreid);
|
||||
tiles[newx][newy] = newTile;
|
||||
}
|
||||
|
||||
i += consecutives;
|
||||
}
|
||||
|
||||
//read blocks
|
||||
for(int i = 0; i < width * height; i++){
|
||||
int x = i % width, y = i / width;
|
||||
Block block = content.block(stream.readByte());
|
||||
Tile tile = tiles[x][y];
|
||||
|
||||
if(block == Blocks.part){
|
||||
tile.link = stream.readByte();
|
||||
}else if(tile.entity != null){
|
||||
byte tr = stream.readByte();
|
||||
@ -123,13 +162,12 @@ public abstract class SaveFileVersion{
|
||||
|
||||
tile.entity.readConfig(stream);
|
||||
tile.entity.read(stream);
|
||||
}else if(wallid == 0){
|
||||
}else{
|
||||
int consecutives = stream.readUnsignedByte();
|
||||
|
||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
||||
int newx = j % width, newy = j / width;
|
||||
Tile newTile = new Tile(newx, newy, floorid, wallid);
|
||||
tiles[newx][newy] = newTile;
|
||||
tiles[newx][newy].setBlock(block);
|
||||
}
|
||||
|
||||
i += consecutives;
|
||||
|
@ -2,40 +2,35 @@ package io.anuke.mindustry.maps;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.ObjectMap;
|
||||
import io.anuke.arc.function.Supplier;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.graphics.Texture;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class Map{
|
||||
/** Internal map name. This is the filename, without any extensions.*/
|
||||
public final String name;
|
||||
/** Whether this is a custom map.*/
|
||||
public final boolean custom;
|
||||
/** Metadata. Author description, display name, etc.*/
|
||||
public final ObjectMap<String, String> tags;
|
||||
/** Supplies a new input stream with the data of this map.*/
|
||||
public final Supplier<InputStream> stream;
|
||||
/** Base file of this map.*/
|
||||
public final FileHandle file;
|
||||
/**Map width/height, shorts.*/
|
||||
public int width, height;
|
||||
/** Preview texture.*/
|
||||
public Texture texture;
|
||||
|
||||
public Map(String name, int width, int height, ObjectMap<String, String> tags, boolean custom, Supplier<InputStream> streamSupplier){
|
||||
this.name = name;
|
||||
public Map(FileHandle file, int width, int height, ObjectMap<String, String> tags, boolean custom){
|
||||
this.custom = custom;
|
||||
this.tags = tags;
|
||||
this.stream = streamSupplier;
|
||||
this.file = file;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public Map(String name, int width, int height){
|
||||
this(name, width, height, new ObjectMap<>(), true, () -> null);
|
||||
public String fileName(){
|
||||
return file.nameWithoutExtension();
|
||||
}
|
||||
|
||||
public String getDisplayName(){
|
||||
return tags.get("name", name);
|
||||
return tags.get("name", fileName());
|
||||
}
|
||||
|
||||
public String author(){
|
||||
@ -57,7 +52,7 @@ public class Map{
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Map{" +
|
||||
"name='" + name + '\'' +
|
||||
"file='" + file + '\'' +
|
||||
", custom=" + custom +
|
||||
", tags=" + tags +
|
||||
'}';
|
||||
|
@ -1,166 +1,125 @@
|
||||
package io.anuke.mindustry.maps;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.graphics.Texture;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.util.Disposable;
|
||||
import io.anuke.arc.collection.ObjectMap;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.arc.function.Supplier;
|
||||
import io.anuke.arc.util.Log;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Maps implements Disposable{
|
||||
/**List of all built-in maps.*/
|
||||
private static final String[] defaultMapNames = {};
|
||||
/**Tile format version.*/
|
||||
private static final int version = 0;
|
||||
/** List of all built-in maps. */
|
||||
private static final String[] defaultMapNames = {"impact0079"};
|
||||
/** All maps stored in an ordered array. */
|
||||
private Array<Map> maps = new Array<>();
|
||||
|
||||
/**Maps map names to the real maps.*/
|
||||
private ObjectMap<String, Map> maps = new ObjectMap<>();
|
||||
/**All maps stored in an ordered array.*/
|
||||
private Array<Map> allMaps = new Array<>();
|
||||
/**Temporary array used for returning things.*/
|
||||
private Array<Map> returnArray = new Array<>();
|
||||
|
||||
/**Returns a list of all maps, including custom ones.*/
|
||||
/** Returns a list of all maps, including custom ones. */
|
||||
public Array<Map> all(){
|
||||
return allMaps;
|
||||
return maps;
|
||||
}
|
||||
|
||||
/**Returns a list of only custom maps.*/
|
||||
/** Returns a list of only custom maps. */
|
||||
public Array<Map> customMaps(){
|
||||
returnArray.clear();
|
||||
for(Map map : allMaps){
|
||||
if(map.custom) returnArray.add(map);
|
||||
}
|
||||
return returnArray;
|
||||
return maps.select(m -> m.custom);
|
||||
}
|
||||
|
||||
/**Returns a list of only default maps.*/
|
||||
/** Returns a list of only default maps. */
|
||||
public Array<Map> defaultMaps(){
|
||||
returnArray.clear();
|
||||
for(Map map : allMaps){
|
||||
if(!map.custom) returnArray.add(map);
|
||||
}
|
||||
return returnArray;
|
||||
return maps.select(m -> !m.custom);
|
||||
}
|
||||
|
||||
/**Returns map by internal name.*/
|
||||
public Map getByName(String name){
|
||||
return maps.get(name);
|
||||
}
|
||||
|
||||
/**Loads a map from the map folder and returns it. Should only be used for zone maps.
|
||||
* Does not add this map to the map list.*/
|
||||
/**
|
||||
* Loads a map from the map folder and returns it. Should only be used for zone maps.
|
||||
* Does not add this map to the map list.
|
||||
*/
|
||||
public Map loadInternalMap(String name){
|
||||
FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension);
|
||||
|
||||
try(DataInputStream ds = new DataInputStream(file.read())) {
|
||||
return new Map(name, MapIO.readMapMeta(ds), false, file::read);
|
||||
try{
|
||||
return MapIO.readMap(file, false);
|
||||
}catch(IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**Load all maps. Should be called at application start.*/
|
||||
/** Load all maps. Should be called at application start. */
|
||||
public void load(){
|
||||
try{
|
||||
for (String name : defaultMapNames) {
|
||||
for(String name : defaultMapNames){
|
||||
FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension);
|
||||
loadMap(file.nameWithoutExtension(), file::read, false);
|
||||
loadMap(file, false);
|
||||
}
|
||||
}catch (IOException e){
|
||||
}catch(IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
loadCustomMaps();
|
||||
}
|
||||
|
||||
/**Save a map. This updates all values and stored data necessary.*/
|
||||
public void saveMap(String name, MapTileData data, ObjectMap<String, String> tags){
|
||||
/** Save a map. This updates all values and stored data necessary. */
|
||||
public void saveMap(Map map, Tile[][] data){
|
||||
try{
|
||||
//create copy of tags to prevent mutation later
|
||||
ObjectMap<String, String> newTags = new ObjectMap<>();
|
||||
newTags.putAll(tags);
|
||||
tags = newTags;
|
||||
|
||||
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
|
||||
MapIO.writeMap(file.write(false), tags, data);
|
||||
|
||||
if(maps.containsKey(name)){
|
||||
if(maps.get(name).texture != null) {
|
||||
maps.get(name).texture.dispose();
|
||||
maps.get(name).texture = null;
|
||||
}
|
||||
allMaps.removeValue(maps.get(name), true);
|
||||
}
|
||||
|
||||
Map map = new Map(name, new MapMeta(version, tags, data.width(), data.height(), null), true, getStreamFor(name));
|
||||
MapIO.writeMap(map.file.write(false), map, data);
|
||||
if(!headless){
|
||||
map.texture = new Texture(MapIO.generatePixmap(data));
|
||||
map.texture = new Texture(MapIO.generatePreview(data));
|
||||
}
|
||||
allMaps.add(map);
|
||||
|
||||
maps.put(name, map);
|
||||
}catch (IOException e){
|
||||
maps.add(map);
|
||||
}catch(IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**Removes a map completely.*/
|
||||
/** Import a map, then save it. This updates all values and stored data necessary. */
|
||||
public void importMap(FileHandle file, Map map){
|
||||
file.copyTo(customMapDirectory.child(file.name()));
|
||||
if(!headless){
|
||||
map.texture = new Texture(MapIO.generatePreview(map));
|
||||
}
|
||||
maps.add(map);
|
||||
}
|
||||
|
||||
/** Removes a map completely. */
|
||||
public void removeMap(Map map){
|
||||
if(map.texture != null){
|
||||
map.texture.dispose();
|
||||
map.texture = null;
|
||||
}
|
||||
|
||||
maps.remove(map.name);
|
||||
allMaps.removeValue(map, true);
|
||||
|
||||
customMapDirectory.child(map.name + "." + mapExtension).delete();
|
||||
maps.remove(map);
|
||||
map.file.delete();
|
||||
}
|
||||
|
||||
private void loadMap(String name, Supplier<InputStream> 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);
|
||||
private void loadMap(FileHandle file, boolean custom) throws IOException{
|
||||
Map map = MapIO.readMap(file, custom);
|
||||
|
||||
if (!headless){
|
||||
map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true)));
|
||||
}
|
||||
|
||||
maps.put(map.name, map);
|
||||
allMaps.add(map);
|
||||
if(!headless){
|
||||
map.texture = new Texture(MapIO.generatePreview(map));
|
||||
}
|
||||
|
||||
maps.add(map);
|
||||
}
|
||||
|
||||
private void loadCustomMaps(){
|
||||
for(FileHandle file : customMapDirectory.list()){
|
||||
try{
|
||||
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||
loadMap(file.nameWithoutExtension(), file::read, true);
|
||||
loadMap(file, true);
|
||||
}
|
||||
}catch (Exception e){
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to load custom map file '{0}'!", file);
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Returns an input stream supplier for a given map name.*/
|
||||
private Supplier<InputStream> getStreamFor(String name){
|
||||
return customMapDirectory.child(name + "." + mapExtension)::read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
public void dispose(){
|
||||
|
||||
}
|
||||
}
|
@ -113,7 +113,7 @@ public class LoadDialog extends FloatingDialog{
|
||||
|
||||
button.defaults().padBottom(3);
|
||||
button.row();
|
||||
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().meta.name())));
|
||||
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().getDisplayName())));
|
||||
button.row();
|
||||
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
|
||||
button.row();
|
||||
|
@ -17,8 +17,6 @@ import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.ui.BorderImage;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class MapsDialog extends FloatingDialog{
|
||||
@ -31,22 +29,18 @@ public class MapsDialog extends FloatingDialog{
|
||||
buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> {
|
||||
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
|
||||
try{
|
||||
DataInputStream stream = new DataInputStream(file.read());
|
||||
MapMeta meta = MapIO.readMapMeta(stream);
|
||||
MapTileData data = MapIO.readTileData(stream, meta, true);
|
||||
stream.close();
|
||||
|
||||
String name = meta.tags.get("name", file.nameWithoutExtension());
|
||||
Map map = MapIO.readMap(file.read(), file.name(), true, file::read);
|
||||
String name = map.tags.get("name", file.nameWithoutExtension());
|
||||
|
||||
if(world.maps.getByName(name) != null && !world.maps.getByName(name).custom){
|
||||
ui.showError(Core.bundle.format("editor.import.exists", name));
|
||||
}else if(world.maps.getByName(name) != null){
|
||||
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
|
||||
world.maps.saveMap(name, data, meta.tags);
|
||||
world.maps.importMap(file, map);
|
||||
setup();
|
||||
});
|
||||
}else{
|
||||
world.maps.saveMap(name, data, meta.tags);
|
||||
world.maps.importMap(file, map);
|
||||
setup();
|
||||
}
|
||||
|
||||
@ -87,7 +81,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get();
|
||||
button.clearChildren();
|
||||
button.margin(9);
|
||||
button.add(map.meta.tags.get("name", map.name)).width(mapsize - 18f).center().get().setEllipsis(true);
|
||||
button.add(map.getDisplayName()).width(mapsize - 18f).center().get().setEllipsis(true);
|
||||
button.row();
|
||||
button.addImage("white").growX().pad(4).color(Color.GRAY);
|
||||
button.row();
|
||||
@ -127,15 +121,15 @@ public class MapsDialog extends FloatingDialog{
|
||||
|
||||
t.add("$editor.name").padRight(10).color(Color.GRAY).padTop(0);
|
||||
t.row();
|
||||
t.add(map.meta.tags.get("name", map.name)).growX().wrap().padTop(2);
|
||||
t.add(map.getDisplayName()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
t.add("$editor.author").padRight(10).color(Color.GRAY);
|
||||
t.row();
|
||||
t.add(map.meta.author()).growX().wrap().padTop(2);
|
||||
t.add(map.author()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
t.add("$editor.description").padRight(10).color(Color.GRAY).top();
|
||||
t.row();
|
||||
t.add(map.meta.description()).growX().wrap().padTop(2);
|
||||
t.add(map.description()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
t.add("$editor.oregen.info").padRight(10).color(Color.GRAY);
|
||||
}).height(mapsize).width(mapsize);
|
||||
|
@ -194,8 +194,8 @@ public class ApplicationTests{
|
||||
resetWorld();
|
||||
SaveIO.loadFromSlot(0);
|
||||
|
||||
assertEquals(world.width(), map.meta.width);
|
||||
assertEquals(world.height(), map.meta.height);
|
||||
assertEquals(world.width(), map.width);
|
||||
assertEquals(world.height(), map.height);
|
||||
assertTrue(state.teams.get(defaultTeam).cores.size > 0);
|
||||
}
|
||||
|
||||
|
11
tests/src/test/java/MapTests.java
Normal file
11
tests/src/test/java/MapTests.java
Normal file
@ -0,0 +1,11 @@
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
public class MapTests{
|
||||
|
||||
@BeforeAll
|
||||
static void launchApplication(){
|
||||
ApplicationTests.launchApplication();
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
Loading…
Reference in New Issue
Block a user