Jump to content

Recommended Posts

Posted (edited)

Hi

 

I'm trying to save a custom object, holding only primitive values, to a chunk. It adds more information to the chunk that I need for my mod.

The values are simple numbers that show the amount of player made pollution.
What I did was putting all the chunks into a hashmap (the chunk's coordinates converted to a string and my custom object as a value), then convert that hashmap to json and save it with NBT on the world map.

 

I soon found out that the string is simply too long to store and it won't load the objects. I also think this way is a bit too devious and that there must be an easier way.

 

I'm looking for a way so I can add a value to a chunk, this would be the best manner ,I think, and also save it to the chunk in the same way chunks are saved.

Or is there an easier way to save the hashmap I have to NBT?

 

I'm just not entirely sure how to go at this. If anyone could point me in the right direction, that'd be great.

 

Thanks

Edited by Viperdream
Posted

Ok, that should work.

Just a few questions. How do I make the ChunkPos the key of the NBTTag? Since it requires a string? Or do I somehow use the hashcode I can generate with that?

 

Also, I tried out a different method which seems to be working partly. But for some reason the NBT data doesn't persist when I restart Minecraft.

I've based myself on your Questology mod for the WorldSavedData extension class (thanks for that).

 

public class ChunkEcoValuesData extends WorldSavedData{
	
	private static final String IDENTIFIER = EcoBalance.MODID;
	
	private static String coords;
	private String jsonCv;
	
	public ChunkEcoValuesData(){
		super(IDENTIFIER);
	}
	public ChunkEcoValuesData(String id){
		super(id);
	}
	
	@Override
	public void readFromNBT(NBTTagCompound nbt) {
		jsonCv = nbt.getString(coords);
	}
	@Override
	public void writeToNBT(NBTTagCompound nbt) {
		System.out.println("[EcoBalance]: Saving to NBT...");
		nbt.setString(coords, jsonCv);
	}
	
	public String getJson(){
		System.out.println("Getting this json string: " + jsonCv);
		return jsonCv;
	}
	
	public void setJson(String json){
		this.jsonCv = json;
		System.out.println("Setting this json string: " + jsonCv);
		markDirty();
	}
	
	public void setCoords(String nCoords){
		coords = nCoords;
	}
	
	public static ChunkEcoValuesData get (World w, String chunkCoords){
		coords = chunkCoords;
		System.out.println("[EcoBalance] Getting data with coords: " + coords);
		
		ChunkEcoValuesData data = (ChunkEcoValuesData)w.perWorldStorage.loadData(ChunkEcoValuesData.class, IDENTIFIER);
		if(data == null){
			System.out.println("[EcoBalance] Data is null ");
			data = new ChunkEcoValuesData(coords);
			w.perWorldStorage.setData(IDENTIFIER, data);
		}
		return data;
	}

}

 

I'm a bit clueless here, because every time I set the value I mark it dirty. Shouldn't it save it then? I can see in the console that it passes the correct variable through, but yet it returns null when I restart Minecraft.

Posted

Ok, if I understand this right. Should something like this work?

 

	@SubscribeEvent
	public void onChunkSave(ChunkDataEvent.Save e){
		NBTTagCompound nbt = e.getData();
		nbt.setDouble("value1", 1);
		nbt.setDouble("val2", 1);
	}

 

So once the event launches I can get the NBTTagCompound from the chunk and then I simply add my values to the NBT tag? Will it save automatically with the chunk without me having to do anything else?

And to get the values I simply use the ChunkDataEvent.Load and call upon the NBTTagCompound to find my values?

 

Sorry for all the questions, you've been a great help so far. I've been at this for a day now trying out various methods.

Posted

This works like a charm, thanks a ton.

 

If anyone is wondering how my code looks like, here it is

 

	/**This saves the ChunkEcoValues object to the NBTTagCompound to its corresponding chunk
	 */
	@SubscribeEvent
	public void onChunkDataSave(ChunkDataEvent.Save e){
		NBTTagCompound nbt = e.getData();
		Chunk c = e.getChunk();
		ChunkEcoValues cv = Pollution.pollutedChunks.get(c);
		
		if(cv.getPassiveFactor() == null){
			cv.initDefault(c);
		}
		nbt.setDouble(passiveFactor, cv.getPassiveFactor());
		nbt.setDouble(originalPassive, cv.getActivePollution());
		nbt.setDouble(activePollution, cv.getActivePollution());
		nbt.setDouble(activeEco, cv.getActiveEco());
	}
	/**This loads the ChunkEcoValues from the NBTTagCompound from the chunk
	 */
	@SubscribeEvent
	public void onChunkDataLoad(ChunkDataEvent.Load e){ 
		if(!Pollution.pollutedChunks.containsKey(e.getChunk())){
			Chunk c = e.getChunk();
			NBTTagCompound nbt = e.getData();
			ChunkEcoValues cv = new ChunkEcoValues();
			
			cv.setChunk(c);
			cv.setPassiveFactor(nbt.getDouble(passiveFactor));
			cv.setOriginalPassive(nbt.getDouble(originalPassive));
			cv.setActivePollution(nbt.getDouble(activePollution));
			cv.setActiveEco(nbt.getDouble(activeEco));
			
			Pollution.pollutedChunks.put(c, cv);
		}else{	
			Chunk c = e.getChunk();
			ChunkEcoValues cv;
			
			cv.initDefault(c);
			
			Pollution.pollutedChunks.put(c, cv);
		}
	}

 

Posted

Or more clearly:

ChunkDataEvent.Save - save your data to NBT

ChunkDataEvent.Load - load your data from NBT

ChunkEvent.Unload - remove unused data from your runtime storage (likely a Map)

 

You need to do all three.  Save can happen any time, so it's not safe to purge runtime data at that point, and ChunkEvent.Load doesn't give you access to the NBT data.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

I have an example of something similar here, here and here.

 

I use a World capability (IChunkEnergyHolder) to store a Map containing the IChunkEnergy (which stores a single integer) for each chunk of the World. I use ChunkDataEvent.Load to read the IChunkEnergy from the chunk's NBT and store it in the Map, ChunkEvent.Load to create a default IChunkEnergy for the chunk if it doesn't have one and store it in the MapChunkDataEvent.Save to save the IChunkEnergy to the chunk's NBT and ChunkEvent.Unload to remove the IChunkEnergy from the Map.

 

The capability doesn't actually save any data itself, it only exists to hold the Map at runtime.

 

I use ChunkWatchEvent.Watch to send the IChunkEnergy to the client when a player starts watching a chunk. Whenever an IChunkEnergy's stored value changes, it's sent to all players watching the chunk.

  • Like 1

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

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.