Data Managers
Data Managers are used to define a new data type in the datapack. It offers automatic reload and broadcast from server to client.
We will work with a simple data:
public class MyData {
private String stringValue;
private int integerValue;
// getters and setters...
}You first need to create a simple DataManager like this:
public static final IDataManager<MyData> MY_DATA_MANAGER = IDataManager.builder(MyData.class, "mymod_mydata").build();It's recommended to store it in a static field as it will be used to access the data later.
IDataManager#Builder provide:
-
withDefaultset the default value to use. -
withIdSettertake aBiConsumer<T, ResourceLocation>to be called after the creation of a data to set its id it should look something like this:withIdSetter(MyData::setId). -
mergedallows you to create a composed data from al the occurrence of it in all the different datapacks (like tags do). You will need a merging function (Function<Stream<R>, T>whereRis the raw type before merging).
It exist in 3 version:- one that only take a mlerging function, in this one the raw and the working type must be the same.
- on that take a
Decoder(aka aCodec) for to parse the raw type. - the last one with a parsing function for the raw value:
Function<JsonElement, R>.
Finally you can create your own data manager by implementing the IDataManager interface.
Then you can simply need to send an IMC with the DataManager to inform DataPack Anvil of your DataManager.
private void enqueueIMC(InterModEnqueueEvent event) {
DataManagerIMC.enqueue(() -> new DataManagerIMC<>((new ResourceLoaction("mymod", "mydata"), MY_DATA_MANAGER).withCodec(MyData.CODEC));
}Finally you also need a serializer or a Codec.
You can find more resources about mojang codecs here:
If we wanted to use a serializer we would have done something like:
private void enqueueIMC(InterModEnqueueEvent event) {
DataManagerIMC.enqueue(() -> new DataManagerIMC<>((new ResourceLoaction("mymod", "mydata"), MY_DATA_MANAGER).withSerializer(
json -> {
MyData myData = new MyData();
myData.setStringValue(JSONUtils.getString(json, "stringValue"));
myData.setIntegerValue(JSONUtils.getInt(json, "integerValue"));
return myData;
}, buf -> {
MyData myData = new MyData();
myData.setStringValue(buf.readString());
myData.setIntegerValue(buf.readInt());
return myData;
}, (buf, myData) -> {
buf.writeString(myData.getStringValue());
buf.writeInt(myData.getIntegerValue());
}));
}Note: it is not required to create a json deserialization fonction if you are using a custom implementation of IDataManager or you are using a merged data manager with raw type.
It's strongly recommended to use a codec over a serializer.
DataPack Anvil provaide 2 events: DataManagerReloadEvent<T> and DataPackReloadCompletEvent.
-
DataManagerReloadEvent<T>is a generic event and will be fired once the data manager handling its type has been leaded/reloaded. -
DataPackReloadCompletEventis fired once all data from vanilla and DataPack Anvil has been loaded/reladed. Client side it is fired once all data from the server had been sychronized.
@DataHolder is an annotation that will automatically set a field with the corresponding data found in the pack. It's realy close to the forge @ObjectHolder.
You can use it like this:
@DataHolder("mymod:mydata") public static final MyData MY_DATA = null;It is important to note that if the data isn't present in the pack this will be null and may cause crash is someone remove it from the datapack.