Map conversion code
This commit is contained in:
@@ -104,8 +104,10 @@ public class Vars{
|
||||
public static FileHandle customMapDirectory;
|
||||
/** data subdirectory used for saves */
|
||||
public static FileHandle saveDirectory;
|
||||
/** old map file extension, for conversion */
|
||||
public static final String oldMapExtension = "mmap";
|
||||
/** map file extension */
|
||||
public static final String mapExtension = "mmap";
|
||||
public static final String mapExtension = "msav";
|
||||
/** save file extension */
|
||||
public static final String saveExtension = "msav";
|
||||
|
||||
|
||||
@@ -477,7 +477,7 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
sent++;
|
||||
|
||||
if(syncStream.position() > maxSnapshotSize){
|
||||
if(syncStream.size() > maxSnapshotSize){
|
||||
dataStream.close();
|
||||
byte[] syncBytes = syncStream.toByteArray();
|
||||
Call.onEntitySnapshot(player.con.id, (byte)group.getID(), (short)sent, (short)syncBytes.length, Net.compressSnapshot(syncBytes));
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.anuke.mindustry.core;
|
||||
|
||||
import io.anuke.annotations.Annotations.Nullable;
|
||||
import io.anuke.arc.*;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.collection.IntArray;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.geom.Geometry;
|
||||
@@ -18,7 +17,7 @@ import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.maps.*;
|
||||
import io.anuke.mindustry.maps.generators.Generator;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.type.Zone;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||
|
||||
@@ -33,11 +32,10 @@ public class World implements ApplicationListener{
|
||||
private Map currentMap;
|
||||
private Tile[][] tiles;
|
||||
|
||||
private Array<Tile> tempTiles = new Array<>();
|
||||
private boolean generating, invalidMap;
|
||||
|
||||
public World(){
|
||||
maps.load();
|
||||
Core.app.post(maps::load);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.arc.collection.StringMap;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.graphics.Pixmap;
|
||||
@@ -10,6 +10,7 @@ import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapIO.TileProvider;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock;
|
||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||
@@ -18,12 +19,25 @@ import io.anuke.mindustry.world.blocks.Floor;
|
||||
import java.io.*;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import static io.anuke.mindustry.Vars.bufferSize;
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
/** Map IO for the "old" .mmap format.
|
||||
* Differentiate between legacy maps and new maps by checking the extension (or the header).*/
|
||||
public class LegacyMapIO{
|
||||
private static final ObjectMap<String, String> fallback = ObjectMap.of("alpha-dart-mech-pad", "dart-mech-pad");
|
||||
|
||||
/* Convert a map from the old format to the new format. */
|
||||
public static void convertMap(FileHandle in, FileHandle out) throws IOException{
|
||||
Map map = readMap(in, true);
|
||||
Tile[][] tiles = world.createTiles(map.width, map.height);
|
||||
for(int x = 0; x < map.width; x++){
|
||||
for(int y = 0; y < map.height; y++){
|
||||
tiles[x][y] = new Tile(x, y);
|
||||
}
|
||||
}
|
||||
readTiles(map, tiles);
|
||||
MapIO.writeMap(out, map);
|
||||
}
|
||||
|
||||
public static Map readMap(FileHandle file, boolean custom) throws IOException{
|
||||
try(DataInputStream stream = new DataInputStream(file.read(1024))){
|
||||
@@ -78,24 +92,40 @@ public class LegacyMapIO{
|
||||
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
|
||||
|
||||
try{
|
||||
SaveIO.getSaveWriter().readContentHeader(stream);
|
||||
byte mapped = stream.readByte();
|
||||
IntMap<Block> idmap = new IntMap<>();
|
||||
IntMap<String> namemap = new IntMap<>();
|
||||
|
||||
for(int i = 0; i < mapped; i++){
|
||||
byte type = stream.readByte();
|
||||
short total = stream.readShort();
|
||||
|
||||
for(int j = 0; j < total; j++){
|
||||
String name = stream.readUTF();
|
||||
if(type == 1){
|
||||
Block res = content.getByName(ContentType.block, fallback.get(name, name));
|
||||
idmap.put(j, res == null ? Blocks.air : res);
|
||||
namemap.put(j, fallback.get(name, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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 oreid = stream.readByte();
|
||||
int floorid = stream.readUnsignedByte();
|
||||
int oreid = stream.readUnsignedByte();
|
||||
int consecutives = stream.readUnsignedByte();
|
||||
|
||||
Tile tile = tiles.get(x, y);
|
||||
tile.setFloor((Floor)content.block(floorid));
|
||||
tile.setOverlay(content.block(oreid));
|
||||
tile.setFloor((Floor)idmap.get(floorid));
|
||||
tile.setOverlay(idmap.get(oreid));
|
||||
|
||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
||||
int newx = j % width, newy = j / width;
|
||||
Tile newTile = tiles.get(newx, newy);
|
||||
newTile.setFloor((Floor)content.block(floorid));
|
||||
newTile.setOverlay(content.block(oreid));
|
||||
newTile.setFloor((Floor)idmap.get(floorid));
|
||||
newTile.setOverlay(idmap.get(oreid));
|
||||
}
|
||||
|
||||
i += consecutives;
|
||||
@@ -104,7 +134,8 @@ public class LegacyMapIO{
|
||||
//read blocks
|
||||
for(int i = 0; i < width * height; i++){
|
||||
int x = i % width, y = i / width;
|
||||
Block block = content.block(stream.readByte());
|
||||
int id = stream.readUnsignedByte();
|
||||
Block block = idmap.get(id);
|
||||
|
||||
Tile tile = tiles.get(x, y);
|
||||
//the spawn block is saved in the block tile layer in older maps, shift it to the overlay
|
||||
@@ -114,7 +145,9 @@ public class LegacyMapIO{
|
||||
tile.setOverlay(block);
|
||||
}
|
||||
|
||||
if(tile.entity != null){
|
||||
if(namemap.get(id).equals("part")){
|
||||
stream.readByte(); //link
|
||||
}else if(tile.entity != null){
|
||||
byte tr = stream.readByte();
|
||||
stream.readShort(); //read health (which is actually irrelevant)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.zip.InflaterInputStream;
|
||||
import static io.anuke.mindustry.Vars.bufferSize;
|
||||
|
||||
/** Reads and writes map files. */
|
||||
//TODO does this class even need to exist??? move to Maps
|
||||
//TODO does this class even need to exist??? move to Maps?
|
||||
public class MapIO{
|
||||
private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||
|
||||
|
||||
@@ -11,17 +11,18 @@ import java.io.*;
|
||||
public abstract class SaveFileReader{
|
||||
protected final ReusableByteOutStream byteOutput = new ReusableByteOutStream();
|
||||
protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput);
|
||||
protected final ObjectMap<String, String> fallback = ObjectMap.of("alpha-dart-mech-pad", "dart-mech-pad");
|
||||
protected final ObjectMap<String, String> fallback = ObjectMap.of();
|
||||
|
||||
protected void region(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{
|
||||
counter.resetCount();
|
||||
int length;
|
||||
try{
|
||||
length = readChunk(stream, cons);
|
||||
}catch(Throwable e){
|
||||
throw new IOException("Error reading region \"" + name + "\".", e);
|
||||
}
|
||||
if(length != counter.count() + 4){
|
||||
throw new IOException("Error reading region \"" + name + "\": read length mismatch. Expected: " + length + "; Actual: " + (counter.count() + 4));
|
||||
if(length != counter.count() - 4){
|
||||
throw new IOException("Error reading region \"" + name + "\": read length mismatch. Expected: " + length + "; Actual: " + (counter.count() - 4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +41,10 @@ public abstract class SaveFileReader{
|
||||
/** Write a chunk of input to the stream. An integer of some length is written first, followed by the data. */
|
||||
public void writeChunk(DataOutput output, boolean isByte, IORunner<DataOutput> runner) throws IOException{
|
||||
//reset output position
|
||||
byteOutput.position(0);
|
||||
//writer the needed info
|
||||
byteOutput.reset();
|
||||
//write the needed info
|
||||
runner.accept(dataBytes);
|
||||
int length = byteOutput.position();
|
||||
int length = byteOutput.size();
|
||||
//write length (either int or byte) followed by the output bytes
|
||||
if(!isByte){
|
||||
output.writeInt(length);
|
||||
|
||||
@@ -58,11 +58,19 @@ public class SaveIO{
|
||||
}
|
||||
|
||||
public static boolean isSaveValid(int slot){
|
||||
return isSaveValid(getSlotStream(slot)) || isSaveValid(getBackupSlotStream(slot));
|
||||
try{ //file may not even exist at all, so catch that too
|
||||
return isSaveValid(getSlotStream(slot)) || isSaveValid(getBackupSlotStream(slot));
|
||||
}catch(Exception e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSaveValid(FileHandle file){
|
||||
return isSaveValid(new DataInputStream(new InflaterInputStream(file.read(bufferSize))));
|
||||
try{
|
||||
return isSaveValid(new DataInputStream(new InflaterInputStream(file.read(bufferSize))));
|
||||
}catch(Exception e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSaveValid(DataInputStream stream){
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.collection.StringMap;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.util.io.CounterInputStream;
|
||||
import io.anuke.mindustry.entities.Entities;
|
||||
@@ -52,7 +53,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
"saved", Time.millis(),
|
||||
"playtime", headless ? 0 : control.saves.getTotalPlaytime(),
|
||||
"build", Version.build,
|
||||
"mapname", world.getMap().name(),
|
||||
"mapname", world.getMap() == null ? "unknown" : world.getMap().name(),
|
||||
"wave", state.wave,
|
||||
"wavetime", state.wavetime,
|
||||
"stats", Serialization.writeStatsJson(state.stats),
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.anuke.arc.util.Disposable;
|
||||
import io.anuke.arc.util.Log;
|
||||
import io.anuke.arc.util.serialization.Json;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
import io.anuke.mindustry.io.LegacyMapIO;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -59,6 +60,15 @@ public class Maps implements Disposable{
|
||||
/** Load all maps. Should be called at application start. */
|
||||
public void load(){
|
||||
try{
|
||||
//TODO remove, this is only for testing
|
||||
for(FileHandle in : Core.files.absolute("/home/anuke/Projects/Mindustry/core/assets/maps").list()){
|
||||
if(in.extension().equalsIgnoreCase(oldMapExtension)){
|
||||
Log.info("Converting {0}...", in);
|
||||
LegacyMapIO.convertMap(in, in.sibling(in.nameWithoutExtension() + "." + mapExtension));
|
||||
Log.info("Converted {0}", in);
|
||||
}
|
||||
}
|
||||
|
||||
for(String name : defaultMapNames){
|
||||
FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension);
|
||||
loadMap(file, false);
|
||||
@@ -183,6 +193,26 @@ public class Maps implements Disposable{
|
||||
}
|
||||
|
||||
private void loadCustomMaps(){
|
||||
boolean convertedAny = false;
|
||||
for(FileHandle file : customMapDirectory.list()){
|
||||
if(file.extension().equalsIgnoreCase(oldMapExtension)){
|
||||
convertedAny = true;
|
||||
try{
|
||||
LegacyMapIO.convertMap(file, file.sibling(file.nameWithoutExtension() + "." + mapExtension));
|
||||
//TODO delete so conversion doesn't happen again
|
||||
//file.delete();
|
||||
}catch(IOException e){
|
||||
//don't convert
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//free up any potential memory that was used up during conversion
|
||||
if(convertedAny){
|
||||
world.createTiles(0, 0);
|
||||
}
|
||||
|
||||
for(FileHandle file : customMapDirectory.list()){
|
||||
try{
|
||||
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||
|
||||
@@ -60,9 +60,10 @@ public class MapGenerator extends Generator{
|
||||
@Override
|
||||
public void init(Loadout loadout){
|
||||
this.loadout = loadout;
|
||||
map = world.maps.loadInternalMap(mapName);
|
||||
width = map.width;
|
||||
height = map.height;
|
||||
//TODO uncomment once conversion works
|
||||
//map = world.maps.loadInternalMap(mapName);
|
||||
//width = map.width;
|
||||
//height = map.height;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user