Jump to content

[1.8] Generating new block types in existing (pre-generated) worlds


Recommended Posts

Posted

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

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

Posted

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?

Posted

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.

Posted

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.

Posted

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.

Posted

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!

Posted

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.

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

Posted

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.

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.