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 #### Changes
* Replaced GuideHandlers with FlexCategories * Replaced GuideHandlers with FlexCategories
* Removed support for old EmeraldEnchants versions * 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 #### Fixes
* Fixed error message when clicking empty slots in the Slimefun Guide * Fixed error message when clicking empty slots in the Slimefun Guide
* Fixed #1779 * Fixed #1779
* Fixed localized messages not showing in the book guide * 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) ## Release Candidate 10 (28 Mar 2020)

View File

@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -19,9 +20,11 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.config.Config; import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece; import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory; import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Research; import me.mrCookieSlime.Slimefun.Objects.Research;
@ -201,27 +204,28 @@ public final class PlayerProfile {
public void sendStats(CommandSender sender) { public void sendStats(CommandSender sender) {
Set<Research> researched = getResearches(); Set<Research> researched = getResearches();
int levels = researched.stream().mapToInt(Research::getCost).sum(); 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); float progress = Math.round(((researched.size() * 100.0F) / totalResearches) * 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% ";
sender.sendMessage(""); sender.sendMessage("");
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Statistics for Player: &b" + name)); sender.sendMessage(ChatColors.color("&7Statistics for Player: &b" + name));
sender.sendMessage(""); sender.sendMessage("");
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Title: &b" + getTitle())); sender.sendMessage(ChatColors.color("&7Title: " + ChatColor.AQUA + getTitle()));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Research Progress: " + progress + "&e(" + researched.size() + " / " + SlimefunPlugin.getRegistry().getResearches().size() + ")")); sender.sendMessage(ChatColors.color("&7Research Progress: " + NumberUtils.getColorFromPercentage(progress) + progress + " &r% " + ChatColor.YELLOW + '(' + researched.size() + " / " + totalResearches + ')'));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Total XP Levels spent: &b" + levels)); sender.sendMessage(ChatColors.color("&7Total XP Levels spent: " + ChatColor.AQUA + levels));
} }
public Player getPlayer() { public Player getPlayer() {
return Bukkit.getPlayer(getUUID()); 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() { public GuideHistory getGuideHistory() {
return guideHistory; return guideHistory;
} }
@ -291,26 +295,24 @@ public final class PlayerProfile {
* The player who's profile to retrieve * The player who's profile to retrieve
* @param callback * @param callback
* The callback with the PlayerProfile * The callback with the PlayerProfile
*
* @return If the player was cached or not. * @return If the player was cached or not.
*/ */
public static boolean get(OfflinePlayer p, Consumer<PlayerProfile> callback) { 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) { if (cached != null) {
callback.accept(profile); callback.accept(cached);
return true; return true;
} }
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> { Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> {
PlayerProfile pp = new PlayerProfile(p); PlayerProfile profile = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), pp); SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), profile);
callback.accept(pp); callback.accept(profile);
}); });
return false;
}
public static boolean isLoaded(UUID uuid) { return false;
return SlimefunPlugin.getRegistry().getPlayerProfiles().containsKey(uuid);
} }
public static Optional<PlayerProfile> find(OfflinePlayer p) { public static Optional<PlayerProfile> find(OfflinePlayer p) {
@ -324,24 +326,23 @@ public final class PlayerProfile {
public static PlayerBackpack getBackpack(ItemStack item) { public static PlayerBackpack getBackpack(ItemStack item) {
if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasLore()) return null; if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasLore()) return null;
Optional<Integer> id = Optional.empty(); OptionalInt id = OptionalInt.empty();
String uuid = ""; String uuid = "";
for (String line : item.getItemMeta().getLore()) { for (String line : item.getItemMeta().getLore()) {
if (line.startsWith(ChatColor.translateAlternateColorCodes('&', "&7ID: ")) && line.indexOf('#') != -1) { if (line.startsWith(ChatColors.color("&7ID: ")) && line.indexOf('#') != -1) {
try {
String[] splitLine = PatternUtils.HASH.split(line); String[] splitLine = PatternUtils.HASH.split(line);
id = Optional.of(Integer.parseInt(splitLine[1]));
uuid = splitLine[0].replace(ChatColor.translateAlternateColorCodes('&', "&7ID: "), ""); if (PatternUtils.NUMERIC.matcher(splitLine[1]).matches()) {
} id = OptionalInt.of(Integer.parseInt(splitLine[1]));
catch (NumberFormatException x) { uuid = splitLine[0].replace(ChatColors.color("&7ID: "), "");
return null;
} }
} }
} }
if (id.isPresent()) { if (id.isPresent()) {
return PlayerProfile.fromUUID(UUID.fromString(uuid)).getBackpack(id.get()); PlayerProfile profile = fromUUID(UUID.fromString(uuid));
return profile.getBackpack(id.getAsInt());
} }
else { else {
return null; return null;

View File

@ -9,6 +9,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -55,6 +57,7 @@ public class SlimefunRegistry {
private final Set<UUID> researchingPlayers = new HashSet<>(); private final Set<UUID> researchingPlayers = new HashSet<>();
private final KeyMap<Research> researchIds = new KeyMap<>(); private final KeyMap<Research> researchIds = new KeyMap<>();
private boolean automaticallyLoadItems;
private boolean enableResearches; private boolean enableResearches;
private boolean freeCreativeResearches; private boolean freeCreativeResearches;
private boolean researchFireworks; private boolean researchFireworks;
@ -71,9 +74,9 @@ public class SlimefunRegistry {
private final Set<String> chargeableBlocks = new HashSet<>(); private final Set<String> chargeableBlocks = new HashSet<>();
private final Map<String, WitherProof> witherProofBlocks = new HashMap<>(); 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, BlockStorage> worlds = new HashMap<>();
private final Map<String, BlockInfoConfig> chunks = 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<SlimefunGuideLayout, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideLayout.class);
private final Map<EntityType, Set<ItemStack>> drops = new EnumMap<>(EntityType.class); private final Map<EntityType, Set<ItemStack>> drops = new EnumMap<>(EntityType.class);
private final Map<String, Integer> capacities = new HashMap<>(); private final Map<String, Integer> capacities = new HashMap<>();
@ -99,6 +102,14 @@ public class SlimefunRegistry {
researchFireworks = cfg.getBoolean("options.research-unlock-fireworks"); researchFireworks = cfg.getBoolean("options.research-unlock-fireworks");
} }
public boolean isAutoLoadingEnabled() {
return automaticallyLoadItems;
}
public void setAutoLoadingMode(boolean mode) {
automaticallyLoadItems = mode;
}
public List<Category> getEnabledCategories() { public List<Category> getEnabledCategories() {
return categories; return categories;
} }
@ -201,7 +212,7 @@ public class SlimefunRegistry {
return universalInventories; return universalInventories;
} }
public Map<UUID, PlayerProfile> getPlayerProfiles() { public ConcurrentMap<UUID, PlayerProfile> getPlayerProfiles() {
return profiles; return profiles;
} }

View File

@ -38,7 +38,7 @@ public abstract class FlexCategory extends Category {
@Override @Override
public final boolean isHidden(Player p) { public final boolean isHidden(Player p) {
// We can stop this method right here. // 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; return false;
} }

View File

@ -84,8 +84,9 @@ public final class SlimefunGuide {
} }
public static void openGuide(Player p, SlimefunGuideLayout layout) { public static void openGuide(Player p, SlimefunGuideLayout layout) {
if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled")) return; if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
if (!SlimefunPlugin.getWhitelist().getBoolean(p.getWorld().getName() + ".enabled-items.SLIMEFUN_GUIDE")) return; return;
}
Optional<PlayerProfile> optional = PlayerProfile.find(p); Optional<PlayerProfile> optional = PlayerProfile.find(p);

View File

@ -20,15 +20,10 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/ */
public class CustomTextureService { public class CustomTextureService {
private final Plugin plugin; private final Config config;
private Config config;
private boolean modified = false; private boolean modified = false;
public CustomTextureService(Plugin plugin) { public CustomTextureService(Plugin plugin) {
this.plugin = plugin;
}
public void load() {
config = new Config(plugin, "item-models.yml"); 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."); 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.List;
import java.util.Optional; import java.util.Optional;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe; import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.RecipeChoice; import org.bukkit.inventory.RecipeChoice;
@ -33,10 +34,22 @@ public class MinecraftRecipeService {
this.plugin = plugin; 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); 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) { public Optional<ItemStack> getFurnaceOutput(ItemStack input) {
return snapshot.getRecipeOutput(MinecraftRecipe.FURNACE, 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) { public Recipe[] getRecipesFor(ItemStack item) {
if (item == null) {
return new Recipe[0];
}
else {
return snapshot.getRecipesFor(item).toArray(new Recipe[0]); 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 { public class PermissionsService {
private final SlimefunPlugin plugin; private final Config config;
private Config config;
public PermissionsService(SlimefunPlugin plugin) { public PermissionsService(SlimefunPlugin plugin) {
this.plugin = plugin; 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.");
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."
);
config.getConfiguration().options().copyHeader(true); config.getConfiguration().options().copyHeader(true);
} }

View File

@ -1,5 +1,8 @@
package io.github.thebusybiscuit.slimefun4.core.services.localization; 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.Server;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -39,10 +42,13 @@ public final class Language {
* The hash of the skull texture to use * The hash of the skull texture to use
*/ */
public Language(String id, String hash) { 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; this.id = id;
item = SkullItem.fromHash(hash); 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 org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; 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.ChatComponent;
import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent; import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface; 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.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.LockedCategory; import me.mrCookieSlime.Slimefun.Objects.LockedCategory;
@ -34,6 +36,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class BookSlimefunGuide implements SlimefunGuideImplementation { public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance, "search");
@Override @Override
public SlimefunGuideLayout getLayout() { public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.BOOK; return SlimefunGuideLayout.BOOK;
@ -50,6 +54,12 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
for (int i = 0; i < lines.size(); i = i + 10) { 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")); 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++) { for (int j = i; j < lines.size() && j < i + 10; j++) {
page.append(lines.get(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.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockUseHandler; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockUseHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> { public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
@ -117,12 +118,12 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
if (block.getY() == b.getY()) { if (block.getY() == b.getY()) {
line = new ChatComponent("\n" + ChatColor.GRAY + "> " + (floors.size() - i) + ". " + ChatColor.RESET + floor); 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 { else {
line = new ChatComponent("\n" + ChatColor.GRAY.toString() + (floors.size() - i) + ". " + ChatColor.RESET + floor); 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.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocal().getMessage(p, "machines.ELEVATOR.click-to-teleport")), "", ChatColor.RESET + floor, ""));
line.setClickEvent(new ClickEvent(elevatorKey, player -> { line.setClickEvent(new ClickEvent(elevatorKey, player -> Slimefun.runSync(() -> {
users.add(player.getUniqueId()); users.add(player.getUniqueId());
float yaw = player.getEyeLocation().getYaw() + 180; 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.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); player.sendTitle(ChatColor.RESET + ChatColors.color(floor), " ", 20, 60, 20);
})); })));
} }
page.append(line); page.append(line);

View File

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

View File

@ -5,7 +5,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -19,6 +18,7 @@ import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; 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.PlayerBackpack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.Cooler; 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<>(); private Map<UUID, ItemStack> backpacks = new HashMap<>();
public void load(SlimefunPlugin plugin) { public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, 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) { public void openBackpack(Player p, ItemStack item, SlimefunBackpack backpack) {
if (item.getAmount() == 1) { 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"); 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) { private void openBackpack(Player p, ItemStack item, PlayerProfile profile, int size) {
Player p = profile.getPlayer(); List<String> lore = item.getItemMeta().getLore();
for (int line = 0; line < lore.size(); line++) {
for (int line = 0; line < item.getItemMeta().getLore().size(); line++) { if (lore.get(line).equals(ChatColors.color("&7ID: <ID>"))) {
if (item.getItemMeta().getLore().get(line).equals(ChatColor.translateAlternateColorCodes('&', "&7ID: <ID>"))) {
setBackpackId(p, item, line, profile.createBackpack(size).getID()); setBackpackId(p, item, line, profile.createBackpack(size).getID());
break; break;
} }
@ -140,7 +139,13 @@ public class BackpackListener implements Listener {
p.playSound(p.getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F); p.playSound(p.getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F);
backpacks.put(p.getUniqueId(), item); 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 { else {
SlimefunPlugin.getLocal().sendMessage(p, "backpack.already-open", true); SlimefunPlugin.getLocal().sendMessage(p, "backpack.already-open", true);

View File

@ -52,7 +52,7 @@ public class BlockPhysicsListener implements Listener {
@EventHandler @EventHandler
public void onPistonExtend(BlockPistonExtendEvent e) { public void onPistonExtend(BlockPistonExtendEvent e) {
for (Block b : e.getBlocks()) { 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); e.setCancelled(true);
return; return;
} }
@ -63,7 +63,7 @@ public class BlockPhysicsListener implements Listener {
public void onPistonRetract(BlockPistonRetractEvent e) { public void onPistonRetract(BlockPistonRetractEvent e) {
if (e.isSticky()) { if (e.isSticky()) {
for (Block b : e.getBlocks()) { 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); e.setCancelled(true);
return; return;
} }
@ -71,15 +71,18 @@ public class BlockPhysicsListener implements Listener {
} }
} }
@EventHandler @EventHandler(ignoreCancelled = true)
public void onLiquidFlow(BlockFromToEvent e) { public void onLiquidFlow(BlockFromToEvent e) {
Block block = e.getToBlock(); Block block = e.getToBlock();
if (block.getType() == Material.PLAYER_HEAD || block.getType() == Material.PLAYER_WALL_HEAD) {
String item = BlockStorage.checkID(block); String item = BlockStorage.checkID(block);
if (item != null) { if (item != null) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
}
@EventHandler @EventHandler
public void onBucketUse(PlayerBucketEmptyEvent e) { public void onBucketUse(PlayerBucketEmptyEvent e) {

View File

@ -16,9 +16,11 @@ import org.bukkit.inventory.EquipmentSlot;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock; import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet; 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 io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems; import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock; import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
@ -69,9 +71,12 @@ public class DebugFishListener implements Listener {
} }
private void sendInfo(Player p, Block b) { private void sendInfo(Player p, Block b) {
SlimefunItem item = BlockStorage.check(b);
p.sendMessage(" "); p.sendMessage(" ");
p.sendMessage(ChatColors.color("&d" + b.getType() + " &e@ X: " + b.getX() + " Y: " + b.getY() + " Z: " + b.getZ())); 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) { if (b.getState() instanceof Skull) {
p.sendMessage(ChatColors.color("&dSkull: " + enabledTooltip)); p.sendMessage(ChatColors.color("&dSkull: " + enabledTooltip));
@ -92,17 +97,19 @@ public class DebugFishListener implements Listener {
p.sendMessage(ChatColors.color("&dInventory: " + disabledTooltip)); 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("&dTicker: " + enabledTooltip));
p.sendMessage(ChatColors.color(" &dAsync: &e" + (BlockStorage.check(b).getBlockTicker().isSynchronized() ? disabledTooltip : 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(" &dTimings: &e" + ticker.toMillis(ticker.getTimings(b), true) + "ms"));
p.sendMessage(ChatColors.color(" &dTotal Timings: &e" + SlimefunPlugin.getTicker().getTimings(BlockStorage.checkID(b)) + "ns")); p.sendMessage(ChatColors.color(" &dTotal Timings: &e" + ticker.toMillis(ticker.getTimings(BlockStorage.checkID(b)), true) + "ms"));
p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + SlimefunPlugin.getTicker().getTimings(b.getChunk()) + "ns")); 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("&dTicking: " + "&3Indirect"));
p.sendMessage(ChatColors.color(" &dTimings: &e" + SlimefunPlugin.getTicker().getTimings(b) + "ns")); p.sendMessage(ChatColors.color(" &dTimings: &e" + ticker.toMillis(ticker.getTimings(b), true) + "ms"));
p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + SlimefunPlugin.getTicker().getTimings(b.getChunk()) + "ns")); p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + ticker.toMillis(ticker.getTimings(b.getChunk()), true) + "ms"));
} }
else { else {
p.sendMessage(ChatColors.color("&dTicker: " + disabledTooltip)); 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 Set<UUID> invulnerable = new HashSet<>();
private final Map<UUID, Entity[]> temporaryEntities = new HashMap<>(); private final Map<UUID, Entity[]> temporaryEntities = new HashMap<>();
public void load(SlimefunPlugin plugin) { public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }

View File

@ -1,12 +1,25 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners; 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.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import me.mrCookieSlime.Slimefun.SlimefunPlugin; 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 class PlayerProfileListener implements Listener {
public PlayerProfileListener(SlimefunPlugin plugin) { public PlayerProfileListener(SlimefunPlugin plugin) {
@ -15,8 +28,21 @@ public class PlayerProfileListener implements Listener {
@EventHandler @EventHandler
public void onDisconnect(PlayerQuitEvent e) { public void onDisconnect(PlayerQuitEvent e) {
if (PlayerProfile.isLoaded(e.getPlayer().getUniqueId())) { Optional<PlayerProfile> profile = PlayerProfile.find(e.getPlayer());
PlayerProfile.get(e.getPlayer()).markForDeletion();
// 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<>(); private final Map<UUID, SlimefunBow> bows = new HashMap<>();
public void load(SlimefunPlugin plugin) { public void register(SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }

View File

@ -27,8 +27,10 @@ public class SlimefunGuideListener implements Listener {
public void onJoin(PlayerJoinEvent e) { public void onJoin(PlayerJoinEvent e) {
if (giveOnFirstJoin && !e.getPlayer().hasPlayedBefore()) { if (giveOnFirstJoin && !e.getPlayer().hasPlayedBefore()) {
Player p = e.getPlayer(); 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; SlimefunGuideLayout type = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST;
p.getInventory().addItem(SlimefunGuide.getItem(type)); p.getInventory().addItem(SlimefunGuide.getItem(type));
@ -43,6 +45,10 @@ public class SlimefunGuideListener implements Listener {
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.BOOK), true)) { if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.BOOK), true)) {
e.cancel(); e.cancel();
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
if (p.isSneaking()) { if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, item); SlimefunGuideSettings.openSettings(p, item);
} }
@ -53,6 +59,10 @@ public class SlimefunGuideListener implements Listener {
else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEST), true)) { else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEST), true)) {
e.cancel(); e.cancel();
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
if (p.isSneaking()) { if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, item); SlimefunGuideSettings.openSettings(p, item);
} }
@ -63,6 +73,10 @@ public class SlimefunGuideListener implements Listener {
else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEAT_SHEET), true)) { else if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(SlimefunGuideLayout.CHEAT_SHEET), true)) {
e.cancel(); e.cancel();
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
if (p.isSneaking()) { if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, item); SlimefunGuideSettings.openSettings(p, item);
} }

View File

@ -19,11 +19,8 @@ public class WorldListener implements Listener {
@EventHandler @EventHandler
public void onWorldLoad(WorldLoadEvent e) { public void onWorldLoad(WorldLoadEvent e) {
SlimefunPlugin.getWorldSettingsService().load(e.getWorld());
BlockStorage.getForcedStorage(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 @EventHandler

View File

@ -13,7 +13,6 @@ import java.util.stream.Stream;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.inventory.ItemStack; 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() { public static void loadItems() {
Iterator<SlimefunItem> iterator = SlimefunPlugin.getRegistry().getEnabledSlimefunItems().iterator(); Iterator<SlimefunItem> iterator = SlimefunPlugin.getRegistry().getEnabledSlimefunItems().iterator();
@ -117,7 +110,8 @@ public final class PostSetup {
SlimefunPlugin.getItemCfg().save(); SlimefunPlugin.getItemCfg().save();
SlimefunPlugin.getResearchCfg().save(); SlimefunPlugin.getResearchCfg().save();
SlimefunPlugin.getWhitelist().save();
SlimefunPlugin.getRegistry().setAutoLoadingMode(true);
} }
private static void loadAutomaticCraftingChamber() { private static void loadAutomaticCraftingChamber() {

View File

@ -48,6 +48,7 @@ public class SlimefunStartupTask implements Runnable {
PostSetup.loadItems(); PostSetup.loadItems();
// Load all worlds // Load all worlds
SlimefunPlugin.getWorldSettingsService().load(Bukkit.getWorlds());
for (World world : Bukkit.getWorlds()) { for (World world : Bukkit.getWorlds()) {
new BlockStorage(world); new BlockStorage(world);
} }
@ -55,11 +56,11 @@ public class SlimefunStartupTask implements Runnable {
// Load all listeners that depend on items to be enabled // Load all listeners that depend on items to be enabled
if (isEnabled("ANCIENT_ALTAR")) { if (isEnabled("ANCIENT_ALTAR")) {
SlimefunPlugin.getAncientAltarListener().load(plugin); SlimefunPlugin.getAncientAltarListener().register(plugin);
} }
if (isEnabled("GRAPPLING_HOOK")) { if (isEnabled("GRAPPLING_HOOK")) {
SlimefunPlugin.getGrapplingHookListener().load(plugin); SlimefunPlugin.getGrapplingHookListener().register(plugin);
} }
if (isEnabled("BLADE_OF_VAMPIRES")) { if (isEnabled("BLADE_OF_VAMPIRES")) {

View File

@ -36,7 +36,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class TickerTask implements Runnable { 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, Location> move = new ConcurrentHashMap<>();
private final ConcurrentMap<Location, Boolean> delete = new ConcurrentHashMap<>(); private final ConcurrentMap<Location, Boolean> delete = new ConcurrentHashMap<>();
private final ConcurrentMap<Location, Long> blockTimings = new ConcurrentHashMap<>(); private final ConcurrentMap<Location, Long> blockTimings = new ConcurrentHashMap<>();
@ -198,14 +198,14 @@ public class TickerTask implements Runnable {
} }
public String getTime() { public String getTime() {
return toMillis(time); return toMillis(time, false);
} }
public void info(CommandSender sender) { public void info(CommandSender sender) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2== &aSlimefun Diagnostic Tool &2==")); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2== &aSlimefun Diagnostic Tool &2=="));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Halted: &e&l" + String.valueOf(halted).toUpperCase())); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Halted: &e&l" + String.valueOf(halted).toUpperCase()));
sender.sendMessage(""); 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 Chunks: &e" + chunks));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Machines: &e" + machines)); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Machines: &e" + machines));
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Skipped Machines: &e" + skipped)); sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Skipped Machines: &e" + skipped));
@ -222,8 +222,8 @@ public class TickerTask implements Runnable {
for (Map.Entry<String, Long> entry : timings) { for (Map.Entry<String, Long> entry : timings) {
int count = machineCount.get(entry.getKey()); int count = machineCount.get(entry.getKey());
if (entry.getValue() > 500_000) { if (entry.getValue() > 300_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)"); 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++; else hidden++;
} }
@ -239,7 +239,7 @@ public class TickerTask implements Runnable {
for (Map.Entry<String, Long> entry : timings) { for (Map.Entry<String, Long> entry : timings) {
int count = machineCount.get(entry.getKey()); int count = machineCount.get(entry.getKey());
if (entry.getValue() > 500_000) { 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++; else hidden++;
} }
@ -260,7 +260,7 @@ public class TickerTask implements Runnable {
for (Map.Entry<String, Long> entry : timings) { for (Map.Entry<String, Long> entry : timings) {
if (!chunksSkipped.contains(entry.getKey())) { if (!chunksSkipped.contains(entry.getKey())) {
if (entry.getValue() > 0) { 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++; else hidden++;
} }
@ -277,7 +277,7 @@ public class TickerTask implements Runnable {
for (Map.Entry<String, Long> entry : timings) { for (Map.Entry<String, Long> entry : timings) {
if (!chunksSkipped.contains(entry.getKey())) { if (!chunksSkipped.contains(entry.getKey())) {
if (entry.getValue() > 0) { 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++; else hidden++;
} }
@ -316,8 +316,16 @@ public class TickerTask implements Runnable {
halted = true; halted = true;
} }
private String toMillis(long time) { public String toMillis(long nanoseconds, boolean colors) {
return decimalFormat.format(time / 1000000F) + "ms"; String number = decimalFormat.format(time / 1000000F);
if (!colors) {
return number;
}
else {
String[] parts = number.split(",|\\.");
return parts[0] + "," + ChatColor.GRAY + parts[1] + "ms";
}
} }
@Override @Override

View File

@ -7,6 +7,8 @@ import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.ChatColor;
import me.mrCookieSlime.Slimefun.SlimefunPlugin; import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun; 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) { public static String timeDelta(Date date) {
long timestamp = date.getTime(); long timestamp = date.getTime();
int hours = (int) ((System.currentTimeMillis() - timestamp) / (1000 * 60 * 60)); 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 DASH = Pattern.compile("-");
public static final Pattern ASCII = Pattern.compile("[A-Za-z \"_]+"); 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 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. * By default, a category is automatically registered when a {@link SlimefunItem} is bound to it.
*/ */
public void register() { public void register() {
if (this instanceof SeasonalCategory) { if (!(this instanceof SeasonalCategory) || ((SeasonalCategory) this).isVisible()) {
if (((SeasonalCategory) this).isVisible()) {
SlimefunPlugin.getRegistry().getEnabledCategories().add(this);
Collections.sort(SlimefunPlugin.getRegistry().getEnabledCategories(), Comparator.comparingInt(Category::getTier));
}
}
else {
SlimefunPlugin.getRegistry().getEnabledCategories().add(this); SlimefunPlugin.getRegistry().getEnabledCategories().add(this);
Collections.sort(SlimefunPlugin.getRegistry().getEnabledCategories(), Comparator.comparingInt(Category::getTier)); Collections.sort(SlimefunPlugin.getRegistry().getEnabledCategories(), Comparator.comparingInt(Category::getTier));
} }
@ -181,7 +175,7 @@ public class Category implements Keyed {
*/ */
public boolean isHidden(Player p) { public boolean isHidden(Player p) {
for (SlimefunItem slimefunItem : getItems()) { for (SlimefunItem slimefunItem : getItems()) {
if (Slimefun.isEnabled(p, slimefunItem, false)) { if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) {
return 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."); 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) * @see #addParent(Category)
*/ */
public void removeParent(Category 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 java.util.logging.Level;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; 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-enchanting", enchantable);
SlimefunPlugin.getItemCfg().setDefaultValue(id + ".allow-disenchanting", disenchantable); SlimefunPlugin.getItemCfg().setDefaultValue(id + ".allow-disenchanting", disenchantable);
// Load all item settings
for (ItemSetting<?> setting : itemSettings) { for (ItemSetting<?> setting : itemSettings) {
setting.load(this); 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")) { if (ticking && !SlimefunPlugin.getCfg().getBoolean("URID.enable-tickers")) {
state = ItemState.DISABLED; state = ItemState.DISABLED;
return; return;
@ -387,6 +381,11 @@ public class SlimefunItem implements Placeable {
} }
postRegister(); postRegister();
if (SlimefunPlugin.getRegistry().isAutoLoadingEnabled()) {
info("Item was registered during runtime.");
load();
}
} }
catch (Exception x) { catch (Exception x) {
error("Registering " + toString() + " has failed", x); error("Registering " + toString() + " has failed", x);
@ -690,11 +689,13 @@ public class SlimefunItem implements Placeable {
} }
public void info(String message) { 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) { 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); 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) { public static SlimefunItem getByItem(ItemStack item) {
if (item == null) return null; if (item == null) return null;
@ -759,11 +776,6 @@ public class SlimefunItem implements Placeable {
return null; 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) { public static Set<ItemHandler> getPublicItemHandlers(Class<? extends ItemHandler> identifier) {
return SlimefunPlugin.getRegistry().getPublicItemHandlers().computeIfAbsent(identifier, c -> new HashSet<>()); 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.CustomTextureService;
import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService; import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService;
import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService; 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.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService; import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService; 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 AutoSavingService autoSavingService = new AutoSavingService();
private final BackupService backupService = new BackupService(); private final BackupService backupService = new BackupService();
private final PermissionsService permissionsService = new PermissionsService(this); private final PermissionsService permissionsService = new PermissionsService(this);
private final PerWorldSettingsService worldSettingsService = new PerWorldSettingsService(this);
private final ThirdPartyPluginService thirdPartySupportService = new ThirdPartyPluginService(this); private final ThirdPartyPluginService thirdPartySupportService = new ThirdPartyPluginService(this);
private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this); private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this);
private LocalizationService local; private LocalizationService local;
@ -117,10 +119,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private ProtectionManager protections; private ProtectionManager protections;
// Important config files for Slimefun // Important config files for Slimefun
private Config researches; private final Config config = new Config(this);
private Config items; private final Config items = new Config(this, "Items.yml");
private Config whitelist; private final Config researches = new Config(this, "Researches.yml");
private Config config;
// Listeners that need to be accessed elsewhere // Listeners that need to be accessed elsewhere
private final AncientAltarListener ancientAltarListener = new AncientAltarListener(); private final AncientAltarListener ancientAltarListener = new AncientAltarListener();
@ -142,22 +143,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
instance = this; instance = this;
// Creating all necessary Folders // Creating all necessary Folders
getLogger().log(Level.INFO, "Loading files..."); getLogger().log(Level.INFO, "Loading various systems...");
createDirectories(); createDirectories();
// Setup config.yml
getLogger().log(Level.INFO, "Loading config...");
config = new Config(this);
registry.load(config); registry.load(config);
// Loading all extra configs // Set up localization
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();
local = new LocalizationService(this, config.getString("options.language")); local = new LocalizationService(this, config.getString("options.language"));
// Setting up Networks // Setting up Networks
@ -209,7 +199,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new WitherListener(this); new WitherListener(this);
new IronGolemListener(this); new IronGolemListener(this);
bowListener.load(this); bowListener.register(this);
// Toggleable Listeners for performance reasons // Toggleable Listeners for performance reasons
if (config.getBoolean("items.talismans")) { if (config.getBoolean("items.talismans")) {
@ -221,7 +211,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
} }
if (config.getBoolean("items.backpacks")) { if (config.getBoolean("items.backpacks")) {
backpackListener.load(this); backpackListener.register(this);
} }
// Handle Slimefun Guide being given on Join // Handle Slimefun Guide being given on Join
@ -238,7 +228,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
protections = new ProtectionManager(getServer()); protections = new ProtectionManager(getServer());
textureService.register(registry.getAllSlimefunItems()); textureService.register(registry.getAllSlimefunItems());
permissionsService.register(registry.getAllSlimefunItems()); permissionsService.register(registry.getAllSlimefunItems());
recipeService.load(); recipeService.refresh();
}), 0); }), 0);
// Setting up the command /sf and all subcommands // Setting up the command /sf and all subcommands
@ -254,9 +244,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
thirdPartySupportService.start(); thirdPartySupportService.start();
gitHubService.start(this); 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! // Hooray!
getLogger().log(Level.INFO, "Slimefun has finished loading in {0}", getStartupTime(timestamp)); 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; return;
} }
// Cancel all tasks from this plugin immediately
Bukkit.getScheduler().cancelTasks(this); Bukkit.getScheduler().cancelTasks(this);
if (ticker != null) { if (ticker != null) {
@ -367,9 +355,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
menu.save(); menu.save();
} }
// Create a new backup zip
backupService.run(); backupService.run();
// Prevent Memory Leaks // Prevent Memory Leaks
// These static Maps should be removed at some point...
AContainer.processing = null; AContainer.processing = null;
AContainer.progress = null; AContainer.progress = null;
@ -381,6 +371,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
instance = null; instance = null;
// Close all inventories on the server to prevent item dupes
// (Incase some idiot uses /reload)
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
p.closeInventory(); p.closeInventory();
} }
@ -388,22 +380,21 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private void createDirectories() { private void createDirectories() {
String[] storageFolders = { "Players", "blocks", "stored-blocks", "stored-inventories", "stored-chunks", "universal-inventories", "waypoints", "block-backups" }; 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) { 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(); if (!file.exists()) file.mkdirs();
} }
for (String folder : pluginFolders) { for (String folder : pluginFolders) {
File file = new File("plugins/Slimefun/" + folder); File file = new File("plugins/Slimefun", folder);
if (!file.exists()) file.mkdirs(); if (!file.exists()) file.mkdirs();
} }
} }
private void loadItems() { private void loadItems() {
try { try {
PostSetup.setupItemSettings();
SlimefunItemSetup.setup(this); SlimefunItemSetup.setup(this);
} }
catch (Throwable x) { catch (Throwable x) {
@ -432,10 +423,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.items; return instance.items;
} }
public static Config getWhitelist() {
return instance.whitelist;
}
public static GPSNetwork getGPSNetwork() { public static GPSNetwork getGPSNetwork() {
return instance.gpsNetwork; return instance.gpsNetwork;
} }
@ -490,6 +477,10 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.thirdPartySupportService; return instance.thirdPartySupportService;
} }
public static PerWorldSettingsService getWorldSettingsService() {
return instance.worldSettingsService;
}
/** /**
* This method returns the {@link UpdaterService} of Slimefun. * This method returns the {@link UpdaterService} of Slimefun.
* It is used to handle automatic updates. * It is used to handle automatic updates.

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_BLOCKS = "data-storage/Slimefun/stored-blocks/";
private static final String PATH_CHUNKS = "data-storage/Slimefun/stored-chunks/"; private static final String PATH_CHUNKS = "data-storage/Slimefun/stored-chunks/";
private World world; private final World world;
private Map<Location, Config> storage = new ConcurrentHashMap<>(); private final Map<Location, Config> storage = new ConcurrentHashMap<>();
private Map<Location, BlockMenu> inventories = new ConcurrentHashMap<>(); private final Map<Location, BlockMenu> inventories = new ConcurrentHashMap<>();
private Map<String, Config> blocksCache = new ConcurrentHashMap<>(); private final Map<String, Config> blocksCache = new ConcurrentHashMap<>();
public static BlockStorage getStorage(World world) { public static BlockStorage getStorage(World world) {
return SlimefunPlugin.getRegistry().getWorlds().get(world.getName()); return SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
@ -83,9 +83,13 @@ public class BlockStorage {
} }
public BlockStorage(World w) { public BlockStorage(World w) {
if (SlimefunPlugin.getRegistry().getWorlds().containsKey(w.getName())) return;
this.world = w; 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, "Loading Blocks for World \"" + w.getName() + "\"");
Slimefun.getLogger().log(Level.INFO, "This may take a long time..."); Slimefun.getLogger().log(Level.INFO, "This may take a long time...");

View File

@ -247,28 +247,15 @@ public final class Slimefun {
return false; 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(); return false;
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; 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;
}
}
else return true;
}
public static BukkitTask runSync(Runnable r) { public static BukkitTask runSync(Runnable r) {
return Bukkit.getScheduler().runTask(SlimefunPlugin.instance, r); return Bukkit.getScheduler().runTask(SlimefunPlugin.instance, r);

View File

@ -189,17 +189,15 @@ public class SlimefunItemStack extends CustomItem {
} }
private static String getTexture(String id, String texture) { private static String getTexture(String id, String texture) {
String base64 = texture; if (texture.startsWith("ey")) {
return 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());
} }
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!"); throw new IllegalArgumentException("The provided texture for Item \"" + id + "\" does not seem to be a valid texture String!");
} }
return base64;
} }
} }