Cleanup and refactoring: Eliminate duplicated code.
This commit is contained in:
parent
9579066cb5
commit
5a642b354b
10 changed files with 132 additions and 246 deletions
|
@ -0,0 +1,100 @@
|
||||||
|
package ch.fritteli.maze.generator.serialization;
|
||||||
|
|
||||||
|
import ch.fritteli.maze.generator.model.Direction;
|
||||||
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary format description of a {@link Tile}.<br>
|
||||||
|
* A tile is stored in one byte:
|
||||||
|
* <ul>
|
||||||
|
* <li>bits 0..2: always 0</li>
|
||||||
|
* <li>bit 3: 1=solution, 0=not solution</li>
|
||||||
|
* <li>bits 4..7: encode walls</li>
|
||||||
|
* </ul>
|
||||||
|
* The values for bits 4..7 are as follows:
|
||||||
|
* <pre>
|
||||||
|
* decimal hex bin border
|
||||||
|
* 0 0 0000 no border
|
||||||
|
* 1 1 0001 top
|
||||||
|
* 2 2 0010 right
|
||||||
|
* 3 3 0011 top+right
|
||||||
|
* 4 4 0100 bottom
|
||||||
|
* 5 5 0101 top+bottom
|
||||||
|
* 6 6 0110 right+bottom
|
||||||
|
* 7 7 0111 top+right+bottom
|
||||||
|
* 8 8 1000 left
|
||||||
|
* 9 9 1001 top+left
|
||||||
|
* 10 a 1010 right+left
|
||||||
|
* 11 b 1011 top+right+left
|
||||||
|
* 12 c 1100 bottom+left
|
||||||
|
* 13 d 1101 top+bottom+left
|
||||||
|
* 14 e 1110 right+bottom+left
|
||||||
|
* 15 f 1111 top+right+bottom+left
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@UtilityClass
|
||||||
|
public class CommonTileHandler {
|
||||||
|
private final byte TOP_BIT = 0b0000_0001;
|
||||||
|
private final byte RIGHT_BIT = 0b0000_0010;
|
||||||
|
private final byte BOTTOM_BIT = 0b0000_0100;
|
||||||
|
private final byte LEFT_BIT = 0b0000_1000;
|
||||||
|
private final byte SOLUTION_BIT = 0b0001_0000;
|
||||||
|
|
||||||
|
public byte getBitmaskForTile(@NotNull final Tile tile) {
|
||||||
|
byte bitmask = 0;
|
||||||
|
if (tile.hasWallAt(Direction.TOP)) {
|
||||||
|
bitmask |= TOP_BIT;
|
||||||
|
}
|
||||||
|
if (tile.hasWallAt(Direction.RIGHT)) {
|
||||||
|
bitmask |= RIGHT_BIT;
|
||||||
|
}
|
||||||
|
if (tile.hasWallAt(Direction.BOTTOM)) {
|
||||||
|
bitmask |= BOTTOM_BIT;
|
||||||
|
}
|
||||||
|
if (tile.hasWallAt((Direction.LEFT))) {
|
||||||
|
bitmask |= LEFT_BIT;
|
||||||
|
}
|
||||||
|
if (tile.isSolution()) {
|
||||||
|
bitmask |= SOLUTION_BIT;
|
||||||
|
}
|
||||||
|
return bitmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Tile getTileForBitmask(final byte bitmask) {
|
||||||
|
final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class);
|
||||||
|
if ((bitmask & TOP_BIT) == TOP_BIT) {
|
||||||
|
walls.add(Direction.TOP);
|
||||||
|
}
|
||||||
|
if ((bitmask & RIGHT_BIT) == RIGHT_BIT) {
|
||||||
|
walls.add(Direction.RIGHT);
|
||||||
|
}
|
||||||
|
if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) {
|
||||||
|
walls.add(Direction.BOTTOM);
|
||||||
|
}
|
||||||
|
if ((bitmask & LEFT_BIT) == LEFT_BIT) {
|
||||||
|
walls.add(Direction.LEFT);
|
||||||
|
}
|
||||||
|
final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT;
|
||||||
|
return createTile(walls, solution);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) {
|
||||||
|
try {
|
||||||
|
final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return constructor.newInstance(walls, solution);
|
||||||
|
} catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||||
|
InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Can not deserialize Tile from maze data.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package ch.fritteli.maze.generator.serialization.v1;
|
||||||
import ch.fritteli.maze.generator.model.Maze;
|
import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class MazeInputStreamV1 extends AbstractMazeInputStream {
|
public class MazeInputStreamV1 extends AbstractMazeInputStream {
|
||||||
|
@ -13,6 +14,9 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkHeader() {
|
public void checkHeader() {
|
||||||
|
// 00 0x1a magic
|
||||||
|
// 01 0xb1 magic
|
||||||
|
// 02 0x01 version
|
||||||
final byte magic1 = this.readByte();
|
final byte magic1 = this.readByte();
|
||||||
if (magic1 != SerializerDeserializerV1.MAGIC_BYTE_1) {
|
if (magic1 != SerializerDeserializerV1.MAGIC_BYTE_1) {
|
||||||
throw new IllegalArgumentException("Invalid maze data.");
|
throw new IllegalArgumentException("Invalid maze data.");
|
||||||
|
@ -30,6 +34,10 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Maze readMazeData() {
|
public Maze readMazeData() {
|
||||||
|
// 03..10 random seed number (long)
|
||||||
|
// 11..14 width (int)
|
||||||
|
// 15..18 height (int)
|
||||||
|
// 19.. tiles
|
||||||
final long randomSeed = this.readLong();
|
final long randomSeed = this.readLong();
|
||||||
final int width = this.readInt();
|
final int width = this.readInt();
|
||||||
final int height = this.readInt();
|
final int height = this.readInt();
|
||||||
|
@ -42,7 +50,7 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
final byte bitmask = this.readByte();
|
final byte bitmask = this.readByte();
|
||||||
tiles[x][y] = SerializerDeserializerV1.getTileForBitmask(bitmask);
|
tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,16 @@ package ch.fritteli.maze.generator.serialization.v1;
|
||||||
import ch.fritteli.maze.generator.model.Maze;
|
import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class MazeOutputStreamV1 extends AbstractMazeOutputStream {
|
public class MazeOutputStreamV1 extends AbstractMazeOutputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeader() {
|
public void writeHeader() {
|
||||||
|
// 00 0x1a magic
|
||||||
|
// 01 0xb1 magic
|
||||||
|
// 02 0x02 version
|
||||||
this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_1);
|
this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_1);
|
||||||
this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_2);
|
this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_2);
|
||||||
this.writeByte(SerializerDeserializerV1.VERSION_BYTE);
|
this.writeByte(SerializerDeserializerV1.VERSION_BYTE);
|
||||||
|
@ -16,6 +20,10 @@ public class MazeOutputStreamV1 extends AbstractMazeOutputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeMazeData(@NotNull final Maze maze) {
|
public void writeMazeData(@NotNull final Maze maze) {
|
||||||
|
// 03..10 random seed number (long)
|
||||||
|
// 11..14 width (int)
|
||||||
|
// 15..18 height (int)
|
||||||
|
// 19.. tiles
|
||||||
final long randomSeed = maze.getRandomSeed();
|
final long randomSeed = maze.getRandomSeed();
|
||||||
final int width = maze.getWidth();
|
final int width = maze.getWidth();
|
||||||
final int height = maze.getHeight();
|
final int height = maze.getHeight();
|
||||||
|
@ -27,7 +35,7 @@ public class MazeOutputStreamV1 extends AbstractMazeOutputStream {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
// We .get() it, because we want to crash hard if it is not available.
|
// We .get() it, because we want to crash hard if it is not available.
|
||||||
final Tile tile = maze.getTileAt(x, y).get();
|
final Tile tile = maze.getTileAt(x, y).get();
|
||||||
final byte bitmask = SerializerDeserializerV1.getBitmaskForTile(tile);
|
final byte bitmask = CommonTileHandler.getBitmaskForTile(tile);
|
||||||
this.writeByte(bitmask);
|
this.writeByte(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ch.fritteli.maze.generator.serialization.v1;
|
package ch.fritteli.maze.generator.serialization.v1;
|
||||||
|
|
||||||
import ch.fritteli.maze.generator.model.Direction;
|
|
||||||
import ch.fritteli.maze.generator.model.Maze;
|
import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
@ -8,37 +7,17 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.EnumSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* Header bytes are:
|
||||||
* decimal hex bin border
|
|
||||||
* 0 0 0000 no border
|
|
||||||
* 1 1 0001 top
|
|
||||||
* 2 2 0010 right
|
|
||||||
* 3 3 0011 top+right
|
|
||||||
* 4 4 0100 bottom
|
|
||||||
* 5 5 0101 top+bottom
|
|
||||||
* 6 6 0110 right+bottom
|
|
||||||
* 7 7 0111 top+right+bottom
|
|
||||||
* 8 8 1000 left
|
|
||||||
* 9 9 1001 top+left
|
|
||||||
* 10 a 1010 right+left
|
|
||||||
* 11 b 1011 top+right+left
|
|
||||||
* 12 c 1100 bottom+left
|
|
||||||
* 13 d 1101 top+bottom+left
|
|
||||||
* 14 e 1110 right+bottom+left
|
|
||||||
* 15 f 1111 top+right+bottom+left
|
|
||||||
* </pre>
|
|
||||||
* ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are:
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* byte hex meaning
|
* byte hex meaning
|
||||||
* 00 0x1a magic
|
* 00 0x1a magic
|
||||||
* 01 0xb1 magic
|
* 01 0xb1 magic
|
||||||
* 02 0x01 version (0x00 -> dev, 0x01 -> stable)
|
* 02 0x01 version (0x00 -> dev, 0x01 -> stable)
|
||||||
* 03..06 width (int)
|
* 03..10 random seed number (long)
|
||||||
* 07..10 height (int)
|
* 11..14 width (int)
|
||||||
* 11..18 random seed number (long)
|
* 15..18 height (int)
|
||||||
* 19.. tiles
|
* 19.. tiles
|
||||||
* </pre>
|
* </pre>
|
||||||
* Extraneous space (poss. last nibble) is ignored.
|
* Extraneous space (poss. last nibble) is ignored.
|
||||||
|
@ -49,12 +28,6 @@ public class SerializerDeserializerV1 {
|
||||||
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
||||||
final byte VERSION_BYTE = 0x01;
|
final byte VERSION_BYTE = 0x01;
|
||||||
|
|
||||||
private final byte TOP_BIT = 0b0000_0001;
|
|
||||||
private final byte RIGHT_BIT = 0b0000_0010;
|
|
||||||
private final byte BOTTOM_BIT = 0b0000_0100;
|
|
||||||
private final byte LEFT_BIT = 0b0000_1000;
|
|
||||||
private final byte SOLUTION_BIT = 0b0001_0000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the {@code maze} into a byte array.
|
* Serializes the {@code maze} into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -93,55 +66,4 @@ public class SerializerDeserializerV1 {
|
||||||
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) {
|
|
||||||
try {
|
|
||||||
final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE);
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
return constructor.newInstance(walls, solution);
|
|
||||||
} catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException |
|
|
||||||
InvocationTargetException e) {
|
|
||||||
throw new RuntimeException("Can not deserialize Tile from maze data.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getBitmaskForTile(@NotNull final Tile tile) {
|
|
||||||
byte bitmask = 0;
|
|
||||||
if (tile.hasWallAt(Direction.TOP)) {
|
|
||||||
bitmask |= TOP_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.RIGHT)) {
|
|
||||||
bitmask |= RIGHT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.BOTTOM)) {
|
|
||||||
bitmask |= BOTTOM_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt((Direction.LEFT))) {
|
|
||||||
bitmask |= LEFT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.isSolution()) {
|
|
||||||
bitmask |= SOLUTION_BIT;
|
|
||||||
}
|
|
||||||
return bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
Tile getTileForBitmask(final byte bitmask) {
|
|
||||||
final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class);
|
|
||||||
if ((bitmask & TOP_BIT) == TOP_BIT) {
|
|
||||||
walls.add(Direction.TOP);
|
|
||||||
}
|
|
||||||
if ((bitmask & RIGHT_BIT) == RIGHT_BIT) {
|
|
||||||
walls.add(Direction.RIGHT);
|
|
||||||
}
|
|
||||||
if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) {
|
|
||||||
walls.add(Direction.BOTTOM);
|
|
||||||
}
|
|
||||||
if ((bitmask & LEFT_BIT) == LEFT_BIT) {
|
|
||||||
walls.add(Direction.LEFT);
|
|
||||||
}
|
|
||||||
final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT;
|
|
||||||
return createTile(walls, solution);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class MazeInputStreamV2 extends AbstractMazeInputStream {
|
public class MazeInputStreamV2 extends AbstractMazeInputStream {
|
||||||
|
@ -58,7 +59,7 @@ public class MazeInputStreamV2 extends AbstractMazeInputStream {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
final byte bitmask = this.readByte();
|
final byte bitmask = this.readByte();
|
||||||
tiles[x][y] = SerializerDeserializerV2.getTileForBitmask(bitmask);
|
tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class MazeOutputStreamV2 extends AbstractMazeOutputStream {
|
public class MazeOutputStreamV2 extends AbstractMazeOutputStream {
|
||||||
|
@ -45,7 +46,7 @@ public class MazeOutputStreamV2 extends AbstractMazeOutputStream {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
// We .get() it, because we want to crash hard if it is not available.
|
// We .get() it, because we want to crash hard if it is not available.
|
||||||
final Tile tile = maze.getTileAt(x, y).get();
|
final Tile tile = maze.getTileAt(x, y).get();
|
||||||
final byte bitmask = SerializerDeserializerV2.getBitmaskForTile(tile);
|
final byte bitmask = CommonTileHandler.getBitmaskForTile(tile);
|
||||||
this.writeByte(bitmask);
|
this.writeByte(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ch.fritteli.maze.generator.serialization.v2;
|
package ch.fritteli.maze.generator.serialization.v2;
|
||||||
|
|
||||||
import ch.fritteli.maze.generator.model.Direction;
|
|
||||||
import ch.fritteli.maze.generator.model.Maze;
|
import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
|
@ -9,29 +8,9 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.EnumSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* Header bytes are:
|
||||||
* decimal hex bin border
|
|
||||||
* 0 0 0000 no border
|
|
||||||
* 1 1 0001 top
|
|
||||||
* 2 2 0010 right
|
|
||||||
* 3 3 0011 top+right
|
|
||||||
* 4 4 0100 bottom
|
|
||||||
* 5 5 0101 top+bottom
|
|
||||||
* 6 6 0110 right+bottom
|
|
||||||
* 7 7 0111 top+right+bottom
|
|
||||||
* 8 8 1000 left
|
|
||||||
* 9 9 1001 top+left
|
|
||||||
* 10 a 1010 right+left
|
|
||||||
* 11 b 1011 top+right+left
|
|
||||||
* 12 c 1100 bottom+left
|
|
||||||
* 13 d 1101 top+bottom+left
|
|
||||||
* 14 e 1110 right+bottom+left
|
|
||||||
* 15 f 1111 top+right+bottom+left
|
|
||||||
* </pre>
|
|
||||||
* ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are:
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* byte hex meaning
|
* byte hex meaning
|
||||||
* 00 0x1a magic
|
* 00 0x1a magic
|
||||||
|
@ -55,12 +34,6 @@ public class SerializerDeserializerV2 {
|
||||||
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
||||||
final byte VERSION_BYTE = 0x02;
|
final byte VERSION_BYTE = 0x02;
|
||||||
|
|
||||||
private final byte TOP_BIT = 0b0000_0001;
|
|
||||||
private final byte RIGHT_BIT = 0b0000_0010;
|
|
||||||
private final byte BOTTOM_BIT = 0b0000_0100;
|
|
||||||
private final byte LEFT_BIT = 0b0000_1000;
|
|
||||||
private final byte SOLUTION_BIT = 0b0001_0000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the {@code maze} into a byte array.
|
* Serializes the {@code maze} into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -99,55 +72,4 @@ public class SerializerDeserializerV2 {
|
||||||
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) {
|
|
||||||
try {
|
|
||||||
final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE);
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
return constructor.newInstance(walls, solution);
|
|
||||||
} catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException |
|
|
||||||
InvocationTargetException e) {
|
|
||||||
throw new RuntimeException("Can not deserialize Tile from maze data.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getBitmaskForTile(@NotNull final Tile tile) {
|
|
||||||
byte bitmask = 0;
|
|
||||||
if (tile.hasWallAt(Direction.TOP)) {
|
|
||||||
bitmask |= TOP_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.RIGHT)) {
|
|
||||||
bitmask |= RIGHT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.BOTTOM)) {
|
|
||||||
bitmask |= BOTTOM_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt((Direction.LEFT))) {
|
|
||||||
bitmask |= LEFT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.isSolution()) {
|
|
||||||
bitmask |= SOLUTION_BIT;
|
|
||||||
}
|
|
||||||
return bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
Tile getTileForBitmask(final byte bitmask) {
|
|
||||||
final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class);
|
|
||||||
if ((bitmask & TOP_BIT) == TOP_BIT) {
|
|
||||||
walls.add(Direction.TOP);
|
|
||||||
}
|
|
||||||
if ((bitmask & RIGHT_BIT) == RIGHT_BIT) {
|
|
||||||
walls.add(Direction.RIGHT);
|
|
||||||
}
|
|
||||||
if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) {
|
|
||||||
walls.add(Direction.BOTTOM);
|
|
||||||
}
|
|
||||||
if ((bitmask & LEFT_BIT) == LEFT_BIT) {
|
|
||||||
walls.add(Direction.LEFT);
|
|
||||||
}
|
|
||||||
final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT;
|
|
||||||
return createTile(walls, solution);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -66,7 +67,7 @@ public class MazeInputStreamV3 extends AbstractMazeInputStream {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
final byte bitmask = this.readByte();
|
final byte bitmask = this.readByte();
|
||||||
tiles[x][y] = SerializerDeserializerV3.getTileForBitmask(bitmask);
|
tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream;
|
||||||
|
import ch.fritteli.maze.generator.serialization.CommonTileHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -52,7 +53,7 @@ public class MazeOutputStreamV3 extends AbstractMazeOutputStream {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
// We .get() it, because we want to crash hard if it is not available.
|
// We .get() it, because we want to crash hard if it is not available.
|
||||||
final Tile tile = maze.getTileAt(x, y).get();
|
final Tile tile = maze.getTileAt(x, y).get();
|
||||||
final byte bitmask = SerializerDeserializerV3.getBitmaskForTile(tile);
|
final byte bitmask = CommonTileHandler.getBitmaskForTile(tile);
|
||||||
this.writeByte(bitmask);
|
this.writeByte(bitmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ch.fritteli.maze.generator.serialization.v3;
|
package ch.fritteli.maze.generator.serialization.v3;
|
||||||
|
|
||||||
import ch.fritteli.maze.generator.model.Direction;
|
|
||||||
import ch.fritteli.maze.generator.model.Maze;
|
import ch.fritteli.maze.generator.model.Maze;
|
||||||
import ch.fritteli.maze.generator.model.Position;
|
import ch.fritteli.maze.generator.model.Position;
|
||||||
import ch.fritteli.maze.generator.model.Tile;
|
import ch.fritteli.maze.generator.model.Tile;
|
||||||
|
@ -10,29 +9,9 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.EnumSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* Header bytes are:
|
||||||
* decimal hex bin border
|
|
||||||
* 0 0 0000 no border
|
|
||||||
* 1 1 0001 top
|
|
||||||
* 2 2 0010 right
|
|
||||||
* 3 3 0011 top+right
|
|
||||||
* 4 4 0100 bottom
|
|
||||||
* 5 5 0101 top+bottom
|
|
||||||
* 6 6 0110 right+bottom
|
|
||||||
* 7 7 0111 top+right+bottom
|
|
||||||
* 8 8 1000 left
|
|
||||||
* 9 9 1001 top+left
|
|
||||||
* 10 a 1010 right+left
|
|
||||||
* 11 b 1011 top+right+left
|
|
||||||
* 12 c 1100 bottom+left
|
|
||||||
* 13 d 1101 top+bottom+left
|
|
||||||
* 14 e 1110 right+bottom+left
|
|
||||||
* 15 f 1111 top+right+bottom+left
|
|
||||||
* </pre>
|
|
||||||
* ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are:
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* byte hex meaning
|
* byte hex meaning
|
||||||
* 00 0x1a magic
|
* 00 0x1a magic
|
||||||
|
@ -58,12 +37,6 @@ public class SerializerDeserializerV3 {
|
||||||
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
final byte MAGIC_BYTE_2 = (byte) 0xb1;
|
||||||
final byte VERSION_BYTE = 0x03;
|
final byte VERSION_BYTE = 0x03;
|
||||||
|
|
||||||
private final byte TOP_BIT = 0b0000_0001;
|
|
||||||
private final byte RIGHT_BIT = 0b0000_0010;
|
|
||||||
private final byte BOTTOM_BIT = 0b0000_0100;
|
|
||||||
private final byte LEFT_BIT = 0b0000_1000;
|
|
||||||
private final byte SOLUTION_BIT = 0b0001_0000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the {@code maze} into a byte array.
|
* Serializes the {@code maze} into a byte array.
|
||||||
*
|
*
|
||||||
|
@ -116,55 +89,4 @@ public class SerializerDeserializerV3 {
|
||||||
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
throw new RuntimeException("Can not deserialize Maze from maze data.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) {
|
|
||||||
try {
|
|
||||||
final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE);
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
return constructor.newInstance(walls, solution);
|
|
||||||
} catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException |
|
|
||||||
InvocationTargetException e) {
|
|
||||||
throw new RuntimeException("Can not deserialize Tile from maze data.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getBitmaskForTile(@NotNull final Tile tile) {
|
|
||||||
byte bitmask = 0;
|
|
||||||
if (tile.hasWallAt(Direction.TOP)) {
|
|
||||||
bitmask |= TOP_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.RIGHT)) {
|
|
||||||
bitmask |= RIGHT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt(Direction.BOTTOM)) {
|
|
||||||
bitmask |= BOTTOM_BIT;
|
|
||||||
}
|
|
||||||
if (tile.hasWallAt((Direction.LEFT))) {
|
|
||||||
bitmask |= LEFT_BIT;
|
|
||||||
}
|
|
||||||
if (tile.isSolution()) {
|
|
||||||
bitmask |= SOLUTION_BIT;
|
|
||||||
}
|
|
||||||
return bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
Tile getTileForBitmask(final byte bitmask) {
|
|
||||||
final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class);
|
|
||||||
if ((bitmask & TOP_BIT) == TOP_BIT) {
|
|
||||||
walls.add(Direction.TOP);
|
|
||||||
}
|
|
||||||
if ((bitmask & RIGHT_BIT) == RIGHT_BIT) {
|
|
||||||
walls.add(Direction.RIGHT);
|
|
||||||
}
|
|
||||||
if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) {
|
|
||||||
walls.add(Direction.BOTTOM);
|
|
||||||
}
|
|
||||||
if ((bitmask & LEFT_BIT) == LEFT_BIT) {
|
|
||||||
walls.add(Direction.LEFT);
|
|
||||||
}
|
|
||||||
final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT;
|
|
||||||
return createTile(walls, solution);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue