Veri manipülatörleri

Uyarı

These docs were written for SpongeAPI 7 and are likely out of date. If you feel like you can help update them, please submit a PR!

Verilere erişme ve değiştirme

A data manipulator represents a certain component and all of its data. It stores a representation of that data and can be offered to or created from data holders which possess a matching component. Again, let’s use an example. Once more we try to heal someone (or something).

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

First, we need to check if our target has health data. We do so by first asking it to provide us with its health data by passing its class to the get() method. We get an Optional which we can use for our check. This Optional will be absent if either our target does not support HealthData or if it supports it but at the present moment does not hold any health data.

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

First, we check if both targets support HealthData. If they do, we save the health of both in one variable each. We don’t need to bother with Optional this time since we verified that HealthData is supported and the getOrCreate() method ensures that even if no data is present, default values are generated.

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.

A possible use case for this would be a custom event fired when someone is healed. It should provide copies of the health data before and after, but event listeners should not be able to change them. Therefore, we can write our event to only provide ImmutableHealthData instances. That way, even if third party code gets to interact with our data, we can rest assured that it will not be changed.

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``ü desteklemez

  • DataHolder, 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 belirlidir

  • DisplayNameData, :javadoc:`Player`da daima belirlidir, fakat diğer entity’lerde bulunmayabilir.