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(netServer = new NetServer());
module(netClient = new NetClient());
}
@Override
public void postInit(){
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 Throwable error;
//private Input gdxInput;
public Control(){
@@ -68,8 +67,6 @@ public class Control extends Module{
db.load();
//gdxInput = Gdx.input;
Sounds.setFalloff(9000f);
Sounds.setPlayer((sound, volume) -> {
long time = TimeUtils.millis();

View File

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

View File

@@ -495,7 +495,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
.size(size).get().setAlignment(Align.center, Align.center);
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);
}).margin(0).left().growY();

View File

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

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.graphics;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
@@ -32,10 +33,11 @@ public class FogRenderer implements Disposable{
private TextureRegion region = new TextureRegion();
private FrameBuffer buffer;
private ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4);
private ByteBuffer pixelBuffer;
private Array<Tile> changeQueue = new Array<>();
private int padding;
private Rectangle rect = new Rectangle();
private boolean dirty;
public FogRenderer(){
Events.on(WorldLoadGraphicsEvent.class, () -> {
@@ -51,15 +53,8 @@ public class FogRenderer implements Disposable{
Graphics.clear(0, 0, 0, 1f);
buffer.end();
for(int x = 0; x < world.width(); x++){
for(int y = 0; y < world.height(); y++){
Tile tile = world.tile(x, y);
if(tile.getTeam() == players[0].getTeam() && tile.block().synthetic() && tile.block().viewRange > 0){
changeQueue.add(tile);
}
}
}
pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 3);
dirty = true;
});
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(){
return padding;
}
@@ -94,12 +108,6 @@ public class FogRenderer implements Disposable{
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),
(world.width() + shadowPadding*2) ,
(world.height() + shadowPadding*2)));
@@ -118,6 +126,16 @@ public class FogRenderer implements Disposable{
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);
Graphics.end();
buffer.end();

View File

@@ -135,6 +135,18 @@ public class Save16 extends SaveFileVersion{
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();
}
@@ -223,5 +235,27 @@ public class Save16 extends SaveFileVersion{
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
stream.writeByte(state.teams.getTeams().size);
for(TeamData data : state.teams.getTeams()){
@@ -215,6 +237,18 @@ public class NetworkIO{
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();
state.teams = new TeamInfo();

View File

@@ -44,6 +44,8 @@ public class Tile implements PosTrait, TargetTrait{
private byte team;
/** Tile elevation. -1 means slope.*/
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){
this.x = (short) x;
@@ -67,6 +69,10 @@ public class Tile implements PosTrait, TargetTrait{
this.team = team;
}
public boolean discovered(){
return visibility > 0;
}
public int packedPosition(){
return x + y * world.width();
}
@@ -172,6 +178,14 @@ public class Tile implements PosTrait, TargetTrait{
this.floor = type;
}
public byte getVisibility(){
return visibility;
}
public void setVisibility(byte visibility){
this.visibility = visibility;
}
public byte getRotation(){
return rotation;
}