Simple staff mod

This page is a tutorial about how to create a simple staff mod using StaffModLib.

Introduction

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

The library may contain several implementation for different API. The one which is used here is the Bukkit one.

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.

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.

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.

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.

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.

@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:

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.

@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.

// 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.

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.

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.

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.

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);
}

Note that the slot of the item must be a number between 0 and 8.

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

@Override
public void enable(Player holder) {

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

Step 6 : Final result

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.

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.

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.

Last updated