Egyéni DataManipulators

A központi része az egyéni adatok DataManipulator. Hajtják végre, először el kell dönteni, ha azt akarom, hogy hozzon létre egy külön API, az egyéni adatok. Általában az a legjobb, ha külön az API-a végrehajtás (mint SpongeAPI nem), de ha nem látta más fejlesztők, akkor csak tedd mindketten ugyanabban az osztályban.

You’ll want to define an API method for each „unit” your data, such as a String, int, ItemStack or a custom type like Home. These units will be wrapped in a Value, which will allow it to be accessed with Keys. There are various extensions of Value depending on which object will be represented, such as MapValue which provides the standard map operations, or BoundedComparableValue which can set limits on the upper and lower bound of an Comparable objects like integers.

Most, válasszon, amely a AbstractData típusú, akkor meghosszabbítja. Amíg lehet végrehajtani a semmiből, ezek az absztrakt típusok eltávolítása sok a munka, amit meg kell tenni végrehajtási a szükséges módszereket. A teljes lista megtalálható org.spongepowered.api.adatok.manipulátor.változékony.közös. Lásd single-adatok-típusok, vagy :ref:`összetett-adatok-típusok alatt a megvalósítás részleteit, minden típus.

Létre kell hozni két különböző osztályok - ami változékony, illetve valósít meg DataManipulator az absztrakt típus, egy megváltoztathatatlan változata, amely végrehajtja ImmutableDataManipulator s a állandó absztrakt típus.

Megjegyzés

**** Kell az adatokat változékony, megváltoztathatatlan verziók kell végrehajtása.

Minden típusú, akkor meg kell adnunk azt az DataManipulator#asImmutable()/ asMutable() módszerek - ez olyan egyszerű, mint a másolás, a meglévő objektumok a kivitelező a másik változat is.

Values

Az érték vagány(s) kell egy értéket meg kíván kapni. Az alábbi példa mutatja, a ValueFactory. Ez ment meg bennünket, sok típus segítségével Szivacs már végre Érték tárgyakat. Attól függően, hogy milyen értéket hoz létre más módszerek hívni, mint createMapValue, createBoundedComparableValue, stb.

Kód, Például: Végrehajtási Érték Erőszakos

import org.spongepowered.api.Sponge;
import org.spongepowered.api.data.value.ValueFactory;
import org.spongepowered.api.data.value.mutable.Value;

import org.spongepowered.cookbook.myhomes.data.home.Home;
import org.spongepowered.cookbook.myhomes.data.Keys;

@Override
protected Value<Home> defaultHome() {
    return Sponge.getRegistry().getValueFactory()
            .createValue(Keys.DEFAULT_HOME, getValue(), null);
}

Megjegyzés: ez egy ImmutableDataManipulator inkább vissza egy ImmutableValue, hívja asImmutable() a visszatért Érték. Javasoljuk, hogy cache-e (például egy osztály mező) a megváltoztathatatlan verzió.

Minden Értéke is szüksége van egy :javadoc:`Kulcs`, hogy azonosítani, a példában látjuk is, mint a Kulcsok.DEFAULT_HOME. Hasonló értékek, használja a makeXKey() módszerek :javadoc:`KeyFactory, hogy hozzon létre egy `Kulcs` az értéke.

Meg kell adni egy TypeToken képviselő nyers írja be az értéket, majd egy TypeToken képviselő Érték. Neked is meg kell adnia DataQuery utat - ez a leggyakrabban használt serialize az Érték. Mint minden katalógus írja meg kell adnia egy egyedi AZONOSÍTÓ, név. Tedd ezt minden együtt van egy Kulcs a Értéks.

Kód, Például: Létrehozása Gomb

import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.key.Key;
import org.spongepowered.api.data.key.KeyFactory;
import org.spongepowered.api.data.value.mutable.Value;
import org.spongepowered.api.data.value.mutable.Value;

import com.google.common.reflect.TypeToken;

import org.spongepowered.cookbook.myhomes.data.home.Home;

public static final Key<Value<Home>> DEFAULT_HOME = KeyFactory.makeSingleKey(
        TypeToken.of(Home.class),
        new TypeToken<Value<Home>>() {},
        DataQuery.of("DefaultHome"), "myhomes:default_home", "Default Home");

Megjegyzés

TypeTokens are used by the server implementation to preserve the generic type of your values. They are created in one of two ways:

  • A nem-generikus típusok, használja a TypeToken.(MyType.class)`

  • A generikus típusok, hozzon létre egy névtelen osztályt TypeToken<MyGenericType<String>>() {}`

Sorozatkészítés

Ahhoz, hogy az adatok serializable hogy DataHolders vagy a config fájlok, akkor is kell végrehajtani ::javadoc::DataSerializable#toContainer(). Javasoljuk, hívja a szuper.toContainer() mivel ez tartalmazza a verzió DataSerializable#getContentVersion(). Növelni kell a változat minden alkalommal, amikor egy változás történt, hogy a formátum a megjelent adatok, használjuk :ref:`content-updaters, hogy lehetővé teszik, visszafelé kompatibilitás.

Megjegyzés

Ez nem szükséges akkor, egyszerű, egységes típusú, mint a már végre toContainer()`

Kód, Például: Végrehajtási toContainer

import org.spongepowered.api.data.DataContainer;

import org.spongepowered.cookbook.myhomes.data.Keys;

@Override
public DataContainer toContainer() {
    DataContainer container = super.toContainer();
    // This is the simplest, but use whatever structure you want!
    container.set(Keys.DEFAULT_HOME.getQuery(), this.defaultHome);
    container.set(Keys.HOMES, this.homes);

    return container;
}

Single Types

Egyes típusok igényel kis végrehajtás, mert sok a munka már megtörtént a AbstractSingleData type meghosszabbítja.

Az „egyszerű” absztrakt típusok a legegyszerűbb megvalósítani, de kizárólag csak a típusok az alábbi:

  • Boolean

  • Comparable

  • Integer

  • List

  • Map

  • CatalogType

  • Enum

Minden más típusú kell végrehajtani egyéni egyetlen típus, kiterjesztve AbstractSingleData. Ez lehetővé teszi, hogy meghatározza a saját egyetlen adat, amit típus akar, miközben még mindig a legtöbb munka.

Javaslat

The abstract implementations save the object for you in the constructor. You can access it in your implementation by calling the getValue() and getValueGetter() methods.

Simple Single Types

Szinte minden a munka az ön számára egyszerű absztrakt típusok. Csak ennyit kell tennie:

  • Extend the relevant abstract type

  • át a Kulcs az adatok, maga az objektum, az alapértelmezett tárgy (ha az objektum null) a kivitelező

AbstractBoundedComparableData (and the immutable equivalent) additionally require minimum and maximum values that will be checked, as well as a Comparator.

Megjegyzés

List and Mapped single types must instead implement ListData / MappedData (or the immutable equivalent). This adds additional methods to allow Map-like/List-like behavior directly on the DataManipulator.

A következő 3 módszerekkel meg kell határozni a változékony manipluators:

fill(DataHolder, MergeFunction) should replace the data on your object with that of the given DataHolder, using the result of MergeFunction#merge().

import org.spongepowered.api.data.DataHolder;
import org.spongepowered.api.data.merge.MergeFunction;

import org.spongepowered.cookbook.myhomes.data.friends.FriendsData;

import java.util.Optional;

@Override
public Optional<FriendsData> fill(DataHolder dataHolder, MergeFunction overlap) {
    FriendsData merged = overlap.merge(this, dataHolder.get(FriendsData.class).orElse(null));
    setValue(merged.friends().get());

    return Optional.of(this);
}

from(DataContainer) should overwrite its value with the one in the container and return itself, otherwise return Optional.empty()

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

import org.spongepowered.cookbook.myhomes.data.Keys;
import org.spongepowered.cookbook.myhomes.data.friends.FriendsData;
import org.spongepowered.cookbook.myhomes.data.friends.ImmutableFriendsData;

import com.google.common.collect.Maps;

import java.util.Optional;
import java.util.UUID;

@Override
public Optional<FriendsData> from(DataContainer container) {
    if(container.contains(Keys.FRIENDS)) {
        List<UUID> friends = container.getObjectList(Keys.FRIENDS.getQuery(), UUID.class).get();
        return Optional.of(setValue(friends));
    }

    return Optional.empty();
}

copy() should, as the name suggests, return a copy of itself with the same data.

import org.spongepowered.cookbook.myhomes.data.friends.FriendsData;

@Override
public FriendsData copy() {
    return new FriendsDataImpl(getValue());
}

Custom Single Types

Amellett, hogy a , meg kell, hogy felülbírálja a következő módszereket:

getValueGetter() should pass the Value representing your data (see above).

toContainer() should return a DataContainer representing your data (see above).

Compound Types

Whereas single types only support one value, „compound” types support however many values you want. This is useful when multiple objects are grouped, such as FurnaceData. The downside, however, is that they are more complex to implement.

To start with, create all the Value getters that your data will have. For each value, create a method to get and set the raw object, which you’ll use later. For immutable data, only the getters are necessary.

Registering Values

Next, you’ll want to register these so that the Keys-based system can reference them. To do this, implement either DataManipulator#registerGettersAndSetters() or ImmutableDataManipulator#registerGetters() depending on whether the data is mutable or not.

For each value you must call:

  • registerKeyValue(Key, Supplier) referencing the Value getter for the given key

  • registerFieldGetter(Key, Supplier) referencing the getter method for the raw object defined above

  • registerFieldSetter(Key, Consumer) referencing the setter method above if you are implementing the mutable version

We recommend using Java 8’s :: syntax for easy Supplier and Consumer functions.

Code Example: Implementing Getters and Setters

import org.spongepowered.cookbook.myhomes.data.Keys

// registerGetters() for immutable implementation
@Override
protected void registerGettersAndSetters() {
    registerKeyValue(Keys.DEFAULT_HOME, this::defaultHome);
    registerKeyValue(Keys.HOMES, this::homes);

    registerFieldGetter(Keys.DEFAULT_HOME, this::getDefaultHome);
    registerFieldGetter(Keys.HOMES, this::getHomes);

    // Only on mutable implementation
    registerFieldSetter(Keys.DEFAULT_HOME, this::setDefaultHome);
    registerFieldSetter(Keys.HOMES, this::setHomes);
}

fill(DataHolder, MergeFunction) and from(DataContainer) are similar to the implementations for single data, but loading all your values.