Last active
April 19, 2020 14:34
-
-
Save bristermitten/de7d6d96fd9b0f6117ce75b3a3f8ab7e to your computer and use it in GitHub Desktop.
A simple Spigot Custom Enchant template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.bristermitten.enchant; | |
import org.bukkit.Bukkit; | |
import org.bukkit.NamespacedKey; | |
import org.bukkit.enchantments.Enchantment; | |
import org.bukkit.enchantments.EnchantmentTarget; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.block.BlockBreakEvent; | |
import org.bukkit.inventory.ItemStack; | |
import org.bukkit.inventory.meta.ItemMeta; | |
import org.jetbrains.annotations.NotNull; | |
import java.lang.reflect.Field; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* A simple Spigot custom enchantment template. | |
* This defines a simple enchantment that creates an explosion when mining a block. | |
* Some may prefer to have a separate Listener implementation to keep the Enchantment as a POJO. | |
* You can also make an intermediary abstract class to handle the boilerplate methods that don't need implementing, such as isTreasure(). | |
* | |
* @author BristerMitten (github.com/knightzmc) | |
*/ | |
public class BreakerEnchant extends Enchantment implements Listener { | |
/** | |
* Keep it a Singleton - it makes things easier | |
*/ | |
public static final BreakerEnchant INSTANCE = new BreakerEnchant(); | |
/** | |
* ID of the enchantment. Shouldn't conflict with any others. | |
* Note that in newer Minecraft Versions (>1.15) this uses a NamespacedKey instead of an int for the ID. | |
*/ | |
private static final int ID = 500; | |
/** | |
* Our Enchantment name. | |
*/ | |
private static final String NAME = "Breaker"; | |
/** | |
* No other instances allowed. We should only refer to our Singleton instance | |
*/ | |
private BreakerEnchant() { | |
//super(ID); //For < 1.15 | |
super(new NamespacedKey(YourPluginInstance, NAME)); //For 1.15 | |
} | |
@Override | |
@NotNull | |
public String getName() { | |
return NAME; | |
} | |
/* | |
* Implement as required. Must be more than the start level. | |
* Note that this line defines where addUnsafeEnchants must be used. | |
*/ | |
@Override | |
public int getMaxLevel() { | |
return 5; | |
} | |
/* | |
* Implement as required. | |
*/ | |
@Override | |
public int getStartLevel() { | |
return 0; | |
} | |
/* | |
* Implement as required | |
*/ | |
@Override | |
@NotNull | |
public EnchantmentTarget getItemTarget() { | |
return EnchantmentTarget.ALL; | |
} | |
/* | |
* Implement as required | |
*/ | |
@Override | |
public boolean isTreasure() { | |
return false; | |
} | |
/* | |
* Implement as required | |
*/ | |
@Override | |
public boolean isCursed() { | |
return false; | |
} | |
/* | |
* Implement as required | |
*/ | |
@Override | |
public boolean conflictsWith(@NotNull Enchantment other) { | |
return false; | |
} | |
/* | |
* Implement as required | |
*/ | |
@Override | |
public boolean canEnchantItem(@NotNull ItemStack item) { | |
return true; | |
} | |
/** | |
* Example event handler. | |
* This shows the boilerplate needed for a simple handler, and can do just about anything. | |
* Obviously, this could handle any event, it's not specific to block breaking. | |
*/ | |
@EventHandler | |
public void onBlockBreak(BlockBreakEvent e) { | |
ItemStack itemInMainHand = e.getPlayer().getInventory().getItemInMainHand(); | |
if (!itemInMainHand.containsEnchantment(this)) return; | |
e.getPlayer().getWorld().createExplosion(e.getPlayer().getLocation(), 4F, false, true, e.getPlayer()); | |
//do something cool like an explosion | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* In charge of registering enchantments and enchanting items. | |
* <p> | |
* Example Usage: <pre>{@code | |
* void onEnable() { | |
* EnchantManager.registerCustomEnchantments(); | |
* //Gives level 3 | |
* EnchantManager.enchantItem(BreakerEnchant.INSTANCE, someItem, 3); | |
* } | |
* }</pre> | |
*/ | |
class EnchantManager { | |
/** | |
* You should register all of your custom enchants in here, and only once per server startup. | |
* | |
* @throws Exception if reflection fails or any enchantments are already registered | |
*/ | |
public static void registerCustomEnchantments() throws Exception { | |
//Reflection to allow registering new enchants. It's locked by default | |
Field acceptingField = Enchantment.class.getDeclaredField("acceptingNew"); | |
acceptingField.setAccessible(true); | |
acceptingField.set(null, true); | |
//Register all enchants here | |
Enchantment.registerEnchantment(BreakerEnchant.INSTANCE); | |
Bukkit.getPluginManager().registerEvents(BreakerEnchant.INSTANCE, YourPluginInstance); | |
} | |
/** | |
* Enchant an item. | |
* | |
* @param enchantment the enchantment to give | |
* @param item the item to enchant | |
* @param level the level to enchant the item to | |
*/ | |
public static void enchantItem(@NotNull Enchantment enchantment, @NotNull ItemStack item, int level) { | |
ItemMeta itemMeta = item.getItemMeta(); | |
if (itemMeta == null) return; //the item type is probably AIR | |
List<String> lore = itemMeta.getLore(); | |
if (lore == null) { | |
lore = new ArrayList<>(1); //a nice little micro-optimization since we're only adding 1 element to the list | |
} else { | |
//remove any old lore. Note that this way of doing it could break lore ordering. | |
lore.removeIf(line -> line.matches(enchantment.getName() + " [0-9]+")); | |
} | |
//Note that in 1.15 getKey().getKey() should be used instead of getName() | |
lore.add(enchantment.getName() + " " + level); | |
itemMeta.setLore(lore); | |
item.setItemMeta(itemMeta); | |
//Simple as this! Glowing is handled automatically. | |
item.addEnchantment(enchantment, level); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment