Serializando Datos Personalizados

Sin un método para serializar y deserializar, sus datos no se mantendrán durante los reinicios. Sponge tiene algunas formas diferentes de serializar/deserializar los datos según el tipo de datos:

  • DataSerializables implement an interface to perform serialization, and use DataBuilder for deserialization and creation

  • DataManipulators also implement DataSerializable, but instead use a DataManipulatorBuilder for deserialization and creation

  • Los objetos que no implementan o no pueden implementar `` DataSerializable`` usan :javadoc: DataTranslator para la serialización y la deserialización

Esto significa que prácticamente cualquier objeto en Java se puede guardar en el disco si ha sido registrado!

Lectura de DataViews

Whenever you’re reading a serialized object, it’s tempting to read all the individual values yourself in order to manually create all the required objects (and their parameters) for your data. However, depending on the data saved in the container there are a few ways that are far more convenient:

  • Los tipos comunes de Java como int, String, double, List y Map se pueden recuperar utilizando los métodos integrados ``getInt(DataQuery) ``, ``getString(DataQuery) ``, etc. Las listas de estos tipos también se pueden recuperar de manera similar, por ejemplo ``getStringList(DataQuery) ``.

  • Los objetos DataSerializable pueden ser recuperados usando getSerializable (DataQuery, Class) `` o ``getSerializableList (DataQuery, Class) ``. Junto con la ruta, también debe especificar la ``Clase del tipo serializable, como Home.class.

  • Los objetos con un DataTranslator registrado se pueden recuperar utilizando getObject(DataQuery, Class) o ` getObjectList(DataQuery, Class) . Se puede encontrar una lista completa de las clases admitidas de manera predeterminada en :javadoc: `DataTranslators.

En todos los casos, debe especificar una ruta usando a :javadoc: DataQuery. Si sus datos tienen una Key correspondiente, esto es tan fácil como llamar a ``key.getQuery () ``. De lo contrario, la forma más fácil de hacerlo es con ``DataQuery.of («name») ``.

Truco

DataQueries se puede utilizar para hacer referencia a múltiples nodos de datos en un árbol al utilizar, por ejemplo, ``DataQuery.of(«my», «custom», «data») ``.

DataBuilders

Para hacer un objeto serializable, primero asegúrese de que implemente :javadoc: DataSerializable. Usted debe implementar solo dos métodos:

  • ``getContentVersion () `` - esto definió la versión actual de sus datos.

  • toContainer () `` - esto es lo que se le dará a su compilador cuando intente deserializar y objetar. Puede almacenar lo que desee en el ``DataContainer devuelto, siempre que también se pueda serializar utilizando uno de los métodos anteriores. Simplemente use el método ``set (DataQuery, Object) `` para guardar sus datos en la ruta dada.

Truco

Se recomienda que también guarde la versión de sus datos en el contenedor utilizando Queries.CONTENT_VERSION como consulta. Esto permitirá actualizaciones del control de versiones con :ref: content-updaters.

Ejemplo de Código: Implementando toContainer

import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.Queries;
import org.spongepowered.api.data.MemoryDataContainer;

private String name = "Spongie";

@Override
public DataContainer toContainer() {
    return DataContainer.createNew()
            .set(DataQuery.of("Name"), this.name)
            .set(Queries.CONTENT_VERSION, getContentVersion());
}

La siguiente parte es implementar un :javadoc: DataBuilder. Se recomienda extender :javadoc: AbstractDataBuilder ya que tratará de actualizar sus datos si la versión es menor a la versión actual. Solo hay un método que usted necesita implementar: `` build (DataView) , o `` buildContent(DataView) `` si usted está usando ``AbstractDataBuilder.

You’ll want to check that all the queries you want to retrieve are present using DataView.contains(Key...). If not, the data is likely incomplete and you should return Optional.empty().

Si todo parece estar allí, utilice los métodos getX para construir los valores y devolver un objeto recién creado como un Optional.

DataContentUpdaters

¿Qué sucede si cambia el diseño de los datos en el lanzamiento de una nueva versión? :javadoc: DataContentUpdater s resuelve ese problema. Si el objeto serializado es menor que la versión actual, un AbstractDataBuilder intentará actualizar los datos antes de pasarlos al compilador.

Cada actualizador tiene una versión de entrada y una versión de salida. Debería tomar los datos anteriores y cambiar lo que sea necesario para actualizarlo a un diseño más nuevo. Si es imposible realizar la conversión debido a la falta de datos, es posible proveer un valor predeterminado que es interpretado en otro lugar - como por ejemplo, el compilador principal o el objeto en sí.

Finalmente, debe asegurarse de que todos los DataContentUpdater s se registren con ``DataManager#registerContentUpdater() `` haciendo referencia a la clase de datos principal, esto les permitirá a ellos ser descubiertos por el compilador.

Ejemplo de código: Implementando un DataContentUpdater

import org.spongepowered.api.data.persistence.DataContentUpdater
import org.spongepowered.api.text.Text

public class NameUpdater implements DataContentUpdater {

    @Override
    public int getInputVersion() {
        return 1;
    }

    @Override
    public int getOutputVersion() {
        return 2;
    }

    @Override
    public DataView update(DataView content) {
        String name = content.getString(DataQuery.of("Name")).get();

        // For example, version 2 uses a text for the name
        return content.set(DataQuery.of("Name"), Text.of(name));
    }
}

DataManipulatorBuilders

Un DataManipualatorBuilder es muy similar a DataBuilder, sin embargo, agrega algunos métodos directamente relacionados con los manipuladores de deserialización:

  • create () debería devolver un nuevo manipulador con valores predeterminados

  • createFrom (DataHolder) es similar al método de compilación, pero en su lugar los valores deben tomarse de DataHolder. Si no hay datos para tomar del titular, solo devuelva la salida de create (). Si los datos son incompatibles con el DataHolder, en su lugar debe devolver Optional.empty ().

Al igual que DataBuilder, debe leer y devolver su manipulador en el método `` build`` aplicable.

DataManipulatorBuilder s puede también usar DataContentUpdaters, siempre que implemente` AbstractDataBuilder`.

El registro de un DataManipulatorBuilder también es similar a DataBuilder pero utiliza el método register(). Usted debe hacer una referencia tanto a sus clases mutables como inmutables en el método, además de una instancia de su compilador.

Nota

Usted Debe hacer referencia a las clases de implementación si ha dividido la API de la implementación.

DataTranslators

A menudo, los objetos que desea serializar no son objetos que implementan DataSerializable, como `` Vector3d`` o `` Date``. Para permitir a estos objetos ustedimplementa un DataTranslator que maneje ambos, la serialización y deserialización del objeto.

La implementación de translate es idéntica a toContainer() y build(DataView) `` para un ``DataSerializable como se muestra arriba, excepto que se lanza un InvalidDataException si faltan datos en lugar de devolver un Optional.

As with other data, ensure that you register the translator during GameRegistryEvent.Register<DataTranslator<?>>.