Show / Hide Table of Contents

Pieces and PieceTables

Pieces in Valheim are anything that can be built in the game, through means such as the Hammer, Cultivator, Hoe or your own custom tool items. This includes things such as plant sapplings, the workbench, and walls. In order for a prefab to be a piece, it must have the Piece component attached to the prefab.

Piece Tables in Valheim are connecting the buildable pieces to the tools used for building. They also define the build categories and if a tool can remove pieces again. In vanilla Valheim you only can use four building categories or none on a piece table. Jötunn adds the ability to use custom categories on vanilla tools or completely own categories on custom tool items. In order for a prefab to be a piece table, it must have the PieceTable component attached to the prefab.

Custom pieces and piece tables are handled by the PieceManager singleton.

This example requires assets to be loaded. The code snippets are taken from our example mod.

Note

You must only use names of existing prefabs. This can be prefabs you created, that have already been registered by another mod, or that already exist in the game.

Creating custom pieces

Custom pieces using PieceConfigs

Now we will load a new piece from an asset bundle. In order to better facilitate creation of pieces we have introduced the abstractions of PieceConfig's and RequirementConfig. These allow us to quickly and easily define common properties for pieces, such as the table they belong too, any restrictions or resources required.

private void Awake()
{
    AssetBundle pieceBundle = AssetUtils.LoadAssetBundleFromResources("pieces");

    PieceConfig cylinder = new PieceConfig();
    cylinder.Name = "$cylinder_display_name";
    cylinder.Description = "$cylinder_description";
    cylinder.PieceTable = PieceTables.Hammer;
    cylinder.CraftingStation = CraftingStations.Workbench;
    cylinder.Category = PieceCategories.Misc;
    cylinder.AddRequirement("Wood", 2);

    PieceManager.Instance.AddPiece(new CustomPiece(pieceBundle, "Cylinder", fixReference: false, cylinder));
}

To clone an existing pieces, they first have to be loaded by the game and are not available in Awake. Jötunn provides the PrefabManager.OnVanillaPrefabsAvailable event where vanilla prefabs are loaded. This event is called every time before a new is copied. This means we have to unregister after adding our custom pieces, because Jötunn already cached the custom piece.

private void Awake()
{
    PrefabManager.OnVanillaPrefabsAvailable += CreateDeerRugPiece;
}

private void CreateDeerRugPiece()
{
    PieceConfig rug = new PieceConfig();
    rug.Name = "$our_rug_deer_display_name";
    rug.PieceTable = PieceTableNames.Hammer;
    rug.Category = PieceCategoryNames.Misc;
    rug.AddRequirement("Wood", 2);

    PieceManager.Instance.AddPiece(new CustomPiece("our_rug_deer", "rug_deer", rug));

    // You want that to run only once, Jotunn has the piece cached for the game session
    PrefabManager.OnVanillaPrefabsAvailable -= CreateDeerRugPiece;
}

And here we have our final results:
Blue Print Rune Piece Table

As you can see in the screenshot the name and description are not yet localized. To read more about localization/translation head over to the localization tutorial pages.

Note

A PieceConfig has an empty array of requirements by default and doesn't change original requirements of that piece unless requirements were explicitely added to the PieceConfig object. So in case you really want to remove all requirements from a specific piece (for example a cloned vanilla piece), you have to do it manually: CustomPiece.Piece.m_resources = Array.Empty<Piece.Requirement>();

Adding custom piece table categories to vanilla tables

With PieceConfig's it is possible to add your pieces to a vanilla or even custom piece table category. For this example we create "empty" pieces (GameObjects with just a cube model and a Piece component) and add them to a new category "Lulzies" on the Hammer.

// Implementation of custom pieces from an "empty" prefab with new piece categories
private void AddPieceCategories()
{
    // load a test texture from out mod folder
    var testTexture = AssetUtils.LoadTexture("TestMod/Assets/test_tex.jpg");

    GameObject cube = PrefabManager.Instance.CreateEmptyPrefab("piece_lul");
    // Add our test texture to the Unity MeshRenderer
    cube.GetComponent<MeshRenderer>().material.mainTexture = testTexture;

    PieceConfig lulConfig = new PieceConfig();
    lulConfig.Name = "$piece_lul";
    lulConfig.Description = "$piece_lul_description";
    lulConfig.PieceTable = PieceTableNames.Hammer;
    lulConfig.Icon = RenderManager.Instance.Render(cube, RenderManager.IsometricRotation); // render a new icon at runtime
    lulConfig.ExtendStation = CraftingStations.Workbench; // Makes this piece a station extension
    lulConfig.Category = "Lulzies";  // Adds a custom category for the Hammer
    PieceManager.Instance.AddPiece(new CustomPiece(cube, false, lulConfig));
}

The result is a new category added to the piece table of the Hammer:
Custom Vanilla Categories

One of the pieces placed in the world:
Piece Stub Placed

Custom piece table

After loading our custom item, we will load a piece table GameObject from our example asset bundle, create a CustomPieceTable from it and add it to the PieceManager.

private void CreateRunePieceTable()
{
    GameObject tablePrefab = blueprintRuneBundle.LoadAsset<GameObject>("_BlueprintTestTable");
    CustomPieceTable CPT = new CustomPieceTable(tablePrefab);
    PieceManager.Instance.AddPieceTable(CPT);
}

Creating completely new categories using PieceTableConfigs

While adding pieces with custom categories to existing piece tables (such as the Hammer), you can also create custom items with piece tables using only custom categories. For that you will need to use PieceTableConfig's when creating a CustomPieceTable. This example is not used in our example mod but in our TestMod for Jötunn. Keep that in mind as you will not find the code in the example mod. We are still using the piece table of the example Blueprint Rune but this time add the custom pieces to own categories.

private void AddItemsWithConfigs()
{
    // Add a custom piece table with custom categories
    PieceTableConfig runeTable = new PieceTableConfig();
    runeTable.CanRemovePieces = false;
    runeTable.UseCategories = false;
    runeTable.UseCustomCategories = true;
    runeTable.CustomCategories = new string[] { "Make", "Place" };
    PieceManager.Instance.AddPieceTable(new CustomPieceTable(BlueprintRuneBundle, "_BlueprintTestTable", runeTable));

    // Create and add a custom item
    ItemConfig runeConfig = new ItemConfig();
    runeConfig.Amount = 1;
    runeConfig.AddRequirement("Stone", 1);
    // Prefab did not use mocked refs so no need to fix them
    var runeItem = new CustomItem(BlueprintRuneBundle, "BlueprintTestRune", fixReference: false, runeConfig);
    ItemManager.Instance.AddItem(runeItem);

    // Create and add custom pieces
    PieceConfig makeConfig = new PieceConfig();
    makeConfig.PieceTable = "_BlueprintTestTable";
    makeConfig.Category = "Make";
    var makePiece = new CustomPiece(BlueprintRuneBundle, "make_testblueprint", fixReference: false, makeConfig);
    PieceManager.Instance.AddPiece(makePiece);

    var placeConfig = new PieceConfig();
    placeConfig.PieceTable = "_BlueprintTestTable";
    placeConfig.Category = "Place";
    placeConfig.AllowedInDungeons = true;
    placeConfig.AddRequirement("Wood", 2);
    var placePiece = new CustomPiece(BlueprintRuneBundle, "piece_testblueprint", fixReference: false, placeConfig);
    PieceManager.Instance.AddPiece(placePiece);
}

The result is a tool with two completely custom categories:
Custom Piece Tables Categories

Translating your custom categories

You can provide localized versions of your custom categories. Please see our localization tutorial on how to do this.

  • Edit this page
☀
☾
In this article
Back to top
Generated by DocFX
☀
☾