# Energy

**URL:** https://heroiclabs.com/docs/hiro/server-framework/energy/
**Keywords:** energy, hiro
**Categories:** hiro, energy, server-framework

---


# Energy

Read more about the Energy system in Hiro [here](../../concepts/energy/).

## Functions

### Get

Get all energies defined and the values a user currently owns by ID.

```go
userId := "userId"

energies, err := systems.GetEnergySystem().Get(ctx, logger, nk, userId)
if err != nil {
  return err
}
```

### Spend

Deduct the given amounts from each energy for a user by ID.

```go
userId := "userId"
amounts := map[string]int32{"hearts": 1, "stamina": 3}

energies, reward, err := systems.GetEnergySystem().Spend(ctx, logger, nk, userId, amounts)
if err != nil {
  return err
}
```

### SpendWithRefillStartTime

Deduct the given amounts from each energy and set custom refill start times for a user by ID.

```go
userId := "userId"
spends := map[string]*hiro.EnergySpendWithTime{
    "hearts": {Amount: 1, RefillStartTime: time.Now().Add(-5 * time.Minute).Unix()},
    "stamina": {Amount: 3, RefillStartTime: time.Now().Unix()},
}

energies, reward, err := systems.GetEnergySystem().SpendWithRefillStartTime(ctx, logger, nk, userId, spends)
if err != nil {
    return err
}
```

### BatchSpend

Deduct the given amounts from each energy for multiple users in a single atomic transaction. Either all users spend successfully or none do.
`usersAmounts` is a map of user IDs to energy amounts. Each user can spend from one or more energy types in the same call.

```go
usersAmounts := map[string]map[string]int32{
    "userId1": {"hearts": 1, "stamina": 3},
    "userId2": {"hearts": 2},
    "userId3": {"stamina": 5},
}

userEnergies, userRewards, err := systems.GetEnergySystem().BatchSpend(ctx, logger, nk, usersAmounts)
if err != nil {
    return err
}
```

If any user has insufficient energy, the entire transaction fails and no energy is deducted for any user. Duplicate user IDs in `usersAmounts` are deduplicated automatically.

The function returns:

- `userEnergies`: a map of user ID to energy ID to current `Energy` state after deduction
- `userRewards`: a map of user ID to the aggregated `Reward` earned across all energy spends for that user

### Grant

Add the given amounts to each energy (while applying any energy modifiers) for a user by ID.

```go
userId := "userId"
amounts := map[string]int32{"hearts": 1, "stamina": 3}
modifiers := []*hiro.RewardEnergyModifier{{
  Id:          "myModifier",
  Operator:    "multiplier",
  Value:       2,
  DurationSec: 86400,
  Weight:      -1,
}}

energies, err := systems.GetEnergySystem().Grant(ctx, logger, nk, userId, amounts, modifiers)
if err != nil {
  return err
}
```

## Hooks

### SetOnSpendReward

Set a custom reward function which will run after an energy reward's value has been rolled.

```go
systems.GetEnergySystem().SetOnSpendReward(OnSpendReward)

func OnSpendReward(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userID, sourceID string, source *hiro.EnergyConfigEnergy, rewardConfig *hiro.EconomyConfigReward, reward *hiro.Reward) (*hiro.Reward, error) {
	// Modify reward or take additional actions.
	return reward, nil
}
```