diff --git a/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java b/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java index 4e743db..65e1562 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java +++ b/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java @@ -9,8 +9,9 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.utils.Align; import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; -public abstract class BaseScorer { +public abstract class BaseScorer implements BinSerializable { //region Members diff --git a/core/src/io/github/lonamiwebs/klooni/game/Board.java b/core/src/io/github/lonamiwebs/klooni/game/Board.java index 6c430de..d091237 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Board.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Board.java @@ -6,11 +6,16 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; // Represents the on screen board, with all the put cells // and functions to determine when it is game over given a PieceHolder -public class Board { +public class Board implements BinSerializable { //region Members @@ -185,4 +190,30 @@ public class Board { } //endregion + + //region Serialization + + @Override + public void write(DataOutputStream out) throws IOException { + // Cell count, cells in row-major order + out.writeInt(cellCount); + for (int i = 0; i < cellCount; ++i) + for (int j = 0; j < cellCount; ++j) + cells[i][j].write(out); + } + + @Override + public void read(DataInputStream in) throws IOException { + // If the saved cell count does not match the current cell count, + // then an IOException is thrown since the data saved was invalid + final int savedCellCount = in.readInt(); + if (savedCellCount != cellCount) + throw new IOException("Invalid cellCount saved."); + + for (int i = 0; i < cellCount; ++i) + for (int j = 0; j < cellCount; ++j) + cells[i][j].read(in); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/Cell.java b/core/src/io/github/lonamiwebs/klooni/game/Cell.java index a221666..861332e 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Cell.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Cell.java @@ -7,11 +7,16 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Vector2; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; // Represents a single cell, with a position, size and color. // Instances will use the cell texture provided by the currently used skin. -public class Cell { +public class Cell implements BinSerializable { //region Members @@ -108,4 +113,19 @@ public class Cell { } //endregion + + //region Serialization + + @Override + public void write(DataOutputStream out) throws IOException { + // Only the color index is saved + out.writeInt(colorIndex); + } + + @Override + public void read(DataInputStream in) throws IOException { + colorIndex = in.readInt(); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/Piece.java b/core/src/io/github/lonamiwebs/klooni/game/Piece.java index 4a8aa6a..e19f526 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Piece.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Piece.java @@ -6,6 +6,10 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import io.github.lonamiwebs.klooni.Klooni; // Represents a piece with an arbitrary shape, which @@ -88,22 +92,25 @@ public class Piece { // Generates a random piece with always the same color for the generated shape static Piece random() { - int color = MathUtils.random(8); // 9 pieces - switch (color) { + return fromIndex(MathUtils.random(8)); // 9 pieces, [0…8] + } + + private static Piece fromIndex(int colorIndex) { + switch (colorIndex) { // Squares - case 0: return new Piece(1, 1, false, color); - case 1: return new Piece(2, 2, false, color); - case 2: return new Piece(3, 3, false, color); + case 0: return new Piece(1, 1, false, colorIndex); + case 1: return new Piece(2, 2, false, colorIndex); + case 2: return new Piece(3, 3, false, colorIndex); // Lines - case 3: return new Piece(1, 2, MathUtils.randomBoolean(), color); - case 4: return new Piece(1, 3, MathUtils.randomBoolean(), color); - case 5: return new Piece(1, 4, MathUtils.randomBoolean(), color); - case 6: return new Piece(1, 5, MathUtils.randomBoolean(), color); + case 3: return new Piece(1, 2, MathUtils.randomBoolean(), colorIndex); + case 4: return new Piece(1, 3, MathUtils.randomBoolean(), colorIndex); + case 5: return new Piece(1, 4, MathUtils.randomBoolean(), colorIndex); + case 6: return new Piece(1, 5, MathUtils.randomBoolean(), colorIndex); // L's - case 7: return new Piece(2, MathUtils.random(3), color); - case 8: return new Piece(3, MathUtils.random(3), color); + case 7: return new Piece(2, MathUtils.random(3), colorIndex); + case 8: return new Piece(3, MathUtils.random(3), colorIndex); } throw new RuntimeException("Random function is broken."); } @@ -161,4 +168,16 @@ public class Piece { } //endregion + + //region Serialization + + void write(DataOutputStream out) throws IOException { + out.writeInt(colorIndex); + } + + static Piece read(DataInputStream in) throws IOException { + return fromIndex(in.readInt()); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java index 831eb6f..0fc3faf 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java +++ b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java @@ -9,11 +9,16 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; // A holder of pieces that can be drawn on screen. // Pieces can be picked up from it and dropped on a board. -public class PieceHolder { +public class PieceHolder implements BinSerializable { //region Members @@ -229,4 +234,34 @@ public class PieceHolder { } //endregion + + //region Serialization + + @Override + public void write(DataOutputStream out) throws IOException { + // Piece count, false if piece == null, true + piece if piece != null + out.writeInt(count); + for (int i = 0; i < count; ++i) { + if (pieces[i] == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + pieces[i].write(out); + } + } + } + + @Override + public void read(DataInputStream in) throws IOException { + // If the saved piece count does not match the current piece count, + // then an IOException is thrown since the data saved was invalid + final int savedPieceCount = in.readInt(); + if (savedPieceCount != count) + throw new IOException("Invalid piece count saved."); + + for (int i = 0; i < count; i++) + pieces[i] = in.readBoolean() ? Piece.read(in) : null; + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/Scorer.java b/core/src/io/github/lonamiwebs/klooni/game/Scorer.java index 67c0f10..d980b83 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Scorer.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Scorer.java @@ -4,16 +4,21 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.MathUtils; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; // Used to keep track of the current and maximum // score, and to also display it on the screen. // The maximum score is NOT saved automatically. -public class Scorer extends BaseScorer { +public class Scorer extends BaseScorer implements BinSerializable { //region Members - private int currentScore, maxScore; + private int currentScore, highScore; // To interpolate between shown score -> real score private float shownScore; @@ -27,7 +32,7 @@ public class Scorer extends BaseScorer { super(game, layout, Klooni.getMaxScore()); currentScore = 0; - maxScore = Klooni.getMaxScore(); + highScore = Klooni.getMaxScore(); } //endregion @@ -55,7 +60,7 @@ public class Scorer extends BaseScorer { @Override protected boolean isNewRecord() { - return currentScore > maxScore; + return currentScore > highScore; } @Override @@ -73,4 +78,21 @@ public class Scorer extends BaseScorer { } //endregion + + //region Serialization + + @Override + public void write(DataOutputStream out) throws IOException { + // currentScore, highScore + out.writeInt(currentScore); + out.writeInt(highScore); + } + + @Override + public void read(DataInputStream in) throws IOException { + currentScore = in.readInt(); + highScore = in.readInt(); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/TimeScorer.java b/core/src/io/github/lonamiwebs/klooni/game/TimeScorer.java index bd89ba7..e390b26 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/TimeScorer.java +++ b/core/src/io/github/lonamiwebs/klooni/game/TimeScorer.java @@ -4,14 +4,19 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.TimeUtils; -import io.github.lonamiwebs.klooni.Klooni; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; -public class TimeScorer extends BaseScorer { +import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.serializer.BinSerializable; + +public class TimeScorer extends BaseScorer implements BinSerializable { //region Members private long startTime; - private final int highScoreTime; + private int highScoreTime; // Indicates where we would die in time. Score adds to this, so we take // longer to die. To get the "score" we simply calculate `deadTime - startTime` @@ -113,4 +118,23 @@ public class TimeScorer extends BaseScorer { } //endregion + + //region Serialization + + @Override + public void write(DataOutputStream out) throws IOException { + // startTime, highScoreTime, deadTime + out.writeLong(startTime); + out.writeInt(highScoreTime); + out.writeLong(deadTime); + } + + @Override + public void read(DataInputStream in) throws IOException { + startTime = in.readLong(); + highScoreTime = in.readInt(); + deadTime = in.readLong(); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializable.java b/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializable.java new file mode 100644 index 0000000..9005870 --- /dev/null +++ b/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializable.java @@ -0,0 +1,10 @@ +package io.github.lonamiwebs.klooni.serializer; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public interface BinSerializable { + void write(final DataOutputStream out) throws IOException; + void read(final DataInputStream in) throws IOException; +} diff --git a/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializer.java b/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializer.java new file mode 100644 index 0000000..68c241c --- /dev/null +++ b/core/src/io/github/lonamiwebs/klooni/serializer/BinSerializer.java @@ -0,0 +1,38 @@ +package io.github.lonamiwebs.klooni.serializer; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class BinSerializer { + public static void serialize(final BinSerializable serializable, final OutputStream output) + throws IOException { + DataOutputStream out = new DataOutputStream(output); + try { + serializable.write(out); + } finally { + try { + out.close(); + } catch (IOException ignored) { } + } + + // todo uhm maybe make the classes serializable? like telethon, kinda, idk, bye. + + + /* + DataInputStream d = new DataInputStream(new FileInputStream("test.txt")); + DataOutputStream out = new DataOutputStream(new FileOutputStream("test1.txt")); + String count; + d.readFully(); + while((count = d.readLine()) != null){ + String u = count.toUpperCase(); + System.out.println(u); + out.writeBytes(u + " ,"); + } + d.close(); + out.close(); + */ + + + } +}