# 🆕 Custom Add-ons

Custom add-ons are jars you write yourself that PhoenixShop loads from its addons folder, the same way it loads its own add-ons. Like every add-on, they load on Premium only.

## Maven Dependency

```xml
<repositories>
  <repository>
    <id>phoenix</id>
    <url>https://repo.phoenixplugins.com/repository/maven-public/</url>
  </repository>
</repositories>
```

```xml
<dependency>
  <groupId>com.phoenixplugins.sdk</groupId>
  <artifactId>api</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>com.phoenixplugins.phoenixshop</groupId>
  <artifactId>api</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <scope>provided</scope>
</dependency>
```

The first gives you the add-on base class, the second the shop API.

## Relocation

The PhoenixShop jar relocates the SDK, so your add-on has to point at the same package or it will not find the base class. Add the shade plugin with this relocation, without bundling anything:

```xml
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <artifactSet>
          <includes>
            <include>${project.groupId}:${project.artifactId}</include>
          </includes>
        </artifactSet>
        <relocations>
          <relocation>
            <pattern>com.phoenixplugins.sdk</pattern>
            <shadedPattern>com.phoenixplugins.phoenixshop.sdk</shadedPattern>
          </relocation>
        </relocations>
      </configuration>
    </execution>
  </executions>
</plugin>
```

## addon.yml

Create an `addon.yml` file in your project resources folder.

```yaml
name: AddonName
main: your.path.AddonExample
version: 1.0.0
description: Small description (optional)
color: "#3fb950"
```

| Field | Required | What it does |
| ----- | -------- | ------------ |
| `name` | Yes | The name of the add-on. Spaces are turned into underscores, and it names the add-on's data folder. |
| `main` | Yes | The full path to your class that extends `Addon`. |
| `version` | Yes | The version of your add-on. |
| `description` | No | A short description. |
| `color` | No | A hex color for the add-on's name in the console. |

## Main Class

```java
package your.path;

import com.phoenixplugins.phoenixshop.api.PhoenixShopAPI;
import com.phoenixplugins.sdk.api.plugin.addons.Addon;

public class AddonExample extends Addon {

    @Override
    public void init() {
    }

    @Override
    public void load() throws Exception {
    }

    @Override
    public void unload() {
    }

    @Override
    public void reload() throws Exception {
        unload();
        load();
    }

    @Override
    public String getRequiredPluginVersion() {
        return "1.0.0";
    }
}
```

| Method | When it runs |
| ------ | ------------ |
| `init` | Once, when the jar is read, before the plugin registers its hooks. Throwing here stops the add-on from loading. |
| `load` | When the plugin starts, and again on every `/pshop reload`. Register commands, listeners and tasks here. |
| `unload` | When the plugin stops, and before every reload. Undo everything `load` did. |
| `reload` | Not called by the plugin, which runs `unload` and then `load` instead. Point it at the same two so the add-on behaves the same either way. |
| `getRequiredPluginVersion` | The lowest PhoenixShop version the add-on runs on. On an older version it refuses to load. |

`getDataFolder()` returns the add-on's own folder, and `getResource(name)` reads a file out of your jar, which is how an add-on writes its default config on first start. `PhoenixShopAPI.getShopsManager()` gives you the shops.

## Events

The API module also carries Bukkit events, which any plugin can listen to, add-on or not, on Lite and Premium.

| Event | Fired | Cancellable |
| ----- | ----- | ----------- |
| `ShopPreTransactionEvent` | Before a buy or sell in a shop menu. The price can be changed. | Yes |
| `ShopTransactionEvent` | After a buy or sell in a shop menu went through. | No |
| `ShopEditEvent` | After a change made in the editor. | No |
| `PlayerShopCreateEvent` | When a chest shop is made. | No |
| `PlayerShopRemoveEvent` | When a chest shop is removed. | No |
| `PlayerShopPreTradeEvent` | Before a chest shop trade, once every check has passed and right before money or items move. | Yes |
| `PlayerShopTradeEvent` | After a chest shop trade went through. | No |

Cancelling `PlayerShopPreTradeEvent` stops the trade with nothing moved and nothing said to the player, so send your own message if they should know why. With [Click Confirm](../main-features/player-shops/settings.md#click-confirm) on, it also fires on the click that only asks the player to confirm, and cancelling it there skips the question.

Both chest shop trade events fire on the server thread (the shop's region thread on Folia) and carry:

| Getter | What it holds |
| ------ | ------------- |
| `getPlayer()` | The customer. |
| `getOwner()`, `getOwnerName()` | The shop's owner. |
| `getShopId()`, `getLocation()` | The shop's id and its sign. |
| `getKind()` | `BUY` when the customer buys, `SELL` when they sell. |
| `getItem()` | A copy of one of the traded item. |
| `getAmount()` | How many items change hands. |
| `getPrice()` | The total, in the currency or in payment items. |
| `getCurrency()` | The currency id, or `null` on a shop paid in an item. |
| `getPaymentItem()`, `paysInItems()` | A copy of the payment item on a shop paid in an item, otherwise `null`. |
| `isAdmin()` | Whether it is an admin shop. |
| `isRemote()` | Whether the customer traded from the shop list or find menu instead of at the sign. |
| `getMode()`, `getBuyPrice()`, `getSellPrice()` | The shop's mode and its prices per Amount. |

## Install

1. Build the jar with your usual build command.
2. Move it into the PhoenixShop/addons folder.
3. Restart the server.
4. Check the console for `Enabling addon` followed by your add-on's name.

Source: https://www.phoenixplugins.com/docs/phoenix-shop/add-ons/custom-addons