Documents how to create custom blocks in Hytale plugins using asset packs and JSON definitions. Use when creating blocks, defining block JSON, configuring block textures, materials, gathering, block types, or setting up block asset folder structure. Triggers - block, create block, custom block, BlockType, block JSON, block definition, block texture, block material, DrawType, Gathering, block creation, asset pack, IncludesAssetPack, block item, Cube block, block sound, block particle.
Reference for creating custom blocks in Hytale plugins via asset packs and JSON item definitions with BlockType configuration.
Source: https://hytalemodding.dev/en/docs/guides/plugin/creating-block Related skills: For block components and ECS ticking behavior, see
hytale-ecs. For items and interactions, seehytale-items.
| Task | Approach |
|---|---|
| Enable asset packs | Set "IncludesAssetPack": true in manifest.json |
| Define a block | Create Server/Item/Items/<name>.json with a BlockType section |
| Set block texture | "Textures": [{ "All": "BlockTextures/<name>.png" }] |
| Set block material | "Material": "Solid" (or Liquid, NonSolid, etc.) |
| Set draw type | "DrawType": "Cube" (or Cross, Slab, Model) |
| Add localized name | Server/Languages/en-US/items.lang → <name>.name = Display Name |
| Set gathering/breaking | "Gathering": { "Breaking": { "GatherType": "...", "ItemId": "..." } } |
| Set block icon | "Icon": "Icons/ItemsGenerated/<name>.png" |
| Create an animated block | Use DrawType: "Model" and specify CustomModel, CustomModelAnimation, and CustomModelTexture. See the Animated Textures guide. |
Your plugin's manifest.json must declare asset pack inclusion:
{
"IncludesAssetPack": true,
"dependencies": ["Hytale:EntityModule", "Hytale:BlockModule"]
}
src/main/resources/
├── manifest.json
├── Server/
│ ├── Item/
│ │ └── Items/
│ │ └── my_new_block.json # Block definition
│ └── Languages/
│ └── en-US/
│ └── items.lang # Translations
└── Common/
├── Icons/ # Item icons
├── Blocks/
│ └── my_new_block/
│ └── model.blockymodel # Block model
└── BlockTextures/
└── my_new_block.png # Block texture
Not every block has a "block entity" (a ChunkStore ECS entity with components). Plain blocks are just block IDs in the chunk data. A block entity only exists when one has been explicitly created for that position \u2014 either by the engine (for blocks with engine-managed state) or by a plugin.
BlockModule.getBlockEntity(world, x, y, z) \u2014 lookup only. Returns null for plain blocks. Never auto-creates.hytale-ecs skill \u2014 "Block Entity Lookup and Creation".RefChangeSystem<ChunkStore, YourComponent>.Create Server/Languages/en-US/items.lang:
my_new_block.name = My New Block
my_new_block.description = My Description
The filename
itemsbecomes the translation key prefix, so"items.my_new_block.name"resolves toMy New Block.
Create Server/Item/Items/my_new_block.json:
{
"TranslationProperties": {
"Name": "items.my_new_block.name",
"Description": "items.my_new_block.description"
},
"Id": "My_New_Block",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/my_new_block.png",
"Categories": [
"Blocks.Rocks"
],
"PlayerAnimationsId": "Block",
"Set": "Rock_Stone",
"BlockType": {
"Material": "Solid",
"DrawType": "Cube",
"Group": "Stone",
"Flags": {},
"Gathering": {
"Breaking": {
"GatherType": "Rocks",
"ItemId": "my_new_block"
}
},
"BlockParticleSetId": "Stone",
"Textures": [
{
"All": "BlockTextures/my_new_block.png"
}
],
"ParticleColor": "#aeae8c",
"BlockSoundSetId": "Stone",
"BlockBreakingDecalId": "Breaking_Decals_Rock"
},
"ResourceTypes": [
{
"Id": "Rock"
}
]
}
To create blocks with animated textures, you use a custom model and an animation file instead of static textures. This involves setting DrawType to "Model" and providing paths to your assets.
For a complete guide, see the Animated Block Textures reference.
| Property | Description | Examples |
|---|---|---|
Material | Physics material type | "Solid", "Liquid", "NonSolid" |
DrawType | How the block is rendered | "Cube", "Cross", "Slab", "Model" |
Group | Block category group | "Stone", "Wood", "Sand" |
Flags | Additional block flags | {} (empty object for defaults) |
Gathering.Breaking.GatherType | Tool type needed to break | "Rocks", "Wood", "Sand" |
Gathering.Breaking.Quality | Minimum tool quality tier (int, default 0). Tool spec quality must be ≥ this. | 0, 1, 2 |
Gathering.Breaking.ItemId | Item dropped when broken | ID string matching the block's Id |
BlockParticleSetId | Particle effect when breaking | "Stone", "Wood", "Sand" |
Textures | Array of texture definitions | See Texture Configuration below |
ParticleColor | Break particle color | Hex color string "#aeae8c" |
BlockSoundSetId | Sound set for interactions | "Stone", "Wood", "Sand" |
BlockBreakingDecalId | Breaking animation decal | "Breaking_Decals_Rock" |
CustomModel | Path to a .blockymodel file (used with DrawType: "Model") | "VFX/Fire/Fire.blockymodel" |
CustomModelAnimation | Path to a .blockyanim file for the model | "Blocks/Animations/Fire/Fire_Burn.blockyanim" |
CustomModelTexture | Texture for the custom model | [{ "Texture": "VFX/Fire/Fire.png", "Weight": 1 }] |
Looping | Whether a CustomModelAnimation should loop | true |
For DrawType: "Cube", textures are defined as an array of objects. Use "All" to apply one texture to all faces, or specify per-face:
"Textures": [
{
"All": "BlockTextures/my_block.png"
}
]
Per-face texturing (when supported):
"Textures": [
{
"Top": "BlockTextures/my_block_top.png",
"Bottom": "BlockTextures/my_block_bottom.png",
"Side": "BlockTextures/my_block_side.png"
}
]
These properties are standard item fields that the block also uses:
| Property | Description |
|---|---|
TranslationProperties | Name and Description translation keys |
Id | Unique identifier for the item/block |
MaxStack | Maximum stack size in inventory |
Icon | Path to inventory icon image |
Categories | Array of category tags (e.g., "Blocks.Rocks") |
PlayerAnimationsId | Animation set when held (e.g., "Block") |
Set | Visual set grouping (e.g., "Rock_Stone") |
ResourceTypes | Array of resource type objects with Id field |
BlockChunk (obtained via chunkStore.getComponent(chunkRef, BlockChunk.getComponentType())) provides palette-based query methods that are O(unique block types), not O(chunk volume):
// Count all blocks of a specific type in this chunk (palette-based, cheap)
int count = blockChunk.count(blockTypeIndex);
// Map of blockTypeIndex → count for every type present (iterate unique types only)
Int2IntMap counts = blockChunk.blockCounts();
// Set of all block type indices present in the chunk
IntSet presentTypes = blockChunk.blocks();
// Fast existence check — no iteration
boolean hasWood = blockChunk.contains(blockTypeIndex);
Use these to cheaply detect whether a chunk's content has changed (e.g. compare a cached count against the current value) before doing an expensive per-block scan.
Id field is case-sensitive and must be unique across all items and blocks<lang-filename>.<key>.name — the .lang filename is the prefixIncludesAssetPack must be true in manifest — without it, Common/ assets are ignoredCommon/BlockTextures/, not Common/Textures/ItemId in Gathering.Breaking should match the block's Id for the block to drop itself when brokenlib/Server/ for existing block definitions to see all available property values