Posted July 5, 20223 yr Hey guys, I am trying to save a custom class in my tile entity`s NBT data. I think I figured out how to save it, but I don't know how to load it. Ingame Server class (Class that should be saved to nbt) Spoiler public class Server implements INBTSerializable { public enum ServerType{ CUSTOM } private boolean isOn = false; private ServerType serverType; private String ip; private BlockPos pos; private Database db; public Server(ServerType serverType, String ip, BlockPos pos, Database db){ this.serverType = serverType; this.ip = ip; this.pos = pos; this.db = db; } @Override public INBT serializeNBT() { CompoundNBT nbt = new CompoundNBT(); nbt.putBoolean("isOn", this.isOn); nbt.putInt("serverType", this.serverType.ordinal()); nbt.putString("ip", this.ip); nbt.put("pos", NBTUtil.writeBlockPos(this.pos)); nbt.put("db", this.db.serializeNBT()); return nbt; } @Override public void deserializeNBT(INBT compound) { CompoundNBT nbt = (CompoundNBT) compound; this.isOn = nbt.getBoolean("isOn"); this.serverType = ServerType.values()[nbt.getInt("")]; this.ip = nbt.getString("name"); this.pos = NBTUtil.readBlockPos(nbt); this.db = (Database) nbt.get("db"); } My tile entity class Spoiler public class ServerTile extends TileEntity { private Server server; public ServerTile(TileEntityType<?> tileEntityType) { super(tileEntityType); } public ServerTile(){ this(ModTileEntities.SERVER_TILE.get()); } @Override public void read(BlockState state, CompoundNBT nbt) { this.server = ... super.read(state, nbt); } @Override public CompoundNBT write(CompoundNBT nbt) { nbt.put("server", this.server.serializeNBT()); return super.write(nbt); } Thanks for your help
July 5, 20223 yr you can create a constructor with a CompoundNBT as parameter, inside the constructor you read the data and set the fields in this case your fields can be final (if you want that they are), then you can simply create a new instance the other option would be to add an empty constructor and then call Server#serializeNBT i personally prefer the first option but you could choose the option you want i would also recommend you to specify the INBT type in the type arguments of INBTSerializable last but not least i would recommend you to update to 1.18 since 1.16.5 will fall out of support in the next 2-3 days Edited July 5, 20223 yr by Luis_ST
July 5, 20223 yr Author Quote This doesn't look right. Thanks. I forgot to add the key ^^ Quote INBTSerializable only really works if you have a no-argument constructor, so you can create the instance. I would recommend to instead make a static factory method and not use INBTSerializable. Do you have an example?
July 5, 20223 yr 5 minutes ago, J3ramy said: Do you have an example? Spoiler public void save() { Foo foo = new Foo(10); CompoundTag tag = foo.serializeNBT(); // do stuff } public void load(CompoundTag tag) { Foo foo = new Foo(); foo.deserializeNBT(tag); } public class Foo implements INBTSerializable<CompoundTag> { protected int data; public Foo() { } public Foo(int data) { this.data = data; } @Override public CompoundTag serializeNBT() { CompoundTag tag = new CompoundTag(); tag.putInt("data", this.data); return tag; } @Override public void deserializeNBT(CompoundTag tag) { this.data = tag.getInt("data"); } } this is a simply example, but i would recommend to use a factory method or a constructor instead Note: create with mojang mappings
July 5, 20223 yr Author Thank you. I decided for the constructor way and changed the class to Spoiler public class Server { public enum ServerType{ CUSTOM } private boolean isOn = false; private boolean isSet = false; private final ServerType serverType; private final String ip; private final BlockPos pos; private final Database db; public Server(CompoundNBT nbt){ this.isOn = nbt.getBoolean("isOn"); this.isSet = nbt.getBoolean("isSet"); this.serverType = ServerType.valueOf(nbt.getString("serverType")); this.ip = nbt.getString("name"); this.pos = NBTUtil.readBlockPos(nbt); this.db = (Database) nbt.get("db"); } } But how am I supposed to save/load this in the tile entity write and read method? EDIT: I created a getData method in Server which returns a CompoundNBT containing the class data. Now, I do this in my tile entity: Spoiler @Override public void read(BlockState state, CompoundNBT nbt) { this.server = new Server(nbt); super.read(state, nbt); } @Override public CompoundNBT write(CompoundNBT nbt) { nbt.put("server", this.server.getData()); return super.write(nbt); } Edited July 5, 20223 yr by J3ramy
July 5, 20223 yr public void read(BlockState state, CompoundNBT nbt) { this.server = new Server(nbt.getCompound("server"); super.read(state, nbt); } You need to retrieve the subtag of the tile's nbt. The place where you put it. The read/write happens automatically. Except, if you change data for the tile, you need to call setChanged() so minecraft knows it needs to save it. Edited July 5, 20223 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 5, 20223 yr Quote Except, if you change data for the tile, you need to call setChanged() so minecraft knows it needs to save it. This also notifies neighbouring blocks they may need to do stuff. e.g. if you output a redstone signal any redstone would recalculate its signal strength. Edited July 5, 20223 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.