mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-16 18:58:01 +07:00
Map previews functional
This commit is contained in:
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,31 +59,25 @@ 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();
|
||||
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);
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
@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();
|
||||
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);
|
||||
@ -94,10 +86,37 @@ public class MapIO{
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
//TODO actually generate the preview
|
||||
return floors;
|
||||
}finally{
|
||||
content.setTemporaryMapper(null);
|
||||
}
|
||||
}
|
||||
|
||||
public static Pixmap generatePreview(Tile[][] tiles){
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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{
|
||||
|
@ -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{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
22
core/src/io/anuke/mindustry/world/WorldContext.java
Normal file
22
core/src/io/anuke/mindustry/world/WorldContext.java
Normal file
@ -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();
|
||||
}
|
Reference in New Issue
Block a user