Progress
This commit is contained in:
@@ -22,6 +22,7 @@ import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
|||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.io.MapIO;
|
import io.anuke.mindustry.io.MapIO;
|
||||||
import io.anuke.mindustry.maps.Map;
|
import io.anuke.mindustry.maps.Map;
|
||||||
|
import io.anuke.mindustry.maps.MapException;
|
||||||
import io.anuke.mindustry.maps.Maps;
|
import io.anuke.mindustry.maps.Maps;
|
||||||
import io.anuke.mindustry.maps.generators.Generator;
|
import io.anuke.mindustry.maps.generators.Generator;
|
||||||
import io.anuke.mindustry.type.ContentType;
|
import io.anuke.mindustry.type.ContentType;
|
||||||
@@ -232,12 +233,10 @@ public class World implements ApplicationListener{
|
|||||||
beginMapLoad();
|
beginMapLoad();
|
||||||
this.currentMap = map;
|
this.currentMap = map;
|
||||||
|
|
||||||
int width = map.meta.width, height = map.meta.height;
|
|
||||||
|
|
||||||
createTiles(width, height);
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
loadTileData(tiles, MapIO.readTileData(map, true));
|
createTiles(map.width, map.height);
|
||||||
|
tiles = MapIO.readTiles(map, tiles);
|
||||||
|
prepareTiles(tiles);
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
if(!headless){
|
if(!headless){
|
||||||
@@ -257,7 +256,7 @@ public class World implements ApplicationListener{
|
|||||||
if(state.teams.get(players[0].getTeam()).cores.size == 0){
|
if(state.teams.get(players[0].getTeam()).cores.size == 0){
|
||||||
ui.showError("$map.nospawn");
|
ui.showError("$map.nospawn");
|
||||||
invalidMap = true;
|
invalidMap = true;
|
||||||
}else if(state.rules.pvp){ //pvp maps need two cores to be valid
|
}else if(state.rules.pvp){ //pvp maps need two cores to be valid
|
||||||
invalidMap = true;
|
invalidMap = true;
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){
|
if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){
|
||||||
@@ -413,18 +412,7 @@ public class World implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */
|
/**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */
|
||||||
void loadTileData(Tile[][] tiles, MapTileData data){
|
void loadTileData(Tile[][] tiles){
|
||||||
data.position(0, 0);
|
|
||||||
TileDataMarker marker = data.newDataMarker();
|
|
||||||
|
|
||||||
for(int y = 0; y < data.height(); y++){
|
|
||||||
for(int x = 0; x < data.width(); x++){
|
|
||||||
data.read(marker);
|
|
||||||
|
|
||||||
tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareTiles(tiles);
|
prepareTiles(tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import io.anuke.arc.util.Pack;
|
|||||||
import io.anuke.arc.util.Structs;
|
import io.anuke.arc.util.Structs;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.Blocks;
|
||||||
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
|
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
|||||||
@@ -1,38 +1,31 @@
|
|||||||
package io.anuke.mindustry.io;
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
import io.anuke.arc.collection.IntIntMap;
|
|
||||||
import io.anuke.arc.collection.ObjectMap;
|
import io.anuke.arc.collection.ObjectMap;
|
||||||
import io.anuke.arc.collection.ObjectMap.Entry;
|
import io.anuke.arc.collection.ObjectMap.Entry;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
import io.anuke.arc.graphics.Color;
|
import io.anuke.arc.graphics.Color;
|
||||||
import io.anuke.arc.graphics.Pixmap;
|
import io.anuke.arc.graphics.Pixmap;
|
||||||
import io.anuke.arc.graphics.Pixmap.Format;
|
|
||||||
import io.anuke.arc.util.Pack;
|
import io.anuke.arc.util.Pack;
|
||||||
import io.anuke.arc.util.Structs;
|
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.Blocks;
|
||||||
|
import io.anuke.mindustry.game.MappableContent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
|
import io.anuke.mindustry.game.Version;
|
||||||
import io.anuke.mindustry.maps.Map;
|
import io.anuke.mindustry.maps.Map;
|
||||||
import io.anuke.mindustry.maps.MapMeta;
|
|
||||||
import io.anuke.mindustry.maps.MapTileData;
|
|
||||||
import io.anuke.mindustry.maps.MapTileData.DataPosition;
|
|
||||||
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
|
|
||||||
import io.anuke.mindustry.type.ContentType;
|
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.LegacyColorMapper;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock;
|
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.zip.DeflaterOutputStream;
|
||||||
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
/**
|
/** Reads and writes map files.*/
|
||||||
* Reads and writes map files.
|
|
||||||
*/
|
|
||||||
//TODO name mapping
|
|
||||||
public class MapIO{
|
public class MapIO{
|
||||||
|
private static final int version = 1;
|
||||||
private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
|
private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||||
private static final int version = 0;
|
|
||||||
private static IntIntMap defaultBlockMap = new IntIntMap();
|
|
||||||
|
|
||||||
public static boolean isImage(FileHandle file){
|
public static boolean isImage(FileHandle file){
|
||||||
try(InputStream stream = file.read()){
|
try(InputStream stream = file.read()){
|
||||||
@@ -47,161 +40,21 @@ public class MapIO{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadDefaultBlocks(){
|
//TODO implement
|
||||||
for(Block block : content.blocks()){
|
public static Pixmap unfinished_generatePreview(Map map){
|
||||||
defaultBlockMap.put(block.id, block.id);
|
return null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pixmap generatePixmap(MapTileData data){
|
//TODO implement
|
||||||
Pixmap pixmap = new Pixmap(data.width(), data.height(), Format.RGBA8888);
|
/**Reads a pixmap in the 3.5 pixmap format.*/
|
||||||
data.position(0, 0);
|
public static Tile[][] unfinished_readLegacyPixmap(Pixmap pixmap){
|
||||||
|
return null;
|
||||||
TileDataMarker marker = data.newDataMarker();
|
|
||||||
|
|
||||||
for(int y = 0; y < data.height(); y++){
|
|
||||||
for(int x = 0; x < data.width(); x++){
|
|
||||||
data.read(marker);
|
|
||||||
Block floor = content.block(marker.floor);
|
|
||||||
Block wall = content.block(marker.wall);
|
|
||||||
int color = colorFor(floor, wall, Team.all[marker.team]);
|
|
||||||
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.position(0, 0);
|
|
||||||
|
|
||||||
return pixmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Reads a pixmap in the old (3.5) map format.*/
|
//TODO implement
|
||||||
public static MapTileData readLegacyPixmap(Pixmap pixmap){
|
/**Reads a pixmap in the old 4.0 .mmap format.*/
|
||||||
MapTileData data = new MapTileData(pixmap.getWidth(), pixmap.getHeight());
|
private static Tile[][] unfinished_readLegacyMmap(InputStream stream) throws IOException{
|
||||||
|
return null;
|
||||||
for(int x = 0; x < data.width(); x++){
|
|
||||||
for(int y = 0; y < data.height(); y++){
|
|
||||||
int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y);
|
|
||||||
LegacyBlock block = LegacyColorMapper.get(color);
|
|
||||||
|
|
||||||
data.write(x, y, DataPosition.floor, block.floor.id);
|
|
||||||
data.write(x, y, DataPosition.wall, block.wall.id);
|
|
||||||
|
|
||||||
//place core
|
|
||||||
if(color == Color.rgba8888(Color.GREEN)){
|
|
||||||
for(int dx = 0; dx < 3; dx++){
|
|
||||||
for(int dy = 0; dy < 3; dy++){
|
|
||||||
int worldx = dx - 1 + x;
|
|
||||||
int worldy = dy - 1 + y;
|
|
||||||
|
|
||||||
if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){
|
|
||||||
data.write(worldx, worldy, DataPosition.wall, Blocks.part.id);
|
|
||||||
data.write(worldx, worldy, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal()));
|
|
||||||
data.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.write(x, y, DataPosition.wall, Blocks.coreShard.id);
|
|
||||||
data.write(x, y, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeMap(OutputStream stream, ObjectMap<String, String> tags, MapTileData data) throws IOException{
|
|
||||||
if(defaultBlockMap == null){
|
|
||||||
loadDefaultBlocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
MapMeta meta = new MapMeta(version, tags, data.width(), data.height(), defaultBlockMap);
|
|
||||||
|
|
||||||
DataOutputStream ds = new DataOutputStream(stream);
|
|
||||||
|
|
||||||
writeMapMeta(ds, meta);
|
|
||||||
ds.write(data.toArray());
|
|
||||||
|
|
||||||
ds.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads tile data, skipping meta.
|
|
||||||
*/
|
|
||||||
public static MapTileData readTileData(DataInputStream stream, boolean readOnly) throws IOException{
|
|
||||||
MapMeta meta = readMapMeta(stream);
|
|
||||||
return readTileData(stream, meta, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does not skip meta. Call after reading meta.
|
|
||||||
*/
|
|
||||||
public static MapTileData readTileData(DataInputStream stream, MapMeta meta, boolean readOnly) throws IOException{
|
|
||||||
byte[] bytes = new byte[stream.available()];
|
|
||||||
stream.readFully(bytes);
|
|
||||||
return new MapTileData(bytes, meta.width, meta.height, meta.blockMap, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads tile data, skipping meta tags.
|
|
||||||
*/
|
|
||||||
public static MapTileData readTileData(Map map, boolean readOnly){
|
|
||||||
try(DataInputStream ds = new DataInputStream(map.stream.get())){
|
|
||||||
return MapIO.readTileData(ds, readOnly);
|
|
||||||
}catch(IOException e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MapMeta readMapMeta(DataInputStream stream) throws IOException{
|
|
||||||
ObjectMap<String, String> tags = new ObjectMap<>();
|
|
||||||
IntIntMap map = new IntIntMap();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
short blocks = stream.readShort();
|
|
||||||
for(int i = 0; i < blocks; i++){
|
|
||||||
short id = stream.readShort();
|
|
||||||
String name = stream.readUTF();
|
|
||||||
Block block = content.getByName(ContentType.block, name);
|
|
||||||
if(block == null){
|
|
||||||
block = Blocks.air;
|
|
||||||
}
|
|
||||||
map.put(id, block.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = stream.readShort();
|
|
||||||
int height = stream.readShort();
|
|
||||||
|
|
||||||
return new MapMeta(version, tags, width, height, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(content.blocks().size);
|
|
||||||
for(Block block : content.blocks()){
|
|
||||||
stream.writeShort(block.id);
|
|
||||||
stream.writeUTF(block.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.writeShort(meta.width);
|
|
||||||
stream.writeShort(meta.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int colorFor(Block floor, Block wall, Team team){
|
public static int colorFor(Block floor, Block wall, Team team){
|
||||||
@@ -210,4 +63,140 @@ public class MapIO{
|
|||||||
}
|
}
|
||||||
return Color.rgba8888(wall.solid ? wall.color : floor.color);
|
return Color.rgba8888(wall.solid ? wall.color : floor.color);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static void writeMap(Map map, Tile[][] tiles, OutputStream output) throws IOException{
|
||||||
|
try(DataOutputStream stream = new DataOutputStream(output)){
|
||||||
|
stream.writeInt(version);
|
||||||
|
stream.writeInt(Version.build);
|
||||||
|
stream.writeShort(tiles.length);
|
||||||
|
stream.writeShort(tiles[0].length);
|
||||||
|
stream.writeByte((byte)map.tags.size);
|
||||||
|
|
||||||
|
for(Entry<String, String> entry : map.tags.entries()){
|
||||||
|
stream.writeUTF(entry.key);
|
||||||
|
stream.writeUTF(entry.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try(DataOutputStream stream = new DataOutputStream(new DeflaterOutputStream(output))){
|
||||||
|
|
||||||
|
SaveIO.getSaveWriter().writeContentHeader(stream);
|
||||||
|
|
||||||
|
stream.writeShort(tiles.length);
|
||||||
|
stream.writeShort(tiles[0].length);
|
||||||
|
|
||||||
|
//TODO 2-phase rle
|
||||||
|
for(int i = 0; i < tiles.length * tiles[0].length; i++){
|
||||||
|
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||||
|
|
||||||
|
stream.writeByte(tile.getFloorID());
|
||||||
|
stream.writeByte(tile.getBlockID());
|
||||||
|
stream.writeByte(tile.getOre());
|
||||||
|
|
||||||
|
if(tile.block() instanceof BlockPart){
|
||||||
|
stream.writeByte(tile.link);
|
||||||
|
}else if(tile.entity != null){
|
||||||
|
stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation
|
||||||
|
stream.writeShort((short)tile.entity.health); //health
|
||||||
|
tile.entity.writeConfig(stream);
|
||||||
|
}else if(tile.block() == Blocks.air){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map readMap(String useName, InputStream input) throws IOException{
|
||||||
|
try(DataInputStream stream = new DataInputStream(input)){
|
||||||
|
ObjectMap<String, String> tags = new ObjectMap<>();
|
||||||
|
|
||||||
|
//meta is uncompressed
|
||||||
|
int version = stream.readInt();
|
||||||
|
int build = stream.readInt();
|
||||||
|
short width = stream.readShort(), height = stream.readShort();
|
||||||
|
byte tagAmount = stream.readByte();
|
||||||
|
|
||||||
|
for(int i = 0; i < tagAmount; i++){
|
||||||
|
String name = stream.readUTF();
|
||||||
|
String value = stream.readUTF();
|
||||||
|
tags.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Map(useName, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Tile[][] readTiles(Map map, Tile[][] tiles) throws IOException{
|
||||||
|
return readTiles(map.stream.get(), 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);
|
||||||
|
|
||||||
|
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
|
||||||
|
|
||||||
|
MappableContent[][] c = SaveIO.getSaveWriter().readContentHeader(stream);
|
||||||
|
|
||||||
|
try{
|
||||||
|
content.setTemporaryMapper(c);
|
||||||
|
//TODO 2-phase rle
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
Tile tile = new Tile(x, y, floorid, wallid);
|
||||||
|
|
||||||
|
if(wallid == Blocks.part.id){
|
||||||
|
tile.link = stream.readByte();
|
||||||
|
}else if(tile.entity != null){
|
||||||
|
byte tr = stream.readByte();
|
||||||
|
short health = stream.readShort();
|
||||||
|
|
||||||
|
byte team = Pack.leftByte(tr);
|
||||||
|
byte rotation = Pack.rightByte(tr);
|
||||||
|
|
||||||
|
tile.setTeam(Team.all[team]);
|
||||||
|
tile.entity.health = health;
|
||||||
|
tile.setRotation(rotation);
|
||||||
|
|
||||||
|
tile.entity.readConfig(stream);
|
||||||
|
}else if(wallid == 0){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += consecutives;
|
||||||
|
}
|
||||||
|
|
||||||
|
tiles[x][y] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiles;
|
||||||
|
|
||||||
|
}finally{
|
||||||
|
content.setTemporaryMapper(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ public abstract class SaveFileVersion{
|
|||||||
return new SaveMeta(version, time, playtime, build, map, wave, rules);
|
return new SaveMeta(version, time, playtime, build, map, wave, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO 2-phase rle
|
||||||
public void writeMap(DataOutputStream stream) throws IOException{
|
public void writeMap(DataOutputStream stream) throws IOException{
|
||||||
|
|
||||||
//write world size
|
//write world size
|
||||||
@@ -86,6 +87,7 @@ public abstract class SaveFileVersion{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO 2-phase rle
|
||||||
public void readMap(DataInputStream stream) throws IOException{
|
public void readMap(DataInputStream stream) throws IOException{
|
||||||
short width = stream.readShort();
|
short width = stream.readShort();
|
||||||
short height = stream.readShort();
|
short height = stream.readShort();
|
||||||
|
|||||||
@@ -16,18 +16,22 @@ public class Map{
|
|||||||
public final ObjectMap<String, String> tags;
|
public final ObjectMap<String, String> tags;
|
||||||
/** Supplies a new input stream with the data of this map.*/
|
/** Supplies a new input stream with the data of this map.*/
|
||||||
public final Supplier<InputStream> stream;
|
public final Supplier<InputStream> stream;
|
||||||
|
/**Map width/height, shorts.*/
|
||||||
|
public int width, height;
|
||||||
/** Preview texture.*/
|
/** Preview texture.*/
|
||||||
public Texture texture;
|
public Texture texture;
|
||||||
|
|
||||||
public Map(String name, ObjectMap<String, String> tags, boolean custom, Supplier<InputStream> streamSupplier){
|
public Map(String name, int width, int height, ObjectMap<String, String> tags, boolean custom, Supplier<InputStream> streamSupplier){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.custom = custom;
|
this.custom = custom;
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
this.stream = streamSupplier;
|
this.stream = streamSupplier;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map(String name){
|
public Map(String name, int width, int height){
|
||||||
this(name, new ObjectMap<>(), true, () -> null);
|
this(name, width, height, new ObjectMap<>(), true, () -> null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayName(){
|
public String getDisplayName(){
|
||||||
@@ -50,10 +54,6 @@ public class Map{
|
|||||||
return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown");
|
return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasOreGen(){
|
|
||||||
return !tags.get("oregen", "0").equals("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "Map{" +
|
return "Map{" +
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import io.anuke.mindustry.content.Blocks;
|
|||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.io.MapIO;
|
import io.anuke.mindustry.io.MapIO;
|
||||||
import io.anuke.mindustry.maps.Map;
|
import io.anuke.mindustry.maps.Map;
|
||||||
import io.anuke.mindustry.maps.MapTileData;
|
|
||||||
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
|
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.type.Loadout;
|
import io.anuke.mindustry.type.Loadout;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
@@ -21,8 +19,9 @@ import io.anuke.mindustry.world.blocks.StaticWall;
|
|||||||
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
|
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
|
||||||
import io.anuke.mindustry.world.blocks.storage.StorageBlock;
|
import io.anuke.mindustry.world.blocks.storage.StorageBlock;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import java.io.IOException;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class MapGenerator extends Generator{
|
public class MapGenerator extends Generator{
|
||||||
private Map map;
|
private Map map;
|
||||||
@@ -73,112 +72,109 @@ public class MapGenerator extends Generator{
|
|||||||
public void init(Loadout loadout){
|
public void init(Loadout loadout){
|
||||||
this.loadout = loadout;
|
this.loadout = loadout;
|
||||||
map = world.maps.loadInternalMap(mapName);
|
map = world.maps.loadInternalMap(mapName);
|
||||||
width = map.meta.width;
|
width = map.width;
|
||||||
height = map.meta.height;
|
height = map.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(Tile[][] tiles){
|
public void generate(Tile[][] tiles){
|
||||||
MapTileData data = MapIO.readTileData(map, true);
|
try{
|
||||||
|
MapIO.readTiles(map, tiles);
|
||||||
|
Array<Point2> players = new Array<>();
|
||||||
|
Array<Point2> enemies = new Array<>();
|
||||||
|
|
||||||
data.position(0, 0);
|
for(int x = 0; x < width; x++){
|
||||||
TileDataMarker marker = data.newDataMarker();
|
for(int y = 0; y < height; y++){
|
||||||
Array<Point2> players = new Array<>();
|
if(tiles[x][y].block() instanceof CoreBlock){
|
||||||
Array<Point2> enemies = new Array<>();
|
players.add(new Point2(x, y));
|
||||||
|
tiles[x][y].setBlock(Blocks.air);
|
||||||
|
}
|
||||||
|
|
||||||
for(int y = 0; y < data.height(); y++){
|
if(tiles[x][y].block() == Blocks.spawn){
|
||||||
for(int x = 0; x < data.width(); x++){
|
enemies.add(new Point2(x, y));
|
||||||
data.read(marker);
|
tiles[x][y].setBlock(Blocks.air);
|
||||||
|
}
|
||||||
if(content.block(marker.wall) instanceof CoreBlock){
|
|
||||||
players.add(new Point2(x, y));
|
|
||||||
marker.wall = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(enemySpawns != -1 && content.block(marker.wall) == Blocks.spawn){
|
|
||||||
enemies.add(new Point2(x, y));
|
|
||||||
marker.wall = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Simplex simplex = new Simplex(Mathf.random(99999));
|
Simplex simplex = new Simplex(Mathf.random(99999));
|
||||||
|
|
||||||
for(int x = 0; x < data.width(); x++){
|
for(int x = 0; x < width; x++){
|
||||||
for(int y = 0; y < data.height(); y++){
|
for(int y = 0; y < height; y++){
|
||||||
final double scl = 10;
|
final double scl = 10;
|
||||||
Tile tile = tiles[x][y];
|
Tile tile = tiles[x][y];
|
||||||
int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, data.width()-1);
|
int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, width - 1);
|
||||||
int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, data.height()-1);
|
int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, height - 1);
|
||||||
|
|
||||||
if((tile.block() instanceof StaticWall
|
if((tile.block() instanceof StaticWall
|
||||||
&& tiles[newX][newY].block() instanceof StaticWall)
|
&& tiles[newX][newY].block() instanceof StaticWall)
|
||||||
|| (tile.block() == Blocks.air && !tiles[newX][newY].block().synthetic())
|
|| (tile.block() == Blocks.air && !tiles[newX][newY].block().synthetic())
|
||||||
|| (tiles[newX][newY].block() == Blocks.air && tile.block() instanceof StaticWall)){
|
|| (tiles[newX][newY].block() == Blocks.air && tile.block() instanceof StaticWall)){
|
||||||
tile.setBlock(tiles[newX][newY].block());
|
tile.setBlock(tiles[newX][newY].block());
|
||||||
}
|
|
||||||
|
|
||||||
if(distortFloor){
|
|
||||||
tile.setFloor(tiles[newX][newY].floor());
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Decoration decor : decorations){
|
|
||||||
if(tile.block() == Blocks.air && !(decor.wall instanceof Floor) && tile.floor() == decor.floor && Mathf.chance(decor.chance)){
|
|
||||||
tile.setBlock(decor.wall);
|
|
||||||
}else if(tile.floor() == decor.floor && decor.wall instanceof Floor && Mathf.chance(decor.chance)){
|
|
||||||
tile.setFloor((Floor)decor.wall);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){
|
if(distortFloor){
|
||||||
for(ItemStack stack : storageDrops){
|
tile.setFloor(tiles[newX][newY].floor());
|
||||||
if(Mathf.chance(0.3)){
|
}
|
||||||
tile.entity.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity));
|
|
||||||
|
for(Decoration decor : decorations){
|
||||||
|
if(tile.block() == Blocks.air && !(decor.wall instanceof Floor) && tile.floor() == decor.floor && Mathf.chance(decor.chance)){
|
||||||
|
tile.setBlock(decor.wall);
|
||||||
|
}else if(tile.floor() == decor.floor && decor.wall instanceof Floor && Mathf.chance(decor.chance)){
|
||||||
|
tile.setFloor((Floor)decor.wall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(enemySpawns != -1){
|
if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){
|
||||||
if(enemySpawns > enemies.size){
|
for(ItemStack stack : storageDrops){
|
||||||
throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number.");
|
if(Mathf.chance(0.3)){
|
||||||
}
|
tile.entity.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity));
|
||||||
|
|
||||||
enemies.shuffle();
|
|
||||||
for(int i = 0; i < enemySpawns; i++){
|
|
||||||
Point2 point = enemies.get(i);
|
|
||||||
tiles[point.x][point.y].setBlock(Blocks.spawn);
|
|
||||||
|
|
||||||
int rad = 10, frad = 12;
|
|
||||||
|
|
||||||
for(int x = -rad; x <= rad; x++){
|
|
||||||
for(int y = -rad; y <= rad; y++){
|
|
||||||
int wx = x + point.x, wy = y + point.y;
|
|
||||||
double dst = Mathf.dst(x, y);
|
|
||||||
if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){
|
|
||||||
Tile tile = tiles[wx][wy];
|
|
||||||
if(tile.floor() instanceof OreBlock){
|
|
||||||
OreBlock block = (OreBlock)tile.floor();
|
|
||||||
tile.setFloor(block.base);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(enemySpawns != -1){
|
||||||
|
if(enemySpawns > enemies.size){
|
||||||
|
throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number.");
|
||||||
|
}
|
||||||
|
|
||||||
|
enemies.shuffle();
|
||||||
|
for(int i = 0; i < enemySpawns; i++){
|
||||||
|
Point2 point = enemies.get(i);
|
||||||
|
tiles[point.x][point.y].setBlock(Blocks.spawn);
|
||||||
|
|
||||||
|
int rad = 10, frad = 12;
|
||||||
|
|
||||||
|
for(int x = -rad; x <= rad; x++){
|
||||||
|
for(int y = -rad; y <= rad; y++){
|
||||||
|
int wx = x + point.x, wy = y + point.y;
|
||||||
|
double dst = Mathf.dst(x, y);
|
||||||
|
if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){
|
||||||
|
Tile tile = tiles[wx][wy];
|
||||||
|
if(tile.floor() instanceof OreBlock){
|
||||||
|
OreBlock block = (OreBlock)tile.floor();
|
||||||
|
tile.setFloor(block.base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point2 core = players.random();
|
||||||
|
if(core == null){
|
||||||
|
throw new IllegalArgumentException("All zone maps must have a core.");
|
||||||
|
}
|
||||||
|
|
||||||
|
loadout.setup(core.x, core.y);
|
||||||
|
|
||||||
|
world.prepareTiles(tiles);
|
||||||
|
world.setMap(map);
|
||||||
|
}catch(IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point2 core = players.random();
|
|
||||||
if(core == null){
|
|
||||||
throw new IllegalArgumentException("All zone maps must have a core.");
|
|
||||||
}
|
|
||||||
|
|
||||||
loadout.setup(core.x, core.y);
|
|
||||||
|
|
||||||
world.prepareTiles(tiles);
|
|
||||||
world.setMap(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Decoration{
|
public static class Decoration{
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public class Tile implements Position, TargetTrait{
|
|||||||
private byte rotation;
|
private byte rotation;
|
||||||
/** Team ordinal. */
|
/** Team ordinal. */
|
||||||
private byte team;
|
private byte team;
|
||||||
|
/**Ore that is on top of this (floor) block.*/
|
||||||
|
private byte ore;
|
||||||
|
|
||||||
public Tile(int x, int y){
|
public Tile(int x, int y){
|
||||||
this.x = (short) x;
|
this.x = (short) x;
|
||||||
@@ -316,6 +318,14 @@ public class Tile implements Position, TargetTrait{
|
|||||||
return getTeam() == Team.none || team == getTeam();
|
return getTeam() == Team.none || team == getTeam();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getOre(){
|
||||||
|
return ore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOre(byte ore){
|
||||||
|
this.ore = ore;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateOcclusion(){
|
public void updateOcclusion(){
|
||||||
cost = 1;
|
cost = 1;
|
||||||
boolean occluded = false;
|
boolean occluded = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user