Veri manipülatörleri
Verilere erişme ve değiştirme
Bir veri manipülatörü, belirli bir bileşeni ve tüm verilerini temsil eder. Bu verilerin bir temsilini depolar ve eşleşen bir bileşene sahip olan veri sahiplerine sunulabilir veya bunları oluşturulabilir. Yine, bir örnek kullanalım. Ve yine birisini iyileştirmeye çalışın (ya da başka bir şey).
Kod Örneği: Veri manipülatörleri ile iyileştirme
import org.spongepowered.api.data.DataHolder;
import org.spongepowered.api.data.DataTransactionResult;
import org.spongepowered.api.data.manipulator.mutable.entity.HealthData;
import org.spongepowered.api.data.value.mutable.MutableBoundedValue;
import java.util.Optional;
public static DataTransactionResult heal(DataHolder target) {
Optional<HealthData> healthOptional = target.get(HealthData.class);
if (healthOptional.isPresent()) {
HealthData healthData = healthOptional.get();
double maxHealth = healthData.maxHealth().get();
MutableBoundedValue<Double> currentHealth = healthData.health();
currentHealth.set(maxHealth);
healthData.set(currentHealth);
target.offer(healthData);
}
}
Öncelikle hedefimiz, sağlık verileri olup olmadığını kontrol etmektir. Onu ilk önce sınıfını get()
metoduna geçirerek sağlık verilerimizi vermesini isteyerek yapıyoruz. Çeklerimiz için kullanabileceğimiz bir Optional
alıyoruz. Hedefimiz şunları desteklemiyorsa, bu Optional
mevcut olmayacaktır HealthData veya destekliyorsa, şu an herhangi bir sağlık verisi tutmuyor.
Sağlık verileri mevcutsa, artık veri sahibi üzerinde bulunan verilerin değiştirilebilir bir kopyasını içerir. Değişikliklerimizi yaparız ve nihayet değiştirilen veriyi kabul edildiği yerde tekrar hedefimize geri getiririz (yine, ‘’ offer () ‘’ a :javadoc: ‘DataTransactionResult’ bu, bu örneği de gözardı edeceğiz ve şunlara geri döneceğiz :doc: ‘daha sonraki bir noktada<transactions>’).
Gördüğünüz gibi ‘’ health () ‘’ ve ‘’ maxHealth () ‘’ sonuçları yine :javadoc: ‘DataHolder’ den elde ettiğimiz anahtar değerlerdir. ‘’ Health () ‘’ çağrısından aldığımız :javadoc: ‘MutableBoundedValue’, sadece bir verinin bir kopyasını içerdiğinden önce değişiklikleri uygulamanız gerekiyor::javadoc: ‘DataManipulator’, ‘healthData’’ hedefimize döndü.
Tüyo
Data API Kural 1: Aldığınız her şey bir kopyadır. Bu nedenle, bir şeyi değiştirdiğinizde, değişikliğinizin orijinal değere nereden geri dönüp geldiğine emin olun.
Bir diğer muhtemel değişiklik, tamamen bir DtaManipulator``ü kaldırmaktır. Bu, kaldırılması gereken ``DtaManipulator
türü için bir sınıf başvurusu kabul eden remove()
yöntemi ile yapılır. Bazı veriler kaldırılamaz ve bunu yapma girişimleri her zaman başarısızlığı gösteren bir DataTransactionResult
ı geri döndürecektir. Takip eden kod DtaHolder
dan verilen özel bir ismi kaldırmak için girişimde bulunur. Yine işlemin sonucu kullanımdan düşmüştür.
Örnek Kod: Özel display name’i kaldırmak
import org.spongepowered.api.data.manipulator.mutable.DisplayNameData;
public void removeName(DataHolder target) {
target.remove(DisplayNameData.class);
}
DataManipulator ve Anahtarlar
İyileştirme örneklerinin her ikisini de karşılaştırdıysanız, ‘Neden veri manipülatörleri ile uğraşıyorsunuz, tuşlar çok daha kolay’ ve doğru mu? - tek değer elde etmek ve ayarlamak için merak edebilirsiniz. Ancak, bir veri manipülatörünün gerçek avantajı, belirli bir bileşene ilişkin tüm verileri içeriyor olmasıdır. Hadi başka bir örneğe bir göz atalım.
Kod Örneği: İki veri sahibinin sağlığını değiştirme
public void swapHealth(DataHolder targetA, DataHolder targetB) {
if (targetA.supports(HealthData.class) && targetB.supports(HealthData.class)) {
HealthData healthA = targetA.getOrCreate(HealthData.class).get();
HealthData healthB = targetB.getOrCreate(HealthData.class).get();
targetA.offer(healthB);
targetB.offer(healthA);
}
}
İlk olarak her iki hedefinde HealthData’yı destekleyip desteklemediğini kontrol ediyoruz. Eğer destekliyorsa her ikisininde sağlığını bir değişkende kaybederiz. HealthData``nın desteklendiğini doğruladığımız için bu sefer ``Optional
ile uğraşmaya gerek duymayız ve getOrCreate()
yöntemi hiçbir veri bulunmasa bile varsayılan değerler üretilir.
Sonra kaydedilen sağlık verilerini diğer hedefe sunuyoruz, böylece sağlık durumlarını birbirleriyle değiştiriyoruz.
Her bir tuş ile kendimiz ilgilenmek zorunda olduğumuz için Keys
ile yapılan bu örnek biraz uzun ve daha karmaşık olacaktır. Ve sağlığın yerine daha fazla veri içeren başka bir veri manipülatörü takas etseydik (belki hatta bir liste içeren :javadoc: InvisibilityData), yapacak daha çok işimiz olurdu. Fakat veri sahibi kendisi ile ilgili olan tüm verileri dikkate aldığı için, iki sahip arasında rastgele veri takas etmek için yukarıdaki işlevi bile değiştirebiliriz.
Kod örneği: Herhangi bir veri manipülatörünü değiştirme
import org.spongepowered.api.data.manipulator.DataManipulator;
public <T extends DataManipulator<?,?>> void swapData(DataHolder targetA, DataHolder targetB, Class<T> dataClass) {
if (targetA.supports(dataClass) && targetB.supports(dataClass)) {
T dataA = targetA.getOrCreate(dataClass).get();
T dataB = targetB.getOrCreate(dataClass).get();
targetA.offer(dataB);
targetB.offer(dataA);
}
}
Aynı veri ile başka bir veri tutucu üzerindeki herhangi bir veriyi değiştiren bir işlev yazabilme özelliği, Data API’nın temel tasarım hedefini gösterir: API boyunca maksimum uyumluluk.
Değişken ve Değiştirilemez Veri Manipülatörleri
Her veri manipülatöre eşleşen :javadoc: ImmutableDataManipulator var. Örneğin, ``HealthData` ve :javadoc: ImmutableHealthData aynı verileri içerir; sadece sonuncusu, değiştirilmiş veriyi talep ederken yeni örnekleri döndürür.
Değiştirilebilir ve değiştirilemeyen veri manipülatörleri arasındaki dönüştürme, her biri verilerin bir kopyasını döndürecek olan asImmutable()
ve asMutable()
yöntemleri ile yapılır. Bir veri sahibinden değişmez bir veri manipülatörü elde etmenin tek yolu değiştirilebilir bir veri elde etmek ve daha sonra asImmutable()
yi kullanmaktır.
Bunun için olası bir kullanım durumunda, biri iyileştiğinde tetiklenen özel bir olay olacaktır. Önce ve sonra sağlık verilerinin kopyalarını sağlamalıdır, ancak etkinlik dinleyicileri bunları değiştirememelidir. Dolayısıyla olayımızı yalnızca ImmutableHealthData
örnekleri sunmak için yazabiliriz. Bu şekilde, üçüncü taraf kodu verilerimizle etkileşime girilse bile, değiştirilemeyeceğinden emin olabiliriz.
Eksik veri
Yukarıda bahsedildiği gibi, get()
yöntemi eğer takip edenlerden biri doğru ise boş bir Optional
a dönüşebilir:
DataHolder
verilmiş olan ``DataManipulator``ü desteklemezDataHolder
,DataManipulator
’ı desteklemesine rağmen şu anda o type’taki bir veriyi içermemektedir
Verilerin mevcut olmadığı ve varsayılan değerlerden oluşan veriler arasında büyük bir anlamsal fark vardır. İkincisi her zaman mümkün olmakla birlikte, bir DataHolder
‘ın bir tür veriyi desteklemesi ve ardından tutması olanaksız olduğu durumlar vardır. Bunların örnekleri şunları içerir:
HealthData
onu destekleyen her (vanilla)``DataHolder``da daima belirlidirDisplayNameData, :javadoc:`Player`da daima belirlidir, fakat diğer entity’lerde bulunmayabilir.