Modding:WorldGen API: Difference between revisions

From Vintage Story Wiki
No edit summary
Line 245: Line 245:
this.worldBlockAccessor = api.World.BlockAccessor;
this.worldBlockAccessor = api.World.BlockAccessor;
</syntaxhighlight>
</syntaxhighlight>
Next we will register a call back delegate to be passed the IBlockAccessor we need. Place this in OnServerStart.
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
this.api.Event.GetWorldgenBlockAccessor(OnWorldGenBlockAccessor);
this.api.Event.GetWorldgenBlockAccessor(OnWorldGenBlockAccessor);
</syntaxhighlight>
</syntaxhighlight>
Then add this method:
Then add this method to your class:
 
<syntaxhighlight lang="c#">
private void OnWorldGenBlockAccessor(IChunkProviderThread chunkProvider)
{
    chunkGenBlockAccessor = chunkProvider.GetBlockAccessor(true);
}
</syntaxhighlight>
Let's do a quick refactoring before we move on. Remember our PlaceTreasureChestInFrontOfPlayer method? The code in that to place the chest is going to be reused by our world gen code but we won't have a player in that case and we will also need to use a different IBlockAccessor to place our block. So let's refactor that to use a new method we call PlaceTreasureChest. So replace PlaceTreasureChestInFrontOfPlayer with the following.
<syntaxhighlight lang="c#">
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)
{
    PlaceTreasureChest(worldBlockAccessor, player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos);
}


private bool PlaceTreasureChest(IBlockAccessor blockAccessor, BlockPos pos)
{
    ushort blockID = api.WorldManager.GetBlockId("chest-south");
    Block chest = api.WorldManager.GetBlockType(blockID);
    chest.TryPlaceBlockForWorldGen(blockAccessor, pos, BlockFacing.UP);
    IBlockEntityContainer chestEntity = (IBlockEntityContainer)blockAccessor.GetBlockEntity(pos);
    if (chestEntity != null)
    {
        AddItemStacks(chestEntity, MakeItemStacks());
        System.Diagnostics.Debug.WriteLine("Placed treasure chest at " + pos.ToString(), new object[] { });
        return true;
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("FAILED TO PLACE TREASURE CHEST AT " + pos.ToString(), new object[] { });
        return false;
    }
}
</syntaxhighlight>
So what we did is make a PlaceTreasureChest that takes an IBlockAccessor and a BlockPos for placing the chest. The null check on chestEntity is probably not necessary however while developing this I found I was misusing the API by using the wrong IBlockAccessor so the null check helps detect this scenario and provides a more meaningful message than just a NullReferenceException so I suggest leaving this in. Also notice that we are printing a message to the console when a chest is placed. This is also optional however it's helpful for finding chests in the world when testing. Our PlaceTreasureChestInFrontOfPlayer method now calls our new method passing it the appropriate IBlockAccessor and the BlockPos 2 blocks in front of the player. Now that this refactoring has been done, we are ready to find a suitable spot to place our chests.


== Finding where to place the chest ==
== Finding where to place the chest ==
256

edits