Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.11.2] Using WorldSavedData


lukas2005
 Share

Recommended Posts

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;
	}	

}

 

Link to comment
Share on other sites

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.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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
		
	}
	
}

 

Link to comment
Share on other sites

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.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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 .

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

Strange. Would you update your code?

Just in case you don't know: markDirty calls should be on server side.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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 by FredTargaryen
Link to comment
Share on other sites

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.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.