All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.fritteli.maze.generator.serialization.v3.MazeOutputStreamV3 Maven / Gradle / Ivy

package ch.fritteli.maze.generator.serialization.v3;

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 ch.fritteli.maze.generator.serialization.MazeConstants;
import org.jetbrains.annotations.NotNull;

import java.nio.charset.StandardCharsets;

public class MazeOutputStreamV3 extends AbstractMazeOutputStream {

    @Override
    public void writeHeader() {
        // 00 0x1a magic
        // 01 0xb1 magic
        // 02 0x03 version
        this.writeByte(MazeConstants.MAGIC_BYTE_1);
        this.writeByte(MazeConstants.MAGIC_BYTE_2);
        this.writeByte(SerializerDeserializerV3.VERSION_BYTE);
    }

    @Override
    public void writeMazeData(@NotNull final Maze maze) {
        // 03..06   width (int)
        // 07..10   height (int)
        // 11..14   start-x (int)
        // 15..18   start-y (int)
        // 19..22   end-x (int)
        // 23..26   end-y (int)
        // 27..34   random seed number (long)
        // 35       length of the algorithm's name (unsigned byte)
        // 36..+len name (bytes of String)
        // +len+1.. tiles
        final long randomSeed = maze.getRandomSeed();
        final AlgorithmWrapper algorithm = this.getAlgorithmWrapper(maze.getAlgorithm());
        final int width = maze.getWidth();
        final int height = maze.getHeight();
        final Position start = maze.getStart();
        final Position end = maze.getEnd();
        this.writeInt(width);
        this.writeInt(height);
        this.writeInt(start.x());
        this.writeInt(start.y());
        this.writeInt(end.x());
        this.writeInt(end.y());
        this.writeLong(randomSeed);
        this.writeByte(algorithm.length());
        this.writeBytes(algorithm.name());

        for (int y = 0; y < height; y++) {
            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 = CommonTileHandler.getBitmaskForTile(tile);
                this.writeByte(bitmask);
            }
        }
    }

    @NotNull
    private AlgorithmWrapper getAlgorithmWrapper(@NotNull final String algorithm) {
        final byte[] bytes = algorithm.getBytes(StandardCharsets.UTF_8);
        if (bytes.length < 256) {
            // Phew, that's the easy case!
            return new AlgorithmWrapper(bytes, (byte) bytes.length);
        }

        // Let's use a very primitive, brute-force approach
        int strLen = Math.min(255, algorithm.length());
        int len;
        byte[] name;
        do {
            name = algorithm.substring(0, strLen).getBytes(StandardCharsets.UTF_8);
            len = name.length;
            strLen--;
        } while (len > 255);

        return new AlgorithmWrapper(name, (byte) len);
    }

    private record AlgorithmWrapper(@NotNull byte[] name, byte length) {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy