Paint & Textures
Paint & Textures
Part of the 7DTD Modding Knowledgebase. Covers the block paint system, texture IDs, and how to apply paint from C#.
Overview
7DTD has a paint system that lets players apply surface textures to blocks. Each face of a block can be painted independently. Paint textures are referenced by integer IDs — not by arbitrary RGB colors.
For recoloring an entity's textures at runtime (vehicle repaint from a color picker), see Runtime Texture Tinting (entity repaint) — a completely different mechanism.
Applying Paint from C#
// Paint a single face
GameManager.Instance.SetBlockTextureServer(
position, // Vector3i
BlockFace.North, // which face
(byte)textureId, // 0–255 texture ID
0 // entity ID (0 = server/no player)
);
// Paint all faces the same
foreach (BlockFace face in new[] {
BlockFace.Top, BlockFace.Bottom,
BlockFace.North, BlockFace.South,
BlockFace.East, BlockFace.West })
{
GameManager.Instance.SetBlockTextureServer(position, face, (byte)textureId, 0);
}
Texture ID to Color Mapping
The game ships with a fixed set of paint textures referenced by integer IDs. PixelPaste maps pixel RGB values to the nearest texture ID using squared Euclidean distance in RGB space.
This mapping lives in PaintColorMap.cs. The palette was generated by averaging the RGB pixels of each texture image from the game data (painting.xml defines paint ID → texture ID; the texture PNGs live in ../7builder/game-data/textures/). All 155 non-hidden paint IDs from painting.xml are included.
To regenerate: parse
painting.xmlfor paint ID → TextureId, load each{TextureId}.png, compute average RGB, and emitPaintEntrylines.
Nearest-Color Matching
public static int FindClosestTextureId(Color32 pixel)
{
int bestId = 0;
float bestDist = float.MaxValue;
foreach (var entry in palette)
{
float dr = pixel.r - entry.r;
float dg = pixel.g - entry.g;
float db = pixel.b - entry.b;
float dist = dr*dr + dg*dg + db*db;
if (dist < bestDist)
{
bestDist = dist;
bestId = entry.textureId;
}
}
return bestId;
}
Transparency
Pixels with alpha below a threshold should be skipped (no block placed):
public static bool IsTransparent(Color32 pixel)
{
return pixel.a < 128;
}
Gotchas
Texture IDs are bytes (0–255) — cast to
bytewhen callingSetBlockTextureServer.
The palette covers all 155 paint IDs from vanilla
painting.xml. Colors are average RGB from the actual texture PNGs, which may not perfectly match in-game appearance due to lighting/normal maps.
SetBlockTextureServerapplies immediately on the server side. In singleplayer, server and client are the same process so this works fine.