Data Manipulator

Mengakses dan memodifikasi data

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).

Contoh Kode: Penyembuhan dengan manipulator data

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.

Jika data kesehatan ada, sekarang berisi salinan yang tidak tetap dari data yang ada pada pemegang data. Kita membuat perubahan dan akhirnya menawarkan penggantian data kembali ke sasaran kita, yang diterima (lagi, offer() yang akan mengembalikan DataTransactionResult yang akan kita abaikan dalam contoh ini dan kembali ke at a later point).

Seperti yang dapat anda lihat, hasil untuk health() dan maxHealth()``lagi-lagi merupakan nilai kunci yang kita peroleh dari :javadoc:`DataHolder`. Sebagai :javadoc:`MutableBoundedValue` kita menerima panggilan ``health() lagi yang berisi salinan data, yang perlu kita terapkan perubahan kembali ke DataManipulator sebelum kita dapat menawarkan healthData kembali ke sasaran kita.

Tip

Peraturan #1 dari Data API: Semua yang anda terima merupakan salinan. Jadi kapanpun anda mengubah sesuatu, pastikan bahwa yang anda ubah diterapkan kembali ke nilai aslinya berasal.

Modifikasi lain yang memungkinkan adalah sepenuhnya menghapus DataManipulator. Ini dapat dilakukan melalui metode remove() yang menerima referensi kelas dari jenis DataManipulator untuk dihapus. Beberapa data tidak dapat dihapus dan upaya untuk melakukannya akan selalu mengembalikan tanda kegagalan DataTransactionResult. Kode berikut berupaya untuk menghapus nama pilihan dari yang diberikan DataHolder. Lagi-lagi, hasil transaksinya dibuang.

Contoh kode: menghapus nama tampilan kustom

import org.spongepowered.api.data.manipulator.mutable.DisplayNameData;

public void removeName(DataHolder target) {
    target.remove(DisplayNameData.class);
}

Datamanipulator Vs, tombol

Jika Anda membandingkan kedua contoh penyembuhan kami, mungkin Anda bertanya-tanya 'Mengapa repot-repot dengan manipulator data, kunci menjadi lebih mudah' dan benar - untuk mendapatkan dan menetapkan nilai tunggal. Tapi manfaat sebenarnya dari manipulator data adalah data berisi semua data yang berkaitan dengan komponen tertentu. Mari kita lihat contoh lain.

Contoh Kode: Menukar dua data pemegang kesehatan

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.

Kemudian kami hanya menawarkan data kesehatan yang tersimpan ke target lainnya, sehingga mengubah status kesehatan mereka satu sama lain.

Contoh ini diselesaikan dengan Keys yang akan memakan waktu lebih lama dan lebih rumit karena kita akan mengurus kunci individu masing-masing oleh kita sendiri. Dan daripada kesehatan kita menukar data manipulator lain yang berisi bahkan lebih data (mungkin berisi daftar InvisibilityData), yang akan memiliki banyak pekerjaan untuk dilakukan. Tetapi sejak pemegang data itu sendiri mengurus semua data yang berkaitan dengan itu, kita bahkan dapat mengubah fungsi di atas untuk menukar data sewenang-wenang di antara dua pemegang.

Contoh Kode: Penyembuhan dengan manipulator data

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

Kemampuan untuk menulis fungsi yang dapat menukar data pada dudukan data dengan data yang sama pada dudukan data lain menunjukkan tujuan perancangan inti API data: kompatibilitas maksimum di API.

Data Manipulator Tidak Tetap vs Tetap

Untuk setiap manipulasi data, ada yang cocok :javadoc: ImmutableDataManipulator. Misalnya, HealthData dan :javadoc: ImmutableHealthData berisi data yang sama, hanya yang terakhir mengembalikan kasus baru saat meminta data yang dimodifikasi.

Konversi antara data manipulator yang tetap dan tidak tetap diselesaikan melalui metode asImmutable() dan asMutable(), yang masing-masing akan mengembalikan salinan data. Satu-satunya cara untuk memperoleh data manipulator yang tetap dari pemegang data adalah memperoleh satu yang tetap lalu menggunakan asImmutable().

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.

Data absen

Seperti yang telah disebutkan di atas, metode get() mungkin mengembalikan Optional kosong jika salah satu dari ini benar:

  • DataHolder tidak mendukung pemberian DataManipulator

  • DataHolder mendukung DataManipulator, tetapi saat ini tidak memegang data jenis tersebut

Ada perbedaan semantik besar antara data tidak hadir dan data yang terdiri dari nilai default. Sedangkan yang kedua selalu mungkin, ada kasus-kasus yang mana ianya mustahil untuk DataHolder untuk mendukung jenis data dan kemudian tidak tahan. Contoh yang meliputi:

  • HealthData selalu ada pada setiap (vanilla) DataHolder yang mendukung

  • DisplayNameData selalu ada pada Player, tetapi mungkin tidak ada pada entitas lainnya.