Modding:WorldGen API: Difference between revisions

From Vintage Story Wiki
Line 283: Line 283:


== Finding where to place the chest ==
== Finding where to place the chest ==
Now we are ready to place code in our OnChunkColumnGeneration to find a suitable spot for our chest. We are going to set up a nested for loop to loop through each x,y,z location in the chunk and see if that spot is beside a tree. Before we set up our loop we are going to add a few more variables at the top of our class.  
Now we are ready to place code in our '''OnChunkColumnGeneration''' to find a suitable spot for our chest. We are going to set up a nested for loop to loop through each x,y,z location in the chunk and see if that spot is beside a tree. Before we set up our loop we are going to add a few more variables at the top of our class.  
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
private const int MAX_CHESTS_PER_CHUNK = 1;
private const int MAX_CHESTS_PER_CHUNK = 1;
Line 290: Line 290:
private ISet<string> treeTypes;
private ISet<string> treeTypes;
</syntaxhighlight>
</syntaxhighlight>
They are mostly self explanatory. The first one indicates how many chests we are going to allow to be placed per chunk. CHEST_SPAWN_PROBABILITY is a probability of placing a chest in the current chunk at all. chunkSize is just stored as a convenient way to access chunkSize. To initialize it we need the following in StartServerSide:
They are mostly self explanatory. The first one indicates how many chests we are going to allow to be placed per chunk. '''CHEST_SPAWN_PROBABILITY''' is a probability of placing a chest in the current chunk at all. '''chunkSize''' is just stored as a convenient way to access the chunk size. To initialize it we need the following in '''StartServerSide''':
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
this.chunkSize = worldBlockAccessor.ChunkSize;
this.chunkSize = worldBlockAccessor.ChunkSize;
</syntaxhighlight>
</syntaxhighlight>
Make sure to add this after you set worldBlockAccessor!
Make sure to add this after you set '''worldBlockAccessor'''!


I'll explain the treeTypes variable in a bit. Just add it for now.
I'll explain the '''treeTypes''' variable in a bit. Just add it for now.


Replace the empty OnChunkColumnGeneration with the following:
Replace the empty '''OnChunkColumnGeneration''' with the following:
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ)
private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ)
Line 352: Line 352:
}
}
</syntaxhighlight>
</syntaxhighlight>
We've added a couple of methods here that I'll explain first. The ShouldPlaceChest method simply generates a random number between 0 and 100. If the number is between 0 and our CHEST_SPAWN_PROBABILITY multiplied by 100 then it returns true. This is called before we do our loop to see whether we should proceed in placing our chest. We will fill in the details of TryGetChestLocation in the next section so just leave it for now. The loop goes through each x, z then y coordinate and converts the coordinates to world coordinates by multiplying the chunkX coordinate by the chunkSize and adding our x coordinate in the loop. The same goes for Z. This is very important! Our IBlockAccessor expects world coordinates. World coordinates start at the beginning of the world whereas chunk coordinates start at the beginning of the chunk. Always keep your coordinate system in mind. Another thing to note here is that BlockPos is created outside our loop and reused to cut down on object creation. You don't want to create a ton of objects and cause garbage collection because this will negatively impact performance. Try to create as few objects as you can in code that will be executed frequently. The meat of the code calls our TryGetChestLocation to get a BlockPos. If the method returns null that means the current x,y,z is not a suitable location. However if it is then it moves on to our PlaceTreasureChest and increments the chestsPlaced counter which is used to check and make sure we aren't placing more chests in the chunk than MAX_CHESTS_PER_CHUNK.
We've added a couple of methods here that I'll explain first. The '''ShouldPlaceChest''' method simply generates a random number between 0 and 100. If the number is between 0 and our '''CHEST_SPAWN_PROBABILITY''' multiplied by 100 then it returns true. This is called before we do our loop to see whether we should proceed in placing our chest. We will fill in the details of '''TryGetChestLocation''' in the next section so just leave it for now. The loop goes through each x, z then y coordinate and converts the coordinates to world coordinates by multiplying the '''chunkX''' coordinate by the '''chunkSize''' and adding our x coordinate in the loop. The same goes for Z. This is very important! Our '''IBlockAccessor''' expects world coordinates. World coordinates start at the beginning of the world whereas chunk coordinates start at the beginning of the chunk. Always keep your coordinate system in mind. Another thing to note here is that '''BlockPos''' is created outside our loop and reused to cut down on object creation. You don't want to create a ton of objects and cause garbage collection because this will negatively impact performance. Try to create as few objects as you can in code that will be executed frequently. The meat of the code calls our '''TryGetChestLocation''' to get a '''BlockPos'''. If the method returns null that means the current x,y,z is not a suitable location. However if it is then it moves on to our '''PlaceTreasureChest''' and increments the '''chestsPlaced''' counter which is used to check and make sure we aren't placing more chests in the chunk than '''MAX_CHESTS_PER_CHUNK'''.
 
Our loop and main logic is finished. Now it's time to implement TryGetChestLocation to detect trees.


Our loop and main logic is finished. Now it's time to implement '''TryGetChestLocation''' to detect trees.


== Detecting trees ==
== Detecting trees ==
256

edits