home / skills / mnkyarts / hytale-skills / hytale-custom-blocks

hytale-custom-blocks skill

/skills/hytale-custom-blocks

npx playbooks add skill mnkyarts/hytale-skills --skill hytale-custom-blocks

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
13.7 KB
---
name: hytale-custom-blocks
description: Create custom block types for Hytale with textures, physics, states, farming, and interactions. Use when asked to "add a custom block", "create a new block type", "make blocks farmable", "add block interactions", or "configure block physics".
metadata:
  author: Liam Robinson (MnkyArts)
  version: "1.0.0"
---

# Creating Custom Hytale Blocks

Complete guide for defining custom block types with all available properties and configurations.

## When to use this skill

Use this skill when:
- Creating new block types
- Configuring block rendering (textures, models)
- Setting up block physics (support, bouncy, climbable)
- Making blocks farmable with growth stages
- Adding crafting benches
- Defining block interactions
- Setting up block sounds and particles
- Managing block states

## Block Asset Structure

Blocks are defined as JSON assets in your plugin's asset pack:

```
my-plugin/
└── assets/
    └── Server/
        └── Content/
            └── BlockTypes/
                ├── my_custom_block.blocktype
                ├── my_crop.blocktype
                └── my_bench.blocktype
```

## Basic Block Definition

**File**: `my_custom_block.blocktype`

```json
{
  "DisplayName": {
    "en-US": "Custom Block"
  },
  "Description": {
    "en-US": "A custom block with special properties"
  },
  "DrawType": "Cube",
  "Texture": "MyPlugin/Textures/custom_block",
  "Material": "Stone",
  "Tags": {
    "Category": ["Building", "Decorative"]
  }
}
```

## Block Properties Reference

### Core Properties

| Property | Type | Description |
|----------|------|-------------|
| `DisplayName` | LocalizedString | Localized display name |
| `Description` | LocalizedString | Localized description |
| `Parent` | String | Inherit from another block type |
| `Tags` | Object | Category tags for filtering |

### Rendering Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `DrawType` | Enum | `Cube` | `Cube`, `Model`, `Empty` |
| `Texture` | String | - | Texture path for cube rendering |
| `TextureTop` | String | - | Top face texture |
| `TextureSide` | String | - | Side faces texture |
| `TextureBottom` | String | - | Bottom face texture |
| `Model` | String | - | Model asset for DrawType=Model |
| `Shader` | String | - | Custom shader |
| `Opacity` | Float | 1.0 | Block opacity (0-1) |
| `AlphaBlend` | Boolean | false | Enable alpha blending |
| `RandomRotation` | Boolean | false | Random Y rotation on place |
| `VariantRotation` | Enum | - | Rotation variant mode |
| `FlipType` | Enum | - | Random flipping mode |
| `RotationOffset` | Float | 0 | Rotation offset in degrees |

### Physics Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `Material` | String | - | Physics material type |
| `IsSolid` | Boolean | true | Collision enabled |
| `IsReplaceable` | Boolean | false | Can be replaced when placing |
| `HasGravity` | Boolean | false | Falls like sand |
| `BlockFaceSupport` | Object | - | Support provided to neighbors |
| `RequiredBlockFaceSupport` | Object | - | Support needed from neighbors |

### Movement Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `Climbable` | Boolean | false | Can be climbed (ladders) |
| `Bouncy` | Float | 0 | Bounce factor (0-1) |
| `Drag` | Float | 0 | Movement drag |
| `Friction` | Float | 1 | Surface friction |
| `SpeedMultiplier` | Float | 1 | Walk speed multiplier |

### Behavior Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `IsUsable` | Boolean | false | Right-click interaction |
| `IsStackable` | Boolean | true | Can be placed adjacent |
| `ItemId` | String | - | Item dropped when broken |
| `LightLevel` | Integer | 0 | Light emission (0-15) |
| `LightColor` | Color | white | Light color |
| `Flammable` | Boolean | false | Can catch fire |
| `FlammableSpread` | Integer | 0 | Fire spread rate |

## Draw Types

### Cube (Default)

Standard voxel block with 6-sided textures:

```json
{
  "DrawType": "Cube",
  "Texture": "MyPlugin/Textures/stone",
  "TextureTop": "MyPlugin/Textures/stone_top"
}
```

### Model

Custom 3D model:

```json
{
  "DrawType": "Model",
  "Model": "MyPlugin/Models/custom_model",
  "BoundingBox": "MyPlugin/BoundingBoxes/custom_box"
}
```

### Empty

Invisible block (air-like, for logic):

```json
{
  "DrawType": "Empty",
  "IsSolid": false
}
```

## Block Physics System

### Block Face Support

Define which faces provide support:

```json
{
  "BlockFaceSupport": {
    "Top": {
      "Type": "Full",
      "SupportStrength": 100
    },
    "Bottom": {
      "Type": "Full",
      "SupportStrength": 100
    },
    "North": { "Type": "Full" },
    "South": { "Type": "Full" },
    "East": { "Type": "Full" },
    "West": { "Type": "Full" }
  }
}
```

**Support Types**: `Full`, `Partial`, `None`, `Center`

### Required Support

Define what support the block needs:

```json
{
  "RequiredBlockFaceSupport": {
    "Bottom": [
      {
        "Type": "Full",
        "Match": "REQUIRED"
      }
    ]
  }
}
```

**Match Types**:
- `REQUIRED` - Must have this support
- `IGNORED` - Don't care
- `DISALLOWED` - Must NOT have this support

### Gravity Blocks

```json
{
  "HasGravity": true,
  "GravityDelay": 5,
  "PhysicsDrop": {
    "GatherType": "Shovel",
    "Drops": [
      {
        "Item": "minecraft:sand",
        "Quantity": 1
      }
    ]
  }
}
```

## Block Gathering/Breaking

### Breaking Configuration

```json
{
  "Gathering": {
    "Breaking": {
      "GatherType": "Pickaxe",
      "Power": 2,
      "Quality": 1,
      "Drops": [
        {
          "Item": "my_plugin:custom_ore",
          "Quantity": {
            "Min": 1,
            "Max": 3
          },
          "Chance": 1.0
        }
      ]
    },
    "Harvest": {
      "GatherType": "Hoe",
      "Quality": 1,
      "Drops": [
        {
          "Item": "my_plugin:seeds",
          "Quantity": 1
        }
      ]
    },
    "SoftBlock": {
      "Enabled": true,
      "Drops": [
        {
          "Item": "my_plugin:dust",
          "Quantity": 1
        }
      ]
    }
  }
}
```

**Gather Types**: `Hand`, `Pickaxe`, `Axe`, `Shovel`, `Hoe`, `Sword`

## Block States

Define different visual/behavioral states:

```json
{
  "States": {
    "powered": {
      "Values": ["true", "false"],
      "Default": "false"
    },
    "facing": {
      "Values": ["north", "south", "east", "west"],
      "Default": "north"
    }
  },
  "StateData": {
    "powered=true,facing=north": {
      "Model": "MyPlugin/Models/powered_north"
    },
    "powered=true,facing=south": {
      "Model": "MyPlugin/Models/powered_south"
    },
    "powered=false": {
      "Model": "MyPlugin/Models/unpowered"
    }
  }
}
```

## Farming Blocks

Create crops with growth stages:

```json
{
  "DisplayName": { "en-US": "Wheat" },
  "DrawType": "Model",
  "FarmingData": {
    "Stages": [
      {
        "Model": "Hytale/Models/Crops/wheat_stage_0",
        "GrowthTime": 300,
        "LightRequired": 8
      },
      {
        "Model": "Hytale/Models/Crops/wheat_stage_1",
        "GrowthTime": 300,
        "LightRequired": 8
      },
      {
        "Model": "Hytale/Models/Crops/wheat_stage_2",
        "GrowthTime": 300,
        "LightRequired": 8
      },
      {
        "Model": "Hytale/Models/Crops/wheat_stage_3",
        "GrowthTime": 0,
        "LightRequired": 0,
        "IsFinalStage": true
      }
    ],
    "Modifiers": {
      "Biome": {
        "Plains": 1.2,
        "Desert": 0.5
      },
      "Weather": {
        "Rain": 1.3
      }
    },
    "SpreadSettings": {
      "Enabled": true,
      "Chance": 0.1,
      "Radius": 2
    },
    "RequiredSoil": ["Hytale:Farmland", "Hytale:Dirt"]
  }
}
```

## Crafting Benches

Create blocks that open crafting interfaces:

### Standard Crafting Bench

```json
{
  "DisplayName": { "en-US": "Workbench" },
  "DrawType": "Model",
  "Model": "MyPlugin/Models/workbench",
  "IsUsable": true,
  "Bench": {
    "Type": "Crafting",
    "Categories": ["MyPlugin:BasicCrafting", "MyPlugin:AdvancedCrafting"],
    "GridSize": {
      "Width": 3,
      "Height": 3
    },
    "OutputSlots": 1
  }
}
```

### Processing Bench

```json
{
  "Bench": {
    "Type": "Processing",
    "Categories": ["MyPlugin:Smelting"],
    "InputSlots": 1,
    "FuelSlots": 1,
    "OutputSlots": 1,
    "ProcessingTime": 200,
    "FuelTypes": ["Hytale:Coal", "Hytale:Charcoal"]
  }
}
```

### Diagram Crafting Bench

```json
{
  "Bench": {
    "Type": "DiagramCrafting",
    "Categories": ["MyPlugin:BlueprintCrafting"],
    "DiagramSlot": true,
    "MaterialSlots": 6,
    "OutputSlots": 1
  }
}
```

## Block Sounds

```json
{
  "BlockSound": "MyPlugin/BlockSounds/metal",
  "AmbientSound": {
    "Sound": "MyPlugin/Sounds/machine_hum",
    "Volume": 0.5,
    "Radius": 8
  }
}
```

**Standard BlockSound sets**: `Stone`, `Wood`, `Metal`, `Glass`, `Dirt`, `Sand`, `Grass`, `Gravel`, `Snow`, `Wool`

## Block Particles

```json
{
  "BreakParticle": "MyPlugin/Particles/stone_break",
  "AmbientParticle": {
    "Particle": "MyPlugin/Particles/sparkle",
    "SpawnRate": 2,
    "Radius": 0.5
  },
  "FootstepParticle": "MyPlugin/Particles/dust"
}
```

## Block Interactions

Define custom interactions via the Interaction system:

```json
{
  "Interactions": {
    "Use": "MyPlugin:MyBlockInteraction",
    "Attack": "MyPlugin:MyBlockAttackInteraction"
  }
}
```

### Interaction Types

| Type | Trigger |
|------|---------|
| `Use` | Right-click |
| `Attack` | Left-click |
| `Look` | Look at block |
| `Touch` | Walk into block |

## Complete Example: Custom Ore

```json
{
  "DisplayName": {
    "en-US": "Mythril Ore"
  },
  "Description": {
    "en-US": "A rare ore found deep underground"
  },
  "DrawType": "Cube",
  "Texture": "MyPlugin/Textures/mythril_ore",
  "Material": "Stone",
  "LightLevel": 3,
  "LightColor": { "R": 0.5, "G": 0.8, "B": 1.0 },
  "Tags": {
    "Category": ["Ore", "Mining"]
  },
  "Gathering": {
    "Breaking": {
      "GatherType": "Pickaxe",
      "Power": 4,
      "Quality": 3,
      "Drops": [
        {
          "Item": "MyPlugin:RawMythril",
          "Quantity": { "Min": 1, "Max": 2 }
        }
      ]
    }
  },
  "BlockFaceSupport": {
    "Top": { "Type": "Full" },
    "Bottom": { "Type": "Full" },
    "North": { "Type": "Full" },
    "South": { "Type": "Full" },
    "East": { "Type": "Full" },
    "West": { "Type": "Full" }
  },
  "BlockSound": "Hytale/BlockSounds/Stone",
  "BreakParticle": "MyPlugin/Particles/mythril_break",
  "AmbientParticle": {
    "Particle": "MyPlugin/Particles/mythril_sparkle",
    "SpawnRate": 0.5
  }
}
```

## Complete Example: Door Block

```json
{
  "DisplayName": { "en-US": "Wooden Door" },
  "DrawType": "Model",
  "Material": "Wood",
  "IsUsable": true,
  "States": {
    "open": {
      "Values": ["true", "false"],
      "Default": "false"
    },
    "facing": {
      "Values": ["north", "south", "east", "west"],
      "Default": "north"
    },
    "half": {
      "Values": ["upper", "lower"],
      "Default": "lower"
    }
  },
  "StateData": {
    "open=false,facing=north,half=lower": {
      "Model": "MyPlugin/Models/door_closed_lower_n"
    },
    "open=true,facing=north,half=lower": {
      "Model": "MyPlugin/Models/door_open_lower_n"
    }
  },
  "IsSolid": false,
  "Interactions": {
    "Use": "MyPlugin:DoorInteraction"
  },
  "PlacementSettings": {
    "RotationMode": "PlayerFacing",
    "MultiBlock": {
      "Pattern": [
        { "Offset": [0, 1, 0], "State": "half=upper" }
      ]
    }
  },
  "BlockSound": "Hytale/BlockSounds/Wood",
  "RequiredBlockFaceSupport": {
    "Bottom": [
      { "Type": "Full", "Match": "REQUIRED" }
    ]
  }
}
```

## Registering Blocks from Plugin Code

For dynamic block registration:

```java
@Override
protected void setup() {
    // Listen for block type loading
    getEventRegistry().register(
        LoadedAssetsEvent.class, 
        BlockType.class, 
        this::onBlockTypesLoaded
    );
}

private void onBlockTypesLoaded(LoadedAssetsEvent<BlockType> event) {
    // Access loaded block types
    BlockType myBlock = event.getAssetStore().get("MyPlugin:my_custom_block");
    if (myBlock != null) {
        getLogger().atInfo().log("Custom block loaded: %s", myBlock.getDisplayName());
    }
}
```

## Block Events

Handle block-related events:

```java
@Override
protected void setup() {
    // Block break event
    getEntityStoreRegistry().registerSystem(new BreakBlockHandler());
    
    // Block place event  
    getEntityStoreRegistry().registerSystem(new PlaceBlockHandler());
    
    // Block use event
    getEntityStoreRegistry().registerSystem(new UseBlockHandler());
}

public class BreakBlockHandler extends EntityEventSystem<EntityStore, BreakBlockEvent> {
    public BreakBlockHandler() {
        super(BreakBlockEvent.class);
    }
    
    @Override
    public void handle(int index, ArchetypeChunk<EntityStore> chunk, 
                       Store<EntityStore> store, CommandBuffer<EntityStore> buffer,
                       BreakBlockEvent event) {
        BlockType blockType = event.getBlockType();
        Vector3i position = event.getPosition();
        
        // Custom logic here
        if (blockType.getId().equals("MyPlugin:protected_block")) {
            event.setCancelled(true);
        }
    }
}
```

## Troubleshooting

### Block Not Rendering

1. Verify `DrawType` is correct
2. Check texture path exists
3. Ensure asset pack is registered in manifest

### Block Breaking Instantly

1. Check `Material` property
2. Verify `GatherType` and `Power` settings
3. Ensure tool requirements are set

### Physics Not Working

1. Verify `BlockFaceSupport` configuration
2. Check `RequiredBlockFaceSupport` matches
3. Ensure `IsSolid` is true

See `references/block-materials.md` for material properties.
See `references/block-states.md` for advanced state management.