Modding:World Access

From Vintage Story Wiki
Revision as of 23:59, 22 November 2024 by Nateonus (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Other languages:
Wrench-copper.png

This page is a candidate to be rewritten.
This page may use or reference older systems, and is due to be rewritten. Feel free to use it, but please be aware that its contents may not reflect the rest of the wiki.

This page was last verified for Vintage Story version 1.19.8.

Get and Set Blocks through the API

Let's Take our basic mod init code for a server mod

    public class SampleMod : ModSystem
    {
        ICoreServerAPI api;

        public override bool ShouldLoad(EnumAppSide side)
        {
            return side == EnumAppSide.Server;
        }


        public override void StartServerSide(ICoreServerAPI api)
        {
            this.api = api;
        }
    }

With this you can already start placing or reading blocks using the api object. Please note that mods are loaded before the world is loaded, so you cannot immediately access the world. Depending on what you want to achieve, you have to register to the appropriate event. For some examples in order to do something...

  • after the world has loaded you could register to the RunGame phase: api.Event.ServerRunPhase(EnumServerRunPhase.RunGame, OnRunGame);
  • during world generation we'd have to register to the appropriate world gen events.
  • when a player joins the game: api.Event.PlayerJoin += OnPlayerJoin;

Let's register to the player join event.

        public override void StartServerSide(ICoreServerAPI api)
        {
            this.api = api;
            api.Event.PlayerJoin += OnPlayerJoin;
        }

        private void OnPlayerJoin(IServerPlayer byPlayer)
        {
            
        }

Let's do 2 simple things whenever a player joins:

  • Always place some fire clay bricks just below his feet
  • Count the amount log blocks around the player in a 3 block radius

Now, blocks are always uniquely identified by a number of characters called the block code. If you want to find out a blocks code, a simple way of doing it is to start the game, enable the debug info mode via the command .edi and look at a block in the creative inventory:

Blockcode.png

So the code of a fire brick block is game:claybricks-fire. The first part before the colon is the domain, for the default domain 'game' we can usually ignore it.

We now have to retrieve it's number identifier for this particular world in order to get or set it. We do this as followed:

        private void OnPlayerJoin(IServerPlayer byPlayer)
        {
            Block firebrickblock = api.World.GetBlock(new AssetLocation("claybricks-fire"));
            int blockId = firebrickblock.BlockId;
        }

Now all we have to do is set the block right below the players position through the IBlockAccessor interface.

            BlockPos plrpos = byPlayer.Entity.Pos.AsBlockPos;
            api.World.BlockAccessor.SetBlock(blockId, plrpos.DownCopy());

We're using plrpos.DownCopy() to keep the original player position for later use and to move the position down by 1 for placing the block below the player.

And finally let's count the number of log blocks around the player and inform him via chat message.

            // Check a 7x7x7 area for logs
            int quantityLogs = 0;
            for (int x = -3; x <= 3; x++)
            {
                for (int y = -3; y <= 3; y++)
                {
                    for (int z = -3; z <= 3; z++)
                    {
                        Block block = api.World.BlockAccessor.GetBlock(new BlockPos(plrpos.X + x, plrpos.Y + y, plrpos.Z + z, plrpos.dimension));
                        
                        if (block.Code.Path.Contains("log"))
                        {
                            quantityLogs++;
                        }                        
                    }
                }
            }

            byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, "You have " + quantityLogs + " logs nearby you", EnumChatType.Notification);


Alternatively we could also use a shorthand method to have more elegant code.

            int quantityLogs = 0;
            api.World.BlockAccessor.WalkBlocks(
                plrpos.AddCopy(-3, -3, -3), 
                plrpos.AddCopy(3, 3, 3), 
                (block, x, y, z) => quantityLogs += block.Code.Path.Contains("log") ? 1 : 0
            );

            byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, "You have " + quantityLogs + " logs nearby you", EnumChatType.Notification);

And the complete code and final result:

        private void OnPlayerJoin(IServerPlayer byPlayer)
        {
            Block firebrickblock = api.World.GetBlock(new AssetLocation("claybricks-fire"));
            int blockId = firebrickblock.BlockId;

            BlockPos plrpos = byPlayer.Entity.Pos.AsBlockPos;
            api.World.BlockAccessor.SetBlock(blockId, plrpos.DownCopy());

            // Check a 7x7x7 area for logs
            int quantityLogs = 0;
            api.World.BlockAccessor.WalkBlocks(
                plrpos.AddCopy(-3, -3, -3),
                plrpos.AddCopy(3, 3, 3),
                (block, x, y, z) => quantityLogs += block.Code.Path.Contains("log") ? 1 : 0
            );

            byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, "You have " + quantityLogs + " logs nearby you", EnumChatType.Notification);

        }

SetblockTut.png


I hope this taught you the basics of accessing the world. More ways to access blocks and entities will be added here in the future.


Code Modding
Basics Code Mods Preparing For Code Mods Creating A Code Mod
Tutorials
Advanced Server-Client Considerations Setting up your Development Environment Advanced Blocks Advanced Items Block and Item Interactions Block Behavior Block Entity Particle Effects World Access Inventory Handling Commands GUIs Network API Monkey patching (Harmony)
Data Management VCDBS format Savegame Moddata ModConfig File Chunk Moddata Serialization Formats TreeAttribute
Worldgen WorldGen API NatFloat EvolvingNatFloat
Rendering Shaders and Renderers
Icon Sign.png

Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.

Modding
Modding Introduction Getting Started Theme Pack
Content Modding Content Mods Developing a Content Mod Basic Tutorials Intermediate Tutorials Advanced Tutorials Content Mod Concepts
Code Modding Code Mods Setting up your Development Environment
Property Overview ItemEntityEntity BehaviorsBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsCollectible BehaviorsWorld properties
Workflows & Infrastructure Modding Efficiency TipsMod-engine compatibilityMod ExtensibilityVS Engine
Additional Resources Community Resources Modding API Updates Programming Languages List of server commandsList of client commandsClient startup parametersServer startup parameters
Example ModsAPI DocsGitHub Repository