Ö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.
Verilerinizin her “birimi” için bir `` String``, `` int``,: javadoc: ItemStack veya` Home` gibi özel bir tip gibi tanımlamak isteyeceksiniz. Bu birimler bir: javadoc: Değer ‘ile birleşir ve bu da: javadoc: Key`’i s ile erişilebilir. Hangi nesnenin temsil edileceğine bağlı olarak, “Değer” in çeşitli uzantıları vardır: javadoc: Standart harita işlemlerini sağlayan “MapValue” veya: üst ve alt sınırlara sınırlar koyabilen javadoc: BoundedComparableValue of: javadoc: Comparable nesneleri tamsayılar gibi.
Ş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
: javadoc: TypeToken s değerleri, değerlerin genel türünü korumak için sunucu uygulaması tarafından kullanılır. Bunlar iki yoldan biriyle oluşturulur:
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;
}
Tek Tipler
Tek tipler, çok az uygulama gerektirir, çünkü işin büyük kısmı zaten uzantılı AbstractSingleData
tipi içerisinde yapılmıştır.
“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.
Değiştirilebilir manipluatörler üzerinde aşağıdaki 3 yöntem tanımlanmalıdır:
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
Buna ek olarak, aşağıdaki yöntemleri geçersiz kılmanız gerekir:
``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
Sonra, bunları kaydetmek isteyeceksiniz ki Keys-based sistemi onlara referans verebilsin. Bunu yapmak için aşağıdakilerden birini uygulayın; Verilerin değiştirilebilir olup olmadığına bağlı olarak DataManipulator#registerGettersAndSetters() veya ImmutableDataManipulator#registerGetters() çağırın.
Herhangi bir işlem için aramanız gereken:
registerKeyValue(Key, Supplier)
verilen key’in alıcısı ``Value``yu simgelerregisterFieldGetter(Key, Supplier)
, yukarıda belirlenmiş ham obje için getter metodunu simgelerregisterFieldSetter(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.