com.artemis.io.SaveFileFormat Maven / Gradle / Ivy
Show all versions of artemis-odb-serializer Show documentation
package com.artemis.io;
import com.artemis.Component;
import com.artemis.Entity;
import com.artemis.EntitySubscription;
import com.artemis.annotations.Transient;
import com.artemis.utils.IntBag;
import com.artemis.utils.reflect.ClassReflection;
import java.util.*;
/**
*
* Represents a set of Entities ready to be serialized, or a set of Entities that was just
* deserialized (and therefore ready to use in your game). This class can be extended if additional
* data requires persisting. All instance fields in this class - or its children - are persisted.
*
*
* The default de/serializer backend provided is
* {@code JsonArtemisSerializer}. A kryo backend is planned for a later release.
* A backend knows how to serialize entities and metadata, but little else.
* If extending this class, custom per-type serializers can be defined - these
* serializers are convenient to have, but normal POJO classes with some
* custom logic works too.
*
* The typical custom serializer works on type, e.g. a GameStateManager
* contains additional data not available to components directly. A serializer would
* be registered to only interact with that class; during loading and saving, the
* serializer interacts directly with the manager and reads/writes the data as needed.
*
* @see EntityReference
*/
public class SaveFileFormat {
// all non-transient fields are automatically serialized
public Metadata metadata;
public ComponentIdentifiers componentIdentifiers;
public IntBag entities;
public ArchetypeMapper archetypes;
transient SerializationKeyTracker tracker = new SerializationKeyTracker();
public SaveFileFormat(IntBag entities) {
this.entities = (entities != null) ? entities : new IntBag();
componentIdentifiers = new ComponentIdentifiers();
metadata = new Metadata();
metadata.version = Metadata.LATEST;
}
public SaveFileFormat(EntitySubscription es) {
this(es.getEntities());
}
public SaveFileFormat() {
this((IntBag)null);
}
public final Entity get(String key) {
return tracker.get(key);
}
public final boolean has(String key) {
return tracker.get(key) != null;
}
public final Set keys() {
return tracker.keys();
}
public static class Metadata {
public static final int VERSION_1 = 1;
public static final int LATEST = VERSION_1;
public int version;
}
public static class ComponentIdentifiers {
public Map, String> typeToName =
new IdentityHashMap, String>();
private Map> nameToType =
new HashMap>();
public Map, Integer> typeToId =
new HashMap, Integer>();
public Map> idToType =
new HashMap>();
transient Set> transientComponents =
new HashSet>();
void build() {
if (typeToName.size() > 0)
buildFromNames();
else
buildFromIndices();
}
public Class extends Component> getType(String name) {
Class extends Component> type = nameToType.get(name);
if (type == null)
throw new SerializationException("No component type with name: " + name);
return type;
}
public Collection> getTypes() {
return nameToType.values();
}
private void buildFromNames() {
Iterator, String>> it = typeToName.entrySet().iterator();
while (it.hasNext()) {
Map.Entry, String> entry = it.next();
Class extends Component> c = entry.getKey();
if (ClassReflection.getDeclaredAnnotation(c, Transient.class) == null) {
nameToType.put(entry.getValue(), c);
if (typeToId.get(c) == null) {
typeToId.put(c, nameToType.size());
idToType.put(nameToType.size(), c);
}
} else {
transientComponents.add(c);
it.remove();
}
}
}
private void buildFromIndices() {
Iterator>> it = idToType.entrySet().iterator();
while (it.hasNext()) {
Map.Entry> entry = it.next();
Class extends Component> c = entry.getValue();
if (ClassReflection.getDeclaredAnnotation(c, Transient.class) == null) {
typeToId.put(c, nameToType.size());
} else {
transientComponents.add(c);
it.remove();
}
}
}
boolean isTransient(Class extends Component> c) {
return transientComponents.contains(c);
}
}
}