archeserde

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 24, 2024 License: MIT Imports: 7 Imported by: 1

README

Arche Serde

Test status Coverage Status Go Report Card Go Reference GitHub MIT license

Arche Serde provides JSON serialization and deserialization for the Arche Entity Component System (ECS).

Features

  • Serialize/deserialize an entire Arche world in one line.
  • Proper serialization of entity relations, as well as of entities stored in components.
  • Skip arbitrary components and resources when serializing or deserializing.

Installation

go get github.com/mlange-42/arche-serde

Usage

See the API docs for more details and examples.
Go Reference

Serialize a world:

jsonData, err := archeserde.Serialize(&world)
if err != nil {
    // handle the error
}

Deserialize a world:

err = archeserde.Deserialize(jsonData, &world)
if err != nil {
    // handle the error
}

License

This project is distributed under the MIT licence.

Documentation

Overview

Package archeserde provides JSON serialization and deserialization for the Arche ECS.

Example
package main

import (
	"fmt"
	"math/rand"

	archeserde "github.com/mlange-42/arche-serde"
	"github.com/mlange-42/arche/ecs"
	"github.com/mlange-42/arche/generic"
)

const (
	width  = 40
	height = 12
)

type Coords struct {
	X int
	Y int
}

func main() {
	rng := rand.New(rand.NewSource(42))

	// Create a world.
	world := ecs.NewWorld()

	// Populate the world with entities, components and resources.
	builder := generic.NewMap1[Coords](&world)
	query := builder.NewBatchQ(60)
	for query.Next() {
		coord := query.Get()
		coord.X = rng.Intn(width)
		coord.Y = rng.Intn(height)
	}

	// Print the original world
	fmt.Println("====== Original world ========")
	printWorld(&world)

	// Serialize the world.
	jsonData, err := archeserde.Serialize(&world)
	if err != nil {
		fmt.Printf("could not serialize: %s\n", err)
		return
	}

	// Print the resulting JSON.
	//fmt.Println(string(jsonData))

	// Create a new, empty world.
	newWorld := ecs.NewWorld()

	// Register required components and resources
	_ = ecs.ComponentID[Coords](&newWorld)

	// Deserialize into the new world.
	err = archeserde.Deserialize(jsonData, &newWorld)
	if err != nil {
		fmt.Printf("could not deserialize: %s\n", err)
		return
	}

	// Print the deserialized world
	fmt.Println("====== Deserialized world ========")
	printWorld(&newWorld)
}

func printWorld(world *ecs.World) {
	grid := make([][]rune, height)
	for i := range grid {
		grid[i] = make([]rune, width)
		for j := range grid[i] {
			grid[i][j] = '-'
		}
	}

	filter := generic.NewFilter1[Coords]()
	query := filter.Query(world)

	for query.Next() {
		coords := query.Get()
		grid[coords.Y][coords.X] = 'O'
	}

	for i := 0; i < len(grid); i++ {
		fmt.Println(string(grid[i]))
	}
}
Output:

====== Original world ========
--------------------------------O-O---O-
-----------------------O----------------
-O-------------O------OO--------------O-
----O------------------------OOO--------
O--------------OO-O---------------------
------------O-----------O---------------
--O-------------O-------O---O------O----
O-O-----O----OOO-O--O--------------OO---
-----------O---OO----O--O------------O--
------------O-----O---------------------
---O---------------O------O--O----------
------O-OO--O---------OO-OOO-----------O
====== Deserialized world ========
--------------------------------O-O---O-
-----------------------O----------------
-O-------------O------OO--------------O-
----O------------------------OOO--------
O--------------OO-O---------------------
------------O-----------O---------------
--O-------------O-------O---O------O----
O-O-----O----OOO-O--O--------------OO---
-----------O---OO----O--O------------O--
------------O-----O---------------------
---O---------------O------O--O----------
------O-OO--O---------OO-OOO-----------O
Example (Options)
world := ecs.NewWorld()
builder := generic.NewMap2[Position, Velocity](&world)
builder.NewBatch(10)

// Serialize the world, skipping Velocity.
jsonData, err := archeserde.Serialize(
	&world,
	archeserde.Opts.SkipComponents(generic.T[Velocity]()),
)
if err != nil {
	fmt.Printf("could not serialize: %s\n", err)
	return
}

newWorld := ecs.NewWorld()

// Register required components and resources
_ = ecs.ComponentID[Position](&newWorld)

err = archeserde.Deserialize(jsonData, &newWorld)
if err != nil {
	fmt.Printf("could not deserialize: %s\n", err)
	return
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var Opts = Options{}

Opts is a helper to create Option instances.

Functions

func Deserialize

func Deserialize(jsonData []byte, world *ecs.World, options ...Option) error

Deserialize an Arche ecs.World from JSON.

The world must be prepared the following way:

  • The world must not contain any alive or dead entities (i.e. a new or ecs.World.Reset world)
  • All required component types must be registered using ecs.ComponentID
  • All required resources must be added as dummies using ecs.AddResource

The options can be used to skip some or all components, entities entirely, and/or some or all resources. It only some components or resources are skipped, they still need to be registered to the world.

Query iteration order

After deserialization, it is not guaranteed that entity iteration order in queries is the same as before. More precisely, it should at first be the same as before, but will likely deviate over time from what would happen when continuing the original, serialized run. Multiple worlds deserialized from the same source should, however, behave exactly the same.

func Serialize

func Serialize(world *ecs.World, options ...Option) ([]byte, error)

Serialize an Arche ecs.World to JSON.

Serializes the following:

  • Entities and the entity pool
  • All components of all entities
  • All resources

All components and resources must be "JSON-able" with encoding/json.

The options can be used to skip some or all components, entities entirely, and/or some or all resources.

Types

type Option added in v0.2.0

type Option func(o *serdeOptions)

Option is an option. Modifies o. Create them using Opts.

type Options added in v0.2.0

type Options struct{}

Options is a helper to create Option instances. Use it via the instance Opts.

func (Options) SkipAllComponents added in v0.2.0

func (o Options) SkipAllComponents() Option

SkipAllComponents skips serialization or de-serialization of all components.

func (Options) SkipAllResources added in v0.2.0

func (o Options) SkipAllResources() Option

SkipAllResources skips serialization or de-serialization of all resources.

func (Options) SkipComponents added in v0.2.0

func (o Options) SkipComponents(comps ...generic.Comp) Option

SkipAllResources skips serialization or de-serialization of certain components.

When deserializing, the skipped components must still be registered.

func (Options) SkipEntities added in v0.2.0

func (o Options) SkipEntities() Option

SkipEntities skips serialization or de-serialization of all entities and components.

func (Options) SkipResources added in v0.2.0

func (o Options) SkipResources(comps ...generic.Comp) Option

SkipAllResources skips serialization or de-serialization of certain resources.

When deserializing, the skipped resources must still be registered.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL