Posted February 11, 20178 yr 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 February 11, 20178 yr by Viperdream
February 11, 20178 yr Author 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.
February 11, 20178 yr Author 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.
February 11, 20178 yr Author 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); } }
February 12, 20178 yr 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.
February 12, 20178 yr 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 Map, ChunkDataEvent.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. 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.