lukas2005 Posted August 6, 2017 Posted August 6, 2017 Hello i want to save some data to world and i have the WorldSavedData implementation but i am not sure what i shloud fill in those functions and how to add data docs are not really too clear about that all they say is "The existing data can be obtained using MapStorage#getOrLoadData, and new data can be attached using MapStorage#setData". Wich does not really tell me much i have this code: package io.github.lukas2005.spymod; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.WorldSavedData; import net.minecraft.world.storage.MapStorage; public class MyWorldSavedData extends WorldSavedData { private static final String DATA_NAME = Reference.MOD_ID + "_MyWorldSavedData"; public MyWorldSavedData() { super(DATA_NAME); } @Override public void readFromNBT(NBTTagCompound nbt) { } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { return null; } public static MyWorldSavedData get(World world) { MapStorage storage = world.getMapStorage(); MyWorldSavedData instance = (MyWorldSavedData) storage.getOrLoadData(MyWorldSavedData.class, DATA_NAME); if (instance == null) { instance = new MyWorldSavedData(); storage.setData(DATA_NAME, instance); } return instance; } } Quote
Abastro Posted August 6, 2017 Posted August 6, 2017 You mean readFromNBT and writeToNBT? That's simple. readFromNBT: read from nbt to fill up the fields of WorldSavedData. writeToNBT: write to nbt with the fields of WorldSavedData. So basically, you save your fields to NBT using writeToNBT, and load it later using readFromNBT. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 6, 2017 Author Posted August 6, 2017 Ok now i have those classes now the only thing i am wondering about is to where but markDirty calls. The goal is to make a hashmap of all cameras in all dimensions in world that is synced to all clients and server and is saved to world file MyWorldSavedData: package io.github.lukas2005.spymod; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import net.minecraft.world.WorldSavedData; import net.minecraft.world.storage.MapStorage; public class MyWorldSavedData extends WorldSavedData { private static final String DATA_NAME = Reference.MOD_ID + "_MyWorldSavedData"; public MyWorldSavedData() { super(DATA_NAME); } @Override public void readFromNBT(NBTTagCompound nbt) { Camera.REGISTRY.clear(); NBTTagList list = (NBTTagList) nbt.getTag("CameraRegistry"); for (int i=0;i < list.tagCount();i++) { NBTTagCompound camnbt = (NBTTagCompound) list.get(0); Camera.registerCamera(new Camera(camnbt.getUniqueId("UUID")).readFromNBT(camnbt)); } } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { NBTTagList list = new NBTTagList(); for (Camera cam : Camera.REGISTRY.values()) { NBTTagCompound camnbt = new NBTTagCompound(); camnbt.setUniqueId("UUID", cam.getUUID()); cam.writeToNBT(camnbt); list.appendTag(camnbt); } nbt.setTag("CameraRegistry", list); Camera.REGISTRY.clear(); return nbt; } public static MyWorldSavedData get(World world) { MapStorage storage = world.getMapStorage(); MyWorldSavedData instance = (MyWorldSavedData) storage.getOrLoadData(MyWorldSavedData.class, DATA_NAME); if (instance == null) { instance = new MyWorldSavedData(); storage.setData(DATA_NAME, instance); } return instance; } } Camera: package io.github.lukas2005.spymod; import java.util.HashMap; import java.util.UUID; import io.github.lukas2005.spymod.Network.CameraRegistryChangeMessage; import io.github.lukas2005.spymod.Network.CameraRegistryChangeMessage.Type; import io.github.lukas2005.spymod.Network.NetworkManager; import io.netty.buffer.ByteBuf; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fml.common.network.ByteBufUtils; public class Camera { public static HashMap<UUID, Camera> REGISTRY = new HashMap<UUID, Camera>(); private final UUID uuid; private String name; private UUID attachment; public Camera() { this.uuid = UUID.randomUUID(); } public Camera(UUID uuid) { this.uuid = uuid; } public Camera(UUID uuid, Object...data) { this.uuid = uuid; this.name = (String) data[0]; this.attachment = (UUID) data[1]; } public static Camera getCamera(UUID uuid) { return REGISTRY.get(uuid); } public static void registerCamera(Camera cam) { REGISTRY.put(cam.getUUID(), cam); NetworkManager.INSTANCE.sendToServer(new CameraRegistryChangeMessage(Type.ADD_CAMERA, cam.uuid)); } public static void registerCameraNoUpdate(Camera cam) { REGISTRY.put(cam.getUUID(), cam); } public static void unRegisterCamera(Camera cam) { REGISTRY.remove(cam.getUUID()); NetworkManager.INSTANCE.sendToServer(new CameraRegistryChangeMessage(Type.REMOVE_CAMERA, cam.uuid)); } public static void unRegisterCameraNoUpdate(Camera cam) { REGISTRY.remove(cam.getUUID()); } public static void unRegisterCamera(UUID cam) { REGISTRY.remove(cam); NetworkManager.INSTANCE.sendToServer(new CameraRegistryChangeMessage(Type.REMOVE_CAMERA, cam)); } public static void unRegisterCameraNoUpdate(UUID cam) { REGISTRY.remove(cam); } public String getName() { return name; } public Camera setName(String name) { this.name = name; NetworkManager.INSTANCE.sendToServer(new CameraRegistryChangeMessage(Type.UPDATE_CAMERA, getUUID(), name, null)); return this; } public Camera setNameNoUpdate(String name) { this.name = name; return this; } public UUID getAttachment() { return attachment; } public Camera setAttachment(UUID attachment) { this.attachment = attachment; NetworkManager.INSTANCE.sendToServer(new CameraRegistryChangeMessage(Type.UPDATE_CAMERA, getUUID(), null, attachment)); return this; } public Camera setAttachmentNoUpdate(UUID attachment) { this.attachment = attachment; return this; } public UUID getUUID() { return uuid; } public Camera writeToNBT(NBTTagCompound nbt) { nbt.setString("Name", getName()); nbt.setUniqueId("Attach", getAttachment()); return this; } public Camera readFromNBT(NBTTagCompound nbt) { setName(nbt.getString("Name")); setAttachment(nbt.getUniqueId("Attach")); return this; } public void writeToByteBuf(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, getName()); // New camera name ByteBufUtils.writeUTF8String(buf, ((UUID)getAttachment()).toString()); } public Camera readFromByteBuf(ByteBuf buf) { setName(ByteBufUtils.readUTF8String(buf)); // New camera name setAttachment(UUID.fromString(ByteBufUtils.readUTF8String(buf))); //New camera block pos attachment return this; } } CameraRegistryChangeMessage: package io.github.lukas2005.spymod.Network; import java.util.UUID; import io.github.lukas2005.spymod.Camera; import io.netty.buffer.ByteBuf; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class CameraRegistryChangeMessage implements IMessage { int type = 0; Type etype; Object[] data; public CameraRegistryChangeMessage() {} public CameraRegistryChangeMessage(Type type, Object...data) { switch(type) { case ADD_CAMERA: this.type = 0; break; case REMOVE_CAMERA: this.type = 1; break; case UPDATE_CAMERA: this.type = 2; break; } this.etype = type; this.data = data; } @Override public void fromBytes(ByteBuf buf) { switch(buf.readInt()) { case 0: this.etype = Type.ADD_CAMERA; data = new Object[1]; data[0] = UUID.fromString(ByteBufUtils.readUTF8String(buf)); break; case 1: this.etype = Type.REMOVE_CAMERA; data = new Object[1]; data[0] = UUID.fromString(ByteBufUtils.readUTF8String(buf)); // UUID of camera to remove break; case 2: this.etype = Type.UPDATE_CAMERA; data = new Object[3]; data[0] = UUID.fromString(ByteBufUtils.readUTF8String(buf)); Camera cam = new Camera((UUID) data[0]).readFromByteBuf(buf); data[1] = cam.getName(); data[2] = cam.getAttachment(); break; } } @Override public void toBytes(ByteBuf buf) { buf.writeInt(type); switch(etype) { case ADD_CAMERA: ByteBufUtils.writeUTF8String(buf, ((UUID)data[0]).toString()); break; case REMOVE_CAMERA: ByteBufUtils.writeUTF8String(buf, ((UUID)data[0]).toString()); break; case UPDATE_CAMERA: ByteBufUtils.writeUTF8String(buf, ((UUID)data[0]).toString()); //UUID of camera to update new Camera((UUID)data[0], (String)data[1], data[2]).writeToByteBuf(buf); break; } } public static class Handler implements IMessageHandler<CameraRegistryChangeMessage, IMessage> { @Override public IMessage onMessage(final CameraRegistryChangeMessage message, MessageContext ctx) { UUID uuid = (UUID)message.data[0]; switch(message.etype) { case ADD_CAMERA: if (!Camera.REGISTRY.containsKey(uuid)) { Camera.registerCameraNoUpdate(new Camera(uuid)); } break; case REMOVE_CAMERA: if (Camera.REGISTRY.containsKey(uuid)) { Camera.unRegisterCameraNoUpdate(uuid); } break; case UPDATE_CAMERA: if (Camera.REGISTRY.containsKey(uuid)) { String name = (String) message.data[1]; UUID attachment = (UUID) message.data[2]; Camera cam = Camera.REGISTRY.get(uuid); if (name != null) cam.setNameNoUpdate(name); if (attachment != null) cam.setAttachmentNoUpdate(attachment); } break; } NetworkManager.INSTANCE.sendToAll(message); return null; } } public static enum Type { ADD_CAMERA, REMOVE_CAMERA, UPDATE_CAMERA } } Quote
Abastro Posted August 6, 2017 Posted August 6, 2017 18 minutes ago, lukas2005 said: camnbt = (NBTTagCompound) list.get(0); You got something wrong here. 0 seems to be i instead Oh, and about markDirty, I forgot that! You should call it whereever you change WorldSavedData field value. In your case, it's whereever a camera changes. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Okay thank you I will try this when I'll turn my PC on because I am writing from phone now Quote
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Ok one thing how shloud i get world instance from my Camera class? Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 2 minutes ago, lukas2005 said: Ok one thing how shloud i get world instance from my Camera class? You can't. If you really need it, provide it on WorldEvent.Load . Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Ok now i did it but it does not save/load even added prints in writeNBT readNBT and markDirty functions looks like writeNBT and readNBT are not called shloud i call them manually?? Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 Before that, check if it's called. Use either breakpoint or print statements. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 (edited) Just now, Abastro said: Before that, check if it's called. Use either breakpoint or print statements. i arelady did that markDirty does gets called but those other 2 func dont Edited August 7, 2017 by lukas2005 Quote
FredTargaryen Posted August 7, 2017 Posted August 7, 2017 Interesting that the MySavedWorldData constructor can take no parameters. Forge complains when I try that. What works for me is: Message sent from client -> Message received on Server -> onMessage calls a method in MySavedWorldData that updates your HashMap. markDirty(); should be placed at the end of that last method. Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 Strange. Would you update your code? Just in case you don't know: markDirty calls should be on server side. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Ok i removed the markDirty call from all methods except my sync packet handler and added a constructor with String and still the same i think that i will just create a Github Repo instead of posting walls of code here Quote
FredTargaryen Posted August 7, 2017 Posted August 7, 2017 (edited) Don't remove it from all methods; just try putting it at the end of the method that updates your HashMap. Edit: Oh well if you can call markDirty on the MyWorldSavedData instance from the message handler, then I think we should see your code as it is now Edited August 7, 2017 by FredTargaryen Quote
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 ok heres the link https://github.com/lukas2005/Spy-Mod Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 1. For the worldsaveddata on map storage, you should only register it once(it's shared throughout worlds(. WorldEvent.Load is called every time the world is loaded, so you should find another event or check to allow only one world to load the data. Same for WorldEvent.Unload. 2. Why did you register the packet to both server and client? The logic should be on the server side. Client is only for the rendering and sending input to the server. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Just now, Abastro said: 2. Why did you register the packet to both server and client? The logic should be on the server side. Client is only for the rendering and sending input to the server. Because i need data about cameras on both server and client Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 1 minute ago, lukas2005 said: Because i need data about cameras on both server and client Just sync it from the server to the client, otherwise by editing client plauers could cheat. Client to server packet is mostly for sending the user input to the server. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 What about WorldEvent.Save? (see https://github.com/lukas2005/Spy-Mod/commit/bb83d4d746a239b5aca2e53b15658ce50878b115) im just worried that the registry and world saved data instances are gonna be trashed before it will get saved Quote
FredTargaryen Posted August 7, 2017 Posted August 7, 2017 If writeToNBT is getting called then your registry will save at the right time. Quote
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 but it does not get called and i dont know why! Quote
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 Just now, diesieben07 said: Please show where you call markDirty, I am not going to click through your whole code. https://github.com/lukas2005/Spy-Mod/blob/master/src/main/java/io/github/lukas2005/spymod/Network/CameraRegistryChangeMessage.java#L105 Quote
lukas2005 Posted August 7, 2017 Author Posted August 7, 2017 3 minutes ago, diesieben07 said: Oh god. No, no no no. You must obtain the WorldSavedData instance from the World, you can't just stuff it into some random static field. fixed that and still nothing Quote
Abastro Posted August 7, 2017 Posted August 7, 2017 1. Don't reference Minecraft in the packet - it will crash on dedicated server. 2. Why bidirectional packet? No need to send it from client to server. Just move all non-rendeing logics to the server, and only send packet from client to server. 3. So you have the item ItemCamera to represent the camera. Why to have separate registry. 4. Certainly this is not the way to go; don't put the registry as WorldSavedData. Also don't make static reference of it. (It means it won't be loaded on time. Also WorldEvent are only called on server. So client-side one won't exist. Try running dedicated server to try this) 5. What's the supposed function of the camera and the monitor? Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
Recommended Posts
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.