# Landing

Welcome to the Negative Games Wiki; this is the primary source of knowledge for many Negative Games projects!

## Active Projects

{% content-ref url="/pages/6LfXQWawEaJCljuUq23h" %}
[Punishments](/projects/punishments)
{% endcontent-ref %}


# Punishments

A LiteBans addon which allows you to stack punishments and have a GUI interface while punishing players.

## Commands Overview

{% content-ref url="/pages/ZQwINgGHT06UhIxAGx4A" %}
[Commands](/projects/punishments/commands)
{% endcontent-ref %}

## Configuration Overview

{% content-ref url="/pages/GbJV9D8jidzthVl2f5uH" %}
[Configuration](/projects/punishments/configs)
{% endcontent-ref %}


# Commands

An overview of all commands provided by the plugin.

<table data-view="cards"><thead><tr><th>Command</th><th>Description</th><th>Permission</th></tr></thead><tbody><tr><td><mark style="color:orange;">/punish &#x3C;user></mark></td><td>This command is designed to punish players using a user-interface approach and automatically assign punishment lengths depending on the user's history.</td><td><mark style="color:blue;">punishments.punish</mark></td></tr><tr><td><mark style="color:orange;">/history &#x3C;user></mark></td><td>This command is designed for staff members to view a player's history in a user-interface environment.</td><td><mark style="color:blue;">punishments.history</mark></td></tr><tr><td><mark style="color:orange;">/record</mark></td><td>This command is designed for players to view their own history in a user-interface environment.</td><td><mark style="color:blue;">punishments.record</mark></td></tr><tr><td><mark style="color:orange;">/staffhistory &#x3C;user></mark></td><td>This command is designed to view the punishment history of a staff member in a user-interface environment.</td><td><mark style="color:blue;">punishments.staffhistory</mark></td></tr><tr><td><mark style="color:orange;">/staffleaderboard</mark></td><td>View the current statistical leaderboard that displays the staff member's punishment statistics.</td><td><mark style="color:blue;">punishments.staffleaderboard</mark></td></tr><tr><td><mark style="color:orange;">/punishreload</mark></td><td>Reload the plugin's configuration to apply any changes you've made to the configurations onto the server.</td><td><mark style="color:blue;">punishments.reload</mark></td></tr><tr><td><mark style="color:orange;">/notes &#x3C;user></mark></td><td>This command is designed for staff members to leave notes on specific users for more convience when dealing with complicated situations. <em>Just leave a note!</em></td><td><mark style="color:blue;">punishments.notes</mark></td></tr><tr><td><mark style="color:orange;">/togglenotenotice</mark></td><td>Toggle the notice you get when users with a <mark style="color:red;">severe note</mark> joins the server.</td><td><mark style="color:blue;">punishments.notes.notice</mark></td></tr></tbody></table>


# Configuration

An overview of all the default configuration files provided by the plugin.

{% hint style="info" %}
All plugin messages, menus, and menu buttons use the **MiniMessage** format!

For more information:

* Documentation: <https://docs.advntr.dev/minimessage/index.html>
* Web UI: <https://webui.advntr.dev/>
  {% endhint %}

***

## Config File Overview

<table data-view="cards"><thead><tr><th data-type="content-ref">File</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><a href="/projects/punishments/configs/main.yml">main.yml</a></td><td><a href="/projects/punishments/configs/main.yml">main.yml</a></td></tr><tr><td><a href="/projects/punishments/configs/messages.yml">messages.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/history-main.yml">history-main.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/history.yml">history.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/note-delete-confirmation.yml">note-delete-confirmation.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/note-editor.yml">note-editor.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/notes.yml">notes.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/punish-confirm.yml">punish-confirm.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/punish.yml">punish.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/records-main.yml">records-main.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/records.yml">records.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/records-single.yml">records-single.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/staff-history-main.yml">staff-history-main.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/staff-history.yml">staff-history.yml</a></td><td></td></tr><tr><td><a href="/projects/punishments/configs/menus/staff-leaderboard.yml">staff-leaderboard.yml</a></td><td></td></tr></tbody></table>


# main.yml

{% code fullWidth="true" %}

```yaml
# --------------------------------------------------------
# Punishments Configuration
#  
# Useful Resources:
# * Discord: https://dsc.gg/negative-games
# * Wiki: https://wiki.ericlmao.com/projects/punishments
# * MiniMessage Format: https://docs.advntr.dev/minimessage/format.html
# * MiniMessage Web UI: https://webui.advntr.dev/
# --------------------------------------------------------

# When true, the plugin will disable unnecessary logs to the console.
disable-unnecessary-logs: false

# The interval in seconds in which the cache is synchronized with the database.
# In lamen's terms, this is the interval that the plugin will check the database for new
# or updated punishments and then store them locally.
cache-sync-interval: 5

# When true, the /record command is enabled for all players to use.
record-command-enabled: true

# Whether to use a categorized record menu or not.
# If set to true, the record menu will be categorized
# by punishment type (e.g. mutes, bans, warns) in their own
# dedicated submenus, similar to the /history command.
#  
# If set to false, the record menu will display all punishments
# in a single menu.
record-menu-categorized: true

# Staff Leaderboard Configuration
staff-leaderboard:
  # When true, the staff leaderboard system is enabled.
  enabled: true

  # The interval in seconds in which the staff leaderboard cache is synchronized with the database.
  # In lamen's terms, this is the interval that the plugin will check the database for new
  # or updated staff leaderboard data and then store it locally.
  cache-sync-interval: 30

# Note Configuration
notes:
  # When true, the note system is enabled.
  enabled: true

  # When true, the note database system will use an external database instead of the default SQLite database.
  use-external-database: false

  # External Database Information
  database:
    host: localhost
    port: 3306
    database: punishments
    username: root
    password: password

# Punishments
punishments:
  Hacking:
    reason: Hacking
    filter-revoked-punishments: false
    forgiveness: 100d
    icon:
      position: 10
      name: <red>Hacking
      material: BOOK
      lore:
      - ' '
      - '<white>Violation #1: <yellow>7 days <red>(BAN)'
      - '<white>Violation #2: <yellow>30 days <red>(BAN)'
      - '<white>Violation #3: <yellow>Permanent <red>(IP BAN)'
      - ' '
      - '<white>Total Punishments: <yellow>%total%'
    ladder:
      FIRST:
        length: 30d
        category: BAN
        force-silent: true
        ip: false
        commands:
        - lp user %player% parent remove VIP

# Authors: ericlmao

```

{% endcode %}


# messages.yml

{% hint style="info" %}
All plugin messages use the **MiniMessage** format.&#x20;

For more information:

* Documentation: <https://docs.advntr.dev/minimessage/index.html>
* Web UI: <https://webui.advntr.dev/>
  {% endhint %}

{% code fullWidth="true" %}

```yaml
SPECIFY_PUNISHMENT:
- <red><bold>ERROR!</bold> <gray>Please specify a punishment!
INVALID_PUNISHMENT:
- <red><bold>ERROR!</bold> <gray>The punishment of '<red>%argument%</red>' cannot
  be found.
CANNOT_PUNISH_SELF:
- <red><bold>ERROR!</bold> <gray>You cannot punish yourself!
STAFF_HISTORY_MISSING_PROFILES:
- <gray><i>Some records are missing critical data to be displayed, so they have been
  omitted.
RELOAD:
- <green><bold>SUCCESS!</bold> <gray>Reloaded configuration files!
NOTE_NOTICE_TOGGLE_ON:
- <green><bold>SUCCESS!</bold> <gray>You have toggled note notices <dark_green><bold>ON</bold></dark_green>!
NOTE_NOTICE_TOGGLE_OFF:
- <green><bold>SUCCESS!</bold> <gray>You have toggled note notices <red><bold>OFF</bold></red>!
NOTE_NOTICE:
- <aqua>[Alert] <gray>Player <aqua>%player%</aqua> has joined and has <aqua>%amount%</aqua>
  notes (<red>%severe%</red> severe).
NOTE_CREATE_PROMPT:
- <aqua>[Alert] <gray>Please enter the note you would like to attach to this user.
- <gray><i><click:suggest_command:'cancel'>Click this message or type <red>cancel</red>
  to cancel!</click>
NOTE_CREATE_CANCELLED:
- <red><bold>CANCELLED!</bold> <gray>You have canceled the note creation process!
NOTE_CREATED:
- <green><bold>SUCCESS!</bold> <gray>You have created a note for <aqua>%player%</aqua>!
NOTE_EDIT_PROMPT:
- <aqua>[Alert] <gray>Please enter the new content of the note you would like to change!
- <gray><i><click:run_command:'cancel'>Click this message or type <red>cancel</red>
  to cancel!</click>
NOTE_EDIT_CANCELLED:
- <red><bold>CANCELLED!</bold> <gray>You have cancelled the note editorial process!
NOTE_EDITED:
- <green><bold>SUCCESS!</bold> <gray>You have edited the content for the note!
NOTE_DELETE_CONFIRMED:
- <aqua>[Alert] <gray>You have successfully deleted the note.

```

{% endcode %}


# Menus

An overview of all menu configurations provided by the plugin.

{% hint style="info" %}
All plugin menus and menu buttons use the **MiniMessage** format!

For more information:

* Documentation: <https://docs.advntr.dev/minimessage/index.html>
* Web UI: <https://webui.advntr.dev/>
  {% endhint %}


# history-main.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /history <player>
# -------------------------------------------------------

# The title of the menu.
title: History of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 3

#  
# The categories that will be displayed in the menu.
#  
# Current categories: BAN, MUTE, WARN, KICK
#  
categories:
  BAN:
    display-name: <red><b>Ban History
    material: RED_WOOL
    amount: 1
    slot: 10
    glowing: false
    lore:
    - <gray>Click to view the ban history of %player%
  MUTE:
    display-name: <dark_gray><b>Mute History
    material: GRAY_WOOL
    amount: 1
    slot: 12
    glowing: false
    lore:
    - <gray>Click to view the mute history of %player%
  WARN:
    display-name: <green><b>Warning History
    material: GREEN_WOOL
    amount: 1
    slot: 14
    glowing: false
    lore:
    - <gray>Click to view the warning history of %player%
  KICK:
    display-name: <yellow><b>Kick History
    material: YELLOW_WOOL
    amount: 1
    slot: 16
    glowing: false
    lore:
    - <gray>Click to view the kick history of %player%

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - '11'
  - '13'
  - '15'
  - 17-26

```


# history.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you select a category
# in the main history menu.
# -------------------------------------------------------

# The title of the menu.
title: History of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 5

# What "title-page" means is if the current page is greater
# than or equal to "title-page-min", the title will add "(Page %current%)" to the end of it.
# To disable this, set "title-page-min" to 0.
title-page: (Page %current%)

# The minimum page number to show the page number in the title.
title-page-min: 2

# The item that will be used to display a history entry.
entry:
  name: '<red>Punishment #%id%'
  material: BOOK
  main:
  - <dark_gray><st>--------------------------------</dark_gray>
  - '<gray>Issuer: <red>%issuer%'
  - '<gray>Reason: <red>%reason%'
  - '<gray>Date Issued: <red>%issued%'
  expired:
  - ' '
  - <dark_gray><b>PUNISHMENT EXPIRED
  - '<gray>Expired: <red>%expires%'
  nonexpired:
  - '<gray>Date Expires: <red>%expires%'
  removed:
  - ' '
  - <dark_gray><b>PUNISHMENT REMOVED
  - '<gray>Removed by: <red>%removed-by%'
  - '<gray>Removed Reason: <red>%removed-reason%'
  bottom:
  - <dark_gray><st>--------------------------------</dark_gray>

# The slots where the history entries will be displayed.
entry-slots:
- 10-16
- 19-25
- 28-34

# The item that will be used to go to the next page.
next-page-item:
  display-name: <green>Next Page
  material: ARROW
  amount: 1
  slot: 26
  glowing: false

# The item that will be used to go to the previous page.
previous-page-item:
  display-name: <red>Previous Page
  material: ARROW
  amount: 1
  slot: 18
  glowing: false

# The item that will be used to close the history menu.
close-menu-item:
  display-name: <red>Close
  material: BARRIER
  amount: 1
  slot: 40
  glowing: false

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-44

```


# note-delete-confirmation.yml

This menu opens when you use the /history \<user> command.

```yaml
# # -------------------------------------------------------- #
# # The menu that opens when you are deleting a note.
# # -------------------------------------------------------- #

# The title of the menu.
title: Note Delete Confirmation

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 3

# The confirmation button
confirm:
  display-name: <green><b>Confirm Action
  material: GREEN_STAINED_GLASS_PANE
  amount: 1
  slot: 11
  glowing: false

# The cancel button
cancel:
  display-name: <dark_red><b>Cancel Action
  material: RED_STAINED_GLASS_PANE
  amount: 1
  slot: 15
  glowing: false

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-10
  - 12-14
  - 16-26

```


# note-editor.yml

This menu opens when you use the /history \<user> command.

```yaml
# The title of the menu.
title: Note Editor

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 3

# Severity Toggle Button
severe-note-toggle:
  slot: 13
  on:
    display-name: <red><b>Severe Note
    material: REDSTONE_TORCH
    amount: 1
    slot: -1
    glowing: false
    lore:
    - <gray>Click to mark this note as <green>normal</green>.
  off:
    display-name: <green><b>Severe Note
    material: SOUL_TORCH
    amount: 1
    slot: -1
    glowing: false
    lore:
    - <gray>Click to mark this note as <red>severe</red>.

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-10
  - '12'
  - '14'
  - 16-26

```


# notes.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /notes <player>
# -------------------------------------------------------

# The title of the menu.
title: Notes of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 5

# The date format used to display the date of a note.
date-format: MM/dd/yyyy HH:mm:ss

# The item that will be used to display a note entry.
entry:
  display-name: ' '
  material: PAPER
  amount: 1
  slot: -1
  glowing: false
  lore:
  - <dark_gray><st>--------------------------------
  - '<gray>Issuer: <red>%issuer%'
  - '<gray>Date Issued: <red>%issued%'
  - '<gray>Last Edited: <red>%edited%'
  - <dark_gray><st>--------------------------------
  - <reset>%content%
  - <dark_gray><st>--------------------------------

# The slots where the note entries will be displayed.
entry-slots:
- 10-16
- 19-25
- 28-34

# The button to go to the next page.
next:
  display-name: <green>Next Page
  material: ARROW
  amount: 1
  slot: 26
  glowing: false

# The button to go to the previous page.
previous:
  display-name: <red>Previous Page
  material: ARROW
  amount: 1
  slot: 18
  glowing: false

# The button to add a new note.
add:
  display-name: <green><b>Add Note
  material: ANVIL
  amount: 1
  slot: 40
  glowing: false
  lore:
  - <gray>Click to add a new note.

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-44

```


# punish-confirm.yml

This menu opens when you use the /history \<user> command.

```yaml
#  -------------------------------------------------------
#  The menu that opens when you attempt to punish a player.
#  -------------------------------------------------------

# The title of the menu.
title: Confirm Punishment

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 3

# The item showed for issuing silent punishments
silent-option:
  display-name: <gray>Silent Punishment
  material: LIGHT_GRAY_WOOL
  amount: 1
  slot: 15
  glowing: false
  lore:
  - <gray>Click to punish %player% silently.

# The item showed for issuing public punishments
public-option:
  display-name: <red>Public Punishment
  material: RED_WOOL
  amount: 1
  slot: 11
  glowing: false
  lore:
  - <gray>Click to punish %player% public.

# Fillers are used to fill empty slots in the menu.
fillers: {}

```


# punish.yml

This menu opens when you use the /history \<user> command.

```yaml
#  -------------------------------------------------------
#  The menu that opens when you use /punish <player>
#   
#  To edit the punishment icons, see main.yml!
#  -------------------------------------------------------

# The title of the menu.
title: Punish %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 6

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-36
  - 44-53
```


# records-main.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /record.
# -------------------------------------------------------

# The title of the menu.
title: Your Punishment History

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 3

#  
# The categories that will be displayed in the menu.
#  
# Current categories: BAN, MUTE, WARN, KICK
#  
categories:
  BAN:
    display-name: <red><b>Ban History
    material: RED_WOOL
    amount: 1
    slot: 10
    glowing: false
    lore:
    - <gray>Click to view your ban history
  MUTE:
    display-name: <dark_gray><b>Mute History
    material: GRAY_WOOL
    amount: 1
    slot: 12
    glowing: false
    lore:
    - <gray>Click to view your mute history
  WARN:
    display-name: <green><b>Warning History
    material: GREEN_WOOL
    amount: 1
    slot: 14
    glowing: false
    lore:
    - <gray>Click to view your warning history
  KICK:
    display-name: <yellow><b>Kick History
    material: YELLOW_WOOL
    amount: 1
    slot: 16
    glowing: false
    lore:
    - <gray>Click to view your kick history

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - '11'
  - '13'
  - '15'
  - 17-26

```


# records.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you select a category
# in the main record menu.
# -------------------------------------------------------

# The title of the menu.
title: Your Punishment History

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 5
# What "title-page" means is if the current page is greater
# than or equal to "title-page-min", the title will add "(Page %current%)" to the end of it.
# To disable this, set "title-page-min" to 0.

title-page: (Page %current%)

# The minimum page number to show the page number in the title.
title-page-min: 2

# The slots where the history entries will be displayed.
entry-slots:
- 10-16
- 19-25
- 28-34

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-44

```


# records-single.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /record.
# This menu opens under the condition that
# 'record-menu-categorized' is set to 'false' in main.yml.
# -------------------------------------------------------

# The title of the menu.
title: History of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 5

# What "title-page" means is if the current page is greater
# than or equal to "title-page-min", the title will add "(Page %current%)" to the end of it.
# To disable this, set "title-page-min" to 0.
title-page: (Page %current%)

# The minimum page number to show the page number in the title.
title-page-min: 2

# The history entries that will be displayed in the menu.
# The item displayed can be different depending on the punishment category.
#  
# Current categories:
entries:
  BAN:
    name: '<red>Ban #%id%'
    material: DIAMOND_AXE
    main:
    - <dark_gray><st>--------------------------------</dark_gray>
    - '<gray>Issuer: <red>%issuer%'
    - '<gray>Reason: <red>%reason%'
    - '<gray>Date Issued: <red>%issued%'
    expired:
    - ' '
    - <dark_gray><b>PUNISHMENT EXPIRED
    - '<gray>Expired: <red>%expires%'
    nonexpired:
    - '<gray>Date Expires: <red>%expires%'
    removed:
    - ' '
    - <dark_gray><b>PUNISHMENT REMOVED
    - '<gray>Removed by: <red>%removed-by%'
    - '<gray>Removed Reason: <red>%removed-reason%'
    bottom:
    - <dark_gray><st>--------------------------------</dark_gray>
  MUTE:
    name: '<red>Mute #%id%'
    material: OAK_SIGN
    main:
    - <dark_gray><st>--------------------------------</dark_gray>
    - '<gray>Issuer: <red>%issuer%'
    - '<gray>Reason: <red>%reason%'
    - '<gray>Date Issued: <red>%issued%'
    expired:
    - ' '
    - <dark_gray><b>PUNISHMENT EXPIRED
    - '<gray>Expired: <red>%expires%'
    nonexpired:
    - '<gray>Date Expires: <red>%expires%'
    removed:
    - ' '
    - <dark_gray><b>PUNISHMENT REMOVED
    - '<gray>Removed by: <red>%removed-by%'
    - '<gray>Removed Reason: <red>%removed-reason%'
    bottom:
    - <dark_gray><st>--------------------------------</dark_gray>
  WARN:
    name: '<red>Warn #%id%'
    material: BOOK
    main:
    - <dark_gray><st>--------------------------------</dark_gray>
    - '<gray>Issuer: <red>%issuer%'
    - '<gray>Reason: <red>%reason%'
    - '<gray>Date Issued: <red>%issued%'
    expired:
    - ' '
    - <dark_gray><b>PUNISHMENT EXPIRED
    - '<gray>Expired: <red>%expires%'
    nonexpired:
    - '<gray>Date Expires: <red>%expires%'
    removed:
    - ' '
    - <dark_gray><b>PUNISHMENT REMOVED
    - '<gray>Removed by: <red>%removed-by%'
    - '<gray>Removed Reason: <red>%removed-reason%'
    bottom:
    - <dark_gray><st>--------------------------------</dark_gray>
  KICK:
    name: '<red>Kick #%id%'
    material: FEATHER
    main:
    - <dark_gray><st>--------------------------------</dark_gray>
    - '<gray>Issuer: <red>%issuer%'
    - '<gray>Reason: <red>%reason%'
    - '<gray>Date Issued: <red>%issued%'
    expired:
    - ' '
    - <dark_gray><b>PUNISHMENT EXPIRED
    - '<gray>Expired: <red>%expires%'
    nonexpired:
    - '<gray>Date Expires: <red>%expires%'
    removed:
    - ' '
    - <dark_gray><b>PUNISHMENT REMOVED
    - '<gray>Removed by: <red>%removed-by%'
    - '<gray>Removed Reason: <red>%removed-reason%'
    bottom:
    - <dark_gray><st>--------------------------------</dark_gray>

# The slots where the record entries will be displayed.
entry-slots:
- 10-16
- 19-25
- 28-34

# The item that will be used to go to the next page.
next-page-item:
  display-name: <green>Next Page
  material: ARROW
  amount: 1
  slot: 26
  glowing: false

# The item that will be used to go to the previous page.
previous-page-item:
  display-name: <red>Previous Page
  material: ARROW
  amount: 1
  slot: 18
  glowing: false

# The item that will be used to close the history menu.
close-menu-item:
  display-name: <red>Close
  material: BARRIER
  amount: 1
  slot: 40
  glowing: false

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-44

```


# staff-history-main.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /staffhistory <player>
# -------------------------------------------------------

# The title of the menu.
title: History of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 5

# The item that shows the user's statistics.
statistics:
  display-name: <aqua><b>Statistics
  material: PAPER
  amount: 1
  slot: 13
  glowing: false
  lore:
  - <dark_gray><st>--------------------------------------
  - '<gray>Total Punishments: <aqua>%total%'
  - ' '
  - '<gray>Total Bans: <aqua>%bans%'
  - '<gray>Total Mutes: <aqua>%mutes%'
  - '<gray>Total Kicks: <aqua>%kicks%'
  - '<gray>Total Warns: <aqua>%warns%'
  - ' '
  - '<gray>Staff Leaderboard Ranking: <aqua>%ranking%'
  - <dark_gray><st>--------------------------------------

#  
# The categories that will be displayed in the menu.
#  
# Current categories: BAN, MUTE, WARN, KICK
#  
categories:
  BAN:
    display-name: <red><b>Ban History
    material: RED_WOOL
    amount: 1
    slot: 19
    glowing: false
    lore:
    - <gray>Click to view the staff ban history of %player%
  MUTE:
    display-name: <dark_gray><b>Mute History
    material: GRAY_WOOL
    amount: 1
    slot: 21
    glowing: false
    lore:
    - <gray>Click to view the staff mute history of %player%
  WARN:
    display-name: <green><b>Warning History
    material: GREEN_WOOL
    amount: 1
    slot: 23
    glowing: false
    lore:
    - <gray>Click to view the staff warning history of %player%
  KICK:
    display-name: <yellow><b>Kick History
    material: YELLOW_WOOL
    amount: 1
    slot: 25
    glowing: false
    lore:
    - <gray>Click to view the staff kick history of %player%

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-12
  - 14-18
  - '20'
  - '22'
  - '24'
  - 26-35

```


# staff-history.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you select a category
# in the main staff-history menu.
# -------------------------------------------------------

# The title of the menu.
title: History of %player%

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 4

# What "title-page" means is if the current page is greater
# than or equal to "title-page-min", the title will add "(Page %current%)" to the end of it.
# To disable this, set "title-page-min" to 0.
title-page: (Page %current%)

# The minimum page number to show the page number in the title.
title-page-min: 2

# The item that will be used to display a history entry.
entry:
  name: '<red>Punishment #%id%'
  material: PLAYER_HEAD
  main:
  - <dark_gray><st>--------------------------------</dark_gray>
  - '<gray>Offender: <red>%offender%'
  - '<gray>Reason: <red>%reason%'
  - '<gray>Date Issued: <red>%issued%'
  expired:
  - ' '
  - <dark_gray><b>PUNISHMENT EXPIRED
  - '<gray>Expired: <red>%expires%'
  nonexpired:
  - '<gray>Date Expires: <red>%expires%'
  removed:
  - ' '
  - <dark_gray><b>PUNISHMENT REMOVED
  - '<gray>Removed by: <red>%removed-by%'
  - '<gray>Removed Reason: <red>%removed-reason%'
  bottom:
  - <dark_gray><st>--------------------------------</dark_gray>

# The slots where the history entries will be displayed.
entry-slots:
- 10-16
- 19-25
- 28-34

# The item that will be used to go to the next page.
next-page-item:
  display-name: <green>Next Page
  material: ARROW
  amount: 1
  slot: 26
  glowing: false

# The item that will be used to go to the previous page.
previous-page-item:
  display-name: <red>Previous Page
  material: ARROW
  amount: 1
  slot: 18
  glowing: false

# The item that will be used to close the history menu.
close-menu-item:
  display-name: <red>Close
  material: BARRIER
  amount: 1
  slot: 40
  glowing: false

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-9
  - 17-18
  - 26-27
  - 35-44

```


# staff-leaderboard.yml

This menu opens when you use the /history \<user> command.

```yaml
# -------------------------------------------------------
# The menu that opens when you use /staffleaderboard
# -------------------------------------------------------

# The title of the menu.
title: Staff Leaderboard

# The amount of rows in the menu.
# Can be between 1 and 6.
rows: 6

# The statistics item that shows the user's staff statistics.
statistics:
  display-name: <aqua>Your Statistics
  material: PAPER
  amount: 1
  slot: 40
  glowing: false
  lore:
  - <dark_gray><st>--------------------------------
  - '<gray>Total Punishments: <red>%total%'
  - ' '
  - '<gray>Total Bans: <red>%bans%'
  - '<gray>Total Mutes: <red>%mutes%'
  - '<gray>Total Kicks: <red>%kicks%'
  - '<gray>Total Warns: <red>%warns%'
  - ' '
  - '<gray>Ranking: <aqua>%ranking%'
  - <dark_gray><st>--------------------------------

# The positions that are displayed in the leaderboard.
positions:
  8:
    display-name: <gray><b>8th Place
    material: PLAYER_HEAD
    slot: 24
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  9:
    display-name: <gray><b>9th Place
    material: PLAYER_HEAD
    slot: 26
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  1:
    display-name: <red><b>1st Place
    material: PLAYER_HEAD
    slot: 4
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  2:
    display-name: <dark_gray><b>2nd Place
    material: PLAYER_HEAD
    slot: 11
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  3:
    display-name: <gray><b>3rd Place
    material: PLAYER_HEAD
    slot: 13
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  4:
    display-name: <gray><b>4th Place
    material: PLAYER_HEAD
    slot: 15
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  5:
    display-name: <gray><b>5th Place
    material: PLAYER_HEAD
    slot: 18
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  6:
    display-name: <gray><b>6th Place
    material: PLAYER_HEAD
    slot: 20
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------
  7:
    display-name: <gray><b>7th Place
    material: PLAYER_HEAD
    slot: 22
    lore:
    - <dark_gray><st>--------------------------------
    - '<gray>Staff Member: <red>%player%'
    - ' '
    - '<gray>Total Punishments: <red>%total%'
    - ' '
    - '<gray>Total Bans: <red>%bans%'
    - '<gray>Total Mutes: <red>%mutes%'
    - '<gray>Total Kicks: <red>%kicks%'
    - '<gray>Total Warns: <red>%warns%'
    - <dark_gray><st>--------------------------------

# Fillers are used to fill empty slots in the menu.
fillers:
  BLACK_STAINED_GLASS_PANE:
  - 0-3
  - 5-10
  - '12'
  - '14'
  - 16-17
  - '19'
  - '21'
  - '23'
  - '25'
  - 27-39
  - 41-53

```


# alumina

A powerful and modern plugin library to streamline the process of developing Minecraft plugins!

{% hint style="warning" %}
This wiki is currently in development and may not have all up-to-date documentation.
{% endhint %}

## Useful Resources

JavaDocs: <https://jd.alumina.dev/>

## Adding alumina

<details>

<summary>Maven</summary>

**Repository**

```xml
<repository>
    <id>Negative Games</id>
    <url>https://repo.negative.games/repository/maven-releases/</url>
</repository>
```

**Dependency**

```xml
<dependency>
    <groupId>games.negative.alumina</groupId>
    <artifactId>alumina</artifactId>
    <version>VERSION</version>
    <scope>compile</scope>
</dependency>
```

**Shading**

While optional, it is highly recommended to shade alumina to match your project's namespace; when multiple plugins use alumina on a server, it may produce some unexpected outcomes.

```xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.5.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <relocations>
                    <relocation>
                        <pattern>games.negative.alumina</pattern>
                        <shadedPattern>[YOUR NAMESPACE].alumina</shadedPattern>
                    </relocation>
                </relocations>
            </configuration>
        </execution>
    </executions>
</plugin>
```

</details>

<details>

<summary>Gradle</summary>

**Repository**

```gradle
maven { url 'https://repo.negative.games/repository/maven-releases/' }
```

**Dependency**

```gradle
implementation("games.negative.alumina:alumina:VERSION")
```

**Shading**

While optional, it is highly recommended to shade alumina to match your project's namespace; when multiple plugins use alumina on a server, it may produce some unexpected outcomes.

**`Shadow Plugin`**

The shadow-jar plugin is required to shade alumina into your project.

```gradle
plugins {
    id 'java'
    id "com.github.johnrengelman.shadow" version "7.1.2"
}
```

**`Build-Task-Dependency`**

While it is optional to have this because you can do <mark style="color:green;">`gradle shadowJar`</mark>, it is recommended to add the following declaration so your <mark style="color:green;">`gradle build`</mark> will automatically shade alumina.

```gradle
tasks {
    build {
        dependsOn(shadowJar)
    }
}
```

**`ShadowJar Task`**

This is the bread & butter of the shading process, and this declaration is required to shade alumina in your project.

<pre class="language-gradle"><code class="lang-gradle">def group = 'com.myplugin.plugin' // Not required
def id = 'MyAmazingPlugin' // Not required
<strong>
</strong><strong>shadowJar {
</strong>    archiveBaseName.set("${id}")
    archiveClassifier.set("")
    archiveVersion.set("")

    relocate("games.negative.alumina", "${group}.libs.alumina")
}
</code></pre>

</details>

## Adding <mark style="color:blue;">`AluminaPlugin`</mark>

The <mark style="color:green;">`AluminaPlugin`</mark> class, which extends <mark style="color:green;">`JavaPlugin`</mark>, is a required class for alumina to function, as the library does some logic behind the scenes when the plugin starts.

When being used, the <mark style="color:green;">`AluminaPlugin`</mark> class has three abstract methods that are required to be implemented, which is [<mark style="color:purple;">`load()`</mark>](#user-content-fn-1)[^1], [<mark style="color:purple;">`enable()`</mark>](#user-content-fn-2)[^2], and [<mark style="color:purple;">`disable()`</mark>](#user-content-fn-3)[^3].

<details>

<summary>Example Class</summary>

```java
public class ExamplePlugin extends AluminaPlugin {
    
    @Override
    public void load() {
        
    }

    @Override
    public void enable() {
        // Register listeners, commands, etc.
    }

    @Override
    public void disable() {

    }
    
}
```

</details>

[^1]: This method takes over for the <mark style="color:green;">`JavaPlugin`</mark>'s <mark style="color:purple;">`onLoad()`</mark> method.

[^2]: This method takes over for the <mark style="color:green;">`JavaPlugin`</mark>'s <mark style="color:purple;">`onEnable()`</mark> method.

[^3]: This method takes over for the <mark style="color:green;">`JavaPlugin`</mark>'s <mark style="color:purple;">`onDisable()`</mark> method.


# ItemBuilder

The ItemBuilder class is expansive, allowing you to customize your ItemStack in many ways in a builder environment.

There are over 30 methods in the ItemBuilder for you to use to customize your ItemStack!

<details>

<summary>Example</summary>

In this example, we make a Diamond Sword with a custom name, lore, and enchantments.

```java
ItemStack sword = new ItemBuilder(Material.DIAMOND_SWORD)
    .setName("<red>Amazing Sword") // Names are in MiniMessage format
    //.setName(Component.text("Amazing Sword")) // or alternatively in Component format
                
    .setLore("<gray>It's amazing!") // Lore is in MiniMessage format
    //.setLore(Component.text("It's amazing!")) // or alternatively in Component format

    .addEnchantment(Enchantment.DAMAGE_ALL, 5)
    .addEnchantment(Enchantment.DURABILITY, 3)
    .build();
```

</details>


# PotionBuilder

A simple yet fantastic way of building Potion Effects!

<details>

<summary>Example</summary>

```java
PotionEffect effect = new PotionBuilder(PotionEffectType.SPEED)
    .duration(-1) // infinite duration
    .amplifier(0) // for level 1
    .particles(true) // show particles
    .build();
```

</details>


# InputListener

This utility is a great way to capture a player's next chat message and execute logic based on it. This type of feature is typically used for "confirmation" messages where the user will have to say a certain word or message to confirm or cancel a certain action.

<details>

<summary>Example</summary>

```java
UUID uuid = UUID.randomUUID(); // should be a player's uuid!
InputListener.listen(uuid, event -> {
    if (!(event.originalMessage() instanceof TextComponent text)) return;

    String message = text.content();

    Player player = event.getPlayer();
            
    if (message.equalsIgnoreCase("hi")) {
        player.sendMessage(Component.text("Hello!"));
    }
});
```

</details>


# Commands

The command system is very flexible and efficient. It allows you to create commands without registering them in a plugin.yml and a few cool features to reduce boilerplate.

## Creating a Command

To create a command, you will need to create a class which extends <mark style="color:green;">`games.negative.alumina.command.Command`</mark>, which is easily mistaken for <mark style="color:red;">`org.bukkit.command.Command`</mark>, so be sure you're importing the correct one!

<details>

<summary>Example</summary>

```java
public class ExampleCommand extends Command {
    
    public ExampleCommand() {
        super(
                CommandProperties.builder()
                        .name("example") // main command label
                        .aliases(List.of("myexamplecommand")) // command aliases
                        .permissions(List.of(new Permission("example.permission"))) // command permissions
                        .playerOnly(true) // Only players can execute this command
                        //.consoleOnly(true) // Only console can execute this command
                        .description("This is an example command") // command description
                        .usage("/example mine") // command usage
                        .params(List.of("message")) // command (required) parameters
                        .smartTabComplete(true) // Smart tab completion
                .build());
    }

    @Override
    public void execute(@NotNull Context context) {
        // We can use context to get the player who executed the command
        // and we can use orElseThrow() because we have
        // player-only enabled, so the player will always be present
        Player player = context.player().orElseThrow();

        // Alternatively we can get the command sender
        // if we're not sure if the command sender is a player
        CommandSender sender = context.sender();

        // We can also get "argument" 0 from the context
        // because we have a required parameter, so the check if
        // the argument is present is not needed here as its done
        // in the background.
        String message = context.argument(0).orElseThrow();
        
        player.sendMessage(Component.text(message));
    }
    
}
```

</details>

## Understanding `CommandProperties`

The CommandProperties class is a builder for the command system, which gives you a lot of flexibility when designing your command properties with a vast array of options!

Here is a detailed description of all CommandProperties methods:

<table><thead><tr><th width="232">Method</th><th>Description</th></tr></thead><tbody><tr><td><code>name()</code></td><td>The name of the command.</td></tr><tr><td><code>description()</code></td><td>The description of the command.</td></tr><tr><td><code>usage()</code></td><td>The usage of the command.</td></tr><tr><td><code>aliases()</code></td><td>The aliases of the command.</td></tr><tr><td><code>permissions()</code></td><td>A list of permissions that only require the executor to have at least one to be allowed to use the command.</td></tr><tr><td><code>params()</code></td><td>A list of required parameters, or "arguments," for the command to execute correctly. The command will fail to execute if the executor has not completed the required parameters in their command.</td></tr><tr><td><code>shortcuts()</code></td><td>Used in subcommands to allow the subcommand to also be a primary command. An example is <strong>Essentials</strong> with <code>/gamemode creative</code> and <code>/gmc</code>. <code>/gmc</code> being a "shortcut".</td></tr><tr><td><code>playerOnly()</code></td><td>When true, the command becomes "player only," meaning it can only be executed by players.</td></tr><tr><td><code>consoleOnly()</code></td><td>When true, the command becomes "console-only," meaning it can only be executed by non-player objects like the Console.</td></tr><tr><td><code>smartTabComplete()</code></td><td>When true, the command automatically takes all subcommands, parameters, etc, into account and displays your command in tab-completion.</td></tr></tbody></table>

## Creating a SubCommand

There are two ways of making a subcommand, so we will display how to do both.

### Injection

Injecting a SubCommand is an alternative to creating a class to add a SubCommand, especially if the SubCommand is very short in lines of code; it will save time compared to creating an entirely new class for five lines of code, for example.

<details>

<summary>Example</summary>

```java
public class ExampleCommand extends Command {

    public ExampleCommand() {
        super(CommandProperties.builder().name("example").build());
        
        injectSubCommand(CommandProperties.builder().name("epic").build(), context -> {
            CommandSender sender = context.sender();
            
            sender.sendMessage(Component.text("This is an epic injected subcommand!"));
        });
    }

    @Override
    public void execute(@NotNull Context context) {
        // Main command logic here!
    }

}
```

</details>

### Class

In what is considered the "normal" way of creating SubCommands, you need to create an entirely separate class to run your command logic. Then, in the constructor of your main command class, you register the subcommand.

#### Creating SubCommand class

Creating a subcommand class is exactly like a regular command!

<details>

<summary>Example</summary>

```java
public class ExampleSubCommand extends Command {
    
    public ExampleSubCommand() {
        super(CommandProperties.builder().name("amazingness").build());
    }

    @Override
    public void execute(@NotNull Context context) {
        // Subcommand logic here!
    }
    
}
```

</details>

#### Registering a SubCommand

As stated before, to register a subcommand, you just invoke the addSubCommand method in the main command class. *Fun fact: You can also add subcommands to subcommand classes! It's a subcommand ception!*

<details>

<summary>Example</summary>

```java
public class ExampleCommand extends Command {

    public ExampleCommand() {
        super(CommandProperties.builder().name("example").build());

        addSubCommand(new ExampleSubCommand());
    }

    @Override
    public void execute(@NotNull Context context) {
        // Main command logic here!
    }

}
```

</details>

## Custom Tab Completion

If you wish to add your custom tab completion logic, you're able to do so by overriding the <mark style="color:green;">`onTabComplete()`</mark> method!

<details>

<summary>Example</summary>

```java
public class ExampleCommand extends Command {

    public ExampleCommand() {
        super(CommandProperties.builder().name("example").build());
    }

    @Override
    public void execute(@NotNull Context context) {
        // Main command logic here!
    }

    @Override
    public List<String> onTabComplete(@NotNull TabContext context) {
        // If the current index is 1, and the previous argument is "hello"
        if (context.index() == 1 && context.argument(0).orElseThrow().equalsIgnoreCase("hello"))
            return List.of("hi!");

        return List.of();
    }
}
```

</details>

## Registering a Command

To register a command, you must go to your main class and invoke the <mark style="color:green;">`registerCommand()`</mark> method.&#x20;

<details>

<summary>Example</summary>

```java
public class ExamplePlugin extends AluminaPlugin {
    
    @Override
    public void load() {
        
    }

    @Override
    public void enable() {

        registerCommand(new ExampleCommand());
        
    }

    @Override
    public void disable() {

    }
    
}
```

</details>


# DependencyLoader

The dependency loader system is a great way to load some of your dependencies into runtime without needing to shade them into your final jar, thus reducing the file size of your finalized jar. For example, using the dependency loader to load database drivers instead of shading them into your jar would reduce the file size of your finalized jar by hundreds of kilobytes or, in some cases, megabytes.

There are two primary ways of accessing and using the dependency loader.

### Main Class

Using your plugin's main class, which should extend <mark style="color:green;">`AluminaPlugin`</mark>, a built-in method allows you to load a dependency.

<details>

<summary>Example</summary>

```java
public class ExamplePlugin extends AluminaPlugin {

    @Override
    public void load() {
        // Loads the SQLite database driver
        loadDependency("org.xerial", "sqlite-jdbc", "3.34.0");
    }

    @Override
    public void enable() {

    }

    @Override
    public void disable() {

    }
    
}
```

</details>

### Using the DependencyLoader class

You can also directly load a dependency using the <mark style="color:blue;">`DependencyLoader`</mark> class itself using one of the static methods.

<details>

<summary>Example</summary>

```java
public class ExamplePlugin extends AluminaPlugin {

    @Override
    public void load() {
        // Loads the SQLite database driver using the DependencyLoader
        DependencyLoader.loadDependency(this, "org.xerial", "sqlite-jdbc", "3.34.0");
    }

    @Override
    public void enable() {

    }

    @Override
    public void disable() {

    }

}
```

</details>


# Events Subscriber

This utility allows you to statically and dynamically subscribe, listen, and react to events.

<details>

<summary>Example</summary>

```java
public class ExamplePlugin extends AluminaPlugin {

    @Override
    public void load() {

    }

    @Override
    public void enable() {
        Events.listen(PlayerJoinEvent.class, event -> {
            Player player = event.getPlayer();
            
            player.sendMessage(Component.text("Welcome to the server! :)").color(NamedTextColor.GREEN));
        });
    }

    @Override
    public void disable() {

    }

}
```

</details>


# Static Logger

This utility allows you to statically log messages using the Bukkit logging system, with the added benefit of a configurable variable to disallow logging "non-required" log messages, but also that restriction can be bypassed under some conditions.

<details>

<summary>Example</summary>

```java
public class ExamplePlugin extends AluminaPlugin {

    @Override
    public void load() {

    }

    @Override
    public void enable() {
        Logs.setDisabled(true); // Disable non-essential logs
        
        Logs.INFO.print("Hello, world!"); // This is a non-essential log
        
        Logs.INFO.print("Bye, world.", true); // This is an essential log
    }

    @Override
    public void disable() {

    }

}
```

</details>


