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.

La primera línea verifica si nuestro titular de datos dado soporta un valor de curación actual. Solo si lo hace, puede ser curado después de todo. Ya que un titular de datos puede tener la salud actual sin tener una máxima curación y viceversa, basta una verificación de una de las claves utilizando el método supports().

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

Nuevamente, verificamos si nuestro objetivo soporta la clave de salud y luego obtiene el valor clave. Un MutableBoundedValue contiene un método getMinValue(), por lo que obtenemos el valor mínimo, agregamos 1 y luego lo configuramos como nuestro contenedor de datos. Internamente, el método set() realiza una verificación si nuestro valor suministrado es válido y falla silenciosamente si no lo es. Llamar a health.set(-2) no cambiaría el valor dentro de salud ya que fallaría la verificación de validación. Para finalmente aplicar nuestros cambios al objetivo, necesitamos ofrecerle el valor clave de vuelta a él. Como un valor clave también contiene la Clave utilizada para identificarlo, llamar a target.offer(health) es equivalente a target.offer(health.getKey(), health.get()).