Implemented fog saving

This commit is contained in:
Anuken
2018-07-27 17:26:12 -04:00
parent 0d4cf9f6c4
commit 0875c29da5
10 changed files with 149 additions and 43 deletions

View File

@@ -29,7 +29,10 @@ public class Mindustry extends ModuleCore{
module(ui = new UI()); module(ui = new UI());
module(netServer = new NetServer()); module(netServer = new NetServer());
module(netClient = new NetClient()); module(netClient = new NetClient());
}
@Override
public void postInit(){
Log.info("Time to load [total]: {0}", Timers.elapsed()); Log.info("Time to load [total]: {0}", Timers.elapsed());
} }

View File

@@ -48,7 +48,6 @@ public class Control extends Module{
private ObjectMap<Sound, Long> soundMap = new ObjectMap<>(); private ObjectMap<Sound, Long> soundMap = new ObjectMap<>();
private Throwable error; private Throwable error;
//private Input gdxInput;
public Control(){ public Control(){
@@ -68,8 +67,6 @@ public class Control extends Module{
db.load(); db.load();
//gdxInput = Gdx.input;
Sounds.setFalloff(9000f); Sounds.setFalloff(9000f);
Sounds.setPlayer((sound, volume) -> { Sounds.setPlayer((sound, volume) -> {
long time = TimeUtils.millis(); long time = TimeUtils.millis();

View File

@@ -67,21 +67,21 @@ public class UI extends SceneModule{
public UI(){ public UI(){
Dialog.setShowAction(() -> sequence( Dialog.setShowAction(() -> sequence(
alpha(0f), alpha(0f),
originCenter(), originCenter(),
moveToAligned(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, Align.center), moveToAligned(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, Align.center),
scaleTo(0.0f, 1f), scaleTo(0.0f, 1f),
parallel( parallel(
scaleTo(1f, 1f, 0.1f, Interpolation.fade), scaleTo(1f, 1f, 0.1f, Interpolation.fade),
fadeIn(0.1f, Interpolation.fade) fadeIn(0.1f, Interpolation.fade)
) )
)); ));
Dialog.setHideAction(() -> sequence( Dialog.setHideAction(() -> sequence(
parallel( parallel(
scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade), scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade),
fadeOut(0.1f, Interpolation.fade) fadeOut(0.1f, Interpolation.fade)
) )
)); ));
TooltipManager.getInstance().animations = false; TooltipManager.getInstance().animations = false;
@@ -179,6 +179,7 @@ public class UI extends SceneModule{
listfrag.build(group); listfrag.build(group);
debugfrag.build(group); debugfrag.build(group);
loadfrag.build(group); loadfrag.build(group);
} }
@Override @Override

View File

@@ -495,7 +495,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
.size(size).get().setAlignment(Align.center, Align.center); .size(size).get().setAlignment(Align.center, Align.center);
t.addImageButton("icon-arrow-right", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() + 1)) t.addImageButton("icon-arrow-right", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() + 1))
.disabled(b -> editor.getDrawElevation() >= 127).size(size); .disabled(b -> editor.getDrawElevation() >= 63).size(size);
}).colspan(3).height(size).padTop(-5).width(size * 3f); }).colspan(3).height(size).padTop(-5).width(size * 3f);
}).margin(0).left().growY(); }).margin(0).left().growY();

View File

@@ -75,8 +75,7 @@ public class Saves{
Timers.run(2f, () -> { Timers.run(2f, () -> {
try{ try{
SaveIO.saveToSlot(current.index); current.save();
current.meta = SaveIO.getData(current.index);
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }
@@ -108,10 +107,7 @@ public class Saves{
slot.setName(name); slot.setName(name);
saves.add(slot); saves.add(slot);
saveMap.put(slot.index, slot); saveMap.put(slot.index, slot);
SaveIO.saveToSlot(slot.index); slot.save();
slot.meta = SaveIO.getData(slot.index);
current = slot;
saveSlots(); saveSlots();
return slot; return slot;
} }
@@ -162,9 +158,18 @@ public class Saves{
} }
public void save(){ public void save(){
SaveIO.saveToSlot(index); threads.runGraphics(() -> {
meta = SaveIO.getData(index); //Renderer fog needs to be written on graphics thread, but save() can run on logic thread
current = this; //thus, runGraphics is required here
renderer.fog().writeFog();
//save on the logic thread
threads.run(() -> {
SaveIO.saveToSlot(index);
meta = SaveIO.getData(index);
current = this;
});
});
} }
public boolean isHidden(){ public boolean isHidden(){

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.graphics;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
@@ -32,10 +33,11 @@ public class FogRenderer implements Disposable{
private TextureRegion region = new TextureRegion(); private TextureRegion region = new TextureRegion();
private FrameBuffer buffer; private FrameBuffer buffer;
private ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4); private ByteBuffer pixelBuffer;
private Array<Tile> changeQueue = new Array<>(); private Array<Tile> changeQueue = new Array<>();
private int padding; private int padding;
private Rectangle rect = new Rectangle(); private Rectangle rect = new Rectangle();
private boolean dirty;
public FogRenderer(){ public FogRenderer(){
Events.on(WorldLoadGraphicsEvent.class, () -> { Events.on(WorldLoadGraphicsEvent.class, () -> {
@@ -51,15 +53,8 @@ public class FogRenderer implements Disposable{
Graphics.clear(0, 0, 0, 1f); Graphics.clear(0, 0, 0, 1f);
buffer.end(); buffer.end();
for(int x = 0; x < world.width(); x++){ pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 3);
for(int y = 0; y < world.height(); y++){ dirty = true;
Tile tile = world.tile(x, y);
if(tile.getTeam() == players[0].getTeam() && tile.block().synthetic() && tile.block().viewRange > 0){
changeQueue.add(tile);
}
}
}
}); });
Events.on(TileChangeEvent.class, tile -> threads.runGraphics(() -> { Events.on(TileChangeEvent.class, tile -> threads.runGraphics(() -> {
@@ -69,6 +64,25 @@ public class FogRenderer implements Disposable{
})); }));
} }
public void writeFog(){
if(buffer == null) return;
buffer.begin();
pixelBuffer.position(0);
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
Gdx.gl.glReadPixels(padding, padding, world.width(), world.height(), GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, pixelBuffer);
pixelBuffer.position(0);
for(int i = 0; i < world.width() * world.height(); i++){
byte r = pixelBuffer.get();
if(r != 0){
world.tile(i).setVisibility((byte)1);
}
pixelBuffer.position(pixelBuffer.position() + 2);
}
buffer.end();
}
public int getPadding(){ public int getPadding(){
return padding; return padding;
} }
@@ -94,12 +108,6 @@ public class FogRenderer implements Disposable{
buffer.begin(); buffer.begin();
//TODO use this for per-tile visibility to show/hide units
//pixelBuffer.position(0);
//Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
//Gdx.gl.glReadPixels(world.width()/2, world.height()/2 + 20, 1, 1, GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, pixelBuffer);
//Log.info(pixelBuffer.get(0));
boolean pop = ScissorStack.pushScissors(rect.set((padding-shadowPadding), (padding-shadowPadding), boolean pop = ScissorStack.pushScissors(rect.set((padding-shadowPadding), (padding-shadowPadding),
(world.width() + shadowPadding*2) , (world.width() + shadowPadding*2) ,
(world.height() + shadowPadding*2))); (world.height() + shadowPadding*2)));
@@ -118,6 +126,16 @@ public class FogRenderer implements Disposable{
changeQueue.clear(); changeQueue.clear();
if(dirty){
for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i);
if(tile.discovered()){
Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize);
}
}
dirty = false;
}
EntityDraw.setClip(true); EntityDraw.setClip(true);
Graphics.end(); Graphics.end();
buffer.end(); buffer.end();

View File

@@ -135,6 +135,18 @@ public class Save16 extends SaveFileVersion{
tiles[x][y] = tile; tiles[x][y] = tile;
} }
for(int i = 0; i < width * height; i++){
boolean discovered = stream.readBoolean();
int consecutives = stream.readUnsignedShort();
if(discovered){
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
tiles[newx][newy].setVisibility((byte) 1);
}
}
i += consecutives;
}
world.endMapLoad(); world.endMapLoad();
} }
@@ -223,5 +235,27 @@ public class Save16 extends SaveFileVersion{
i += consecutives; i += consecutives;
} }
} }
//write visibility, length-run encoded
for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i);
boolean discovered = tile.discovered();
int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
Tile nextTile = world.tile(j);
if(nextTile.discovered() != discovered){
break;
}
consecutives++;
}
stream.writeBoolean(discovered);
stream.writeShort(consecutives);
i += consecutives;
}
} }
} }

View File

@@ -96,6 +96,28 @@ public class NetworkIO{
} }
} }
//write visibility, length-run encoded
for(int i = 0; i < world.width() * world.height(); i++){
Tile tile = world.tile(i);
boolean discovered = tile.discovered();
int consecutives = 0;
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
Tile nextTile = world.tile(j);
if(nextTile.discovered() != discovered){
break;
}
consecutives++;
}
stream.writeBoolean(discovered);
stream.writeShort(consecutives);
i += consecutives;
}
//write team data //write team data
stream.writeByte(state.teams.getTeams().size); stream.writeByte(state.teams.getTeams().size);
for(TeamData data : state.teams.getTeams()){ for(TeamData data : state.teams.getTeams()){
@@ -215,6 +237,18 @@ public class NetworkIO{
tiles[x][y] = tile; tiles[x][y] = tile;
} }
for(int i = 0; i < width * height; i++){
boolean discovered = stream.readBoolean();
int consecutives = stream.readUnsignedShort();
if(discovered){
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
tiles[newx][newy].setVisibility((byte) 1);
}
}
i += consecutives;
}
player.reset(); player.reset();
state.teams = new TeamInfo(); state.teams = new TeamInfo();

View File

@@ -44,6 +44,8 @@ public class Tile implements PosTrait, TargetTrait{
private byte team; private byte team;
/** Tile elevation. -1 means slope.*/ /** Tile elevation. -1 means slope.*/
private byte elevation; private byte elevation;
/** Visibility status: 3 states, but saved as a single bit. 0 = unexplored, 1 = visited, 2 = currently visible (saved as 1)*/
private byte visibility;
public Tile(int x, int y){ public Tile(int x, int y){
this.x = (short) x; this.x = (short) x;
@@ -67,6 +69,10 @@ public class Tile implements PosTrait, TargetTrait{
this.team = team; this.team = team;
} }
public boolean discovered(){
return visibility > 0;
}
public int packedPosition(){ public int packedPosition(){
return x + y * world.width(); return x + y * world.width();
} }
@@ -172,6 +178,14 @@ public class Tile implements PosTrait, TargetTrait{
this.floor = type; this.floor = type;
} }
public byte getVisibility(){
return visibility;
}
public void setVisibility(byte visibility){
this.visibility = visibility;
}
public byte getRotation(){ public byte getRotation(){
return rotation; return rotation;
} }

View File

@@ -108,8 +108,8 @@ public class DesktopPlatform extends Platform{
@Override @Override
public boolean isDebug(){ public boolean isDebug(){
//honestly I'm just putting this ridiculous """anti-debug""" mess here to see if anyone bothers solving it without editing source //honestly I'm just putting this ridiculous """anti-debug""" mess here to see if anyone bothers solving it without editing source
return args.length > 0 && args[0].equals("-debug_" + getUUID().hashCode() + "_" return args.length > 0 && args[0].equals(("-debug_" + getUUID().hashCode() + "_"
+ " " + System.getProperty("os.arch") + "nice" + (int)(Math.sin(System.getProperty("user.dir").hashCode()) * 100) + Thread.currentThread().getStackTrace()[1].toString()) && new File("../../desktop/build/").exists(); + " " + System.getProperty("os.arch") + "nice" + (int)(Math.sin(System.getProperty("user.dir").hashCode()) * 100) + Thread.currentThread().getStackTrace()[1].toString()).hashCode() + "") && new File("../../desktop/build/").exists();
} }
@Override @Override