> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/0x48lab/skills/llms.txt
> Use this file to discover all available pages before exploring further.

# SkillsAPI reference

> Complete reference for all 19 methods in the SkillsAPI interface.

The `SkillsAPI` interface is located at `com.hacklab.minecraft.skills.api.SkillsAPI`. Obtain an instance via the Bukkit `ServicesManager` as described in [Getting started](/api/getting-started).

***

## Skill operations

### `getSkill` (by Player)

```kotlin theme={null}
fun getSkill(player: Player, skillName: String): Double?
```

Returns the current value of a skill for an online player.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ParamField path="skillName" type="String" required>
  Skill name in any accepted format (display name, enum name, case-insensitive, spaces or underscores).
</ParamField>

<ResponseField name="return" type="Double?">
  Skill value in the range `0.0`–`100.0`, or `null` if `skillName` does not match any known skill.
</ResponseField>

```kotlin theme={null}
val sword: Double = api.getSkill(player, "Swordsmanship") ?: 0.0
```

***

### `getSkill` (by UUID)

```kotlin theme={null}
fun getSkill(uuid: UUID, skillName: String): Double?
```

Returns the current value of a skill looked up by UUID. Useful when you only have a UUID and the player may be offline in cache.

<ParamField path="uuid" type="UUID" required>
  The UUID of the player.
</ParamField>

<ParamField path="skillName" type="String" required>
  Skill name in any accepted format.
</ParamField>

<ResponseField name="return" type="Double?">
  Skill value `0.0`–`100.0`, or `null` if the skill name is invalid or the player's data is not loaded.
</ResponseField>

```kotlin theme={null}
val mining: Double = api.getSkill(player.uniqueId, "Mining") ?: 0.0
```

***

### `setSkill`

```kotlin theme={null}
fun setSkill(player: Player, skillName: String, value: Double): Boolean
```

Sets a skill to an explicit value. The value is clamped to `0.0`–`100.0` before being applied.

<ParamField path="player" type="Player" required>
  The online player to modify.
</ParamField>

<ParamField path="skillName" type="String" required>
  Skill name in any accepted format.
</ParamField>

<ParamField path="value" type="Double" required>
  Target skill value. Automatically clamped to `[0.0, 100.0]`.
</ParamField>

<ResponseField name="return" type="Boolean">
  `true` if the skill was updated, `false` if `skillName` is invalid.
</ResponseField>

```kotlin theme={null}
// Ensure a new player starts with at least 10 Mining
if ((api.getSkill(player, "Mining") ?: 0.0) < 10.0) {
    api.setSkill(player, "Mining", 10.0)
}
```

***

### `addSkill`

```kotlin theme={null}
fun addSkill(player: Player, skillName: String, amount: Double): Double?
```

Adds (or subtracts, if `amount` is negative) a delta to the current skill value. Respects the `0.0`–`100.0` cap.

<ParamField path="player" type="Player" required>
  The online player to modify.
</ParamField>

<ParamField path="skillName" type="String" required>
  Skill name in any accepted format.
</ParamField>

<ParamField path="amount" type="Double" required>
  Amount to add. May be negative to reduce the skill.
</ParamField>

<ResponseField name="return" type="Double?">
  The new skill value after the delta is applied, or `null` if `skillName` is invalid.
</ResponseField>

```kotlin theme={null}
// Award 5 points of Crafting as a quest reward
val newValue = api.addSkill(player, "Crafting", 5.0)
player.sendMessage("Crafting is now ${newValue?.toInt()}.")
```

***

### `hasSkillLevel`

```kotlin theme={null}
fun hasSkillLevel(player: Player, skillName: String, minLevel: Double): Boolean
```

Checks whether a player's skill is at or above a threshold without requiring a null check on the caller side.

<ParamField path="player" type="Player" required>
  The online player to check.
</ParamField>

<ParamField path="skillName" type="String" required>
  Skill name in any accepted format.
</ParamField>

<ParamField path="minLevel" type="Double" required>
  The minimum required skill value.
</ParamField>

<ResponseField name="return" type="Boolean">
  `true` if the player's skill value is greater than or equal to `minLevel`. Returns `false` if the skill name is invalid.
</ResponseField>

<Tip>
  Use `hasSkillLevel()` instead of comparing the result of `getSkill()` directly. It handles the invalid-skill case for you.
</Tip>

```kotlin theme={null}
if (!api.hasSkillLevel(player, "Archery", 30.0)) {
    event.isCancelled = true
    player.sendMessage("You need 30 Archery to use this bow.")
}
```

***

### `getAllSkills`

```kotlin theme={null}
fun getAllSkills(player: Player): Map<String, Double>
```

Returns a snapshot of all 37 skill values for a player.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Map<String, Double>">
  Map keyed by skill display name (e.g. `"Swordsmanship"`) with the current value as the entry. All 37 skills are always present; unlearned skills have a value of `0.0`.
</ResponseField>

```kotlin theme={null}
val skills = api.getAllSkills(player)
skills.forEach { (name, value) ->
    if (value > 0.0) println("$name: $value")
}
```

***

### `getTotalSkillPoints`

```kotlin theme={null}
fun getTotalSkillPoints(player: Player): Double
```

Returns the sum of all skill values. The in-game cap is 700 points.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Sum of all 37 skill values. Maximum is `700.0` (7 skills at `100.0`).
</ResponseField>

```kotlin theme={null}
val total = api.getTotalSkillPoints(player)
player.sendMessage("Total skill points: ${total.toInt()} / 700")
```

***

## Stat operations

STR, DEX, and INT are derived stats calculated automatically from the player's skill values. They cannot be set directly; they update whenever the underlying skills change.

| Stat | Range | Effect                                               |
| ---- | ----- | ---------------------------------------------------- |
| STR  | 0–100 | Max HP = 100 + STR; mining/lumberjacking speed bonus |
| DEX  | 0–100 | Attack speed +DEX/2%; movement speed +DEX/10%        |
| INT  | 0–100 | Mana cost −INT/2%; cast success rate +INT/5%         |

### `getStat`

```kotlin theme={null}
fun getStat(player: Player, statName: String): Int?
```

Returns the current value of a single derived stat.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ParamField path="statName" type="String" required>
  One of `"STR"`, `"DEX"`, or `"INT"` (also accepts the long forms `"STRENGTH"`, `"DEXTERITY"`, `"INTELLIGENCE"`).
</ParamField>

<ResponseField name="return" type="Int?">
  Stat value `0`–`100`, or `null` if `statName` is not recognised.
</ResponseField>

```kotlin theme={null}
val str = api.getStat(player, "STR") ?: 0
val maxHp = 100 + str
```

***

### `getAllStats`

```kotlin theme={null}
fun getAllStats(player: Player): Map<String, Int>
```

Returns all three derived stats in a single call.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Map<String, Int>">
  Map with keys `"STR"`, `"DEX"`, and `"INT"` mapped to their current integer values.
</ResponseField>

```kotlin theme={null}
val stats = api.getAllStats(player)
val str = stats["STR"] ?: 0
val dex = stats["DEX"] ?: 0
val int = stats["INT"] ?: 0
```

***

## HP, mana, and stamina

Skills maintains internal HP, mana, and stamina values that are separate from vanilla Minecraft hunger and hearts. HP is synchronised to vanilla hearts as a percentage.

### `getCurrentHp`

```kotlin theme={null}
fun getCurrentHp(player: Player): Double
```

Returns the player's current internal HP.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Current internal HP. Minimum `0.0`; maximum equals `getMaxHp()`.
</ResponseField>

```kotlin theme={null}
val hp = api.getCurrentHp(player)
```

***

### `getMaxHp`

```kotlin theme={null}
fun getMaxHp(player: Player): Double
```

Returns the player's maximum internal HP. Calculated as `100 + STR`, giving a range of `100`–`200`.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Maximum HP in the range `100.0`–`200.0` based on the player's STR stat.
</ResponseField>

```kotlin theme={null}
val pct = api.getCurrentHp(player) / api.getMaxHp(player)
```

***

### `getCurrentMana`

```kotlin theme={null}
fun getCurrentMana(player: Player): Double
```

Returns the player's current mana. Mana is consumed by spell casting and is independent of the vanilla hunger bar.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Current mana. Minimum `0.0`; maximum `20.0`.
</ResponseField>

```kotlin theme={null}
val mana = api.getCurrentMana(player)
```

***

### `getMaxMana`

```kotlin theme={null}
fun getMaxMana(player: Player): Double
```

Returns the player's maximum mana. The maximum is always `20.0`. INT reduces the cost of spells rather than increasing the pool.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Maximum mana. Always `20.0`.
</ResponseField>

```kotlin theme={null}
val maxMana = api.getMaxMana(player) // always 20.0
```

***

### `getCurrentStamina`

```kotlin theme={null}
fun getCurrentStamina(player: Player): Double
```

Returns the player's current stamina. Stamina is consumed while sprinting.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Current stamina. Minimum `0.0`; maximum equals `getMaxStamina()`.
</ResponseField>

```kotlin theme={null}
val stamina = api.getCurrentStamina(player)
```

***

### `getMaxStamina`

```kotlin theme={null}
fun getMaxStamina(player: Player): Double
```

Returns the player's maximum stamina. Calculated as `100 + DEX + (Focus / 2)`, giving a maximum of `250.0` when DEX and Focus are both 100.

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="Double">
  Maximum stamina. Range `100.0`–`250.0` depending on DEX stat and Focus skill.
</ResponseField>

```kotlin theme={null}
val staminaPct = api.getCurrentStamina(player) / api.getMaxStamina(player)
```

***

### `restoreMana`

```kotlin theme={null}
fun restoreMana(player: Player, amount: Double)
```

Adds mana to the player, capped at the maximum.

<ParamField path="player" type="Player" required>
  The online player to restore mana for.
</ParamField>

<ParamField path="amount" type="Double" required>
  Amount of mana to restore. Excess is discarded.
</ParamField>

```kotlin theme={null}
// Simulate a mana potion
api.restoreMana(player, 5.0)
```

***

### `restoreStamina`

```kotlin theme={null}
fun restoreStamina(player: Player, amount: Double)
```

Adds stamina to the player, capped at the maximum.

<ParamField path="player" type="Player" required>
  The online player to restore stamina for.
</ParamField>

<ParamField path="amount" type="Double" required>
  Amount of stamina to restore. Excess is discarded.
</ParamField>

```kotlin theme={null}
// Give a brief stamina burst on a specific event
api.restoreStamina(player, 20.0)
```

***

## Utility

### `getAvailableSkillNames`

```kotlin theme={null}
fun getAvailableSkillNames(): List<String>
```

Returns the display names of all 37 skills registered by the plugin.

<ResponseField name="return" type="List<String>">
  Ordered list of skill display names (e.g. `["Swordsmanship", "Axe", ...]`). Use these as inputs to other skill methods.
</ResponseField>

```kotlin theme={null}
val names: List<String> = api.getAvailableSkillNames()
```

***

### `isValidSkillName`

```kotlin theme={null}
fun isValidSkillName(skillName: String): Boolean
```

Checks whether a string resolves to a known skill, using the same lenient matching as all other skill methods.

<ParamField path="skillName" type="String" required>
  The string to validate.
</ParamField>

<ResponseField name="return" type="Boolean">
  `true` if the name resolves to a known skill, `false` otherwise.
</ResponseField>

```kotlin theme={null}
if (!api.isValidSkillName(input)) {
    sender.sendMessage("Unknown skill: $input")
    return
}
```

***

### `getTitle`

```kotlin theme={null}
fun getTitle(player: Player): String
```

Returns the player's current title string, which is derived from their highest-ranked skills (e.g. `"Grandmaster Swordsman"`).

<ParamField path="player" type="Player" required>
  The online player to query.
</ParamField>

<ResponseField name="return" type="String">
  Human-readable title string. The format depends on the player's skill distribution.
</ResponseField>

```kotlin theme={null}
val title = api.getTitle(player)
player.sendMessage("Your title: $title")
```

***

## Skill name reference

All skill names accepted by any API method. Matching is case-insensitive; spaces and underscores are interchangeable.

| Display name            | Enum name                 |
| ----------------------- | ------------------------- |
| Swordsmanship           | `SWORDSMANSHIP`           |
| Axe                     | `AXE`                     |
| Mace Fighting           | `MACE_FIGHTING`           |
| Spear                   | `SPEAR`                   |
| Archery                 | `ARCHERY`                 |
| Throwing                | `THROWING`                |
| Wrestling               | `WRESTLING`               |
| Tactics                 | `TACTICS`                 |
| Anatomy                 | `ANATOMY`                 |
| Parrying                | `PARRYING`                |
| Focus                   | `FOCUS`                   |
| Magery                  | `MAGERY`                  |
| Evaluating Intelligence | `EVALUATING_INTELLIGENCE` |
| Meditation              | `MEDITATION`              |
| Resisting Spells        | `RESISTING_SPELLS`        |
| Inscription             | `INSCRIPTION`             |
| Crafting                | `CRAFTING`                |
| Cooking                 | `COOKING`                 |
| Mining                  | `MINING`                  |
| Lumberjacking           | `LUMBERJACKING`           |
| Fishing                 | `FISHING`                 |
| Farming                 | `FARMING`                 |
| Hiding                  | `HIDING`                  |
| Stealth                 | `STEALTH`                 |
| Detecting Hidden        | `DETECTING_HIDDEN`        |
| Snooping                | `SNOOPING`                |
| Stealing                | `STEALING`                |
| Poisoning               | `POISONING`               |
| Animal Taming           | `ANIMAL_TAMING`           |
| Animal Lore             | `ANIMAL_LORE`             |
| Veterinary              | `VETERINARY`              |
| Athletics               | `ATHLETICS`               |
| Swimming                | `SWIMMING`                |
| Heat Resistance         | `HEAT_RESISTANCE`         |
| Cold Resistance         | `COLD_RESISTANCE`         |
| Endurance               | `ENDURANCE`               |
| Arms Lore               | `ARMS_LORE`               |
