Skip to content
Download

Rewards for actions

Unstable

A reward says “when a player does this, give that”. A mod declares it in code or in a pack’s rewards.toml; the server gives it and keeps who got it beside the world’s save. The calls are unstable.

A reward has a name, the action it follows, what it gives, a limit and a chance.

use enshwick::rewards::{Action, Give, Limit, Reward};
fn init(load: &mut enshwick::Load<'_>) -> Result<(), enshwick::Off> {
const TONIC: enshwick::ItemId = enshwick::ItemId::named("you.tonics:tonic");
load.add_reward(
Reward::new("level-two", Action::LevelUp(2))
.with(Give::Items { item: TONIC, count: 2 })
.with(Give::Experience(50))
.with_limit(Limit::Once),
)
}
rewards.toml
[[reward]]
id = "level-two"
on = { level_up = 2 }
give = [{ item = "tonic", count = 2 }, { experience = 50 }]
limit = "once"

In rewards.toml an item or a recipe is the pack’s own name, another mod’s content id or a vanilla name, as in the other pack files; a knowledge entry or a buff is its GUID.

Actionon in rewards.tomlWhen
Craft(recipe)craft = "<recipe>"The server crafts a request of the player
LevelUp(level)level_up = <level>The player reaches the level; 0 for any
Joinjoin = trueThe player joins the world
Lootloot = trueThe player loots a container
Questquest = trueThe player completes a quest
Consume(item)consume = "<item>"The player eats, drinks or uses the item
Pickup(item)pickup = "<item>"The player picks the item up
GiftIn rewards.tomlWhat the player gets
Items { item, count }{ item = "<item>", count = 2 }The items, all or nothing; a full inventory gets none
Experience(amount){ experience = 50 }Experience on the next gains, at most a level a tick
Knowledge(id){ knowledge = "<guid>" }The knowledge entry, set
Buff(id){ buff = "<guid>" }The buff, for its type’s own duration

The limit is Every (every, when left out), Once per player in the world, Daily, once per player each calendar day in UTC, or World, once in the world to the first player. The chance is from 0 to 1, always when left out. pack check reports a reward without an action or with two, one that gives nothing, a chance outside 0 to 1, a name used twice and a name the pack does not define.

load.on_reward(filter) runs before the mod gives any of its rewards; false holds the grant back and leaves its limit unused. To give something else, give it and return false. load.rewards() returns the handle that grants a declared reward by name, within its limit and chance, or gives anything at once.

fn init(load: &mut enshwick::Load<'_>) -> Result<(), enshwick::Off> {
load.on_reward(|grant| grant.reward != "level-two" || grant.player != enshwick::Entity(1))?;
let rewards = load.rewards()?;
load.on::<enshwick::events::PlayerJoined>(move |joined| {
let _given = rewards.grant(joined.entity, "level-two");
})
}

Rewards run in the server’s world, on the game thread, a step after their action. A craft counts when the crafting system made the player’s request: the server pairs each made recipe with the oldest request for it of the last 30 seconds, and a request older than that gives no reward. The world’s file rewards.toml in the mod’s data folder beside the save keeps who got a limited reward, by account, so a limit holds across restarts and moves with the save. Items and experience are given as the reward states them; the game’s rates do not change them.

A reward whose action this game build lacks turns off alone, with a warning in the log; the rest of the pack applies. Rewards::grant and Rewards::give run on the thread that calls them, so call them on the game thread; an item handler runs on its system’s thread, so schedule the grant from there.