Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package dev.espi.protectionstones;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.toml.TomlFormat;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.profile.Profile;
import dev.espi.protectionstones.commands.ArgHelp;
import dev.espi.protectionstones.commands.PSCommandArg;
import dev.espi.protectionstones.placeholders.PSPlaceholderExpansion;
import dev.espi.protectionstones.utils.BlockUtil;
import dev.espi.protectionstones.utils.UUIDCache;
import dev.espi.protectionstones.utils.WGUtils;
import net.milkbowl.vault.economy.Economy;
import org.bstats.bukkit.Metrics;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.command.CommandMap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
import org.bukkit.inventory.meta.tags.ItemTagType;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import net.luckperms.api.LuckPerms;
import java.io.File;
import java.lang.reflect.Field;
import java.util.*;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The base class for the plugin. Some utilities are static, and others are instance methods, so they need to
* be accessed through getInstance().
*/
public class ProtectionStones extends JavaPlugin {
// change this when the config version goes up
public static final int CONFIG_VERSION = 13;
public static File configLocation, blockDataFolder;
public static CommentedFileConfig config;
private static List commandArgs = new ArrayList<>();
private static ProtectionStones plugin;
private PSEconomy economy;
// all configuration file options are stored in here
private PSConfig configOptions;
static HashMap protectionStonesOptions = new HashMap<>();
// ps alias to id cache
// >
static HashMap>> regionNameToID = new HashMap<>();
// vault economy integration
private boolean vaultSupportEnabled = false;
private Economy vaultEconomy;
// luckperms integration
private boolean luckPermsSupportEnabled = false;
private LuckPerms luckPerms;
private boolean placeholderAPISupportEnabled = false;
public static Set toggleList = new HashSet<>();
/* ~~~~~~~~~~ Instance methods ~~~~~~~~~~~~ */
/**
* Add a command argument to /ps.
*
* @param psca PSCommandArg object to be added
*/
public void addCommandArgument(PSCommandArg psca) {
commandArgs.add(psca);
}
/**
* @return the list of command arguments for /ps
*/
public List getCommandArguments() {
return commandArgs;
}
/**
* @return whether PlaceholderAPI support is enabled
*/
public boolean isPlaceholderAPISupportEnabled() {
return placeholderAPISupportEnabled;
}
/**
* @return whether vault support is enabled
*/
public boolean isVaultSupportEnabled() {
return vaultSupportEnabled;
}
/**
* @return returns this instance's vault economy hook
*/
public Economy getVaultEconomy() {
return vaultEconomy;
}
public PSEconomy getPSEconomy() {
return economy;
}
public boolean isLuckPermsSupportEnabled() {
return luckPermsSupportEnabled;
}
public LuckPerms getLuckPerms() {
return luckPerms;
}
/**
* @return returns the config options of this instance of ProtectionStones
*/
public PSConfig getConfigOptions() {
return configOptions;
}
/**
* @param conf config object to replace current config
*/
public void setConfigOptions(PSConfig conf) {
this.configOptions = conf;
}
/**
* Returns the list of PSProtectBlocks configured through the config.
*
* @return the list of PSProtectBlocks configured
*/
public List getConfiguredBlocks() {
List l = new ArrayList<>();
for (PSProtectBlock b : protectionStonesOptions.values()) {
if (!l.contains(b)) l.add(b);
}
return l;
}
/* ~~~~~~~~~~ Static methods ~~~~~~~~~~~~~~ */
/**
* @return the plugin instance that is currently being used
*/
public static ProtectionStones getInstance() {
return plugin;
}
/**
* @return the plugin's logger
*/
public static Logger getPluginLogger() {
return plugin.getLogger();
}
/**
* @return the PSEconomy object adapter
*/
public static PSEconomy getEconomy() {
return getInstance().getPSEconomy();
}
/**
* Get the protection block config options for the block specified.
*
* @param block the block to get the block options of
* @return the config options for the protect block specified (null if not found)
*/
public static PSProtectBlock getBlockOptions(Block block) {
if (block == null) return null;
return getBlockOptions(BlockUtil.getProtectBlockType(block));
}
/**
* Get the protection block config options for the item specified.
*
* If the options has restrict-obtaining enabled, and the item does not contain the required NBT tag, null will
* be returned.
*
* @param item the item to get the block options of
* @return the config options for the protect item specified (null if not found)
*/
public static PSProtectBlock getBlockOptions(ItemStack item) {
if (!isProtectBlockItem(item)) return null;
return getBlockOptions(BlockUtil.getProtectBlockType(item));
}
/**
* Gets the config options for the protection block type specified. It is recommended to use the block parameter overloaded
* method instead if possible, since it deals better with heads.
*
* @param blockType the material type name (Bukkit) of the protect block to get the options for, or "PLAYER_HEAD name" for heads
* @return the config options for the protect block specified (null if not found)
*/
public static PSProtectBlock getBlockOptions(String blockType) {
return protectionStonesOptions.get(blockType);
}
public static boolean isProtectBlockType(Block b) {
return getBlockOptions(b) != null;
}
/**
* Get whether or not a material is used as a protection block. It is recommended to use the block
* parameter overloaded method if possible since player heads have a different format.
*
* @param material material type to check (Bukkit material name), or "PLAYER_HEAD name" for heads
* @return whether or not that material is being used for a protection block
*/
public static boolean isProtectBlockType(String material) {
return protectionStonesOptions.containsKey(material);
}
/**
* Check whether or not a given block is a protection block, and actually protects a region.
* @param b the block to look at
* @return whether or not the block is a protection block responsible for a region.
*/
public static boolean isProtectBlock(Block b) {
if (!isProtectBlockType(b)) return false;
RegionManager rgm = WGUtils.getRegionManagerWithWorld(b.getWorld());
if (rgm == null) return false;
return rgm.getRegion(WGUtils.createPSID(b.getLocation())) != null || PSMergedRegion.getMergedRegion(b.getLocation()) != null;
}
/**
* Check if a WorldGuard {@link ProtectedRegion} is a ProtectionStones region, and is configured in the config.
*
* @param r the region to check
* @return true if the WorldGuard region is a ProtectionStones region, and false if it isn't
*/
public static boolean isPSRegion(ProtectedRegion r) {
return isPSRegionFormat(r) && getBlockOptions(r.getFlag(FlagHandler.PS_BLOCK_MATERIAL)) != null;
}
/**
* Check if a WorldGuard {@link ProtectedRegion} has the format of a ProtectionStones region, but is not necessarily configured
* in the config.
*
* @param r the region to check
* @return true if the WorldGuard region is a ProtectionStones region, and false if it isn't
*/
public static boolean isPSRegionFormat(ProtectedRegion r) {
return r != null && r.getId().startsWith("ps") && r.getFlag(FlagHandler.PS_BLOCK_MATERIAL) != null;
}
/**
* Check if a ProtectionStones name is already used by a region globally (from /ps name)
*
* @param name the name to search for
* @return whether or not there is a region with this name
*/
public static boolean isPSNameAlreadyUsed(String name) {
for (UUID worldUid : regionNameToID.keySet()) {
RegionManager rgm = WGUtils.getRegionManagerWithWorld(Bukkit.getWorld(worldUid));
List l = regionNameToID.get(worldUid).get(name);
if (l == null) continue;
for (int i = 0; i < l.size(); i++) { // remove outdated cache
if (rgm.getRegion(l.get(i)) == null) {
l.remove(i);
i--;
}
}
if (!l.isEmpty()) return true;
}
return false;
}
/**
* Get protection stone regions using an ID or alias.
*
* @param w the world to search in (only if it is an id; aliases/names are global)
* @param identifier id or alias of the region
* @return a list of psregions that match the id or alias; will be empty if no regions were found
*/
public static List getPSRegions(World w, String identifier) {
RegionManager rgm = WGUtils.getRegionManagerWithWorld(w);
if (rgm == null) return new ArrayList<>();
PSRegion r = PSRegion.fromWGRegion(w, rgm.getRegion(identifier));
if (r != null) { // return id based query
return new ArrayList<>(Collections.singletonList(r));
} else { // return alias based query
List regions = new ArrayList<>();
PSRegion.fromName(identifier).values().forEach(regions::addAll);
return regions;
}
}
/**
* Removes a protection stone region given its ID, and the region manager it is stored in
* Note: Does not remove the PS block.
*
* @param w the world that the region is in
* @param psID the worldguard region ID of the region
* @return whether or not the event was cancelled
*/
public static boolean removePSRegion(World w, String psID) {
PSRegion r = PSRegion.fromWGRegion(checkNotNull(w), checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
return r != null && r.deleteRegion(false);
}
/**
* Removes a protection stone region given its ID, and the region manager it is stored in, with a player as its cause
* Note: Does not remove the PS block, and does not check if the player (cause) has permission to do this.
*
* @param w the world that the region is in
* @param psID the worldguard region ID of the region
* @param cause the player that caused the removal
* @return whether or not the event was cancelled
*/
public static boolean removePSRegion(World w, String psID, Player cause) {
PSRegion r = PSRegion.fromWGRegion(checkNotNull(w), checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
return r != null && r.deleteRegion(false, cause);
}
/**
* Get the config options for a protect block based on its alias
*
* @param name the alias of the protection block
* @return the protect block options, or null if it wasn't found
*/
public static PSProtectBlock getProtectBlockFromAlias(String name) {
if (name == null) return null;
for (PSProtectBlock cpb : ProtectionStones.protectionStonesOptions.values()) {
if (cpb.alias.equalsIgnoreCase(name) || cpb.type.equalsIgnoreCase(name)) return cpb;
}
return null;
}
/**
* Check if an item is a valid protection block, and if checkNBT is true, check if it was created by
* ProtectionStones. Be aware that blocks may have restrict-obtaining off, meaning that it is ignored whether or not
* the item is created by ProtectionStones (in this case have checkNBT false).
*
* @param item the item to check
* @param checkNBT whether or not to check if the plugin signed off on the item (restrict-obtaining)
* @return whether or not the item is a valid protection block item, and was created by protection stones
*/
public static boolean isProtectBlockItem(ItemStack item, boolean checkNBT) {
if (item == null) return false;
// check basic item
if (!ProtectionStones.isProtectBlockType(BlockUtil.getProtectBlockType(item))) return false;
// check for player heads
if (!checkNBT) return true; // if not checking nbt, you only need to check type
boolean tag = false;
// otherwise, check if the item was created by protection stones (stored in custom tag)
if (item.getItemMeta() != null) {
CustomItemTagContainer tagContainer = item.getItemMeta().getCustomTagContainer();
try { // check if tag byte is 1
Byte isPSBlock = tagContainer.getCustomTag(new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.BYTE);
tag = isPSBlock != null && isPSBlock == 1;
} catch (IllegalArgumentException es) {
try { // some nbt data may be using a string (legacy nbt from ps version 2.0.0 -> 2.0.6)
String isPSBlock = tagContainer.getCustomTag(new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.STRING);
tag = isPSBlock != null && isPSBlock.equals("true");
} catch (IllegalArgumentException ignored) {
}
}
}
return tag; // whether or not the nbt tag was found
}
/**
* Check if an item is a valid protection block, and if the block type has restrict-obtaining on, check if it was
* created by ProtectionStones (custom NBT tag). Be aware that blocks may have restrict-obtaining
* off, meaning that it ignores whether or not the item is created by ProtectionStones.
*
* @param item the item to check
* @return whether or not the item is a valid protection block item, and was created by protection stones
*/
public static boolean isProtectBlockItem(ItemStack item) {
if (item == null) return false;
PSProtectBlock b = ProtectionStones.getBlockOptions(BlockUtil.getProtectBlockType(item));
if (b == null) return false;
return isProtectBlockItem(item, b.restrictObtaining);
}
/**
* Get a protection block item from a protect block config object.
*
* @param b the config options for the protection block
* @return the item with NBT and other metadata to signify that it was created by protection stones
*/
// Create protection stone item (for /ps get and /ps give, and unclaiming)
public static ItemStack createProtectBlockItem(PSProtectBlock b) {
ItemStack is = BlockUtil.getProtectBlockItemFromType(b.type);
ItemMeta im = is.getItemMeta();
// add skull metadata, must be before others since it resets item metadata
if (im instanceof SkullMeta && is.getType().equals(Material.PLAYER_HEAD) && b.type.split(":").length > 1) {
is = BlockUtil.setHeadType(b.type, is);
im = is.getItemMeta();
}
// add display name and lore
if (!b.displayName.equals("")) {
im.setDisplayName(ChatColor.translateAlternateColorCodes('&', b.displayName));
}
List lore = new ArrayList<>();
for (String s : b.lore) lore.add(ChatColor.translateAlternateColorCodes('&', s));
im.setLore(lore);
// add identifier for protection stone created items
im.getCustomTagContainer().setCustomTag(new NamespacedKey(plugin, "isPSBlock"), ItemTagType.BYTE, (byte) 1);
is.setItemMeta(im);
return is;
}
// called on first start, and /ps reload
public static void loadConfig(boolean isReload) {
// remove old ps crafting recipes
PSConfig.removePSRecipes();
// init config
PSConfig.initConfig();
// init messages
PSL.loadConfig();
// init help menu
ArgHelp.initHelpMenu();
// load economy
if (ProtectionStones.getInstance().economy != null) ProtectionStones.getInstance().economy.stop();
ProtectionStones.getInstance().economy = new PSEconomy();
// add command to Bukkit (using reflection)
if (!isReload) {
try {
final Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap");
bukkitCommandMap.setAccessible(true);
CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer());
PSCommand psc = new PSCommand(getInstance().configOptions.base_command);
for (String command : getInstance().configOptions.aliases) { // add aliases
psc.getAliases().add(command);
}
commandMap.register(getInstance().configOptions.base_command, psc); // register command
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onLoad() {
// register WG flags
FlagHandler.registerFlags();
}
@Override
public void onEnable() {
FlagHandler.registerHandlers(); // register custom WG flag handlers
TomlFormat.instance();
Config.setInsertionOrderPreserved(true); // make sure that config upgrades aren't a complete mess
plugin = this;
configLocation = new File(this.getDataFolder() + "/config.toml");
blockDataFolder = new File(this.getDataFolder() + "/blocks");
// metrics (bStats)
new Metrics(this);
// load command arguments
PSCommand.addDefaultArguments();
// register event listeners
getServer().getPluginManager().registerEvents(new ListenerClass(), this);
// check that WorldGuard and WorldEdit are enabled (WorldGuard will only be enabled if there's WorldEdit)
if (getServer().getPluginManager().getPlugin("WorldGuard") == null || !getServer().getPluginManager().getPlugin("WorldGuard").isEnabled()) {
getLogger().severe("WorldGuard or WorldEdit not enabled! Disabling ProtectionStones...");
getServer().getPluginManager().disablePlugin(this);
}
// check if Vault is enabled (for economy support)
if (getServer().getPluginManager().getPlugin("Vault") != null && getServer().getPluginManager().getPlugin("Vault").isEnabled()) {
RegisteredServiceProvider econ = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (econ == null) {
getLogger().warning("No economy plugin found by Vault! There will be no economy support!");
vaultSupportEnabled = false;
} else {
vaultEconomy = econ.getProvider();
vaultSupportEnabled = true;
}
} else {
getLogger().warning("Vault not enabled! There will be no economy support!");
}
// check for PlaceholderAPI
if (getServer().getPluginManager().getPlugin("PlaceholderAPI") != null && getServer().getPluginManager().getPlugin("PlaceholderAPI").isEnabled()) {
getLogger().info("PlaceholderAPI support enabled!");
placeholderAPISupportEnabled = true;
new PSPlaceholderExpansion().register();
} else {
getLogger().info("PlaceholderAPI not found! There will be no PlaceholderAPI support.");
}
// check for LuckPerms
if (getServer().getPluginManager().getPlugin("LuckPerms") != null && getServer().getPluginManager().getPlugin("LuckPerms").isEnabled()) {
try {
luckPermsSupportEnabled = true;
luckPerms = getServer().getServicesManager().load(LuckPerms.class);
getLogger().info("LuckPerms support enabled!");
} catch (NoClassDefFoundError err) { // incompatible luckperms api
getLogger().warning("Incompatible LuckPerms version found! Please upgrade your LuckPerms!");
}
}
// load configuration
loadConfig(false);
// register protectionstones.flags.edit.[flag] permission
FlagHandler.initializePermissions();
// build up region cache
getLogger().info("Building region cache...");
HashMap regionManagers = WGUtils.getAllRegionManagers();
for (World w : regionManagers.keySet()) {
RegionManager rgm = regionManagers.get(w);
HashMap> m = new HashMap<>();
for (ProtectedRegion r : rgm.getRegions().values()) {
String name = r.getFlag(FlagHandler.PS_NAME);
if (isPSRegion(r) && name != null) {
if (m.containsKey(name)) {
m.get(name).add(r.getId());
} else {
m.put(name, new ArrayList<>(Collections.singletonList(r.getId())));
}
}
}
regionNameToID.put(w.getUID(), m);
}
// uuid cache
getLogger().info("Building UUID cache... (if slow change async-load-uuid-cache in the config to true)");
if (configOptions.asyncLoadUUIDCache) { // async load
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
for (OfflinePlayer op : Bukkit.getOfflinePlayers()) {
UUIDCache.storeUUIDNamePair(op.getUniqueId(), op.getName());
if (op.getName() != null)
UUIDCache.storeWGProfile(op.getUniqueId(), op.getName());
}
});
} else { // sync load
List profiles = new ArrayList<>();
for (OfflinePlayer op : Bukkit.getOfflinePlayers()) {
UUIDCache.storeUUIDNamePair(op.getUniqueId(), op.getName());
if (op.getName() != null) profiles.add(new Profile(op.getUniqueId(), op.getName()));
}
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
for (Profile p : profiles) {
WorldGuard.getInstance().getProfileCache().put(p);
}
});
}
// check if UUIDs have been upgraded already
getLogger().info("Checking if PS regions have been updated to UUIDs...");
// update to UUIDs
if (!configOptions.uuidupdated)
LegacyUpgrade.convertToUUID();
getLogger().info(ChatColor.WHITE + "ProtectionStones has successfully started!");
}
}