diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 8b5e924b2a..50c035c264 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -28,6 +28,7 @@ public class World implements ApplicationListener{ public final BlockIndexer indexer = new BlockIndexer(); public final WaveSpawner spawner = new WaveSpawner(); public final Pathfinder pathfinder = new Pathfinder(); + public final Context context = new Context(); private Map currentMap; private Tile[][] tiles; @@ -479,4 +480,36 @@ public class World implements ApplicationListener{ public interface Raycaster{ boolean accept(int x, int y); } + + class Context implements WorldContext{ + @Override + public Tile tile(int x, int y){ + return tiles[x][y]; + } + + @Override + public void resize(int width, int height){ + createTiles(width, height); + } + + @Override + public Tile create(int x, int y, int floorID, int overlayID, int wallID){ + return new Tile(x, y, floorID, overlayID, wallID); + } + + @Override + public boolean isGenerating(){ + return World.this.isGenerating(); + } + + @Override + public void begin(){ + beginMapLoad(); + } + + @Override + public void end(){ + endMapLoad(); + } + } } diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index a7d479106b..02f5ece065 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -11,8 +11,7 @@ import io.anuke.mindustry.gen.TileOp; import io.anuke.mindustry.io.LegacyMapIO; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; @@ -21,6 +20,7 @@ import static io.anuke.mindustry.Vars.world; public class MapEditor{ public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20}; + private final Context context = new Context(); private StringMap tags = new StringMap(); private MapRenderer renderer = new MapRenderer(this); @@ -51,8 +51,7 @@ public class MapEditor{ loading = true; tags.putAll(map.tags); - //TODO this actually creates the tiles, which are not editor tiles - MapIO.loadMap(map, EditorTile::new); + MapIO.loadMap(map, context); checkLinkedTiles(); renderer.resize(width(), height()); loading = false; @@ -273,4 +272,36 @@ public class MapEditor{ renderer.updatePoint(TileOp.x(data), TileOp.y(data)); } + + class Context implements WorldContext{ + @Override + public Tile tile(int x, int y){ + return world.tile(x, y); + } + + @Override + public void resize(int width, int height){ + world.createTiles(width, height); + } + + @Override + public Tile create(int x, int y, int floorID, int overlayID, int wallID){ + return new EditorTile(x, y, floorID, overlayID, wallID); + } + + @Override + public boolean isGenerating(){ + return world.isGenerating(); + } + + @Override + public void begin(){ + world.beginMapLoad(); + } + + @Override + public void end(){ + world.endMapLoad(); + } + } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index df6a420be4..06dba70468 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -62,7 +62,7 @@ public class FloorRenderer implements Disposable{ //loop through all layers, and add layer index if it exists for(int i = 0; i < layers; i++){ - if(chunk.caches[i] != -1){ + if(chunk.caches[i] != -1 && i != CacheLayer.walls.ordinal()){ drawnLayerSet.add(i); } } diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 5d6ac0e182..fa419655bf 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -5,20 +5,18 @@ 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.Time; import io.anuke.arc.util.io.CounterInputStream; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.world.*; -import io.anuke.mindustry.world.Tile.TileConstructor; -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; /** Reads and writes map files. */ //TODO does this class even need to exist??? move to Maps? @@ -61,43 +59,64 @@ public class MapIO{ SaveIO.load(map.file); } - public static void loadMap(Map map, TileConstructor cons){ + public static void loadMap(Map map, WorldContext cons){ SaveIO.load(map.file, cons); } public static Pixmap generatePreview(Map map) throws IOException{ - Time.mark(); - Pixmap floors = new Pixmap(map.width, map.height, Format.RGBA8888); - Pixmap walls = new Pixmap(map.width, map.height, Format.RGBA8888); - int black = Color.rgba8888(Color.BLACK); - int shade = Color.rgba8888(0f, 0f, 0f, 0.5f); - CachedTile tile = new CachedTile(){ - @Override - public void setFloor(Floor type){ - floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(type, Blocks.air, Blocks.air, getTeam())); - } + try(InputStream is = new InflaterInputStream(map.file.read(bufferSize)); CounterInputStream counter = new CounterInputStream(is); DataInputStream stream = new DataInputStream(counter)){ + SaveIO.readHeader(stream); + int version = stream.readInt(); + SaveVersion ver = SaveIO.getSaveWriter(version); + ver.region("meta", stream, counter, ver::readStringMap); - @Override - public void setOverlay(Block type){ - if(type != Blocks.air) - floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(floor(), Blocks.air, type, getTeam())); - } - - @Override - protected void changed(){ - super.changed(); - int c = colorFor(Blocks.air, block(), Blocks.air, getTeam()); - if(c != black){ - walls.drawPixel(x, floors.getHeight() - 1 - y, c); - floors.drawPixel(x, floors.getHeight() - 1 - y + 1, shade); + Pixmap floors = new Pixmap(map.width, map.height, Format.RGBA8888); + Pixmap walls = new Pixmap(map.width, map.height, Format.RGBA8888); + int black = Color.rgba8888(Color.BLACK); + int shade = Color.rgba8888(0f, 0f, 0f, 0.5f); + CachedTile tile = new CachedTile(){ + @Override + public void setBlock(Block type){ + super.setBlock(type); + int c = colorFor(Blocks.air, block(), Blocks.air, getTeam()); + if(c != black){ + walls.drawPixel(x, floors.getHeight() - 1 - y, c); + floors.drawPixel(x, floors.getHeight() - 1 - y + 1, shade); + } } - } - }; + }; - floors.drawPixmap(walls, 0, 0); - walls.dispose(); - //TODO actually generate the preview - return floors; + ver.region("content", stream, counter, ver::readContentHeader); + ver.region("preview_map", stream, counter, in -> ver.readMap(in, new WorldContext(){ + @Override public void resize(int width, int height){} + @Override public boolean isGenerating(){return false;} + @Override public void begin(){} + @Override public void end(){} + + @Override + public Tile tile(int x, int y){ + tile.x = (short)x; + tile.y = (short)y; + return tile; + } + + @Override + public Tile create(int x, int y, int floorID, int overlayID, int wallID){ + if(overlayID != 0){ + floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(Blocks.air, Blocks.air, content.block(overlayID), Team.none)); + }else{ + floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(content.block(floorID), Blocks.air, Blocks.air, Team.none)); + } + return tile; + } + })); + + floors.drawPixmap(walls, 0, 0); + walls.dispose(); + return floors; + }finally{ + content.setTemporaryMapper(null); + } } public static Pixmap generatePreview(Tile[][] tiles){ diff --git a/core/src/io/anuke/mindustry/io/SaveFileReader.java b/core/src/io/anuke/mindustry/io/SaveFileReader.java index c8f9eb9f2a..8384aca50e 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileReader.java +++ b/core/src/io/anuke/mindustry/io/SaveFileReader.java @@ -5,7 +5,7 @@ import io.anuke.arc.collection.ObjectMap.Entry; import io.anuke.arc.collection.StringMap; import io.anuke.arc.util.io.CounterInputStream; import io.anuke.arc.util.io.ReusableByteOutStream; -import io.anuke.mindustry.world.Tile.TileConstructor; +import io.anuke.mindustry.world.WorldContext; import java.io.*; @@ -103,7 +103,7 @@ public abstract class SaveFileReader{ return map; } - public abstract void read(DataInputStream stream, CounterInputStream counter, TileConstructor tiles) throws IOException; + public abstract void read(DataInputStream stream, CounterInputStream counter, WorldContext context) throws IOException; public abstract void write(DataOutputStream stream) throws IOException; diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 0b2efad272..bfee055910 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -6,8 +6,7 @@ import io.anuke.arc.util.io.CounterInputStream; import io.anuke.arc.util.io.FastDeflaterOutputStream; import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save1; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.Tile.TileConstructor; +import io.anuke.mindustry.world.WorldContext; import java.io.*; import java.util.Arrays; @@ -133,18 +132,18 @@ public class SaveIO{ } public static void load(FileHandle file) throws SaveException{ - load(file, Tile::new); + load(file, world.context); } - public static void load(FileHandle file, TileConstructor cons) throws SaveException{ + public static void load(FileHandle file, WorldContext context) throws SaveException{ try{ //try and load; if any exception at all occurs - load(new InflaterInputStream(file.read(bufferSize)), cons); + load(new InflaterInputStream(file.read(bufferSize)), context); }catch(SaveException e){ e.printStackTrace(); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); if(backup.exists()){ - load(new InflaterInputStream(backup.read(bufferSize)), cons); + load(new InflaterInputStream(backup.read(bufferSize)), context); }else{ throw new SaveException(e.getCause()); } @@ -152,14 +151,14 @@ public class SaveIO{ } /** Loads from a deflated (!) input stream.*/ - public static void load(InputStream is, TileConstructor cons) throws SaveException{ + public static void load(InputStream is, WorldContext context) throws SaveException{ try(CounterInputStream counter = new CounterInputStream(is); DataInputStream stream = new DataInputStream(counter)){ logic.reset(); readHeader(stream); int version = stream.readInt(); SaveVersion ver = versions.get(version); - ver.read(stream, counter, cons); + ver.read(stream, counter, context); }catch(Exception e){ throw new SaveException(e); }finally{ diff --git a/core/src/io/anuke/mindustry/io/SaveVersion.java b/core/src/io/anuke/mindustry/io/SaveVersion.java index 1819e79360..ffa3df29c0 100644 --- a/core/src/io/anuke/mindustry/io/SaveVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveVersion.java @@ -9,9 +9,7 @@ import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.*; import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.Tile.TileConstructor; +import io.anuke.mindustry.world.*; import java.io.*; @@ -36,10 +34,10 @@ public abstract class SaveVersion extends SaveFileReader{ } @Override - public final void read(DataInputStream stream, CounterInputStream counter, TileConstructor tiles) throws IOException{ + public final void read(DataInputStream stream, CounterInputStream counter, WorldContext context) throws IOException{ region("meta", stream, counter, this::readMeta); region("content", stream, counter, this::readContentHeader); - region("map", stream, counter, in -> readMap(in, tiles)); + region("map", stream, counter, in -> readMap(in, context)); region("entities", stream, counter, this::readEntities); } @@ -130,15 +128,16 @@ public abstract class SaveVersion extends SaveFileReader{ } } - public void readMap(DataInput stream, TileConstructor constructor) throws IOException{ + public void readMap(DataInput stream, WorldContext context) throws IOException{ int width = stream.readUnsignedShort(); int height = stream.readUnsignedShort(); - boolean generating = world.isGenerating(); + boolean generating = context.isGenerating(); - if(!generating) world.beginMapLoad(); + if(!generating) context.begin(); - Tile[][] tiles = world.createTiles(width, height); + //Tile[][] tiles = world.createTiles(width, height); + context.resize(width, height); //read floor and create tiles first for(int i = 0; i < width * height; i++){ @@ -147,11 +146,11 @@ public abstract class SaveVersion extends SaveFileReader{ short oreid = stream.readShort(); int consecutives = stream.readUnsignedByte(); - tiles[x][y] = constructor.construct(x, y, floorid, oreid, (short)0); + context.create(x, y, floorid, oreid, (short)0); for(int j = i + 1; j < i + 1 + consecutives; j++){ int newx = j % width, newy = j / width; - tiles[newx][newy] = constructor.construct(newx, newy, floorid, oreid, (short)0); + context.create(newx, newy, floorid, oreid, (short)0); } i += consecutives; @@ -161,7 +160,7 @@ public abstract class SaveVersion extends SaveFileReader{ for(int i = 0; i < width * height; i++){ int x = i % width, y = i / width; Block block = content.block(stream.readShort()); - Tile tile = tiles[x][y]; + Tile tile = context.tile(x, y); tile.setBlock(block); if(tile.entity != null){ @@ -174,7 +173,7 @@ public abstract class SaveVersion extends SaveFileReader{ for(int j = i + 1; j < i + 1 + consecutives; j++){ int newx = j % width, newy = j / width; - tiles[newx][newy].setBlock(block); + context.tile(newx, newy).setBlock(block); } i += consecutives; @@ -182,7 +181,7 @@ public abstract class SaveVersion extends SaveFileReader{ } content.setTemporaryMapper(null); - if(!generating) world.endMapLoad(); + if(!generating) context.end(); } public void writeEntities(DataOutput stream) throws IOException{ diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 7f97bbee1f..48d467d17d 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -8,7 +8,6 @@ import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.world.Tile; import java.io.*; import java.nio.ByteBuffer; @@ -53,7 +52,7 @@ public class NetworkIO{ player.resetID(id); player.add(); - SaveIO.getSaveWriter().readMap(stream, Tile::new); + SaveIO.getSaveWriter().readMap(stream, world.context); }catch(IOException e){ throw new RuntimeException(e); } diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index d55e2dd694..965ed5a5bc 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -454,8 +454,4 @@ public class Tile implements Position, TargetTrait{ public String toString(){ return floor.name + ":" + block.name + ":" + content.block(overlay) + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())); } - - public interface TileConstructor{ - Tile construct(int x, int y, int floor, int overlay, int wall); - } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/WorldContext.java b/core/src/io/anuke/mindustry/world/WorldContext.java new file mode 100644 index 0000000000..12a3d190b3 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/WorldContext.java @@ -0,0 +1,22 @@ +package io.anuke.mindustry.world; + +public interface WorldContext{ + + /** Return a tile in the tile array.*/ + Tile tile(int x, int y); + + /** Create the tile array.*/ + void resize(int width, int height); + + /** This should create a tile and put it into the tile array, then return it. */ + Tile create(int x, int y, int floorID, int overlayID, int wallID); + + /** Returns whether the world is already generating.*/ + boolean isGenerating(); + + /** Begins generating.*/ + void begin(); + + /** End generating, prepares tiles.*/ + void end(); +}