Manipulating snapshots
The SDK provides two classes in to manipulate snapshots stored in files:
Improbable.Worker.SnapshotInputStream
to read snapshot files from disk, one entity at a timeImprobable.Worker.SnapshotOutputStream
to write snapshot files to disk, one entity at a time
This lets you write tools to perform offline transformations of the simulation state, or to programmatically create the starting point of a simulation.
Snapshot manipulation does not require a
Connection
, making it possible to
develop standalone, offline snapshot manipulation tools. However, we recommend using the build infrastructure
provided by SpatialOS for workers to build your standalone tools.
These stream classes are the recommended methods of manipulating snapshots as they do not require the entire snapshot to be stored in memory when reading or writing a snapshot.
SnapshotInputStream
SnapshotInputStream
has a constructor and three public methods:
// Constructs a SnapshotInputStream to read the file at the given string path.
public SnapshotInputStream(string path)
// Releases the resources of the SnapshotInputStream.
public void Dispose()
// Reads the next EntityId entityId, Entity entity pair from the snapshot.
// Returns an optional string error message if an error occurs during reading.
public Option<string> ReadEntity(out EntityId entityId, out Entity entity)
// Returns true if the SnapshotInputStream has not reached the end of the snapshot.
public bool HasNext();
SnapshotOutputStream
SnapshotOutputStream
has a constructor and two public methods:
// Construct a SnapshotOutputStream to write a snapshot to a file at the string path.
public SnapshotOutputStream(string path)
// Writes the end of snapshot header and releases the resources of the SnapshotOutputStream.
public void Dispose()
// Writes the (EntityId entityId, Entity entity) pair to the snapshot.
// Returns an Optional string error message if an error occurs during writing.
public Option<string> WriteEntity(EntityId entityId, Entity entity)
Example
Here is an example of loading a snapshot, performing some manipulation on it, and saving it back. It uses the types and components defined in the example from Generated code.
public static void AddLowHealthEffectToEntities(string snapshotFilename, string newSnapshotFilename)
{
// Open a SnapshotInputStream to read from the snapshot file saved at snapshotFilename.
SnapshotInputStream inputStream = new SnapshotInputStream(snapshotFilename);
// Open a SnapshotOutputStream to write to a snapshot file at newSnapshotFilename.
SnapshotOutputStream outputStream = new SnapshotOutputStream(newSnapshotFilename);
Improbable.EntityId entityId;
Entity entity;
// Iterate over every entity in the snapshot file.
while (inputStream.HasNext())
{
// Read the next (entityId, entity) pair from the snapshot file.
var errorOpt = inputStream.ReadEntity(out entityId, out entity);
if (errorOpt.HasValue)
{
throw new System.SystemException("Error loading snapshot: " + errorOpt.Value);
}
if (entity.Get<Creature>().HasValue)
{
var status = entity.Get<Creature>().Value.Get();
// Add the "LowHealth" effect to all entities that have a Creature component
// and less than 10 health points.
if (status.Value.health < 10)
{
status.Value.effects.Add(new StatusEffect("LowHealth", 100));
}
}
// Write the (entityId, entity) pair to the snapshot file.
errorOpt = outputStream.WriteEntity(entityId, entity);
if (errorOpt.HasValue)
{
throw new System.SystemException("Error saving snapshot: " + errorOpt.Value);
}
}
// Dispose of the inputStream to release the stream's resources.
inputStream.Dispose();
// Dispose of the outputStream to write the end of the Snapshot and release the stream's
// resources.
outputStream.Dispose();
}