# Content Creation Guide This project provides a framework for adding new items and features (components) using the HcuItems plugin. Event handling is uniformly managed by the `EventListener`, which delegates to appropriate classes based on information in the item's PersistentDataContainer (PDC). ## Architecture Overview All events (right-click, damage, movement, etc.) are received by the `EventListener`. The `EventListener` delegates processing through the following steps: 1. Retrieves the item involved in the event. 2. Checks the item's PDC. - If an `AbstractItem` ID (`hcu_items:id`) exists → Retrieves the item definition from `ItemRegistry` and executes. - If a component key (`hcu_items:component_id`) exists → Retrieves the component definition from `ComponentRegistry` and executes. ## 1. Creating an AbstractItem (Custom Item) Use this when creating an item with completely unique behavior. ### Steps 1. Create a new class that inherits from the `AbstractItem` class. 2. Specify a unique ID in the constructor. 3. Implement the `buildItem` method to define the item's appearance (Material, Name, Lore, etc.). 4. Override necessary event handlers (`onInteract`, `onPlayerMove`, etc.). 5. Register by calling `ItemRegistry.register(YourItem())` in `App.kt`'s `onEnable`. ```kotlin class MyCustomItem : AbstractItem("my_custom_item") { override fun buildItem(tier: Tier): ItemStack { return ItemStack(Material.DIAMOND_SWORD).apply { // Meta configuration } } override fun onInteract(event: PlayerInteractEvent) { event.player.sendMessage("Used custom item!") } } ``` ## 2. Creating a CustomComponent (Adding Features to Existing Items) Use this when adding common features (e.g., glider, passive effects) to existing items or items that meet specific conditions. ### Steps 1. Create a class that inherits from `AbstractComponent` and implements `CustomComponent` (or `EquippableComponent`). 2. Specify a unique component ID in the constructor. 3. Implement the `apply` method with logic to apply the component to the item (key registration to PDC is automatic, but describe if additional metadata is needed). 4. Override necessary event handlers. 5. Register by calling `ComponentRegistry.register(YourComponent(this))` in `App.kt`'s `onEnable`. ```kotlin class MyComponent(plugin: App) : AbstractComponent(plugin, "my_component") { override fun onInteract(event: PlayerInteractEvent) { event.player.sendMessage("Component interaction!") } } ``` ### Event Mechanism `AbstractComponent` generates a `NamespacedKey` during initialization and writes this key to the item's PDC during `apply`. When the `EventListener` confirms this key exists in the item's PDC, it calls your component's event handler. ## Notes - `AbstractItem` and `CustomComponent` can coexist. A single item can be an `AbstractItem` and have multiple `CustomComponent`s. - Within event handlers, appropriately control `event.isCancelled` as needed. ## 3. Configuration Management The project uses a centralized `Config` object to manage configuration values from `config.yml`. This allows for easy adjustment of values (like cooldowns) without code changes. ### Accessing Configuration To access configuration values, simply access the public properties of the `Config` object: ```kotlin import net.hareworks.hcu.items.config.Config // Example usage val cooldown = Cooldown(Config.blinkCooldown) ``` ### Adding New Config Values 1. **Add Property to Config Object**: Add a new property to `net.hareworks.hcu.items.config.Config.kt`. 2. **Update Load Method**: Read the value from `plugin.config` in the `load` method. 3. **Update Defaults**: Add the default value in the `saveDefaults` method. ```kotlin object Config { // 1. Add Property var newFeatureEnabled: Boolean = true fun load(plugin: JavaPlugin) { // ... existing code ... // 2. Load Value newFeatureEnabled = config.getBoolean("components.new_feature.enabled", true) // ... existing code ... } private fun saveDefaults(plugin: JavaPlugin, config: FileConfiguration) { // ... existing code ... // 3. Set Default config.addDefault("components.new_feature.enabled", true) // ... existing code ... } } ```