Creating an Effect
An effect is the action that libreforge does. This page tells you how to make a triggered effect and a permanent effect. For the terms on this page, see the Glossary.
Choose the effect type
The parameters property sets the type of the effect.
If
parametersis empty, the effect is permanent. OverrideonEnableandonDisable.If
parametershas one or more values, the effect is triggered. OverrideonTrigger.
Do not make one effect that is both types.
Make a triggered effect
Make a Kotlin
objectthat extendsEffect<T>. Give the ID to the constructor.Set
TtoNoCompileDataif you do not need compile data.Set
parametersto the trigger parameters that the effect needs.Add the arguments that the user must write.
Override
onTrigger. Returntrueif the effect ran. Returnfalseif it did not run.
object EffectRestoreHunger : Effect<NoCompileData>("restore_hunger") {
override val description = "Gives food points to the player."
// Libreforge only lets users attach this effect to triggers that send a player.
override val parameters = setOf(
TriggerParameter.PLAYER
)
override val arguments = arguments {
require(
"amount",
"You must specify the amount of food points!",
description = "The number of food points to give.",
type = ArgType.EXPRESSION,
example = "4"
)
}
override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean {
val player = data.player ?: return false
val amount = config.getIntFromExpression("amount", data)
player.foodLevel = (player.foodLevel + amount).coerceAtMost(20)
return true
}
}
Note: Use config.getDoubleFromExpression(key, data) or config.getIntFromExpression(key, data) to read numbers. These functions calculate placeholders and math, for example %level% * 2.
Make a permanent effect
Make a Kotlin
objectthat extendsEffect<T>. Do not setparameters.Override
onEnable. Apply the change to the dispatcher here.Override
onDisable. Remove the change here. Remove only the change that this effect made.Use
identifiersto find the change. Each dispatcher gets different identifiers for the same effect.
object EffectNoFallDamage : Effect<NoCompileData>("no_fall_damage") {
override val description = "Stops fall damage to the player."
// The change does not use the config, so libreforge does not have to reload it.
override val shouldReload = false
// The change does not use the item or the slot of the holder.
override val providerBinding = ProviderBinding.NONE
// For each dispatcher, the identifiers of each active copy of this effect.
private val active = listMap<UUID, UUID>()
override fun onEnable(
dispatcher: Dispatcher<*>,
config: Config,
identifiers: Identifiers,
holder: ProvidedHolder,
compileData: NoCompileData
) {
active[dispatcher.uuid].add(identifiers.uuid)
}
override fun onDisable(dispatcher: Dispatcher<*>, identifiers: Identifiers, holder: ProvidedHolder) {
active[dispatcher.uuid].remove(identifiers.uuid)
}
// Effects are listeners. Libreforge registers this handler for you.
@EventHandler(ignoreCancelled = true)
fun handle(event: EntityDamageEvent) {
if (event.cause != EntityDamageEvent.DamageCause.FALL) {
return
}
if (active[event.entity.uniqueId].isNotEmpty()) {
event.isCancelled = true
}
}
}
Caution: Two holders can give the same effect to one player. Keep a list for each dispatcher, as in the example. If you keep only one value, the first onDisable removes the change for both holders.
Optional settings for permanent effects
| Setting | Default | Use |
|---|---|---|
shouldReload | true | Set to false if the change does not use values from the config that can change. |
onReload | Calls onDisable, then onEnable | Override to update the change in one step. For example, change the amount of an attribute modifier. |
providerBinding | SLOT | Set to ITEM if the effect changes the item that gives the holder. Set to NONE if the effect does not use the item or the slot. |
isApplied | Returns null | Return false if the change is not present now, for example because a different plugin removed it. Libreforge then applies it again. Return null if you cannot know. This function runs frequently, so make it fast. |
Compile data
Use compile data to do slow work one time, when the config loads.
Set
Tto your data type.Override
makeCompileData. Read the config and return the data.Use
compileDatainonTriggeroronEnable.
object EffectGiveItem : Effect<TestableItem>("give_custom_item") {
override val parameters = setOf(TriggerParameter.PLAYER)
override fun makeCompileData(config: Config, context: ViolationContext): TestableItem {
return Items.lookup(config.getString("item"))
}
override fun onTrigger(config: Config, data: TriggerData, compileData: TestableItem): Boolean {
val player = data.player ?: return false
player.inventory.addItem(compileData.item)
return true
}
}
Next steps
Register the effect. See Registering Elements.
See a full example: Full Example: Permanent Effect or Full Example: Triggered Effect.