MissionPouches

Commands & Permissions

MissionPouches has a variety of commands and permissions, allowing you to give pouches to your players, list available expansions, reload the plugin and more.

Note: <> are mandatory arguments, and [] are optional arguments.

 

Permissions

NOTE: Every pouch can have its own permission, and random actions can have permission checks as well.

Creating a Pouch

Creating a pouch is relatively simple once you understand the configuration.

This is a full example pouch configuration file:

name: Example
weight: 0.1

lockedItem:
  material: DIAMOND_BLOCK
  name: '<red><bold>Example Pouch'
  lore:
    - '<gray>Break 100 cobblestone blocks and'
    - '<gray>10 diamond ores to unlock this pouch!'
    - ''
    - '<yellow>Cobblestone: %progress_breakCobblestone%/%goal_breakCobblestone%'
    - '<yellow>Diamond Ores: %progress_breakDiamonds%/%goal_breakDiamonds%'
unlockedItem:
  material: DIAMOND_BLOCK
  name: '<green><bold>Example Pouch'
  lore:
    - '<gray>Break 100 cobblestone blocks and'
    - '<gray>10 diamond ores to unlock this pouch!'
    - ''
    - '<yellow>Click to open!'

singleMission: false
missions:
  breakCobblestone:
    type: BLOCK_BREAK
    goal: 100
    parameters:
      blocks:
        - COBBLESTONE
  breakDiamonds:
    type: BLOCK_BREAK
    goal: 10
    parameters:
      blocks:
        - DIAMOND_ORE

expireTime: -1

pouchUpgrade: Example2

recipe:
  shape:
    - AAA
    - ABA
    - AAA
  ingredients:
    A: GLASS
    B: NETHER_STAR

actions:
  guaranteed:
    - '[Message] text=<gray>Congratulations, you redeemed the Example Pouch!'
  randomAmount: 1
  random:
    '0':
      actions:
        - '[Message] text=<green>This green message can appear 50% of the time.'
      weight: 0.5
      requirePermission: false
      invertPermissionCheck: false
      permission: actions.check
    '1':
      actions:
        - '[Message] text=<red>This red message can appear 50% of the time.'
      weight: 0.5
      requirePermission: true
      invertPermissionCheck: false
      permission: actions.check

If you need more help creating your pouches, feel free to reach out on Discord!

Built-in Actions

Actions allow you to define a variety of things to run whenever a pouch gets redeemed.

Actions support PlaceholderAPI and has 2 built-in placeholders:

  1. Broadcast
    • Arguments:
      • text: Text to send. Formatted in MiniMessage.
    • Example: "[Broadcast] text=<green>Test Broadcast"
  2. Console
    • Arguments:
      • cmd: Command to execute as console.
    • Example: "[Console] cmd=say Hello!"
  3. GiveEffect
  4. GiveFood
    • Arguments:
      • amount: Amount of food points to give.
    • Example: "[GiveFood] amount=5"
  5. GiveHealth
    • Arguments:
      • amount: Amount of health to give. 1 health equals to 1/2 heart.
    • Example: "[GiveHealth] amount=6"
  6. Message
    • Arguments:
      • text: Text to send. Formatted in MiniMessage.
    • Example: "[Message] text=<green>Test Message"
  7. Sudo
    • Arguments:
      • cmd: Command to execute as player.
    • Example: "[Sudo] cmd=say Hello!"
  8. PlaySound
    • Arguments:
      • sound: Sound to play. This needs to be a full Minecraft sound key. Here is a list: https://minecraft.wiki/w/Sounds.json
      • source: Sound source. Available values: AMBIENT, BLOCK, HOSTILE, MASTER, MUSIC, NEUTRAL, PLAYER, RECORD, VOICE, WEATHER. Defaults to AMBIENT.
      • volume: Sound volume. Usually goes from 0.0 to 1.0. Defaults to 1.0.
      • pitch: Sound pitch. Usually goes from 0.0 to 1.0. Defaults to 1.0.
    • Example: "[PlaySound] sound=block.note_block.bell;;source=MUSIC;;volume=1.0;;pitch=0.5"
  9. Title
    • Arguments:
      • title: Title to send. Formatted in MiniMessage.
      • subtitle: Optional subtitle to send. Also formatted in MiniMessage.
      • fadeIn: Fade in time.
      • stay: How long the title stays on screen.
      • fadeOut: Fade out time.
    • Example: "[Title] title=<green>Test;;subtitle=<yellow>Test 2;;fadeIn=50;;stay=100;;fadeOut=50"

If you need more actions, contact me on Discord!

Built-in Mission Types

MissionPouches comes with a few built-in mission types.

If you need a custom mission type, let me know on Discord!

Developer API

Repository Information

Maven:

<repository>
    <id>mysticalkingdoms-public</id>
    <url>https://nexus.mysticalkingdoms.com/repository/public/</url>
</repository>

Gradle:

    maven {
        url = uri('https://nexus.mysticalkingdoms.com/repository/public/')
    }

To create your own expansion, you first need to have a main class that will handle enabling, disabling and reloading the expansion, just like a plugin. This is an example of a main class for an expansion:

package com.mysticalkingdoms.pouchexpansion.cratereloaded;

import com.mysticalkingdoms.missionpouches.MissionPouches;
import com.mysticalkingdoms.missionpouches.missions.MissionExpansion;
import com.mysticalkingdoms.missionpouches.missions.MissionExpansionDescription;
import com.mysticalkingdoms.pouchexpansion.cratereloaded.types.CrateReloadedOpen;

import java.io.File;

public class CrateReloadedExpansion extends MissionExpansion {

    public CrateReloadedExpansion(MissionPouches plugin, MissionExpansionDescription expansionDescription, File dataFolder) {
        super(plugin, expansionDescription, dataFolder);
    }

    @Override
    protected boolean onEnable() {
        registerMissionTypes(new CrateReloadedOpen(getPlugin()));
        return true;
    }

    @Override
    protected void onDisable() {}

    @Override
    protected void onReload() {}
}

Keep the constructor as is, otherwise your expansion will not load.

Now, for your mission type, you need to extend the class "MissionType".

There are two ways to create this class. The first one uses a Function that gives you a ConfigurationSection (the pouch configuration), and expects MissionProgress as the return value.

You must specify a mission type key. This should be unique. A good idea is to prefix it with the name of your plugin/expansion.

package com.mysticalkingdoms.pouchexpansion.cratereloaded.types;

import com.hazebyte.crate.api.event.CrateRewardEvent;
import com.mysticalkingdoms.missionpouches.MissionPouches;
import com.mysticalkingdoms.missionpouches.missions.MissionProgress;
import com.mysticalkingdoms.missionpouches.missions.MissionType;
import org.bukkit.event.EventHandler;

import java.util.List;

public class CrateReloadedOpen extends MissionType {
    public CrateReloadedOpen(MissionPouches plugin) {
        super(plugin, "CRATERELOADED_OPEN");
    }

    @EventHandler
    public void onReward(CrateRewardEvent event) {
        checkPouches(event.getPlayer(), section -> {
            if (section == null) {
                return MissionProgress.of(1L, true);
            }

            List<String> crates = section.getStringList("crates");
            if (crates.isEmpty()) {
                return MissionProgress.of(1L, true);
            }

            return MissionProgress.of(crates.contains(event.getCrate().getCrateName()) ? 1L : 0L, true);
        });
    }
}

MissionType implements Listener, so you can listen to any Bukkit events. In the example above, we're listening to CrateRewardEvent, and then calling checkPouches on the player, we get the ConfigurationSection for the pouch configuration, we do our checks, and then finally return MissionProgress. MissionProgress has 2 static methods:

Notes:

  1. The ConfiguratIonSection from the function can be null, for example, if the user didn't specify any parameters.

Now, there's a second version which gives you access to the NBTItem of the pouch when it's being checked.

This is an example of an expansion that uses it:

package com.mysticalkingdoms.pouchexpansion.uniquekills.types;

import de.tr7zw.changeme.nbtapi.NBTList;
import com.mysticalkingdoms.missionpouches.MissionPouches;
import com.mysticalkingdoms.missionpouches.missions.MissionProgress;
import com.mysticalkingdoms.missionpouches.missions.MissionType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.PlayerDeathEvent;

import java.util.UUID;

public class UniqueKillsType extends MissionType {
    public UniqueKillsType(MissionPouches plugin) {
        super(plugin, "UNIQUEKILLS_KILL");
    }

    @EventHandler
    public void onKill(PlayerDeathEvent event) {
        Player killer = event.getEntity().getKiller();
        if (killer == null) {
            return;
        }

        checkPouches(killer, (section, nbtItem) -> {
            NBTList<UUID> list = nbtItem.getUUIDList("PlayersKilled");
            if (list.contains(event.getEntity().getUniqueId())) {
                return MissionProgress.noProgress();
            }

            list.add(event.getEntity().getUniqueId());
            return MissionProgress.of(1L, true);
        });
    }
}

This allows you to query the item for specific things, to make your expansions even more flexible. For example, the UniqueKills expansion, available on Discord, uses this to write NBT data of which players have been killed, so that you have to kill unique players to progress through the mission.

 

If you have any questions, feel free to ask on Discord!