Jump to content

Recommended Posts

Posted

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

}

 

Posted

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.

Posted

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

 

Posted
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.

Posted
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.

Posted

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

Posted

Before that, check if it's called. Use either breakpoint or print statements.

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

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

Posted (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 by lukas2005
Posted

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.

Posted

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.

Posted

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

Posted (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 by FredTargaryen
Posted

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.

Posted
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

Posted
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.

Posted
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

Posted

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?

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

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

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.

Announcements



×
×
  • Create New...

Important Information

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