diff --git a/CHANGELOG.md b/CHANGELOG.md index 46371c214..09210105d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,11 +59,17 @@ #### Changes * Replaced GuideHandlers with FlexCategories * Removed support for old EmeraldEnchants versions +* Updated the book variant of the guide to use the newer API +* Removed internal /sf elevator command +* Split whitelist.yml up into individual /world-settings/worldname.yml files +* Performance improvements +* Slimefun Guide runs much faster now and can better deal with many Categories and items #### Fixes * Fixed error message when clicking empty slots in the Slimefun Guide * Fixed #1779 * Fixed localized messages not showing in the book guide +* Fixed empty categories showing up when items inside were hidden ## Release Candidate 10 (28 Mar 2020) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java index 092079ec9..e86ee00d5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java @@ -7,6 +7,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; @@ -19,9 +20,11 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.config.Config; import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece; import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory; +import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.Research; @@ -201,27 +204,28 @@ public final class PlayerProfile { public void sendStats(CommandSender sender) { Set researched = getResearches(); int levels = researched.stream().mapToInt(Research::getCost).sum(); + int totalResearches = SlimefunPlugin.getRegistry().getResearches().size(); - String progress = String.valueOf(Math.round(((researched.size() * 100.0F) / SlimefunPlugin.getRegistry().getResearches().size()) * 100.0F) / 100.0F); - if (Float.parseFloat(progress) < 16.0F) progress = "&4" + progress + " &r% "; - else if (Float.parseFloat(progress) < 32.0F) progress = "&c" + progress + " &r% "; - else if (Float.parseFloat(progress) < 48.0F) progress = "&6" + progress + " &r% "; - else if (Float.parseFloat(progress) < 64.0F) progress = "&e" + progress + " &r% "; - else if (Float.parseFloat(progress) < 80.0F) progress = "&2" + progress + " &r% "; - else progress = "&a" + progress + " &r% "; + float progress = Math.round(((researched.size() * 100.0F) / totalResearches) * 100.0F) / 100.0F; sender.sendMessage(""); - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Statistics for Player: &b" + name)); + sender.sendMessage(ChatColors.color("&7Statistics for Player: &b" + name)); sender.sendMessage(""); - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Title: &b" + getTitle())); - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Research Progress: " + progress + "&e(" + researched.size() + " / " + SlimefunPlugin.getRegistry().getResearches().size() + ")")); - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Total XP Levels spent: &b" + levels)); + sender.sendMessage(ChatColors.color("&7Title: " + ChatColor.AQUA + getTitle())); + sender.sendMessage(ChatColors.color("&7Research Progress: " + NumberUtils.getColorFromPercentage(progress) + progress + " &r% " + ChatColor.YELLOW + '(' + researched.size() + " / " + totalResearches + ')')); + sender.sendMessage(ChatColors.color("&7Total XP Levels spent: " + ChatColor.AQUA + levels)); } public Player getPlayer() { return Bukkit.getPlayer(getUUID()); } + /** + * This returns the {@link GuideHistory} of this {@link Player}. + * It is basically that player's browsing history. + * + * @return The {@link GuideHistory} of this {@link Player} + */ public GuideHistory getGuideHistory() { return guideHistory; } @@ -291,28 +295,26 @@ public final class PlayerProfile { * The player who's profile to retrieve * @param callback * The callback with the PlayerProfile + * * @return If the player was cached or not. */ public static boolean get(OfflinePlayer p, Consumer callback) { - PlayerProfile profile = SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId()); + PlayerProfile cached = SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId()); - if (profile != null) { - callback.accept(profile); + if (cached != null) { + callback.accept(cached); return true; } Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> { - PlayerProfile pp = new PlayerProfile(p); - SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), pp); - callback.accept(pp); + PlayerProfile profile = new PlayerProfile(p); + SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), profile); + callback.accept(profile); }); + return false; } - public static boolean isLoaded(UUID uuid) { - return SlimefunPlugin.getRegistry().getPlayerProfiles().containsKey(uuid); - } - public static Optional find(OfflinePlayer p) { return Optional.ofNullable(SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId())); } @@ -324,24 +326,23 @@ public final class PlayerProfile { public static PlayerBackpack getBackpack(ItemStack item) { if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasLore()) return null; - Optional id = Optional.empty(); + OptionalInt id = OptionalInt.empty(); String uuid = ""; for (String line : item.getItemMeta().getLore()) { - if (line.startsWith(ChatColor.translateAlternateColorCodes('&', "&7ID: ")) && line.indexOf('#') != -1) { - try { - String[] splitLine = PatternUtils.HASH.split(line); - id = Optional.of(Integer.parseInt(splitLine[1])); - uuid = splitLine[0].replace(ChatColor.translateAlternateColorCodes('&', "&7ID: "), ""); - } - catch (NumberFormatException x) { - return null; + if (line.startsWith(ChatColors.color("&7ID: ")) && line.indexOf('#') != -1) { + String[] splitLine = PatternUtils.HASH.split(line); + + if (PatternUtils.NUMERIC.matcher(splitLine[1]).matches()) { + id = OptionalInt.of(Integer.parseInt(splitLine[1])); + uuid = splitLine[0].replace(ChatColors.color("&7ID: "), ""); } } } if (id.isPresent()) { - return PlayerProfile.fromUUID(UUID.fromString(uuid)).getBackpack(id.get()); + PlayerProfile profile = fromUUID(UUID.fromString(uuid)); + return profile.getBackpack(id.getAsInt()); } else { return null; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java index 016e361a9..a2f8758c0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.bukkit.Location; import org.bukkit.entity.EntityType; @@ -55,6 +57,7 @@ public class SlimefunRegistry { private final Set researchingPlayers = new HashSet<>(); private final KeyMap researchIds = new KeyMap<>(); + private boolean automaticallyLoadItems; private boolean enableResearches; private boolean freeCreativeResearches; private boolean researchFireworks; @@ -71,9 +74,9 @@ public class SlimefunRegistry { private final Set chargeableBlocks = new HashSet<>(); private final Map witherProofBlocks = new HashMap<>(); + private final ConcurrentMap profiles = new ConcurrentHashMap<>(); private final Map worlds = new HashMap<>(); private final Map chunks = new HashMap<>(); - private final Map profiles = new HashMap<>(); private final Map layouts = new EnumMap<>(SlimefunGuideLayout.class); private final Map> drops = new EnumMap<>(EntityType.class); private final Map capacities = new HashMap<>(); @@ -99,6 +102,14 @@ public class SlimefunRegistry { researchFireworks = cfg.getBoolean("options.research-unlock-fireworks"); } + public boolean isAutoLoadingEnabled() { + return automaticallyLoadItems; + } + + public void setAutoLoadingMode(boolean mode) { + automaticallyLoadItems = mode; + } + public List getEnabledCategories() { return categories; } @@ -201,7 +212,7 @@ public class SlimefunRegistry { return universalInventories; } - public Map getPlayerProfiles() { + public ConcurrentMap getPlayerProfiles() { return profiles; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/FlexCategory.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/FlexCategory.java index e703441db..696937dfd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/FlexCategory.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/FlexCategory.java @@ -38,7 +38,7 @@ public abstract class FlexCategory extends Category { @Override public final boolean isHidden(Player p) { // We can stop this method right here. - // We provide a custom method for this. See isVisible(...); + // We provide a custom method for this. See isVisible(...) return false; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java index 94656396b..334936907 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java @@ -84,11 +84,12 @@ public final class SlimefunGuide { } public static void openGuide(Player p, SlimefunGuideLayout layout) { - if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled")) return; - if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled-items.SLIMEFUN_GUIDE")) return; - - Optional optional = PlayerProfile.find(p); + if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { + return; + } + Optional optional = PlayerProfile.find(p); + if (optional.isPresent()) { PlayerProfile profile = optional.get(); SlimefunGuideImplementation guide = SlimefunPlugin.getRegistry().getGuideLayout(layout); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java index eb0e42458..4f648d30e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java @@ -20,15 +20,10 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; */ public class CustomTextureService { - private final Plugin plugin; - private Config config; + private final Config config; private boolean modified = false; public CustomTextureService(Plugin plugin) { - this.plugin = plugin; - } - - public void load() { config = new Config(plugin, "item-models.yml"); config.getConfiguration().options().header("This file is used to assign items from Slimefun or any of its addons\n" + "the 'CustomModelData' NBT tag. This can be used in conjunction with a custom resource pack\n" + "to give items custom textures.\n\n" + "There is no official Slimefun resource pack at the moment."); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java index ddde78336..8c0993c5d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java @@ -4,6 +4,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; +import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.RecipeChoice; @@ -33,10 +34,22 @@ public class MinecraftRecipeService { this.plugin = plugin; } - public void load() { + /** + * This method refreshes the {@link RecipeSnapshot} that is used by the {@link MinecraftRecipeService}. + */ + public void refresh() { snapshot = new RecipeSnapshot(plugin); } + /** + * This method returns an {@link Optional} describing the output of a {@link FurnaceRecipe} + * with the given {@link ItemStack} as an input. + * + * @param input + * The input {@link ItemStack} + * + * @return An {@link Optional} describing the furnace output of the given {@link ItemStack} + */ public Optional getFurnaceOutput(ItemStack input) { return snapshot.getRecipeOutput(MinecraftRecipe.FURNACE, input); } @@ -65,8 +78,21 @@ public class MinecraftRecipeService { } } + /** + * This returns an array containing all {@link Recipe Recipes} for crafting the given + * {@link ItemStack}. + * + * @param item + * The {@link ItemStack} for which to get the recipes + * @return An array of {@link Recipe Recipes} to craft the given {@link ItemStack} + */ public Recipe[] getRecipesFor(ItemStack item) { - return snapshot.getRecipesFor(item).toArray(new Recipe[0]); + if (item == null) { + return new Recipe[0]; + } + else { + return snapshot.getRecipesFor(item).toArray(new Recipe[0]); + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java new file mode 100644 index 000000000..d4c2d4bc2 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java @@ -0,0 +1,190 @@ +package io.github.thebusybiscuit.slimefun4.core.services; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.logging.Level; + +import org.bukkit.World; + +import io.github.thebusybiscuit.cscorelib2.collections.OptionalMap; +import io.github.thebusybiscuit.cscorelib2.config.Config; +import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon; +import me.mrCookieSlime.Slimefun.SlimefunPlugin; +import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; + +/** + * This Service is responsible for disabling a {@link SlimefunItem} in a certain {@link World}. + * + * @author TheBusyBiscuit + * + */ +public class PerWorldSettingsService { + + private final SlimefunPlugin plugin; + + private final OptionalMap> disabledItems = new OptionalMap<>(HashMap::new); + private final Map> disabledAddons = new HashMap<>(); + private final Set disabledWorlds = new HashSet<>(); + + public PerWorldSettingsService(SlimefunPlugin plugin) { + this.plugin = plugin; + } + + /** + * This method will forcefully load all currently active Worlds to load up their settings. + */ + public void load(Iterable worlds) { + try { + migrate(); + } + catch (IOException e) { + plugin.getLogger().log(Level.WARNING, "An error occured while migrating old world settings", e); + } + + for (World world : worlds) { + load(world); + } + } + + /** + * This method loads the given {@link World} if it was not loaded before. + * + * @param world + * The {@link World} to load + */ + public void load(World world) { + disabledItems.putIfAbsent(world.getName(), loadWorld(world.getName())); + } + + /** + * Temporary migration method for the old system + * + * @throws IOException + * This will be thrown if we failed to delete the old {@link File} + */ + private void migrate() throws IOException { + Config oldConfig = new Config(plugin, "whitelist.yml"); + + if (oldConfig.getFile().exists()) { + for (String world : oldConfig.getKeys()) { + Config newConfig = new Config(plugin, "world-settings/" + world + ".yml"); + newConfig.setDefaultValue("enabled", oldConfig.getBoolean(world + ".enabled")); + + for (String id : oldConfig.getKeys(world + ".enabled-items")) { + SlimefunItem item = SlimefunItem.getByID(id); + + if (item != null) { + String addon = item.getAddon().getName().toLowerCase(Locale.ROOT); + newConfig.setDefaultValue(addon + ".enabled", true); + newConfig.setDefaultValue(addon + '.' + id, oldConfig.getBoolean(world + ".enabled-items." + id)); + } + } + + newConfig.save(); + } + + Files.delete(oldConfig.getFile().toPath()); + } + } + + /** + * This method checks whether the given {@link SlimefunItem} is enabled in the given {@link World}. + * + * @param world + * The {@link World} to check + * @param item + * The {@link SlimefunItem} that should be checked + * + * @return Whether the given {@link SlimefunItem} is enabled in that {@link World} + */ + public boolean isEnabled(World world, SlimefunItem item) { + Set items = disabledItems.computeIfAbsent(world.getName(), this::loadWorld); + + if (disabledWorlds.contains(world.getName())) { + return false; + } + + return !items.contains(item.getID()); + } + + /** + * This checks whether the given {@link World} is enabled or not. + * + * @param world + * The {@link World} to check + * + * @return Whether this {@link World} is enabled + */ + public boolean isWorldEnabled(World world) { + loadWorld(world.getName()); + return !disabledWorlds.contains(world.getName()); + } + + /** + * This method checks whether the given {@link SlimefunAddon} is enabled in that {@link World}. + * + * @param world + * The {@link World} to check + * @param addon + * The {@link SlimefunAddon} to check + * + * @return Whether this addon is enabled in that {@link World} + */ + public boolean isAddonEnabled(World world, SlimefunAddon addon) { + return isWorldEnabled(world) && disabledAddons.getOrDefault(addon, Collections.emptySet()).contains(world.getName()); + } + + private Set loadWorld(String name) { + Optional> optional = disabledItems.get(name); + + if (optional.isPresent()) { + return optional.get(); + } + else { + Set items = new LinkedHashSet<>(); + Config config = new Config(plugin, "world-settings/" + name + ".yml"); + + config.getConfiguration().options().header("This file is used to disable certain items in a particular world.\nYou can set any item to 'false' to disable it in the world '" + name + "'.\nYou can also disable an entire addon from Slimefun by setting the respective\nvalue of 'enabled' for that Addon.\n\nItems which are disabled in this world will not show up in the Slimefun Guide.\nYou won't be able to use these items either. Using them will result in a warning message."); + config.getConfiguration().options().copyHeader(true); + config.setDefaultValue("enabled", true); + + if (config.getBoolean("enabled")) { + for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) { + if (item != null && item.getID() != null) { + String addon = item.getAddon().getName().toLowerCase(Locale.ROOT); + config.setDefaultValue(addon + ".enabled", true); + config.setDefaultValue(addon + '.' + item.getID(), true); + + boolean isAddonDisabled = config.getBoolean(addon + ".enabled"); + + if (isAddonDisabled) { + Set blacklist = disabledAddons.computeIfAbsent(plugin, key -> new HashSet<>()); + blacklist.add(name); + } + + if (!isAddonDisabled || !config.getBoolean(addon + '.' + item.getID())) { + items.add(item.getID()); + } + } + } + + config.save(); + } + else { + disabledWorlds.add(name); + } + + return items; + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java index 849e4e03e..7edfe86cc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java @@ -21,22 +21,11 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; */ public class PermissionsService { - private final SlimefunPlugin plugin; - private Config config; + private final Config config; public PermissionsService(SlimefunPlugin plugin) { - this.plugin = plugin; - } - - public void load() { - config = new Config(plugin, "permissions.yml"); - - config.getConfiguration().options().header( - "This file is used to assign permission nodes to items from Slimefun or any of its addons.\n" + - "To assign an item a certain permission node you simply have to set the 'permission' attribute\n" + - "to your desired permission node. You can also customize the text that is displayed when a Player does not have that permission." - ); - + this.config = new Config(plugin, "permissions.yml"); + config.getConfiguration().options().header("This file is used to assign permission nodes to items from Slimefun or any of its addons.\nTo assign an item a certain permission node you simply have to set the 'permission' attribute\nto your desired permission node. You can also customize the text that is displayed when a Player does not have that permission."); config.getConfiguration().options().copyHeader(true); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Language.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Language.java index ee988c487..a137e6ea0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Language.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Language.java @@ -1,5 +1,8 @@ package io.github.thebusybiscuit.slimefun4.core.services.localization; +import java.util.Locale; + +import org.apache.commons.lang.Validate; import org.bukkit.Server; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; @@ -39,10 +42,13 @@ public final class Language { * The hash of the skull texture to use */ public Language(String id, String hash) { + Validate.notNull(id, "A Language must have an id that is not null!"); + Validate.notNull(hash, "A Language must have a texture that is not null!"); + this.id = id; item = SkullItem.fromHash(hash); - SlimefunPlugin.getItemTextureService().setTexture(item, "_UI_LANGUAGE_" + id.toUpperCase()); + SlimefunPlugin.getItemTextureService().setTexture(item, "_UI_LANGUAGE_" + id.toUpperCase(Locale.ROOT)); } /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java index fa1fe0962..7be5ee231 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java @@ -12,6 +12,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; +import io.github.thebusybiscuit.cscorelib2.chat.ChatInput; import io.github.thebusybiscuit.cscorelib2.chat.json.ChatComponent; import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent; import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface; @@ -25,6 +26,7 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; +import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.LockedCategory; @@ -34,6 +36,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; public class BookSlimefunGuide implements SlimefunGuideImplementation { + private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance, "search"); + @Override public SlimefunGuideLayout getLayout() { return SlimefunGuideLayout.BOOK; @@ -50,6 +54,12 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation { for (int i = 0; i < lines.size(); i = i + 10) { ChatComponent page = new ChatComponent(ChatColors.color("&b&l- " + SlimefunPlugin.getLocal().getMessage(p, "guide.title.main") + " -\n\n")); + page.setHoverEvent(new HoverEvent(ChestMenuUtils.getSearchButton(p))); + + page.setClickEvent(new ClickEvent(guideSearch, player -> PlayerProfile.get(player, profile -> Slimefun.runSync(() -> { + SlimefunPlugin.getLocal().sendMessage(player, "guide.search.message"); + ChatInput.waitForPlayer(SlimefunPlugin.instance, player, msg -> SlimefunGuide.openSearch(profile, msg, true, true)); + }, 1)))); for (int j = i; j < lines.size() && j < i + 10; j++) { page.append(lines.get(j)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/ElevatorPlate.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/ElevatorPlate.java index ee9840d7e..c7bf5fb7e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/ElevatorPlate.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/ElevatorPlate.java @@ -31,6 +31,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockUseHandler; import me.mrCookieSlime.Slimefun.api.BlockStorage; +import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class ElevatorPlate extends SimpleSlimefunItem { @@ -117,12 +118,12 @@ public class ElevatorPlate extends SimpleSlimefunItem { if (block.getY() == b.getY()) { line = new ChatComponent("\n" + ChatColor.GRAY + "> " + (floors.size() - i) + ". " + ChatColor.RESET + floor); - line.setHoverEvent(new HoverEvent(ChatColor.RESET + floor, "", ChatColors.color(SlimefunPlugin.getLocal().getMessage(p, "machines.ELEVATOR.current-floor")), ChatColor.RESET + floor, "")); + line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocal().getMessage(p, "machines.ELEVATOR.current-floor")), "", ChatColor.RESET + floor, "")); } else { line = new ChatComponent("\n" + ChatColor.GRAY.toString() + (floors.size() - i) + ". " + ChatColor.RESET + floor); - line.setHoverEvent(new HoverEvent(ChatColor.RESET + floor, "", ChatColors.color(SlimefunPlugin.getLocal().getMessage(p, "machines.ELEVATOR.click-to-teleport")), ChatColor.RESET + floor, "")); - line.setClickEvent(new ClickEvent(elevatorKey, player -> { + line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocal().getMessage(p, "machines.ELEVATOR.click-to-teleport")), "", ChatColor.RESET + floor, "")); + line.setClickEvent(new ClickEvent(elevatorKey, player -> Slimefun.runSync(() -> { users.add(player.getUniqueId()); float yaw = player.getEyeLocation().getYaw() + 180; @@ -133,7 +134,7 @@ public class ElevatorPlate extends SimpleSlimefunItem { player.teleport(new Location(player.getWorld(), block.getX() + 0.5, block.getY() + 0.4, block.getZ() + 0.5, yaw, player.getEyeLocation().getPitch())); player.sendTitle(ChatColor.RESET + ChatColors.color(floor), " ", 20, 60, 20); - })); + }))); } page.append(line); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java index 4235ea6ac..a44305769 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java @@ -57,7 +57,7 @@ public class AncientAltarListener implements Listener { private final List altars = new ArrayList<>(); private final Set removedItems = new HashSet<>(); - public void load(SlimefunPlugin plugin) { + public void register(SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java index 1acc3d121..2d6f5d98b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -19,6 +18,7 @@ import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.slimefun4.api.player.PlayerBackpack; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.implementation.items.food.Cooler; @@ -47,7 +47,7 @@ public class BackpackListener implements Listener { private Map backpacks = new HashMap<>(); - public void load(SlimefunPlugin plugin) { + public void register(SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } @@ -117,7 +117,7 @@ public class BackpackListener implements Listener { public void openBackpack(Player p, ItemStack item, SlimefunBackpack backpack) { if (item.getAmount() == 1) { - if (Slimefun.hasUnlocked(p, backpack, true) && !PlayerProfile.get(p, profile -> openBackpack(item, profile, backpack.getSize()))) { + if (Slimefun.hasUnlocked(p, backpack, true) && !PlayerProfile.get(p, profile -> openBackpack(p, item, profile, backpack.getSize()))) { SlimefunPlugin.getLocal().sendMessage(p, "messages.opening-backpack"); } } @@ -126,11 +126,10 @@ public class BackpackListener implements Listener { } } - private void openBackpack(ItemStack item, PlayerProfile profile, int size) { - Player p = profile.getPlayer(); - - for (int line = 0; line < item.getItemMeta().getLore().size(); line++) { - if (item.getItemMeta().getLore().get(line).equals(ChatColor.translateAlternateColorCodes('&', "&7ID: "))) { + private void openBackpack(Player p, ItemStack item, PlayerProfile profile, int size) { + List lore = item.getItemMeta().getLore(); + for (int line = 0; line < lore.size(); line++) { + if (lore.get(line).equals(ChatColors.color("&7ID: "))) { setBackpackId(p, item, line, profile.createBackpack(size).getID()); break; } @@ -140,7 +139,13 @@ public class BackpackListener implements Listener { p.playSound(p.getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F); backpacks.put(p.getUniqueId(), item); - Slimefun.runSync(() -> PlayerProfile.getBackpack(item).open(p)); + Slimefun.runSync(() -> { + PlayerBackpack backpack = PlayerProfile.getBackpack(item); + + if (backpack != null) { + backpack.open(p); + } + }); } else { SlimefunPlugin.getLocal().sendMessage(p, "backpack.already-open", true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockPhysicsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockPhysicsListener.java index e8d71e604..1ac1faeab 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockPhysicsListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockPhysicsListener.java @@ -52,7 +52,7 @@ public class BlockPhysicsListener implements Listener { @EventHandler public void onPistonExtend(BlockPistonExtendEvent e) { for (Block b : e.getBlocks()) { - if (BlockStorage.hasBlockInfo(b) || b.getRelative(e.getDirection()).getType() == Material.AIR && BlockStorage.hasBlockInfo(b.getRelative(e.getDirection()))) { + if (BlockStorage.hasBlockInfo(b) || (b.getRelative(e.getDirection()).getType() == Material.AIR && BlockStorage.hasBlockInfo(b.getRelative(e.getDirection())))) { e.setCancelled(true); return; } @@ -63,7 +63,7 @@ public class BlockPhysicsListener implements Listener { public void onPistonRetract(BlockPistonRetractEvent e) { if (e.isSticky()) { for (Block b : e.getBlocks()) { - if (BlockStorage.hasBlockInfo(b) || b.getRelative(e.getDirection()).getType() == Material.AIR && BlockStorage.hasBlockInfo(b.getRelative(e.getDirection()))) { + if (BlockStorage.hasBlockInfo(b) || (b.getRelative(e.getDirection()).getType() == Material.AIR && BlockStorage.hasBlockInfo(b.getRelative(e.getDirection())))) { e.setCancelled(true); return; } @@ -71,13 +71,16 @@ public class BlockPhysicsListener implements Listener { } } - @EventHandler + @EventHandler(ignoreCancelled = true) public void onLiquidFlow(BlockFromToEvent e) { Block block = e.getToBlock(); - String item = BlockStorage.checkID(block); - if (item != null) { - e.setCancelled(true); + if (block.getType() == Material.PLAYER_HEAD || block.getType() == Material.PLAYER_WALL_HEAD) { + String item = BlockStorage.checkID(block); + + if (item != null) { + e.setCancelled(true); + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index 9334186b2..830ab4308 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -16,9 +16,11 @@ import org.bukkit.inventory.EquipmentSlot; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet; +import io.github.thebusybiscuit.slimefun4.implementation.tasks.TickerTask; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Lists.SlimefunItems; +import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock; @@ -69,9 +71,12 @@ public class DebugFishListener implements Listener { } private void sendInfo(Player p, Block b) { + SlimefunItem item = BlockStorage.check(b); + p.sendMessage(" "); p.sendMessage(ChatColors.color("&d" + b.getType() + " &e@ X: " + b.getX() + " Y: " + b.getY() + " Z: " + b.getZ())); - p.sendMessage(ChatColors.color("&dID: " + "&e" + BlockStorage.checkID(b))); + p.sendMessage(ChatColors.color("&dId: " + "&e" + item.getID())); + p.sendMessage(ChatColors.color("&Plugin: " + "&e" + item.getAddon().getName())); if (b.getState() instanceof Skull) { p.sendMessage(ChatColors.color("&dSkull: " + enabledTooltip)); @@ -92,17 +97,19 @@ public class DebugFishListener implements Listener { p.sendMessage(ChatColors.color("&dInventory: " + disabledTooltip)); } - if (BlockStorage.check(b).isTicking()) { + TickerTask ticker = SlimefunPlugin.getTicker(); + + if (item.isTicking()) { p.sendMessage(ChatColors.color("&dTicker: " + enabledTooltip)); p.sendMessage(ChatColors.color(" &dAsync: &e" + (BlockStorage.check(b).getBlockTicker().isSynchronized() ? disabledTooltip : enabledTooltip))); - p.sendMessage(ChatColors.color(" &dTimings: &e" + SlimefunPlugin.getTicker().getTimings(b) + "ns")); - p.sendMessage(ChatColors.color(" &dTotal Timings: &e" + SlimefunPlugin.getTicker().getTimings(BlockStorage.checkID(b)) + "ns")); - p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + SlimefunPlugin.getTicker().getTimings(b.getChunk()) + "ns")); + p.sendMessage(ChatColors.color(" &dTimings: &e" + ticker.toMillis(ticker.getTimings(b), true) + "ms")); + p.sendMessage(ChatColors.color(" &dTotal Timings: &e" + ticker.toMillis(ticker.getTimings(BlockStorage.checkID(b)), true) + "ms")); + p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + ticker.toMillis(ticker.getTimings(b.getChunk()), true) + "ms")); } - else if (BlockStorage.check(b).getEnergyTicker() != null) { + else if (item.getEnergyTicker() != null) { p.sendMessage(ChatColors.color("&dTicking: " + "&3Indirect")); - p.sendMessage(ChatColors.color(" &dTimings: &e" + SlimefunPlugin.getTicker().getTimings(b) + "ns")); - p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + SlimefunPlugin.getTicker().getTimings(b.getChunk()) + "ns")); + p.sendMessage(ChatColors.color(" &dTimings: &e" + ticker.toMillis(ticker.getTimings(b), true) + "ms")); + p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + ticker.toMillis(ticker.getTimings(b.getChunk()), true) + "ms")); } else { p.sendMessage(ChatColors.color("&dTicker: " + disabledTooltip)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java index 97a205e7d..852d6110a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GrapplingHookListener.java @@ -30,7 +30,7 @@ public class GrapplingHookListener implements Listener { private final Set invulnerable = new HashSet<>(); private final Map temporaryEntities = new HashMap<>(); - public void load(SlimefunPlugin plugin) { + public void register(SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/PlayerProfileListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/PlayerProfileListener.java index cb133da51..c7aa87e36 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/PlayerProfileListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/PlayerProfileListener.java @@ -1,12 +1,25 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; +import java.util.Optional; + +import org.bukkit.Server; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerQuitEvent; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import me.mrCookieSlime.Slimefun.SlimefunPlugin; +/** + * This {@link Listener} removes a {@link PlayerProfile} from memory if the corresponding {@link Player} + * has left the {@link Server} or was kicked. + * + * @author TheBusyBiscuit + * @author SoSeDiK + * + */ public class PlayerProfileListener implements Listener { public PlayerProfileListener(SlimefunPlugin plugin) { @@ -15,8 +28,21 @@ public class PlayerProfileListener implements Listener { @EventHandler public void onDisconnect(PlayerQuitEvent e) { - if (PlayerProfile.isLoaded(e.getPlayer().getUniqueId())) { - PlayerProfile.get(e.getPlayer()).markForDeletion(); + Optional profile = PlayerProfile.find(e.getPlayer()); + + // if we still have a profile of this Player in memory, delete it + if (profile.isPresent()) { + profile.get().markForDeletion(); + } + } + + @EventHandler(ignoreCancelled = true) + public void onKick(PlayerKickEvent e) { + Optional profile = PlayerProfile.find(e.getPlayer()); + + // if we still have a profile of this Player in memory, delete it + if (profile.isPresent()) { + profile.get().markForDeletion(); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBowListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBowListener.java index 416c49d3e..0c34199c2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBowListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBowListener.java @@ -23,7 +23,7 @@ public class SlimefunBowListener implements Listener { private final Map bows = new HashMap<>(); - public void load(SlimefunPlugin plugin) { + public void register(SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java index ed08bd3e7..fc7e84c59 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunGuideListener.java @@ -27,8 +27,10 @@ public class SlimefunGuideListener implements Listener { public void onJoin(PlayerJoinEvent e) { if (giveOnFirstJoin && !e.getPlayer().hasPlayedBefore()) { Player p = e.getPlayer(); - if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled")) return; - if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled-items.SLIMEFUN_GUIDE")) return; + + if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { + return; + } SlimefunGuideLayout type = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST; p.getInventory().addItem(SlimefunGuide.getItem(type)); @@ -42,6 +44,10 @@ public class SlimefunGuideListener implements Listener { if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.BOOK), true)) { e.cancel(); + + if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { + return; + } if (p.isSneaking()) { SlimefunGuideSettings.openSettings(p, item); @@ -52,6 +58,10 @@ public class SlimefunGuideListener implements Listener { } else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEST), true)) { e.cancel(); + + if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { + return; + } if (p.isSneaking()) { SlimefunGuideSettings.openSettings(p, item); @@ -62,6 +72,10 @@ public class SlimefunGuideListener implements Listener { } else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEAT_SHEET), true)) { e.cancel(); + + if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) { + return; + } if (p.isSneaking()) { SlimefunGuideSettings.openSettings(p, item); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/WorldListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/WorldListener.java index 8fdc770a3..2ebb33834 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/WorldListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/WorldListener.java @@ -19,11 +19,8 @@ public class WorldListener implements Listener { @EventHandler public void onWorldLoad(WorldLoadEvent e) { + SlimefunPlugin.getWorldSettingsService().load(e.getWorld()); BlockStorage.getForcedStorage(e.getWorld()); - - SlimefunPlugin.getWhitelist().setDefaultValue(e.getWorld().getName() + ".enabled", true); - SlimefunPlugin.getWhitelist().setDefaultValue(e.getWorld().getName() + ".enabled-items.SLIMEFUN_GUIDE", true); - SlimefunPlugin.getWhitelist().save(); } @EventHandler diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/PostSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/PostSetup.java index 262f001c9..e3d5ddb60 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/PostSetup.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/PostSetup.java @@ -13,7 +13,6 @@ import java.util.stream.Stream; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.inventory.ItemStack; @@ -62,12 +61,6 @@ public final class PostSetup { } } - public static void setupItemSettings() { - for (World world : Bukkit.getWorlds()) { - SlimefunPlugin.getWhitelist().setDefaultValue(world.getName() + ".enabled-items.SLIMEFUN_GUIDE", true); - } - } - public static void loadItems() { Iterator iterator = SlimefunPlugin.getRegistry().getEnabledSlimefunItems().iterator(); @@ -117,7 +110,8 @@ public final class PostSetup { SlimefunPlugin.getItemCfg().save(); SlimefunPlugin.getResearchCfg().save(); - SlimefunPlugin.getWhitelist().save(); + + SlimefunPlugin.getRegistry().setAutoLoadingMode(true); } private static void loadAutomaticCraftingChamber() { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/SlimefunStartupTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/SlimefunStartupTask.java index b83690daa..925997235 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/SlimefunStartupTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/SlimefunStartupTask.java @@ -48,6 +48,7 @@ public class SlimefunStartupTask implements Runnable { PostSetup.loadItems(); // Load all worlds + SlimefunPlugin.getWorldSettingsService().load(Bukkit.getWorlds()); for (World world : Bukkit.getWorlds()) { new BlockStorage(world); } @@ -55,11 +56,11 @@ public class SlimefunStartupTask implements Runnable { // Load all listeners that depend on items to be enabled if (isEnabled("ANCIENT_ALTAR")) { - SlimefunPlugin.getAncientAltarListener().load(plugin); + SlimefunPlugin.getAncientAltarListener().register(plugin); } if (isEnabled("GRAPPLING_HOOK")) { - SlimefunPlugin.getGrapplingHookListener().load(plugin); + SlimefunPlugin.getGrapplingHookListener().register(plugin); } if (isEnabled("BLADE_OF_VAMPIRES")) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 73c4dc266..2a8eaeb2d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -36,7 +36,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; public class TickerTask implements Runnable { - private final DecimalFormat decimalFormat = new DecimalFormat("#.###"); + private final DecimalFormat decimalFormat = new DecimalFormat("#.##"); private final ConcurrentMap move = new ConcurrentHashMap<>(); private final ConcurrentMap delete = new ConcurrentHashMap<>(); private final ConcurrentMap blockTimings = new ConcurrentHashMap<>(); @@ -198,14 +198,14 @@ public class TickerTask implements Runnable { } public String getTime() { - return toMillis(time); + return toMillis(time, false); } public void info(CommandSender sender) { sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2== &aSlimefun Diagnostic Tool &2==")); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Halted: &e&l" + String.valueOf(halted).toUpperCase())); sender.sendMessage(""); - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Impact: &e" + toMillis(time))); + sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Impact: &e" + toMillis(time, true))); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Chunks: &e" + chunks)); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Machines: &e" + machines)); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Skipped Machines: &e" + skipped)); @@ -222,8 +222,8 @@ public class TickerTask implements Runnable { for (Map.Entry entry : timings) { int count = machineCount.get(entry.getKey()); - if (entry.getValue() > 500_000) { - builder.append("\n&c").append(entry.getKey()).append(" - ").append(count).append("x &7(").append(toMillis(entry.getValue())).append(", ").append(toMillis(entry.getValue() / count)).append(" avg/machine)"); + if (entry.getValue() > 300_000) { + builder.append("\n&c").append(entry.getKey()).append(" - ").append(count).append("x &7(").append(toMillis(entry.getValue(), true)).append(", ").append(toMillis(entry.getValue() / count, true)).append(" avg/machine)"); } else hidden++; } @@ -239,7 +239,7 @@ public class TickerTask implements Runnable { for (Map.Entry entry : timings) { int count = machineCount.get(entry.getKey()); if (entry.getValue() > 500_000) { - sender.sendMessage(" " + entry.getKey() + " - " + count + "x (" + toMillis(entry.getValue()) + ", " + toMillis(entry.getValue() / count) + " avg/machine)"); + sender.sendMessage(" " + entry.getKey() + " - " + count + "x (" + toMillis(entry.getValue(), false) + ", " + toMillis(entry.getValue() / count, false) + " avg/machine)"); } else hidden++; } @@ -260,7 +260,7 @@ public class TickerTask implements Runnable { for (Map.Entry entry : timings) { if (!chunksSkipped.contains(entry.getKey())) { if (entry.getValue() > 0) { - builder.append("\n&c").append(formatChunk(entry.getKey())).append(" - ").append(chunkItemCount.getOrDefault(entry.getKey(), 0)).append("x &7(").append(toMillis(entry.getValue())).append(')'); + builder.append("\n&c").append(formatChunk(entry.getKey())).append(" - ").append(chunkItemCount.getOrDefault(entry.getKey(), 0)).append("x &7(").append(toMillis(entry.getValue(), true)).append(')'); } else hidden++; } @@ -277,7 +277,7 @@ public class TickerTask implements Runnable { for (Map.Entry entry : timings) { if (!chunksSkipped.contains(entry.getKey())) { if (entry.getValue() > 0) { - sender.sendMessage(" " + formatChunk(entry.getKey()) + " - " + (chunkItemCount.getOrDefault(entry.getKey(), 0)) + "x (" + toMillis(entry.getValue()) + ")"); + sender.sendMessage(" " + formatChunk(entry.getKey()) + " - " + (chunkItemCount.getOrDefault(entry.getKey(), 0)) + "x (" + toMillis(entry.getValue(), false) + ")"); } else hidden++; } @@ -316,8 +316,16 @@ public class TickerTask implements Runnable { halted = true; } - private String toMillis(long time) { - return decimalFormat.format(time / 1000000F) + "ms"; + public String toMillis(long nanoseconds, boolean colors) { + String number = decimalFormat.format(time / 1000000F); + + if (!colors) { + return number; + } + else { + String[] parts = number.split(",|\\."); + return parts[0] + "," + ChatColor.GRAY + parts[1] + "ms"; + } } @Override diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java index 403da6a15..c0043118f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java @@ -7,6 +7,8 @@ import java.util.Date; import java.util.Locale; import java.util.logging.Level; +import org.bukkit.ChatColor; + import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.api.Slimefun; @@ -30,6 +32,15 @@ public final class NumberUtils { } } + public static ChatColor getColorFromPercentage(float percentage) { + if (percentage < 16.0F) return ChatColor.DARK_RED; + else if (percentage < 32.0F) return ChatColor.RED; + else if (percentage < 48.0F) return ChatColor.GOLD; + else if (percentage < 64.0F) return ChatColor.YELLOW; + else if (percentage < 80.0F) return ChatColor.DARK_GREEN; + else return ChatColor.GREEN; + } + public static String timeDelta(Date date) { long timestamp = date.getTime(); int hours = (int) ((System.currentTimeMillis() - timestamp) / (1000 * 60 * 60)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/PatternUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/PatternUtils.java index 54e1d1df9..0ca3b83aa 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/PatternUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/PatternUtils.java @@ -22,5 +22,6 @@ public final class PatternUtils { public static final Pattern DASH = Pattern.compile("-"); public static final Pattern ASCII = Pattern.compile("[A-Za-z \"_]+"); public static final Pattern ALPHANUMERIC = Pattern.compile("[A-Fa-f0-9]+"); - + public static final Pattern NUMERIC = Pattern.compile("[0-9]+"); + } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java index b0f518667..95507d34b 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java @@ -89,13 +89,7 @@ public class Category implements Keyed { * By default, a category is automatically registered when a {@link SlimefunItem} is bound to it. */ public void register() { - if (this instanceof SeasonalCategory) { - if (((SeasonalCategory) this).isVisible()) { - SlimefunPlugin.getRegistry().getEnabledCategories().add(this); - Collections.sort(SlimefunPlugin.getRegistry().getEnabledCategories(), Comparator.comparingInt(Category::getTier)); - } - } - else { + if (!(this instanceof SeasonalCategory) || ((SeasonalCategory) this).isVisible()) { SlimefunPlugin.getRegistry().getEnabledCategories().add(this); Collections.sort(SlimefunPlugin.getRegistry().getEnabledCategories(), Comparator.comparingInt(Category::getTier)); } @@ -181,7 +175,7 @@ public class Category implements Keyed { */ public boolean isHidden(Player p) { for (SlimefunItem slimefunItem : getItems()) { - if (Slimefun.isEnabled(p, slimefunItem, false)) { + if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) { return false; } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/LockedCategory.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/LockedCategory.java index 9f5c20737..288df3fee 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/LockedCategory.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/LockedCategory.java @@ -88,7 +88,7 @@ public class LockedCategory extends Category { throw new IllegalArgumentException("Category '" + item.getItemMeta().getDisplayName() + "' cannot be a parent of itself or have a 'null' parent."); } - this.parents.add(category); + parents.add(category); } /** @@ -101,7 +101,7 @@ public class LockedCategory extends Category { * @see #addParent(Category) */ public void removeParent(Category category) { - this.parents.remove(category); + parents.remove(category); } /** diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java index 1c060055f..edff16718 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java @@ -10,8 +10,6 @@ import java.util.function.Consumer; import java.util.logging.Level; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -336,15 +334,11 @@ public class SlimefunItem implements Placeable { SlimefunPlugin.getItemCfg().setDefaultValue(id + ".allow-enchanting", enchantable); SlimefunPlugin.getItemCfg().setDefaultValue(id + ".allow-disenchanting", disenchantable); + // Load all item settings for (ItemSetting setting : itemSettings) { setting.load(this); } - for (World world : Bukkit.getWorlds()) { - SlimefunPlugin.getWhitelist().setDefaultValue(world.getName() + ".enabled", true); - SlimefunPlugin.getWhitelist().setDefaultValue(world.getName() + ".enabled-items." + id, true); - } - if (ticking && !SlimefunPlugin.getCfg().getBoolean("URID.enable-tickers")) { state = ItemState.DISABLED; return; @@ -387,6 +381,11 @@ public class SlimefunItem implements Placeable { } postRegister(); + + if (SlimefunPlugin.getRegistry().isAutoLoadingEnabled()) { + info("Item was registered during runtime."); + load(); + } } catch (Exception x) { error("Registering " + toString() + " has failed", x); @@ -690,11 +689,13 @@ public class SlimefunItem implements Placeable { } public void info(String message) { - addon.getLogger().log(Level.INFO, message); + String msg = toString() + ": " + message; + addon.getLogger().log(Level.INFO, msg); } public void warn(String message) { - addon.getLogger().log(Level.WARNING, message); + String msg = toString() + ": " + message; + addon.getLogger().log(Level.WARNING, msg); } /** @@ -721,6 +722,22 @@ public class SlimefunItem implements Placeable { return SlimefunPlugin.getRegistry().getSlimefunItemIds().get(id); } + /** + * This gets an ItemStack from the SlimefunItem with that id. + * + * @deprecated Please use {@link #getByID(String)} to obtain the {@link SlimefunItem} and then get the ItemStack + * from that. + * + * @param id + * the item id + * @return The item + */ + @Deprecated + public static ItemStack getItem(String id) { + SlimefunItem sfi = getByID(id); + return sfi == null ? null : sfi.getItem(); + } + public static SlimefunItem getByItem(ItemStack item) { if (item == null) return null; @@ -759,11 +776,6 @@ public class SlimefunItem implements Placeable { return null; } - public static ItemStack getItem(String id) { - SlimefunItem item = getByID(id); - return item != null ? item.getItem() : null; - } - public static Set getPublicItemHandlers(Class identifier) { return SlimefunPlugin.getRegistry().getPublicItemHandlers().computeIfAbsent(identifier, c -> new HashSet<>()); } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/SlimefunPlugin.java b/src/main/java/me/mrCookieSlime/Slimefun/SlimefunPlugin.java index 23b3d217f..635802cc8 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/SlimefunPlugin.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/SlimefunPlugin.java @@ -34,6 +34,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.CustomItemDataService; import io.github.thebusybiscuit.slimefun4.core.services.CustomTextureService; import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService; import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService; +import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService; import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService; import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService; import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService; @@ -108,6 +109,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private final AutoSavingService autoSavingService = new AutoSavingService(); private final BackupService backupService = new BackupService(); private final PermissionsService permissionsService = new PermissionsService(this); + private final PerWorldSettingsService worldSettingsService = new PerWorldSettingsService(this); private final ThirdPartyPluginService thirdPartySupportService = new ThirdPartyPluginService(this); private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this); private LocalizationService local; @@ -117,10 +119,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private ProtectionManager protections; // Important config files for Slimefun - private Config researches; - private Config items; - private Config whitelist; - private Config config; + private final Config config = new Config(this); + private final Config items = new Config(this, "Items.yml"); + private final Config researches = new Config(this, "Researches.yml"); // Listeners that need to be accessed elsewhere private final AncientAltarListener ancientAltarListener = new AncientAltarListener(); @@ -142,22 +143,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { instance = this; // Creating all necessary Folders - getLogger().log(Level.INFO, "Loading files..."); + getLogger().log(Level.INFO, "Loading various systems..."); createDirectories(); - - // Setup config.yml - getLogger().log(Level.INFO, "Loading config..."); - config = new Config(this); registry.load(config); - // Loading all extra configs - researches = new Config(this, "Researches.yml"); - items = new Config(this, "Items.yml"); - whitelist = new Config(this, "whitelist.yml"); - - // Setup various other config files - textureService.load(); - permissionsService.load(); + // Set up localization local = new LocalizationService(this, config.getString("options.language")); // Setting up Networks @@ -209,7 +199,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { new WitherListener(this); new IronGolemListener(this); - bowListener.load(this); + bowListener.register(this); // Toggleable Listeners for performance reasons if (config.getBoolean("items.talismans")) { @@ -221,7 +211,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { } if (config.getBoolean("items.backpacks")) { - backpackListener.load(this); + backpackListener.register(this); } // Handle Slimefun Guide being given on Join @@ -238,7 +228,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { protections = new ProtectionManager(getServer()); textureService.register(registry.getAllSlimefunItems()); permissionsService.register(registry.getAllSlimefunItems()); - recipeService.load(); + recipeService.refresh(); }), 0); // Setting up the command /sf and all subcommands @@ -254,9 +244,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { thirdPartySupportService.start(); gitHubService.start(this); - // Exclude the command /sf elevator from our server log, it could get quite spammy - CSCoreLib.getLib().filterLog("([A-Za-z0-9_]{3,16}) issued server command: /sf elevator (.{0,})"); - // Hooray! getLogger().log(Level.INFO, "Slimefun has finished loading in {0}", getStartupTime(timestamp)); } @@ -333,6 +320,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { return; } + // Cancel all tasks from this plugin immediately Bukkit.getScheduler().cancelTasks(this); if (ticker != null) { @@ -367,9 +355,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { menu.save(); } + // Create a new backup zip backupService.run(); // Prevent Memory Leaks + // These static Maps should be removed at some point... AContainer.processing = null; AContainer.progress = null; @@ -381,6 +371,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { instance = null; + // Close all inventories on the server to prevent item dupes + // (Incase some idiot uses /reload) for (Player p : Bukkit.getOnlinePlayers()) { p.closeInventory(); } @@ -388,22 +380,21 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private void createDirectories() { String[] storageFolders = { "Players", "blocks", "stored-blocks", "stored-inventories", "stored-chunks", "universal-inventories", "waypoints", "block-backups" }; - String[] pluginFolders = { "scripts", "generators", "error-reports", "cache/github" }; + String[] pluginFolders = { "scripts", "generators", "error-reports", "cache/github", "world-settings" }; for (String folder : storageFolders) { - File file = new File("data-storage/Slimefun/" + folder); + File file = new File("data-storage/Slimefun", folder); if (!file.exists()) file.mkdirs(); } for (String folder : pluginFolders) { - File file = new File("plugins/Slimefun/" + folder); + File file = new File("plugins/Slimefun", folder); if (!file.exists()) file.mkdirs(); } } private void loadItems() { try { - PostSetup.setupItemSettings(); SlimefunItemSetup.setup(this); } catch (Throwable x) { @@ -432,10 +423,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { return instance.items; } - public static Config getWhitelist() { - return instance.whitelist; - } - public static GPSNetwork getGPSNetwork() { return instance.gpsNetwork; } @@ -490,6 +477,10 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { return instance.thirdPartySupportService; } + public static PerWorldSettingsService getWorldSettingsService() { + return instance.worldSettingsService; + } + /** * This method returns the {@link UpdaterService} of Slimefun. * It is used to handle automatic updates. @@ -563,7 +554,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { public static MinecraftVersion getMinecraftVersion() { return instance.minecraftVersion; } - + public static String getCSCoreLibVersion() { return CSCoreLib.getLib().getDescription().getVersion(); } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java index 15a832af1..4b41c9e4e 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java @@ -43,10 +43,10 @@ public class BlockStorage { private static final String PATH_BLOCKS = "data-storage/Slimefun/stored-blocks/"; private static final String PATH_CHUNKS = "data-storage/Slimefun/stored-chunks/"; - private World world; - private Map storage = new ConcurrentHashMap<>(); - private Map inventories = new ConcurrentHashMap<>(); - private Map blocksCache = new ConcurrentHashMap<>(); + private final World world; + private final Map storage = new ConcurrentHashMap<>(); + private final Map inventories = new ConcurrentHashMap<>(); + private final Map blocksCache = new ConcurrentHashMap<>(); public static BlockStorage getStorage(World world) { return SlimefunPlugin.getRegistry().getWorlds().get(world.getName()); @@ -83,9 +83,13 @@ public class BlockStorage { } public BlockStorage(World w) { - if (SlimefunPlugin.getRegistry().getWorlds().containsKey(w.getName())) return; this.world = w; + if (SlimefunPlugin.getRegistry().getWorlds().containsKey(w.getName())) { + // Cancel the loading process if the world was already loaded + return; + } + Slimefun.getLogger().log(Level.INFO, "Loading Blocks for World \"" + w.getName() + "\""); Slimefun.getLogger().log(Level.INFO, "This may take a long time..."); diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java b/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java index 862e5e025..30a998e41 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java @@ -247,27 +247,14 @@ public final class Slimefun { return false; } + else if (!SlimefunPlugin.getWorldSettingsService().isEnabled(p.getWorld(), sfItem)) { + if (message) { + SlimefunPlugin.getLocal().sendMessage(p, "messages.disabled-in-world", true); + } - String world = p.getWorld().getName(); - if (SlimefunPlugin.getWhitelist().contains(world + ".enabled")) { - if (SlimefunPlugin.getWhitelist().getBoolean(world + ".enabled")) { - if (!SlimefunPlugin.getWhitelist().contains(world + ".enabled-items." + sfItem.getID())) { - SlimefunPlugin.getWhitelist().setDefaultValue(world + ".enabled-items." + sfItem.getID(), true); - } - if (SlimefunPlugin.getWhitelist().getBoolean(world + ".enabled-items." + sfItem.getID())) { - return true; - } - else { - if (message) SlimefunPlugin.getLocal().sendMessage(p, "messages.disabled-in-world", true); - return false; - } - } - else { - if (message) SlimefunPlugin.getLocal().sendMessage(p, "messages.disabled-in-world", true); - return false; - } + return false; } - else return true; + return true; } public static BukkitTask runSync(Runnable r) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/SlimefunItemStack.java b/src/main/java/me/mrCookieSlime/Slimefun/api/SlimefunItemStack.java index 0123ef589..41914756c 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/SlimefunItemStack.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/SlimefunItemStack.java @@ -189,17 +189,15 @@ public class SlimefunItemStack extends CustomItem { } private static String getTexture(String id, String texture) { - String base64 = texture; - - // At this point we can be sure it's not a base64 encoded texture - if (!texture.startsWith("ey")) { - base64 = Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + texture + "\"}}}").getBytes()); + if (texture.startsWith("ey")) { + return texture; } - else if (!PatternUtils.ALPHANUMERIC.matcher(texture).matches()) { + else if (PatternUtils.ALPHANUMERIC.matcher(texture).matches()) { + return Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + texture + "\"}}}").getBytes()); + } + else { throw new IllegalArgumentException("The provided texture for Item \"" + id + "\" does not seem to be a valid texture String!"); } - - return base64; } }