1
0
mirror of https://e.coding.net/circlecloud/Soulbound.git synced 2024-11-24 02:09:08 +00:00

初始化项目...

Signed-off-by: j502647092 <jtb1@163.com>
This commit is contained in:
j502647092 2015-04-29 10:04:46 +08:00
commit 70d7d7f6a0
41 changed files with 3566 additions and 0 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# Eclipse stuff
/.classpath
/.project
/.settings
# netbeans
/nbproject
# we use maven!
/build.xml
# maven
/target
/repo
# vim
.*.sw[a-p]
# various other potential build files
/build
/bin
/dist
/manifest.mf
/world
# Mac filesystem dust
*.DS_Store
# intellij
*.iml
*.ipr
*.iws
.idea/
# Project Stuff
/src/main/resources/Soulbound
# Other Libraries
*.jar
# Atlassian Stuff
/atlassian-ide-plugin.xml

22
README.md Normal file
View File

@ -0,0 +1,22 @@
[![Soulbound][Banner]][GitHub]
What is Soulbound?
----------------
Souldbound is a Bukkit plugin that makes it possible to have Soulbound items.
Whenever an item is soulbinded, players cannot transfer the item to other players.
How does it work?
----------------
Check out the [BukkitDev]-page for more information!
Who made this?
----------------
[![TfT_02](http://www.gravatar.com/avatar/b8914f9970e1f6ffd5281ce4770e20a7.png)](http://dev.bukkit.org/profiles/TfT_02/)
Download here: [BukkitDev]
[Banner]: https://dl.dropbox.com/u/29178507/Dev/Soulbound/title-banner.png
[BukkitDev]: http://dev.bukkit.org/server-mods/Soulbound/
[GitHub]: https://github.com/TfT-02/Soulbound

94
changelog.txt Normal file
View File

@ -0,0 +1,94 @@
Changelog:
Key:
+ Addition
= Fix
! Change
- Removal
Version 1.2.0 | Tested on CB 1.7.9-R0.1
+ Added support for giving Soulbinded kits to other players
+ Added option to have Soulbind items without adding the player name
! Changed the way UUIDs are handled, they are now hidden in the Soulbound lore :)
! Changed "Bind on Use" also triggers when enchanting
Version 1.1.9 | Tested on CB 1.7.5-R0.1
! Now using MythicDrops hook to support MythicDrops versions 1.1.2 through 3.0.0. Huge shout-out to Nunnery!
Version 1.1.8 | Tested on CB 1.7.5-R0.1
+ Added new Items config file, define items with displaynames/lore here which will be Soulbound
+ Added feature which allows you to Soulbind items when spawning in a kit
+ Added feature which allows you to Soulbind items on respawn, useful for spawnkits.
+ Added MythicDrops 1.1.2 AND 2.0.0 support. Thanks Nunnery!
+ Added UUID support
Version 1.1.7 | Tested on CB 1.6.4-R0.1
- Removed old Updater class
Version 1.1.6 | Tested on CB 1.6.4-R0.1
! Changed Updater, now uses Gravity's updater v2.0
! Changed notification messages when dependencies are found, they're hidden by default
Version 1.1.5 | Tested on CB 1.6.2-R1.0
+ Added new config option; "Delete_On_Drop"
+ Added new permission nodes soulbound.items.keep_on_death and soulbound.items.delete_on_death, both are false by default
= Fixed bug where soulbound items would disappear when dropping them by dragging them out of the inventory
= Fixed MythicDrops support, works with MythicDrops 1.1.2
! Changed config file system, files now automatically update
! Changed "Allow_Item_Drop" to "Prevent_Item_Drop"
- Removed config options "Keep_On_Death" and "Delete_On_Death". Use permissions instead!
- Removed DiabloDrops support
Version 1.1.4 | Tested on CB 1.5.2-R0.1
+ Added a new configuration option to prevent using certain commands when holding a Soulbound item
+ Added a new configuration option to Soulbind the item in hand when a certain command is used.
+ Added an option to disable the feedback messages "Inventory now Soulbound to.."
! Hoppers can no longer pickup Soulbound items
= Fixed infinite durability not working for armor and special tools
Version 1.1.3 | Tested on CB 1.5.0-R0.1
+ Added MythicDrops support
+ Added permission node which allows certain players to pickup items which are not Soulbound to that player
+ Added permission node which limit the maximum amount of Soulbound items a player can carry at once
+ Added new configuration option to let Soulbound items have infinite durability
+ Added new command to Soulbind a full inventory. /bind [player] inventory
= Fixed bug which caused the plugin to ignore cancelled SoulbindItemEvents
! Improved the Bind on Equip mechanism even more, to account for recent inventory changes in MC 1.5
Version 1.1.2 | Tested on CB 1.4.7-R1.0 & 1.5.0-R0.1
+ Added help pages, access them using /soulbound help
= Fixed bug where DiabloDrops chests where never edited. Chest generated by DiabloDrops can now also contain Soulbound items
= Fixed bug where Chainmail armor and Skulls were never Binded on Equip
= Fixed bug which caused an NPE when trying to bind with nothing in hand
= Fixed bug which would throw an ArrayIndexOutOfBounds error
= Fixed bug which allowed player to Soulbind items twice
! Improved the Bind on Equip mechanism!
Version 1.1.1 | Tested on CB 1.4.7-R1.0
+ Added API functions so other plugins can hook into Soulbound as well! (Instead of the other way round)
+ Added support for LoreLocks!
= Fixed bug with the Update Checker (I really did this time)
= Fixed bug with EpicBossRecoded when bosses had no loot defined
Version 1.1.0 | Tested on CB 1.4.7-R1.0
+ Added support for DiabloDrops! Make Legendary items Soulbound on pickup, or make armor Sets Soulbound on Equip
+ Added support for EpicBossRecoded! Drops from an EpicBoss can get flagged as "Bind on Pickup", "Bind on Equip" or "Bind on Use"
+ Added new item type "Bind on Equip", when a player equips this item it will get Soulbound to that player
+ Added new item type "Bind on Use", when a player uses (left/right click) this item it will get Soulbound to that player
! Bind on Pickup, now also binds items when clicking them in containers.
= Fixed bug where /bindonpickup was broken
= Fixed bug where items could have multiple lines with "Soulbound"
Version 1.0.1 | Tested on CB 1.4.7-R1.0
= Fixed bug with the Update Checker
Version 1.0.0 | Tested on CB 1.4.7-R1.0
+ First release
+ Added Soulbound items
+ Added Bind on Pickup items
+ Added prevent storing Soulbound in containers
+ Added prevent dropping Soulbound items
+ Added prevent dropping Soulbound items on death
+ Added keep Soulbound items after death
+ Added Metrics for stats
+ Added an update check

101
pom.xml Normal file
View File

@ -0,0 +1,101 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.me.tft_02.soulbound</groupId>
<artifactId>Soulbound</artifactId>
<version>1.1.10-SNAPSHOT</version>
<name>Soulbound</name>
<url>https://github.com/TfT-02/Soulbound</url>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/TfT-02/Soulbound/issues</url>
</issueManagement>
<build>
<finalName>Soulbound</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}/src/</directory>
<includes>
<include>*.yml</include>
<include>.jenkins</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<configuration>
<artifactSet>
<includes>
<include>org.mcstats.bukkit:metrics</include>
<include>org.nunnerycode.bukkit:mythicdropsapi-lib</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.mcstats.bukkit</pattern>
<shadedPattern>com.me.tft_02.soulbound.util</shadedPattern>
</relocation>
<relocation>
<pattern>org.nunnerycode.bukkit</pattern>
<shadedPattern>com.me.tft_02.soulbound.util</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>Plugin Metrics</id>
<url>http://repo.mcstats.org/content/repositories/public</url>
</repository>
<repository>
<id>mythicdrops-repo</id>
<url>http://repository-topplethenun.forge.cloudbees.com/snapshot/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mcstats.bukkit</groupId>
<artifactId>metrics</artifactId>
<version>R7</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,14 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>bin</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<files>
<file>
<source>${project.build.directory}/${artifactId}.jar</source>
<outputDirectory>/</outputDirectory>
<destName>Soulbound.jar</destName>
</file>
</files>
</assembly>

View File

@ -0,0 +1,136 @@
package com.me.tft_02.soulbound;
import java.io.File;
import net.gravitydevelopment.updater.soulbound.Updater;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.me.tft_02.soulbound.commands.BindCommand;
import com.me.tft_02.soulbound.commands.BindOnEquipCommand;
import com.me.tft_02.soulbound.commands.BindOnPickupCommand;
import com.me.tft_02.soulbound.commands.BindOnUseCommand;
import com.me.tft_02.soulbound.commands.SoulboundCommand;
import com.me.tft_02.soulbound.commands.UnbindCommand;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.config.ItemsConfig;
import com.me.tft_02.soulbound.hooks.EpicBossRecodedListener;
import com.me.tft_02.soulbound.listeners.BlockListener;
import com.me.tft_02.soulbound.listeners.EntityListener;
import com.me.tft_02.soulbound.listeners.InventoryListener;
import com.me.tft_02.soulbound.listeners.PlayerListener;
import com.me.tft_02.soulbound.util.LogFilter;
public class Soulbound extends JavaPlugin {
/* File Paths */
private static String mainDirectory;
public static Soulbound p;
// Jar Stuff
public static File soulbound;
// Checks for hooking into other plugins
public static boolean epicBossRecodedEnabled = false;
public static boolean loreLocksEnabled = false;
public static boolean mythicDropsEnabled = false;
// Update Check
private boolean updateAvailable;
/**
* Run things on enable.
*/
@Override
public void onEnable() {
p = this;
getLogger().setFilter(new LogFilter(this));
setupFilePaths();
loadConfigFiles();
setupEpicBossRecoded();
registerEvents();
getCommand("soulbound").setExecutor(new SoulboundCommand());
getCommand("bind").setExecutor(new BindCommand());
getCommand("bindonpickup").setExecutor(new BindOnPickupCommand());
getCommand("bindonuse").setExecutor(new BindOnUseCommand());
getCommand("bindonequip").setExecutor(new BindOnEquipCommand());
getCommand("unbind").setExecutor(new UnbindCommand());
checkForUpdates();
}
private void registerEvents() {
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new PlayerListener(), this);
pm.registerEvents(new InventoryListener(), this);
pm.registerEvents(new EntityListener(), this);
pm.registerEvents(new BlockListener(), this);
}
private void setupEpicBossRecoded() {
if (getServer().getPluginManager().isPluginEnabled("EpicBossRecoded")) {
epicBossRecodedEnabled = true;
debug("EpicBossRecoded found!");
getServer().getPluginManager().registerEvents(new EpicBossRecodedListener(), this);
}
}
/**
* Run things on disable.
*/
@Override
public void onDisable() {}
public static String getMainDirectory() {
return mainDirectory;
}
public boolean isUpdateAvailable() {
return updateAvailable;
}
public void debug(String message) {
getLogger().info("[Debug] " + message);
}
/**
* Setup the various storage file paths
*/
private void setupFilePaths() {
soulbound = getFile();
mainDirectory = getDataFolder().getPath() + File.separator;
}
private void loadConfigFiles() {
Config.getInstance();
ItemsConfig.getInstance();
}
private void checkForUpdates() {
if (!Config.getInstance().getUpdateCheckEnabled()) {
return;
}
Updater updater = new Updater(this, 53483, soulbound, Updater.UpdateType.NO_DOWNLOAD, false);
if (updater.getResult() != Updater.UpdateResult.UPDATE_AVAILABLE) {
this.updateAvailable = false;
return;
}
if (updater.getLatestType().equals("beta") && !Config.getInstance().getPreferBeta()) {
this.updateAvailable = false;
return;
}
this.updateAvailable = true;
getLogger().info("Soulbound is outdated!");
getLogger().info("http://dev.bukkit.org/server-mods/soulbound/");
}
}

View File

@ -0,0 +1,116 @@
package com.me.tft_02.soulbound.api;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.ItemUtils;
public final class ItemAPI {
private ItemAPI() {}
/**
* Check if a Player is binded to an ItemStack.
* </br>
* This function is designed for API usage.
*
* @param player The Player to check
* @param itemStack The ItemStack to check
*
* @return true or false
*/
public static boolean isSoulbindedPlayer(Player player, ItemStack itemStack) {
return ItemUtils.isBindedPlayer(player, itemStack);
}
/**
* Soulbind an ItemStack to a Player.
* </br>
* This function is designed for API usage.
*
* @param player The Player to bind the item to
* @param itemStack The ItemStack to bind
*
* @return the soulbound ItemStack
*/
public static ItemStack soulbindItem(Player player, ItemStack itemStack) {
return ItemUtils.soulbindItem(player, itemStack);
}
/**
* Check if an itemstack is Soulbound.
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to check
*
* @return true or false
*/
public static boolean isSoulbound(ItemStack itemStack) {
return ItemUtils.isSoulbound(itemStack);
}
/**
* Mark an itemstack as Bind on Pickup
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to mark as Bind on Pickup
*
* @return the marked itemstack
*/
public static ItemStack bindOnPickupItem(ItemStack itemStack) {
return ItemUtils.bopItem(itemStack);
}
/**
* Check if an itemstack is Bind on Pickup.
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to check
*
* @return true or false
*/
public static boolean isBindOnPickup(ItemStack itemStack) {
return ItemUtils.isBindOnPickup(itemStack);
}
/**
* Mark an itemstack as Bind on Use
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to mark as Bind on Use
*
* @return the marked itemstack
*/
public static ItemStack bindOnUseItem(ItemStack itemStack) {
return ItemUtils.bouItem(itemStack);
}
/**
* Mark an itemstack as Bind on Equip
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to mark as Bind on Equip
*
* @return the marked itemstack
*/
public static ItemStack bindOnEquipItem(ItemStack itemStack) {
return ItemUtils.boeItem(itemStack);
}
/**
* Get the Soulbound type of an itemstack.
* </br>
* This function is designed for API usage.
*
* @param itemStack The itemstack to check
*
* @return the Bind type
*/
public static String getItemType(ItemStack itemStack) {
return ItemUtils.getItemType(itemStack).toString();
}
}

View File

@ -0,0 +1,92 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.Soulbound;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
public class BindCommand implements CommandExecutor {
String soulbound = ChatColor.GOLD + "Soulbound ";
@SuppressWarnings("deprecation")
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
if (!sender.hasPermission("soulbound.commands.bind")) {
return false;
}
boolean bindFullInventory = false;
Player player = (Player) sender;
Player target;
switch (args.length) {
case 1:
target = Soulbound.p.getServer().getPlayerExact(args[0]);
if (CommandUtils.isOffline(sender, target)) {
return true;
}
break;
case 2:
if (!args[1].equalsIgnoreCase("inventory")) {
sender.sendMessage(ChatColor.RED + "Proper usage: " + ChatColor.GREEN + "/bind <player> inventory");
return true;
}
bindFullInventory = true;
target = Soulbound.p.getServer().getPlayerExact(args[0]);
if (CommandUtils.isOffline(sender, target)) {
return true;
}
break;
default:
target = player;
}
if (bindFullInventory) {
return handleBindFullInventory(player, target);
}
ItemStack itemInHand = player.getItemInHand();
if ((itemInHand.getType() == Material.AIR) || ItemUtils.isSoulbound(itemInHand)) {
sender.sendMessage(ChatColor.GRAY + "You can't " + soulbound + ChatColor.GRAY + "this item.");
return false;
}
ItemUtils.soulbindItem(target, itemInHand);
if (ItemUtils.isSoulbound(itemInHand) && Config.getInstance().getFeedbackEnabled()) {
sender.sendMessage(ChatColor.GRAY + "Item is now " + soulbound + ChatColor.GRAY + "to " + ChatColor.DARK_AQUA + target.getName());
}
return true;
}
private boolean handleBindFullInventory(Player player, Player target) {
for (ItemStack itemStack : player.getInventory().getContents()) {
if (itemStack != null && itemStack.getType() != Material.AIR) {
ItemUtils.soulbindItem(target, itemStack);
}
}
if (Config.getInstance().getFeedbackEnabled()) {
player.sendMessage(ChatColor.GRAY + "All items in " + ChatColor.DARK_AQUA + target.getName() + ChatColor.GRAY + "'s inventory are now " + soulbound + ChatColor.GRAY + "to " + ChatColor.DARK_AQUA + target.getName());
}
return true;
}
}

View File

@ -0,0 +1,51 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
public class BindOnEquipCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
switch (args.length) {
case 0:
Player player = (Player) sender;
if (!player.hasPermission("soulbound.commands.bindonequip")) {
return false;
}
ItemStack itemInHand = player.getItemInHand();
if ((itemInHand.getType() == Material.AIR) || ItemUtils.isSoulbound(itemInHand)) {
player.sendMessage(ChatColor.GRAY + "You can't " + ChatColor.GOLD + "Soulbound " + ChatColor.GRAY + "this item.");
return false;
}
ItemUtils.unbindItem(itemInHand);
ItemUtils.boeItem(itemInHand);
if (ItemUtils.isBindOnEquip(itemInHand)) {
player.sendMessage(ChatColor.GRAY + "Item is now " + ChatColor.DARK_RED + "Bind on Equip");
}
else {
player.sendMessage(ChatColor.RED + "Cannot mark this item as " + ChatColor.DARK_RED + "Bind on Equip");
}
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,45 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
public class BindOnPickupCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
switch (args.length) {
case 0:
Player player = (Player) sender;
if (!player.hasPermission("soulbound.commands.bindonpickup")) {
return false;
}
ItemStack itemInHand = player.getItemInHand();
if ((itemInHand.getType() == Material.AIR) || ItemUtils.isSoulbound(itemInHand)) {
player.sendMessage(ChatColor.GRAY + "You can't " + ChatColor.GOLD + "Soulbound " + ChatColor.GRAY + "this item.");
return false;
}
ItemUtils.unbindItem(itemInHand);
ItemUtils.bopItem(itemInHand);
player.sendMessage(ChatColor.GRAY + "Item is now " + ChatColor.DARK_RED + "Bind on pickup");
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,45 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
public class BindOnUseCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
switch (args.length) {
case 0:
Player player = (Player) sender;
if (!player.hasPermission("soulbound.commands.bindonuse")) {
return false;
}
ItemStack itemInHand = player.getItemInHand();
if ((itemInHand.getType() == Material.AIR) || ItemUtils.isSoulbound(itemInHand)) {
player.sendMessage(ChatColor.GRAY + "You can't " + ChatColor.GOLD + "Soulbound " + ChatColor.GRAY + "this item.");
return false;
}
ItemUtils.unbindItem(itemInHand);
ItemUtils.bouItem(itemInHand);
player.sendMessage(ChatColor.GRAY + "Item is now " + ChatColor.DARK_RED + "Bind on Use");
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,134 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.me.tft_02.soulbound.Soulbound;
public class SoulboundCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command,
String label, String[] args) {
switch (args.length) {
case 0:
sender.sendMessage("Soulbound version "
+ Soulbound.p.getDescription().getVersion());
return printUsage(sender);
case 1:
if (args[0].equalsIgnoreCase("reload")) {
return reloadConfiguration(sender);
}
default:
if (args[0].equalsIgnoreCase("help")
|| args[0].equalsIgnoreCase("?")) {
return helpPages(sender, args);
}
return false;
}
}
private boolean reloadConfiguration(CommandSender sender) {
if (sender instanceof Player
&& !sender.hasPermission("soulbound.commands.reload")) {
return false;
}
Soulbound.p.reloadConfig();
sender.sendMessage(ChatColor.GREEN + "Configuration reloaded.");
return false;
}
private boolean helpPages(CommandSender sender, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("Can't use this from the console, sorry!");
return false;
}
if (args.length >= 2 && Integer.parseInt(args[1]) > 0) {
getHelpPage(Integer.parseInt(args[1]), sender);
return true;
}
return false;
}
private void getHelpPage(int page, CommandSender sender) {
int maxPages = 2;
int nextPage = page + 1;
if (page > maxPages) {
sender.sendMessage(ChatColor.RED + "This page does not exist."
+ ChatColor.GOLD + " /help [0-" + maxPages + "]");
return;
}
String dot = ChatColor.DARK_RED + "* ";
sender.sendMessage(ChatColor.GRAY + "-----[ " + ChatColor.GOLD
+ "Soulbound Help" + ChatColor.GRAY + " ]----- Page " + page
+ "/" + maxPages);
if (page == 1) {
sender.sendMessage(ChatColor.GOLD + "How does it work?");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "Soulbound items are special items which are bound to a sender.");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "Players are prevented from doing certain actions with Soulbound items, such as:");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "dropping them on the ground, storing them in chests or giving them to other players.");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "Items marked as 'Bind on Pickup' will get Soulbound as soon as they get picked up.");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "Items marked as 'Bind on Use' will get Soulbound as soon as they get used.");
sender.sendMessage(dot
+ ChatColor.GRAY
+ "Items marked as 'Bind on Equip' will get Soulbound as soon as they get equipped.");
}
if (page == 2) {
sender.sendMessage(ChatColor.GOLD + "Commands:");
if (sender.hasPermission("soulbound.commands.bindonpickup")) {
sender.sendMessage(dot + ChatColor.GREEN + "/soulbound"
+ ChatColor.GRAY + " Check the status of the plugin.");
}
if (sender.hasPermission("soulbound.commands.bind")) {
sender.sendMessage(dot + ChatColor.GREEN + "/bind <sender>"
+ ChatColor.GRAY
+ " Soulbound the item currently in hand.");
sender.sendMessage(dot + ChatColor.GREEN
+ "/bind <sender> inventory" + ChatColor.GRAY
+ " Soulbound an entire inventory.");
}
if (sender.hasPermission("soulbound.commands.bindonpickup")) {
sender.sendMessage(dot + ChatColor.GREEN + "/bindonpickup"
+ ChatColor.GRAY
+ " Mark the item in hand as 'Bind on Pickup'");
}
if (sender.hasPermission("soulbound.commands.bindonuse")) {
sender.sendMessage(dot + ChatColor.GREEN + "/bindonuse"
+ ChatColor.GRAY
+ " Mark the item in hand as 'Bind on Use'");
}
if (sender.hasPermission("soulbound.commands.bindonequip")) {
sender.sendMessage(dot + ChatColor.GREEN + "/bindonequip"
+ ChatColor.GRAY
+ " Mark the item in hand as 'Bind on Equip'");
}
if (sender.hasPermission("soulbound.commands.unbind")) {
sender.sendMessage(dot + ChatColor.GREEN + "/unbind"
+ ChatColor.GRAY + " Unbind the item in hand.");
}
}
if (nextPage <= maxPages) {
sender.sendMessage(ChatColor.GOLD + "Type /soulbound help "
+ nextPage + " for more");
}
}
private boolean printUsage(CommandSender sender) {
sender.sendMessage("Usage: /soulbound [reload | help]");
return false;
}
}

View File

@ -0,0 +1,47 @@
package com.me.tft_02.soulbound.commands;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
public class UnbindCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
switch (args.length) {
case 0:
Player player = (Player) sender;
if (!player.hasPermission("soulbound.commands.unbind")) {
return false;
}
ItemStack itemInHand = player.getItemInHand();
if ((itemInHand.getType() == Material.AIR) || !ItemUtils.isSoulbound(itemInHand)) {
player.sendMessage(ChatColor.GRAY + "You can't " + ChatColor.GOLD + "Unbind " + ChatColor.GRAY + "this item.");
return false;
}
if (ItemUtils.unbindItem(itemInHand)==null ){
player.sendMessage(ChatColor.GRAY + "You can't " + ChatColor.GOLD + "Unbind " + ChatColor.GRAY + "this item.");
return false;
}
player.sendMessage(ChatColor.GRAY + "Item no longer Soulbound.");
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,119 @@
package com.me.tft_02.soulbound.config;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
public abstract class AutoUpdateConfigLoader extends ConfigLoader {
public AutoUpdateConfigLoader(String relativePath, String fileName) {
super(relativePath, fileName);
}
public AutoUpdateConfigLoader(String fileName) {
super(fileName);
}
@SuppressWarnings("deprecation")
@Override
protected void loadFile() {
super.loadFile();
FileConfiguration internalConfig = YamlConfiguration.loadConfiguration(plugin.getResource(fileName));
Set<String> configKeys = config.getKeys(true);
Set<String> internalConfigKeys = internalConfig.getKeys(true);
boolean needSave = false;
Set<String> oldKeys = new HashSet<String>(configKeys);
oldKeys.removeAll(internalConfigKeys);
Set<String> newKeys = new HashSet<String>(internalConfigKeys);
newKeys.removeAll(configKeys);
// Don't need a re-save if we have old keys sticking around?
// Would be less saving, but less... correct?
if (!newKeys.isEmpty() || !oldKeys.isEmpty()) {
needSave = true;
}
for (String key : oldKeys) {
plugin.debug("Removing unused key: " + key);
config.set(key, null);
}
for (String key : newKeys) {
plugin.debug("Adding new key: " + key + " = " + internalConfig.get(key));
config.set(key, internalConfig.get(key));
}
if (needSave) {
// Get Bukkit's version of an acceptable config with new keys, and no old keys
String output = config.saveToString();
// Convert to the superior 4 space indentation
output = output.replace(" ", " ");
// Rip out Bukkit's attempt to save comments at the top of the file
while (output.indexOf('#') != -1) {
output = output.substring(output.indexOf('\n', output.indexOf('#')) + 1);
}
// Read the internal config to get comments, then put them in the new one
try {
// Read internal
BufferedReader reader = new BufferedReader(new InputStreamReader(plugin.getResource(fileName)));
HashMap<String, String> comments = new HashMap<String, String>();
String temp = "";
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("#")) {
temp += line + "\n";
}
else if (line.contains(":")) {
line = line.substring(0, line.indexOf(":") + 1);
if (!temp.isEmpty()) {
comments.put(line, temp);
temp = "";
}
}
}
// Dump to the new one
for (String key : comments.keySet()) {
if (output.indexOf(key) != -1) {
output = output.substring(0, output.indexOf(key)) + comments.get(key) + output.substring(output.indexOf(key));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
// Save it
try {
String saveName = fileName;
// At this stage we cannot guarantee that Config has been loaded, so we do the check directly here
if (!plugin.getConfig().getBoolean("General.Config_Update_Overwrite", true)) {
saveName += ".new";
}
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(plugin.getDataFolder(), saveName)));
writer.write(output);
writer.flush();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,89 @@
package com.me.tft_02.soulbound.config;
import java.util.ArrayList;
import java.util.List;
public class Config extends AutoUpdateConfigLoader {
private static Config instance;
private Config() {
super("config.yml");
}
public static Config getInstance() {
if (instance == null) {
instance = new Config();
}
return instance;
}
@Override
protected void loadKeys() {}
/* @formatter:off */
/* GENERAL SETTINGS */
// public String getLocale() { return config.getString("General.Locale", "en_us"); }
// public int getSaveInterval() { return config.getInt("General.Save_Interval", 10); }
public boolean getStatsTrackingEnabled() { return config.getBoolean("General.Stats_Tracking", true); }
public boolean getUpdateCheckEnabled() { return config.getBoolean("General.Update_Check", true); }
public boolean getPreferBeta() { return config.getBoolean("General.Prefer_Beta", false); }
public boolean getVerboseLoggingEnabled() { return config.getBoolean("General.Verbose_Logging", false); }
public boolean getConfigOverwriteEnabled() { return config.getBoolean("General.Config_Update_Overwrite", true); }
/* @formatter:on */
/* SOULBOUND SETTINGS */
public boolean getShowNameInLore() { return config.getBoolean("Soulbound.Show_Name_In_Lore", true); }
public boolean getFeedbackEnabled() { return config.getBoolean("Soulbound.Feedback_Messages_Enabled", true); }
public boolean getPreventItemDrop() { return config.getBoolean("Soulbound.Prevent_Item_Drop", false); }
public boolean getDeleteOnDrop() { return config.getBoolean("Soulbound.Delete_On_Drop", false); }
public boolean getAllowItemStoring() { return config.getBoolean("Soulbound.Allow_Item_Storing", true); }
public boolean getInfiniteDurability() { return config.getBoolean("Soulbound.Infinite_Durability", false); }
public List<String> getBlockedCommands() { return config.getStringList("Soulbound.Blocked_Commands"); }
public List<String> getBindCommands() { return config.getStringList("Soulbound.Commands_Bind_When_Used"); }
// EpicBossRecoded config settings
public boolean getEBRBindOnPickup() { return config.getBoolean("Dependency_Plugins.EpicBossRecoded.BindOnPickup"); }
public boolean getEBRBindOnEquip() { return config.getBoolean("Dependency_Plugins.EpicBossRecoded.BindOnEquip"); }
public boolean getEBRBindOnUse() { return config.getBoolean("Dependency_Plugins.EpicBossRecoded.BindOnUse");}
// DiabloDrops config settings
public List<String> getDiabloDropsBindOnPickupTiers() { return getDiabloDropsItemTiers("BindOnPickup");}
public List<String> getDiabloDropsBindOnUseTiers() { return getDiabloDropsItemTiers("BindOnUse");}
public List<String> getDiabloDropsBindOnEquipTiers() { return getDiabloDropsItemTiers("BindOnEquip"); }
public List<String> getDiabloDropsItemTiers(String bindType) {
String[] tiersString = config.getString("Dependency_Plugins.DiabloDrops." + bindType).replaceAll(" ", "").split("[,]");
List<String> tiers = new ArrayList<String>();
for (String tier : tiersString) {
tiers.add(tier);
}
return tiers;
}
// LoreLocks config settings
public boolean getLoreLocksBindKeys() { return config.getBoolean("Dependency_Plugins.LoreLocks.Bind_Keys"); }
// MythicDrops config settings
public List<String> getMythicDropsBindOnPickupTiers() { return getMythicDropsItemTiers("BindOnPickup"); }
public List<String> getMythicDropsBindOnUseTiers() { return getMythicDropsItemTiers("BindOnUse"); }
public List<String> getMythicDropsBindOnEquipTiers() { return getMythicDropsItemTiers("BindOnEquip"); }
public List<String> getMythicDropsItemTiers(String bindType) {
String[] tiersString = config.getString("Dependency_Plugins.MythicDrops." + bindType).replaceAll(" ", "").split("[,]");
List<String> tiers = new ArrayList<String>();
for (String tier : tiersString) {
tiers.add(tier);
}
return tiers;
}
}

View File

@ -0,0 +1,93 @@
package com.me.tft_02.soulbound.config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import com.me.tft_02.soulbound.Soulbound;
public abstract class ConfigLoader {
protected static final Soulbound plugin = Soulbound.p;
protected String fileName;
protected File configFile;
protected FileConfiguration config;
public ConfigLoader(String relativePath, String fileName) {
this.fileName = fileName;
configFile = new File(plugin.getDataFolder(), relativePath + File.separator + fileName);
loadFile();
}
public ConfigLoader(String fileName) {
this.fileName = fileName;
configFile = new File(plugin.getDataFolder(), fileName);
loadFile();
}
protected void loadFile() {
if (!configFile.exists()) {
plugin.debug("Creating Soulbound " + fileName + " File...");
createFile();
}
else {
plugin.debug("Loading Soulbound " + fileName + " File...");
}
config = YamlConfiguration.loadConfiguration(configFile);
}
protected abstract void loadKeys();
protected void createFile() {
configFile.getParentFile().mkdirs();
InputStream inputStream = plugin.getResource(fileName);
if (inputStream == null) {
plugin.getLogger().severe("Missing resource file: '" + fileName + "' please notify the plugin authors");
return;
}
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(configFile);
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (outputStream != null) {
try {
outputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,155 @@
package com.me.tft_02.soulbound.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import com.me.tft_02.soulbound.datatypes.ActionType;
import com.me.tft_02.soulbound.datatypes.SoulbindItem;
public class ItemsConfig extends ConfigLoader {
private static ItemsConfig instance;
private List<SoulbindItem> soulbindOnCraft = new ArrayList<SoulbindItem>();
private List<SoulbindItem> soulbindOnOpenChest = new ArrayList<SoulbindItem>();
private List<SoulbindItem> soulbindOnPickupItem = new ArrayList<SoulbindItem>();
private List<SoulbindItem> soulbindOnDrop = new ArrayList<SoulbindItem>();
private List<SoulbindItem> soulbindOnRespawn = new ArrayList<SoulbindItem>();
private List<SoulbindItem> soulbindOnKit = new ArrayList<SoulbindItem>();
public ItemsConfig() {
super("items.yml");
loadKeys();
}
public static ItemsConfig getInstance() {
if (instance == null) {
instance = new ItemsConfig();
}
return instance;
}
@SuppressWarnings("deprecation")
@Override
protected void loadKeys() {
ConfigurationSection configurationSection = config.getConfigurationSection("Items");
if (configurationSection == null) {
return;
}
Set<String> itemConfigSet = configurationSection.getKeys(false);
for (String itemName : itemConfigSet) {
String[] itemInfo = itemName.split("[|]");
Material itemMaterial = Material.matchMaterial(itemInfo[0]);
if (itemMaterial == null) {
plugin.getLogger().warning("Invalid material name. This item will be skipped. - " + itemInfo[0]);
continue;
}
byte itemData = (itemInfo.length == 2) ? Byte.valueOf(itemInfo[1]) : 0;
MaterialData itemMaterialData = new MaterialData(itemMaterial, itemData);
List<String> lore = new ArrayList<String>();
if (config.contains("Items." + itemName + ".Lore")) {
for (String loreEntry : config.getStringList("Items." + itemName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', loreEntry));
}
}
String name = null;
if (config.contains("Items." + itemName + ".Name")) {
name = ChatColor.translateAlternateColorCodes('&', config.getString("Items." + itemName + ".Name"));
}
SoulbindItem soulbindItem = new SoulbindItem(itemMaterialData, name, lore);
List<String> actions = config.getStringList("Items." + itemName + ".Actions");
for (ActionType actionType : ActionType.values()) {
if (actions.contains(actionType.toString())) {
addSoulbindItem(actionType, soulbindItem);
}
}
}
}
private void addSoulbindItem(ActionType actionType, SoulbindItem soulbindItem) {
switch (actionType) {
case CRAFT:
soulbindOnCraft.add(soulbindItem);
return;
case OPEN_CHEST:
soulbindOnOpenChest.add(soulbindItem);
return;
case PICKUP_ITEM:
soulbindOnPickupItem.add(soulbindItem);
return;
case DROP_ITEM:
soulbindOnDrop.add(soulbindItem);
return;
case RESPAWN:
soulbindOnRespawn.add(soulbindItem);
return;
case KIT:
soulbindOnKit.add(soulbindItem);
return;
}
}
public List<SoulbindItem> getSoulbindItems(ActionType actionType) {
switch (actionType) {
case CRAFT:
return soulbindOnCraft;
case OPEN_CHEST:
return soulbindOnOpenChest;
case PICKUP_ITEM:
return soulbindOnPickupItem;
case DROP_ITEM:
return soulbindOnDrop;
case RESPAWN:
return soulbindOnRespawn;
case KIT:
return soulbindOnKit;
default:
return null;
}
}
public boolean isActionItem(ItemStack itemStack, ActionType actionType) {
for (SoulbindItem soulbindItem : getSoulbindItems(actionType)) {
if (itemStack.getData().equals(soulbindItem.getMaterialData())) {
if (itemStack.hasItemMeta()) {
ItemMeta itemMeta = itemStack.getItemMeta();
if (soulbindItem.getName() != null) {
if (!itemMeta.getDisplayName().contains(soulbindItem.getName())) {
return false;
}
}
if (soulbindItem.getLore() != null && !soulbindItem.getLore().isEmpty()) {
if (itemMeta.hasLore() || !itemMeta.getLore().containsAll(soulbindItem.getLore())) {
return false;
}
}
}
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,10 @@
package com.me.tft_02.soulbound.datatypes;
public enum ActionType {
CRAFT,
OPEN_CHEST,
PICKUP_ITEM,
DROP_ITEM,
RESPAWN,
KIT;
};

View File

@ -0,0 +1,34 @@
package com.me.tft_02.soulbound.datatypes;
import java.util.List;
import org.bukkit.material.MaterialData;
public class SoulbindItem {
private MaterialData materialData;
private String name;
private List<String> lore;
public SoulbindItem(MaterialData materialData, String name, List<String> lore) {
this.materialData = materialData;
this.name = name;
this.lore = lore;
}
public MaterialData getMaterialData() {
return materialData;
}
public List<String> getLore() {
return lore;
}
public String getName() {
return name;
}
@Override
public String toString() {
return materialData.toString() + " " + name.toString() + " " + lore.toString();
}
}

View File

@ -0,0 +1,54 @@
package com.me.tft_02.soulbound.events;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
public class SoulbindItemEvent extends PlayerEvent implements Cancellable {
private ItemStack itemStack;
private boolean cancelled;
public SoulbindItemEvent(Player player, ItemStack itemStack) {
super(player);
this.setItemStack(itemStack);
this.cancelled = false;
}
/**
* @return The itemStack being soulbound
*/
public ItemStack getItemStack() {
return itemStack;
}
/**
* @return Set the itemStack being soulbound
*/
public void setItemStack(ItemStack itemStack) {
this.itemStack = itemStack;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
private static final HandlerList handlers = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,40 @@
package com.me.tft_02.soulbound.hooks;
//import me.ThaH3lper.com.Api.BossDeathEvent;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.util.ItemUtils;
public class EpicBossRecodedListener implements Listener {
/**
* Check BossDeathEvent events.
*
* @param event The event to check
*/
/* @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBossDeath(BossDeathEvent event) {
if (event.getDrops().isEmpty()) {
return;
}
for (ItemStack itemStack : event.getDrops()) {
handleEpicBossItems(itemStack);
}
}
*/
public void handleEpicBossItems(ItemStack itemStack) {
if (Config.getInstance().getEBRBindOnEquip() && ItemUtils.isEquipable(itemStack)) {
ItemUtils.boeItem(itemStack);
}
else if (Config.getInstance().getEBRBindOnPickup()) {
ItemUtils.bopItem(itemStack);
}
else if (Config.getInstance().getEBRBindOnUse()) {
ItemUtils.bouItem(itemStack);
}
}
}

View File

@ -0,0 +1,19 @@
package com.me.tft_02.soulbound.listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.DurabilityUtils;
public class BlockListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
ItemStack itemStack = event.getPlayer().getItemInHand();
DurabilityUtils.handleInfiniteDurability(itemStack);
}
}

View File

@ -0,0 +1,80 @@
package com.me.tft_02.soulbound.listeners;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.util.DurabilityUtils;
public class EntityListener implements Listener {
/**
* Check EntityDamageByEntityEvent events.
*
* @param event The event to check
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityDeath(EntityDamageByEntityEvent event) {
if (event.getDamage() == 0 || event.getEntity().isDead()) {
return;
}
if (event.getEntity() instanceof LivingEntity) {
combatChecks(event);
}
}
/**
* Apply combat modifiers
*
* @param event The event to run the combat checks on.
*/
void combatChecks(EntityDamageByEntityEvent event) {
Entity damager = event.getDamager();
EntityType damagerType = damager.getType();
switch (damagerType) {
case PLAYER:
Player attacker = (Player) event.getDamager();
ItemStack itemInHand = attacker.getItemInHand();
DurabilityUtils.handleInfiniteDurability(itemInHand);
default:
return;
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
private void onEntityShootBow(EntityShootBowEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
DurabilityUtils.handleInfiniteDurability(((Player) entity).getItemInHand());
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
private void onEntityDamage(EntityDamageEvent event) {
if (event.getDamage() == 0 || event.getEntity().isDead()) {
return;
}
Entity entity = event.getEntity();
if (entity instanceof Player) {
Player player = (Player) entity;
for (ItemStack itemStack : player.getInventory().getArmorContents()) {
DurabilityUtils.handleInfiniteDurability(itemStack);
}
}
}
}

View File

@ -0,0 +1,179 @@
package com.me.tft_02.soulbound.listeners;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.Soulbound;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.config.ItemsConfig;
import com.me.tft_02.soulbound.datatypes.ActionType;
import com.me.tft_02.soulbound.runnables.UpdateArmorTask;
import com.me.tft_02.soulbound.util.ItemUtils;
import com.me.tft_02.soulbound.util.ItemUtils.ItemType;
import com.me.tft_02.soulbound.util.Permissions;
public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
void onInventoryClick(InventoryClickEvent event) {
HumanEntity entity = event.getWhoClicked();
ItemStack itemStack = event.getCurrentItem();
SlotType slotType = event.getSlotType();
InventoryType inventoryType = event.getInventory().getType();
if (inventoryType == null) {
return;
}
if (itemStack == null) {
return;
}
if (entity instanceof Player) {
Player player = (Player) entity;
switch (slotType) {
case ARMOR:
new UpdateArmorTask(player).runTaskLater(Soulbound.p, 2);
return;
case CONTAINER:
ItemType itemType = ItemUtils.getItemType(itemStack);
switch (itemType) {
case BIND_ON_PICKUP:
ItemUtils.soulbindItem(player, itemStack);
return;
default:
return;
}
default:
if (ItemUtils.isEquipable(itemStack) && event.isShiftClick()) {
new UpdateArmorTask(player).runTaskLater(Soulbound.p, 2);
return;
}
break;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryClickEvent(InventoryClickEvent event) {
HumanEntity entity = event.getWhoClicked();
if (!(entity instanceof Player)) {
return;
}
Player player = (Player) entity;
ItemStack itemStack = event.getCurrentItem();
InventoryType inventoryType = event.getInventory().getType();
if (inventoryType == null) {
return;
}
ItemType itemType = ItemUtils.getItemType(itemStack);
if (itemType != ItemType.SOULBOUND) {
return;
}
if (!Config.getInstance().getAllowItemStoring() && !(inventoryType == InventoryType.CRAFTING)) {
event.setCancelled(true);
}
if (ItemUtils.isBindedPlayer(player, itemStack) || Permissions.pickupBypass(player)) {
return;
}
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryMoveEvent(InventoryMoveItemEvent event) {
ItemStack itemStack = event.getItem();
ItemType itemType = ItemUtils.getItemType(itemStack);
if (itemType == ItemType.SOULBOUND) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryPickupItemEvent(InventoryPickupItemEvent event) {
ItemStack itemStack = event.getItem().getItemStack();
ItemType itemType = ItemUtils.getItemType(itemStack);
if (itemType == ItemType.SOULBOUND) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInventoryOpen(InventoryOpenEvent event) {
HumanEntity humanEntity = event.getPlayer();
Inventory inventory = event.getInventory();
if (!(humanEntity instanceof Player)) {
return;
}
Player player = (Player) humanEntity;
for (ItemStack itemStack : inventory.getContents()) {
if (itemStack != null && ItemsConfig.getInstance().isActionItem(itemStack, ActionType.OPEN_CHEST)) {
ItemUtils.soulbindItem(player, itemStack);
}
}
}
/**
* Check CraftItemEvent events.
*
* @param event The event to check
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onCraftItem(CraftItemEvent event) {
HumanEntity humanEntity = event.getWhoClicked();
if (!(humanEntity instanceof Player)) {
return;
}
Player player = (Player) humanEntity;
ItemStack itemStack = event.getRecipe().getResult();
if (ItemsConfig.getInstance().isActionItem(itemStack, ActionType.CRAFT)) {
event.getInventory().setResult(ItemUtils.soulbindItem(player, itemStack));
}
}
/**
* Check EnchantItemEvent events.
*
* @param event The event to check
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onEnchantItem(EnchantItemEvent event) {
Player player = event.getEnchanter();
ItemStack itemStack = event.getItem();
if (ItemUtils.isBindOnUse(itemStack)) {
ItemUtils.soulbindItem(player, itemStack);
return;
}
}
}

View File

@ -0,0 +1,284 @@
package com.me.tft_02.soulbound.listeners;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.Soulbound;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.config.ItemsConfig;
import com.me.tft_02.soulbound.datatypes.ActionType;
import com.me.tft_02.soulbound.runnables.SoulbindInventoryTask;
import com.me.tft_02.soulbound.runnables.UpdateArmorTask;
import com.me.tft_02.soulbound.runnables.UpdateInventoryTask;
import com.me.tft_02.soulbound.util.CommandUtils;
import com.me.tft_02.soulbound.util.DurabilityUtils;
import com.me.tft_02.soulbound.util.ItemUtils;
import com.me.tft_02.soulbound.util.Permissions;
import com.me.tft_02.soulbound.util.PlayerData;
public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
private void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (Soulbound.p.isUpdateAvailable() && Permissions.updateCheck(player)) {
player.sendMessage(ChatColor.GOLD + "Soulbound is outdated!");
player.sendMessage(ChatColor.AQUA + "http://dev.bukkit.org/server-mods/Soulbound/");
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
private void onItemPickup(PlayerPickupItemEvent event) {
Player player = event.getPlayer();
Item item = event.getItem();
ItemStack itemStack = item.getItemStack();
if (ItemUtils.isSoulbound(itemStack) && !ItemUtils.isBindedPlayer(player, itemStack)) {
if (Permissions.pickupBypass(player)) {
return;
}
event.setCancelled(true);
return;
}
if (ItemUtils.isBindOnPickup(itemStack)) {
ItemUtils.soulbindItem(player, itemStack);
return;
}
if (ItemsConfig.getInstance().isActionItem(itemStack, ActionType.PICKUP_ITEM)) {
ItemUtils.soulbindItem(player, itemStack);
return;
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onItemDrop(PlayerDropItemEvent event) {
Player player = event.getPlayer();
Item item = event.getItemDrop();
ItemStack itemStack = item.getItemStack();
if (Config.getInstance().getPreventItemDrop()) {
if (ItemUtils.isSoulbound(itemStack) && ItemUtils.isBindedPlayer(player, itemStack)) {
item.setPickupDelay(2 * 20);
event.setCancelled(true);
new UpdateInventoryTask(player).runTask(Soulbound.p);
}
return;
}
if (Config.getInstance().getDeleteOnDrop()) {
player.playSound(player.getLocation(), Sound.ITEM_BREAK, 1.0F, 1.0F);
event.getItemDrop().remove();
return;
}
if (ItemsConfig.getInstance().isActionItem(itemStack, ActionType.DROP_ITEM)) {
ItemUtils.soulbindItem(player, itemStack);
return;
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onPlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
boolean deleteOnDeath = Permissions.deleteOnDeath(player);
boolean keepOnDeath = Permissions.keepOnDeath(player);
List<ItemStack> items = new ArrayList<ItemStack>();
if (!keepOnDeath && !deleteOnDeath) {
return;
}
for (ItemStack item : new ArrayList<ItemStack>(event.getDrops())) {
if (ItemUtils.isSoulbound(item) && ItemUtils.isBindedPlayer(player, item)) {
if (keepOnDeath) {
items.add(item);
event.getDrops().remove(item);
}
else if (deleteOnDeath) {
event.getDrops().remove(item);
}
}
}
PlayerData.storeItemsDeath(player, items);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onPlayerRespawn(PlayerRespawnEvent event) {
new SoulbindInventoryTask(event.getPlayer(), ActionType.RESPAWN).runTask(Soulbound.p);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onPlayerRespawnHighest(PlayerRespawnEvent event) {
Player player = event.getPlayer();
boolean keepOnDeath = Permissions.keepOnDeath(player);
if (!keepOnDeath) {
return;
}
List<ItemStack> items = new ArrayList<ItemStack>();
items = PlayerData.retrieveItemsDeath(player);
if (items != null) {
for (ItemStack item : items) {
player.getInventory().addItem(item);
}
}
new UpdateInventoryTask(player).runTask(Soulbound.p);
}
/**
* Watch PlayerInteract events.
*
* @param event The event to watch
*/
@EventHandler(priority = EventPriority.LOW)
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
ItemStack inHand = player.getItemInHand();
switch (action) {
case RIGHT_CLICK_BLOCK:
case RIGHT_CLICK_AIR:
case LEFT_CLICK_AIR:
case LEFT_CLICK_BLOCK:
if (ItemUtils.isEquipable(inHand)) {
new UpdateArmorTask(player).runTaskLater(Soulbound.p, 2);
}
else if (ItemUtils.isBindOnUse(inHand)) {
ItemUtils.soulbindItem(player, inHand);
}
default:
break;
}
}
/**
* Monitor PlayerFishEvent events.
*
* @param event The event to monitor
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
private void onPlayerFish(PlayerFishEvent event) {
ItemStack itemInHand = event.getPlayer().getItemInHand();
DurabilityUtils.handleInfiniteDurability(itemInHand);
}
/**
* Monitor PlayerShearEntityEvent events.
*
* @param event The event to monitor
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
private void onPlayerShearEntity(PlayerShearEntityEvent event) {
ItemStack itemInHand = event.getPlayer().getItemInHand();
DurabilityUtils.handleInfiniteDurability(itemInHand);
}
/**
* Watch PlayerCommandPreprocessEvent events.
*
* @param event The event to watch
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerCommand(PlayerCommandPreprocessEvent event) {
Player player = event.getPlayer();
ItemStack itemStack = player.getItemInHand();
String command = event.getMessage();
if (ItemUtils.isSoulbound(itemStack) && Config.getInstance().getBlockedCommands().contains(command)) {
player.sendMessage(ChatColor.RED + "You're not allowed to use " + ChatColor.GOLD + command + ChatColor.RED + " command while holding a Soulbound item.");
event.setCancelled(true);
}
}
/**
* Monitor PlayerCommandPreprocessEvent events.
*
* @param event The event to monitor
*/
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerCommandMonitor(PlayerCommandPreprocessEvent event) {
Player player = event.getPlayer();
ItemStack inHand = player.getItemInHand();
String command = event.getMessage();
String[] args = CommandUtils.extractArgs(command);
if (!ItemUtils.isSoulbound(inHand) && Config.getInstance().getBindCommands().contains(command)) {
ItemUtils.soulbindItem(player, inHand);
return;
}
if (command.contains("kit")) {
Player target;
if (args.length >= 2) {
target = Soulbound.p.getServer().getPlayer(args[1]);
}
else {
target = player;
}
if (target == null) {
return;
}
new SoulbindInventoryTask(target, ActionType.KIT).runTask(Soulbound.p);
}
}
/**
* Monitor ServerCommandEvent events.
*
* @param event The event to monitor
*/
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onServerCommand(ServerCommandEvent event) {
String command = event.getCommand();
String[] args = CommandUtils.extractArgs(command);
if (!command.contains("kit")) {
return;
}
if (args.length < 2) {
return;
}
Player target = Soulbound.p.getServer().getPlayer(args[1]);
new SoulbindInventoryTask(target, ActionType.KIT).runTask(Soulbound.p);
}
}

View File

@ -0,0 +1,38 @@
package com.me.tft_02.soulbound.listeners;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.events.SoulbindItemEvent;
import com.me.tft_02.soulbound.util.ItemUtils;
import com.me.tft_02.soulbound.util.Permissions;
public class SelfListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onItemSoulbound(SoulbindItemEvent event) {
Player player = event.getPlayer();
Inventory inventory = player.getInventory();
int maxAmount = Permissions.getSoulbindMaximum(player);
if (maxAmount < 0) {
return;
}
int count = 0;
for (ItemStack itemStack : inventory.getContents()) {
if (itemStack != null && ItemUtils.isSoulbound(itemStack)) {
count++;
}
}
if (count >= maxAmount) {
player.sendMessage(ChatColor.RED + "Cannot Soulbind any more items, maximum amount reached! " + ChatColor.GOLD + "(" + maxAmount + ")");
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,34 @@
package com.me.tft_02.soulbound.runnables;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import com.me.tft_02.soulbound.config.ItemsConfig;
import com.me.tft_02.soulbound.datatypes.ActionType;
import com.me.tft_02.soulbound.util.ItemUtils;
public class SoulbindInventoryTask extends BukkitRunnable {
private Player player;
private ActionType actionType;
public SoulbindInventoryTask(Player player, ActionType actionType) {
this.player = player;
this.actionType = actionType;
}
@Override
public void run() {
for (ItemStack itemStack : player.getInventory().getContents()) {
if (itemStack != null && ItemsConfig.getInstance().isActionItem(itemStack, actionType)) {
ItemUtils.soulbindItem(player, itemStack);
}
}
for (ItemStack itemStack : player.getInventory().getArmorContents()) {
if (itemStack != null && ItemsConfig.getInstance().isActionItem(itemStack, actionType)) {
ItemUtils.soulbindItem(player, itemStack);
}
}
}
}

View File

@ -0,0 +1,31 @@
package com.me.tft_02.soulbound.runnables;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import com.me.tft_02.soulbound.util.ItemUtils;
import com.me.tft_02.soulbound.util.ItemUtils.ItemType;
public class UpdateArmorTask extends BukkitRunnable {
private Player player;
public UpdateArmorTask(Player player) {
this.player = player;
}
@Override
public void run() {
handleBindOnEquip(player);
}
public void handleBindOnEquip(Player player) {
for (ItemStack armor : player.getInventory().getArmorContents()) {
if (armor != null && ItemUtils.getItemType(armor) == ItemType.BIND_ON_EQUIP) {
ItemUtils.soulbindItem(player, armor);
}
}
player.getInventory().setArmorContents(player.getInventory().getArmorContents());
}
}

View File

@ -0,0 +1,20 @@
package com.me.tft_02.soulbound.runnables;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class UpdateInventoryTask extends BukkitRunnable {
private Player player;
public UpdateInventoryTask(Player player) {
this.player = player;
}
@SuppressWarnings("deprecation")
@Override
public void run() {
if (player.isValid()) {
player.updateInventory();
}
}
}

View File

@ -0,0 +1,38 @@
package com.me.tft_02.soulbound.util;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public final class CommandUtils {
public static String[] extractArgs(String command) {
String[] args = {""};
String[] split = command.split(" ", 2);
if (split.length > 1) {
args = split[1].split(" ");
}
return args;
}
public static boolean noConsoleUsage(CommandSender sender) {
if (sender instanceof Player) {
return false;
}
sender.sendMessage("This command does not support console usage.");
return true;
}
public static boolean isOffline(CommandSender sender, OfflinePlayer player) {
if (player != null && player.isOnline()) {
return false;
}
sender.sendMessage(ChatColor.RED + "This command does not work for offline players.");
return true;
}
}

View File

@ -0,0 +1,15 @@
package com.me.tft_02.soulbound.util;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.config.Config;
public class DurabilityUtils {
public static void handleInfiniteDurability(ItemStack itemStack) {
if (Config.getInstance().getInfiniteDurability() && ItemUtils.isSoulbound(itemStack)) {
itemStack.setDurability((short) 0);
return;
}
}
}

View File

@ -0,0 +1,435 @@
package com.me.tft_02.soulbound.util;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.me.tft_02.soulbound.Soulbound;
import com.me.tft_02.soulbound.config.Config;
import com.me.tft_02.soulbound.events.SoulbindItemEvent;
public class ItemUtils {
public enum ItemType {
NORMAL,
SOULBOUND,
BIND_ON_PICKUP,
BIND_ON_USE,
BIND_ON_EQUIP;
}
public static ItemStack soulbindItem(Player player, ItemStack itemStack) {
if (itemStack == null) {
return itemStack;
}
if (isSoulbound(itemStack)) {
return itemStack;
}
SoulbindItemEvent soulbindItemEvent = new SoulbindItemEvent(player, itemStack);
Soulbound.p.getServer().getPluginManager().callEvent(soulbindItemEvent);
itemStack = soulbindItemEvent.getItemStack();
if (soulbindItemEvent.isCancelled()) {
return itemStack;
}
ItemMeta itemMeta = itemStack.getItemMeta();
List<String> itemLore = new ArrayList<String>();
if (itemMeta.hasLore()) {
List<String> oldLore = itemMeta.getLore();
oldLore.remove(ChatColor.DARK_RED + "Bind on Pickup");
oldLore.remove(ChatColor.DARK_RED + "Bind on Equip");
oldLore.remove(ChatColor.DARK_RED + "Bind on Use");
itemLore.addAll(oldLore);
}
itemLore.add(Misc.SOULBOUND_TAG + StringUtils.hideUUID(player.getUniqueId()));
if (Config.getInstance().getShowNameInLore()) {
itemLore.add(player.getName());
}
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static ItemStack bopItem(ItemStack itemStack) {
if (itemStack == null) {
return itemStack;
}
if (isBindOnPickup(itemStack)) {
return itemStack;
}
ItemMeta itemMeta = itemStack.getItemMeta();
List<String> itemLore = new ArrayList<String>();
if (itemMeta.hasLore()) {
itemLore.addAll(itemMeta.getLore());
}
itemLore.add(ChatColor.DARK_RED + "Bind on Pickup");
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static ItemStack boeItem(ItemStack itemStack) {
if (itemStack == null) {
return itemStack;
}
if (isBindOnEquip(itemStack)) {
return itemStack;
}
ItemMeta itemMeta = itemStack.getItemMeta();
List<String> itemLore = new ArrayList<String>();
if (itemMeta.hasLore()) {
itemLore.addAll(itemMeta.getLore());
}
itemLore.add(ChatColor.DARK_RED + "Bind on Equip");
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static ItemStack bouItem(ItemStack itemStack) {
if (itemStack == null) {
return itemStack;
}
if (isBindOnUse(itemStack)) {
return itemStack;
}
ItemMeta itemMeta = itemStack.getItemMeta();
List<String> itemLore = new ArrayList<String>();
if (itemMeta.hasLore()) {
itemLore.addAll(itemMeta.getLore());
}
itemLore.add(ChatColor.DARK_RED + "Bind on Use");
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static ItemStack unbindItem(ItemStack itemStack) {
if (itemStack == null) {
return null;
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasLore() && isSoulbound(itemStack)) {
List<String> oldLore = itemMeta.getLore();
int loreSize = oldLore.size();
if (loreSize <= 2) {
itemMeta.setLore(null);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
List<String> itemLore = new ArrayList<String>();
itemLore.addAll(oldLore);
int index = StringUtils.getIndexOfSoulbound(itemLore);
if (index == -1){
return null;
}
itemLore.remove(index);
if (index<itemLore.size())
itemLore.remove(index);
itemMeta.setLore(itemLore);
}
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static boolean isSoulbound(ItemStack itemStack) {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasLore()) {
List<String> itemLore = itemMeta.getLore();
for (String lore : itemLore) {
if (lore.equalsIgnoreCase(Misc.SOULBOUND_TAG)) {
return true;
}
}
}
return false;
}
public static boolean isBindOnPickup(ItemStack itemStack) {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasLore()) {
List<String> itemLore = itemMeta.getLore();
if (itemLore.contains(ChatColor.DARK_RED + "Bind on Pickup")) {
return true;
}
}
return false;
}
public static boolean isBindOnUse(ItemStack itemStack) {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasLore()) {
List<String> itemLore = itemMeta.getLore();
if (itemLore.contains(ChatColor.DARK_RED + "Bind on Use")) {
return true;
}
}
return false;
}
public static boolean isBindOnEquip(ItemStack itemStack) {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasLore()) {
List<String> itemLore = itemMeta.getLore();
if (itemLore.contains(ChatColor.DARK_RED + "Bind on Equip")) {
return true;
}
}
return false;
}
public static boolean isBindedPlayer(Player player, ItemStack itemStack) {
updateOldLore(player, itemStack);
checkNameChange(player, itemStack);
List<String> itemLore = itemStack.getItemMeta().getLore();
Soulbound.p.debug("UUID MATCH? " + player.getUniqueId().equals(StringUtils.readUUIDFromLore(itemLore)));
Soulbound.p.debug("NAME MATCH? " + itemLore.contains(player.getName()));
return player.getUniqueId().equals(StringUtils.readUUIDFromLore(itemLore)) || itemLore.contains(player.getName());
}
private static ItemStack updateOldLore(Player player, ItemStack itemStack) {
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta != null) {
if (!itemMeta.hasLore()) {
return itemStack;
}
}
List<String> itemLore = itemMeta.getLore();
if (itemLore.size() - 1 < StringUtils.getIndexOfSoulbound(itemLore) + 2) {
return itemStack;
}
int indexOfSoulbound = StringUtils.getIndexOfSoulbound(itemLore);
int indexOfUniqueId = indexOfSoulbound + 2;
UUID uuid = null;
if (itemLore.get(indexOfUniqueId).contains(player.getUniqueId().toString())) {
uuid = UUID.fromString(ChatColor.stripColor(itemLore.get(indexOfUniqueId)));
itemLore.remove(indexOfUniqueId);
}
if (StringUtils.readUUIDFromLore(itemLore) == null && uuid != null) {
itemLore.set(indexOfSoulbound, Misc.SOULBOUND_TAG + StringUtils.hideUUID(uuid));
}
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
private static ItemStack checkNameChange(Player player, ItemStack itemStack) {
ItemMeta itemMeta = itemStack.getItemMeta();
List<String> itemLore = itemMeta.getLore();
int indexName = StringUtils.getIndexOfSoulbound(itemLore) + 1;
if (itemLore.size() >= 2 && itemLore.contains(player.getName()) && !Config.getInstance().getShowNameInLore()) {
Soulbound.p.debug("Item lore has a player name but that's disabled in config");
Soulbound.p.debug("Going to remove what is at indexName " + indexName + " which is: " + itemLore.get(indexName));
itemLore.remove(indexName);
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
if (Config.getInstance().getShowNameInLore() && !itemLore.contains(player.getName()) && player.getUniqueId().equals(StringUtils.readUUIDFromLore(itemLore))) {
Soulbound.p.debug("Item lore doesn't have (correct) player name but it should and the UUIDs match");
itemLore.add(indexName, player.getName());
}
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static boolean isNormalItem(ItemStack itemStack) {
return !itemStack.hasItemMeta() && !itemStack.getItemMeta().hasLore() || ItemUtils.getItemType(itemStack) == ItemType.NORMAL;
}
public static ItemType getItemType(ItemStack itemStack) {
if (itemStack == null) {
return ItemType.NORMAL;
}
else if (isSoulbound(itemStack)) {
return ItemType.SOULBOUND;
}
else if (isBindOnPickup(itemStack)) {
return ItemType.BIND_ON_PICKUP;
}
else if (isBindOnUse(itemStack)) {
return ItemType.BIND_ON_USE;
}
else if (isBindOnEquip(itemStack)) {
return ItemType.BIND_ON_EQUIP;
}
else {
return ItemType.NORMAL;
}
}
/**
* Checks to see if an item is an equipable item.
*
* @param is Item to check
*
* @return true if the item is equipable, false otherwise
*/
public static boolean isEquipable(ItemStack is) {
return isMinecraftArmor(is) || is.getType() == Material.SKULL_ITEM || is.getType() == Material.JACK_O_LANTERN;
}
/**
* Checks to see if an item is a wearable armor piece.
*
* @param is Item to check
*
* @return true if the item is armor, false otherwise
*/
public static boolean isMinecraftArmor(ItemStack is) {
return isLeatherArmor(is) || isGoldArmor(is) || isIronArmor(is) || isDiamondArmor(is) || isChainmailArmor(is);
}
/**
* Checks to see if an item is a leather armor piece.
*
* @param is Item to check
*
* @return true if the item is leather armor, false otherwise
*/
public static boolean isLeatherArmor(ItemStack is) {
switch (is.getType()) {
case LEATHER_BOOTS:
case LEATHER_CHESTPLATE:
case LEATHER_HELMET:
case LEATHER_LEGGINGS:
return true;
default:
return false;
}
}
/**
* Checks to see if an item is a gold armor piece.
*
* @param is Item to check
*
* @return true if the item is gold armor, false otherwise
*/
public static boolean isGoldArmor(ItemStack is) {
switch (is.getType()) {
case GOLD_BOOTS:
case GOLD_CHESTPLATE:
case GOLD_HELMET:
case GOLD_LEGGINGS:
return true;
default:
return false;
}
}
/**
* Checks to see if an item is an iron armor piece.
*
* @param is Item to check
*
* @return true if the item is iron armor, false otherwise
*/
public static boolean isIronArmor(ItemStack is) {
switch (is.getType()) {
case IRON_BOOTS:
case IRON_CHESTPLATE:
case IRON_HELMET:
case IRON_LEGGINGS:
return true;
default:
return false;
}
}
/**
* Checks to see if an item is a diamond armor piece.
*
* @param is Item to check
*
* @return true if the item is diamond armor, false otherwise
*/
public static boolean isDiamondArmor(ItemStack is) {
switch (is.getType()) {
case DIAMOND_BOOTS:
case DIAMOND_CHESTPLATE:
case DIAMOND_HELMET:
case DIAMOND_LEGGINGS:
return true;
default:
return false;
}
}
/**
* Checks to see if an item is a chainmail armor piece.
*
* @param is Item to check
*
* @return true if the item is chainmail armor, false otherwise
*/
public static boolean isChainmailArmor(ItemStack is) {
switch (is.getType()) {
case CHAINMAIL_BOOTS:
case CHAINMAIL_CHESTPLATE:
case CHAINMAIL_HELMET:
case CHAINMAIL_LEGGINGS:
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,24 @@
package com.me.tft_02.soulbound.util;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
import com.me.tft_02.soulbound.Soulbound;
public class LogFilter implements Filter {
private boolean debug;
public LogFilter(Soulbound plugin) {
// Doing a config loading lite here, because we can't depend on the config loader to have loaded before any debug messages are sent
debug = plugin.getConfig().getBoolean("General.Verbose_Logging");
}
@Override
public boolean isLoggable(LogRecord record) {
if (record.getMessage().contains("[Debug]") && !debug) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,7 @@
package com.me.tft_02.soulbound.util;
import org.bukkit.ChatColor;
public class Misc {
public static String SOULBOUND_TAG = ChatColor.GOLD + "Soulbound";
}

View File

@ -0,0 +1,40 @@
package com.me.tft_02.soulbound.util;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissionAttachmentInfo;
public class Permissions {
public static boolean keepOnDeath(Permissible permissible) {
return permissible.hasPermission("soulbound.items.keep_on_death");
}
public static boolean deleteOnDeath(Permissible permissible) {
return permissible.hasPermission("soulbound.items.delete_on_death");
}
public static boolean pickupBypass(Permissible permissible) {
return permissible.hasPermission("soulbound.pickup.bypass");
}
public static boolean updateCheck(Permissible permissible) {
return permissible.hasPermission("soulbound.updatecheck");
}
public static int getSoulbindMaximum(Player player) {
String match = "soulbound.maximum_allowed.";
int amount = -1;
for (PermissionAttachmentInfo permission : player
.getEffectivePermissions()) {
if (permission.getPermission().startsWith(match)
&& permission.getValue()) {
amount = Integer.parseInt(permission.getPermission().split(
"[.]")[2]);
}
}
return amount;
}
}

View File

@ -0,0 +1,40 @@
package com.me.tft_02.soulbound.util;
import java.util.HashMap;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.me.tft_02.soulbound.Soulbound;
public class PlayerData {
Soulbound plugin;
public PlayerData(Soulbound instance) {
plugin = instance;
}
public static HashMap<String, List<ItemStack>> playerSoulboundItems = new HashMap<String, List<ItemStack>>();
public static void storeItemsDeath(Player player, List<ItemStack> items) {
String playerName = player.getName();
if (playerSoulboundItems.containsKey(playerName)) {
playerSoulboundItems.put(playerName, null);
}
playerSoulboundItems.put(playerName, items);
}
public static List<ItemStack> retrieveItemsDeath(Player player) {
String playerName = player.getName();
if (playerSoulboundItems.containsKey(playerName)) {
return playerSoulboundItems.get(playerName);
}
else {
return null;
}
}
}

View File

@ -0,0 +1,49 @@
package com.me.tft_02.soulbound.util;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
public class StringUtils {
public static int getIndexOfSoulbound(List<String> itemLore) {
int index = -1;
for (String line : itemLore) {
if (line.contains(Misc.SOULBOUND_TAG)) {
return itemLore.indexOf(line);
}
}
return index;
}
public static UUID readUUIDFromLore(List<String> itemLore) {
int index = getIndexOfSoulbound(itemLore);
if (index == -1) {
return null;
}
String line = itemLore.get(index);
line = line.substring(11);
return readUUID(line);
}
public static String hideUUID(UUID uuid) {
String string = uuid.toString();
string = string.replaceAll("-", ChatColor.MAGIC.toString());
StringBuilder formattedString = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
formattedString.append(ChatColor.COLOR_CHAR).append(string.charAt(i));
}
return formattedString.toString();
}
public static UUID readUUID(String string) {
return UUID.fromString(string.replaceAll(ChatColor.MAGIC.toString(), "-").replaceAll("§", ""));
}
}

50
src/main/java/config.yml Normal file
View File

@ -0,0 +1,50 @@
#
# Soulbound configuration
# Last updated on ${project.version}-b${BUILD_NUMBER}
#
#####
#
# Settings for Soulbound in general
###
General:
# Allow Soulbound to report on basic anonymous usage
Stats_Tracking: true
# Allow Soulbound to check if a new version is available
Update_Check: true
Prefer_Beta: false
# Should Soulbound print out debug messages?
Verbose_Logging: false
# Should Soulbound over-write configs to update, or make new ones ending in .new?
Config_Update_Overwrite: true
Soulbound:
Show_Name_In_Lore: true
Feedback_Messages_Enabled: true
Prevent_Item_Drop: false
Delete_On_Drop: false
Allow_Item_Storing: true
Infinite_Durability: false
Blocked_Commands:
/blockedcommand
Commands_Bind_When_Used:
/enchant
Dependency_Plugins:
DiabloDrops:
BindOnPickup: Legendary, Rare, Unidentified
BindOnUse: Magical
BindOnEquip: Set
EpicBossRecoded:
BindOnPickup: true
BindOnUse: false
BindOnEquip: false
LoreLocks:
Bind_Keys: true
MythicDrops:
BindOnPickup: common, uncommon, rare
BindOnUse: terric, netheric
BindOnEquip: endric

35
src/main/java/items.yml Normal file
View File

@ -0,0 +1,35 @@
#
# Soulbound item configuration
#
# Items in this config file will be automatically Soulbound to the player on certain
# actions, such as dropping the item or picking it up.
#
# You can add items under "Items" using the exact material name. You can add a data value using a |
# For example, WOOL|15 would be Material.WOOL with data value 15.
#
# The bare minimum of a Soulbound item is that it has Actions
#
# Name: This is the displayname of an item
#
# Lore: List one or more lines of lore here
#
# Actions: The actions when the item should be soulbound to the player.
# Valid values are: CRAFT, OPEN_CHEST, PICKUP_ITEM, DROP_ITEM, RESPAWN, KIT
#
#
###
Items:
DIAMOND_SPADE:
Lore:
- Made from diamond,
- can dig dirt!
Actions:
- CRAFT
- OPEN_CHEST
WOOL|15:
Name: Black Piece Of Wool
Actions:
- PICKUP_ITEM
- DROP_ITEM

View File

@ -0,0 +1,558 @@
/*
* Updater for Bukkit.
*
* This class provides the means to safely and easily update a plugin, or check to see if it is updated using dev.bukkit.org
*/
package net.gravitydevelopment.updater.soulbound;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import com.me.tft_02.soulbound.config.Config;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
/**
* Check dev.bukkit.org to find updates for a given plugin, and download the updates if needed.
* <p/>
* <b>VERY, VERY IMPORTANT</b>: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed auto-updating.
* <br>
* It is a <b>BUKKIT POLICY</b> that you include a boolean value in your config that prevents the auto-updater from running <b>AT ALL</b>.
* <br>
* If you fail to include this option in your config, your plugin will be <b>REJECTED</b> when you attempt to submit it to dev.bukkit.org.
* <p/>
* An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater.
* <br>
* If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l
*
* @author Gravity
* @version 2.0
*/
public class Updater {
private Plugin plugin;
private UpdateType type;
private String versionName;
private String versionLink;
private String versionType;
private String versionGameVersion;
private boolean announce; // Whether to announce file downloads
private URL url; // Connecting to RSS
private File file; // The plugin's file
private Thread thread; // Updater thread
private int id = -1; // Project's Curse ID
private String apiKey = null; // BukkitDev ServerMods API key
private static final String TITLE_VALUE = "name"; // Gets remote file's title
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
private static final int BYTE_SIZE = 1024; // Used for downloading files
private YamlConfiguration config; // Config file
private String updateFolder;// The folder that downloads will be placed in
private Updater.UpdateResult result = Updater.UpdateResult.SUCCESS; // Used for determining the outcome of the update process
/**
* Gives the dev the result of the update process. Can be obtained by called getResult().
*/
public enum UpdateResult {
/**
* The updater found an update, and has readied it to be loaded the next time the server restarts/reloads.
*/
SUCCESS,
/**
* The updater did not find an update, and nothing was downloaded.
*/
NO_UPDATE,
/**
* The server administrator has disabled the updating system
*/
DISABLED,
/**
* The updater found an update, but was unable to download it.
*/
FAIL_DOWNLOAD,
/**
* For some reason, the updater was unable to contact dev.bukkit.org to download the file.
*/
FAIL_DBO,
/**
* When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'.
*/
FAIL_NOVERSION,
/**
* The id provided by the plugin running the updater was invalid and doesn't exist on DBO.
*/
FAIL_BADID,
/**
* The server administrator has improperly configured their API key in the configuration
*/
FAIL_APIKEY,
/**
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
*/
UPDATE_AVAILABLE
}
/**
* Allows the dev to specify the type of update that will be run.
*/
public enum UpdateType {
/**
* Run a version check, and then if the file is out of date, download the newest version.
*/
DEFAULT,
/**
* Don't run a version check, just find the latest update and download it.
*/
NO_VERSION_CHECK,
/**
* Get information about the version and the download size, but don't actually download anything.
*/
NO_DOWNLOAD
}
/**
* Initialize the updater
*
* @param plugin The plugin that is checking for an update.
* @param id The dev.bukkit.org id of the project
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
* @param type Specify the type of update this will be. See {@link UpdateType}
* @param announce True if the program should announce the progress of new updates in console
*/
public Updater(Plugin plugin, int id, File file, UpdateType type, boolean announce) {
this.plugin = plugin;
this.type = type;
this.announce = announce;
this.file = file;
this.id = id;
this.updateFolder = plugin.getServer().getUpdateFolder();
final File pluginFile = plugin.getDataFolder().getParentFile();
final File updaterFile = new File(pluginFile, "Updater");
final File updaterConfigFile = new File(updaterFile, "config.yml");
if (!updaterFile.exists()) {
updaterFile.mkdir();
}
if (!updaterConfigFile.exists()) {
try {
updaterConfigFile.createNewFile();
}
catch (final IOException e) {
plugin.getLogger().severe("The updater could not create a configuration in " + updaterFile.getAbsolutePath());
e.printStackTrace();
}
}
this.config = YamlConfiguration.loadConfiguration(updaterConfigFile);
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" + '\n'
+ "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." + '\n'
+ "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
this.config.addDefault("api-key", "PUT_API_KEY_HERE");
this.config.addDefault("disable", false);
if (this.config.get("api-key", null) == null) {
this.config.options().copyDefaults(true);
try {
this.config.save(updaterConfigFile);
}
catch (final IOException e) {
plugin.getLogger().severe("The updater could not save the configuration in " + updaterFile.getAbsolutePath());
e.printStackTrace();
}
}
if (this.config.getBoolean("disable")) {
this.result = UpdateResult.DISABLED;
return;
}
String key = this.config.getString("api-key");
if (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals("")) {
key = null;
}
this.apiKey = key;
try {
this.url = new URL(Updater.HOST + Updater.QUERY + id);
}
catch (final MalformedURLException e) {
plugin.getLogger().severe("The project ID provided for updating, " + id + " is invalid.");
this.result = UpdateResult.FAIL_BADID;
e.printStackTrace();
}
this.thread = new Thread(new UpdateRunnable());
this.thread.start();
}
/**
* Get the result of the update process.
*/
public Updater.UpdateResult getResult() {
this.waitForThread();
return this.result;
}
/**
* Get the latest version's release type (release, beta, or alpha).
*/
public String getLatestType() {
this.waitForThread();
return this.versionType;
}
/**
* Get the latest version's game version.
*/
public String getLatestGameVersion() {
this.waitForThread();
return this.versionGameVersion;
}
/**
* Get the latest version's name.
*/
public String getLatestName() {
this.waitForThread();
return this.versionName;
}
/**
* Get the latest version's file link.
*/
public String getLatestFileLink() {
this.waitForThread();
return this.versionLink;
}
/**
* As the result of Updater output depends on the thread's completion, it is necessary to wait for the thread to finish
* before allowing anyone to check the result.
*/
private void waitForThread() {
if ((this.thread != null) && this.thread.isAlive()) {
try {
this.thread.join();
}
catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Save an update from dev.bukkit.org into the server's update folder.
*/
private void saveFile(File folder, String file, String u) {
if (!folder.exists()) {
folder.mkdir();
}
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
// Download the file
final URL url = new URL(u);
final int fileLength = url.openConnection().getContentLength();
in = new BufferedInputStream(url.openStream());
fout = new FileOutputStream(folder.getAbsolutePath() + "/" + file);
final byte[] data = new byte[Updater.BYTE_SIZE];
int count;
if (this.announce) {
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
}
long downloaded = 0;
while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) {
downloaded += count;
fout.write(data, 0, count);
final int percent = (int) ((downloaded * 100) / fileLength);
if (this.announce && ((percent % 10) == 0)) {
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
}
}
//Just a quick check to make sure we didn't leave any files from last time...
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
if (xFile.getName().endsWith(".zip")) {
xFile.delete();
}
}
// Check to see if it's a zip file, if it is, unzip it.
final File dFile = new File(folder.getAbsolutePath() + "/" + file);
if (dFile.getName().endsWith(".zip")) {
// Unzip
this.unzip(dFile.getCanonicalPath());
}
if (this.announce) {
this.plugin.getLogger().info("Finished updating.");
}
}
catch (final Exception ex) {
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
}
finally {
try {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
catch (final Exception ex) {
}
}
}
/**
* Part of Zip-File-Extractor, modified by Gravity for use with Bukkit
*/
private void unzip(String file) {
try {
final File fSourceZip = new File(file);
final String zipPath = file.substring(0, file.length() - 4);
ZipFile zipFile = new ZipFile(fSourceZip);
Enumeration<? extends ZipEntry> e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
File destinationFilePath = new File(zipPath, entry.getName());
destinationFilePath.getParentFile().mkdirs();
if (entry.isDirectory()) {
continue;
}
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
int b;
final byte buffer[] = new byte[Updater.BYTE_SIZE];
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
final BufferedOutputStream bos = new BufferedOutputStream(fos, Updater.BYTE_SIZE);
while ((b = bis.read(buffer, 0, Updater.BYTE_SIZE)) != -1) {
bos.write(buffer, 0, b);
}
bos.flush();
bos.close();
bis.close();
final String name = destinationFilePath.getName();
if (name.endsWith(".jar") && this.pluginFile(name)) {
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + "/" + name));
}
entry = null;
destinationFilePath = null;
}
e = null;
zipFile.close();
zipFile = null;
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
for (final File dFile : new File(zipPath).listFiles()) {
if (dFile.isDirectory()) {
if (this.pluginFile(dFile.getName())) {
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
{
boolean found = false;
for (final File xFile : contents) // Loop through contents to see if it exists
{
if (xFile.getName().equals(cFile.getName())) {
found = true;
break;
}
}
if (!found) {
// Move the new file into the current dir
cFile.renameTo(new File(oFile.getCanonicalFile() + "/" + cFile.getName()));
}
else {
// This file already exists, so we don't need it anymore.
cFile.delete();
}
}
}
}
dFile.delete();
}
new File(zipPath).delete();
fSourceZip.delete();
}
catch (final IOException ex) {
this.plugin.getLogger().warning("The auto-updater tried to unzip a new update file, but was unsuccessful.");
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
ex.printStackTrace();
}
new File(file).delete();
}
/**
* Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip.
*/
private boolean pluginFile(String name) {
for (final File file : new File("plugins").listFiles()) {
if (file.getName().equals(name)) {
return true;
}
}
return false;
}
/**
* Check to see if the program should continue by evaluation whether the plugin is already updated, or shouldn't be updated
*/
private boolean versionCheck(String title) {
if (type != UpdateType.NO_VERSION_CHECK) {
String version = plugin.getDescription().getVersion();
title = title.substring(1);
String[] oldTokens = version.split("-");
String[] newTokens = title.split("-");
int oldVersion = Integer.parseInt(oldTokens[0].replaceAll("[.]", ""));
int newVersion = Integer.parseInt(newTokens[0].replaceAll("[.]", ""));
// Check versions
if (oldVersion < newVersion) {
return true;
}
// Check release vs. beta & SNAPSHOT
if (newTokens.length == 1 && oldTokens.length == 3 && oldVersion == newVersion) {
return true;
}
// Check beta vs. SNAPSHOT
if (version.contains("SNAPSHOT") && title.contains("beta")) {
if (Integer.parseInt(oldTokens[1].substring(8)) <= Integer.parseInt(newTokens[1].substring(4))) {
return true;
}
result = UpdateResult.NO_UPDATE;
return false;
}
// Check beta vs. beta
if (version.contains("beta") && title.contains("beta")) {
if (Integer.parseInt(oldTokens[1].substring(4)) < Integer.parseInt(newTokens[1].substring(4))) {
return true;
}
result = UpdateResult.NO_UPDATE;
return false;
}
if (oldTokens.length == 3 && !version.contains("beta") && !version.contains("SNAPSHOT")) {
plugin.getLogger().warning("Could not get information about this Soulbound version; perhaps you are running a custom one?");
result = UpdateResult.FAIL_NOVERSION;
return false;
}
result = UpdateResult.NO_UPDATE;
return false;
}
return true;
}
private boolean read() {
try {
final URLConnection conn = this.url.openConnection();
conn.setConnectTimeout(5000);
if (this.apiKey != null) {
conn.addRequestProperty("X-API-Key", this.apiKey);
}
conn.addRequestProperty("User-Agent", "Updater (by Gravity)");
conn.setDoOutput(true);
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
final String response = reader.readLine();
final JSONArray array = (JSONArray) JSONValue.parse(response);
if (array.size() == 0) {
this.plugin.getLogger().warning("The updater could not find any files for the project id " + this.id);
this.result = UpdateResult.FAIL_BADID;
return false;
}
this.versionName = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TITLE_VALUE);
this.versionLink = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.LINK_VALUE);
this.versionType = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TYPE_VALUE);
this.versionGameVersion = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.VERSION_VALUE);
return true;
}
catch (final IOException e) {
if (e.getMessage().contains("HTTP response code: 403")) {
this.plugin.getLogger().warning("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
this.plugin.getLogger().warning("Please double-check your configuration to ensure it is correct.");
this.result = UpdateResult.FAIL_APIKEY;
}
else {
this.plugin.getLogger().warning("The updater could not contact dev.bukkit.org for updating.");
this.plugin.getLogger().warning("If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime.");
this.result = UpdateResult.FAIL_DBO;
}
if (Config.getInstance().getVerboseLoggingEnabled()) {
e.printStackTrace();
}
return false;
}
}
private class UpdateRunnable implements Runnable {
@Override
public void run() {
if (Updater.this.url != null) {
// Obtain the results of the project's file feed
if (Updater.this.read()) {
if (Updater.this.versionCheck(Updater.this.versionName)) {
if ((Updater.this.versionLink != null) && (Updater.this.type != UpdateType.NO_DOWNLOAD)) {
String name = Updater.this.file.getName();
// If it's a zip file, it shouldn't be downloaded as the plugin's name
if (Updater.this.versionLink.endsWith(".zip")) {
final String[] split = Updater.this.versionLink.split("/");
name = split[split.length - 1];
}
Updater.this.saveFile(new File(Updater.this.plugin.getDataFolder().getParent(), Updater.this.updateFolder), name, Updater.this.versionLink);
}
else {
Updater.this.result = UpdateResult.UPDATE_AVAILABLE;
}
}
}
}
}
}
}

56
src/main/java/plugin.yml Normal file
View File

@ -0,0 +1,56 @@
name: Soulbound
version: 1.1.10-SNAPSHOT-b84
author: TfT_02
main: com.me.tft_02.soulbound.Soulbound
description: Soulbound items for your RPG servers!
softdepend: [EpicBossRecoded, LoreLocks, MythicDrops]
commands:
soulbound:
description: Usage /soulbound
permission-message: You don't have <permission>
bind:
description: Usage /bind
alias: bound
permission: soulbound.commands.bind
permission-message: You don't have <permission>
bindonpickup:
description: Usage /bindonpickup
permission: soulbound.commands.bindonpickup
permission-message: You don't have <permission>
bindonuse:
description: Usage /bindonuse
permission: soulbound.commands.bindonuse
permission-message: You don't have <permission>
bindonequip:
description: Usage /bindonequip
permission: soulbound.commands.bindonequip
permission-message: You don't have <permission>
unbind:
description: Usage /unbind
alias: unbound
permission: soulbound.commands.unbind
permission-message: You don't have <permission>
permissions:
soulbound.commands.all:
description: Gives access to the Soulbound commands
default: op
children:
soulbound.commands.bind: true
soulbound.commands.bindonpickup: true
soulbound.commands.bindonuse: true
soulbound.commands.bindonequip: true
soulbound.commands.unbind: true
soulbound.commands.reload: true
soulbound.updatecheck: true
soulbound.pickup.bypass:
description: Users with this permission will be able to pickup Soulbound items that do not belong to them.
default: false
soulbound.items.keep_on_death:
description: Users with this permission will keep their Soulbound items after dying
default: false
soulbound.items.delete_on_death:
description: Users with this permission will have their Soulbound items deleted on death
default: false
soulbound.updatecheck:
description: Users with this permission will receive a notification when there is a new version available.
default: op