# Simple staff mod

### Introduction

In this tutorial, you will learn how to create a simple staff mod only in code using **StaffModLib** and **Bukkit**. Let's begin !

{% hint style="info" %}
The library may contain **several implementation** for different API. The one which is used here is the **Bukkit** one.
{% endhint %}

### Step 1 : Initializing manager

First of all, you have to create a new instance of the `BukkitStaffModManager` class. This class has for goal to handle all the players which are in staff mod and will be required when we'll create our staff mod.

So, let's create an instance of this class. In this tutorial, we'll store it in the main class of our plugin.

```java
public class StaffModLibExample extends JavaPlugin {

    private BukkitStaffModManager manager;

    @Override
    public void onEnable() {
        // Creating a new BukkitStaffModManager instance which will
        // be used by all the staff mods.
        this.manager = new BukkitStaffModManager(this);
    }
}
```

### Step 2 : Creating a staff mod

Now, let's create our first staff mod. To begin, you have to create a new class that extends the `SimpleBukkitStaffMod` class. It is an implementation of the `StaffMod` interface and it provides the basics to create your staff mod.

A constructor that takes as parameter an instance of the `BukkitStaffModManager` class is also needed. Furthermore, a plugin instance we'll be used to handle item listeners so we need to pass it too as a parameter of the constructor.

```java
public class SimpleStaffMod extends SimpleBukkitStaffMod {

    private final Plugin plugin;

    public SimpleStaffMod(BukkitStaffModManager manager, Plugin plugin) {
        super(manager);
        this.plugin = plugin;
    }
}
```

### Step 3 : Handling player data

Before continuing the creation of our staff mod, we would like to **save** and **clear** the current player's state to **restore** it later. Indeed, the process of setting a player in staff mod will **modify** his inventory and you may also want to **clear** some states or to **keep** others to restore them when the staff mod we'll be **disabled**.

To do that, we have to use the `PlayerDataHandler` interface. You can click on the page below to see how to use it and to get more information about it.

{% content-ref url="/pages/-MSJfbUfTkb7kY90tIYp" %}
[Handle player data](/staffmodlib/other/the-playerdata-class.md)
{% endcontent-ref %}

So, let's create a `createPlayerData()` method which will handle the creation of  `PlayerDataHandler` object. We'll use it later by adding code when enabling and disabling the staff mod.

```java
private PlayerDataHandler createPlayerData() {

    // This method has for goal to create a PlayerData object
    // which will store player state before enabling the staff mod.
    
    List<DataHandler<Player>> data = Arrays.asList(
        new InventoryDataHandler(), // Storing inventory information.
        new PotionDataHandler(), // Storing potion effects information.
        new GameModeDataHandler(), // Storing current game mode.
        new HealthDataHandler(), // Storing health information.
        new FoodDataHandler() // Storing food information.
    );
    return new PlayerDataHandler(data);
}
```

Now, write the following code in the `enable(Player holder)` and the `disable(Player holder)` methods.&#x20;

```java
@Override
public void enable(Player holder) {

    // Saving player data.
    this.handler = this.createPlayerData();
    this.handler.save(holder);
    this.handler.clear(holder);

    super.enable(holder);
}

@Override
public void disable(Player holder) {

    // Restoring player data.
    this.handler.clear(holder);
    this.handler.restore(holder);
    this.handler = null; // Avoiding reuse.

    super.disable(holder);
}
```

### Step 4 : Creating items

Now, let's create our items. In this tutorial, we'll only create an item that simulates a **freeze system**. So, to do that, you must first create a new class that inherits from the `BukkitStaffModItem` class. Now, redefine the require method and implement a constructor that takes a player instance and a plugin instance as parameter. You should have something like this:

```java
public class FreezeItem extends BukkitStaffModItem {

    private final Player holder;
    private final Plugin plugin;

    public FreezeItem(Player holder, Plugin plugin) {
        this.holder = holder;
        this.plugin = plugin;
    }

    @Override
    public ItemStack getItem() {
        return null;
    }
}
```

#### Creating the ItemStack

Now, let's create the item which will be given to the player by implementing the body of the `getItemStack()` method.

```java
@Override
public ItemStack getItem() {

    ItemStack item = new ItemStack(Material.BLAZE_ROD);
    ItemMeta meta = item.getItemMeta();
    meta.setDisplayName("§eFreeze");
    item.setItemMeta(meta);

    return item;
}
```

#### Handling events

In this part, we'll handle the events related to the freeze item that we're currently creating. So, to do that, we'll create an internal class that implements the `Listener` interface and we'll add methods to handle the events related to the freeze system.&#x20;

```java
// This class will handle the event related with the item.
private class ItemListener implements Listener {

    @EventHandler
    public void onItemUseOnEntity(ItemUseOnEntityEvent event) {

        Player player = event.getPlayer();

        // Necessary. Checking that the holder of the items and the player
        // associated with the event are the sames.
        if(!player.equals(getHolder())) return;

        // Necessary. Checking that the current item and the items associated
        // with the event are the sames.
        if(!event.getStaffModItem().equals(FreezeItem.this)) return;

        Entity entity = event.getEntity();

        // If the entity isn't a Player, return.
        if(!(entity instanceof Player)) return;

        Player target = (Player) entity;

        // Note that in this example, only messages are sent.
        // You should create by yourself the freeze logic.
        player.sendMessage(String.format("%s is now frozen.", target.getName()));
        target.sendMessage(String.format("You have been frozen by %s.", player.getName()));

        // Cancelling the interaction.
        event.setCancelled(true);
    }
    
    @EventHandler
    public void onItemUse(ItemUseEvent event) {
        event.setCancelled(true);
        event.getPlayer().updateInventory(); // Preventing display bugs.
    }

    @EventHandler
    public void onItemUseOnBlock(ItemUseOnBlockEvent event) {
        event.setCancelled(true);
        event.getPlayer().updateInventory(); // Preventing display bugs.
    }
}
```

You can see that I'm using a custom event called `ItemUseOnEntityEvent`. If you want to learn more about it and the other custom events provided by the library, you can click on the page below.

{% content-ref url="/pages/-MSUPdBNpjM8tndymlcQ" %}
[Custom events](/staffmodlib/other/custom-events.md)
{% endcontent-ref %}

Now, let's handle this listener by overriding the `onRegister()` and the `onUnregister()` methods of the `FreezeItem` class. Before doing that, don't forget to create an instance variable which will store our listener instance and which will allow us to unregister the listener when the item will be unregistered.

```java
private Listener listener;

// ...

@Override
public void onRegister() {
    // Registering our listener. Don't forget to store it into an instance variable
    // to allow to unregister it later.
    this.listener = new ItemListener();
    Bukkit.getPluginManager().registerEvents(this.listener, this.plugin);
}

@Override
public void onUnregister() {
    // Unregistering the listener.
    HandlerList.unregisterAll(this.listener);
}

// ...
```

#### Final result

You can see the whole class below. Now, you have to follow the previously mentioned steps and adapt them to each item that you want to create.

```java
public class FreezeItem extends BukkitStaffModItem {

    private final Player holder;
    private final Plugin plugin;
    
    private Listener listener;

    public FreezeItem(Player holder, Plugin plugin) {
        this.holder = holder;
        this.plugin = plugin;
    }
    
    @Override
    public void onRegister() {
        this.listener = new ItemListener();
        Bukkit.getPluginManager().registerEvents(this.listener, this.plugin);
    }
    
    @Override
    public void onUnregister() {
        HandlerList.unregisterAll(this.listener);
    }

    @Override
    public ItemStack getItem() {
    
        ItemStack item = new ItemStack(Material.BLAZE_ROD);
        ItemMeta meta = item.getItemMeta();
        meta.setDisplayName("§eFreeze");
        item.setItemMeta(meta);
    
        return item;
    }
    
    private class ItemListener implements Listener {
    
        @EventHandler
        public void onItemUseOnEntity(ItemUseOnEntityEvent event) {
    
            Player player = event.getPlayer();
    
            if(!player.equals(getHolder())) return;
    
            if(!event.getStaffModItem().equals(FreezeItem.this)) return;
    
            Entity entity = event.getEntity();
    
            if(!(entity instanceof Player)) return;
    
            Player target = (Player) entity;
    
            player.sendMessage(String.format("%s is now frozen.", target.getName()));
            target.sendMessage(String.format("You have been frozen by %s.", player.getName()));
    
            event.setCancelled(true);
        }
        
        @EventHandler
        public void onItemUse(ItemUseEvent event) {
            event.setCancelled(true);
            event.getPlayer().updateInventory();
        }
    
        @EventHandler
        public void onItemUseOnBlock(ItemUseOnBlockEvent event) {
            event.setCancelled(true);
            event.getPlayer().updateInventory();
        }
    }
}
```

### Step 5 : Registering the items

Now, we'll register the item that has been previously created into our staff mod. To share responsibilities between the methods, we'll create a `registerItems(Player player)` method which will handle items registration. So, open your `SimpleStaffMod` class and write the following code.

```java
public void registerItems(Player player) {
    
    // Declaring the item.
    StaffModItem freezeItem = new FreezeItem(player, this.plugin);
    
    // Setting its slot.
    freezeItem.setSlot(0);
    
    // Registering it.
    super.registerItem(freezeItem);
}
```

{% hint style="info" %}
Note that the slot of the item must be a number between 0 and 8.
{% endhint %}

And then, add call this method into the `enable(Player holder)` method:

```java
@Override
public void enable(Player holder) {

    // Registering items.
    this.registerItems(holder);
    
    // Some code...
}
```

### Step 6 : Final result

```java
public class SimpleStaffMod extends BukkitStaffMod {

    private final Plugin plugin;
    private DataHandler<Player> handler;

    public SimpleStaffMod(BukkitStaffModManager manager, Plugin plugin) {
        super(manager);
        this.plugin = plugin;
    }
    
    @Override
    public void enable(Player holder) {

        this.registerItems(holder);

        this.handler = this.createPlayerData();
        this.handler.save(holder);
        this.handler.clear(holder);

        super.enable(holder);
    }

    @Override
    public void disable(Player holder) {

        this.handler.clear(holder);
        this.handler.restore(holder);
        this.handler = null;

        super.disable(holder);
    }

    private void registerItems(Player player) {

        StaffModItem freezeItem = new FreezeItem(player, this.plugin);
        freezeItem.setSlot(0);

        this.registerItem(freezeItem);
    }

    private PlayerDataHandler createPlayerData() {

        List<DataHandler<Player>> data = Arrays.asList(
                new InventoryDataHandler(),
                new PotionDataHandler(),
                new GameModeDataHandler(),
                new HealthDataHandler(),
                new FoodDataHandler()
        );
        return new PlayerDataHandler(data);
    }
}
```

### Step 7 : Enable or disable the staff mod

In the two examples below, we'll suppose that we have access to instances of the `Plugin` and the `BukkitStaffModManager` classes. We'll also suppose that we have access to an instance of the `Player` class. First of all, we'll see how to enable the staff mod for a player.&#x20;

```java
SimpleStaffMod staffMod = new SimpleStaffMod(modManager, plugin);
staffMod.enable(player);
```

Now, let's see how to retrieve the staff mod a player is currently in and how to disable it.

```java
Optional<StaffMod<Player, ItemStack>> optional = modManager.getStaffMod(player);
optional.ifPresent(staffMod -> staffMod.disable(player));
```

Now, you know how to create your own staff mod very easily. In the next tutorials, we'll see how to create more advanced staff mods like a configurable or a pageable staff mod.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://syrows-development.gitbook.io/staffmodlib/create-a-staff-mod/simple-staff-mod.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
