Использование ключей
Getting and offering data using a key
A data holder provides methods to retrieve or alter a single point of data identified by a Key. Let’s just start out with an example:
Code Example: Healing a data holder, if possible
import org.spongepowered.api.data.DataHolder;
import org.spongepowered.api.data.key.Keys;
public void heal(DataHolder target) {
if (target.supports(Keys.HEALTH)) {
double maxHealth = target.get(Keys.MAX_HEALTH).get();
target.offer(Keys.HEALTH, maxHealth);
}
}
А теперь подробнее об указанной выше функции.
The first line checks if our given data holder supports a current health value. Only if it does, it can be healed after
all. Since a data holder cannot have current health without having a maximum health and vice versa, a check for
one of the keys using the supports()
method suffices.
Вторая строка использует функцию get()
для запроса к источнику данных о максимальном здоровье. Кроме метода get()
, есть так же getOrNull()
и getOrElse()
, все из которых принимают Key
как первый параметр. Обычно надо использовать get()
, которое выдаст Optional
запрашиваемых данных или Optional.empty()
если источник данных не поддерживает предоставленный ключ. Так как мы уже убедились, что Key
поддерживается, мы можем просто вызвать get()
без дальнейших проверок. Можно также использовать getOrNull()
, который является сокращенной версией вызова get(key).orNull()
, таким образом избавляясь от Optional
. Третьим вариантом будет getOrElse()
, который принимает значение по умолчанию как второй параметр для выдачи, если значения нет в источнике данных.
В третьей строке мы предлагаем возврат данных в источник данных. Мы предлагаем через Key
определить текущее здоровье и ранее полученное максимальное здоровье, таким образом вылечивая источник данных до полного здоровья. Есть несколько offer()
методов, принимающих различный набор параметров, все из которых выдают DataTransactionResult, содержащий информацию, если предложение было принято. На данный момент, мы будем использовать тот вариант, который принимает Key
и соответствующее значение, но мы продемонстрируем и другие на следующих страницах. Так как мы уже знаем, что наше предложение текущего здоровья принято (так как источник данных его поддерживает), мы можем молча сбросить результат.
Также можно полностью удалить данные из DataHolder, используя функцию remove()
. Просто предоставьте Key
, представляющий данные, которые вы хотите удалить. В примере ниже показана попытка удалить имя пользователя из указанного источника данных:
public void removeName(DataHolder target) {
target.remove(Keys.DISPLAY_NAME);
}
Преобразование данных
Есть также и другой способ взаимодействия с данными, кроме получения, изменения и выдачи значения. Используя методы transform()
источника данных, мы можем ввести Key
и Function
. Внутри будет получено значение ключа и применена указанная функция. Результат будет сохранён под данным ключом и метод transform()
выдаст соответствующий DataTransactionResult
.
Теперь, например, предположим, что мы хотим прокачать источник данных, увеличив максимальное здоровье в два раза.
import java.util.function.Function;
public void buff(DataHolder target) {
target.transform(Keys.MAX_HEALTH, new Function<Double,Double>() {
@Override
public Double apply(Double input) {
return (input == null) ? 0 : input * 2;
}
});
}
Or, if you use Java 8, you’re able to shorten the line with lambda expressions:
public void buff(DataHolder target) {
target.transform(Keys.MAX_HEALTH, d -> (d == null) ? 0 : 2*d);
}
Note that in both cases we need to make sure our passed function can handle null
. You will also notice that no
check has been performed if the target actually supports the Keys#MAX_HEALTH key. If a target does not
support it, the transform()
function will fail and return a DataTransactionResult
indicating so.
Keyed Values
There are cases where you may care about not only the direct value for a Key, but the keyed value
encapsulating it. In that case, use the getValue(key)
method instead of get(key)
. You will receive an
object inheriting from Value which contains a copy of the original value. As Keys#SPAWNABLE_ENTITIES
is a WeightedCollectionValue, we can get a list of potentional entity that could spawn using the Value
of the key.
Code Example: Bring a target to the brink of death
public void scare(DataHolder target) {
if (target.supports(Keys.NEXT_ENTITY_TO_SPAWN)) {
WeightedCollectionValue value = target.getValue(Keys.NEXT_ENTITY_TO_SPAWN).get();
List<Entity> entities = value.get(new Random());
}
}