Add player-read-write-nbt.java
Signed-off-by: Forgejo <forgejo@mctaylors.ddns.net>
This commit is contained in:
parent
458d951ab4
commit
f2b55452d5
1 changed files with 96 additions and 0 deletions
96
player-read-write-nbt.java
Normal file
96
player-read-write-nbt.java
Normal file
|
@ -0,0 +1,96 @@
|
|||
package org.example.examplemod.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
public abstract class PlayerEntityMixin {
|
||||
@Unique
|
||||
public List<MyObject> myList = new ArrayList<>();
|
||||
|
||||
// I recommend you read writeMyDataToNbt first before trying to understand readCustomDataFromNbt
|
||||
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
|
||||
public void readMyDataFromNbt(NbtCompound playerNbt, CallbackInfo ci) {
|
||||
// read our serialized list
|
||||
NbtList myListNbt = playerNbt.getList("MyList", NbtElement.COMPOUND_TYPE);
|
||||
|
||||
// iterate over its items
|
||||
for (int i = 0; i < myListNbt.size(); i++) {
|
||||
// construct the object we need to deserialize
|
||||
MyObject myObject = new MyObject();
|
||||
// read the serialized object
|
||||
NbtCompound myObjectNbt = myListNbt.getCompound(i);
|
||||
|
||||
// read properties that are supported and write them to our object
|
||||
myObject.mySupportedObject = myObjectNbt.getInt("MySupportedObject");
|
||||
// if mySupportedList was int[], we could've just used getIntArray, but since it's a List<Integer>, we have to do something else
|
||||
Arrays.stream(myObjectNbt.getIntArray("MySupportedList")).forEach(myInteger -> myObject.mySupportedList.add(myInteger));
|
||||
|
||||
// read properties that aren't supported
|
||||
MyAnotherObject myAnotherObject = new MyAnotherObject();
|
||||
NbtCompound myNotSupportedObjectNbt = myObjectNbt.getCompound("MyNotSupportedObject");
|
||||
myAnotherObject.myUuid = myNotSupportedObjectNbt.getUuid("MyUUID");
|
||||
|
||||
// write them to our object
|
||||
myObject.myNotSupportedObject = myAnotherObject;
|
||||
|
||||
// finally, add our constructed object to our list
|
||||
myList.add(myObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
|
||||
public void writeMyDataToNbt(NbtCompound playerNbt, CallbackInfo ci) {
|
||||
// create a new NBT record for our list
|
||||
NbtCompound myListNbt = new NbtCompound();
|
||||
|
||||
// you can use a regular for-loop if you want, there's no difference. FabricMC wiki uses Iterable#forEach so that's why it's used here
|
||||
myList.forEach(myObject -> {
|
||||
// create a new NBT record for our object
|
||||
NbtCompound myObjectNbt = new NbtCompound();
|
||||
// write properties that are supported
|
||||
myObjectNbt.putInt("MySupportedObject", myObject.mySupportedObject);
|
||||
myObjectNbt.putIntArray("MySupportedList", myObject.mySupportedList);
|
||||
|
||||
// write myNotSupportedObject, which doesn't have a method for reading/writing in NbtCompound
|
||||
NbtCompound myNotSupportedObjectNbt = new NbtCompound();
|
||||
myNotSupportedObjectNbt.putUuid("MyUUID", myObject.myNotSupportedObject.myUuid);
|
||||
|
||||
// you can nest NBT records infinitely
|
||||
myObjectNbt.put("MyNotSupportedObject", myNotSupportedObjectNbt);
|
||||
|
||||
// put our newly created record into the list record
|
||||
myListNbt.put("MyObject", myObjectNbt);
|
||||
});
|
||||
|
||||
// finally, put our list record into the player's NBT
|
||||
playerNbt.put("MyList", myListNbt);
|
||||
}
|
||||
}
|
||||
|
||||
// these classes are in the same file for simplicity sake. you should make them public and put them in their own files
|
||||
class MyObject {
|
||||
// the NbtCompound class has methods to write and read this object - putInt and getInt
|
||||
public int mySupportedObject = 0;
|
||||
// there are even some supported lists! this one uses putIntArray
|
||||
public List<Integer> mySupportedList = new ArrayList<>();
|
||||
// if there's no method in NbtCompound to handle your class,
|
||||
// you'll have to write their properties separately and, when reading, construct the objects using the written properties
|
||||
// just how are we currently doing with this object
|
||||
public MyAnotherObject myNotSupportedObject;
|
||||
}
|
||||
|
||||
class MyAnotherObject {
|
||||
public UUID myUuid;
|
||||
}
|
Loading…
Reference in a new issue