DataManipulators Uygulanması

Bu, DataManipulators oluşturarak Data API uygulaması ile yardımcı olmak isteyenlere rehberlik eder. Uygulanacak DataManipulators’ın güncellenmiş bir listesi SpongeCommon Sayı # 8 <https://github.com/SpongePowered/SpongeCommon/issues/8> `_’de bulunabilir.

Bir `` DataManipulator``ı tam olarak uygulamak için bu adımlar takip edilmelidir:

  1. `` DataManipulator``nin kendisini uygula

  2. `` ImmutableDataManipulator`` ‘in uygulanması

Bu adımlar tamamlandığında, aşağıdakiler de yapılmalıdır:

  1. KeyRegistry anahtarını kaydettirin

  2. “DataProcessor” ni Uygulama

  3. “DataManipulator” tarafından temsil edilen her değer için “ValueProcessor” uygulamak

  4. Herşeyi “SpongeSerializationRegistry” `e kaydedin

Not

Bizim dokümanımızı takip ettiğinizden emin olun ../ guidelines.

1. DataManipulator Uygulayın

`` DataManipulator`` uygulamaları için adlandırma kuralı, “Sünger” öneki olan arayüzün adıdır. Dolayısıyla, `` HealthData`` arayüzünü uygulamak için, uygun pakete “SpongeHealthData`` adlı bir sınıf oluşturduk. `` DataManipulator`` uygulamak için öncelikle org.spongepowered.common.data.manipulator.mutable.common paketinden uygun bir soyut sınıfı genişlettik. En yaygın olanı `` AbstractData``, ancak yalnızca tek bir değer içeren `` DataManipulator`` gibi bazı özel durumlar için dahası dökümantasyon kodunu düşüren soyutlamalar da var.

public class SpongeHealthData extends AbstractData<HealthData, ImmutableHealthData> implements HealthData {
    [...]
}

AbstractData sınıfında iki tür argüman vardır. İlki, bu sınıf tarafından uygulanan arayüz, ikincisi, karşılık gelen `` ImmutableDataManipulator`` tarafından uygulanan arayüz.

Kurucu

Çoğu durumda soyut bir `` DataManipulator`` uygularken iki kurucuya sahip olmalısınız:

  • İkinci yapıcıyı “varsayılan” değerlerle çağıran bağımsız değişkensiz (bağımsız değişken yok)

  • Desteklediği tüm değerleri alan ikinci kurucu.

İkinci kurucu gerekir

  • uygulanan arabirim için sınıf referansını ileterek, `` AbstractData`` yapıcısını çağırın.

  • geçen değerlerin geçerli olduğundan emin olun

  • `` registerGettersAndSetters () `` yöntemini çağır

import static com.google.common.base.Preconditions.checkArgument;

public class SpongeHealthData {

    public SpongeHealthData() {
        this(DataConstants.DEFAULT_HEALTH, DataConstants.DEFAULT_HEALTH);
    }

    public SpongeHealthData(double currentHealth, double maxHealth) {
        super(HealthData.class);
        checkArgument(currentHealth >= DataConstants.MINIMUM_HEALTH && currentHealth <= (double) Float.MAX_VALUE);
        checkArgument(maxHealth >= DataConstants.MINIMUM_HEALTH && maxHealth <= (double) Float.MAX_VALUE);
        this.currentHealth = currentHealth;
        this.maximumHealth = maxHealth;
        this.registerGettersAndSetters();
    }

    ...

}

Mevcut sağlığın ve maksimum sağlığın sınırlı değerler olduğunu bildiğimizden, bu sınırların dışında hiçbir değerin geçemeyeceğinden emin olmalıyız. Bunu başarmak için, gerekli yöntemleri statik olarak içe aktarmaya çalıştığımız guava’nın “Ön Şartları” nı kullanıyoruz.

Not

Asla kodunuzda sihirli değerler (rasgele sayılar, booleans vb.) Kullanmayın. Bunun yerine, org.spongepowered.common.data.util.DataConstants sınıfını bulun ve bir uydurma sabiti kullanın - veya gerekirse bir tane oluşturun.

Arabirim tarafından tanımlanan erişimciler

Uyguladığımız arayüz, `` Value`` nesnelerine erişmek için bazı yöntemler belirlemektedir. `` HealthData`` için, bunlar `` health () `` ve `` maxHealth () `` dir. Bunlara yapılan her çağrıya yeni bir “Value” getirilmelidir.

public MutableBoundedValue<Double> health() {
    return SpongeValueFactory.boundedBuilder(Keys.HEALTH)
        .minimum(DataConstants.MINIMUM_HEALTH)
        .maximum(this.maximumHealth)
        .defaultValue(this.maximumHealth)
        .actualValue(this.currentHealth)
        .build();
}

Tüyo

`` Double`` bir `` Comparable`` olduğundan, açıkça bir karşılaştırıcı belirtmemiz gerekmez.

Geçerli bir değer belirtilmemişse, Value üzerindeki `` get () `` i çağırmak varsayılan değeri döndürür.

Kopyalama ve Seri hale getirme

`` Copy () `` ve `` asImmutable () `` gibi iki yöntem uygulanacak pek fazla çalışma değildir. Her ikisi için sırasıyla, geçerli örnekle aynı verileri içeren değişken veya değişmez bir veri manipülatörü döndürmeniz yeterlidir.

`` ToContainer () `` yöntemi seri hale getirme amacıyla kullanılır. Sonuç olarak bir `` MemoryDataContainer`` kullanın ve bu örnekte saklanan değerleri kendisine uygulayın. Bir `` DataContainer``, temel olarak değerlere “DataQuery`` eşleştiren bir haritadır. Bir `` Key`` her zaman karşılık gelen bir `` DataQuery`` içerdiğinden bunları `` Key`` doğrudan geçerek kullanın.

public DataContainer toContainer() {
    return new MemoryDataContainer()
        .set(Keys.HEALTH, this.currentHealth)
        .set(Keys.MAX_HEALTH, this.maximumHealth);
}

almayıveayarlamayıkaydet()

`` DataManipulator`` ayrıca, tuşları kullanarak veri almak ve ayarlamak için yöntemler sağlar. Bunun için uygulanma, `` AbstractData`` tarafından gerçekleştirilir, ancak hangi veriye erişebileceğini ve nasıl erişebileceğini söylemeliyiz. Bu nedenle, `` registerGettersAndSetters () `` yönteminde her bir değer için aşağıdakileri yapmamız gerekir:

  • doğrudan bir değeri elde etmek için bir “Tedarikçi” kaydettirin

  • değeri doğrudan ayarlamak için bir “Consumer” kaydettirin

  • değiştirilebilir ‘değer’ i almak için bir ‘tedarikçi <değer>’ `i kaydettirin

“Tedarikçi” ve “Tüketici” fonksiyonel arabirimlerdir, bu nedenle Java 8 Lambda’lar kullanılabilir.

private void setCurrentHealthIfValid(double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        this.currentHealth = value;
    } else {
        throw new IllegalArgumentException("Invalid value for current health");
    }
}

private void setMaximumHealthIfValid(double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        this.maximumHealth = value;
    } else {
        throw new IllegalArgumentException("Invalid value for maximum health");
    }

}

private void registerGettersAndSetters() {
    registerFieldGetter(Keys.HEALTH, () -> SpongeHealthData.this.currentHealth);
    registerFieldSetter(Keys.HEALTH, SpongeHealthData.this::setCurrentHealthIfValid);
    registerKeyValue(Keys.HEALTH, SpongeHealthData.this::health);

    registerFieldGetter(Keys.MAX_HEALTH, () -> SpongeHealthData.this.maximumHealth);
    registerFieldSetter(Keys.MAX_HEALTH, SpongeHealthData.this::setMaximumHealthIfValid);
    registerKeyValue(Keys.MAX_HEALTH, SpongeHealthData.this::maxHealth);
}

Alan ayarlayıcı olarak kaydedilen “Tüketici”, sağlanan değerin geçerli olduğundan emin olmak için yeterli kontrolleri yapmalıdır. Bu, özellikle negatif değerleri kabul etmeyecek olan “DataHolder” için geçerlidir. Bir değer geçersiz ise, bir `` IllegalArgumentException`` atılmalıdır.

Tüyo

Bu ayarlayıcıların geçerlilik kriterleri ilgili “Değer” nesnesi ile aynıdır, bu nedenle geçerlilik kontrolünü “this.health (). Set ()” un bir çağrısına devredebilir ve sadece this.currentHealth = değer ` ilk satırda henüz bir özel durum atılmamışsa.

Bu kadar. `` DataManipulator`` şimdi yapılmalıdır.

2. ImmutableDataManipulator uygulamak

`` ImmutableDataManipulator`` ‘in uygulanması değiştirilebilir programın uygulanmasına benzer.

Tek fark:

  • Sınıf adı değiştirilebilir `` DataManipulator`` ismini `` ImmutableSponge`` ile önekleyerek oluşturulmuştur

  • Onun yerine `` ImmutableAbstractData`` dan miras bırakın

  • `` RegisterGettersAndSetters () `` yerine, yöntem `` registerGetters () ``

`` ImmutableDataHolder`` s veya `` ImmutableValue`` s ‘yi oluştururken, `` ImmutableDataCachingUtil`` değerini kullanmanın mantıklı olup olmadığını kontrol edin. Örneğin, bir Boolean’dan daha fazlasını içeren “WetData” öğesine sahipseniz, mümkün olan her değer için bir tane olmak üzere, yalnızca önbelleğe alınmış “ImmutableWetData” örneklerini korumak daha uygundur. Bununla birlikte manipülatörler ve olası birçok değeri olan değerler (“SignData” gibi) için, önbelleğe alma işleminin çok pahalı olduğu kanıtlanmıştır.

Tüyo

Yanlışlıkla yapılan değişiklikleri önlemek için bir `` ImmutableDataManipulator`` alanlarını `` final`` olarak beyan etmelisiniz.

3. Anahtarı KeyRegistry’e kaydedin

Bir sonraki adım, `` Key`` s’larınızı `` KeyRegistry``ye kaydetmektir. Bunu yapmak için, `` org.spongepowered.common.data.key.KeyRegistry`` sınıfını bulun ve statik `` generateKeyMap () `` işlevini bulun. Kullandığınız tuşları kaydetmek (ve oluşturmak için) bir satır ekleyin.

keyMap.put("health"), makeSingleKey(Double.class, MutableBoundedValue.class, of("Health")));
keyMap.put("max_health", makeSingleKey(Double.class, MutableBoundedValue.class, of("MaxHealth")));

`` KeyMap`` dizeleri `` Key`` s’e eşlenir. Kullanılan dize, küçük harflerle `` Keys`` yardımcı program sınıfına karşılık gelen sabit isim olmalıdır. `` Key`` kendisi, `` KeyFactory`` tarafından sağlanan statik yöntemlerden biri tarafından, çoğu durumda `` makeSingleKey`` tarafından oluşturulur. `` makeSingleKey`` öncelikli olarak, altta yatan veriler için bir sınıf referansı gerektirir; bu da bizim durumumuzda bir “Çift”, daha sonra kullanılan “Value” tipi için bir sınıf referansıdır. Üçüncü argüman seri hale getirme için kullanılan “DataQuery” dir. Statik olarak içe aktarılan DataQuery.of () `` metodundan bir dize kabul edilerek oluşturulur. Bu dize ayrıca alt çizgiden sıyrılmış sabit ad olmalı ve büyük harf büyük deve davasına dönüşmüştür.

4. Veri İşlemcilerini Uygulama

Sıradaki, “DataProcessor” dir. “DataProcessor”, “DataManipulator” ve Minecraft nesneleri arasında bir köprü görevi görür. Vanilla Minecraft’da bulunan “DataHolder’lar” dan talep edilen veya teklif edilen her çağrı, “DataProcessor” ya da “ValueProcessor” ‘a devredilir.

Adınız için “DataManipulator” arayüzünün adını kullanmalı ve “Processor” ‘yı eklemelisiniz. Böylece `` HealthData`` için bir `` HealthDataProcessor`` oluştururuz.

Hazır kaynak kodunu azaltmak için, “DataProcessor”, “org.spongepowered.common.data.processor.common” paketindeki uygun soyut sınıftan miras alınmalıdır. Sağlık yalnızca belirli varlıklar üzerinde mevcut olabileceği için, “net.minecraft.entity.Entity” ‘ye dayanarak “Entities” e özel olarak hedeflenen “AbstractEntityDataProcessor”’ u kullanabiliriz. `` AbstractEntitySingleDataProcessor`` daha az uygulama gerektirir ancak `` HealthData`` sadece bir değerden fazlasını içerdiği için kullanılamaz.

public class HealthDataProcessor extends AbstractEntityDataProcessor<EntityLivingBase, HealthData, ImmutableHealthData> {
    public HealthDataProcessor() {
        super(EntityLivingBase.class);
    }
    [...]
}

Hangi soyutlamayı kullandığınıza bağlı olarak, uygulamak zorunda olduğunuz yöntemler, soyut sınıfta ne kadar çok uygulama işi yapılabileceğine bağlı olarak büyük ölçüde farklılık gösterebilir. Genellikle, yöntemler kategorize edilebilir.

Tüyo

Aynı veri için birden çok DataProcessor oluşturmak mümkündür. Eğer çok farklı DataHolder lar ise desteklenmelidir (örneğin TileEntity ve eşleşen bir ItemStack) sağlanan soyutlamaları tam kullanmak için her bir tip DataHolder için bir işlemci oluşturmak yararlı olabilir. Eşyalar, karolar ve varlıklar için paket biçimini takip ettiğinizden emin olun.

Doğrulama Yöntemleri

Her zaman bir boolean değeri döndürür. Eğer yöntem `` supports () `` olarak adlandırılmışsa, sağlanan hedefin genellikle `` DataProcessor`` tarafından işlenen veri türlerini destekleyip desteklemediğine genel bir denetim yapmalıdır.

Hi everybody

Bunun yerine bir doesDataExist() yöntemi sağlamamız gerekiyor. Soyutlama, verilerin nasıl elde edileceğini bilmediği için bu işlevin uygulanmasına izin verir. İsmin de belirttiği gibi, yöntem desteklenen hedefle verilerin halihazırda olup olmadığını kontrol etmeli. HealthDataProcessor için bu her zaman doğru olur, çünkü her canlı varlığın sağlığı olduğu için.

protected boolean doesDataExist(EntityLivingBase entity) {
    return true;
}

Ayarlayıcı Yöntemleri

Bu ayarlayıcı yöntem bir tür DataHolder ve mümkünse ona uygulanması gereken bazı veriler alır.

‘’ DataProcessor’’ ara yüzü, bir ‘’DataHolder’’ alan bir ‘’ set() ‘’ yöntemi ve ‘’ DataTransactionResult’’ döndüren bir ‘’DataManipulator’’ tanımlar. Kullanılan soyutlama sınıfına bağlı olarak, gerekli işlevlerin bazıları zaten uygulanmış olabilir.

Bu durumda AbstractEntityDataProcessor çoğu şeyi halleder ve başarılı ise bazı değerleri true ya çevirmek için ve başarılı değilse false a çevirmek için sadece bir metoda ihtiyaç duyar. DataHolder``ın "Data"yı destekleyip desteklemediğine dair tüm kontroller halledilir, soyut sınıf her bir ``Key dosyasını DataManipulator``deki değeri ile eşleyerek sadece bir eşlemi geçecek ve sonra işlemin başarılı olup olmadığına bağlı olarak bir ``DataTransactionResult oluşturacak.

protected boolean set(EntityLivingBase entity, Map<Key<?>, Object> keyValues) {
    entity.getEntityAttribute(SharedMonsterAttributes.maxHealth)
        .setBaseValue(((Double) keyValues.get(Keys.MAX_HEALTH)).floatValue());
    entity.setHealth(((Double) keyValues.get(Keys.HEALTH)).floatValue());
    return true;
}

Tüyo

‘’ DataTrans actionResult ‘’ s değerlerini anlamak için :doc: ‘ ilgili dokümanlar sayfasını kontrol edin. <../../ eklenti / veri / işlemler> ‘ başlığına bakın ve :javadoc: ‘org.spongepowered.api.data.DataTransactionResult.Builder ‘ dokümanları oluşturmak için dokümanlar.

Uyarı

Özellikle ‘’ ItemStack ‘’ ‘lerle çalışırken, doğrudan ‘’ NBTTagCompound ‘’ ile uğraşmanız gerekecektir. Birçok NBT anahtarı, ‘’ org.spongepowered.common.data.util.NbtDataUtil ‘’ sınıfında sabitler olarak tanımlanmıştır. Gerekli anahtarınız yoksa, kodda ‘sihirli değerler’ önlemek için onu eklemeniz gerekir.

Kaldırma yöntemi

‘’ Remove () ‘’ yöntemi, verileri ‘’ DataHolder ‘’ alanından kaldırmaya çalışır ve bir ‘’ DataTrans actionResult ‘’ döndürür.

Soyutlamalar, verilerin her zaman uyumlu bir `` DataHolder`` (`` WetData`` veya `` HealthData`` gibi) olup olmadığını bilmenin bir yolu olmadığı için Soyut veri `` DataProcessor`` soyutlamalarında soyutlama yapılmamıştır; bulunabilir veya olmayabilir (“LoreData” gibi). Veriler her zaman mevcutsa, `` remove () `` daima başarısız olmalı. Varsa yada bulunamıyorsa, `` remove () `` onu kaldırmalıdır. Bu gibi durumlarda `` doesDataExist () `` yöntemi geçersiz kılınmalıdır.

Entity’ler istisnasız olarak yaşam puanına sahip olduklarından HealthData değerinin kaldırılması desteklenmemektedir. Bu yüzden dönüt olarak failNoData() dönmekle beraber doesDataExist() metodunu override etmemekteyiz.

public DataTransactionResult remove(DataHolder dataHolder) {
    return DataTransactionBuilder.failNoData();
}

Getter Yöntemleri

Getter yöntemleri, bir “DataHolder” den veri elde eder ve isteğe bağlı bir “DataManipulator” i döndürür.’’ DataProcessor ‘’ arabirimi, ‘’ from() ‘’ ve ‘’ createFrom() ‘’ yöntemlerini belirtir, fark ‘’ from() ‘’ ‘’ Optional.empty() ‘’ veri sahibi uyumlu ancak şu anki verileri içermiyor; buna karşın, ‘’ createFrom() ‘’ bu durumda varsayılan değerleri taşıyan bir “DataManipulator” sağlayacak.

Yine, ‘’ AbstractEntityDataProcessor ‘’ bunun için uygulamanın çoğunu sağlayacak ve yalnızca ‘’ DataHolder ‘’üzerinde fiili değerleri elde etmek için bir yöntem gerektiriyor. Bu yöntem yalnızca, ‘’ supports() ‘’ ve ‘’ doDataExist() ‘’ den sonra çağrılır, her ikisi de doğrudur, yani verilerin bulunduğu varsayımı altında çalışır.

Uyarı

Veriler her zaman hedef “DataHolder” te bulunmayabilirse, örn. ‘’ remove () ‘’ işlevi başarılı olabiliyorsa (yukarıya bakın), veri mevcutsa ‘’ true ‘’ döndürmesi için ‘’ doesDataExist () ‘’ yöntemini geçersiz kılmanız şarttır, yanlış ‘’ değilse.

protected Map<Key<?>, ?> getValues(EntityLivingBase entity) {
    final double health = entity.getHealth();
    final double maxHealth = entity.getMaxHealth();
    return ImmutableMap.<Key<?>, Object>of(Keys.HEALTH, health, Keys.MAX_HEALTH, maxHealth);
}

Dolgu Yöntemleri

Bir dolgu yöntemi, bir dolgu metodundan farklıdır; bu değerlerle doldurmak için bir “DataManipulator” alır. Bu değerler bir “DataHolder” dan gelebilir veya “DataContainer” den deserialize edilmelidir. Yöntem ‘’ DataHolder ‘’ uyumsuzsa ‘’ Optional.empty () ‘’ döner.

`` AbstractEntityDataProcessor``, tutucudan bir `` DataManipulator`` yaratarak ve daha sonra sağlanan manipülatör ile birleştirerek, `` DataHolders`` den doldurmarabilir, ancak bu durum sağlanamadığında `` DataContainer`` deserialization’ı işliyor.

public Optional<HealthData> fill(DataContainer container, HealthData healthData) {
    final Optional<Double> health = container.getDouble(Keys.HEALTH.getQuery());
    final Optional<Double> maxHealth = container.getDouble(Keys.MAX_HEALTH.getQuery());
    if (health.isPresent() && maxHealth.isPresent()) {
        healthData.set(Keys.HEALTH, health.get());
        healthData.set(Keys.MAX_HEALTH, maxHealth.get());
        return Optional.of(healthData);
    }
    return Optional.empty();
}

The fill() method is to return an Optional of the altered healthData, if and only if all required data could be obtained from the DataContainer.

Diğer yöntemler

Kullanılan soyut üst sınıfa bağlı olarak, bazı diğer yöntemler gerekebilir. Örneğin, `` AbstractEntityDataProcessor`` çeşitli noktalarda `` DataManipulator`` örnekleri oluşturmalıdır. Ne uygulama sınıfı ne de yapıcı kullanılacağını bildiği için bunu yapamazsınız. Bu nedenle, uygulama tarafından sağlanması gereken soyut bir işlevi kullanır. Bu, varsayılan veriyle bir `` DataManipulator`` yaratmaktan başka bir şey yapmaz.

``DataManipulator``ınızı önerilen olarak yerine getirirseniz, sadece no-args ustası kullanabilirsiniz.

protected HealthData createManipulator() {
    return new SpongeHealthData();
}

5. Değer İşlemlerini uygula

Yalnızca bir ‘’ DataManipulator ‘’, bir ‘’ DataHolder ‘’ ‘e değil, aynı zamanda anahtarlı ‘’ Value ‘’ ‘e ayrı ayrı teklif edilebilir. Dolayısıyla, ‘’ DataManipulator ‘’ de bulunan her ‘’ Key ‘’ için en az bir ‘’ ValueProcessor ‘’ vermelisiniz. ‘’ ValueProcessor ‘’, ‘’ Keys ‘’ sınıfındaki ‘’ Key ‘’ sabit isminden sonra ‘’ DataQuery ‘’ ye benzer şekilde isimlendirilir. Sabit ismin üstü deve kuşağında kullanılan alt çizgiden sıyrılır ve ardından “Değer İşlemci” ile sonlandırılır.

ValueProcessor daima DataHolder type’ına göre kontrol yapan supports()``un bir kısmını karşılamış olan ``AbstractSpongeValueProcessor ile inherit edilmelidir. Keys.HEALTH için HealthValueProcessor değerini aşağıdaki gibi oluşturmalı ve contruct etmeliyiz.

public class HealthValueProcessor extends AbstractSpongeValueProcessor<EntityLivingBase, Double,
    MutableBoundedValue<Double> {

    public HealthValueProcessor() {
        super(EntityLivingBase.class, Keys.HEALTH);
    }

    [...]
}

Şimdi AbstractSpongeValueProcessor bizi değerin desteklenip desteklenmediğini kontrol etme gerekliliğinden kurtaracak. ValueContainer hedefi ``EntityLivingBase``in bir türü ise desteklendiğini gösterir.

Tüyo

Hangi EntityLivingBase öğelerinin desteklendiği ile ilgili daha etkili bir kontrol için, supports(EntityLivingBase) yöntemi iptal edilebilir.

Yine, çoğu işlem yardımcı uygulama tarafından tamamlandı. Bir Value ve onun değişmez kopyası verilerini almak, kaydetmek ve kaldırmak için bize iki yardımcı uygulama daha gerekiyor.

protected MutableBoundedValue<Double> constructValue(Double value) {
    return SpongeValueFactory.boundedBuilder(Keys.HEALTH)
        .minimum(DataConstants.MINIMUM_HEALTH)
        .maximum((double) Float.MAX_VALUE)
        .defaultValue(DataConstants.DEFAULT_HEALTH)
        .actualValue(value)
        .build();
}

protected ImmutableValue<Double> constructImmutableValue(Double value) {
    return constructValue(value).asImmutable();
}
protected Optional<Double> getVal(EntityLivingBase container) {
    return Optional.of((double) container.getHealth());
}

EntityLivingBase``in doğru çalışması mümkün olmadığı için, bu işlem asla geri dönmeyecektir ``Optional.empty().

protected boolean set(EntityLivingBase container, Double value) {
    if (value >= DataConstants.MINIMUM_HEALTH && value <= (double) Float.MAX_VALUE) {
        container.setHealth(value.floatValue());
        return true;
    }
    return false;
}

set() yöntemi değerin başarıyla ayarlanıp ayarlanamayacağını belirten bir mantıksal değeri gösterecektir. Bu uygulama, yukarıda yaptığımız değerli işlem yöntemlerimiz de kullanılan sınırların dışındaki değerleri reddedecektir.

public DataTransactionResult removeFrom(ValueContainer<?> container) {
    return DataTransactionBuilder.failNoData();
}

Verilerin daima mevcut olması garanti edildiği için kaldırma işleminiz onaylanamaz.

6. Kayıt İşlemcileri

Sponge bizim manpulatörlerimizi ve işlemcilerimizi kullanabilmesi için onları kaydettirmemiz gerekir. Bu org.spongepowered.common.data.SpongeSerializationRegistry sınıfında yapılır.``SetupSerialization`` yönteminde işlemcilerimizi eklediğimiz iki büyük kayıt bloğu vardır.

Veri İşlemcileri

DataProcessor, DataManipulator kullanmakta olduğu arayüz ve uygulama sınıflarının yanısıra kaydedilmektedir. Her değiştirilebilen / değiştirilemeyen DataManipulatorlar için minimum bir DataProcessor kaydedilmelidir.

dataRegistry.registerDataProcessorAndImpl(HealthData.class, SpongeHealthData.class,
    ImmutableHealthData.class, ImmutableSpongeHealthData.class,
    new HealthDataProcessor());

Değer İşlemcileri

Değer işlemcileri aynı işlevin en alt kısmında kayıt edilir. Her Key için birden çok işlemci registerValueProcessor() yönteminin sonraki çağrıları tarafından kaydedilir.

dataRegistry.registerValueProcessor(Keys.HEALTH, new HealthValueProcessor());
dataRegistry.registerValueProcessor(Keys.MAX_HEALTH, new MaxHealthValueProcessor());

Daha fazla bilgi

Sponge’da soyut bir kavram olan Data ile Minecraft sınıflarından kendisine gerekli verilerin nasıl bulunacağı üzerine genel talimatlar vermek zordur. Nasıl çalışması gerektiğini daha iyi anlamak için üzerinde çalışmakta olduğunuz işlemcilerle benzer şekilde önceden hazırlanmış işlemcilere göz atmanız yararlı olacaktır.

Eğer sıkışmışsanız veya bazı belli yönlerden emin değilseniz, ``#spongedev``IRC kanalını, forumları ziyaret ediniz veya GitHub üzerinde problem başlığı açınız. Genel katkı ihtiyaçları için Data Processor Implementation Checklist bölümünü kontrol ettiğinize emin olunuz.