# Creating a Feature

This guide shows how to create a minimal OMS feature.

The example feature will print a message (`hello world`) to the console during OMS startup.

***

### Goal

By the end of this guide, you will have:

* a feature class based on `OmsFeature`
* a working configuration using `ForgeConfigSpec`
* feature registration through an addon
* a fully working `HelloWorldFeature`

***

### 1. Create the feature config

OMS does not require a specific config implementation.\
A feature config only needs to implement `FeatureConfig`.

Below is a minimal working example using Forge:

```kotlin
class CHelloWorldFeature(
    private val enabledValue: ForgeConfigSpec.BooleanValue,
    private val messageValue: ForgeConfigSpec.ConfigValue<String>
) : FeatureConfig {

    override val name: String = NAME

    override fun isEnabled(): Boolean = enabledValue.get()

    override fun enable() {
        enabledValue.set(true)
    }

    override fun disable() {
        enabledValue.set(false)
    }

    fun message(): String = messageValue.get()

    override fun getConfigData(): Map<String, Any> {
        return mapOf(
            "enabled" to enabledValue.get(),
            "message" to messageValue.get()
        )
    }

    companion object {
        const val NAME = "hello_world_feature"
    }
}
```

***

### 2. Create config holder

Define and register your config using `ForgeConfigSpec`:

```kotlin
object HelloWorldConfigs {
    lateinit var feature: CHelloWorldFeature
        private set

    lateinit var spec: ForgeConfigSpec
        private set

    fun register() {
        val specPair = ForgeConfigSpec.Builder()
            .configure { builder ->
                builder.push(CHelloWorldFeature.NAME)

                val enabled = builder.define("enabled", true)
                val message = builder.define("message", "hello world")

                builder.pop()

                CHelloWorldFeature(enabled, message)
            }

        feature = specPair.left
        spec = specPair.right

        registerConfig(ModConfig.Type.SERVER, spec)
    }
}
```

***

### 3. Register config in your mod

```kotlin
@Mod(HelloWorldMod.MOD_ID)
class HelloWorldMod {

    init {
        HelloWorldConfigs.register()
    }

    companion object {
        const val MOD_ID = "hello_world"
    }
}
```

***

### 4. Create the feature

```kotlin
class HelloWorldFeature(
    configProvider: ConfigProvider<CHelloWorldFeature>
) : OmsFeature<CHelloWorldFeature>(configProvider) {

    override fun onOmsStarted(
        event: OMSLifecycle.StartingEvent,
        context: AddonContext
    ) {
        println(config.message())
    }

    override fun info(): FeatureInfo {
        return super.info().copy(
            id = CHelloWorldFeature.NAME,
            priority = Priority.COMMON
        )
    }
}
```

***

### 5. Register the feature

```kotlin
class HelloWorldAddon : OmsAddon(HelloWorldMod.MOD_ID) {

    override fun onRegisterFeatures(context: AddonContext) {
        context.featureManager.register(
            // Provide your feature with config
            HelloWorldFeature { HelloWorldConfigs.feature }
        )
    }
}
```

***

### 6. What happens during startup

1. OMS registers the addon
2. The addon registers `HelloWorldFeature`
3. OMS initializes feature config
4. Lifecycle events are dispatched
5. `HelloWorldFeature` receives `onOmsStarted(...)`
6. The message is printed to the console

***

### Notes

* `FeatureConfig` is a contract, not an implementation
* You can use ForgeConfigSpec or any custom config system
* Features are executed by the `FeatureManager`
* Configuration is provided via `ConfigProvider`

***

### Next Step

You can now extend `HelloWorldFeature` with:

* [custom commands](/oms-wiki/developer-guide/implementation-guides/registering-feature-commands.md)
* [expanding config](/oms-wiki/developer-guide/implementation-guides/working-with-config.md)
* [trigger stop action](/oms-wiki/developer-guide/implementation-guides/triggering-stop-actions.md)
* [external event listeners](/oms-wiki/developer-guide/implementation-guides/using-external-event-listeners.md)
* [runtime fields](/oms-wiki/developer-guide/implementation-guides/using-runtime-fields.md)
* [customize addon context](/oms-wiki/developer-guide/implementation-guides/customizing-addon-context.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://conboi.gitbook.io/oms-wiki/developer-guide/implementation-guides/creating-a-feature.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
