Skip to main content

Voxels

info

Texture and Model related APIs are only available on clients.

In Cubivox, voxels serve as the fundamental building blocks of the game world. These tiny, cubic units of space make up nearly every element in the game, from terrain to structures and objects. Each voxel represents the smallest possible division of the environment, and together, they form a rich and dynamic, fully interactive world for players to shape.

Voxel vs VoxelDef

When working with voxels, there are two key object types: Voxel and VoxelDef.

A VoxelDef (Voxel Definition) is responsible for defining the properties of a voxel, such as its name, texture, and functionality. Each type of voxel has exactly one corresponding VoxelDef instance.

On the other hand, a Voxel represents a specific voxel at the moment it is retrieved. Voxel objects are immutable and cannot be modified. There is only a single voxel definition object instance for each type of voxel.

Accessing and Setting Voxels

A Voxel can be accessed through a World or Chunk object:

// World:
Voxel vox = Cubivox.GetWorlds()[0].GetVoxel(15, 20, 15);

// Chunk:
Voxel chunkVoxel = chunk.GetVoxel(6, 3, 5);

It is important to note that World#GetVoxel() uses global coordinates while Chunk#GetVoxel() uses local coordinates. This means that the x, y, and z parameters of Chunk#GetVoxel() can only range between 0 and 15 (since chunks are 16x16x16 in size). The API modulates the input by 16, so inputing a value outside of that range will still have an effect.

Like accessing a Voxel, setting a Voxel is done through a World or Chunk object. Voxels are set by setting the VoxelDef for that voxel.

VoxelDefs can be retrived from the item registry by using the ControllerKey that represents the voxel definition.

var voxelDefKey = ControllerKey.Create("testmod", "custom_voxel");
VoxelDef customVoxel = Cubivox.GetItemRegistry().GetVoxelDefinition( voxelDefKey );

Since there is only ever one instance of a voxel definiton object, it is recommended to store the instance in a member variable to prevent needing to fetch it multiple times. This can help performance in certain scenarios.

You can then use that voxel definition to set a specific voxel:

// World:
Cubivox.GetWorlds()[0].SetVoxel(15, 20, 15, customVoxel);

// Chunk:
chunk.SetVoxel(6, 3, 5, customVoxel);

The same note about the coordinate systems above applies to setting voxels as well.

Creating Custom Voxels

Custom voxels ares made by defining a new voxel definition that defines the looks and behavior of the new voxel. This is done by extending the ModVoxel abstract class:

[Name("Custom Voxel")]
[Key("CUSTOM_VOXEL")]
[Texture("custom_voxel.png")]
public class CustomVoxel : ModVoxel
{
public CustomVoxel(Mod mod) : base(mod)
{
}
}

The properties of a voxel are defined using attributes above the class definition. Three attributes are required to create a custom voxel:

  • [Name("Custom Voxel")]: This defines the display name that the voxel will show in the game.
  • [Key("CUSTOM_VOXEL")]: This defines the key portion of the ControllerKey that is used to reference the voxel.
  • [Texture("custom_voxel.png")]: This defines what texture the voxel will use. See the section on textures below to learn more about voxel textures.
HINT

There is only a single instance of a voxel definition. Don't store information about individual voxels in the voxel defintion object.

Texturing

The image above is an example of a voxel texture. Each colored square represents a face of the voxel. The pink area is the void area and will not be visible.
The size of the image is not important as long as the ratios are maintained. Each voxel face must have a width that is 1/4 the width of the image and 1/3 the height.

Similar to the mod.json, the texture for a voxel is to be bundled with the mod's dll file.
The best way to accomplish that is to add your image to the project:

Then, right click the image and select Properties. Then change Build Action to Embedded resource.

note

The image will not be put in a Resources folder within the dll. So the texture attribute on the voxel should just be [Texture("custom_voxel.png")].

Transparent Textures

If there is any sort of transparency in the texture the [Transparent] attribute should be added with the other attributes. This prevents the mesh optimization that Cubivox performs on chunks from optimizing away the voxel faces around this voxel. Not adding this will cause players to be able to see inside chunks.

Voxel Events

Voxel events are a way to perform actions when a player interacts with a voxel. These events are known as local events, since they only trigger for a specific voxel type. Local events function similarly to global events, but are slightly different in the way they are registered.

public class CustomVoxel : ModVoxel
{
public CustomVoxel(Mod mod) : base(mod)
{
this.PlaceEvent += OnVoxelPlaced;
}

public void OnVoxelPlaced(VoxelDefPlaceEvent evt)
{
mod.GetLogger().Info($"Player {evt.Player.GetName()} placed a Custom Voxel!");
}
}

Local events use the C# event system, so to register an event of a certain type, the += operator is used on the desired event ModVoxel member veriable. The general format is {Event} += {HandlerMethod}. Only member methods should be registered to a local event.

Here is a table of all local events available to voxel definitions and their related event object:

Event NameEvent Object
PlaceEventVoxelDefPlaceEvent
BreakEventVoxelDefBreakEvent

Similiarly to global events, the [ServerOnly] and [ClientOnly] attributes can be used to only exectue the event on the server or clients respectively.

Registering Custom Voxels

To register a custom voxel for use, you must override the LoadItemsStage loading method within your main CubivoxMod class:

public class TestMod : CubivoxMod
{
public TestMod(ModDescriptionFile modDescriptionFile, Logger logger) : base(modDescriptionFile, logger)
{
}

public override void OnEnable()
{
}

public override void LoadItemsStage(ItemRegistry registry)
{
registry.RegisterItem(new CustomVoxel(this));
}
}

The voxel definition can then be accessed with:

var voxelDefKey = ControllerKey.Create("testmod", "custom_voxel");
VoxelDef customVoxel = Cubivox.GetItemRegistry().GetVoxelDefinition( voxelDefKey );