Utilización de Claves

Obtención y ofrecimiento de datos utilizando una clave

Un titular de datos proporciona métodos para recuperar o modificar un solo punto de los datos identificados por una :javadoc:`Clave`. Vamos a comenzar con un ejemplo:

Ejemplo de Código: Curación de un titular de datos, si es posible

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

Ahora para los detalles de la función anterior.

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.

La segunda línea utiliza la función get() para pedirle al titular de datos su máxima curación. Además de get(), el método getOrNull() y getOrElse() existen, todos acepten una Clave como su primer parámetro. Generalmente, get()``debería ser utilizado, devolverá un ``Opcional de los datos requeridos o Optional.empty() si el titular de los datos no soporta la clave suministrada. Ya que hemos verificado que la Clave es soportada, podemos solo llamar a get() en el Opcional sin comprobaciones adicionales. También podríamos utilizar getOrNull() que es básicamente un atajo para llamar a get(key).orNull(), deshaciéndose así del Opcional. La tercera posibilidad sería el getOrElse(), que acepta un valor predeterminado como un segundo parámetro que se devolverá si el valor no está presente en el titular de datos.

En la tercera línea, ofrecemos los datos al titular de datos. Proporcionamos una Clave que denota la salud actual y la salud máxima adquirida anteriormente, así que cura al titular de datos para la completa salud. Hay una variedad de métodos offer() que aceptan diferentes conjuntos de parámetros, todos los que devuelven un DataTransactionResult que contiene información si la oferta fue aceptada. Por ahora, utilizaremos el único que acepta una Clave y un valor correspondiente, pero encontraremos más en las siguientes páginas. Debido a que ya sabemos que nuestra oferta de salud actual es aceptada (ya que el titular de datos lo soporta), podemos descartar silenciosamente el resultado.

También es posible eliminar completamente datos de un DataHolder utilizando la función remove(). Simplemente proporcione una Clave que represente los datos que quiere remover. El siguiente ejemplo intentará eliminar un nombre personalizado de un titular de datos dado:

public void removeName(DataHolder target) {
    target.remove(Keys.DISPLAY_NAME);
}

Transformación de Datos

Además de obtener, la modificación y oferta de un valor, hay otra manera de interactuar con datos. Utilizando un método transform() del titular de datos podemos pasar una Clave y una Función. Internamente, el valor de la clave será recuperado y la función dada se le aplicará. El resultado es entonces almacenado debajo de la clave y el método transform() devolverá un DataTransactionResult en consecuencia.

Ahora, como un ejemplo, imagine que queremos buffear un titular de datos duplicando su salud máxima.

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

O, si utiliza Java 8, es capaz de acortar la línea con expresiones lambda:

public void buff(DataHolder target) {
    target.transform(Keys.MAX_HEALTH, d -> (d == null) ? 0 : 2*d);
}

Tenga en cuenta que en ambos casos necesitamos asegurar que nuestra función aprobada puede manejar nulo. También notará que no se ha realizado ninguna verificación si el objetivo actualmente soporta la clave Keys#MAX_HEALTH. Si un objetivo no lo admite, la función transform() fallará y devolverá un DataTransactionResult que lo indica.

Valores Clave

Hay casos donde puede importarle no solo los valores directos de una Clave, sino los valores clave que lo encapsulan. En ese caso, utilice el método getValue(key) en lugar del get(key). Recibirá un objeto heredado de BaseValue que contiene una copia del valor original. Ya que sabemos que la salud actual es un MutableBoundedValue, podemos encontrar el mínimo valor posible y establecer la salud del objetivo solo un poquito por encima de eso.

Ejemplo de Código: Llevar un objetivo al borde de la muerte

import org.spongepowered.api.data.value.mutable.MutableBoundedValue;

public void scare(DataHolder target) {
    if (target.supports(Keys.HEALTH)) {
        MutableBoundedValue<Double> health = target.getValue(Keys.HEALTH).get();
        double nearDeath = health.getMinValue() + 1;
        health.set(nearDeath);
        target.offer(health);
    }
}

Again, we check if our target supports the health key and then obtain the keyed value. A MutableBoundedValue contains a getMinValue() method, so we obtain the minimal value, add 1 and then set it to our data container. Internally, the set() method performs a check if our supplied value is valid and silently fails if it is not. Calling health.set(-2) would not change the value within health since it would fail the validity checks. To finally apply our changes to the target, we need to offer the keyed value back to it. As a keyed value also contains the Key used to identify it, calling target.offer(health) is equivalent to target.offer(health.getKey(), health.get()).