1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

[CI skip] A bunch of improvements [javadocs]

This commit is contained in:
TheBusyBiscuit 2020-04-09 02:21:30 +02:00
parent d03cb64c02
commit 0e6af8e0a1
33 changed files with 497 additions and 208 deletions

View File

@ -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)

View File

@ -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<Research> 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<PlayerProfile> 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<PlayerProfile> 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<Integer> 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;

View File

@ -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<UUID> researchingPlayers = new HashSet<>();
private final KeyMap<Research> 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<String> chargeableBlocks = new HashSet<>();
private final Map<String, WitherProof> witherProofBlocks = new HashMap<>();
private final ConcurrentMap<UUID, PlayerProfile> profiles = new ConcurrentHashMap<>();
private final Map<String, BlockStorage> worlds = new HashMap<>();
private final Map<String, BlockInfoConfig> chunks = new HashMap<>();
private final Map<UUID, PlayerProfile> profiles = new HashMap<>();
private final Map<SlimefunGuideLayout, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideLayout.class);
private final Map<EntityType, Set<ItemStack>> drops = new EnumMap<>(EntityType.class);
private final Map<String, Integer> 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<Category> getEnabledCategories() {
return categories;
}
@ -201,7 +212,7 @@ public class SlimefunRegistry {
return universalInventories;
}
public Map<UUID, PlayerProfile> getPlayerProfiles() {
public ConcurrentMap<UUID, PlayerProfile> getPlayerProfiles() {
return profiles;
}

View File

@ -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;
}

View File

@ -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<PlayerProfile> optional = PlayerProfile.find(p);
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
Optional<PlayerProfile> optional = PlayerProfile.find(p);
if (optional.isPresent()) {
PlayerProfile profile = optional.get();
SlimefunGuideImplementation guide = SlimefunPlugin.getRegistry().getGuideLayout(layout);

View File

@ -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.");

View File

@ -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<ItemStack> 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]);
}
}
}

View File

@ -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<String, Set<String>> disabledItems = new OptionalMap<>(HashMap::new);
private final Map<SlimefunAddon, Set<String>> disabledAddons = new HashMap<>();
private final Set<String> 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<World> 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<String> 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<String> loadWorld(String name) {
Optional<Set<String>> optional = disabledItems.get(name);
if (optional.isPresent()) {
return optional.get();
}
else {
Set<String> 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<String> 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;
}
}
}

View File

@ -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);
}

View File

@ -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));
}
/**

View File

@ -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));

View File

@ -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<BlockUseHandler> {
@ -117,12 +118,12 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
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<BlockUseHandler> {
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);

View File

@ -57,7 +57,7 @@ public class AncientAltarListener implements Listener {
private final List<Block> altars = new ArrayList<>();
private final Set<UUID> removedItems = new HashSet<>();
public void load(SlimefunPlugin plugin) {
public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

View File

@ -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<UUID, ItemStack> 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: <ID>"))) {
private void openBackpack(Player p, ItemStack item, PlayerProfile profile, int size) {
List<String> lore = item.getItemMeta().getLore();
for (int line = 0; line < lore.size(); line++) {
if (lore.get(line).equals(ChatColors.color("&7ID: <ID>"))) {
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);

View File

@ -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);
}
}
}

View File

@ -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));

View File

@ -30,7 +30,7 @@ public class GrapplingHookListener implements Listener {
private final Set<UUID> invulnerable = new HashSet<>();
private final Map<UUID, Entity[]> temporaryEntities = new HashMap<>();
public void load(SlimefunPlugin plugin) {
public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

View File

@ -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<PlayerProfile> 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<PlayerProfile> profile = PlayerProfile.find(e.getPlayer());
// if we still have a profile of this Player in memory, delete it
if (profile.isPresent()) {
profile.get().markForDeletion();
}
}

View File

@ -23,7 +23,7 @@ public class SlimefunBowListener implements Listener {
private final Map<UUID, SlimefunBow> bows = new HashMap<>();
public void load(SlimefunPlugin plugin) {
public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

View File

@ -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);

View File

@ -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

View File

@ -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<SlimefunItem> 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() {

View File

@ -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")) {

View File

@ -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<Location, Location> move = new ConcurrentHashMap<>();
private final ConcurrentMap<Location, Boolean> delete = new ConcurrentHashMap<>();
private final ConcurrentMap<Location, Long> 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<String, Long> 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<String, Long> 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<String, Long> 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<String, Long> 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

View File

@ -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));

View File

@ -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]+");
}

View File

@ -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;
}
}

View File

@ -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);
}
/**

View File

@ -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<ItemHandler> getPublicItemHandlers(Class<? extends ItemHandler> identifier) {
return SlimefunPlugin.getRegistry().getPublicItemHandlers().computeIfAbsent(identifier, c -> new HashSet<>());
}

View File

@ -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();
}

View File

@ -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<Location, Config> storage = new ConcurrentHashMap<>();
private Map<Location, BlockMenu> inventories = new ConcurrentHashMap<>();
private Map<String, Config> blocksCache = new ConcurrentHashMap<>();
private final World world;
private final Map<Location, Config> storage = new ConcurrentHashMap<>();
private final Map<Location, BlockMenu> inventories = new ConcurrentHashMap<>();
private final Map<String, Config> 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...");

View File

@ -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) {

View File

@ -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;
}
}