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.

Azt akarja, hogy meghatározzák egy API-t, a módszer minden „egység” az adatok, mint például egy Húr, int, ItemStack vagy egyéni írja be, mint Otthon. Ezek az egységek lesz csomagolva :javadoc:`Érték`, amely lehetővé teszi, hogy elérhető :javadoc:`Kulcs`s. Vannak különböző fájlokat az Érték attól függően, hogy melyik objektum képviseli, mint például MapValue, amely a térkép normál működését, vagy BoundedValue, amely korlátokat a felső, mind az alsó határ értéke (mint egész). A határokat az értékek ellenőrzött használata :javadoc:`Összehasonlító`.

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 által használt, a végrehajtás megőrizni az általános írja be az értékeket. Szivacs biztosítja a hosszú listát előre beépített tokenek az API TypeTokens.

Ha létre kell hozni a saját, akkor ezt két módon:

  • 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;
}

Regisztráció

Regisztráció a DataManipulator lehetővé teszi, hogy elérhető lesz a Szivacs, a többi plugin egy általános módszert. A játék/plugin készíthet másolatot az adatok, vagy/deserialize az adatok nélkül hivatkozás bármely, az osztályokat közvetlenül.

Regisztrálni a DataManipulator Szivacs van DataRegistration#építő() segítő. Ez építeni DataRegistration automatikusan regisztrálja.

Megjegyzés

Jellege miatt Adatok ** regisztrálja a DataManipulator inicializálása során - általában hallgatva GameInitializationEvent, mint az alábbi példa mutatja. Ha megpróbálja, hogy regisztrálni egy DataManipulator ha az inicializálás befejezése kivételt fog dobni.

import org.spongepowered.api.event.game.state.GameInitializationEvent;
import org.spongepowered.api.data.DataRegistration;

import org.example.MyCustomData;
import org.example.ImmutableCustomData;
import org.example.CustomDataBuilder;

@Listener
public void onInit(GameInitializationEvent event) {
  DataRegistration.builder()
      .dataClass(MyCustomData.class)
      .immutableClass(ImmutableCustomData.class)
      .builder(new CustomDataBuilder())
      .manipulatorId("my-custom")
      .dataName("My Custom")
      .buildAndRegister(myPluginContainer);
}

Figyelem

Adatok sorszámozott előtt 6.0.0, vagy az adatok, ahol megváltoztak az ID, nem el kell ismerni, kivéve, ha regisztrált DataManager#registerLegacyManipulatorIds(String, DataRegistration). Ha a regisztráció egy előre 6.0.0 DataManipulator ID venni Osztály.getName()`, mint például a com.példa.MyCustomData`.

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.