diff --git a/src/main/java/ch/fritteli/maze/generator/serialization/CommonTileHandler.java b/src/main/java/ch/fritteli/maze/generator/serialization/CommonTileHandler.java
new file mode 100644
index 0000000..b4051c8
--- /dev/null
+++ b/src/main/java/ch/fritteli/maze/generator/serialization/CommonTileHandler.java
@@ -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}.
+ * A tile is stored in one byte:
+ *
+ * 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 + *+ */ +@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
- * 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 - *- * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: + * Header bytes are: *
* byte hex meaning * 00 0x1a magic * 01 0xb1 magic * 02 0x01 version (0x00 -> dev, 0x01 -> stable) - * 03..06 width (int) - * 07..10 height (int) - * 11..18 random seed number (long) + * 03..10 random seed number (long) + * 11..14 width (int) + * 15..18 height (int) * 19.. tiles ** Extraneous space (poss. last nibble) is ignored. @@ -49,12 +28,6 @@ public class SerializerDeserializerV1 { final byte MAGIC_BYTE_2 = (byte) 0xb1; 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. * @@ -93,55 +66,4 @@ public class SerializerDeserializerV1 { throw new RuntimeException("Can not deserialize Maze from maze data.", e); } } - - @NotNull - private Tile createTile(@NotNull final EnumSet
- * 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 - *- * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: + * Header bytes are: *
* byte hex meaning * 00 0x1a magic @@ -55,12 +34,6 @@ public class SerializerDeserializerV2 { final byte MAGIC_BYTE_2 = (byte) 0xb1; 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. * @@ -99,55 +72,4 @@ public class SerializerDeserializerV2 { throw new RuntimeException("Can not deserialize Maze from maze data.", e); } } - - @NotNull - private Tile createTile(@NotNull final EnumSetwalls, boolean solution) { - try { - final Constructor 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 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); - } } diff --git a/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeInputStreamV3.java b/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeInputStreamV3.java index 1814008..af809b9 100644 --- a/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeInputStreamV3.java +++ b/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeInputStreamV3.java @@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Position; import ch.fritteli.maze.generator.model.Tile; import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; +import ch.fritteli.maze.generator.serialization.CommonTileHandler; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -66,7 +67,7 @@ public class MazeInputStreamV3 extends AbstractMazeInputStream { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { final byte bitmask = this.readByte(); - tiles[x][y] = SerializerDeserializerV3.getTileForBitmask(bitmask); + tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask); } } diff --git a/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeOutputStreamV3.java b/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeOutputStreamV3.java index 52b154a..891f0bb 100644 --- a/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeOutputStreamV3.java +++ b/src/main/java/ch/fritteli/maze/generator/serialization/v3/MazeOutputStreamV3.java @@ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Position; import ch.fritteli.maze.generator.model.Tile; import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; +import ch.fritteli.maze.generator.serialization.CommonTileHandler; import org.jetbrains.annotations.NotNull; import java.nio.charset.StandardCharsets; @@ -52,7 +53,7 @@ public class MazeOutputStreamV3 extends AbstractMazeOutputStream { for (int x = 0; x < width; x++) { // We .get() it, because we want to crash hard if it is not available. final Tile tile = maze.getTileAt(x, y).get(); - final byte bitmask = SerializerDeserializerV3.getBitmaskForTile(tile); + final byte bitmask = CommonTileHandler.getBitmaskForTile(tile); this.writeByte(bitmask); } } diff --git a/src/main/java/ch/fritteli/maze/generator/serialization/v3/SerializerDeserializerV3.java b/src/main/java/ch/fritteli/maze/generator/serialization/v3/SerializerDeserializerV3.java index 839e588..ac9375d 100644 --- a/src/main/java/ch/fritteli/maze/generator/serialization/v3/SerializerDeserializerV3.java +++ b/src/main/java/ch/fritteli/maze/generator/serialization/v3/SerializerDeserializerV3.java @@ -1,6 +1,5 @@ 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.Position; import ch.fritteli.maze.generator.model.Tile; @@ -10,29 +9,9 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.EnumSet; /** - * - * 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 - *- * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: + * Header bytes are: ** byte hex meaning * 00 0x1a magic @@ -58,12 +37,6 @@ public class SerializerDeserializerV3 { final byte MAGIC_BYTE_2 = (byte) 0xb1; 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. * @@ -116,55 +89,4 @@ public class SerializerDeserializerV3 { throw new RuntimeException("Can not deserialize Maze from maze data.", e); } } - - @NotNull - private Tile createTile(@NotNull final EnumSetwalls, boolean solution) { - try { - final Constructor 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 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); - } }