This section details the content and implementation of the Cacheable Value interface from a developer perspective.
Welcome
The Cacheable Value is a type of key-wrapper hybrid. It serves to hold a generic type and provide a value of this type through a key-function map.
Structure
The CacheableValue
interface accepts a generic argument that represents its data type. For example, CacheableValue<Integer>
holds an integer value. The interface has the following methods, where V
denotes its generic type:
Modifiers and Type | Method/Field and Description |
---|---|
V |
get(ServerPlayerEntity player) When the player is online, gets the value from the player. When the player disconnects, this is used to cache the value on the server. |
V |
readFromNbt(NbtCompound tag) Reads the value from nbt. |
void |
writeToNbt(NbtCompound tag, Object value) Writes the value to nbt. |
Identifier |
id() Returns this value’s ‘key’: should be in the form modid:key . Example: opc:current_health . |
Example Implementation
For every value or piece of data that a mod wishes to cache, they must create a new CacheableValue
implementation. The following is an example:
import com.github.clevernucleus.opc.api.CacheableValue;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
public class CurrentHealthValue implements CacheableValue<Float> {
private final Identifier id;
public CurrentHealthValue() {
this.id = new Identifier("opc:current_health");
}
@Override
public Float get(ServerPlayerEntity player) {
return (float)player.getHealth();
}
@Override
public Float readFromNbt(NbtCompound tag) {
return tag.getFloat("CurrentHealth");
}
@Override
public void writeToNbt(NbtCompound tag, Object value) {
tag.putFloat("CurrentHealth", (Float)value);
}
@Override
public Identifier id() {
return this.id;
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(!(obj instanceof CurrentHealthValue)) return false;
CurrentHealthValue currentHealthValue = (CurrentHealthValue)obj;
return this.id.equals(currentHealthValue.id);
}
@Override
public int hashCode() {
return this.id.hashCode();
}
@Override
public String toString() {
return this.id.toString();
}
}
Notes
- It is important that a valid
#equals
method is also implemented, as this is used to differentiate between cacheable values. Note that simply callingthis.id#equals
is not okay here, as this checks that the input is of the typeIdentifier
, which it is not. - This implementation will cache players’ current health when they disconnect, and provide this value if they are offline, or the current current health if they are online.
- You should try to ensure that the appropriate type is used in your generic. In the example above,
Float
is used because the return type ofplayer#getHealth
isfloat
. UsingInteger
here would not be appropriate as you would lose data, and usingDouble
here would also not be appropriate because the extra precision is not utilised.