Özel DataManipulators

Özel verilerin temel kısmı :javadoc: DataManipulator dir. Bunu uygulamak için, önce özel verileriniz için ayrı bir API oluşturmak isteyip istemediğinize karar vermeniz gerekir. Genel olarak konuşmak gerekirse, uygulamanın API’sını (SpongeAPI gibi) ayırmak en iyisidir, ancak diğer geliştiriciler tarafından görülemeyecek olursa her ikisini de aynı sınıfa koyabilirsiniz.

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 MutableBoundedValue which can set limits on the upper and lower bound of the value (like integers). The bounds of the values are verified using a Comparator.

Şimdi, uzatacağınız AbstractData türlerinden hangisiyse onu seçin. Sıfırdan uygulayabiliyorken, bu soyut tipler, gerekli yöntemleri uygulayarak yapılması gereken işin büyük bir kısmını kaldırır. Tam bir liste şu adreste bulunabilir org.spongepowered.api.data.manipulator.mutable.common. Her bir türü uygulama ayrıntıları için single-data-types`veya :ref:`compound-data-types bölümüne bakınız.

Değişken olan ve uygulayan iki farklı sınıf oluşturmanız gerekir DataManipulator soyut ve değişken, bir diğeri ise :javadoc:`ImmutableDataManipulator`sizin immutable soyut türünüzü uygulayan değişmez bir tür.

Not

Tüm veriler, değiştirilebilir ve değişmez sürümlere sahip olmalı, her ikisini de uygulamalısınız.

Her tür için şunları tanımlamanız gerekir DataManipulator#asImmutable()/ asMutable() yöntemler - varolan nesneleri başka bir sürüm için bir yapıcıya kopyalamak kadar basittir.

Değerler

Değer alıcı(lar)ınız bir değer döndürmelidir. Aşağıdaki örnekte :javadoc:`ValueFactory`yi elde ediyoruz. Bu, Sponge'un halihazırda uygulanmış ``Value`` nesnelerini kullanarak çok fazla şey kazandırır. Oluşturduğunuz değere bağlı olarak createMapValue,` createBoundedComparableValue` gibi farklı yöntemler çağırabilir.

Kod örneği: Bir değer olan “Getter“‘ı dahil etmek

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

Bunun yerine bir ImmutableDataManipulator, döndürülen Value üzerinde asImmutable() çağrısı yapılarak bir ImmutableValue döndürür. Değişken olmayan sürümde bunu (sınıf alanı gibi) önbelleğe almanızı öneririz.

Her bir Değer``in ayrıca :javadoc:`Anahtar` tanımlaması gerekir, örnekte ``Keys.DEFAULT_HOME olarak görülüyor. Değerlerinize benzer şekilde, değeriniz için bir Anahtar yaratmak için; makeXKey() yöntemlerinden birini kullanın KeyFactory.

Değerinizin ham type’ını ve Value``yu simgeleyen iki ayrı ``TypeToken okutmalısınız. Aynı zamanda DataQuery yolunu -bu ``Value``yu şifrelemek için en sık kullanılan yöntemdir- belirtmelisiniz. Çoğu katalog type’ında olduğu gibi isim ve benzersiz bir ID belirtmelisiniz. Bunların hepsini yaptığınızda ``Value``unuzda kullanabileceğiniz bir ``Key``iniz olacaktır.

** Kod örneği: Bir anahtar oluşturmak**

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");

Not

TypeToken, değerlerin genel türünü korumak için uygulama tarafından kullanılır. Sponge, içinde API için önceden oluşturulmuş belirteçlerin uzun bir listesini sağlar TypeTokens.

Kendinizin oluşturması gerekiyorsa, bunu iki yoldan biriyle yapabilirsiniz:

  • Genel olmayan türler için, ``TypeToken.of (MyType.class)``kullan

  • Jenerik tipler için, TypeToken<MyGenericType<String>(){} bilinmeyen sınıfı oluşturabilirsiniz

Serileştirme

Verilerinizi serileştirilebilir hale getirebilmek için serializable’ı :javadoc:`DataHolder`config veya config dosyaları da uygulamanız gerekir :javadoc:`DataSerializable#toContainer() `. ``super.toContainer()`` çağrılmasını öneririz, çünkü bu sürüm aşağıdakilerden oluşacaktır DataSerializable#getContentVersion(). Seri hale getirilmiş verilerinizin formatında her değişiklik yapıldığında sürümü artırmanız ve geriye doğru uyumluluğa izin vermek için DataContentUpdaters kullanmanız gerekir.

Not

Bu, basit tek türler için gerekli değildir, hali hazırda toContainer() uygulanıyor

Kod Örneği: toContainer Uygulama

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

Kayıt

`` DataManipulator`` ‘ı kaydetmek, Sponge ve diğer eklentiler tarafından genel bir yolla erişilebilmesini sağlar. Oyun/eklenti verilerinizin kopyalarını oluşturabilir ve doğrudan sınıflarınızdan herhangi birine başvurmadan verilerinizi seri / seriden paralele çevrilmiş hale getirirebilir.

Sponge’ nin bir DataManipulator kaydetmek için DataRegistration#builder() yardımcı programı vardır. Bu bir DataRegistration oluşturacak ve otomatik olarak kaydedecektir.

Not

Data’nın doğasından ötürü, başlatma işlemi sırasında DataManipulator’ı kaydetmeniz gerekir. Genellikle aşağıda ki örnekte olduğu gibi GameInitializationEvent’ı dinliyor. Bir başlatma işlemi tamamlandıktan sonra bir DataManipulator kaydetmeye çalışırsanız, istisna yapılır.

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")
      .build();
}

Uyarı

Data that was serialized prior to 6.0.0, or data where you have changed the ID, will not be recognized unless registered with DataManager#registerLegacyManipulatorIds(String, DataRegistration). If registering a pre-6.0.0 DataManipulator the ID is taken from Class.getName(), such as com.example.MyCustomData.

Tek Tipler

Single types require little implementation because much of the work has already been done in the AbstractSingleData type you extend from.

“Basit” soyut türleri en kolay uygulanabilir ancak yalnızca aşağıdaki türlerle sınırlıdır:

  • Boolean

  • Comparable

  • Integer

  • Liste

  • Harita

  • CatalogType

  • Enum

Diğer tüm türler için, AbstractSingleData uzatarak özel bir tek tip uygulamanız gerekir. Bu sizin için en çok işi yapmaya devam ederken, istediğiniz tek tipte kendi tek verilerinizi tanımlamanıza izin verir.

Tüyo

Soyut uygulamalar, nesneyi yapıcıya kaydeder. Uygulamanızda,``getValue()`` ve `` getValueGetter() yöntemlerini çağırarak erişebilirsiniz.

Basit Tek Türler

Hemen hemen tüm çalışmalar basit soyut türlerle yapılır. Tek yapmanız gereken:

  • İlgili soyut türünü uzatın

  • verilerinizi, nesnenin kendisi ve varsayılan nesnesi (nesne boş ise) için olan Key’i oluşturucudan geçirin

AbstractBoundedComparableData (ve değiştirilemeyen eşdeğeri) ek olarak kontrol edilecek minimum ve maksimum değerleri ve ayrıca bir Comparator gerektirir.

Not

List ve Mapped tekil tipleri yerine ListData/MappedData``(ya da bunların immutable benzerlerini) tiplerini kullanmalısınız. Bu ayrıca ``DataManipulator üzerinde Map ve List benzeri etkileri kullanabileceğiniz metodları sağlar.

The following 3 methods must be defined on mutable manipulators:

fill(DataHolder, MergeFunction), MergeFunction#merge() sonucunda DataHolder ile verilmiş olan objenizin verisini değiştirmelidir.

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), değerini container içindekiyle overwrite etmelidir ve kendine dönüt sağlamalıdır, aksi taktirde``Optional.empty()`` dönütü sağlayacaktır

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() isminden de anlaşılacağı üzere aynı verileri içeren bir kopyasını sağlamalıdır.

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

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

Özel Tek Türler

In addition to the methods from the simple single types, you need to override the following methods:

``getValueGetter()``a verinizi simgeleyen (yukarıyı kontrol edin) ``Value``yu okutmalısınız.

toContainer() verinizi simgeleyen (yukarıyı kontrol edin) DataContainer dönütlemelidir.

Bileşik türler

Tek türler yalnızca bir değeri desteklediğinde, “bileşik” türleri istediğiniz birçok değeri destekler. Bu, birden fazla nesne gruplanmış olduğunda yararlıdır FurnaceData. Bunun zayıf yönü, uygulamanın daha karmaşık olmasıdır.

Başlangıç olarak, verilerinizin sahip olacağı tüm Value çağırıcılarını oluşturun. Her değer için, daha sonra kullanacağınız raw nesnesini almak ve ayarlamak için bir yöntem oluşturun. Değişken olmayan veriler için yalnızca alıcılar gereklidir.

İşlemleri Kaydet

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

Herhangi bir işlem için aramanız gereken:

  • registerKeyValue(Key, Supplier) verilen key’in alıcısı ``Value``yu simgeler

  • registerFieldGetter(Key, Supplier), yukarıda belirlenmiş ham obje için getter metodunu simgeler

  • registerFieldSetter(Key, Consumer), eğer mutable alternatifini kullanıyorsanız yukarıdaki setter metodunu simgeler

Kolay Suplier ve Consumer fonksiyonları için Java 8’in :: sözdizimini öneriyoruz.

Örnek Kod: Getter’ların ve Setter’ların Kullanımı

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) ve from(DataContainer), tekil veriler için olan uygulamalara benzerler, fakat farklı olarak bütün verilerinizi yüklerler.