Require Bukkit 1.8 as minimum version

This commit is contained in:
filoghost 2020-06-05 19:59:13 +02:00
parent e303d6969c
commit 500a2699f3
8 changed files with 179 additions and 291 deletions

View File

@ -41,9 +41,9 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${spigot-api.version}</version>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkit.version}</version>
<scope>provided</scope>
</dependency>

View File

@ -45,6 +45,8 @@ import me.filoghost.chestcommands.task.RefreshMenusTask;
import me.filoghost.chestcommands.util.BukkitUtils;
import me.filoghost.chestcommands.util.CaseInsensitiveMap;
import me.filoghost.chestcommands.util.ErrorLogger;
import me.filoghost.chestcommands.util.Utils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@ -83,6 +85,15 @@ public class ChestCommands extends JavaPlugin {
settings = new Settings(new PluginConfig(this, "config.yml"));
lang = new Lang(new PluginConfig(this, "lang.yml"));
if (!Utils.isClassLoaded("org.bukkit.inventory.ItemFlag")) { // ItemFlag was added in 1.8
if (Bukkit.getVersion().contains("(MC: 1.8)")) {
criticalShutdown("ChestCommands requires a more recent version of Bukkit 1.8 to run.");
} else {
criticalShutdown("ChestCommands requires at least Bukkit 1.8 to run.");
}
return;
}
if (!EconomyBridge.setupEconomy()) {
getLogger().warning("Vault with a compatible economy plugin was not found! Icons with a PRICE or commands that give money will not work.");
@ -266,7 +277,7 @@ public class ChestCommands extends JavaPlugin {
public static void closeAllMenus() {
for (Player player : BukkitUtils.getOnlinePlayers()) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getOpenInventory() != null) {
if (player.getOpenInventory().getTopInventory().getHolder() instanceof MenuInventoryHolder || player.getOpenInventory().getBottomInventory().getHolder() instanceof MenuInventoryHolder) {
player.closeInventory();
@ -315,5 +326,25 @@ public class ChestCommands extends JavaPlugin {
public static void setLastReloadErrors(int lastReloadErrors) {
ChestCommands.lastReloadErrors = lastReloadErrors;
}
private static void criticalShutdown(String... errorMessage) {
String separator = "****************************************************************************";
StringBuffer output = new StringBuffer("\n ");
output.append("\n" + separator);
for (String line : errorMessage) {
output.append("\n " + line);
}
output.append("\n ");
output.append("\n This plugin has been disabled.");
output.append("\n" + separator);
output.append("\n ");
System.out.println(output);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {}
instance.setEnabled(false);
}
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.internal;
import me.filoghost.chestcommands.util.BukkitUtils;
import org.bukkit.Bukkit;
public class CachedGetters {
@ -27,7 +27,7 @@ public class CachedGetters {
if (lastOnlinePlayersRefresh == 0 || now - lastOnlinePlayersRefresh > 1000) {
// getOnlinePlayers() could be expensive if called frequently
lastOnlinePlayersRefresh = now;
onlinePlayers = BukkitUtils.getOnlinePlayers().size();
onlinePlayers = Bukkit.getOnlinePlayers().size();
}
return onlinePlayers;

View File

@ -14,13 +14,13 @@
*/
package me.filoghost.chestcommands.task;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import me.filoghost.chestcommands.internal.ExtendedIconMenu;
import me.filoghost.chestcommands.internal.MenuInventoryHolder;
import me.filoghost.chestcommands.util.BukkitUtils;
public class RefreshMenusTask implements Runnable {
@ -29,7 +29,7 @@ public class RefreshMenusTask implements Runnable {
@Override
public void run() {
for (Player player : BukkitUtils.getOnlinePlayers()) {
for (Player player : Bukkit.getOnlinePlayers()) {
InventoryView view = player.getOpenInventory();
if (view == null) {

View File

@ -1,73 +1,41 @@
package me.filoghost.chestcommands.util;
import com.google.common.collect.ImmutableList;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
public final class BukkitUtils {
private static final Method LEGACY_GET_ONLINE_PLAYERS;
static {
try {
Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
LEGACY_GET_ONLINE_PLAYERS = method.getReturnType() == Player[].class ? method : null;
} catch (NoSuchMethodException e) {
// This should NEVER happen!
throw new IllegalStateException("Missing Bukkit.getOnlinePlayers() method!");
}
}
private BukkitUtils() {
}
public static Collection<? extends Player> getOnlinePlayers() {
try {
if (LEGACY_GET_ONLINE_PLAYERS == null) {
return Bukkit.getOnlinePlayers();
} else {
Player[] playersArray = (Player[]) LEGACY_GET_ONLINE_PLAYERS.invoke(null);
return ImmutableList.copyOf(playersArray);
}
} catch (Exception e) {
e.printStackTrace();
return Collections.emptyList();
}
}
public static String addYamlExtension(String input) {
if (input == null) {
return null;
}
return input.toLowerCase().endsWith(".yml") ? input : input + ".yml";
}
public static void saveResourceSafe(Plugin plugin, String name) {
try {
plugin.saveResource(name, false);
} catch (Exception ignored) {
}
}
public static Sound matchSound(String input) {
if (input == null) {
return null;
}
input = StringUtils.stripChars(input.toLowerCase(), " _-");
for (Sound sound : Sound.values()) {
if (StringUtils.stripChars(sound.toString().toLowerCase(), "_").equals(input)) {
return sound;
}
}
return null;
}
}
package me.filoghost.chestcommands.util;
import org.bukkit.Sound;
import org.bukkit.plugin.Plugin;
public final class BukkitUtils {
private BukkitUtils() {}
public static String addYamlExtension(String input) {
if (input == null) {
return null;
}
return input.toLowerCase().endsWith(".yml") ? input : input + ".yml";
}
public static void saveResourceSafe(Plugin plugin, String name) {
try {
plugin.saveResource(name, false);
} catch (Exception ignored) {
}
}
public static Sound matchSound(String input) {
if (input == null) {
return null;
}
input = StringUtils.stripChars(input.toLowerCase(), " _-");
for (Sound sound : Sound.values()) {
if (StringUtils.stripChars(sound.toString().toLowerCase(), "_").equals(input)) {
return sound;
}
}
return null;
}
}

View File

@ -1,180 +1,98 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.util;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.filoghost.chestcommands.exception.FormatException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public final class ItemUtils {
private static final boolean USE_ITEM_FLAGS_API;
private static final boolean USE_ITEM_FLAGS_REFLECTION;
// Reflection stuff
private static Class<?> nbtTagCompoundClass;
private static Class<?> nbtTagListClass;
private static Class<?> nmsItemstackClass;
private static Method asNmsCopyMethod;
private static Method asCraftMirrorMethod;
private static Method hasTagMethod;
private static Method getTagMethod;
private static Method setTagMethod;
private static Method nbtSetMethod;
static {
if (Utils.isClassLoaded("org.bukkit.inventory.ItemFlag")) {
// We can use the new Bukkit API (1.8.3+)
USE_ITEM_FLAGS_API = true;
USE_ITEM_FLAGS_REFLECTION = false;
} else {
USE_ITEM_FLAGS_API = false;
// Try to get the NMS methods and classes
boolean success;
try {
nbtTagCompoundClass = NMSUtils.getNMSClass("NBTTagCompound");
nbtTagListClass = NMSUtils.getNMSClass("NBTTagList");
nmsItemstackClass = NMSUtils.getNMSClass("ItemStack");
asNmsCopyMethod = NMSUtils.getCraftBukkitClass("inventory.CraftItemStack").getMethod("asNMSCopy", ItemStack.class);
asCraftMirrorMethod = NMSUtils.getCraftBukkitClass("inventory.CraftItemStack").getMethod("asCraftMirror", nmsItemstackClass);
hasTagMethod = nmsItemstackClass.getMethod("hasTag");
getTagMethod = nmsItemstackClass.getMethod("getTag");
setTagMethod = nmsItemstackClass.getMethod("setTag", nbtTagCompoundClass);
nbtSetMethod = nbtTagCompoundClass.getMethod("set", String.class, NMSUtils.getNMSClass("NBTBase"));
success = true;
} catch (Exception e) {
new IllegalStateException("Could not enable the attribute remover for this version." +
"Attributes will show up on items.", e).printStackTrace();
success = false;
}
USE_ITEM_FLAGS_REFLECTION = success;
}
}
private ItemUtils() {
}
public static ItemStack hideAttributes(ItemStack item) {
if (item == null) {
return null;
}
if (USE_ITEM_FLAGS_API) {
ItemMeta meta = item.getItemMeta();
if (Utils.isNullOrEmpty(meta.getItemFlags())) {
// Add them only if necessary
meta.addItemFlags(ItemFlag.values());
item.setItemMeta(meta);
}
return item;
} else if (USE_ITEM_FLAGS_REFLECTION) {
try {
Object nmsItemstack = asNmsCopyMethod.invoke(null, item);
if (nmsItemstack == null) {
return item;
}
Object nbtCompound;
if ((Boolean) hasTagMethod.invoke(nmsItemstack)) {
nbtCompound = getTagMethod.invoke(nmsItemstack);
} else {
nbtCompound = nbtTagCompoundClass.newInstance();
setTagMethod.invoke(nmsItemstack, nbtCompound);
}
if (nbtCompound == null) {
return item;
}
Object nbtList = nbtTagListClass.newInstance();
nbtSetMethod.invoke(nbtCompound, "AttributeModifiers", nbtList);
return (ItemStack) asCraftMirrorMethod.invoke(null, nmsItemstack);
} catch (Throwable t) {
// Ignore
}
}
// On failure just return the item
return item;
}
public static Color parseColor(String input) throws FormatException {
String[] split = StringUtils.stripChars(input, " ").split(",");
if (split.length != 3) {
throw new FormatException("it must be in the format \"red, green, blue\".");
}
int red, green, blue;
try {
red = Integer.parseInt(split[0]);
green = Integer.parseInt(split[1]);
blue = Integer.parseInt(split[2]);
} catch (NumberFormatException ex) {
throw new FormatException("it contains invalid numbers.");
}
if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {
throw new FormatException("it should only contain numbers between 0 and 255.");
}
return Color.fromRGB(red, green, blue);
}
public static DyeColor parseDyeColor(String input) throws FormatException {
DyeColor color;
try {
color = DyeColor.valueOf(input.toUpperCase());
} catch (IllegalArgumentException e) {
throw new FormatException("it must be a valid color.");
}
return color;
}
public static List<Pattern> parseBannerPatternList(List<String> input) throws FormatException {
List<Pattern> patterns = new ArrayList<Pattern>();
for (String str : input) {
String[] split = str.split(":");
if (split.length != 2) {
throw new FormatException("it must be in the format \"pattern:color\".");
}
try {
patterns.add(new Pattern(parseDyeColor(split[1]), PatternType.valueOf(split[0].toUpperCase())));
} catch (IllegalArgumentException e) {
throw new FormatException("it must be a valid pattern type.");
}
}
return patterns;
}
}
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.util;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.filoghost.chestcommands.exception.FormatException;
import java.util.ArrayList;
import java.util.List;
public final class ItemUtils {
private ItemUtils() {
}
public static ItemStack hideAttributes(ItemStack item) {
if (item == null) {
return null;
}
ItemMeta meta = item.getItemMeta();
if (Utils.isNullOrEmpty(meta.getItemFlags())) {
// Add them only if no flag was already set
meta.addItemFlags(ItemFlag.values());
item.setItemMeta(meta);
}
return item;
}
public static Color parseColor(String input) throws FormatException {
String[] split = StringUtils.stripChars(input, " ").split(",");
if (split.length != 3) {
throw new FormatException("it must be in the format \"red, green, blue\".");
}
int red, green, blue;
try {
red = Integer.parseInt(split[0]);
green = Integer.parseInt(split[1]);
blue = Integer.parseInt(split[2]);
} catch (NumberFormatException ex) {
throw new FormatException("it contains invalid numbers.");
}
if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {
throw new FormatException("it should only contain numbers between 0 and 255.");
}
return Color.fromRGB(red, green, blue);
}
public static DyeColor parseDyeColor(String input) throws FormatException {
DyeColor color;
try {
color = DyeColor.valueOf(input.toUpperCase());
} catch (IllegalArgumentException e) {
throw new FormatException("it must be a valid color.");
}
return color;
}
public static List<Pattern> parseBannerPatternList(List<String> input) throws FormatException {
List<Pattern> patterns = new ArrayList<Pattern>();
for (String str : input) {
String[] split = str.split(":");
if (split.length != 2) {
throw new FormatException("it must be in the format \"pattern:color\".");
}
try {
patterns.add(new Pattern(parseDyeColor(split[1]), PatternType.valueOf(split[0].toUpperCase())));
} catch (IllegalArgumentException e) {
throw new FormatException("it must be a valid pattern type.");
}
}
return patterns;
}
}

View File

@ -1,29 +0,0 @@
package me.filoghost.chestcommands.util;
import org.bukkit.Bukkit;
public final class NMSUtils {
private static final String NMS_VERSION;
static {
String packageName = Bukkit.getServer().getClass().getPackage().getName();
NMS_VERSION = packageName.substring(packageName.lastIndexOf('.') + 1);
}
private NMSUtils() {
}
public static String getNMSVersion() {
return NMS_VERSION;
}
public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
return Class.forName("net.minecraft.server." + NMSUtils.getNMSVersion() + "." + name);
}
public static Class<?> getCraftBukkitClass(String name) throws ClassNotFoundException {
return Class.forName("org.bukkit.craftbukkit." + NMSUtils.getNMSVersion() + "." + name);
}
}

View File

@ -22,7 +22,7 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.test.skip>true</maven.test.skip>
<spigot-api.version>1.8.8-R0.1-SNAPSHOT</spigot-api.version>
<bukkit.version>1.8-R0.1-SNAPSHOT</bukkit.version>
</properties>
<modules>