Source: Decompiled from
HytaleServer.jar(pre-release2026.02.05-9ce2783f7)
Block masks control which blocks can be placed and which existing blocks can be replaced during prop placement. They are the final gate in the placement flow: after a position is validated by a scanner and pattern, the block mask determines if the actual block write is allowed.
Class: BlockMaskAsset
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
DontPlace |
MaterialSetAsset |
No | {} |
Set of materials that cannot be placed |
DontReplace |
MaterialSetAsset |
No | {} |
Set of materials that cannot be replaced |
Advanced |
BlockMaskEntryAsset[] |
No | [] |
Conditional replacement rules |
ExportAs |
string |
No | "" |
Name for Export/Import reuse |
Import |
string |
No | "" |
Name of exported block mask to import |
The built BlockMask has two key methods:
canPlace(material) — checks if a material is allowed to be placed:
- Returns
falseif the material is inDontPlace(skippedBlocks)
canReplace(source, destination) — checks if source block can replace destination block:
- Iterates through
Advancedentries: ifsourcematches an entry'sSourceset, returns whetherdestinationmatches that entry'sCanReplaceset - If no advanced entry matches, returns
trueunlessdestinationis inDontReplace(defaultMask)
Each Advanced entry defines a conditional replacement rule.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
Source |
MaterialSetAsset |
Yes | — | Materials this rule applies to (the block being placed) |
CanReplace |
MaterialSetAsset |
Yes | — | Materials that the source is allowed to replace |
{
"DontPlace": { "Materials": ["water"] },
"DontReplace": { "Materials": ["bedrock", "barrier"] },
"Advanced": {
"leaves_rule": {
"Source": { "Materials": ["leaves"] },
"CanReplace": { "Materials": ["air"] }
},
"stone_rule": {
"Source": { "Materials": ["stone"] },
"CanReplace": { "Materials": ["air", "dirt", "grass"] }
}
}
}In this example:
- Water blocks are never placed
- Bedrock and barrier blocks are never replaced (by any material without an Advanced rule)
- Leaf blocks can only replace air
- Stone blocks can replace air, dirt, or grass
A separate block mask system exists for prefab placement, using string-based filter syntax:
| Prefix | Filter Type | Description |
|---|---|---|
| (none) | TargetBlock |
The block itself |
> |
AboveBlock |
Block above |
< |
BelowBlock |
Block below |
~ |
AdjacentBlock |
Horizontally adjacent blocks |
^ |
NeighborBlock |
All 26 neighbors |
+n |
NorthBlock |
North neighbor (Z-1) |
+e |
EastBlock |
East neighbor (X+1) |
+s |
SouthBlock |
South neighbor (Z+1) |
+w |
WestBlock |
West neighbor (X-1) |
%xy |
DiagonalXy |
XY plane diagonals |
%xz |
DiagonalXz |
XZ plane diagonals |
%zy |
DiagonalZy |
ZY plane diagonals |
# |
Selection |
Selection bounds |
- Pipe-separated block names:
"stone|dirt|grass" - Inversion prefix:
"!stone"(matches anything except stone) - Multiple filters comma-separated:
"stone,>air"(stone block with air above) - Multiple masks semicolon-separated:
"stone,>air;dirt,>air"
"stone|dirt,>air,<bedrock"
→ Target is stone OR dirt, AND block above is air, AND block below is bedrock
Source files: BlockMaskAsset.java, BlockMaskEntryAsset.java, BlockMask.java, BlockFilter.java, MultiBlockMask.java, BlockMaskCondition.java