flauwekeul / honeycomb

Create hex grids easily, in node or the browser.
https://abbekeultjes.nl/honeycomb
MIT License
630 stars 57 forks source link

Deserializing Grid is not returning CustomHex #99

Closed arvalaan closed 1 year ago

arvalaan commented 1 year ago

Hey there, I'm trying to deserialize a previously generated grid however am unable to do so as my CustomHex class gets lost.

Here you can find my steps to reproduce:

My custom class definition

export class CustomHex extends defineHex({ dimensions: 4, origin: 'topLeft' }) {
    static create(
        coordinates: HexCoordinates,
        elevation: number,
        moisture: number,
        id: string
    ) {
        const hex = new CustomHex(coordinates)
        hex.elevation = elevation
        hex.moisture = moisture
        hex.id = id
        return hex
    }

    id!: string
    moisture!: number
    elevation!: number
}

My function to convert a square noise grid into a hexagon grid:

export default function convertGrid(mapSize?: number) {
    const generatedMap = generateMap(mapSize)

    const hexes = [...generatedMap].map((hex) =>
        CustomHex.create(
            squareToHex(hex.coordinates[0], hex.coordinates[1]),
            hex.elevation,
            hex.moisture,
            hex.id
        )
    )

    const grid = new Grid(CustomHex, hexes)

    // Return the grid in JSON format in the console
    console.log(grid.toJSON())

    return grid.toJSON()
}

I then try to deserialize in another function however the output is not as expected.

Here's a test function I put together to try and see what I was doing wrong:

const hexes = [
        [0, 0],
        [1, 0],
        [0, 1],
    ].map((coordinates) => CustomHex.create(coordinates, 0, 0, 'id'))
    const grid1 = new Grid(CustomHex, hexes)
    const serializedGrid = JSON.stringify(grid1)

    const deserializedGrid = JSON.parse(serializedGrid)

    // this returns a grid with the same Hex class and hexes as grid1
    const grid2 = Grid.fromJSON(deserializedGrid)

    grid2.forEach(console.log)

Am I missing something?

flauwekeul commented 1 year ago

Hi. Thanks for your question. I can reproduce your problem and the cause is in Grid's fromJSON() method. It looks like this:

  static fromJSON({ hexSettings, coordinates }: GridAsJSON): Grid<Hex> {
    const HexClass = defineHex(hexSettings)
    return new Grid(
      HexClass,
      coordinates.map((_coordinates) => new HexClass(_coordinates)),
    )
  }

As you can see, it creates hexes by simply passing the coordinates to the constructor function, ignoring any custom properties you may have. I'll add an optional hexFactory argument to fromJSON() so that you can do something like this:

const hexFactory = ({ q, r, elevation, moisture, id }: CustomHex) => CustomHex.create({ q, r }, elevation, moisture, id)
const grid2 = Grid.fromJSON(deserializedGrid, hexFactory)
github-actions[bot] commented 1 year ago

:tada: This issue has been resolved in version 4.1.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: