Skip to content

Custom Components

Jean edited this page Jan 10, 2026 · 3 revisions

This Feature has yet to be implemented!!!

Creating Custom Components

This guide shows you how to create your own custom components and register them with Customies.

Item Component

Step 1: Create Component Class

Create a class that implements the ItemComponent interface:

use customiesdevs\customies\item\component\ItemComponent;

class CustomEffectComponent implements ItemComponent {
    
    public function __construct(
        private readonly string $effectName,
        private readonly int $duration,
        private readonly int $amplifier = 0
    ) {}
    
    public function getName(): string {
        return "myplugin:custom_effect";
    }
    
    public function getValue(): array {
        return [
            "effect" => $this->effectName,
            "duration" => $this->duration,
            "amplifier" => $this->amplifier
        ];
    }
    
    public function getPropertyMapping(): ?array {
        // Return null if component doesn't need property mapping
        // Return array if it should be added to item_properties tag
        return null;
    }
}

Step 2: Register Component

Register your component:

use customiesdevs\customies\json\ItemComponentRegistry;

public function onEnable(): void {
    ItemComponentRegistry::register(
        "myplugin:custom_effect",
        CustomEffectComponent::class
    );
}

Step 3: Use Component

You can also use it in code:

class MagicPotion extends Item implements ItemComponents {
    use ItemComponentsTrait;
    
    public function __construct() {
        parent::__construct(new ItemIdentifier(1, 0), "Magic Potion");
        
        $this->addComponent(new MaxStackSizeComponent(16));
        $this->addComponent(new CustomEffectComponent("speed", 200, 1));
    }
}

Block Component

Step 1: Create Component Class

Create a class that implements the BlockComponent interface:

use customiesdevs\customies\block\component\BlockComponent;

class CustomSoundComponent implements BlockComponent {
    
    public function __construct(
        private readonly string $soundName,
        private readonly float $volume = 1.0,
        private readonly float $pitch = 1.0
    ) {}
    
    public function getName(): string {
        return "myplugin:custom_sound";
    }
    
    public function getValue(): array {
        return [
            "sound" => $this->soundName,
            "volume" => $this->volume,
            "pitch" => $this->pitch
        ];
    }
}

Step 2: Register Component

use customiesdevs\customies\json\BlockComponentRegistry;

public function onEnable(): void {
    BlockComponentRegistry::register(
        "myplugin:custom_sound",
        CustomSoundComponent::class
    );
}

Step 3: Use Component

class SoundBlock extends Opaque implements BlockComponents {
    use BlockComponentsTrait;
    
    public function __construct() {
        parent::__construct(
            new BlockIdentifier(BlockTypeIds::newId()),
            "Sound Block",
            new BlockTypeInfo(new BlockBreakInfo(1.0))
        );
        
        $this->addComponent(new CustomSoundComponent("random.click", 1.0, 1.0));
    }
}

Component Interface Requirements

ItemComponent

Must implement:

  • getName(): string - Component identifier (e.g., "myplugin:my_component")
  • getValue(): array - NBT data for serialization
  • getPropertyMapping(): ?array - Property mappings or null

BlockComponent

Must implement:

  • getName(): string - Component identifier
  • getValue(): array - NBT data for serialization

Best Practices

  1. Use readonly properties for immutability:

    public function __construct(
        private readonly string $value
    ) {}
  2. Validate in constructor:

    public function __construct(int $value) {
        if ($value < 0) {
            throw new \InvalidArgumentException("Value must be positive");
        }
        $this->value = $value;
    }
  3. Use namespaced component names:

    public function getName(): string {
        return "myplugin:my_component"; // Good
        // return "my_component"; // Bad - could conflict
    }
  4. Document your component:

    /**
     * Applies a custom effect when the item is used.
     */
    class CustomEffectComponent implements ItemComponent {
        // ...
    }

Accessing Component Data

Get components from items/blocks:

$item = CustomiesItemFactory::getInstance()->get("myplugin:my_item");

if ($item instanceof ItemComponents) {
    foreach ($item->getComponents() as $component) {
        if ($component instanceof CustomEffectComponent) {
            // Access component data
            $effect = $component->getEffectName();
            $duration = $component->getDuration();
        }
    }
}

That's it! You can now create any custom component you need.