Posted April 21, 201510 yr Hi! I'm writing a mod that implements new ore. Rather than just have the ore get generated in new chunks, I'd like servers to be able to use it on their existing maps, as well. Here's the pseudocode for the approach I'm thinking of -- looking for critique / flaws! I'm particularly wondering about methods for storing data to disk -- is there a mechanism in the vanilla code to store mod-related metadata along with the rest of the world state? COMPONENT 1: Keep track of which chunks have the new ore: preInitialization() { HashTable<ChunkCoordIntPair> chunksWithNewOre; chunksWithNewOre = modSpecificRepository.readFromDisk(); } COMPONENT 2: Modify standard ore generator (registered with GameRegistry.registerWorldGenerator()) to keep track as well: generateNewOre( chunk ) { typical_ore_generation( chunk ); chunksWithNewOre.put( chunk.chunkPos ); modSpecificRepository.writeToDisk( chunksWithNewOre ); } COMPONENT 3: Generate ore in all existing chunks as they load: @EventHandler newChunkLoaded( ChunkLoadEvent ) { // if this chunk has NOT had its terrain populated already, that means it's a brand new chunk being generated // (as opposed to loaded from disk). http://minecraft.gamepedia.com/Chunk_format if( !event.chunkData.TerrainPopulated ) brand_new_chunk = true; // If this IS a new chunk being generated, regular terrain/ore generation mechanisms will kick in, so we don't need to do anything special if( brand_new_chunk ) return; // Additionally, if we've *already* put the new ore in this chunk, there's nothing to do either if( completedChunks.get(event.chunkData.pos) ) return; // this is a previously-existing chunk which has not yet had the new ore added! generateNewOre( chunk ); }
April 21, 201510 yr is there a mechanism in the vanilla code to store mod-related metadata along with the rest of the world state? ChunkDataEvent.Save ChunkDataEvent.Load 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.
April 21, 201510 yr Author Thanks Draco. I know I can use those events to find out when the server is going to save/load a chunk... what I'm wondering is if/how I can edit the payload of what's being saved. For example, can I add my own arbitrary fields to the chunk's NBTTagCompound when I'm handling the Save event? Will that screw anything else up in the vanilla code if I do that?
April 21, 201510 yr Those events have a getData() method which returns, unsurprisingly, the chunk's 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.
April 21, 201510 yr Author Right, I saw that :-) What I am wondering is if adding my own data to that would violate underlying assumptions in the vanilla code and break things... or if those extra NBT values would just be happily ignored by the vanilla code. Another question on this approach -- are Forge events synchronous or asynchronous? If they're asynchronous, then even if I did modify the chunk payload in the ChunkDataSave event, there's no guarantee my modification would complete before the save executed.
April 21, 201510 yr NBT is key->value. Don't know, or don't use, the key? You don't get the value. 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.
April 21, 201510 yr I believe that the saves are sort of triggered by setting the chunk's isModified field to true. So I think you're safe in terms of asynchronicity if you do your substitutions then set chunk to isModified at end -- it should then save the result of all your subs. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
April 21, 201510 yr Author NBT is key->value. Don't know, or don't use, the key? You don't get the value. I see. Yeah, that is probably pretty safe. tterrag tells me on IRC that events are synchronous, so it sounds like storing the metadata during the ChunkDataSave event will work! Thanks for the tip... that'll be much cleaner. I believe that the saves are sort of triggered by setting the chunk's isModified field to true. So I think you're safe in terms of asynchronicity if you do your substitutions then set chunk to isModified at end -- it should then save the result of all your subs. Thanks -- good to have this as an alternate strategy!
April 21, 201510 yr Note: Chunk load/unload is threaded. Be sure to use a thread-safe HashTable ( ConcurrentHashMap I know exists, so there's likely a ConcurrentHashTable as well). 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.
April 21, 201510 yr Also note: Just using ConcurrentHashMap won't magically safe you from errors caused by multithreading. Concurrent in the name just means that you can't break the map itself by shooting at it from different threads (if you do that with a HashMap your code can crash, run into infinite loops and all sorts of unpredictable things). It does NOT mean that your own code that just uses the map is also magically threadsafe. This is true. 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.
April 21, 201510 yr Author Thanks for the heads-up on the thread safety issues. Given Draco's suggestions I don't actually think I even need a Hashtable anymore. Instead of tracking which chunks have been completed in my own data structure, I can just read/store that in each chunk's NBT metadata during the load event. It appears the asynchronous phase of chunk loading is completed by the time the ChunkDataEvent fires, so I think that should be safe.
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.