diff --git a/.github/renovate.json b/.github/renovate.json index c74f8617a..f45d8f110 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,8 +1,5 @@ { "extends": [ "config:base" - ], - "labels": [ - "🚨 Dependency Update" ] } diff --git a/.github/workflows/closed-issues-reason.yml b/.github/workflows/closed-issues-reason.yml index 262b9c54b..f20726e9e 100644 --- a/.github/workflows/closed-issues-reason.yml +++ b/.github/workflows/closed-issues-reason.yml @@ -6,8 +6,11 @@ on: jobs: comment: + + name: Comment on Issue runs-on: ubuntu-latest if: contains(github.event.issue.labels.*.name, '🐞 Bug Report') + steps: - name: Query recent commits uses: TheBusyBiscuit/recently-closed-issues@1.1.0 @@ -44,8 +47,8 @@ jobs: * [ ] Your issue has already been reported before, it is a duplicate. Check the other issues first before posting! * [ ] You posted an error without using pastebin. Please always post errors via pastebin otherwise they become nearly unreadable. * [ ] You seem to be reporting multiple bugs at once. Please make a separate issue for each bug you encountered, so we can properly handle them individually. - * [ ] Your issue has already been fixed in a later version of Slimefun or CS-CoreLib, you should update. - * [ ] You are using an outdated and unsupported version of Slimefun / CS-CoreLib, again, you should update. + * [ ] Your issue has already been fixed in a later version of Slimefun, you should update. + * [ ] You are using an outdated and unsupported version of Slimefun, again, you should update. * [ ] You are using an unofficially modified build of Slimefun. We only support official versions of Slimefun - for obvious reasons. * [ ] You are using an unsupported version of Minecraft. We only provide support for the Minecraft versions Slimefun was developed for, older versions are not supported anymore. * [ ] You are using a \"stable\" version of Slimefun (prefixed with \"RC - \"), your issue may have been fixed in a development build, so we only accept bug reports from those. diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml new file mode 100644 index 000000000..85f81e547 --- /dev/null +++ b/.github/workflows/pr-labels.yml @@ -0,0 +1,56 @@ +name: Pull Request Labels + +on: + pull_request: + types: + - opened + +jobs: + pr-labeler: + + name: Pull Request Labels + runs-on: ubuntu-latest + if: github.repository == 'Slimefun/Slimefun4' && github.actor != 'gitlocalize-app[bot]' + + steps: + - uses: WalshyDev/pr-labels@v1.1 + id: labeller + name: Apply labels based on branch + with: + token: "${{ secrets.ACCESS_TOKEN }}" + renovate: '🚨 Dependency Update' + feature: '🎈 Feature' + fix: '✨ Fix' + chore: '🧹 Chores' + performance: '💡 Performance Optimization' + api: '🔧 API' + compatibility: '🤝 Compatibility' + + - uses: thollander/actions-comment-pull-request@1.0.1 + name: Leave a comment about the applied label + if: ${{ steps.labeller.outputs.applied != 0 }} + with: + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} + message: | + Your Pull Request was automatically labelled as: "${{ steps.labeller.outputs.applied }}" + Thank you for contributing to this project! ❤️ + + - uses: thollander/actions-comment-pull-request@1.0.1 + name: Leave a comment about our branch naming convention + if: ${{ steps.labeller.outputs.applied == 0 }} + with: + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} + message: | + **Pro Tip!** + You can help us label your Pull Requests by using the following branch naming convention next time you create a pull request. ❤️ + Branch naming convention | Label + ------------------------ | ------ + `feature/**` | 🎈 Feature + `fix/**` | ✨ Fix + `chore/**` | 🧹 Chores + `api/**` | 🔧 API + `performance/**` | 💡 Performance Optimization + `compatibility/**` | 🤝 Compatibility +
+ If your changes do not fall into any of these categories, don't worry. + You can just ignore this message in that case! 👀 diff --git a/CHANGELOG.md b/CHANGELOG.md index ef1cd355b..65659030b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,6 @@ - - -**Table of contents** - +# Table of contents +- [Release Candidate 21 (TBD)](#release-candidate-21-tbd) +- [Release Candidate 20 (30 Jan 2021)](#release-candidate-20-30-jan-2021) - [Release Candidate 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021) - [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020) - [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020) @@ -22,15 +21,36 @@ - [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019) - [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019) - +## Release Candidate 21 (TBD) -## Release Candidate 20 (TBD) +#### Additions +* Nether Wart Blocks can now be turned into Nether Warts using a Grind Stone +* Added an option to allow Talismans to send their notifications via the Actionbar +* /sf versions now shows the Java version and some useful tooltips + +#### Changes +* Deprecated Automatic Crafting Chamber + +#### Fixes +* Fixed #2794 +* Fixed #2793 +* Fixed #2809 +* Fixed a small exception which gets thrown when Slimefun is disabled due to an invalid environment +* Fixed #2810 +* Fixed #2804 +* Fixed #2817 +* Fixed exceptions with inventories not being printed using the logger of the addon that caused it +* Fixed #2818 + +## Release Candidate 20 (30 Jan 2021) #### Additions * Added a new language: Bulgarian * Added a new language: Hebrew * (API) Added AsyncProfileLoadEvent * Added Talisman of the Wise +* Added Book Binder +* Added Tier 3 Electric Ore Grinder #### Changes * Massive performance improvements to holograms/armorstands @@ -50,6 +70,13 @@ * Fixed Infused Hopper picking up items with a max pickup delay * Fixed duplication issues related to holograms/armorstands * Fixed #2754 +* Fixed machines not respecting max size from inventories +* Fixed #2761 +* Fixed #2460 +* Fixed #2760 +* Fixed #2771 +* Fixed placeholders that did not get loaded yet not having a label +* Fixed #2679 ## Release Candidate 19 (11 Jan 2021) diff --git a/pom.xml b/pom.xml index 753cf0864..7915fa728 100644 --- a/pom.xml +++ b/pom.xml @@ -315,13 +315,13 @@ org.junit.jupiter junit-jupiter - 5.7.0 + 5.7.1 test com.github.seeseemelk MockBukkit-v1.16 - 0.21.0 + 0.24.0 test @@ -343,7 +343,7 @@ com.github.TheBusyBiscuit CS-CoreLib2 - 0.29.6 + 0.30.0 compile @@ -355,7 +355,7 @@ com.konghq unirest-java - 3.11.10 + 3.11.11 compile @@ -387,7 +387,7 @@ com.gmail.nossr50.mcMMO mcMMO - 2.1.172 + 2.1.174 provided @@ -436,7 +436,7 @@ com.github.LoneDev6 itemsadder-api - 2.1.25 + 2.1.35 provided diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java index eef94aec3..015279689 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java @@ -79,6 +79,7 @@ public abstract class Network { * * @param l * The {@link Location} to classify + * * @return The assigned type of {@link NetworkComponent} for this {@link Location} */ @Nullable diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java index 76ad95838..d867ac51a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerProfile.java @@ -388,7 +388,7 @@ public class PlayerProfile { Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> { AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p)); Bukkit.getPluginManager().callEvent(event); - + SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, event.getProfile()); callback.accept(event.getProfile()); }); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java index e282c31af..f41116cd6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java @@ -64,12 +64,14 @@ public final class SlimefunRegistry { private final List researchRanks = new ArrayList<>(); private final Set researchingPlayers = Collections.synchronizedSet(new HashSet<>()); + // TODO: Move this all into a proper "config cache" class private boolean backwardsCompatibility; private boolean automaticallyLoadItems; private boolean enableResearches; private boolean freeCreativeResearches; private boolean researchFireworks; private boolean logDuplicateBlockEntries; + private boolean talismanActionBarMessages; private final Set tickers = new HashSet<>(); private final Set radioactive = new HashSet<>(); @@ -110,6 +112,7 @@ public final class SlimefunRegistry { freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode"); researchFireworks = cfg.getBoolean("researches.enable-fireworks"); logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries"); + talismanActionBarMessages = cfg.getBoolean("talismans.use-actionbar"); } /** @@ -354,6 +357,10 @@ public final class SlimefunRegistry { return logDuplicateBlockEntries; } + public boolean useActionbarForTalismans() { + return talismanActionBarMessages; + } + @Nonnull public NamespacedKey getSoulboundDataKey() { return soulboundKey; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/LockedCategory.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/LockedCategory.java index 7056eadcf..d5334e011 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/LockedCategory.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/categories/LockedCategory.java @@ -19,7 +19,6 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * Represents a {@link Category} that cannot be opened until the parent category/categories @@ -153,14 +152,13 @@ public class LockedCategory extends Category { * @return Whether the {@link Player} has fully completed all parent categories, otherwise false */ public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) { + Validate.notNull(p, "The player cannot be null!"); + Validate.notNull(profile, "The Profile cannot be null!"); + for (Category category : parents) { for (SlimefunItem item : category.getItems()) { - /* - * Should probably be replaced with Slimefun.hasUnlocked(...) - * However this will result in better performance because we don't - * request the PlayerProfile everytime - */ - if (Slimefun.isEnabled(p, item, false) && Slimefun.hasPermission(p, item, false) && !profile.hasUnlocked(item.getResearch())) { + // Check if the Player has researched every item (if the item is enabled) + if (!item.isDisabledIn(p.getWorld()) && item.hasResearch() && !profile.hasUnlocked(item.getResearch())) { return false; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java index 6a21e4ef9..63d9f13e9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java @@ -3,18 +3,30 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands; import java.util.Collection; import javax.annotation.Nonnull; + import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.plugin.Plugin; -import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; +import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon; import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand; import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.papermc.lib.PaperLib; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.hover.content.Text; +/** + * This is our class for the /sf versions subcommand. + * + * @author TheBusyBiscuit + * @author Walshy + * + */ class VersionsCommand extends SubCommand { VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) { @@ -24,39 +36,171 @@ class VersionsCommand extends SubCommand { @Override public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) { if (sender.hasPermission("slimefun.command.versions") || sender instanceof ConsoleCommandSender) { - // After all these years... Spigot still displays as "CraftBukkit" - // so we will just fix this inconsistency for them :) + /* + * After all these years... Spigot still displays as "CraftBukkit". + * so we will just fix this inconsistency for them :) + */ String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName(); + ComponentBuilder builder = new ComponentBuilder(); - sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:"); - sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion())); - sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion())); + // @formatter:off + builder.append("This Server uses the following setup of Slimefun:\n") + .color(ChatColor.GRAY) + .append(serverSoftware) + .color(ChatColor.GREEN) + .append(" " + Bukkit.getVersion() + '\n') + .color(ChatColor.DARK_GREEN) + .append("Slimefun ") + .color(ChatColor.GREEN) + .append(SlimefunPlugin.getVersion() + '\n') + .color(ChatColor.DARK_GREEN); + // @formatter:on if (SlimefunPlugin.getMetricsService().getVersion() != null) { - sender.sendMessage(ChatColors.color("&aMetrics build: &2#" + SlimefunPlugin.getMetricsService().getVersion())); + // @formatter:off + builder.append("Metrics-Module ") + .color(ChatColor.GREEN) + .append("#" + SlimefunPlugin.getMetricsService().getVersion() + '\n') + .color(ChatColor.DARK_GREEN); + // @formatter:on } + addJavaVersion(builder); + if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) { - sender.sendMessage(ChatColor.RED + "Backwards compatibility enabled!"); + // @formatter:off + HoverEvent hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "Backwards compatibility has a negative impact on performance!\n" + + "We recommend you to disable this setting unless your server still " + + "has legacy Slimefun items (from before summer 2019) in circulation." + )); + // @formatter:on + + builder.append("\nBackwards compatibility enabled!\n").color(ChatColor.RED).event(hoverEvent); } - sender.sendMessage(""); + builder.append("\n").event((HoverEvent) null); + addPluginVersions(builder); - Collection addons = SlimefunPlugin.getInstalledAddons(); - sender.sendMessage(ChatColors.color("&7Installed Addons: &8(" + addons.size() + ")")); - - for (Plugin plugin : addons) { - String version = plugin.getDescription().getVersion(); - - if (Bukkit.getPluginManager().isPluginEnabled(plugin)) { - sender.sendMessage(ChatColor.GREEN + " " + plugin.getName() + ChatColor.DARK_GREEN + " v" + version); - } else { - sender.sendMessage(ChatColor.RED + " " + plugin.getName() + ChatColor.DARK_RED + " v" + version); - } - } + sender.spigot().sendMessage(builder.create()); } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true); } } + private void addJavaVersion(@Nonnull ComponentBuilder builder) { + String javaVer = System.getProperty("java.version"); + + if (javaVer.startsWith("1.")) { + javaVer = javaVer.substring(2); + } + + // If it's like 11.0.1.3 or 8.0_275 + if (javaVer.indexOf('.') != -1) { + javaVer = javaVer.substring(0, javaVer.indexOf('.')); + } + + int version = Integer.parseInt(javaVer); + + if (version < 11) { + // @formatter:off + builder.append("Java " + version).color(ChatColor.RED) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text( + "Your Java version is out of date!\n!" + + "You should use Java 11 or higher.\n" + + "Paper will be dropping support for older versions with the release of Minecraft 1.17." + ))) + .append("\n") + .event((HoverEvent) null); + // @formatter:on + } else { + builder.append("Java ").color(ChatColor.GREEN).append(version + "\n").color(ChatColor.DARK_GREEN); + } + } + + private void addPluginVersions(@Nonnull ComponentBuilder builder) { + Collection addons = SlimefunPlugin.getInstalledAddons(); + + if (addons.isEmpty()) { + builder.append("No Addons installed").color(ChatColor.GRAY).italic(true); + return; + } + + builder.append("Installed Addons: ").color(ChatColor.GRAY).append("(" + addons.size() + ")").color(ChatColor.DARK_GRAY); + + for (Plugin plugin : addons) { + String version = plugin.getDescription().getVersion(); + + HoverEvent hoverEvent = null; + ClickEvent clickEvent = null; + ChatColor primaryColor; + ChatColor secondaryColor; + + if (Bukkit.getPluginManager().isPluginEnabled(plugin)) { + primaryColor = ChatColor.GREEN; + secondaryColor = ChatColor.DARK_GREEN; + String authors = String.join(", ", plugin.getDescription().getAuthors()); + + if (plugin instanceof SlimefunAddon && ((SlimefunAddon) plugin).getBugTrackerURL() != null) { + // @formatter:off + hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder() + .append("Author(s): ") + .append(authors) + .color(ChatColor.YELLOW) + .append("\n> Click here to go to their issues tracker") + .color(ChatColor.GOLD) + .create() + )); + // @formatter:on + + clickEvent = new ClickEvent(ClickEvent.Action.OPEN_URL, ((SlimefunAddon) plugin).getBugTrackerURL()); + } else { + // @formatter:off + hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder() + .append("Author(s): ") + .append(authors) + .color(ChatColor.YELLOW) + .create() + )); + // @formatter:on + } + } else { + primaryColor = ChatColor.RED; + secondaryColor = ChatColor.DARK_RED; + + if (plugin instanceof SlimefunAddon && ((SlimefunAddon) plugin).getBugTrackerURL() != null) { + // @formatter:off + hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder() + .append("This plugin is disabled.\nCheck the console for an error message.") + .color(ChatColor.RED) + .append("\n> Click here to report on their issues tracker") + .color(ChatColor.DARK_RED) + .create() + )); + // @formatter:on + + SlimefunAddon addon = (SlimefunAddon) plugin; + + if (addon.getBugTrackerURL() != null) { + clickEvent = new ClickEvent(ClickEvent.Action.OPEN_URL, addon.getBugTrackerURL()); + } + } else { + hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Plugin is disabled. Check the console for an error and report on their issues tracker.")); + } + } + + // @formatter:off + // We need to reset the hover event or it's added to all components + builder.append("\n " + plugin.getName()) + .color(primaryColor) + .event(hoverEvent) + .event(clickEvent) + .append(" v" + version) + .color(secondaryColor) + .append("") + .event((ClickEvent) null) + .event((HoverEvent) null); + // @formatter:on + } + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideModeOption.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideModeOption.java index 007a1d3cc..bd7506eeb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideModeOption.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideModeOption.java @@ -32,7 +32,7 @@ class GuideModeOption implements SlimefunGuideOption { @Nonnull @Override public NamespacedKey getKey() { - return new NamespacedKey(SlimefunPlugin.instance(), "guide_layout"); + return new NamespacedKey(SlimefunPlugin.instance(), "guide_mode"); } @Nonnull @@ -46,25 +46,24 @@ class GuideModeOption implements SlimefunGuideOption { Optional current = getSelectedOption(p, guide); if (current.isPresent()) { - SlimefunGuideMode layout = current.get(); + SlimefunGuideMode selectedMode = current.get(); ItemStack item = new ItemStack(Material.AIR); - if (layout == SlimefunGuideMode.SURVIVAL_MODE) { + if (selectedMode == SlimefunGuideMode.SURVIVAL_MODE) { item.setType(Material.CHEST); } else { item.setType(Material.COMMAND_BLOCK); } ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Design: " + ChatColor.YELLOW + ChatUtils.humanize(layout.name())); + meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Type: " + ChatColor.YELLOW + ChatUtils.humanize(selectedMode.name())); List lore = new ArrayList<>(); lore.add(""); - lore.add((layout == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Chest"); - - lore.add((layout == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet"); + lore.add((selectedMode == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Survival Mode"); + lore.add((selectedMode == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet"); lore.add(""); - lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change your layout"); + lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change the type"); meta.setLore(lore); item.setItemMeta(meta); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java index 250281097..6662fcb22 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java @@ -18,6 +18,8 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode; import io.github.thebusybiscuit.slimefun4.core.researching.Research; +import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService; +import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService; import io.github.thebusybiscuit.slimefun4.core.services.localization.Language; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; @@ -71,46 +73,127 @@ public final class SlimefunGuideSettings { @ParametersAreNonnullByDefault private static void addHeader(Player p, ChestMenu menu, ItemStack guide) { - menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> { + LocalizationService locale = SlimefunPlugin.getLocalization(); + + // @formatter:off + menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), + "&e\u21E6 " + locale.getMessage(p, "guide.back.title"), + "", + "&7" + locale.getMessage(p, "guide.back.guide") + )); + // @formatter:on + + menu.addMenuClickHandler(0, (pl, slot, item, action) -> { SlimefunGuide.openGuide(pl, guide); return false; }); + GitHubService github = SlimefunPlugin.getGitHubService(); + List contributorsLore = new ArrayList<>(); contributorsLore.add(""); - contributorsLore.addAll(SlimefunPlugin.getLocalization().getMessages(p, "guide.credits.description", msg -> msg.replace("%contributors%", String.valueOf(SlimefunPlugin.getGitHubService().getContributors().size())))); + contributorsLore.addAll(locale.getMessages(p, "guide.credits.description", msg -> msg.replace("%contributors%", String.valueOf(github.getContributors().size())))); contributorsLore.add(""); - contributorsLore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.credits.open")); + contributorsLore.add("&7\u21E8 &e" + locale.getMessage(p, "guide.credits.open")); - menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.credits"), contributorsLore.toArray(new String[0])), (pl, slot, action, item) -> { + // @formatter:off + menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), + "&c" + locale.getMessage(p, "guide.title.credits"), + contributorsLore.toArray(new String[0]) + )); + // @formatter:on + + menu.addMenuClickHandler(2, (pl, slot, action, item) -> { ContributorsMenu.open(pl, 0); return false; }); - menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.versions"), "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft: &a" + Bukkit.getBukkitVersion(), "&fSlimefun: &a" + SlimefunPlugin.getVersion()), ChestMenuUtils.getEmptyClickHandler()); + // @formatter:off + menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, + ChatColor.GREEN + locale.getMessage(p, "guide.title.versions"), + "&7&o" + locale.getMessage(p, "guide.tooltips.versions-notice"), + "", + "&fMinecraft: &a" + Bukkit.getBukkitVersion(), + "&fSlimefun: &a" + SlimefunPlugin.getVersion()), + ChestMenuUtils.getEmptyClickHandler() + ); + // @formatter:on + + // @formatter:off + menu.addItem(6, new CustomItem(Material.COMPARATOR, + "&e" + locale.getMessage(p, "guide.title.source"), + "", "&7Last Activity: &a" + NumberUtils.getElapsedTime(github.getLastUpdate()) + " ago", + "&7Forks: &e" + github.getForks(), + "&7Stars: &e" + github.getStars(), + "", + "&7&oSlimefun 4 is a community project,", + "&7&othe source code is available on GitHub", + "&7&oand if you want to keep this Plugin alive,", + "&7&othen please consider contributing to it", + "", + "&7\u21E8 &eClick to go to GitHub" + )); + // @formatter:on - menu.addItem(6, - new CustomItem(Material.COMPARATOR, "&e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.source"), "", "&7Last Activity: &a" + NumberUtils.getElapsedTime(SlimefunPlugin.getGitHubService().getLastUpdate()) + " ago", "&7Forks: &e" + SlimefunPlugin.getGitHubService().getForks(), "&7Stars: &e" + SlimefunPlugin.getGitHubService().getStars(), "", "&7&oSlimefun 4 is a community project,", "&7&othe source code is available on GitHub", "&7&oand if you want to keep this Plugin alive,", "&7&othen please consider contributing to it", "", "&7\u21E8 &eClick to go to GitHub")); menu.addMenuClickHandler(6, (pl, slot, item, action) -> { pl.closeInventory(); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4"); return false; }); - menu.addItem(8, new CustomItem(Material.KNOWLEDGE_BOOK, "&3" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.wiki"), "", "&7Do you need help with an Item or machine?", "&7You cannot figure out what to do?", "&7Check out our community-maintained Wiki", "&7and become one of our Editors!", "", "&7\u21E8 &eClick to go to the official Slimefun Wiki"), (pl, slot, item, action) -> { + // @formatter:off + menu.addItem(8, new CustomItem(Material.KNOWLEDGE_BOOK, + "&3" + locale.getMessage(p, "guide.title.wiki"), + "", "&7Do you need help with an Item or machine?", + "&7You cannot figure out what to do?", + "&7Check out our community-maintained Wiki", + "&7and become one of our Editors!", + "", + "&7\u21E8 &eClick to go to the official Slimefun Wiki" + )); + // @formatter:on + + menu.addMenuClickHandler(8, (pl, slot, item, action) -> { pl.closeInventory(); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki"); return false; }); - menu.addItem(47, new CustomItem(Material.BOOKSHELF, "&3" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.addons"), "", "&7Slimefun is huge. But its addons are what makes", "&7this plugin truly shine. Go check them out, some", "&7of them may be exactly what you were missing out on!", "", "&7Installed on this Server: &b" + SlimefunPlugin.getInstalledAddons().size(), "", "&7\u21E8 &eClick to see all available Addons for Slimefun4"), (pl, slot, item, action) -> { + // @formatter:off + menu.addItem(47, new CustomItem(Material.BOOKSHELF, + "&3" + locale.getMessage(p, "guide.title.addons"), + "", + "&7Slimefun is huge. But its addons are what makes", + "&7this plugin truly shine. Go check them out, some", + "&7of them may be exactly what you were missing out on!", + "", + "&7Installed on this Server: &b" + SlimefunPlugin.getInstalledAddons().size(), + "", + "&7\u21E8 &eClick to see all available addons for Slimefun4" + )); + // @formatter:on + + menu.addMenuClickHandler(47, (pl, slot, item, action) -> { pl.closeInventory(); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki/Addons"); return false; }); if (SlimefunPlugin.getUpdater().getBranch().isOfficial()) { - menu.addItem(49, new CustomItem(Material.REDSTONE_TORCH, "&4" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.bugs"), "", "&7&oBug reports have to be made in English!", "", "&7Open Issues: &a" + SlimefunPlugin.getGitHubService().getOpenIssues(), "&7Pending Pull Requests: &a" + SlimefunPlugin.getGitHubService().getPendingPullRequests(), "", "&7\u21E8 &eClick to go to the Slimefun4 Bug Tracker"), (pl, slot, item, action) -> { + // @formatter:off + menu.addItem(49, new CustomItem(Material.REDSTONE_TORCH, + "&4" + locale.getMessage(p, "guide.title.bugs"), + "", + "&7&oBug reports have to be made in English!", + "", + "&7Open Issues: &a" + github.getOpenIssues(), + "&7Pending Pull Requests: &a" + github.getPendingPullRequests(), + "", + "&7\u21E8 &eClick to go to the Slimefun4 Bug Tracker" + )); + // @formatter:on + + menu.addMenuClickHandler(49, (pl, slot, item, action) -> { pl.closeInventory(); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/issues"); return false; @@ -119,7 +202,7 @@ public final class SlimefunGuideSettings { menu.addItem(49, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler()); } - menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> { + menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + locale.getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> { // Add something here return false; }); @@ -158,7 +241,8 @@ public final class SlimefunGuideSettings { for (SlimefunGuideOption option : options) { if (option instanceof FireworksOption) { FireworksOption fireworks = (FireworksOption) option; - return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE)).orElse(true); + ItemStack guide = SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE); + return fireworks.getSelectedOption(p, guide).orElse(true); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlockMachine.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlockMachine.java index a0f7f33e7..3be2cb608 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlockMachine.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlockMachine.java @@ -31,7 +31,6 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; /** @@ -114,10 +113,11 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace } } + @Nonnull protected MultiBlockInteractionHandler getInteractionHandler() { return (p, mb, b) -> { if (mb.equals(getMultiBlock())) { - if (!isDisabled() && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK) && Slimefun.hasUnlocked(p, this, true)) { + if (canUse(p, true) && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK)) { onInteract(p, b); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/AbstractItemNetwork.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/AbstractItemNetwork.java index 210125e80..3216b0bd5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/AbstractItemNetwork.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/AbstractItemNetwork.java @@ -115,14 +115,14 @@ abstract class AbstractItemNetwork extends Network { if (menu != null) { switch (request.getDirection()) { - case INSERT: - distributeInsertionRequest(inventories, request, menu, iterator, destinations); - break; - case WITHDRAW: - collectExtractionRequest(inventories, request, menu, iterator, providers); - break; - default: - break; + case INSERT: + distributeInsertionRequest(inventories, request, menu, iterator, destinations); + break; + case WITHDRAW: + collectExtractionRequest(inventories, request, menu, iterator, providers); + break; + default: + break; } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNet.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNet.java index 9efb04778..debf7618f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNet.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoNet.java @@ -92,19 +92,19 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner { } switch (id) { - case "CARGO_MANAGER": - return NetworkComponent.REGULATOR; - case "CARGO_NODE": - return NetworkComponent.CONNECTOR; - case "CARGO_NODE_INPUT": - case "CARGO_NODE_OUTPUT": - case "CARGO_NODE_OUTPUT_ADVANCED": - case "CT_IMPORT_BUS": - case "CT_EXPORT_BUS": - case "CHEST_TERMINAL": - return NetworkComponent.TERMINUS; - default: - return null; + case "CARGO_MANAGER": + return NetworkComponent.REGULATOR; + case "CARGO_NODE": + return NetworkComponent.CONNECTOR; + case "CARGO_NODE_INPUT": + case "CARGO_NODE_OUTPUT": + case "CARGO_NODE_OUTPUT_ADVANCED": + case "CT_IMPORT_BUS": + case "CT_EXPORT_BUS": + case "CHEST_TERMINAL": + return NetworkComponent.TERMINUS; + default: + return null; } } @@ -123,24 +123,24 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner { if (to == NetworkComponent.TERMINUS) { String id = BlockStorage.checkID(l); switch (id) { - case "CARGO_NODE_INPUT": - inputNodes.add(l); - break; - case "CARGO_NODE_OUTPUT": - case "CARGO_NODE_OUTPUT_ADVANCED": - outputNodes.add(l); - break; - case "CHEST_TERMINAL": - terminals.add(l); - break; - case "CT_IMPORT_BUS": - imports.add(l); - break; - case "CT_EXPORT_BUS": - exports.add(l); - break; - default: - break; + case "CARGO_NODE_INPUT": + inputNodes.add(l); + break; + case "CARGO_NODE_OUTPUT": + case "CARGO_NODE_OUTPUT_ADVANCED": + outputNodes.add(l); + break; + case "CHEST_TERMINAL": + terminals.add(l); + break; + case "CT_IMPORT_BUS": + imports.add(l); + break; + case "CT_EXPORT_BUS": + exports.add(l); + break; + default: + break; } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java index 69f993a0c..2740f5b8e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java @@ -68,19 +68,19 @@ final class CargoUtils { Material type = block.getType(); switch (type) { - case CHEST: - case TRAPPED_CHEST: - case FURNACE: - case DISPENSER: - case DROPPER: - case HOPPER: - case BREWING_STAND: - case BARREL: - case BLAST_FURNACE: - case SMOKER: - return true; - default: - return SlimefunTag.SHULKER_BOXES.isTagged(type); + case CHEST: + case TRAPPED_CHEST: + case FURNACE: + case DISPENSER: + case DROPPER: + case HOPPER: + case BREWING_STAND: + case BARREL: + case BLAST_FURNACE: + case SMOKER: + return true; + default: + return SlimefunTag.SHULKER_BOXES.isTagged(type); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java index 0be2f59db..d91e4c2b6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java @@ -75,14 +75,14 @@ public class EnergyNet extends Network implements HologramOwner { return null; } else { switch (component.getEnergyComponentType()) { - case CONNECTOR: - case CAPACITOR: - return NetworkComponent.CONNECTOR; - case CONSUMER: - case GENERATOR: - return NetworkComponent.TERMINUS; - default: - return null; + case CONNECTOR: + case CAPACITOR: + return NetworkComponent.CONNECTOR; + case CONSUMER: + case GENERATOR: + return NetworkComponent.TERMINUS; + default: + return null; } } } @@ -98,21 +98,21 @@ public class EnergyNet extends Network implements HologramOwner { if (component != null) { switch (component.getEnergyComponentType()) { - case CAPACITOR: - capacitors.put(l, component); - break; - case CONSUMER: - consumers.put(l, component); - break; - case GENERATOR: - if (component instanceof EnergyNetProvider) { - generators.put(l, (EnergyNetProvider) component); - } else if (component instanceof SlimefunItem) { - ((SlimefunItem) component).warn("This Item is marked as a GENERATOR but does not implement the interface EnergyNetProvider!"); - } - break; - default: - break; + case CAPACITOR: + capacitors.put(l, component); + break; + case CONSUMER: + consumers.put(l, component); + break; + case GENERATOR: + if (component instanceof EnergyNetProvider) { + generators.put(l, (EnergyNetProvider) component); + } else if (component instanceof SlimefunItem) { + ((SlimefunItem) component).warn("This Item is marked as a GENERATOR but does not implement the interface EnergyNetProvider!"); + } + break; + default: + break; } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BackupService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BackupService.java index cacc4f411..a4827a419 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BackupService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BackupService.java @@ -29,38 +29,51 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; */ public class BackupService implements Runnable { + /** + * The maximum amount of backups to maintain + */ private static final int MAX_BACKUPS = 20; + /** + * Our {@link DateTimeFormatter} for formatting file names. + */ private final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm", Locale.ROOT); + + /** + * The directory in which to create the backups + */ private final File directory = new File("data-storage/Slimefun/block-backups"); @Override public void run() { - List backups = Arrays.asList(directory.listFiles()); + // Make sure that the directory exists. + if (directory.exists()) { + List backups = Arrays.asList(directory.listFiles()); - if (backups.size() > MAX_BACKUPS) { - try { - purgeBackups(backups); - } catch (IOException e) { - SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e); - } - } - - File file = new File(directory, format.format(LocalDateTime.now()) + ".zip"); - - if (!file.exists()) { - try { - if (file.createNewFile()) { - try (ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file))) { - createBackup(output); - } - - SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName()); - } else { - SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName()); + if (backups.size() > MAX_BACKUPS) { + try { + purgeBackups(backups); + } catch (IOException e) { + SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e); + } + } + + File file = new File(directory, format.format(LocalDateTime.now()) + ".zip"); + + if (!file.exists()) { + try { + if (file.createNewFile()) { + try (ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file))) { + createBackup(output); + } + + SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName()); + } else { + SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName()); + } + } catch (IOException x) { + SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion()); } - } catch (IOException x) { - SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion()); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java index c525d312e..462ec8f04 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java @@ -138,29 +138,29 @@ public class BlockDataService implements Keyed { } switch (type) { - case PLAYER_HEAD: - case PLAYER_WALL_HEAD: - case CHEST: - case DISPENSER: - case BREWING_STAND: - case DROPPER: - case FURNACE: - case BLAST_FURNACE: - case HOPPER: - case LECTERN: - case JUKEBOX: - case ENDER_CHEST: - case ENCHANTING_TABLE: - case DAYLIGHT_DETECTOR: - case SMOKER: - case BARREL: - case SPAWNER: - case BEACON: - // All of the above Materials are Tile Entities - return true; - default: - // Otherwise we assume they're not Tile Entities - return false; + case PLAYER_HEAD: + case PLAYER_WALL_HEAD: + case CHEST: + case DISPENSER: + case BREWING_STAND: + case DROPPER: + case FURNACE: + case BLAST_FURNACE: + case HOPPER: + case LECTERN: + case JUKEBOX: + case ENDER_CHEST: + case ENCHANTING_TABLE: + case DAYLIGHT_DETECTOR: + case SMOKER: + case BARREL: + case SPAWNER: + case BEACON: + // All of the above Materials are Tile Entities + return true; + default: + // Otherwise we assume they're not Tile Entities + return false; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java index 694f1b352..ccc8785ab 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MinecraftRecipeService.java @@ -1,6 +1,7 @@ package io.github.thebusybiscuit.slimefun4.core.services; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -10,6 +11,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; import org.bukkit.Server; import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.ItemStack; @@ -34,9 +38,19 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunG */ public class MinecraftRecipeService { + /** + * Our {@link Plugin} instance + */ private final Plugin plugin; + + /** + * The subscriber list for the {@link RecipeSnapshot}. + */ private final List> subscriptions = new LinkedList<>(); + /** + * Our {@link RecipeSnapshot} - The centerpiece of this class. + */ private RecipeSnapshot snapshot; /** @@ -115,6 +129,7 @@ public class MinecraftRecipeService { * * @param recipe * The {@link Recipe} to get the shape from + * * @return An Array of {@link RecipeChoice} representing the shape of this {@link Recipe} */ @Nonnull @@ -149,6 +164,7 @@ public class MinecraftRecipeService { * * @param item * The {@link ItemStack} for which to get the recipes + * * @return An array of {@link Recipe Recipes} to craft the given {@link ItemStack} */ @Nonnull @@ -160,4 +176,27 @@ public class MinecraftRecipeService { } } + /** + * This returns the corresponding {@link Keyed} {@link Recipe} for the given {@link NamespacedKey}. + * If no {@link Recipe} was found, null will be returned. + * This is a significantly faster method over {@link Bukkit#getRecipe(NamespacedKey)} since we + * operate on a cached {@link HashMap} + * + * @param key + * The {@link NamespacedKey} + * + * @return The corresponding {@link Recipe} or null + */ + @Nullable + public Recipe getRecipe(@Nonnull NamespacedKey key) { + Validate.notNull(key, "The NamespacedKey should not be null"); + + if (snapshot != null) { + // We operate on a cached HashMap which is much faster than Bukkit's method. + return snapshot.getRecipe(key); + } else { + return Bukkit.getRecipe(key); + } + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java index 79523c45a..02f00f8f8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java @@ -26,6 +26,9 @@ import io.github.thebusybiscuit.slimefun4.api.SlimefunBranch; import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Lists.RecipeType; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; /** * This is an abstract parent class of {@link LocalizationService}. @@ -215,76 +218,84 @@ public abstract class SlimefunLocalization extends Localization implements Keyed } @Override - public void sendMessage(CommandSender sender, String key, boolean addPrefix) { + public void sendMessage(CommandSender recipient, String key, boolean addPrefix) { String prefix = addPrefix ? getPrefix() : ""; - if (sender instanceof Player) { - sender.sendMessage(ChatColors.color(prefix + getMessage((Player) sender, key))); + if (recipient instanceof Player) { + recipient.sendMessage(ChatColors.color(prefix + getMessage((Player) recipient, key))); } else { - sender.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + getMessage(key)))); + recipient.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + getMessage(key)))); } } - @Override - public void sendMessage(CommandSender sender, String key) { - sendMessage(sender, key, true); - } + public void sendActionbarMessage(@Nonnull Player player, @Nonnull String key, boolean addPrefix) { + String prefix = addPrefix ? getPrefix() : ""; + String message = ChatColors.color(prefix + getMessage(player, key)); - public void sendMessage(CommandSender sender, String key, UnaryOperator function) { - sendMessage(sender, key, true, function); + BaseComponent[] components = TextComponent.fromLegacyText(message); + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, components); } @Override - public void sendMessage(CommandSender sender, String key, boolean addPrefix, UnaryOperator function) { + public void sendMessage(CommandSender recipient, String key) { + sendMessage(recipient, key, true); + } + + public void sendMessage(CommandSender recipient, String key, UnaryOperator function) { + sendMessage(recipient, key, true, function); + } + + @Override + public void sendMessage(CommandSender recipient, String key, boolean addPrefix, UnaryOperator function) { if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) { return; } String prefix = addPrefix ? getPrefix() : ""; - if (sender instanceof Player) { - sender.sendMessage(ChatColors.color(prefix + function.apply(getMessage((Player) sender, key)))); + if (recipient instanceof Player) { + recipient.sendMessage(ChatColors.color(prefix + function.apply(getMessage((Player) recipient, key)))); } else { - sender.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + function.apply(getMessage(key))))); + recipient.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + function.apply(getMessage(key))))); } } @Override - public void sendMessages(CommandSender sender, String key) { + public void sendMessages(CommandSender recipient, String key) { String prefix = getPrefix(); - if (sender instanceof Player) { - for (String translation : getMessages((Player) sender, key)) { + if (recipient instanceof Player) { + for (String translation : getMessages((Player) recipient, key)) { String message = ChatColors.color(prefix + translation); - sender.sendMessage(message); + recipient.sendMessage(message); } } else { for (String translation : getMessages(key)) { String message = ChatColors.color(prefix + translation); - sender.sendMessage(ChatColor.stripColor(message)); + recipient.sendMessage(ChatColor.stripColor(message)); } } } @Override - public void sendMessages(CommandSender sender, String key, boolean addPrefix, UnaryOperator function) { + public void sendMessages(CommandSender recipient, String key, boolean addPrefix, UnaryOperator function) { String prefix = addPrefix ? getPrefix() : ""; - if (sender instanceof Player) { - for (String translation : getMessages((Player) sender, key)) { + if (recipient instanceof Player) { + for (String translation : getMessages((Player) recipient, key)) { String message = ChatColors.color(prefix + function.apply(translation)); - sender.sendMessage(message); + recipient.sendMessage(message); } } else { for (String translation : getMessages(key)) { String message = ChatColors.color(prefix + function.apply(translation)); - sender.sendMessage(ChatColor.stripColor(message)); + recipient.sendMessage(ChatColor.stripColor(message)); } } } - public void sendMessages(CommandSender sender, String key, UnaryOperator function) { - sendMessages(sender, key, true, function); + public void sendMessages(CommandSender recipient, String key, UnaryOperator function) { + sendMessages(recipient, key, true, function); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java index 9d668b69c..d717f4027 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java @@ -38,6 +38,7 @@ public class Translators { addTranslator("NinoFutur", SupportedLanguage.FRENCH, true); addTranslator("TheRetix", SupportedLanguage.FRENCH, true); addTranslator("Aeris1One", SupportedLanguage.FRENCH, true); + addTranslator("Aomitsu", SupportedLanguage.FRENCH, true); // Translators - Italian addTranslator("xXDOTTORXx", SupportedLanguage.ITALIAN, true); @@ -47,6 +48,14 @@ public class Translators { addTranslator("dracrus", SupportedLanguage.ITALIAN, true); addTranslator("prolletto64", SupportedLanguage.ITALIAN, true); + // Translators - Spanish + addTranslator("Luu7", "_Luu", SupportedLanguage.SPANISH, true); + addTranslator("Vravinite", SupportedLanguage.SPANISH, true); + addTranslator("NotUmBr4", SupportedLanguage.SPANISH, true); + addTranslator("dbzjjoe", SupportedLanguage.SPANISH, true); + addTranslator("DaHolyCheese", SupportedLanguage.SPANISH, true); + addTranslator("d-l-n", SupportedLanguage.SPANISH, true); + // Translators - Latvian addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true); @@ -81,6 +90,9 @@ public class Translators { addTranslator("MrFriggo", SupportedLanguage.CZECH, true); addTranslator("100petr", SupportedLanguage.CZECH, true); addTranslator("frfole", SupportedLanguage.CZECH, true); + addTranslator("bobhenl", SupportedLanguage.CZECH, true); + addTranslator("janvrska", SupportedLanguage.CZECH, true); + addTranslator("LirCZE", SupportedLanguage.CZECH, true); // Translators - Russian addTranslator("SoSeDiK", SupportedLanguage.RUSSIAN, false); @@ -91,13 +103,6 @@ public class Translators { // Translators - Ukrainian addTranslator("SoSeDiK", SupportedLanguage.UKRAINIAN, false); - // Translators - Spanish - addTranslator("Luu7", "_Luu", SupportedLanguage.SPANISH, true); - addTranslator("Vravinite", SupportedLanguage.SPANISH, true); - addTranslator("NotUmBr4", SupportedLanguage.SPANISH, true); - addTranslator("dbzjjoe", SupportedLanguage.SPANISH, true); - addTranslator("DaHolyCheese", SupportedLanguage.SPANISH, true); - // Translators - Swedish addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false); addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true); @@ -109,6 +114,7 @@ public class Translators { addTranslator("milvantiou", SupportedLanguage.DUTCH, true); addTranslator("Sven313D", SupportedLanguage.DUTCH, true); addTranslator("TypischTeun", SupportedLanguage.DUTCH, true); + addTranslator("peppower", SupportedLanguage.DUTCH, true); // Translators - Danish addTranslator("Mini-kun", SupportedLanguage.DANISH, true); @@ -123,6 +129,7 @@ public class Translators { addTranslator("StarWishsama", "StarWish_Sama", SupportedLanguage.CHINESE_CHINA, false); addTranslator("Rothes", SupportedLanguage.CHINESE_CHINA, true); addTranslator("Chihsiao", SupportedLanguage.CHINESE_CHINA, true); + addTranslator("Jiejue233", SupportedLanguage.CHINESE_CHINA, true); // Translators - Chinese (Taiwan) addTranslator("BrineYT", "HeroBrineKing", SupportedLanguage.CHINESE_TAIWAN, true); @@ -137,6 +144,7 @@ public class Translators { addTranslator("Eylonnn", SupportedLanguage.HEBREW, true); addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false); addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true); + addTranslator("PaladinBear", SupportedLanguage.HEBREW, true); addTranslator("Molioron", SupportedLanguage.HEBREW, true); addTranslator("McAlmog", SupportedLanguage.HEBREW, true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java index 74d3a3f2d..a9ee7b170 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java @@ -676,6 +676,7 @@ public final class SlimefunItems { public static final SlimefunItemStack ELECTRIC_ORE_GRINDER = new SlimefunItemStack("ELECTRIC_ORE_GRINDER", Material.FURNACE, "&cElectric Ore Grinder", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12)); public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_2 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_2", Material.FURNACE, "&cElectric Ore Grinder &7(&eII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(4), LoreBuilder.powerPerSecond(30)); + public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_3 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_3", Material.FURNACE, "&cElectric Ore Grinder &7(&eIII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(10), LoreBuilder.powerPerSecond(90)); public static final SlimefunItemStack ELECTRIC_INGOT_PULVERIZER = new SlimefunItemStack("ELECTRIC_INGOT_PULVERIZER", Material.FURNACE, "&cElectric Ingot Pulverizer", "", "&fPulverizes Ingots into Dust", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(14)); public static final SlimefunItemStack AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10)); public static final SlimefunItemStack AUTO_ENCHANTER = new SlimefunItemStack("AUTO_ENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Enchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18)); @@ -840,7 +841,9 @@ public final class SlimefunItems { public static final SlimefunItemStack ELECTRIC_INGOT_FACTORY_2 = new SlimefunItemStack("ELECTRIC_INGOT_FACTORY_2", Material.RED_TERRACOTTA, "&cElectric Ingot Factory &7(&eII&7)", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.speed(2), LoreBuilder.powerPerSecond(14)); public static final SlimefunItemStack ELECTRIC_INGOT_FACTORY_3 = new SlimefunItemStack("ELECTRIC_INGOT_FACTORY_3", Material.RED_TERRACOTTA, "&cElectric Ingot Factory &7(&eIII&7)", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(8), LoreBuilder.powerPerSecond(40)); + @Deprecated public static final SlimefunItemStack AUTOMATED_CRAFTING_CHAMBER = new SlimefunItemStack("AUTOMATED_CRAFTING_CHAMBER", Material.CRAFTING_TABLE, "&6Automated Crafting Chamber", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &710 J/Item"); + public static final SlimefunItemStack FLUID_PUMP = new SlimefunItemStack("FLUID_PUMP", Material.BLUE_TERRACOTTA, "&9Fluid Pump", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &732 J/Block"); public static final SlimefunItemStack CHARGING_BENCH = new SlimefunItemStack("CHARGING_BENCH", Material.CRAFTING_TABLE, "&6Charging Bench", "", "&fCharges Items such as Jetpacks", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.MACHINE), LoreBuilder.powerBuffer(128), "&8\u21E8 &e\u26A1 &7Energy Loss: &c50%"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java index 74c51bbe4..1f6e88ea8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java @@ -131,14 +131,26 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu; */ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { + /** + * Our static instance of {@link SlimefunPlugin}. + * Make sure to clean this up in {@link #onDisable()} ! + */ private static SlimefunPlugin instance; + /** + * Keep track of which {@link MinecraftVersion} we are on. + */ private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN; + + /** + * Keep track of whether this is a fresh install or a regular boot up. + */ private boolean isNewlyInstalled = false; + // Various things we need private final SlimefunRegistry registry = new SlimefunRegistry(); - private final TickerTask ticker = new TickerTask(); private final SlimefunCommand command = new SlimefunCommand(this); + private final TickerTask ticker = new TickerTask(); // Services - Systems that fulfill certain tasks, treat them as a black box private final CustomItemDataService itemDataService = new CustomItemDataService(this, "slimefun_item"); @@ -154,10 +166,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this); private final HologramsService hologramsService = new HologramsService(this); + // Some other things we need private final IntegrationsManager integrations = new IntegrationsManager(this); private final SlimefunProfiler profiler = new SlimefunProfiler(); private final GPSNetwork gpsNetwork = new GPSNetwork(this); + // Even more things we need private NetworkManager networkManager; private LocalizationService local; @@ -234,6 +248,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private void onPluginStart() { long timestamp = System.nanoTime(); + // Check if Paper (<3) is installed if (PaperLib.isPaper()) { getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied."); } else { @@ -259,6 +274,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { int networkSize = config.getInt("networks.max-size"); + // Make sure that the network size is a valid input if (networkSize < 1) { getLogger().log(Level.WARNING, "Your 'networks.max-size' setting is misconfigured! It must be at least 1, it was set to: {0}", networkSize); networkSize = 1; @@ -362,8 +378,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { Bukkit.getScheduler().cancelTasks(this); // Finishes all started movements/removals of block data - ticker.halt(); - ticker.run(); + try { + ticker.halt(); + ticker.run(); + } catch (Exception x) { + getLogger().log(Level.SEVERE, x, () -> "Something went wrong while disabling the ticker task for Slimefun v" + getDescription().getVersion()); + } // Kill our Profiler Threads profiler.kill(); @@ -619,6 +639,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { new ButcherAndroidListener(this); new NetworkListener(this, networkManager); new HopperListener(this); + new TalismanListener(this); + new SoulboundListener(this); // Bees were added in 1.15 if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) { @@ -640,15 +662,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { bowListener.register(this); backpackListener.register(this); - // Toggleable Listeners for performance reasons - if (config.getBoolean("items.talismans")) { - new TalismanListener(this); - } - - if (config.getBoolean("items.soulbound")) { - new SoulboundListener(this); - } - // Handle Slimefun Guide being given on Join new SlimefunGuideListener(this, config.getBoolean("guide.receive-on-first-join")); @@ -663,7 +676,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { * This (re)loads every {@link SlimefunTag}. */ private void loadTags() { - for (SlimefunTag tag : SlimefunTag.valuesCache) { + for (SlimefunTag tag : SlimefunTag.values()) { try { // Only reload "empty" (or unloaded) Tags if (tag.isEmpty()) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java index 2f8964939..0a1f20420 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/SurvivalSlimefunGuide.java @@ -266,7 +266,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation { SlimefunItem sfitem = category.getItems().get(target); - if (Slimefun.isEnabled(p, sfitem, false)) { + if (!sfitem.isDisabledIn(p.getWorld())) { displaySlimefunItem(menu, category, p, profile, sfitem, page, index); index++; } @@ -613,7 +613,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation { } String lore = Slimefun.hasPermission(p, slimefunItem, false) ? "&fNeeds to be unlocked elsewhere" : "&fNo Permission"; - return Slimefun.hasUnlocked(p, slimefunItem, false) ? item : new CustomItem(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", lore); + return slimefunItem.canUse(p, false) ? item : new CustomItem(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", lore); } else { return item; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ButcherAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ButcherAndroid.java index 51c458d5a..77bb55601 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ButcherAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ButcherAndroid.java @@ -38,20 +38,20 @@ public class ButcherAndroid extends ProgrammableAndroid { boolean attack = false; switch (face) { - case NORTH: - attack = n.getLocation().getZ() < b.getZ(); - break; - case EAST: - attack = n.getLocation().getX() > b.getX(); - break; - case SOUTH: - attack = n.getLocation().getZ() > b.getZ(); - break; - case WEST: - attack = n.getLocation().getX() < b.getX(); - break; - default: - break; + case NORTH: + attack = n.getLocation().getZ() < b.getZ(); + break; + case EAST: + attack = n.getLocation().getX() > b.getX(); + break; + case SOUTH: + attack = n.getLocation().getZ() > b.getZ(); + break; + case WEST: + attack = n.getLocation().getX() < b.getX(); + break; + default: + break; } if (attack) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java index 44948ab4b..1bafdcd3f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java @@ -64,22 +64,22 @@ public class FarmerAndroid extends ProgrammableAndroid { Random random = ThreadLocalRandom.current(); switch (crop) { - case WHEAT: - return new ItemStack(Material.WHEAT, random.nextInt(2) + 1); - case POTATOES: - return new ItemStack(Material.POTATO, random.nextInt(3) + 1); - case CARROTS: - return new ItemStack(Material.CARROT, random.nextInt(3) + 1); - case BEETROOTS: - return new ItemStack(Material.BEETROOT, random.nextInt(3) + 1); - case COCOA: - return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1); - case NETHER_WART: - return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1); - case SWEET_BERRY_BUSH: - return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1); - default: - return null; + case WHEAT: + return new ItemStack(Material.WHEAT, random.nextInt(2) + 1); + case POTATOES: + return new ItemStack(Material.POTATO, random.nextInt(3) + 1); + case CARROTS: + return new ItemStack(Material.CARROT, random.nextInt(3) + 1); + case BEETROOTS: + return new ItemStack(Material.BEETROOT, random.nextInt(3) + 1); + case COCOA: + return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1); + case NETHER_WART: + return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1); + case SWEET_BERRY_BUSH: + return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1); + default: + return null; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 525739b61..c98ad0817 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -194,14 +194,14 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, */ public AndroidFuelSource getFuelSource() { switch (getTier()) { - case 1: - return AndroidFuelSource.SOLID; - case 2: - return AndroidFuelSource.LIQUID; - case 3: - return AndroidFuelSource.NUCLEAR; - default: - throw new IllegalStateException("Cannot convert the following Android tier to a fuel type: " + getTier()); + case 1: + return AndroidFuelSource.SOLID; + case 2: + return AndroidFuelSource.LIQUID; + case 3: + return AndroidFuelSource.NUCLEAR; + default: + throw new IllegalStateException("Cannot convert the following Android tier to a fuel type: " + getTier()); } } @@ -564,38 +564,38 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, private void registerDefaultFuelTypes() { switch (getFuelSource()) { - case SOLID: - registerFuelType(new MachineFuel(80, new ItemStack(Material.COAL_BLOCK))); - registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD))); - registerFuelType(new MachineFuel(70, new ItemStack(Material.DRIED_KELP_BLOCK))); + case SOLID: + registerFuelType(new MachineFuel(80, new ItemStack(Material.COAL_BLOCK))); + registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD))); + registerFuelType(new MachineFuel(70, new ItemStack(Material.DRIED_KELP_BLOCK))); - // Coal & Charcoal - registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL))); - registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL))); + // Coal & Charcoal + registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL))); + registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL))); - // Logs - for (Material mat : Tag.LOGS.getValues()) { - registerFuelType(new MachineFuel(2, new ItemStack(mat))); - } + // Logs + for (Material mat : Tag.LOGS.getValues()) { + registerFuelType(new MachineFuel(2, new ItemStack(mat))); + } - // Wooden Planks - for (Material mat : Tag.PLANKS.getValues()) { - registerFuelType(new MachineFuel(1, new ItemStack(mat))); - } + // Wooden Planks + for (Material mat : Tag.PLANKS.getValues()) { + registerFuelType(new MachineFuel(1, new ItemStack(mat))); + } - break; - case LIQUID: - registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET))); - registerFuelType(new MachineFuel(200, SlimefunItems.OIL_BUCKET)); - registerFuelType(new MachineFuel(500, SlimefunItems.FUEL_BUCKET)); - break; - case NUCLEAR: - registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM)); - registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM)); - registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM)); - break; - default: - throw new IllegalStateException("Unhandled Fuel Source: " + getFuelSource()); + break; + case LIQUID: + registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET))); + registerFuelType(new MachineFuel(200, SlimefunItems.OIL_BUCKET)); + registerFuelType(new MachineFuel(500, SlimefunItems.FUEL_BUCKET)); + break; + case NUCLEAR: + registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM)); + registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM)); + registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM)); + break; + default: + throw new IllegalStateException("Unhandled Fuel Source: " + getFuelSource()); } } @@ -685,26 +685,26 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, BlockFace face = rotationData == null ? BlockFace.NORTH : BlockFace.valueOf(rotationData); switch (instruction) { - case START: - case WAIT: - // We are "waiting" here, so we only move a step forward - BlockStorage.addBlockInfo(b, "index", String.valueOf(index)); - break; - case REPEAT: - // "repeat" just means, we reset our index - BlockStorage.addBlockInfo(b, "index", String.valueOf(0)); - break; - case CHOP_TREE: - // We only move to the next step if we finished chopping wood - if (chopTree(b, inv, face)) { + case START: + case WAIT: + // We are "waiting" here, so we only move a step forward BlockStorage.addBlockInfo(b, "index", String.valueOf(index)); - } - break; - default: - // We set the index here in advance to fix moving android issues - BlockStorage.addBlockInfo(b, "index", String.valueOf(index)); - instruction.execute(this, b, inv, face); - break; + break; + case REPEAT: + // "repeat" just means, we reset our index + BlockStorage.addBlockInfo(b, "index", String.valueOf(0)); + break; + case CHOP_TREE: + // We only move to the next step if we finished chopping wood + if (chopTree(b, inv, face)) { + BlockStorage.addBlockInfo(b, "index", String.valueOf(index)); + } + break; + default: + // We set the index here in advance to fix moving android issues + BlockStorage.addBlockInfo(b, "index", String.valueOf(index)); + instruction.execute(this, b, inv, face); + break; } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java index 2d79132b2..b6c532e37 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java @@ -1,8 +1,11 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; import java.util.List; -import java.util.Optional; import java.util.UUID; +import java.util.function.Predicate; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.Bukkit; import org.bukkit.Effect; @@ -14,9 +17,10 @@ import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.blocks.Vein; -import io.github.thebusybiscuit.cscorelib2.materials.MaterialConverter; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; +import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.api.BlockStorage; @@ -59,6 +63,7 @@ public class WoodcutterAndroid extends ProgrammableAndroid { return true; } + @ParametersAreNonnullByDefault private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) { ItemStack drop = new ItemStack(log.getType()); @@ -67,13 +72,95 @@ public class WoodcutterAndroid extends ProgrammableAndroid { log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType()); if (log.getY() == android.getRelative(face).getY()) { - Optional sapling = MaterialConverter.getSaplingFromLog(log.getType()); - - sapling.ifPresent(log::setType); + replant(log); } else { log.setType(Material.AIR); } } } + private void replant(@Nonnull Block block) { + Material logType = block.getType(); + Material saplingType = null; + Predicate soilRequirement = null; + + switch (logType) { + case OAK_LOG: + case OAK_WOOD: + case STRIPPED_OAK_LOG: + case STRIPPED_OAK_WOOD: + saplingType = Material.OAK_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + case BIRCH_LOG: + case BIRCH_WOOD: + case STRIPPED_BIRCH_LOG: + case STRIPPED_BIRCH_WOOD: + saplingType = Material.BIRCH_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + case JUNGLE_LOG: + case JUNGLE_WOOD: + case STRIPPED_JUNGLE_LOG: + case STRIPPED_JUNGLE_WOOD: + saplingType = Material.JUNGLE_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + case SPRUCE_LOG: + case SPRUCE_WOOD: + case STRIPPED_SPRUCE_LOG: + case STRIPPED_SPRUCE_WOOD: + saplingType = Material.SPRUCE_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + case ACACIA_LOG: + case ACACIA_WOOD: + case STRIPPED_ACACIA_LOG: + case STRIPPED_ACACIA_WOOD: + saplingType = Material.ACACIA_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + case DARK_OAK_LOG: + case DARK_OAK_WOOD: + case STRIPPED_DARK_OAK_LOG: + case STRIPPED_DARK_OAK_WOOD: + saplingType = Material.DARK_OAK_SAPLING; + soilRequirement = SlimefunTag.DIRT_VARIANTS::isTagged; + break; + default: + break; + } + + if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) { + switch (logType) { + case CRIMSON_STEM: + case CRIMSON_HYPHAE: + case STRIPPED_CRIMSON_STEM: + case STRIPPED_CRIMSON_HYPHAE: + saplingType = Material.CRIMSON_FUNGUS; + soilRequirement = SlimefunTag.FUNGUS_SOIL::isTagged; + break; + case WARPED_STEM: + case WARPED_HYPHAE: + case STRIPPED_WARPED_STEM: + case STRIPPED_WARPED_HYPHAE: + saplingType = Material.WARPED_FUNGUS; + soilRequirement = SlimefunTag.FUNGUS_SOIL::isTagged; + break; + default: + break; + } + } + + if (saplingType != null && soilRequirement != null) { + if (soilRequirement.test(block.getRelative(BlockFace.DOWN).getType())) { + // Replant the block + block.setType(saplingType); + } else { + // Simply drop the sapling if the soil does not fit + block.getWorld().dropItemNaturally(block.getLocation(), new ItemStack(saplingType)); + } + } + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java index f5800321d..ea384e019 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java @@ -3,6 +3,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.blocks; import java.util.List; import java.util.UUID; +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Location; @@ -13,10 +16,10 @@ import org.bukkit.block.Block; import org.bukkit.block.Dispenser; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; @@ -47,15 +50,17 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; */ public class BlockPlacer extends SlimefunItem { - private final ItemSetting> blacklist = new MaterialTagSetting("unplaceable-blocks", SlimefunTag.UNBREAKABLE_MATERIALS); + private final ItemSetting> unplaceableBlocks = new MaterialTagSetting("unplaceable-blocks", SlimefunTag.UNBREAKABLE_MATERIALS); + @ParametersAreNonnullByDefault public BlockPlacer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(category, item, recipeType, recipe); - addItemSetting(blacklist); + addItemSetting(unplaceableBlocks); addItemHandler(onPlace(), onBlockDispense()); } + @Nonnull private BlockPlaceHandler onPlace() { return new BlockPlaceHandler(false) { @@ -69,6 +74,7 @@ public class BlockPlacer extends SlimefunItem { }; } + @Nonnull private BlockDispenseHandler onBlockDispense() { return (e, dispenser, facedBlock, machine) -> { if (!hasPermission(dispenser, facedBlock)) { @@ -79,7 +85,7 @@ public class BlockPlacer extends SlimefunItem { Material material = e.getItem().getType(); if (SlimefunTag.SHULKER_BOXES.isTagged(material)) { - /** + /* * Since vanilla Dispensers can already place Shulker boxes, * we simply fallback to the vanilla behaviour. */ @@ -89,7 +95,7 @@ public class BlockPlacer extends SlimefunItem { e.setCancelled(true); if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) { - /** + /* * Some materials cannot be reliably placed, like beds, * it would look kinda wonky, so we just ignore these altogether. * The event has already been cancelled too, so they won't drop. @@ -97,7 +103,7 @@ public class BlockPlacer extends SlimefunItem { return; } - if (facedBlock.isEmpty() && !isBlacklisted(material) && dispenser.getInventory().getViewers().isEmpty()) { + if (facedBlock.isEmpty() && isAllowed(material) && dispenser.getInventory().getViewers().isEmpty()) { SlimefunItem item = SlimefunItem.getByItem(e.getItem()); if (item != null) { @@ -123,11 +129,12 @@ public class BlockPlacer extends SlimefunItem { * * @return Whether this action is permitted or not */ + @ParametersAreNonnullByDefault private boolean hasPermission(Dispenser dispenser, Block target) { String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner"); if (owner == null) { - /** + /* * If no owner was set, then we will fallback to the previous behaviour: * Allowing block placers to bypass protection, newly placed Block placers * will respect protection plugins. @@ -135,20 +142,30 @@ public class BlockPlacer extends SlimefunItem { return true; } + // Get the corresponding OfflinePlayer OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner)); return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK); } - private boolean isBlacklisted(Material type) { - for (String blockType : blacklist.getValue()) { + /** + * This checks if the given {@link Material} is allowed to be placed. + * + * @param type + * The {@link Material} to check + * + * @return Whether placing this {@link Material} is allowed + */ + private boolean isAllowed(@Nonnull Material type) { + for (String blockType : unplaceableBlocks.getValue()) { if (type.toString().equals(blockType)) { - return true; + return false; } } - return false; + return true; } + @ParametersAreNonnullByDefault private void placeSlimefunBlock(SlimefunItem sfItem, ItemStack item, Block block, Dispenser dispenser) { BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, block); Bukkit.getPluginManager().callEvent(e); @@ -156,68 +173,78 @@ public class BlockPlacer extends SlimefunItem { if (!e.isCancelled()) { boolean hasItemHandler = sfItem.callItemHandler(BlockPlaceHandler.class, handler -> { if (handler.isBlockPlacerAllowed()) { - block.setType(item.getType()); - block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType()); + schedulePlacement(block, dispenser.getInventory(), item, () -> { + block.setType(item.getType()); + BlockStorage.store(block, sfItem.getId()); - BlockStorage.store(block, sfItem.getId()); - handler.onBlockPlacerPlace(e); - - if (dispenser.getInventory().containsAtLeast(item, 2)) { - dispenser.getInventory().removeItem(new CustomItem(item, 1)); - } else { - SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L); - } + handler.onBlockPlacerPlace(e); + }); } }); if (!hasItemHandler) { - block.setType(item.getType()); - block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType()); - - BlockStorage.store(block, sfItem.getId()); - - if (dispenser.getInventory().containsAtLeast(item, 2)) { - dispenser.getInventory().removeItem(new CustomItem(item, 1)); - } else { - SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L); - } + schedulePlacement(block, dispenser.getInventory(), item, () -> { + block.setType(item.getType()); + BlockStorage.store(block, sfItem.getId()); + }); } } } + @ParametersAreNonnullByDefault private void placeBlock(ItemStack item, Block facedBlock, Dispenser dispenser) { BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, facedBlock); Bukkit.getPluginManager().callEvent(e); if (!e.isCancelled()) { - facedBlock.setType(item.getType()); + schedulePlacement(facedBlock, dispenser.getInventory(), item, () -> { + facedBlock.setType(item.getType()); - if (item.hasItemMeta()) { - ItemMeta meta = item.getItemMeta(); + if (item.hasItemMeta()) { + ItemMeta meta = item.getItemMeta(); - if (meta.hasDisplayName()) { - BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false); + if (meta.hasDisplayName()) { + BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false); - if ((blockState.getState() instanceof Nameable)) { - Nameable nameable = ((Nameable) blockState.getState()); - nameable.setCustomName(meta.getDisplayName()); + if ((blockState.getState() instanceof Nameable)) { + Nameable nameable = ((Nameable) blockState.getState()); + nameable.setCustomName(meta.getDisplayName()); - if (blockState.isSnapshot()) { - // Update block state after changing name - blockState.getState().update(true, false); + if (blockState.isSnapshot()) { + // Update block state after changing name + blockState.getState().update(true, false); + } } } + } - - } - - facedBlock.getWorld().playEffect(facedBlock.getLocation(), Effect.STEP_SOUND, item.getType()); - - if (dispenser.getInventory().containsAtLeast(item, 2)) { - dispenser.getInventory().removeItem(new CustomItem(item, 1)); - } else { - SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L); - } + }); } } + + @ParametersAreNonnullByDefault + private void schedulePlacement(Block b, Inventory inv, ItemStack item, Runnable runnable) { + // We need to delay this due to Dispenser-Inventory synchronization issues in Spigot. + SlimefunPlugin.runSync(() -> { + // Make sure the Block has not been occupied yet + if (b.isEmpty()) { + // Only remove 1 item. + ItemStack removedItem = item.clone(); + removedItem.setAmount(1); + + // Play particles + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, item.getType()); + + // Make sure the item was actually removed (fixes #2817) + + try { + if (inv.removeItem(removedItem).isEmpty()) { + runnable.run(); + } + } catch (Exception x) { + error("An Exception was thrown while a BlockPlacer was performing its action", x); + } + } + }, 2L); + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/MultiTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/MultiTool.java index 4e0e59903..4494fb95c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/MultiTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/MultiTool.java @@ -110,14 +110,14 @@ public class MultiTool extends SlimefunItem implements Rechargeable { return (e, item, offhand) -> { // Fixes #2217 - Prevent them from being used to shear entities switch (e.getRightClicked().getType()) { - case MUSHROOM_COW: - case SHEEP: - case SNOWMAN: - SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears"); - e.setCancelled(true); - break; - default: - break; + case MUSHROOM_COW: + case SHEEP: + case SNOWMAN: + SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears"); + e.setCancelled(true); + break; + default: + break; } }; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/AutomatedCraftingChamber.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/AutomatedCraftingChamber.java index 93031d45c..69295f738 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/AutomatedCraftingChamber.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/AutomatedCraftingChamber.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -57,10 +60,11 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I private final Map craftingRecipes = new HashMap<>(); + @ParametersAreNonnullByDefault public AutomatedCraftingChamber(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(category, item, recipeType, recipe); - new BlockMenuPreset(getId(), "&6Automated Crafting Chamber") { + new BlockMenuPreset(getId(), "&4Deprecated item. Do not use.") { @Override public void init() { @@ -94,6 +98,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I @Override public boolean canOpen(Block b, Player p) { + p.sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!"); return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK); } @@ -145,6 +150,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I @Override public void onPlayerPlace(BlockPlaceEvent e) { + e.getPlayer().sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!"); BlockStorage.addBlockInfo(e.getBlock(), "enabled", String.valueOf(false)); } @@ -308,4 +314,4 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I craftingRecipes.put(builder.toString(), RecipeType.getRecipeOutputList(machine, inputs)); } } -} +} \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/BookBinder.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/BookBinder.java index a36478f00..a4dd5e52f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/BookBinder.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/BookBinder.java @@ -23,10 +23,10 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; /** -* Represents Book Binder, a machine that binds multiple enchantments books into one. -* -* @author ProfElements -*/ + * Represents Book Binder, a machine that binds multiple enchantments books into one. + * + * @author ProfElements + */ public class BookBinder extends AContainer { private final ItemSetting bypassVanillaMaxLevel = new ItemSetting<>("bypass-vanilla-max-level", false); @@ -36,29 +36,29 @@ public class BookBinder extends AContainer { @ParametersAreNonnullByDefault public BookBinder(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(category, item, recipeType, recipe); - - addItemSetting(bypassVanillaMaxLevel, hasCustomMaxLevel, customMaxLevel); + + addItemSetting(bypassVanillaMaxLevel, hasCustomMaxLevel, customMaxLevel); } @Override protected MachineRecipe findNextRecipe(BlockMenu menu) { for (int slot : getInputSlots()) { ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]); - ItemStack item = menu.getItemInSlot(slot); - if (isCompatible(item) && isCompatible(target)) { - + + if (isCompatible(item) && isCompatible(target)) { EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) item.getItemMeta(); EnchantmentStorageMeta targetMeta = (EnchantmentStorageMeta) target.getItemMeta(); Map storedItemEnchantments = itemMeta.getStoredEnchants(); Map storedTargetEnchantments = targetMeta.getStoredEnchants(); Map enchantments = combineEnchantments(storedItemEnchantments, storedTargetEnchantments); - + if (enchantments.size() > 0) { ItemStack book = new ItemStack(Material.ENCHANTED_BOOK); EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta(); + for (Map.Entry entry : enchantments.entrySet()) { enchantMeta.addStoredEnchant(entry.getKey(), entry.getValue(), bypassVanillaMaxLevel.getValue()); } @@ -69,7 +69,7 @@ public class BookBinder extends AContainer { book.setItemMeta(enchantMeta); - MachineRecipe recipe = new MachineRecipe(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] {target, item}, new ItemStack[] {book}); + MachineRecipe recipe = new MachineRecipe(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] { target, item }, new ItemStack[] { book }); if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) { return null; @@ -109,8 +109,8 @@ public class BookBinder extends AContainer { private Map combineEnchantments(Map ech1, Map ech2) { Map enchantments = new HashMap<>(); boolean conflicts = false; - enchantments.putAll(ech1); + for (Map.Entry entry : ech2.entrySet()) { for (Map.Entry conflictsWith : enchantments.entrySet()) { if (entry.getKey().conflictsWith(conflictsWith.getKey())) { @@ -122,12 +122,12 @@ public class BookBinder extends AContainer { } } - + if (!conflicts) { enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> { int enchantMaxLevel = entry.getKey().getMaxLevel(); - if (a == b) { + if (a.intValue() == b.intValue()) { if (enchantMaxLevel <= a) { return enchantMaxLevel; } @@ -136,7 +136,6 @@ public class BookBinder extends AContainer { } else { return a + 1; } - } else { int highestLevel = Math.max(a, b); @@ -149,13 +148,13 @@ public class BookBinder extends AContainer { } else { return highestLevel; } - - } - }); - } - } - return enchantments; - + } + }); + } + } + + return enchantments; + } } \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricSmeltery.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricSmeltery.java index a0ce3cd4d..aac0dc718 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricSmeltery.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricSmeltery.java @@ -1,16 +1,5 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; - import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.core.attributes.NotHopperable; @@ -22,13 +11,23 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenu import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; +import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; -import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; /** * The {@link ElectricSmeltery} is an electric version of the standard {@link Smeltery}. @@ -112,12 +111,10 @@ public class ElectricSmeltery extends AContainer implements NotHopperable { processing.remove(b); return true; }); - - this.registerDefaultRecipes(); } private Comparator compareSlots(DirtyChestMenu menu) { - return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount(); + return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount()); } @Override diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/HeatedPressureChamber.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/HeatedPressureChamber.java index 95b62ac1f..5a5d16fc2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/HeatedPressureChamber.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/HeatedPressureChamber.java @@ -1,15 +1,5 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; @@ -22,6 +12,15 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; public class HeatedPressureChamber extends AContainer { @@ -73,12 +72,10 @@ public class HeatedPressureChamber extends AContainer { } } }; - - this.registerDefaultRecipes(); } private Comparator compareSlots(DirtyChestMenu menu) { - return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount(); + return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount()); } @Override diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/reactors/Reactor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/reactors/Reactor.java index 012a8ead2..b4bd009db 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/reactors/Reactor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/reactors/Reactor.java @@ -128,24 +128,24 @@ public abstract class Reactor extends AbstractEnergyProvider implements Hologram ReactorMode mode = getReactorMode(b.getLocation()); switch (mode) { - case GENERATOR: - menu.replaceExistingItem(4, new CustomItem(SlimefunItems.NUCLEAR_REACTOR, "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7\u21E8 Click to change the Focus to &eProduction")); - menu.addMenuClickHandler(4, (p, slot, item, action) -> { - BlockStorage.addBlockInfo(b, MODE, ReactorMode.PRODUCTION.toString()); - updateInventory(menu, b); - return false; - }); - break; - case PRODUCTION: - menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7\u21E8 Click to change the Focus to &ePower Generation")); - menu.addMenuClickHandler(4, (p, slot, item, action) -> { - BlockStorage.addBlockInfo(b, MODE, ReactorMode.GENERATOR.toString()); - updateInventory(menu, b); - return false; - }); - break; - default: - break; + case GENERATOR: + menu.replaceExistingItem(4, new CustomItem(SlimefunItems.NUCLEAR_REACTOR, "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7\u21E8 Click to change the Focus to &eProduction")); + menu.addMenuClickHandler(4, (p, slot, item, action) -> { + BlockStorage.addBlockInfo(b, MODE, ReactorMode.PRODUCTION.toString()); + updateInventory(menu, b); + return false; + }); + break; + case PRODUCTION: + menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7\u21E8 Click to change the Focus to &ePower Generation")); + menu.addMenuClickHandler(4, (p, slot, item, action) -> { + BlockStorage.addBlockInfo(b, MODE, ReactorMode.GENERATOR.toString()); + updateInventory(menu, b); + return false; + }); + break; + default: + break; } BlockMenu port = getAccessPort(b.getLocation()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/EnchantmentRune.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/EnchantmentRune.java index 4ca91cec6..8a08067d4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/EnchantmentRune.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/EnchantmentRune.java @@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunIte import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; /** @@ -66,7 +65,7 @@ public class EnchantmentRune extends SimpleSlimefunItem { public ItemDropHandler getItemHandler() { return (e, p, item) -> { if (isItem(item.getItemStack())) { - if (Slimefun.hasUnlocked(p, this, true)) { + if (canUse(p, true)) { SlimefunPlugin.runSync(() -> { try { addRandomEnchantment(p, item); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/SoulboundRune.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/SoulboundRune.java index dfde7821e..997a08acc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/SoulboundRune.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/runes/SoulboundRune.java @@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes; import java.util.Collection; import java.util.Optional; +import javax.annotation.Nonnull; + import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.entity.Entity; @@ -19,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; /** @@ -47,7 +48,7 @@ public class SoulboundRune extends SimpleSlimefunItem { return (e, p, item) -> { if (isItem(item.getItemStack())) { - if (!Slimefun.hasUnlocked(p, this, true)) { + if (!canUse(p, true)) { return true; } @@ -59,7 +60,7 @@ public class SoulboundRune extends SimpleSlimefunItem { }; } - private void activate(Player p, Item rune) { + private void activate(@Nonnull Player p, @Nonnull Item rune) { // Being sure the entity is still valid and not picked up or whatsoever. if (!rune.isValid()) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/MagicianTalisman.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/MagicianTalisman.java index 2d9959a11..0b6758bbe 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/MagicianTalisman.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/MagicianTalisman.java @@ -1,5 +1,18 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans; +import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment; +import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; +import org.apache.commons.lang.Validate; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -7,20 +20,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.logging.Level; import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import org.apache.commons.lang.Validate; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; -import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment; -import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; - /** * The {@link MagicianTalisman} is a special kind of {@link Talisman} which awards a {@link Player} * with an extra {@link Enchantment} when they enchant their {@link ItemStack}. @@ -30,12 +29,16 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; */ public class MagicianTalisman extends Talisman { + private final ItemSetting allowEnchantmentBooks = new ItemSetting<>("allow-enchantment-books", false); + private final Set enchantments = new HashSet<>(); @ParametersAreNonnullByDefault public MagicianTalisman(SlimefunItemStack item, ItemStack[] recipe) { super(item, recipe, false, false, "magician", 80); + addItemSetting(allowEnchantmentBooks); + for (Enchantment enchantment : Enchantment.values()) { try { for (int i = 1; i <= enchantment.getMaxLevel(); i++) { @@ -70,7 +73,7 @@ public class MagicianTalisman extends Talisman { // @formatter:off List enabled = enchantments.stream() - .filter(e -> e.getEnchantment().canEnchantItem(item)) + .filter(e -> (isEnchantmentBookAllowed() && item.getType() == Material.BOOK) || e.getEnchantment().canEnchantItem(item)) .filter(e -> hasConflicts(existingEnchantments, e)) .filter(TalismanEnchantment::getValue) .collect(Collectors.toList()); @@ -90,4 +93,13 @@ public class MagicianTalisman extends Talisman { return true; } + /** + * This method checks whether enchantment books + * can be given an extra {@link Enchantment} or not. + * + * @return Whether enchantment books can receive an extra {@link Enchantment} + */ + public boolean isEnchantmentBookAllowed() { + return allowEnchantmentBooks.getValue(); + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java index 203ee5b74..8c9f34f6f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/magical/talismans/Talisman.java @@ -9,6 +9,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -33,7 +34,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class Talisman extends SlimefunItem { @@ -113,10 +113,6 @@ public class Talisman extends SlimefunItem { return effects; } - protected String getMessageSuffix() { - return suffix; - } - protected boolean isEventCancelled() { return cancel; } @@ -147,36 +143,44 @@ public class Talisman extends SlimefunItem { } } - private static boolean hasMessage(@Nonnull Talisman talisman) { - return talisman.getMessageSuffix() != null; + @ParametersAreNonnullByDefault + public static boolean trigger(Event e, SlimefunItemStack stack) { + return trigger(e, stack.getItem(), true); } @ParametersAreNonnullByDefault - public static boolean checkFor(Event e, SlimefunItemStack stack) { - return checkFor(e, stack.getItem()); + public static boolean trigger(Event e, SlimefunItemStack stack, boolean sendMessage) { + return trigger(e, stack.getItem(), sendMessage); } @ParametersAreNonnullByDefault - public static boolean checkFor(Event e, SlimefunItem item) { + public static boolean trigger(Event e, SlimefunItem item) { + return trigger(e, item, true); + } + + @ParametersAreNonnullByDefault + public static boolean trigger(Event e, SlimefunItem item, boolean sendMessage) { if (!(item instanceof Talisman)) { return false; } Talisman talisman = (Talisman) item; + if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) { return false; } Player p = getPlayerByEventType(e); - if (p == null || !pass(p, talisman)) { + + if (p == null || !talisman.canEffectsBeApplied(p)) { return false; } ItemStack talismanItem = talisman.getItem(); if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) { - if (Slimefun.hasUnlocked(p, talisman, true)) { - activateTalisman(e, p, p.getInventory(), talisman, talismanItem); + if (talisman.canUse(p, true)) { + activateTalisman(e, p, p.getInventory(), talisman, talismanItem, sendMessage); return true; } else { return false; @@ -185,8 +189,8 @@ public class Talisman extends SlimefunItem { ItemStack enderTalisman = talisman.getEnderVariant(); if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) { - if (Slimefun.hasUnlocked(p, talisman, true)) { - activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman); + if (talisman.canUse(p, true)) { + activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage); return true; } else { return false; @@ -198,11 +202,30 @@ public class Talisman extends SlimefunItem { } @ParametersAreNonnullByDefault - private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem) { + private static void activateTalisman(Event e, Player p, Inventory inv, Talisman talisman, ItemStack talismanItem, boolean sendMessage) { consumeItem(inv, talisman, talismanItem); applyTalismanEffects(p, talisman); cancelEvent(e, talisman); - sendMessage(p, talisman); + + if (sendMessage) { + talisman.sendMessage(p); + } + } + + @ParametersAreNonnullByDefault + private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) { + if (talisman.isConsumable()) { + ItemStack[] contents = inv.getContents(); + + for (int i = 0; i < contents.length; i++) { + ItemStack item = contents[i]; + + if (SlimefunUtils.isItemSimilar(item, talismanItem, true, false)) { + ItemUtils.consumeItem(item, false); + return; + } + } + } } @ParametersAreNonnullByDefault @@ -219,29 +242,63 @@ public class Talisman extends SlimefunItem { } } - @ParametersAreNonnullByDefault - private static void sendMessage(Player p, Talisman talisman) { - if (hasMessage(talisman)) { - SlimefunPlugin.getLocalization().sendMessage(p, "messages.talisman." + talisman.getMessageSuffix(), true); - } + /** + * This returns whether the {@link Talisman} is silent. + * A silent {@link Talisman} will not send a message to a {@link Player} + * when activated. + * + * @return Whether this {@link Talisman} is silent + */ + public boolean isSilent() { + return getMessageSuffix() == null; } - @ParametersAreNonnullByDefault - private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) { - if (talisman.isConsumable()) { - ItemStack[] contents = inv.getContents(); - for (int i = 0; i < contents.length; i++) { - ItemStack item = contents[i]; + @Nullable + protected final String getMessageSuffix() { + return suffix; + } - if (SlimefunUtils.isItemSimilar(item, talismanItem, true, false)) { - ItemUtils.consumeItem(item, false); - return; + /** + * This method sends the given {@link Player} the message of this {@link Talisman}. + * Dependent on the selected config setting, the message will be sent via the actionbar + * or in the chat window. + * + * @param p + * The {@link Player} who shall receive the message + */ + public void sendMessage(@Nonnull Player p) { + Validate.notNull(p, "The Player must not be null."); + + // Check if this Talisman has a message + if (!isSilent()) { + try { + String messageKey = "messages.talisman." + getMessageSuffix(); + + if (SlimefunPlugin.getRegistry().useActionbarForTalismans()) { + // Use the actionbar + SlimefunPlugin.getLocalization().sendActionbarMessage(p, messageKey, false); + } else { + // Send the message via chat + SlimefunPlugin.getLocalization().sendMessage(p, messageKey, true); } + } catch (Exception x) { + error("An Exception was thrown while trying to send a Talisman message", x); } } } - private static Player getPlayerByEventType(Event e) { + private boolean canEffectsBeApplied(@Nonnull Player p) { + for (PotionEffect effect : getEffects()) { + if (effect != null && p.hasPotionEffect(effect.getType())) { + return false; + } + } + + return true; + } + + @Nullable + private static Player getPlayerByEventType(@Nonnull Event e) { if (e instanceof EntityDeathEvent) { return ((EntityDeathEvent) e).getEntity().getKiller(); } else if (e instanceof BlockBreakEvent) { @@ -259,14 +316,4 @@ public class Talisman extends SlimefunItem { return null; } - private static boolean pass(Player p, SlimefunItem talisman) { - for (PotionEffect effect : ((Talisman) talisman).getEffects()) { - if (effect != null && p.hasPotionEffect(effect.getType())) { - return false; - } - } - - return true; - } - } \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java index 632e95f0a..2dd1632a2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/AbstractSmeltery.java @@ -19,7 +19,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.papermc.lib.PaperLib; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; /** @@ -48,7 +47,7 @@ abstract class AbstractSmeltery extends MultiBlockMachine { if (canCraft(inv, inputs, i)) { ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); - if (Slimefun.hasUnlocked(p, output, true)) { + if (SlimefunUtils.canPlayerUseItem(p, output, true)) { Inventory outputInv = findOutputInventory(output, dispBlock, inv); if (outputInv != null) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java index ff68a91e1..7d66099fc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/ArmorForge.java @@ -21,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.papermc.lib.PaperLib; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class ArmorForge extends AbstractCraftingTable { @@ -44,7 +43,7 @@ public class ArmorForge extends AbstractCraftingTable { if (isCraftable(inv, inputs.get(i))) { ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); - if (Slimefun.hasUnlocked(p, output, true)) { + if (SlimefunUtils.canPlayerUseItem(p, output, true)) { craft(p, output, inv, dispenser); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java index a55a804c2..5aeab8fb5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/EnhancedCraftingTable.java @@ -20,7 +20,6 @@ import io.papermc.lib.PaperLib; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class EnhancedCraftingTable extends AbstractCraftingTable { @@ -43,7 +42,7 @@ public class EnhancedCraftingTable extends AbstractCraftingTable { if (isCraftable(inv, inputs.get(i))) { ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); - if (Slimefun.hasUnlocked(p, output, true)) { + if (SlimefunUtils.canPlayerUseItem(p, output, true)) { craft(inv, dispenser, p, b, output); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java index 3c1533a98..54d28c391 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/GrindStone.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.stream.Collectors; import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.Material; import org.bukkit.Sound; @@ -27,6 +28,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class GrindStone extends MultiBlockMachine { + @ParametersAreNonnullByDefault public GrindStone(Category category, SlimefunItemStack item) { super(category, item, new ItemStack[] { null, null, null, null, new ItemStack(Material.OAK_FENCE), null, null, new CustomItem(Material.DISPENSER, "Dispenser (Facing up)"), null }, BlockFace.SELF); } @@ -71,6 +73,9 @@ public class GrindStone extends MultiBlockMachine { recipes.add(new ItemStack(Material.PRISMARINE)); recipes.add(new ItemStack(Material.PRISMARINE_SHARD, 4)); + + recipes.add(new ItemStack(Material.NETHER_WART_BLOCK)); + recipes.add(new ItemStack(Material.NETHER_WART, 9)); } @Override diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java index fd0056e6a..d98935eb1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/MagicWorkbench.java @@ -21,7 +21,6 @@ import io.papermc.lib.PaperLib; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; public class MagicWorkbench extends AbstractCraftingTable { @@ -50,7 +49,7 @@ public class MagicWorkbench extends AbstractCraftingTable { if (isCraftable(inv, inputs.get(i))) { ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); - if (Slimefun.hasUnlocked(p, output, true)) { + if (SlimefunUtils.canPlayerUseItem(p, output, true)) { craft(inv, dispenser, p, b, output); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java index bb857f3d5..87df574ae 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/OreCrusher.java @@ -25,7 +25,6 @@ import io.papermc.lib.PaperLib; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; /** @@ -135,7 +134,7 @@ public class OreCrusher extends MultiBlockMachine { ItemStack adding = RecipeType.getRecipeOutput(this, convert); Inventory outputInv = findOutputInventory(adding, dispBlock, inv); - if (Slimefun.hasUnlocked(p, adding, true)) { + if (SlimefunUtils.canPlayerUseItem(p, adding, true)) { if (outputInv != null) { ItemStack removing = current.clone(); removing.setAmount(convert.getAmount()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java index 157b26954..06ec908ed 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/multiblocks/miner/IndustrialMiner.java @@ -120,21 +120,21 @@ public class IndustrialMiner extends MultiBlockMachine { Random random = ThreadLocalRandom.current(); switch (ore) { - case COAL_ORE: - return new ItemStack(Material.COAL); - case DIAMOND_ORE: - return new ItemStack(Material.DIAMOND); - case EMERALD_ORE: - return new ItemStack(Material.EMERALD); - case NETHER_QUARTZ_ORE: - return new ItemStack(Material.QUARTZ); - case REDSTONE_ORE: - return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); - case LAPIS_ORE: - return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); - default: - // This includes Iron and Gold ore (and Ancient Debris) - return new ItemStack(ore); + case COAL_ORE: + return new ItemStack(Material.COAL); + case DIAMOND_ORE: + return new ItemStack(Material.DIAMOND); + case EMERALD_ORE: + return new ItemStack(Material.EMERALD); + case NETHER_QUARTZ_ORE: + return new ItemStack(Material.QUARTZ); + case REDSTONE_ORE: + return new ItemStack(Material.REDSTONE, 4 + random.nextInt(2)); + case LAPIS_ORE: + return new ItemStack(Material.LAPIS_LAZULI, 4 + random.nextInt(4)); + default: + // This includes Iron and Gold ore (and Ancient Debris) + return new ItemStack(ore); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java index f0919044c..da52e9750 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java @@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools; import java.util.ArrayList; import java.util.List; +import javax.annotation.ParametersAreNonnullByDefault; + import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -12,7 +14,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem; @@ -43,6 +44,7 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla private final ItemSetting damageOnUse = new ItemSetting<>("damage-on-use", true); private final ItemSetting callExplosionEvent = new ItemSetting<>("call-explosion-event", false); + @ParametersAreNonnullByDefault public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(category, item, recipeType, recipe); @@ -59,11 +61,12 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F); List blocks = findBlocks(b); - breakBlocks(p, tool, b, blocks, fortune, drops); + breakBlocks(p, tool, b, blocks, drops); }; } - private void breakBlocks(Player p, ItemStack item, Block b, List blocks, int fortune, List drops) { + @ParametersAreNonnullByDefault + private void breakBlocks(Player p, ItemStack item, Block b, List blocks, List drops) { if (callExplosionEvent.getValue().booleanValue()) { BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0); Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent); @@ -71,14 +74,14 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla if (!blockExplodeEvent.isCancelled()) { for (Block block : blockExplodeEvent.blockList()) { if (canBreak(p, block)) { - breakBlock(p, item, block, fortune, drops); + breakBlock(p, item, block, drops); } } } } else { for (Block block : blocks) { if (canBreak(p, block)) { - breakBlock(p, item, block, fortune, drops); + breakBlock(p, item, block, drops); } } } @@ -122,7 +125,8 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla } } - private void breakBlock(Player p, ItemStack item, Block b, int fortune, List drops) { + @ParametersAreNonnullByDefault + private void breakBlock(Player p, ItemStack item, Block b, List drops) { SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK); Material material = b.getType(); @@ -135,19 +139,8 @@ class ExplosiveTool extends SimpleSlimefunItem implements NotPla if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) { drops.add(BlockStorage.retrieve(b)); } - } else if (material == Material.PLAYER_HEAD || SlimefunTag.SHULKER_BOXES.isTagged(material)) { - b.breakNaturally(item); } else { - boolean applyFortune = SlimefunTag.FORTUNE_COMPATIBLE_ORES.isTagged(material); - - for (ItemStack drop : b.getDrops(getItem())) { - // For some reason this check is necessary with Paper - if (drop != null && drop.getType() != Material.AIR) { - b.getWorld().dropItemNaturally(b.getLocation(), applyFortune ? new CustomItem(drop, fortune) : drop); - } - } - - b.setType(Material.AIR); + b.breakNaturally(item); } damageItem(p, item); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java index 16848bbd7..c2cada5b9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java @@ -96,10 +96,6 @@ public class GoldPan extends SimpleSlimefunItem implements Recip for (GoldPanDrop setting : drops) { randomizer.add(setting.getOutput(), setting.getValue()); } - - if (randomizer.sumWeights() < 100) { - randomizer.add(new ItemStack(Material.AIR), 100 - randomizer.sumWeights()); - } } /** @@ -110,7 +106,10 @@ public class GoldPan extends SimpleSlimefunItem implements Recip */ @Nonnull public ItemStack getRandomOutput() { - return randomizer.getRandom(); + ItemStack item = randomizer.getRandom(); + + // Fixes #2804 + return item != null ? item : new ItemStack(Material.AIR); } @Override @@ -126,12 +125,14 @@ public class GoldPan extends SimpleSlimefunItem implements Recip if (block.isPresent()) { Block b = block.get(); + // Check the clicked block type and for protections if (b.getType() == getTargetMaterial() && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) { ItemStack output = getRandomOutput(); b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType()); b.setType(Material.AIR); + // Make sure that the randomly selected item is not air if (output.getType() != Material.AIR) { b.getWorld().dropItemNaturally(b.getLocation(), output.clone()); } @@ -148,6 +149,7 @@ public class GoldPan extends SimpleSlimefunItem implements Recip * * @return the {@link EntityInteractHandler} of this {@link SlimefunItem} */ + @Nonnull public EntityInteractHandler onEntityInteract() { return (e, item, offHand) -> { if (!(e.getRightClicked() instanceof ItemFrame)) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java index aee48bdf8..b93704cb9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/SwordOfBeheading.java @@ -56,39 +56,39 @@ public class SwordOfBeheading extends SimpleSlimefunItem { Random random = ThreadLocalRandom.current(); switch (e.getEntityType()) { - case ZOMBIE: - if (random.nextInt(100) < chanceZombie.getValue()) { - e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD)); - } - break; - case SKELETON: - if (random.nextInt(100) < chanceSkeleton.getValue()) { - e.getDrops().add(new ItemStack(Material.SKELETON_SKULL)); - } - break; - case CREEPER: - if (random.nextInt(100) < chanceCreeper.getValue()) { - e.getDrops().add(new ItemStack(Material.CREEPER_HEAD)); - } - break; - case WITHER_SKELETON: - if (random.nextInt(100) < chanceWitherSkeleton.getValue()) { - e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL)); - } - break; - case PLAYER: - if (random.nextInt(100) < chancePlayer.getValue()) { - ItemStack skull = new ItemStack(Material.PLAYER_HEAD); + case ZOMBIE: + if (random.nextInt(100) < chanceZombie.getValue()) { + e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD)); + } + break; + case SKELETON: + if (random.nextInt(100) < chanceSkeleton.getValue()) { + e.getDrops().add(new ItemStack(Material.SKELETON_SKULL)); + } + break; + case CREEPER: + if (random.nextInt(100) < chanceCreeper.getValue()) { + e.getDrops().add(new ItemStack(Material.CREEPER_HEAD)); + } + break; + case WITHER_SKELETON: + if (random.nextInt(100) < chanceWitherSkeleton.getValue()) { + e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL)); + } + break; + case PLAYER: + if (random.nextInt(100) < chancePlayer.getValue()) { + ItemStack skull = new ItemStack(Material.PLAYER_HEAD); - ItemMeta meta = skull.getItemMeta(); - ((SkullMeta) meta).setOwningPlayer((Player) e.getEntity()); - skull.setItemMeta(meta); + ItemMeta meta = skull.getItemMeta(); + ((SkullMeta) meta).setOwningPlayer((Player) e.getEntity()); + skull.setItemMeta(meta); - e.getDrops().add(skull); - } - break; - default: - break; + e.getDrops().add(skull); + } + break; + default: + break; } }; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java index 646ed0476..58c7d1a3c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java @@ -41,7 +41,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for providing the core mechanics of the {@link AncientAltar} @@ -105,12 +104,13 @@ public class AncientAltarListener implements Listener { } String id = slimefunBlock.get().getId(); + Player p = e.getPlayer(); if (id.equals(pedestalItem.getId())) { e.cancel(); - usePedestal(b, e.getPlayer()); + usePedestal(b, p); } else if (id.equals(altarItem.getId())) { - if (!Slimefun.hasUnlocked(e.getPlayer(), altarItem, true) || altarsInUse.contains(b.getLocation())) { + if (!altarItem.canUse(p, true) || altarsInUse.contains(b.getLocation())) { e.cancel(); return; } @@ -119,7 +119,7 @@ public class AncientAltarListener implements Listener { altarsInUse.add(b.getLocation()); e.cancel(); - useAltar(b, e.getPlayer()); + useAltar(b, p); } } @@ -212,8 +212,9 @@ public class AncientAltarListener implements Listener { } Optional result = getRecipeOutput(catalyst, input); + if (result.isPresent()) { - if (Slimefun.hasUnlocked(p, result.get(), true)) { + if (SlimefunUtils.canPlayerUseItem(p, result.get(), true)) { List consumed = new ArrayList<>(); consumed.add(catalyst); @@ -248,7 +249,7 @@ public class AncientAltarListener implements Listener { } } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent e) { if (altarItem == null || altarItem.isDisabled()) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java index 99da8142f..8d800cb10 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java @@ -31,7 +31,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.SlimefunBackpack; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for all events centered around a {@link SlimefunBackpack}. @@ -122,7 +121,7 @@ public class BackpackListener implements Listener { @ParametersAreNonnullByDefault public void openBackpack(Player p, ItemStack item, SlimefunBackpack backpack) { if (item.getAmount() == 1) { - if (Slimefun.hasUnlocked(p, backpack, true) && !PlayerProfile.get(p, profile -> openBackpack(p, item, profile, backpack.getSize()))) { + if (backpack.canUse(p, true) && !PlayerProfile.get(p, profile -> openBackpack(p, item, profile, backpack.getSize()))) { SlimefunPlugin.getLocalization().sendMessage(p, "messages.opening-backpack"); } } else { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BeeWingsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BeeWingsListener.java index 3ac4ec600..6fc179556 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BeeWingsListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BeeWingsListener.java @@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.magical.BeeWings; import io.github.thebusybiscuit.slimefun4.implementation.tasks.BeeWingsTask; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for the slow falling effect given to the {@link Player} @@ -44,7 +43,7 @@ public class BeeWingsListener implements Listener { Player player = (Player) e.getEntity(); ItemStack chestplate = player.getInventory().getChestplate(); - if (wings.isItem(chestplate) && Slimefun.hasUnlocked(player, chestplate, true)) { + if (wings.isItem(chestplate) && wings.canUse(player, true)) { new BeeWingsTask(player).scheduleRepeating(3, 1); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 82a322bee..6c5f91fc8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -10,7 +10,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -51,10 +50,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; */ public class BlockListener implements Listener { - private final SlimefunPlugin plugin; - public BlockListener(@Nonnull SlimefunPlugin plugin) { - this.plugin = plugin; plugin.getServer().getPluginManager().registerEvents(this, plugin); } @@ -71,22 +67,14 @@ public class BlockListener implements Listener { if (e.getBlockReplacedState().getType().isAir()) { SlimefunItem sfItem = BlockStorage.check(block); - if (sfItem != null) { - /* - * We can move the TickerTask synchronization to an async task to - * avoid blocking the main Thread here. - */ - Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { - if (!SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) { - for (ItemStack item : sfItem.getDrops()) { - if (item != null && !item.getType().isAir()) { - SlimefunPlugin.runSync(() -> block.getWorld().dropItemNaturally(block.getLocation(), item)); - } - } - - BlockStorage.clearBlockInfo(block); + if (sfItem != null && !SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) { + for (ItemStack item : sfItem.getDrops()) { + if (item != null && !item.getType().isAir()) { + block.getWorld().dropItemNaturally(block.getLocation(), item); } - }); + } + + BlockStorage.clearBlockInfo(block); } } else if (BlockStorage.hasBlockInfo(e.getBlock())) { e.setCancelled(true); @@ -99,7 +87,7 @@ public class BlockListener implements Listener { SlimefunItem sfItem = SlimefunItem.getByItem(item); if (sfItem != null && !(sfItem instanceof NotPlaceable) && Slimefun.isEnabled(e.getPlayer(), sfItem, true)) { - if (!Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) { + if (!sfItem.canUse(e.getPlayer(), true)) { e.setCancelled(true); } else { if (SlimefunPlugin.getBlockDataService().isTileEntity(e.getBlock().getType())) { @@ -124,6 +112,11 @@ public class BlockListener implements Listener { return; } + // Ignore blocks which we have marked as deleted (Fixes #2771) + if (SlimefunPlugin.getTickerTask().isDeletedSoon(e.getBlock().getLocation())) { + return; + } + checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock()); ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); @@ -146,7 +139,7 @@ public class BlockListener implements Listener { SlimefunItem tool = SlimefunItem.getByItem(item); if (tool != null) { - if (Slimefun.hasUnlocked(e.getPlayer(), tool, true)) { + if (tool.canUse(e.getPlayer(), true)) { tool.callItemHandler(ToolUseHandler.class, handler -> handler.onToolUse(e, item, fortune, drops)); } else { e.setCancelled(true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/CoolerListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/CoolerListener.java index 87a5a88a6..c2f836bdd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/CoolerListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/CoolerListener.java @@ -21,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler; import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} listens for a {@link FoodLevelChangeEvent} or an {@link EntityDamageEvent} for starvation @@ -74,7 +73,7 @@ public class CoolerListener implements Listener { for (ItemStack item : p.getInventory().getContents()) { if (cooler.isItem(item)) { - if (Slimefun.hasUnlocked(p, cooler, true)) { + if (cooler.canUse(p, true)) { takeJuiceFromCooler(p, item); } else { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java index 8b065acc6..9b40e0fc1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/ElytraImpactListener.java @@ -18,7 +18,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.ElytraCap; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * The {@link Listener} for the {@link ElytraCap}. @@ -57,7 +56,7 @@ public class ElytraImpactListener implements Listener { if (helmet.isPresent()) { SlimefunItem item = helmet.get(); - if (Slimefun.hasUnlocked(p, item, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) { + if (item.canUse(p, true) && profile.hasFullProtectionAgainst(ProtectionType.FLYING_INTO_WALL)) { e.setDamage(0); p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GadgetsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GadgetsListener.java index 2e2b0fecf..f3002e775 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GadgetsListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/GadgetsListener.java @@ -14,13 +14,12 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.armor.Parachute; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.JetBoots; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Jetpack; import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedMagnet; +import io.github.thebusybiscuit.slimefun4.implementation.tasks.InfusedMagnetTask; import io.github.thebusybiscuit.slimefun4.implementation.tasks.JetBootsTask; import io.github.thebusybiscuit.slimefun4.implementation.tasks.JetpackTask; -import io.github.thebusybiscuit.slimefun4.implementation.tasks.InfusedMagnetTask; import io.github.thebusybiscuit.slimefun4.implementation.tasks.ParachuteTask; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for listening to the {@link PlayerToggleSneakEvent} @@ -59,7 +58,7 @@ public class GadgetsListener implements Listener { if (SlimefunUtils.containsSimilarItem(p.getInventory(), SlimefunItems.INFUSED_MAGNET, true)) { InfusedMagnet magnet = (InfusedMagnet) SlimefunItems.INFUSED_MAGNET.getItem(); - if (Slimefun.hasUnlocked(p, magnet, true)) { + if (magnet.canUse(p, true)) { new InfusedMagnetTask(p, magnet.getRadius()).scheduleRepeating(0, 8); } } @@ -67,7 +66,7 @@ public class GadgetsListener implements Listener { } private void handleChestplate(@Nonnull Player p, @Nullable SlimefunItem chestplate) { - if (chestplate == null || !Slimefun.hasUnlocked(p, chestplate, true)) { + if (chestplate == null || !chestplate.canUse(p, true)) { return; } @@ -83,7 +82,7 @@ public class GadgetsListener implements Listener { } private void handleBoots(@Nonnull Player p, @Nullable SlimefunItem boots) { - if (boots instanceof JetBoots && Slimefun.hasUnlocked(p, boots, true)) { + if (boots instanceof JetBoots && boots.canUse(p, true)) { double speed = ((JetBoots) boots).getSpeed(); if (speed > 0.2) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/MultiBlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/MultiBlockListener.java index d684a274b..0d40e4e3e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/MultiBlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/MultiBlockListener.java @@ -62,8 +62,13 @@ public class MultiBlockListener implements Listener { e.setCancelled(true); MultiBlock mb = multiblocks.getLast(); - mb.getSlimefunItem().callItemHandler(MultiBlockInteractionHandler.class, handler -> handler.onInteract(p, mb, b)); - Bukkit.getPluginManager().callEvent(new MultiBlockInteractEvent(p, mb, b, e.getBlockFace())); + MultiBlockInteractEvent event = new MultiBlockInteractEvent(p, mb, b, e.getBlockFace()); + Bukkit.getPluginManager().callEvent(event); + + // Fixes #2809 + if (!event.isCancelled()) { + mb.getSlimefunItem().callItemHandler(MultiBlockInteractionHandler.class, handler -> handler.onInteract(p, mb, b)); + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java index 0db770f40..5c04c7e49 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java @@ -23,7 +23,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.armor.LongFallBoo import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for handling all boots provided by @@ -53,7 +52,7 @@ public class SlimefunBootsListener implements Listener { Player p = (Player) e.getEntity(); SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); - if (boots instanceof EnderBoots && Slimefun.hasUnlocked(p, boots, true)) { + if (boots instanceof EnderBoots && boots.canUse(p, true)) { e.setCancelled(true); } } @@ -65,7 +64,7 @@ public class SlimefunBootsListener implements Listener { if (boots != null) { // Check if the boots were researched - if (!Slimefun.hasUnlocked(p, boots, true)) { + if (!boots.canUse(p, true)) { return; } @@ -91,7 +90,7 @@ public class SlimefunBootsListener implements Listener { Player p = e.getPlayer(); SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); - if (boots instanceof FarmerShoes && Slimefun.hasUnlocked(p, boots, true)) { + if (boots instanceof FarmerShoes && boots.canUse(p, true)) { e.setCancelled(true); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemConsumeListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemConsumeListener.java index bfd4d657a..fdbd271e2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemConsumeListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemConsumeListener.java @@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for handling the {@link ItemConsumptionHandler} @@ -33,7 +32,7 @@ public class SlimefunItemConsumeListener implements Listener { SlimefunItem sfItem = SlimefunItem.getByItem(item); if (sfItem != null) { - if (Slimefun.hasUnlocked(p, sfItem, true)) { + if (sfItem.canUse(p, true)) { sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item)); } else { e.setCancelled(true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index ee276c3d3..d17fa55d4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; -import me.mrCookieSlime.Slimefun.api.Slimefun; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu; @@ -94,8 +93,10 @@ public class SlimefunItemInteractListener implements Listener { Optional optional = event.getSlimefunItem(); if (optional.isPresent()) { - if (Slimefun.hasUnlocked(e.getPlayer(), optional.get(), true)) { - return optional.get().callItemHandler(ItemUseHandler.class, handler -> handler.onRightClick(event)); + SlimefunItem sfItem = optional.get(); + + if (sfItem.canUse(e.getPlayer(), true)) { + return sfItem.callItemHandler(ItemUseHandler.class, handler -> handler.onRightClick(event)); } else { event.setUseItem(Result.DENY); } @@ -109,19 +110,20 @@ public class SlimefunItemInteractListener implements Listener { Optional optional = event.getSlimefunBlock(); if (optional.isPresent()) { - if (!Slimefun.hasUnlocked(event.getPlayer(), optional.get(), true)) { + SlimefunItem sfItem = optional.get(); + + if (!sfItem.canUse(event.getPlayer(), true)) { event.getInteractEvent().setCancelled(true); return false; } - boolean interactable = optional.get().callItemHandler(BlockUseHandler.class, handler -> handler.onRightClick(event)); + boolean interactable = sfItem.callItemHandler(BlockUseHandler.class, handler -> handler.onRightClick(event)); if (!interactable) { - String id = optional.get().getId(); Player p = event.getPlayer(); - if (BlockMenuPreset.isInventory(id)) { - openInventory(p, id, event.getInteractEvent().getClickedBlock(), event); + if (BlockMenuPreset.isInventory(sfItem.getId())) { + openInventory(p, sfItem, event.getInteractEvent().getClickedBlock(), event); return false; } } @@ -131,27 +133,31 @@ public class SlimefunItemInteractListener implements Listener { } @ParametersAreNonnullByDefault - private void openInventory(Player p, String id, Block clickedBlock, PlayerRightClickEvent event) { - if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { - event.getInteractEvent().setCancelled(true); + private void openInventory(Player p, SlimefunItem item, Block clickedBlock, PlayerRightClickEvent event) { + try { + if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { + event.getInteractEvent().setCancelled(true); - if (BlockStorage.hasUniversalInventory(id)) { - UniversalBlockMenu menu = BlockStorage.getUniversalInventory(id); + if (BlockStorage.hasUniversalInventory(item.getId())) { + UniversalBlockMenu menu = BlockStorage.getUniversalInventory(item.getId()); - if (menu.canOpen(clickedBlock, p)) { - menu.open(p); - } else { - SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); - } - } else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) { - BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation()); + if (menu.canOpen(clickedBlock, p)) { + menu.open(p); + } else { + SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); + } + } else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) { + BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation()); - if (menu.canOpen(clickedBlock, p)) { - menu.open(p); - } else { - SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); + if (menu.canOpen(clickedBlock, p)) { + menu.open(p); + } else { + SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true); + } } } + } catch (Exception | LinkageError x) { + item.error("An Exception was caught while trying to open the Inventory", x); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java index 8cf2f71c3..ce21c0f35 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TalismanListener.java @@ -61,24 +61,24 @@ public class TalismanListener implements Listener { public void onDamageGet(EntityDamageEvent e) { if (e.getEntity() instanceof Player) { if (e.getCause() == DamageCause.LAVA) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA); + Talisman.trigger(e, SlimefunItems.TALISMAN_LAVA); } if (e.getCause() == DamageCause.DROWNING) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER); + Talisman.trigger(e, SlimefunItems.TALISMAN_WATER); } if (e.getCause() == DamageCause.FALL) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL); + Talisman.trigger(e, SlimefunItems.TALISMAN_ANGEL); } if (e.getCause() == DamageCause.FIRE) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE); + Talisman.trigger(e, SlimefunItems.TALISMAN_FIRE); } if (e.getCause() == DamageCause.ENTITY_ATTACK) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT); - Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR); + Talisman.trigger(e, SlimefunItems.TALISMAN_KNIGHT); + Talisman.trigger(e, SlimefunItems.TALISMAN_WARRIOR); } if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) { @@ -91,7 +91,7 @@ public class TalismanListener implements Listener { if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) { Projectile projectile = (Projectile) e.getDamager(); - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_WHIRLWIND)) { Player p = (Player) e.getEntity(); returnProjectile(p, projectile); } @@ -143,7 +143,7 @@ public class TalismanListener implements Listener { // We are also excluding entities which can pickup items, this is not perfect // but it at least prevents dupes by tossing items to zombies - if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) { + if (!entity.getCanPickupItems() && Talisman.trigger(e, SlimefunItems.TALISMAN_HUNTER)) { Collection extraDrops = getExtraDrops(e.getEntity(), e.getDrops()); for (ItemStack drop : extraDrops) { @@ -192,7 +192,7 @@ public class TalismanListener implements Listener { @EventHandler public void onItemBreak(PlayerItemBreakEvent e) { - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_ANVIL)) { PlayerInventory inv = e.getPlayer().getInventory(); int slot = inv.getHeldItemSlot(); @@ -225,7 +225,7 @@ public class TalismanListener implements Listener { @EventHandler public void onSprint(PlayerToggleSprintEvent e) { if (e.isSprinting()) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_TRAVELLER); + Talisman.trigger(e, SlimefunItems.TALISMAN_TRAVELLER); } } @@ -235,31 +235,39 @@ public class TalismanListener implements Listener { Map enchantments = e.getEnchantsToAdd(); // Magician Talisman - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MAGICIAN)) { - MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem(); - TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet()); + MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem(); + TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet()); - if (enchantment != null) { + if (enchantment != null && Talisman.trigger(e, SlimefunItems.TALISMAN_MAGICIAN)) { + /* + * Fix #2679 + * By default, the Bukkit API doesn't allow us to give enchantment books extra enchantments. + */ + if (talisman.isEnchantmentBookAllowed() && e.getItem().getType() == Material.BOOK) { + e.getItem().addUnsafeEnchantment(enchantment.getEnchantment(), enchantment.getLevel()); + } else { enchantments.put(enchantment.getEnchantment(), enchantment.getLevel()); } } // Wizard Talisman - if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) { - - for (Enchantment enchantment : enchantments.keySet()) { - if (random.nextInt(100) < 40) { - e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1); + if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.trigger(e, SlimefunItems.TALISMAN_WIZARD)) { + // Randomly lower some enchantments + for (Map.Entry entry : enchantments.entrySet()) { + if (entry.getValue() > 1 && random.nextInt(100) < 40) { + enchantments.put(entry.getKey(), entry.getValue() - 1); } } + // Give an extra Fortune boost (Lvl 3 - 5) enchantments.put(Enchantment.LOOT_BONUS_BLOCKS, random.nextInt(3) + 3); } } - + @EventHandler(ignoreCancelled = true) public void onExperienceReceive(PlayerExpChangeEvent e) { - if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) { + // Check if the experience change was positive. + if (e.getAmount() > 0 && Talisman.trigger(e, SlimefunItems.TALISMAN_WISE)) { // Double-XP e.setAmount(e.getAmount() * 2); } @@ -267,21 +275,27 @@ public class TalismanListener implements Listener { @EventHandler(ignoreCancelled = true) public void onBlockDropItems(BlockDropItemEvent e) { - // We only want to double ores - Material type = e.getBlockState().getType(); - if (type.name().endsWith("_ORE")) { - ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); + ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); - if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { + // We are going to ignore Silk Touch here + if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { + Material type = e.getBlockState().getType(); + + // We only want to double ores + if (SlimefunTag.MINER_TALISMAN_TRIGGERS.isTagged(type)) { Collection drops = e.getItems(); - if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MINER)) { + if (Talisman.trigger(e, SlimefunItems.TALISMAN_MINER, false)) { int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS)); + + // Keep track of whether we actually doubled the drops or not boolean doubledDrops = false; + // Loop through all dropped items for (Item drop : drops) { ItemStack droppedItem = drop.getItemStack(); + // We do not want to dupe blocks if (!droppedItem.getType().isBlock()) { int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount()); e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount)); @@ -289,8 +303,14 @@ public class TalismanListener implements Listener { } } + // Fixes #2077 if (doubledDrops) { - SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.talisman.miner", true); + Talisman talisman = SlimefunItems.TALISMAN_MINER.getItem(Talisman.class); + + // Fixes #2818 + if (talisman != null) { + talisman.sendMessage(e.getPlayer()); + } } } } @@ -300,7 +320,7 @@ public class TalismanListener implements Listener { @EventHandler public void onBlockBreak(BlockBreakEvent e) { if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) { - Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN); + Talisman.trigger(e, SlimefunItems.TALISMAN_CAVEMAN); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VampireBladeListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VampireBladeListener.java index 31e7444ac..e91d2660f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VampireBladeListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/VampireBladeListener.java @@ -13,7 +13,6 @@ import org.bukkit.potion.PotionEffect; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.VampireBlade; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is exclusively used for the {@link VampireBlade}. @@ -44,7 +43,7 @@ public class VampireBladeListener implements Listener { Player p = (Player) e.getDamager(); if (blade.isItem(p.getInventory().getItemInMainHand())) { - if (Slimefun.hasUnlocked(p, blade, true)) { + if (blade.canUse(p, true)) { blade.heal(p); } else { e.setCancelled(true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/EntityInteractionListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/EntityInteractionListener.java index 47bf84f4f..f9aaa6abe 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/EntityInteractionListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/EntityInteractionListener.java @@ -14,7 +14,6 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemState; import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * The {@link Listener} responsible for a {@link Player} interacting with an {@link Entity}. @@ -48,7 +47,7 @@ public class EntityInteractionListener implements Listener { SlimefunItem sfItem = SlimefunItem.getByItem(itemStack); if (sfItem != null) { - if (Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) { + if (sfItem.canUse(e.getPlayer(), true)) { sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND)); } else if (sfItem.getState() != ItemState.VANILLA_FALLBACK) { /* diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/MobDropListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/MobDropListener.java index 47579d295..b0f8b85b1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/MobDropListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/entity/MobDropListener.java @@ -18,7 +18,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for handling any custom mob drops. @@ -55,7 +54,7 @@ public class MobDropListener implements Listener { if (item.getType() != Material.AIR) { SlimefunItem sfItem = SlimefunItem.getByItem(item); - if (sfItem != null && Slimefun.hasUnlocked(p, sfItem, true)) { + if (sfItem != null && sfItem.canUse(p, true)) { sfItem.callItemHandler(EntityKillHandler.class, handler -> handler.onKill(e, e.getEntity(), p, item)); } } @@ -63,21 +62,21 @@ public class MobDropListener implements Listener { } private boolean canDrop(@Nonnull Player p, @Nonnull ItemStack item) { - SlimefunItem sfi = SlimefunItem.getByItem(item); + SlimefunItem sfItem = SlimefunItem.getByItem(item); - if (sfi == null) { + if (sfItem == null) { return true; - } else if (Slimefun.hasUnlocked(p, sfi, true)) { - if (sfi instanceof RandomMobDrop) { + } else if (sfItem.canUse(p, true)) { + if (sfItem instanceof RandomMobDrop) { int random = ThreadLocalRandom.current().nextInt(100); - if (((RandomMobDrop) sfi).getMobDropChance() <= random) { + if (((RandomMobDrop) sfItem).getMobDropChance() <= random) { return false; } } - if (sfi instanceof BasicCircuitBoard) { - return ((BasicCircuitBoard) sfi).isDroppedFromGolems(); + if (sfItem instanceof BasicCircuitBoard) { + return ((BasicCircuitBoard) sfItem).isDroppedFromGolems(); } return true; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/OilResource.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/OilResource.java index c45cc768d..e73b3cfe6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/OilResource.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/OilResource.java @@ -32,56 +32,56 @@ class OilResource extends SlimefunResource { } switch (biome) { - case SNOWY_BEACH: - case STONE_SHORE: - case BEACH: - return 6; + case SNOWY_BEACH: + case STONE_SHORE: + case BEACH: + return 6; - case DESERT: - case DESERT_HILLS: - case DESERT_LAKES: - return 45; + case DESERT: + case DESERT_HILLS: + case DESERT_LAKES: + return 45; - case MOUNTAINS: - case GRAVELLY_MOUNTAINS: - case MOUNTAIN_EDGE: - case RIVER: - return 17; + case MOUNTAINS: + case GRAVELLY_MOUNTAINS: + case MOUNTAIN_EDGE: + case RIVER: + return 17; - case SNOWY_MOUNTAINS: - case SNOWY_TUNDRA: - case ICE_SPIKES: - case FROZEN_OCEAN: - case FROZEN_RIVER: - return 14; + case SNOWY_MOUNTAINS: + case SNOWY_TUNDRA: + case ICE_SPIKES: + case FROZEN_OCEAN: + case FROZEN_RIVER: + return 14; - case BADLANDS: - case BADLANDS_PLATEAU: - case WOODED_BADLANDS_PLATEAU: - case ERODED_BADLANDS: - case MODIFIED_BADLANDS_PLATEAU: - case MODIFIED_WOODED_BADLANDS_PLATEAU: - case MUSHROOM_FIELDS: - case MUSHROOM_FIELD_SHORE: - return 24; + case BADLANDS: + case BADLANDS_PLATEAU: + case WOODED_BADLANDS_PLATEAU: + case ERODED_BADLANDS: + case MODIFIED_BADLANDS_PLATEAU: + case MODIFIED_WOODED_BADLANDS_PLATEAU: + case MUSHROOM_FIELDS: + case MUSHROOM_FIELD_SHORE: + return 24; - case DEEP_OCEAN: - case OCEAN: - case COLD_OCEAN: - case DEEP_COLD_OCEAN: - case DEEP_FROZEN_OCEAN: - case DEEP_LUKEWARM_OCEAN: - case DEEP_WARM_OCEAN: - case LUKEWARM_OCEAN: - case WARM_OCEAN: - return 62; + case DEEP_OCEAN: + case OCEAN: + case COLD_OCEAN: + case DEEP_COLD_OCEAN: + case DEEP_FROZEN_OCEAN: + case DEEP_LUKEWARM_OCEAN: + case DEEP_WARM_OCEAN: + case LUKEWARM_OCEAN: + case WARM_OCEAN: + return 62; - case SWAMP: - case SWAMP_HILLS: - return 20; + case SWAMP: + case SWAMP_HILLS: + return 20; - default: - return 10; + default: + return 10; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/SaltResource.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/SaltResource.java index 532bfa339..f6c14c79d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/SaltResource.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/resources/SaltResource.java @@ -26,33 +26,33 @@ class SaltResource extends SlimefunResource { } switch (biome) { - case SNOWY_BEACH: - case STONE_SHORE: - case BEACH: - case DESERT_LAKES: - case RIVER: - case ICE_SPIKES: - case FROZEN_RIVER: - return 40; + case SNOWY_BEACH: + case STONE_SHORE: + case BEACH: + case DESERT_LAKES: + case RIVER: + case ICE_SPIKES: + case FROZEN_RIVER: + return 40; - case DEEP_OCEAN: - case OCEAN: - case COLD_OCEAN: - case DEEP_COLD_OCEAN: - case DEEP_FROZEN_OCEAN: - case DEEP_LUKEWARM_OCEAN: - case DEEP_WARM_OCEAN: - case FROZEN_OCEAN: - case LUKEWARM_OCEAN: - case WARM_OCEAN: - return 60; + case DEEP_OCEAN: + case OCEAN: + case COLD_OCEAN: + case DEEP_COLD_OCEAN: + case DEEP_FROZEN_OCEAN: + case DEEP_LUKEWARM_OCEAN: + case DEEP_WARM_OCEAN: + case FROZEN_OCEAN: + case LUKEWARM_OCEAN: + case WARM_OCEAN: + return 60; - case SWAMP: - case SWAMP_HILLS: - return 20; + case SWAMP: + case SWAMP_HILLS: + return 20; - default: - return 6; + default: + return 6; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java index 0e9419b34..340090718 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java @@ -217,7 +217,7 @@ public final class ResearchSetup { register("cargo_basics", 205, "Cargo Basics", 30, SlimefunItems.CARGO_MOTOR, SlimefunItems.CARGO_MANAGER, SlimefunItems.CARGO_CONNECTOR_NODE); register("cargo_nodes", 206, "Cargo Setup", 30, SlimefunItems.CARGO_INPUT_NODE, SlimefunItems.CARGO_OUTPUT_NODE); register("electric_ingot_machines", 207, "Electric Ingot Fabrication", 18, SlimefunItems.ELECTRIC_GOLD_PAN, SlimefunItems.ELECTRIC_DUST_WASHER, SlimefunItems.ELECTRIC_INGOT_FACTORY); - register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2); + register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2, SlimefunItems.ELECTRIC_ORE_GRINDER_3); register("automated_crafting_chamber", 210, "Automated Crafting", 20, SlimefunItems.AUTOMATED_CRAFTING_CHAMBER); register("better_food_fabricator", 211, "Upgraded Food Fabrication", 28, SlimefunItems.FOOD_FABRICATOR_2, SlimefunItems.FOOD_COMPOSTER_2); register("reactor_access_port", 212, "Reactor Interaction", 18, SlimefunItems.REACTOR_ACCESS_PORT); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java index e6967e4b0..0757c2931 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java @@ -1666,6 +1666,13 @@ public final class SlimefunItemSetup { .setProcessingSpeed(4) .register(plugin); + new ElectricOreGrinder(categories.electricity, SlimefunItems.ELECTRIC_ORE_GRINDER_3, RecipeType.ENHANCED_CRAFTING_TABLE, + new ItemStack[] {SlimefunItems.REINFORCED_PLATE, SlimefunItems.HEATING_COIL, SlimefunItems.REINFORCED_PLATE, null, SlimefunItems.ELECTRIC_ORE_GRINDER_2, null, SlimefunItems.REINFORCED_PLATE, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.REINFORCED_PLATE}) + .setCapacity(1024) + .setEnergyConsumption(45) + .setProcessingSpeed(10) + .register(plugin); + new HeatedPressureChamber(categories.electricity, SlimefunItems.HEATED_PRESSURE_CHAMBER, RecipeType.ENHANCED_CRAFTING_TABLE, new ItemStack[] {SlimefunItems.LEAD_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, new ItemStack(Material.GLASS), SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, SlimefunItems.HEATING_COIL, SlimefunItems.LEAD_INGOT}) .setCapacity(128) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/ArmorTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/ArmorTask.java index ed1c04fa3..510dfc07d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/ArmorTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/ArmorTask.java @@ -117,7 +117,7 @@ public class ArmorTask implements Runnable { SlimefunPlugin.runSync(() -> { SlimefunArmorPiece slimefunArmor = armorpiece.getItem().get(); - if (Slimefun.hasUnlocked(p, slimefunArmor, true)) { + if (slimefunArmor.canUse(p, true)) { for (PotionEffect effect : slimefunArmor.getPotionEffects()) { p.removePotionEffect(effect.getType()); p.addPotionEffect(effect); @@ -138,7 +138,7 @@ public class ArmorTask implements Runnable { SlimefunItem item = SlimefunItem.getByItem(helmet); - if (item instanceof SolarHelmet && Slimefun.hasUnlocked(p, item, true)) { + if (item instanceof SolarHelmet && item.canUse(p, true)) { ((SolarHelmet) item).rechargeItems(p); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/PlaceholderAPIIntegration.java b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/PlaceholderAPIIntegration.java index b6fa8a0cf..354902c4e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/PlaceholderAPIIntegration.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/integrations/PlaceholderAPIIntegration.java @@ -62,7 +62,12 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion { private boolean isPlaceholder(@Nullable OfflinePlayer p, boolean requiresProfile, @Nonnull String params, @Nonnull String placeholder) { if (requiresProfile) { - return p != null && placeholder.equals(params) && PlayerProfile.request(p); + if (p != null && placeholder.equals(params)) { + PlayerProfile.request(p); + return true; + } else { + return false; + } } else { return placeholder.equals(params); } @@ -76,6 +81,8 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion { if (profile.isPresent()) { Stream stream = profile.get().getResearches().stream(); return String.valueOf(stream.mapToInt(Research::getCost).sum()); + } else if (p instanceof Player) { + return SlimefunPlugin.getLocalization().getMessage((Player) p, "placeholderapi.profile-loading"); } } @@ -85,6 +92,8 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion { if (profile.isPresent()) { Set set = profile.get().getResearches(); return String.valueOf(set.size()); + } else if (p instanceof Player) { + return SlimefunPlugin.getLocalization().getMessage((Player) p, "placeholderapi.profile-loading"); } } @@ -98,6 +107,8 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion { if (profile.isPresent()) { Set set = profile.get().getResearches(); return String.valueOf(Math.round(((set.size() * 100.0F) / SlimefunPlugin.getRegistry().getResearches().size()) * 100.0F) / 100.0F); + } else if (p instanceof Player) { + return SlimefunPlugin.getLocalization().getMessage((Player) p, "placeholderapi.profile-loading"); } } @@ -106,6 +117,8 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion { if (profile.isPresent()) { return profile.get().getTitle(); + } else if (p instanceof Player) { + return SlimefunPlugin.getLocalization().getMessage((Player) p, "placeholderapi.profile-loading"); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterial.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterial.java index fb791fda3..4f6826508 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterial.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/ColoredMaterial.java @@ -47,6 +47,28 @@ public enum ColoredMaterial { Material.BLACK_WOOL }), + /** + * This {@link List} contains all carpet colors ordered by their appearance ingame. + */ + CARPET(new Material[] { + Material.WHITE_CARPET, + Material.ORANGE_CARPET, + Material.MAGENTA_CARPET, + Material.LIGHT_BLUE_CARPET, + Material.YELLOW_CARPET, + Material.LIME_CARPET, + Material.PINK_CARPET, + Material.GRAY_CARPET, + Material.LIGHT_GRAY_CARPET, + Material.CYAN_CARPET, + Material.PURPLE_CARPET, + Material.BLUE_CARPET, + Material.BROWN_CARPET, + Material.GREEN_CARPET, + Material.RED_CARPET, + Material.BLACK_CARPET + }), + /** * This {@link List} contains all stained glass colors ordered by their appearance ingame. */ diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java index 8b6eff1ac..c7446de7f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -15,6 +15,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.Item; +import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -358,4 +359,31 @@ public final class SlimefunUtils { SlimefunPlugin.runSync(new CapacitorTextureUpdateTask(l, charge, capacity)); } + /** + * This checks whether the {@link Player} is able to use the given {@link ItemStack}. + * It will always return true for non-Slimefun items. + *

+ * If you already have an instance of {@link SlimefunItem}, please use {@link SlimefunItem#canUse(Player, boolean)}. + * + * @param p + * The {@link Player} + * @param item + * The {@link ItemStack} to check + * @param sendMessage + * Whether to send a message response to the {@link Player} + * + * @return Whether the {@link Player} is able to use that item. + */ + public static boolean canPlayerUseItem(@Nonnull Player p, @Nullable ItemStack item, boolean sendMessage) { + Validate.notNull(p, "The player cannot be null"); + + SlimefunItem sfItem = SlimefunItem.getByItem(item); + + if (sfItem != null) { + return sfItem.canUse(p, sendMessage); + } else { + return true; + } + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java index 855485681..14cf74b07 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/tags/SlimefunTag.java @@ -22,6 +22,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationExce import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator; +import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel; @@ -120,6 +121,12 @@ public enum SlimefunTag implements Tag { */ DIRT_VARIANTS, + /** + * All soil blocks for a fungus to grow on. + * This includes all dirt variants, nylium and soul soil. + */ + FUNGUS_SOIL, + /** * All variants of concrete powder. * Can you believe there is no tag for this already? @@ -184,6 +191,11 @@ public enum SlimefunTag implements Tag { */ INDUSTRIAL_MINER_ORES, + /** + * All materials (ores) which can be doubled using a Miner {@link Talisman}. + */ + MINER_TALISMAN_TRIGGERS, + /** * All materials (crops) which the {@link CropGrowthAccelerator} will recognize. */ @@ -210,8 +222,16 @@ public enum SlimefunTag implements Tag { */ CAVEMAN_TALISMAN_TRIGGERS; + /** + * Lookup table for tag names. + */ private static final Map nameLookup = new HashMap<>(); - public static final SlimefunTag[] valuesCache = values(); + + /** + * Speed up lookups by caching the values instead of creating a new array + * on every method call. + */ + private static final SlimefunTag[] valuesCache = values(); static { for (SlimefunTag tag : valuesCache) { diff --git a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/Item/CustomItemSerializer.java b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/Item/CustomItemSerializer.java index d28037ba3..6c6b7860f 100644 --- a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/Item/CustomItemSerializer.java +++ b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/Item/CustomItemSerializer.java @@ -59,49 +59,49 @@ public class CustomItemSerializer { builder.append(flag.toString() + "="); switch (flag) { - case AMOUNT: { - builder.append(item.getAmount()); - break; - } - case DATA: { - builder.append((int) item.getData().getData()); - break; - } - case DURABILITY: { - builder.append((int) item.getDurability()); - break; - } - case ENCHANTMENTS: - for (Enchantment enchantment : Enchantment.values()) { - if (item.getEnchantments().containsKey(enchantment)) { - builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment)); - } else { - builder.append(enchantment.getName() + ":0"); + case AMOUNT: { + builder.append(item.getAmount()); + break; + } + case DATA: { + builder.append((int) item.getData().getData()); + break; + } + case DURABILITY: { + builder.append((int) item.getDurability()); + break; + } + case ENCHANTMENTS: + for (Enchantment enchantment : Enchantment.values()) { + if (item.getEnchantments().containsKey(enchantment)) { + builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment)); + } else { + builder.append(enchantment.getName() + ":0"); + } } + break; + case ITEMMETA_DISPLAY_NAME: { + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) { + builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&")); + } else { + builder.append("NONE"); + } + break; } - break; - case ITEMMETA_DISPLAY_NAME: { - if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) { - builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&")); - } else { - builder.append("NONE"); + case ITEMMETA_LORE: { + if (item.hasItemMeta() && item.getItemMeta().hasLore()) { + builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&")); + } else { + builder.append("NONE"); + } + break; } - break; - } - case ITEMMETA_LORE: { - if (item.hasItemMeta() && item.getItemMeta().hasLore()) { - builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&")); - } else { - builder.append("NONE"); + case MATERIAL: { + builder.append(item.getType().toString()); + break; } - break; - } - case MATERIAL: { - builder.append(item.getType().toString()); - break; - } - default: - break; + default: + break; } i++; diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java index cf95721f3..6bf1bf0a7 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/Category.java @@ -26,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.core.categories.SeasonalCategory; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; -import me.mrCookieSlime.Slimefun.api.Slimefun; /** * Represents a category, which structure multiple {@link SlimefunItem} in the {@link SlimefunGuide}. @@ -258,7 +257,7 @@ public class Category implements Keyed { */ public boolean isHidden(@Nonnull Player p) { for (SlimefunItem slimefunItem : getItems()) { - if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) { + if (!slimefunItem.isHidden() && !slimefunItem.isDisabledIn(p.getWorld())) { return false; } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java index 5cca61a0d..28ff901c0 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/SlimefunItem.java @@ -16,9 +16,11 @@ import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.permissions.Permission; import io.github.thebusybiscuit.cscorelib2.collections.OptionalMap; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; @@ -32,6 +34,7 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.UnregisteredItemExcepti import io.github.thebusybiscuit.slimefun4.api.exceptions.WrongItemStackException; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.ItemState; +import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.attributes.NotConfigurable; import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable; import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive; @@ -377,6 +380,26 @@ public class SlimefunItem implements Placeable { return state != ItemState.ENABLED; } + /** + * This method returns whether this {@link SlimefunItem} is disabled + * for that specific {@link World}. + * Note that if the item is disabled globally, this method will still return false. + * + * @param world + * The {@link World} to check + * + * @return Whether this {@link SlimefunItem} is disabled in that world (or in general). + */ + public boolean isDisabledIn(@Nonnull World world) { + if (state == ItemState.UNREGISTERED) { + error("isDisabled(World) cannot be called before registering the item", new UnregisteredItemException(this)); + return false; + } + + // Check if the Item is disabled globally or in this specific world + return isDisabled() || !SlimefunPlugin.getWorldSettingsService().isEnabled(world, this); + } + /** * This method returns the {@link SlimefunAddon} that registered this * {@link SlimefunItem}. If this Item is from Slimefun itself, the current @@ -996,7 +1019,6 @@ public class SlimefunItem implements Placeable { */ public void error(@Nonnull String message, @Nonnull Throwable throwable) { Validate.notNull(addon, "Cannot send an error for an unregistered item!"); - addon.getLogger().log(Level.SEVERE, "Item \"{0}\" from {1} v{2} has caused an Error!", new Object[] { id, addon.getName(), addon.getPluginVersion() }); if (addon.getBugTrackerURL() != null) { @@ -1012,6 +1034,90 @@ public class SlimefunItem implements Placeable { } } + /** + * This method checks if the given {@link Player} is able to use this {@link SlimefunItem}. + * A {@link Player} can use it if the following conditions apply: + * + *

+ *

    + *
  • The {@link SlimefunItem} is not disabled + *
  • The {@link SlimefunItem} was not disabled for that {@link Player}'s {@link World}. + *
  • The {@link Player} has the required {@link Permission} (if present) + *
  • The {@link Player} has unlocked the required {@link Research} (if present) + *
+ *

+ * + * If any of these conditions evaluate to false, then an optional message will be + * sent to the {@link Player}. + * + * @param p + * The {@link Player} to check + * @param sendMessage + * Whether to send that {@link Player} a message response. + * + * @return Whether this {@link Player} is able to use this {@link SlimefunItem}. + */ + public boolean canUse(@Nonnull Player p, boolean sendMessage) { + Validate.notNull(p, "The Player cannot be null!"); + + if (getState() == ItemState.VANILLA_FALLBACK) { + // Vanilla items (which fell back) can always be used. + return true; + } else if (isDisabled()) { + // The Item has been disabled in the config + if (sendMessage) { + SlimefunPlugin.getLocalization().sendMessage(p, "messages.disabled-item", true); + } + + return false; + } else if (!SlimefunPlugin.getWorldSettingsService().isEnabled(p.getWorld(), this)) { + // The Item was disabled in the current World + if (sendMessage) { + SlimefunPlugin.getLocalization().sendMessage(p, "messages.disabled-in-world", true); + } + + return false; + } else if (!SlimefunPlugin.getPermissionsService().hasPermission(p, this)) { + // The Player does not have the required permission node + if (sendMessage) { + SlimefunPlugin.getLocalization().sendMessage(p, "messages.no-permission", true); + } + + return false; + } else if (hasResearch()) { + Optional profile = PlayerProfile.find(p); + + if (!profile.isPresent()) { + /* + * We will return false since we cannot know the answer yet. + * But we will schedule the Profile for loading and not send + * any message. + */ + PlayerProfile.request(p); + return false; + } else if (!profile.get().hasUnlocked(getResearch())) { + /* + * The Profile is loaded but Player has not unlocked the + * required Research to use this SlimefunItem. + */ + if (sendMessage && !(this instanceof VanillaItem)) { + SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-researched", true); + } + + return false; + } else { + /* + * The PlayerProfile is loaded and the Player has unlocked + * the required Research. + */ + return true; + } + } else { + // All checks have passed, the Player can use this item. + return true; + } + } + @Override public final boolean equals(Object obj) { if (obj instanceof SlimefunItem) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java index 2572751b1..077b26c8b 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AContainer.java @@ -74,8 +74,6 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock, processing.remove(b); return true; }); - - registerDefaultRecipes(); } @ParametersAreNonnullByDefault @@ -239,6 +237,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock, warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!"); } + registerDefaultRecipes(); + if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) { super.register(addon); } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java index b09f898e8..47868aac4 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/interfaces/InventoryBlock.java @@ -60,7 +60,7 @@ public interface InventoryBlock { @Override public boolean canOpen(Block b, Player p) { - return p.hasPermission("slimefun.inventory.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES) && Slimefun.hasUnlocked(p, item, false)); + return p.hasPermission("slimefun.inventory.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK) && Slimefun.hasUnlocked(p, item, false)); } }; } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java index 8870e9534..92148998c 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java @@ -18,6 +18,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import com.google.common.collect.ImmutableMap; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -27,6 +28,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.ItemStack; +import org.apache.commons.lang.Validate; + import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -360,6 +363,37 @@ public class BlockStorage { } } + /** + * This will return an {@link ImmutableMap} of the underline {@code Map} of + * this worlds {@link BlockStorage}. + * + * @return An {@link ImmutableMap} of the raw data. + */ + @Nonnull + public Map getRawStorage() { + return ImmutableMap.copyOf(this.storage); + } + + /** + * This will return an {@link ImmutableMap} of the underline {@code Map} of + * this worlds {@link BlockStorage}. If there is no registered world then this will return null. + * + * @param world + * The world of which to fetch the data from. + * @return An {@link ImmutableMap} of the raw data or null if the world isn't registered. + */ + @Nullable + public static Map getRawStorage(@Nonnull World world) { + Validate.notNull(world, "World cannot be null!"); + + BlockStorage storage = getStorage(world); + if (storage != null) { + return storage.getRawStorage(); + } else { + return null; + } + } + public static void store(Block block, ItemStack item) { SlimefunItem sfitem = SlimefunItem.getByItem(item); diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java b/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java index 6b843802c..de397d152 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java @@ -1,18 +1,15 @@ package me.mrCookieSlime.Slimefun.api; -import java.util.Optional; - import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.slimefun4.api.items.ItemState; -import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; -import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem; +import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; /** * Provides a few static convenience methods. + * This class is slowly getting stripped away in favour of a more object-oriented approach. * * @author TheBusyBiscuit * @author Walshy @@ -31,19 +28,17 @@ public final class Slimefun { * the item to check, not null * @param message * whether a message should be sent to the player or not + * + * @deprecated Moved to + * {@link SlimefunUtils#canPlayerUseItem(Player, ItemStack, boolean)} * * @return true if the item is a SlimefunItem, enabled, researched and if the player has the permission * to use it, * false otherwise. */ + @Deprecated public static boolean hasUnlocked(Player p, ItemStack item, boolean message) { - SlimefunItem sfItem = SlimefunItem.getByItem(item); - - if (sfItem != null) { - return hasUnlocked(p, sfItem, message); - } else { - return true; - } + return SlimefunUtils.canPlayerUseItem(p, item, message); } /** @@ -55,39 +50,15 @@ public final class Slimefun { * the item to check, not null * @param message * whether a message should be sent to the player or not + * + * @deprecated Please use {@link SlimefunItem#canUse(Player, boolean)} instead. * * @return true if the item is enabled, researched and the player has the permission to use it, * false otherwise. */ + @Deprecated public static boolean hasUnlocked(Player p, SlimefunItem sfItem, boolean message) { - if (sfItem.getState() == ItemState.VANILLA_FALLBACK) { - return true; - } - - if (isEnabled(p, sfItem, message) && hasPermission(p, sfItem, message)) { - if (sfItem.getResearch() == null) { - return true; - } else { - Optional profile = PlayerProfile.find(p); - - if (!profile.isPresent()) { - // We will return false since we cannot know the answer yet - // But we will schedule the Profile for loading. - PlayerProfile.request(p); - return false; - } else if (profile.get().hasUnlocked(sfItem.getResearch())) { - return true; - } else { - if (message && !(sfItem instanceof VanillaItem)) { - SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-researched", true); - } - - return false; - } - } - } - - return false; + return sfItem.canUse(p, message); } /** @@ -126,10 +97,13 @@ public final class Slimefun { * the item to check, not null * @param message * whether a message should be sent to the player or not + * + * @deprecated This method will be removed. * * @return true if the item is a SlimefunItem and is enabled in the world the player is in, * false otherwise. */ + @Deprecated public static boolean isEnabled(Player p, ItemStack item, boolean message) { SlimefunItem sfItem = SlimefunItem.getByItem(item); diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java index 5155fe76d..3c5412f66 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java @@ -105,15 +105,18 @@ public class DirtyChestMenu extends ChestMenu { if (stack == null) { replaceExistingItem(slot, item); return null; - } else if (stack.getAmount() < stack.getMaxStackSize()) { - if (wrapper == null) { - wrapper = new ItemStackWrapper(item); - } + } else { + int maxStackSize = Math.min(stack.getMaxStackSize(), toInventory().getMaxStackSize()); + if (stack.getAmount() < maxStackSize) { + if (wrapper == null) { + wrapper = new ItemStackWrapper(item); + } - if (ItemUtils.canStack(wrapper, stack)) { - amount -= (stack.getMaxStackSize() - stack.getAmount()); - stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize())); - item.setAmount(amount); + if (ItemUtils.canStack(wrapper, stack)) { + amount -= (maxStackSize - stack.getAmount()); + stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), maxStackSize)); + item.setAmount(amount); + } } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 84aff21b3..a0f9cd53a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -38,9 +38,8 @@ networks: enable-visualizer: true delete-excess-items: false -items: - talismans: true - soulbound: true +talismans: + use-actionbar: true metrics: auto-update: true diff --git a/src/main/resources/languages/categories_cs.yml b/src/main/resources/languages/categories_cs.yml index 1facb887f..6a4ea3f5b 100644 --- a/src/main/resources/languages/categories_cs.yml +++ b/src/main/resources/languages/categories_cs.yml @@ -1,25 +1,26 @@ --- slimefun: - armor: Brnění - basic_machines: Základní stroje - birthday: TheBusyBiscuitovy narozeniny (26. Říjen) - cargo: Cargo systém - christmas: Vánoce (Prosinec) - easter: Velikonoce (Duben) - electricity: Energie a elektrika - ender_talismans: Ender Talismany (Tier II) - food: Jídlo - gps: GPS stroje - halloween: Halloween (31. Října) - items: Užitečné itemy - magical_armor: Magická zbroj - magical_gadgets: Magické pomůcky - magical_items: Magické itemy - resources: Materiály - talismans: Talismany (Tier I) - tech_misc: Technické komponenty - technical_gadgets: Technické pomůcky - tools: Nástroje weapons: Zbraně - misc: Smíšené položky - valentines_day: Svatého Valentýna (14. Února) + tools: Nástroje + items: Užitečné předměty + food: Jídlo + basic_machines: Základní stroje + electricity: Energie a elektrika + gps: GPS stroje + armor: Brnění + magical_items: Magické předměty + magical_gadgets: Magické pomůcky + misc: Smíšené předměty + technical_gadgets: Technické pomůcky + resources: Materiály + cargo: Cargo systém + tech_misc: Technické komponenty + magical_armor: Magická zbroj + talismans: Talismany (Tier I) + ender_talismans: Enderitové talismany (Tier II) + christmas: Vánoce (prosinec) + valentines_day: Svatého Valentýna (14. února) + easter: Velikonoce (duben) + birthday: TheBusyBiscuitovy narozeniny (26. říjen) + halloween: Halloween (31. října) + androids: Programovatelné androidy diff --git a/src/main/resources/languages/categories_nl.yml b/src/main/resources/languages/categories_nl.yml index eef15e6b7..54f830d80 100644 --- a/src/main/resources/languages/categories_nl.yml +++ b/src/main/resources/languages/categories_nl.yml @@ -2,7 +2,7 @@ slimefun: weapons: Wapens tools: Gereedschappen - items: Voorwerpen + items: Handige Voorwerpen food: Eten basic_machines: Standaard machines electricity: Energie en Elektriciteit @@ -13,7 +13,7 @@ slimefun: misc: Diverse Voorwerpen technical_gadgets: Technische Gadgets resources: Grondstoffen - cargo: Cargobehering + cargo: Opslagbehering tech_misc: Technische Componenten magical_armor: Magische Bescherming talismans: Amuletten (Niveau I) diff --git a/src/main/resources/languages/messages_bg.yml b/src/main/resources/languages/messages_bg.yml index a400654de..bfa337459 100644 --- a/src/main/resources/languages/messages_bg.yml +++ b/src/main/resources/languages/messages_bg.yml @@ -4,7 +4,7 @@ commands: cheat: Позволява Ви да чийтвате Предмети give: Позволява Ви да давате на някого Slimefun Предмети guide: Дава ви Slimefun Ръководство - teleporter: Вижте пътни точки от други играчи + teleporter: Вижте пътни точки на други играчи versions: Лист с всички инсталирани Добавки search: Претърсва вашето Ръководство за даден термин / предмет open_guide: Отваря Ви Slimefun Ръководството без да използвате книгата @@ -48,10 +48,10 @@ guide: selected-language: 'Избран в момента:' change: Натисни, за да избереш нов език description: - - "&7Сега имаш опцията да промениш" - - "&7езика, на който е Slimefun" - - "&7той ще се промени само за теб. Предметите" - - "&7не могат да бъдат преведени за момента." + '0': "&7Сега имаш опцията да промениш" + '1': "&7езика, на който е Slimefun" + '2': "&7той ще се промени само за теб. Предметите" + '3': "&7не могат да бъдат преведени за момента." title: main: Slimefun Ръководство settings: Настройки & Информация @@ -73,10 +73,10 @@ guide: profile-link: Натиснете, за да видите техния профил в GitHub open: Натисни, за да видиш нашите контрибутори description: - - "&7Slimefun е проект с отворен код" - - "&7и е поддържан от голямо общество от хора." - - "&7Над &e%contributors% &7хора са работили върху" - - "&7Slimefun през всички тези години." + '0': "&7Slimefun е проект с отворен код" + '1': "&7и е поддържан от голямо общество от хора." + '2': "&7Над &e%contributors% &7хора са работили върху" + '3': "&7Slimefun през всички тези години." pages: previous: Предишна страница next: Следваща страница @@ -96,9 +96,9 @@ guide: settings: Върнете се обратно в Панела с Настройки(Settings Panel) locked: ЗАКЛЮЧЕНО locked-category: - - За да отключите тази категория - - ще трябва да отключите всички предмети от - - следните категории + '0': За да отключите тази категория + '1': ще трябва да отключите всички предмети от + '2': следните категории work-in-progress: Тази функция не е завършена все още! messages: not-researched: "&4Нямате достатъчно познания, за да разберете това" @@ -134,6 +134,7 @@ messages: wizard: "&a&oВашия Талисман Ви даде по-добро Ниво Fortune, но може да е намалило Нивата на някои от другите Ви Enchantment-и" caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене" + wise: "&a&oВашия Талисман удвой вашите XP дропове" soulbound-rune: fail: "& cМожете да свържете само един елемент с душата си наведнъж." success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие @@ -153,22 +154,22 @@ messages: link-prompt: "&eНатиснете тук:" diet-cookie: "&eЗапочнахте да се чувствате доста лекичък..." fortune-cookie: - - "&7Помогнете ми, аз съм затворен в Фабрика за Късметлийски Бисквитки!" - - "&7Утре Вие ще умрете... от Creeper" - - "&7В някакъв момент от живота Ви нещо лошо ще се случи!!!" - - "&7Следващата седмица ще забележите, че това не е реалния свят, а всъщност Вие - сте в компютърна игра" - - "&7Тази бисквитка ще стане вкусна в следващите няколко секунди" - - '&7Последната дума, която ще чуете ще бъде "УНИЩОЖЕТЕ!!!"' - - "&7Каквото и да правите никога, ама никога не прегръщайте Creeper... Аз опитах. - Доста добре е, но не си заслужава." - - "&742. Отговорът е 42." - - "&7Walshy веднъж на ден ще пази неприятностите далече." - - "&7Никога не копайте право надолу!" - - "&7Туй е само плътна рана!" - - "&7Винаги гледайте от към хубавата страна на живота!" - - "&7Това беше Бисквитка, а не Курабийка" - - "&7Неоновите табели светят!" + '0': "&7Помогнете ми, аз съм затворен в Фабрика за Късметлийски Бисквитки!" + '1': "&7Утре Вие ще умрете... от Creeper" + '2': "&7В някакъв момент от живота Ви нещо лошо ще се случи!!!" + '3': "&7Следващата седмица ще забележите, че това не е реалния свят, а всъщност + Вие сте в компютърна игра" + '4': "&7Тази бисквитка ще стане вкусна в следващите няколко секунди" + '5': '&7Последната дума, която ще чуете ще бъде "УНИЩОЖЕТЕ!!!"' + '6': "&7Каквото и да правите никога, ама никога не прегръщайте Creeper... Аз опитах. + Доста добре е, но не си заслужава." + '7': "&742. Отговорът е 42." + '8': "&7Walshy веднъж на ден ще пази неприятностите далече." + '9': "&7Никога не копайте право надолу!" + '10': "&7Туй е само плътна рана!" + '11': "&7Винаги гледайте от към хубавата страна на живота!" + '12': "&7Това беше Бисквитка, а не Курабийка" + '13': "&7Неоновите табели светят!" piglin-barter: "&4Не може да разменяте предмети с Пиглините използвайки предмети от Slimefun" enchantment-rune: @@ -268,9 +269,9 @@ gps: max: "&4Достигнахте максималната бройка локации" duplicate: "&4Вие вече сте създал локация на име: &f%waypoint%" insufficient-complexity: - - "&4Недостатъчна Сложност на GPS Мрежата: &c%complexity%" - - "&4a) Все още нямате направена GPS Мрежа" - - "&4b) Вашата GPS Мрежа не е достатъчно сложна" + '0': "&4Недостатъчна Сложност на GPS Мрежата: &c%complexity%" + '1': "&4a) Все още нямате направена GPS Мрежа" + '2': "&4b) Вашата GPS Мрежа не е достатъчно сложна" geo: scan-required: "&4GEO-Scan изискан! &cПърво сканирайте този чънк използвайки GEO-Scanner!" inventory: @@ -309,11 +310,10 @@ android: INTERFACE_ITEMS: "&9Изпратни съдаржанието на Инвентара към лицевия Интерфейс" INTERFACE_FUEL: "&cИзвадете Гориво от лицевия Интерфейс" enter-name: - - - - "&eМоля въведете име за скрипта си" + '1': "&eМоля въведете име за скрипта си" uploaded: - - "&bКачване..." - - "&aУспешно качихме твоя скрипт!" + '0': "&bКачване..." + '1': "&aУспешно качихме твоя скрипт!" rating: own: "&4Не може да оцените собствения си скрипт!" already: "&4Вие вече сте оставили рейтинг за този скрипт!" @@ -369,3 +369,5 @@ cartography_table: not-working: "&4Не може да използвате Slimefun предмети в картографска маса!" cauldron: no-discoloring: "&4Не можете да обезцветявате Slimefun брони" +placeholderapi: + profile-loading: Зареждане... diff --git a/src/main/resources/languages/messages_cs.yml b/src/main/resources/languages/messages_cs.yml index 89f93a40f..127b0d438 100644 --- a/src/main/resources/languages/messages_cs.yml +++ b/src/main/resources/languages/messages_cs.yml @@ -1,34 +1,38 @@ --- commands: help: Zobrazí tuto nápovědu - cheat: Umožňuje nacheatovat věci - give: Dejte někomu nějaké Slimefun věci - guide: Dá vám Slimefun příručku - timings: Lag-Info vašeho serveru - teleporter: "Zobrazí \nznačky \nostatních hráčů" - versions: Seznam všech nainstalovaných doplňků - search: Vyhledá ve vaší příručce daný příkaz + cheat: Umožní našvindlovat si věci + give: Dá hráči vybrané Slimefun předměty + guide: Dá Slimefun příručku + teleporter: Zobrazí záchytné body ostatních hráčů + versions: Zobrazí všechny nainstalované doplňky + search: Vyhledá v příručce daný předmět open_guide: Otevře Slimefun příručku bez použití knihy stats: Ukáže statistiky hráče research: - description: Odemkne/Resetuje výzkum daného hráče + description: Odemkne či resetuje výzkum daného hráče reset: "&cResetoval jsi výzkum hráče %player%" reset-target: "&cTvoje znalost byla resetována " backpack: description: Načíst kopii existujícího batohu invalid-id: "&4Id nesmí být záporné!" player-never-joined: "&4Hráče s tímto jménem nelze nalézt!" - backpack-does-not-exist: "&4Určený batoh neexistuje!" + backpack-does-not-exist: "&4Zadaný batoh neexistuje!" restored-backpack-given: "&aTvůj batoh byl obnoven a navrácen do tvého inventáře!" + charge: + description: Nabije předmět, který držíš + charge-success: Předmět byl nabit! + not-rechargeable: Tento předmět nelze nabít! + timings: Lag-Info vašeho serveru guide: search: message: "&bCo bys chtěl vyhledat?" name: "&7Hledat..." - tooltip: "&bKliknutím vyhledejte položku" + tooltip: "&bKlikni pro vyhledání předmětu" inventory: 'Hledání: %item%' lore: - - "&bCo bys chtěl vyhledat?" - - "&7Napiš do chatu co chceš vyhledat" + '1': "&7Napiš do chatu co chceš vyhledat" + '0': "&bCo bys chtěl vyhledat?" cheat: no-multiblocks: "&4Nemůžeš podvádět v multiblocích, musíš je postavit!" languages: @@ -41,157 +45,169 @@ guide: selected-language: 'Aktuálně vybráno:' change: Klikni pro výběr nového jazyka description: - - "&7Nyní máš možnost to změnit" - - "&7jazyk, ve kterém bude Slimefun" - - "&7bude ti představeno. Předměty" - - "&7nelze prozatím přeložit." + '0': "&7Nyní máš možnost změnit" + '1': "&7jazyk, ve kterém ti bude" + '2': "&7Slimefun prezentován. Předměty" + '3': "&7nelze prozatím přeložit." title: main: Slimefun příručka settings: Nastavení a informace - languages: Zvol tvůj preferovaný jazyk + languages: Zvol svůj preferovaný jazyk credits: Slimefun4 pomocníci wiki: Slimefun4 Wiki - addons: Addony pro Slimefun4 + addons: Doplňky pro Slimefun4 bugs: Nahlášení chyb source: Zdrojový kód versions: Nainstalovaná verze credits: + commit: Commit commits: Commits roles: developer: "&6Vývojář" wiki: "&3Wiki správce" - resourcepack: "&cTvůrce Resourcepacku" - translator: "&9Překladač" - profile-link: Klikni pro navštívení jejich profilu na GitHubu - open: Klikni pro zobrazení našich spoluúčastníků + resourcepack: "&cTvůrce modifikačního balíčku" + translator: "&9Překladatel" + profile-link: Klikni pro navštívení jeho profilu na GitHubu + open: Klikni pro zobrazení našich pomocníků description: - - "&7Slimefun je open-source projekt" - - "&7a udržován velkou komunitou lidí." - - "&Přes&e%contributors% &7lidí na tom pracovalo" - - "&7Slimefun za všechny ty roky." + '0': "&7Slimefun je open-source projekt" + '1': "&7udržován velkou komunitou lidí." + '2': "&7Na Slimefunu za všechny ty roky pracovalo" + '3': "&7přes &e%contributors% &7lidí." pages: previous: Předchozí strana next: Následující strana tooltips: open-category: Klikni pro otevření versions-notice: To jsou velmi důležité při hlášení chyb! - wiki: Zobrazit tento předmět na oficiální SlimeFun Wiki + wiki: Zobrazit tento předmět na oficiální Slimefun Wiki recipes: machine: Recepty vytvářené tímto strojem miner: Materiály, které můžeš získat tímto těžebním robotem generator: Dostupné typy paliv gold-pan: Materiály, které můžeš získat + climbing-pick: Povrchy, na které můžeš lézt back: title: Zpět - guide: Zpět do Slimefun Guide - settings: Zpět do Settings Panel + guide: Zpět do Slimefun příručky + settings: Zpět do panelu nastavení locked: ZAMČENO locked-category: - - Chcete-li odemknout tuto kategorii, budete - - 'je třeba odemknout všechny položky z ' - - následující kategorie + '0': Chceš-li odemknout tuto kategorii, + '1': je potřeba odemknout všechny předměty + '2': z předchozích kategorií work-in-progress: Tato funkce ještě není zcela dokončena! messages: not-researched: "&4Ještě jsi nepostoupil tak daleko, abys pochopil tuhle věc" - not-enough-xp: "&4Nemáš dostatek XP levelů na to, abys vyzkoumal tuhle věc" - unlocked: '&bMáš vyzkoumáno &7"%research%"' + not-enough-xp: "&4Nemáš dostatek XP úrovní na to, abys vyzkoumal tuhle věc" + unlocked: "&bMáš vyzkoumáno &7„%research%”" only-players: "&4Tenhle příkaz je jenom pro hráče" unknown-player: "&4Neznámý hráč: &c%player%" - no-permission: "&4Na tohle nemáš dostatečné povolení" + no-permission: "&4Na tohle nemáš dostatečné oprávnění" usage: "&4Použití: &c%usage%" not-online: "&4%player% &czrovna není připojen!" - invalid-item: "&4%item% &cnení platný item!" - invalid-amount: "&4%amount% &cnení platné číslo : musí být větší než 0!" - given-item: '&bDostal jsi &a%amount% &7"%item%&7"' - give-item: '&bDal jsi %player% &a%amount% &7"%item%&7"' - invalid-research: "&4%research% &cnení platný výzkum!" + given-item: "&bDostal jsi &a%amount% &7„%item%&7”" + give-item: "&bDal jsi %player% &a%amount% &7„%item%&7”" give-research: '&bUdělil jsi %player% výzkum &7"%research%&7"' hungry: "&cJsi moc hladový na to, abys to zvládl!" disabled-in-world: "&4&lTahle věc není v tomhle světě povolená" disabled-item: |- &4&lTahle věc není povolená! Jak jsi ji vůbec dostal? - no-tome-yourself: "&cNemůžeš použít svůj &4Tome of Knowledge &c..." + no-tome-yourself: "&cNemůžeš použít svůj &4Tome of Knowledge&c..." multimeter: "&bEnergie: &3%stored% &b/ &3%capacity%" talisman: anvil: "&a&oTvůj talisman zachránil tvůj nástroj od rozbití" - miner: "&a&oTvůj talisman zdvojnásobil tvoje dropy" - hunter: "&a&oTvůj talisman zdvojnásobil tvoje dropy" + miner: "&a&oTvůj talisman zdvojnásobil tvou kořist" + hunter: "&a&oTvůj talisman zdvojnásobil tvou kořist" lava: "&a&oTvůj talisman tě zachránil před uhořením" water: "&a&oTvůj talisman tě zachránil před utopením" angel: "&a&oTvůj talisman tě zachránil před poškození pádem" fire: "&a&oTvůj talisman tě zachránil před uhořením" - magician: "&a&oTvůj talisman ti dal přídavné enchanty" + magician: "&a&oTvůj talisman ti dal dodatečná očarování" traveller: "&a&oTvůj talisman ti dal rychlost" - warrior: "&a&oTvůj talisman ti dal efekt síly na nějakou tu chvíli" - knight: "&a&oTvůj talisman ti dal 5 vteřin regenerace" + warrior: "&a&oTvůj talisman ti dal na určitou chvilku efekt síly" + knight: "&a&oTvůj talisman ti dal 5 sekund regenerace" whirlwind: "&a&oTvůj talisman odrazil projektil" - wizard: "&a&oTvůj talisman ti dal větší level Štěstí, ale možná snížil level jiných - enchantů" + wizard: "&a&oTvůj talisman ti dal větší úroveň štěstí, ale možná snížil úroveň + jiných očarování" + caveman: "&a&oTvůj talisman ti dal spěch" + wise: "& a&aTvůj talisman zdvojnásobil zisk tvých zkušeností" soulbound-rune: - fail: "&cKe své duši můžeš přidat jen jeden předmět." - success: "&aÚspěšně jsi přidal tento item ke své duši. Pokud zemřeš, item ti zůstane." + fail: "&cSvou duši můžeš spoutat jen s jedním předmětem." + success: "&aÚspěšně jsi spoutal tento předmět se svou duši. Pokud zemřeš, předmět + ti zůstane." research: - start: "&7Antičtí duchové šeptají magické slova do tvého ucha..." + start: "&7Antičtí duchové šeptají magická slova do tvého ucha..." progress: "&7Začal jsi přemýšlet nad &b%research% &e(%progress%)" fire-extinguish: "&7Uhasil ses" cannot-place: "&cZde nemůžeš položit blok!" no-pvp: "&cZde nemůžeš bojovat s hráči!" radiation: "&4Byl jsi vystaven smrtelné radiaci! &cVyhoď radioaktivní předmět nebo - si obleč Hazmat oblek." - opening-guide: "&bOtevírání příručky, může to pár sekund trvat..." - opening-backpack: "&bOtevírání batohu, může to pár sekund trvat..." - no-iron-golem-heal: "&cTo není Iron Ingot! S tímto nemůžeš léčit Iron Golemy!" + si obleč hazmat oblek." + opening-guide: "&bOtevírá se příručka, může to pár sekund trvat..." + opening-backpack: "&bOtevírá se batoh, může to pár sekund trvat..." + no-iron-golem-heal: "&cTohle není železný ingot, a proto s ním nemůžeš léčit železné + golemy!" link-prompt: "&eKlikni zde:" - diet-cookie: "&eZačínáš se cítit velice lehký..." + diet-cookie: "&eZačínáš se cítit velice lehce..." fortune-cookie: - - "&7POMOOC!! Jsem uvězněn v továrně na sušenky štěstí!" - - "&7Zítra zemřeš... s láskou od pana Creepera" - - "&7V nějaké části tvého života se stane něco špatného!!!" - - "&7Příští týden si uvědomíš, že toto není reálný život, ale jsi v počítačové hře." - - "&7Sušenka ti bude za pár vteřin velice chutnat" - - '&7Poslední slovo, které uslyšíš bude "VYHUBIT!!!"' - - "&7Ať se stane cokoliv, nepokoušej se mazlit Creepera... Zkusil jsem to. Je to - dobrý pocit, ale nestojí to za to." - - "&742. Odpověď je 42." - - "&7Walshy udrží den problémy pryč." - - "&7Nikdy nekopej pod sebe!" - - "&7To je jen rána masa!" - - "&7Vždy se podívejte na světlou stránku života!" - - "&7Tohle byl vlastně Biscuit a ne Cookie" - - "&7Neonové cedule jsou LIT!" - piglin-barter: "&4Nemůžete měnit s pigliny Slimefun předměty" + '0': "&7POMOOC!! Jsem uvězněn v továrně na sušenky štěstí!" + '1': "&7Zítra zemřeš... s láskou od pana creepera" + '2': "&7V nějaké části tvého života se stane něco špatného!!!" + '3': "&7Příští týden si uvědomíš, že toto není reálný život, ale že jsi v počítačové + hře" + '4': "&7Sušenka ti bude za pár sekund velice chutnat" + '5': "&7Poslední slovo, které uslyšíš bude „VYHUBIT!!!”" + '6': "&7Ať se stane cokoliv, nepokoušej se mazlit creepera... Zkusil jsem to. + Je to dobrý pocit, ale nestojí to za to." + '7': "&742. Odpověď je 42." + '8': "&7Walshy udrží den problémy pryč." + '9': "&7Nikdy nekopej pod sebe!" + '10': "&7To je jen rána masa!" + '11': "&7Vždy se podívej na světlou stránku života!" + '12': "&7Tohle byl vlastně Biscuit, a ne Cookie" + '13': "&7Neonové cedule jsou LIT!" + piglin-barter: "&4S pigliny nemůžeš vyměňovat Slimefun předměty" enchantment-rune: - fail: "&cNemůžeš enchantovat tento předmět" - no-enchantment: "&cPro tento předmět nelze najít žádný vhodný enchant." - success: "&aÚspěšně jsi na tento předmět daů náhodný enchant." + fail: "&cNemůžeš očarovat tento předmět." + no-enchantment: "&cPro tento předmět nelze najít žádné vhodné očarování." + success: "&aÚspěšně jsi na tento předmět dal náhodné vhodné očarování." tape-measure: - no-anchor: "&cMusíš nastavit kotvu než začneš měřit! " + no-anchor: "&cPřed začátkem měření musíš nastavit kotvu! " wrong-world: "&cTvoje kotva je pravděpodobně v jiném světa!" distance: "&7Měření zahájeno. &eVzdálenost: %distance%" anchor-set: "&aÚspěšně nastavena kotva:&e %anchor%" multi-tool: mode-change: "&b%device% mód změněn na: &9%mode%" not-shears: "&cMulti Tool nemůže být použit jako nůžky!" + climbing-pick: + dual-wielding: "&4Musíš držet Climbing Picks v obou rukou pro jeho použití!" + wrong-material: "&cNa tento povrch nemůžeš vylézt. Zkontroluj Slimefun Guide, + kde najdeš další informace!" + invalid-item: "&4%item% &cnení platný předmět!" + invalid-amount: "&4%amount% &cnení platné číslo. Musí být větší než 0!" + invalid-research: "&4%research% &cnení platný výzkum!" + bee-suit-slow-fall: "&eTvé Bee Wings ti pomohou bezpečně a pomalu se vrátit na zem" mode-change: "&b%device% mód změněn na: &9%mode%" machines: - pattern-not-found: "&eOmlouvám se, ale nerozpoznal jsem tento recept. Dej do dispenseru + pattern-not-found: "&eBohužel se nepodařilo rozpoznat tento recept. Dej do dávkovače předměty tak, aby odpovídaly receptu." - unknown-material: "&eOmlouvám se, ale nepoznal jsem předmět v dispenseru. Dej tam - něco, co znám." - wrong-item: "&eOmlouvám se, ale nerozpoznal jsem předmět, se kterým jsi na mě kliknul. + unknown-material: "&eBohužel se nepodařilo rozpoznat tento předmět v dávkovači. + Dej tam něco správného." + wrong-item: "&eBohužel se nepodařilo rozpoznat předmět, se kterým jsi na mě kliknul. Zkontroluj recept a koukni se, jaké předměty můžeš použít." - full-inventory: "&eOmlouvám se, můj inventář je plný." - in-use: "&cInventář tohoto bloku je právě otevřen jiným hráčem" + full-inventory: "&eBohužel, můj inventář je plný." + in-use: "&cInventář tohoto bloku je právě otevřen jiným hráčem." ignition-chamber-no-flint: "&cIgnition Chamberu chybí křesadlo." ANCIENT_ALTAR: - not-enough-pedestals: "&4Altáři chybí podstavce &c(%pedestals% / 8)" + not-enough-pedestals: "&4Altar nemá dostatek Pedestal &c(%pedestals% / 8)" unknown-catalyst: "&4Neznámý katalyst. &cPoužij správný recept!" unknown-recipe: "&4Neznámý recept! &cPoužij správný recept!" ANCIENT_PEDESTAL: - obstructed: "&4Podstavce jsou zablokované! &cOdstraň cokoliv nad podstavcema!" + obstructed: "&4Pedestal je zablokován! &cOdstraň cokoliv nad ním!" HOLOGRAM_PROJECTOR: - enter-text: "&7Napiš do chatu zprávu, kterou chceš, aby Hologram ukazoval. &r(Barvy + enter-text: "&7Napiš do chatu zprávu, kterou chceš, aby hologram ukazoval. &r(Barvy jsou podporovány!)" inventory-title: Editor hologramu ELEVATOR: @@ -199,62 +215,63 @@ machines: pick-a-floor: "&3- Vyber si patro -" current-floor: "&eAktuální patro:" click-to-teleport: "&eKliknutím &7se teleportuješ na toto patro:" - enter-name: "&7Prosím, zadejte název podlaží do chatu. &r(Barvy jsou podporovány!)" - named: "&2Podlaží úspěšně pojmenováno na: &r%floor%" + enter-name: "&7Zadej název podlaží do chatu. &r(Barvy jsou podporovány!)" + named: "&2Podlaží úspěšně pojmenováno: &r%floor%" TELEPORTER: teleporting: "&3Teleportuji..." teleported: "&3Teleportace dokončena!" cancelled: "&4Teleportace zrušena!" invulnerability: "&b&lZískal jsi 30 sekund nezranitelnosti!" gui: - title: Vaše waypointy - tooltip: Klikněte pro teleportaci + title: Tvé záchytné body + tooltip: Klikni pro teleportaci time: Předpokládaný čas CARGO_NODES: must-be-placed: "&4Musí být umístěn na truhlu nebo stroj!" GPS_CONTROL_PANEL: title: GPS - Kontrolní panel transmitters: Přehled vysílačů - waypoints: Přehled waypointů + waypoints: Přehled záchytných bodů INDUSTRIAL_MINER: - no-fuel: "&cTvému průmyslovému horníku došlo palivo! Vložte palivo do bedny nad." + no-fuel: "&cTvému průmyslovému horníku došlo palivo! Vlož palivo do bedny nad." piston-facing: "&cTvůj průmyslový horník potřebuje píst směřující nahoru!" piston-space: "&cDva písty potřebují prázdný blok nad nimi!" - destroyed: "&cZdá se, váš průmysloví horník byl rozbit." + destroyed: "&cZdá se, že tvůj průmyslový horník byl zničen." already-running: "&cTento průmyslový horník již běží!" full-chest: "&cBedna vašeho průmyslového horníka je plná!" - no-permission: "&4Zdá se, nemáte oprávnění používat průmyslového horníka zde!" - finished: "&eVáš průmysloví horník dokončil práci! Získal %ores% hornin!" + no-permission: "&4Zdá se, že zde nemáš oprávnění používat průmyslového horníka!" + finished: "&eTvůj průmysloví horník dokončil práci! Získal %ores% rud!" anvil: not-working: "&4Předměty ze Slimefunu nelze použít v kovadlině!" + mcmmo-salvaging: "&4Nemůžeš zachránit Slimefun předměty!" backpack: - already-open: "&cOmlouváme se, tento batoh je otevřený již někde jinde!" - no-stack: "&cNemůžeš stackovat batohy" + already-open: "&cBohužel, tento batoh je již otevřený někde jinde!" + no-stack: "&cNemůžeš shromažďovat batohy" workbench: - not-enhanced: "&4Nemůžeš použít itemy ze Slimefunu v normální výrobě" + not-enhanced: "&4Nemůžeš použít předměty ze Slimefunu v normální pracovním stole" gps: deathpoint: "&4Bod úmrtí &7%date%" waypoint: - new: "&eProsím, zadejte název waypointu do chatu. &7(Barvy jsou podporovány!)" - added: "&aÚspěšně přidán nový waypoint" - max: "&4Dosáhl jsi maxima waypointů" - duplicate: "&4Již jsi vytvořil waypoint pojmenovaný: &f%waypoint%" + new: "&eZadej název záchytného bodu do chatu. &7(Barvy jsou podporovány!)" + added: "&aÚspěšně přidán nový záchytný bod" + max: "&4Dosáhl jsi maxima záchytných bodů" + duplicate: "&4Již jsi vytvořil záchytný bod pojmenovaný: &f%waypoint%" insufficient-complexity: - - "&4Nedostatečná komplexita GPS Networku: &c%complexity%" - - "&4a) Nemáš nastavený GPS Network" - - "&4b) TvůjGPS Network není dostatečně komplexní" + '0': "&4Nedostatečná komplexita GPS Networku: &c%complexity%" + '1': "&4a) Nemáš nastavený GPS Network" + '2': "&4b) Tvůj GPS Network není dostatečně komplexní" geo: - scan-required: "&4GEO-Scan je požadován! &cProzkoumejte tento chunk pomocí GEO-Scanneru!" + scan-required: "&4GEO-Scan je požadován! &cProzkoumej tento chunk pomocí GEO-Scanneru!" inventory: no-access: "&4Nemáš přístup k tomuto bloku" android: - started: "&7Tvůj Android právě začal používat jemu přidělený script" - stopped: "&7Tvůj Android pozastavil jemu přidělený script" + started: "&7Tvůj Android právě začal používat jemu přidělený skript" + stopped: "&7Tvůj Android pozastavil jemu přidělený skript" scripts: - already-uploaded: "&4Tento script byl již nahrán." + already-uploaded: "&4Tento skript již byl nahrán." instructions: - START: "&2Začít Script" - REPEAT: "&9Opakovat Script" + START: "&2Začít skript" + REPEAT: "&9Opakovat skript" WAIT: "&ePočkej 0.5s" GO_FORWARD: "&7Posuň se vpřed" GO_UP: "&7Posuň se nahoru" @@ -267,10 +284,10 @@ android: MOVE_AND_DIG_UP: "&bPosuň se a zároveň kopej nahoru" MOVE_AND_DIG_FORWARD: "&bPosuň se a zároveň kopej dopředu" MOVE_AND_DIG_DOWN: "&bPosuň se a zároveň kopej dolů" - ATTACK_MOBS_ANIMALS: "&4Útoč na &cnepřátelské moby a zvířata" - ATTACK_MOBS: "&4Útoč na &cnepřátelské moby" + ATTACK_MOBS_ANIMALS: "&4Útoč na &cnepřátelská stvoření a zvířata" + ATTACK_MOBS: "&4Útoč na &cnepřátelská stvoření" ATTACK_ANIMALS: "&4Útoč na &czvířata" - ATTACK_ANIMALS_ADULT: "&4Útoč na &czvířata&7[Dospělá]" + ATTACK_ANIMALS_ADULT: "&4Útoč na &czvířata &7[Dospělá]" CHOP_TREE: "&cPokácej a zasaď" CATCH_FISH: "&bRybař" FARM_FORWARD: "&bSkliď a zasaď" @@ -280,15 +297,15 @@ android: INTERFACE_ITEMS: "&9Přesuň obsah inventáře do rozhraní na přední straně" INTERFACE_FUEL: "&cVyndej palivo z rozhraní přední strany" enter-name: - - - - "&eProsíme, zadejte název vašeho scriptu" + '1': "&eZadej název tvého skriptu" uploaded: - - "&bNahrávání..." - - "&aTvůj script byl úspěšně nahrán!" + '0': "&bNahrávání..." + '1': "&aTvůj skript byl úspěšně nahrán!" rating: - own: "&4Nemůžeš hodnotit vlastní script!" - already: "&4K tomuto scriptu jsi již zanechal hlasování!" + own: "&4Nemůžeš hodnotit vlastní skript!" + already: "&4K tomuto skriptu jsi již zanechal hlasování!" editor: Editor skriptu + too-long: "&cSkript je příliš dlouhý na úpravu!" languages: default: Výchozí-serverový en: Angličtina @@ -298,7 +315,7 @@ languages: es: Španělština pl: Polština sv: Švédština - nl: Holandština + nl: Nizozemština cs: Čeština hu: Maďarština lv: Lotyština @@ -310,8 +327,6 @@ languages: zh-CN: Čínština (Čína) el: Řečtina he: Hebrejština - pt: Portugalština (Portugalsko) - pt-BR: Portugalština (Brazílie) ar: Arabština af: Afrikánština da: Dánština @@ -323,6 +338,8 @@ languages: fa: Perština th: Thajština ro: Rumunština + pt: Portugalština (Portugalsko) + pt-BR: Portugalština (Brazílie) bg: Bulharština ko: Korejština tr: Turečtina @@ -330,9 +347,16 @@ languages: mk: Makedonština sr: Srbština be: Běloruština + tl: 'Tagalština ' brewing_stand: not-working: "&4Nemůžeš používat Slimefun předměty ve varném stojanu!" villagers: - no-trading: "&4Nemůžeš měnit Slimefun předměty s vesničany!" + no-trading: "&4Nemůžeš vyměňovat Slimefun předměty s vesničany!" +cartography_table: + not-working: "&4Nemůžeš použít Slimefun předměty v kartografickém stole!" +cauldron: + no-discoloring: "&4Nemůžeš odebrat barvu ze Slimefun brnění" +placeholderapi: + profile-loading: Načítání... miner: no-ores: "&eOmlouvám se, nemohu najít rudy v okolí!" diff --git a/src/main/resources/languages/messages_de.yml b/src/main/resources/languages/messages_de.yml index 369335a38..86aaf9a9c 100644 --- a/src/main/resources/languages/messages_de.yml +++ b/src/main/resources/languages/messages_de.yml @@ -136,6 +136,7 @@ messages: wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das Level einer anderen Verzauberung vermindert" caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft" + wise: "&a&oDein Talisman hat soeben deine Erfahrungspunkte verdoppelt" soulbound-rune: fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden" success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest @@ -319,6 +320,7 @@ android: own: "&4Du kannst nicht dein eigenes Skript bewerten!" already: "&4Du hast dieses Skript bereits bewertet!" editor: Skripteditor + too-long: "&cDieses Skript ist zu lang, um es zu bearbeiten!" languages: default: Server-Standard en: Englisch @@ -340,7 +342,6 @@ languages: zh-CN: Chinesisch (China) el: Griechisch he: Hebräisch - pt: Portugiesisch (Portugal) pt-BR: Portugiesisch (Brasilien) ar: Arabisch af: Afrikaans @@ -353,6 +354,7 @@ languages: fa: Persisch th: Thailändisch ro: Rumänisch + pt: Portugiesisch (Portugal) bg: Bulgarisch ko: Koreanisch tr: Türkisch @@ -371,3 +373,5 @@ cauldron: no-discoloring: "&4Du kannst Slimefun-Rüstung nicht entfärben" miner: no-ores: "&eIch konnte leider keine Erze in der Nähe finden!" +placeholderapi: + profile-loading: Lade... diff --git a/src/main/resources/languages/messages_en.yml b/src/main/resources/languages/messages_en.yml index fa811437a..1331bd69e 100644 --- a/src/main/resources/languages/messages_en.yml +++ b/src/main/resources/languages/messages_en.yml @@ -32,6 +32,9 @@ commands: verbose-player: '&4The verbose flag cannot be used by a Player!' unknown-flag: '&4Unknown flag: &c%flag%' +placeholderapi: + profile-loading: 'Loading...' + guide: locked: 'LOCKED' work-in-progress: 'This feature is not fully finished yet!' diff --git a/src/main/resources/languages/messages_es.yml b/src/main/resources/languages/messages_es.yml index 0e6716f8b..769db6106 100644 --- a/src/main/resources/languages/messages_es.yml +++ b/src/main/resources/languages/messages_es.yml @@ -25,9 +25,9 @@ commands: not-rechargeable: Este ítem no puede ser cargado! timings: description: Timings para Slimefun y sus addon + please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!" verbose-player: "&4La flag verbose no puede ser usada por un jugador!" unknown-flag: "&4flag desconocida: &c%flag%" - please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!" guide: search: message: "&b¿Qué te gustaría buscar?" @@ -134,6 +134,7 @@ messages: wizard: "&a&oTu talismán te ha dado un mayor nivel de fortuna, pero pudo disminuír el nivel de otros encantamientos." caveman: "&a&oTu Talismán te ha dado Haste" + wise: "&a&oTu Talismán ha duplicado tu drop de experiencia" soulbound-rune: fail: "&cSolo puedes ligar un objeto a tu alma." success: "&a¡Has ligado este objeto a tu alma exitosamente! No lo perderás al @@ -189,9 +190,9 @@ messages: invalid-item: "&c¡&4%item% &cno es un objeto válido!" invalid-amount: "&c¡&4%amount% &cno es un valor válido: tiene que ser mayor a 0!" invalid-research: "&c¡&4%research% &cno es un conocimiento válido!" - mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%' bee-suit-slow-fall: "&eTus alas de Abeja te ayudarán a llegar seguro y lento al piso" + mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%' machines: pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca el objeto en el patrón correcto dentro del dispensador." @@ -314,6 +315,7 @@ android: own: "&4¡No puedes calificar tu propio script!" already: "&4¡Ya has calificado este script!" editor: Editor de Guión + too-long: "&cEl script es demasiado largo para editar!" languages: default: Predeterminado en: Inglés @@ -335,6 +337,7 @@ languages: zh-CN: Chino (China) el: Griego he: Hebreo + pt: Portugués (Portugal) ar: Árabe af: Africano da: Danés @@ -346,7 +349,6 @@ languages: fa: Persa th: Tailandés ro: Rumano - pt: Portugués (Portugal) pt-BR: Portugués (Brasil) bg: Búlgaro ko: Coreano diff --git a/src/main/resources/languages/messages_fr.yml b/src/main/resources/languages/messages_fr.yml index a3d15040a..f7c71ae96 100644 --- a/src/main/resources/languages/messages_fr.yml +++ b/src/main/resources/languages/messages_fr.yml @@ -4,7 +4,6 @@ commands: cheat: Vous permet de vous donnez des objets give: Donne à quelqu'un des objets Slimefun guide: Vous donne un guide Slimefun - timings: Informations sur la latence de votre serveur teleporter: Affiche les waypoints d'un autre joueur versions: Affiche toutes les extensions installées search: Recherche dans votre guide le terme donné @@ -25,6 +24,11 @@ commands: description: Charge l'objet que vous avez en main charge-success: L'objet a été chargé ! not-rechargeable: Cet objet ne peut pas être chargé ! + timings: + description: Timings pour Slimefun et ses addons + please-wait: "&eAttendez s'il vous plaît, les résultats arrivent !" + verbose-player: "&4Ce flag ne peux pas être utiliser par un joueur!" + unknown-flag: "&4Flag inconnu: &c%flag%" guide: search: message: "&bQue souhaitez-vous rechercher?" @@ -134,6 +138,7 @@ messages: wizard: "&a&oVotre talisman vous a donné un meilleur niveau de Fortune mais a peut-être diminué plusieurs autres enchantements" caveman: "&a&oVotre Talisman vous a donné Célérité" + wise: "&a&oVotre talisman a doublé votre XP" soulbound-rune: fail: "&cVous pouvez lier un seul objet à la fois à votre âme" success: "&aVous avez réussi à lier cet objet à votre âme! Vous le garderez quand @@ -193,9 +198,9 @@ messages: invalid-amount: "&4%amount% &cn'est pas un montant valide: il doit être supérieur à 0!" invalid-research: "&4%research% &cn'est pas une recherche valide!" - mode-change: 'Vous avez changé votre &b%device% en mode : &9%mode%' bee-suit-slow-fall: "&eVos ailes d'abeille vous aideront à revenir au sol lentement et en toute sécurité" + mode-change: 'Vous avez changé votre &b%device% en mode : &9%mode%' machines: pattern-not-found: "&eDésolé, je ne reconnais pas cette recette. Veuillez disposer les objets correctement dans le distributeur." diff --git a/src/main/resources/languages/messages_he.yml b/src/main/resources/languages/messages_he.yml index 3e26c0d63..170137953 100644 --- a/src/main/resources/languages/messages_he.yml +++ b/src/main/resources/languages/messages_he.yml @@ -1,11 +1,18 @@ --- commands: help: הצגת מסך עזרה - teleporter: ראה נקודות ציון של שחקנים אחרים - search: חפש במדריך את המונח הנתון cheat: מאפשר לזמן פריטים ברמאות give: נותן למישהו פירטי סליים פאן guide: תן לעצמך מדריך סליים פאן + teleporter: ראה נקודות ציון של שחקנים אחרים + versions: הצגת תוספים מותקנים + search: חפש במדריך את המונח הנתון + open_guide: פתח את המדריך בלי להשתמש בספר + stats: מציג כמה נתונים סטטיסטיים על שחקן + research: + description: 'בטל נעילה /מחקרים עבור שחקן זה ' + reset: "&c איפס את הידע של %שחקן% זה" + reset-target: "&cהידע שלך אופס " backpack: description: אחזר עותק של גיבוי קיים invalid-id: " המספר המזהה חייב להיות מספר לא שלילי!&4" @@ -21,46 +28,15 @@ commands: please-wait: "&e !אנא המתן שנייה ... התוצאות מגיעות" verbose-player: "&4 האיתות המילולי אינו יכול להיות בשימוש על ידי שחקן!" unknown-flag: "&4איתות לא ידוע: &c%flag%" - versions: הצגת תוספים מותקנים - open_guide: פתח את המדריך בלי להשתמש בספר - stats: מציג כמה נתונים סטטיסטיים על שחקן - research: - description: 'בטל נעילה /מחקרים עבור שחקן זה ' - reset: "&c איפס את הידע של %שחקן% זה" - reset-target: "&cהידע שלך אופס " guide: - title: - main: סליים פאן מדריך - credits: סליים פאן4 תורמים - wiki: סליים פאן4 ויקי - addons: 'תוספות לסליים פאן ' - versions: גרסאות מותקנות - settings: 'הגדרות & מידע ' - languages: בחר את השפה המועדפת עליך - bugs: דיווחי שגיאות - source: קוד מקור - back: - guide: חזור למדריך סליים פאן - title: חזור - settings: חזור ללוח ההגדרות - tooltips: - wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי - recipes: - climbing-pick: משטחים שאפשר לטפס עליהם - machine: מתכונים שנעשו במכונה זו - miner: משאבים שתוכלו להשיג אצל כורה זה - generator: סוגי דלק זמינים - gold-pan: משאבים שתוכלו להשיג - open-category: לחץ לפתיחה - versions-notice: אלה חשובים מאוד כשמדווחים על באגים! - work-in-progress: תכונה זו עדיין לא הושלמה במלואה! + search: + message: מה תרצה לחפש? + name: "&7חפש...." + tooltip: "&b לחץ לחפש פריט" + inventory: "%item% מחפש עבור: " + cheat: + no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!" languages: - change: לחץ כדי לבחור שפה חדשה - description: - - "&7כעת יש לך אפשרות לשנות" - - "&7השפה שבה סליים פאן" - - "&7יוצג בפניך. פריטים" - - "&7לא ניתן לתרגם לעת עתה." updated: "&a :השפה שלך הוגדרה בהצלחה ל &b%lang%" translations: name: "&aIs משהו חסר?" @@ -68,13 +44,23 @@ guide: select: 'לחץ כדי לבחור שפה זאת ' select-default: לחץ לבחירת שפת ברירת המחדל selected-language: 'נבחר כעת:' - credits: - open: לחץ כדי לראות את התורמים שלנו + change: לחץ כדי לבחור שפה חדשה description: - - "&7 סליים פאן הוא פרויקט קוד פתוח " - - "&7ומתוחזק על ידי קהילה גדולה של אנשים." - - "&7על &e%contributors% &7אנשים עבדו" - - "&7.סליים פאן לאורך כל השנים האלה " + - "&7כעת יש לך אפשרות לשנות" + - "&7השפה שבה סליים פאן" + - "&7יוצג בפניך. פריטים" + - "&7לא ניתן לתרגם לעת עתה." + title: + main: סליים פאן מדריך + settings: 'הגדרות & מידע ' + languages: בחר את השפה המועדפת עליך + credits: סליים פאן4 תורמים + wiki: סליים פאן4 ויקי + addons: 'תוספות לסליים פאן ' + bugs: דיווחי שגיאות + source: קוד מקור + versions: גרסאות מותקנות + credits: commit: להתחייב commits: מתחייב roles: @@ -83,32 +69,60 @@ guide: resourcepack: "&c אמן חבילת משאבים" translator: "&9מתרגם" profile-link: "לחץ כדי לבקר את הפרופיל שלהם \nב -GitHub" - search: - message: &b מה תרצה לחפש? - name: "&7חפש...." - tooltip: "&b לחץ לחפש פריט" - inventory: "%item% מחפש עבור: " - cheat: - no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!" + open: לחץ כדי לראות את התורמים שלנו + description: + - "&7 סליים פאן הוא פרויקט קוד פתוח " + - "&7ומתוחזק על ידי קהילה גדולה של אנשים." + - "&7על &e%contributors% &7אנשים עבדו" + - "&7.סליים פאן לאורך כל השנים האלה " pages: previous: עמוד קודם next: עמוד הבא + tooltips: + open-category: לחץ לפתיחה + versions-notice: אלה חשובים מאוד כשמדווחים על באגים! + wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי + recipes: + machine: מתכונים שנעשו במכונה זו + miner: משאבים שתוכלו להשיג אצל כורה זה + generator: סוגי דלק זמינים + gold-pan: משאבים שתוכלו להשיג + climbing-pick: משטחים שאפשר לטפס עליהם + back: + title: חזור + guide: חזור למדריך סליים פאן + settings: חזור ללוח ההגדרות locked: נעול locked-category: - כדי לבטל את הנעילה של קטגוריה זו - 'צריך לפתוח את כל הפריטים מה ' - הקטגוריות הבאות + work-in-progress: תכונה זו עדיין לא הושלמה במלואה! messages: + not-researched: "&4אין לך מספיק ידע להבין זאת " not-enough-xp: "&4אין לך מספיק נקודות ניסיון\nכדי לפתוח את זה " + unlocked: "&b אתה פתחת %research% " + only-players: "&4 פקודה זו מיועדת רק לשחקנים" + unknown-player: "&4 :שחקן לא מוכר &c%player%" + no-permission: "&4 אין לך את ההרשאה הנדרשת לעשות זאת" + usage: "&4 שימוש: &c %שימוש%" + not-online: "&4 %שחקן%cis לא ברשת!" + given-item: '&b ניתן לך סכום &a %amount% &7"%item%7' + give-item: "&b %ניתן לך %amount% &a %item%" + give-research: '&b נתת %player% את המח"%research%&7"' + hungry: "&cאתה רעב מדיי כדי לעשות את זה!" + disabled-in-world: "&4 פריט זה הושבת בעולם זה" + disabled-item: "&4 פריט זה הושבת איך בכלל השגת את זה ?" + no-tome-yourself: "&c אינך יכול להשתמש ב- 4 כרך של מידע צמך...." + multimeter: "&bStored Energy: &3%stored% &b/ &3%capacity%" talisman: - angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה" - fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות" - caveman: "&a&oהקמע שלך נתן לך מהירות" anvil: "&a&o הקמע שלך הציל את הכלי שלך מלהישבר" miner: "&a&o הקמע שלך בכפיל את הפריטים הנופלים" hunter: "&a&o הקמע שלך בכפיל את הפריטים הנופלים" lava: "&a&oהקמע שלך הציל אותך מלהישרף למוות" water: "&a&oהקמע שלך הציל אותך מלטבוע " + angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה" + fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות" magician: "&a%o הקמע שלך העניק לך כישוף נוסף" traveller: "&a&o הקמע שלך נתן לך דחיפת מהירות" warrior: "&a&oהקמע שלך שיפר את כוחך לזמן מה" @@ -116,54 +130,8 @@ messages: whirlwind: "&a&o הקמע שלך שיקף את הטיל" wizard: "&a&o הקמע שלך העניק לך רמת הון טובה יותר אבל אולי גם הוריד כמה רמות הקסם אחרות" - fortune-cookie: - - "&7 עזור לי, אני כלוא במפעל לעוגיות " - - "&7אתה תמות מחר על ידי.... קריפר " - - "&7 בשלב מסוים בחיים שלך משהו רע יקרה!!!" - - "&7בשבוע הבא תבחין שזה לא העולם האמיתי, אתה נמצא במשחק מחשב" - - "עוגיה זו תהיה טעימה תוך כמה שניות &7" - - '&7 המילה האחרונה שתשמע תהיה "להשמיד !!!"' - - "&7מה שלא תעשה אל תחבק קריפר ניסיתי. זה מרגיש טוב,אבל לא שווה את זה" - - "&7התשובה היא 42" - - "&7 וולשי ביום ירחיקו את הצרות." - - "&7 לעולם אל תחפור ישר למטה!" - - "&7זו רק שריטה!" - - "&7תמיד תסתכל על הצד הטוב שבחיים" - - "&7זה היה למעשה ביסקוויט ולא עוגיה" - - "&7שלטי הניאון דולקים" - piglin-barter: &4 אתה לא יכול לסחור עם חזירונים באמצעות חפצי סליים פאן - enchantment-rune: - fail: "&cאת לא יכול להחליף עם חזירונים חפצים של סליים פאן." - no-enchantment: "&cלא נמצא שום קסם ישים לפריט הזה." - success: "&aהחלת בהצלחה קסם אקראי החל על פריט זה." - tape-measure: - no-anchor: "&c אתה צריך להגדיר עוגן לפני שתוכל להתחיל למדוד!" - wrong-world: "!&cנראה שהעוגן שלך נמצא בעולם אחר" - distance: "&7המדידה נלקחה &eDistance: %distance%." - anchor-set: "&aהעוגן הוגדר בהצלחה:&e %anchor%" - multi-tool: - mode-change: "&b%device% &9: המצב השתנה ל: %mode%" - not-shears: "&c מולטי טול לא יכול לשמש כמזמרה!" - climbing-pick: - dual-wielding: "&4אתה צריך להחזיק מכושי טיפוס בשתי !הידיים כדי להשתמש בהם" - wrong-material: "&cאתה לא יכול לטפס על המשטח הזה. עיין במדריך סליים פאן למידע - נוסף!" - bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה" - not-researched: "&4אין לך מספיק ידע להבין זאת " - unlocked: "&b אתה פתחת %research% " - only-players: "&4 פקודה זו מיועדת רק לשחקנים" - unknown-player: "&4 :שחקן לא מוכר &c%player%" - no-permission: "&4 אין לך את ההרשאה הנדרשת לעשות זאת" - usage: "&4 שימוש: &c %שימוש%" - not-online: "&4 %שחקן%cis לא ברשת!" - given-item: "&b ניתן לך סכום &a %amount% &7\"%item%7" - give-item: '&b %ניתן לך %amount% &a %item%' - give-research: "&b נתת %player% את המח\"%research%&7\"" - hungry: "&cאתה רעב מדיי כדי לעשות את זה!" - disabled-in-world: "&4 פריט זה הושבת בעולם זה" - disabled-item: "&4 פריט זה הושבת איך בכלל השגת את זה ?" - no-tome-yourself: "&c אינך יכול להשתמש ב- 4 כרך של מידע צמך...." - multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%' + caveman: "&a&oהקמע שלך נתן לך מהירות" + wise: "&a&oהקמע שלך הכפיל את ירידת נקודות הניסיון שלך" soulbound-rune: fail: "&c אתה יכול לקשור פריט אחד בלבד לנשמתך בכל פעם." success: "&a אתה קושרת פריט זה בהצלחה לנשמתך! אתה תשמור עליו כשתמות." @@ -182,87 +150,43 @@ messages: ברזל!" link-prompt: "&e לחץ כאן:" diet-cookie: "&eאתה מתחיל להרגיש מרחף...." + fortune-cookie: + - "&7 עזור לי, אני כלוא במפעל לעוגיות " + - "&7אתה תמות מחר על ידי.... קריפר " + - "&7 בשלב מסוים בחיים שלך משהו רע יקרה!!!" + - "&7בשבוע הבא תבחין שזה לא העולם האמיתי, אתה נמצא במשחק מחשב" + - עוגיה זו תהיה טעימה תוך כמה שניות &7 + - '&7 המילה האחרונה שתשמע תהיה "להשמיד !!!"' + - "&7מה שלא תעשה אל תחבק קריפר ניסיתי. זה מרגיש טוב,אבל לא שווה את זה" + - "&7התשובה היא 42" + - "&7 וולשי ביום ירחיקו את הצרות." + - "&7 לעולם אל תחפור ישר למטה!" + - "&7זו רק שריטה!" + - "&7תמיד תסתכל על הצד הטוב שבחיים" + - "&7זה היה למעשה ביסקוויט ולא עוגיה" + - "&7שלטי הניאון דולקים" + piglin-barter: אתה לא יכול לסחור עם חזירונים באמצעות חפצי סליים פאן + enchantment-rune: + fail: "&cאת לא יכול להחליף עם חזירונים חפצים של סליים פאן." + no-enchantment: "&cלא נמצא שום קסם ישים לפריט הזה." + success: "&aהחלת בהצלחה קסם אקראי החל על פריט זה." + tape-measure: + no-anchor: "&c אתה צריך להגדיר עוגן לפני שתוכל להתחיל למדוד!" + wrong-world: "!&cנראה שהעוגן שלך נמצא בעולם אחר" + distance: "&7המדידה נלקחה &eDistance: %distance%." + anchor-set: "&aהעוגן הוגדר בהצלחה:&e %anchor%" + multi-tool: + mode-change: "&b%device% &9: המצב השתנה ל: %mode%" + not-shears: "&c מולטי טול לא יכול לשמש כמזמרה!" + climbing-pick: + dual-wielding: "&4אתה צריך להחזיק מכושי טיפוס בשתי !הידיים כדי להשתמש בהם" + wrong-material: "&cאתה לא יכול לטפס על המשטח הזה. עיין במדריך סליים פאן למידע + נוסף!" invalid-item: "&4%item% &cאינו פריט בר תוקף!" invalid-amount: "&4%amount% &cאינו כמות ברת תוקף : המספר חייב להיות גדול מאפס!" invalid-research: "&4%research% &cאינו מחקר בר תוקף!" -anvil: - not-working: "&4אתה לא יכול להשתמש בפרטי סליים פאן בתוך סדן" - mcmmo-salvaging: "&4אתה לא יכול להציל (לתקן) חפצי סליים פאן" -workbench: - not-enhanced: "&4 אתה לא יכול להשתמש בפרטי סליים פאן על שולחן עבודה רגיל" -gps: - geo: - scan-required: |- - &4-סורק גאולוגי נדרש! - &c סרוק את הנתח הזה באמצעות סורק !גאולוגי-קודם - waypoint: - duplicate: "&4כבר יצרת נקודת ציון בשם: &f%waypoint%" - new: "&eהקלד שם לנקודת הדרך החדשה שלך בצ'אט. (קודי צבע נתמכים!)" - added: "&a נוסף בהצלחה נקודת דרך חדשה" - max: "&4 הגעת לכמות הנקודות הדרך המרבית" - deathpoint: |- - &4נקודת מוות - &7%date% - insufficient-complexity: - - "&4אין מספיק מורכבות ברשת ה GPS: &c%complexity%" - - "&4a) אין לך הגדרות רשת GPS עדיין" - - "&4b) הגדרות ה GPS שלך לא מספיק מורכבות" -languages: - zh-CN: "(מנדרינית(סין" - tl: טגלית - default: שרת ברירת מחדל - en: אנגלית - de: 'גרמנית ' - fr: צרפתית - it: איטלקית - es: ספרדית - pl: פולנית - sv: שוודית - nl: הולנדית - cs: צ'כית - hu: הונגרית - lv: לטבית - ru: רוסית - sk: סלובקית - zh-TW: "(סינית (טייוואן" - vi: וייטנאמי - id: אינדונזית - el: יווני - he: עברית - ar: ערבית - af: אפריקנית - da: דנית - fi: פינית - uk: אוקראינית - ms: מלאית - 'no': נורווגית - ja: יפנית - fa: פרסית - th: תאילנדי - ro: רומנית - pt: "(פורטוגזית (פורטוגל" - pt-BR: "(פורטוגזית (ברזיל" - bg: בולגרית - ko: קוריאנית - tr: טורקי - hr: קרואטית - mk: מקדונית - sr: סרבית - be: בלארוסית + bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה" machines: - GPS_CONTROL_PANEL: - title: לוח בקרה - ג'י פי אס - transmitters: סקירה משדר - waypoints: סקירת נקודות דרך - INDUSTRIAL_MINER: - no-fuel: &c לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל. - piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!" - piston-space: "&cלשתי הבוכנות צריך להיות בלוק מעליהן!" - destroyed: "&cנראה שכורה התעשייתי שלך הושמד." - already-running: "&cהכורה התעשייתית הזה עדיין פועל." - full-chest: "&cהתיבה של הכורה התעשייתי שלך מלאה!" - no-permission: נראה שאין לך אישור להפעיל כאן כורה תעשייתי!&4 - finished: "&eהכורה התעשייתי שלך סיים את !%ores% ore(s)!עבודתו! הוא חצב" pattern-not-found: "&e סליחה לא יכולתי \n .לזהות את המתכון \nאנא הכנס את \nהפריטים בדפוס הנכון לתוך המתקן " unknown-material: "&e סליחה, לא יכולתי לזהות את הפריט במתקן שלי. אנא הכנס משהו שאני @@ -273,7 +197,8 @@ machines: in-use: "&c המלאי של בלוק זה נפתח כרגע על ידי שחקן אחר." ignition-chamber-no-flint: "&c תא הצתה חסר צור ופלדה." ANCIENT_ALTAR: - not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals% /\n8( " + not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals% + /\n8( " unknown-catalyst: "&4 זרז לא ידוע! &c השתמש במתכון הנכון במקום זאת!" unknown-recipe: "&4 מתכון לא ידוע! &cהשתמש במתכון הנכון במקום!" ANCIENT_PEDESTAL: @@ -301,17 +226,50 @@ machines: time: זמן משוער CARGO_NODES: must-be-placed: "&4חייב להיות מונח על תיבה או מכונה!" -brewing_stand: - not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!" -villagers: - no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!" -cartography_table: - not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!" -cauldron: - no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן" + GPS_CONTROL_PANEL: + title: לוח בקרה - ג'י פי אס + transmitters: סקירה משדר + waypoints: סקירת נקודות דרך + INDUSTRIAL_MINER: + no-fuel: לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל. + piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!" + piston-space: "&cלשתי הבוכנות צריך להיות בלוק מעליהן!" + destroyed: "&cנראה שכורה התעשייתי שלך הושמד." + already-running: "&cהכורה התעשייתית הזה עדיין פועל." + full-chest: "&cהתיבה של הכורה התעשייתי שלך מלאה!" + no-permission: נראה שאין לך אישור להפעיל כאן כורה תעשייתי!&4 + finished: "&eהכורה התעשייתי שלך סיים את !%ores% ore(s)!עבודתו! הוא חצב" +anvil: + not-working: "&4אתה לא יכול להשתמש בפרטי סליים פאן בתוך סדן" + mcmmo-salvaging: "&4אתה לא יכול להציל (לתקן) חפצי סליים פאן" +backpack: + already-open: "&cסליחה התרמיל הזה פתוח במקום אחר " + no-stack: "&cאתה לא יכול לערום תרמילים" +workbench: + not-enhanced: "&4 אתה לא יכול להשתמש בפרטי סליים פאן על שולחן עבודה רגיל" +gps: + deathpoint: |- + &4נקודת מוות + &7%date% + waypoint: + new: "&eהקלד שם לנקודת הדרך החדשה שלך בצ'אט. (קודי צבע נתמכים!)" + added: "&a נוסף בהצלחה נקודת דרך חדשה" + max: "&4 הגעת לכמות הנקודות הדרך המרבית" + duplicate: "&4כבר יצרת נקודת ציון בשם: &f%waypoint%" + insufficient-complexity: + - "&4אין מספיק מורכבות ברשת ה GPS: &c%complexity%" + - "&4a) אין לך הגדרות רשת GPS עדיין" + - "&4b) הגדרות ה GPS שלך לא מספיק מורכבות" + geo: + scan-required: |- + &4-סורק גאולוגי נדרש! + &c סרוק את הנתח הזה באמצעות סורק !גאולוגי-קודם +inventory: + no-access: "&4אין לך גישה לבלוק הזה" android: + started: "&7 האנדרואיד שלך ממשיך את תסריט" + stopped: "&7 האנדרואיד שלך \nעצר את התסריט " scripts: - too-long: "&c!התסריט ארוך מכדי לערוך" already-uploaded: "&4 התסריט הזה כבר הועלה." instructions: START: "&2 התחל תסריט" @@ -350,10 +308,56 @@ android: own: "&4אתה לא יכול לדרג את התסריט שלך עצמך!" already: "&4אתה כבר השארת דירוג לתסריט זה!" editor: עורך תסריט - started: "&7 האנדרואיד שלך ממשיך את תסריט" - stopped: "&7 האנדרואיד שלך \nעצר את התסריט " -backpack: - already-open: "&cסליחה התרמיל הזה פתוח במקום אחר " - no-stack: "&cאתה לא יכול לערום תרמילים" -inventory: - no-access: "&4אין לך גישה לבלוק הזה" + too-long: "&c!התסריט ארוך מכדי לערוך" +languages: + default: שרת ברירת מחדל + en: אנגלית + de: 'גרמנית ' + fr: צרפתית + it: איטלקית + es: ספרדית + pl: פולנית + sv: שוודית + nl: הולנדית + cs: צ'כית + hu: הונגרית + lv: לטבית + ru: רוסית + sk: סלובקית + zh-TW: "(מנדרינית (טייוואן" + vi: וייטנאמי + id: אינדונזית + zh-CN: "(מנדרינית(סין" + el: יווני + he: עברית + ar: ערבית + af: אפריקנית + da: דנית + fi: פינית + uk: אוקראינית + ms: מלאית + 'no': נורווגית + ja: יפנית + fa: פרסית + th: תאילנדי + ro: רומנית + pt: "(פורטוגזית (פורטוגל" + pt-BR: "(פורטוגזית (ברזיל" + bg: בולגרית + ko: קוריאנית + tr: טורקי + hr: קרואטית + mk: מקדונית + sr: סרבית + be: בלארוסית + tl: טגלית +brewing_stand: + not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!" +villagers: + no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!" +cartography_table: + not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!" +cauldron: + no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן" +placeholderapi: + profile-loading: בטעינה... diff --git a/src/main/resources/languages/messages_hu.yml b/src/main/resources/languages/messages_hu.yml index 7a806b08e..1f8132d3c 100644 --- a/src/main/resources/languages/messages_hu.yml +++ b/src/main/resources/languages/messages_hu.yml @@ -134,6 +134,7 @@ messages: wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb varázslatot gyengített" caveman: "&a&oA talizmánod adott Sietség effektet" + wise: "&a&oA talizmánod megduplázta a dobott tapasztalat pontokat" soulbound-rune: fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez." success: "&aSikeresen hozzákötötted ezt a tárgyat a lelkedhez! Megmarad, amikor @@ -313,6 +314,7 @@ android: own: "&4Nem értékelheted a saját szkriptedet!" already: "&4Ezt a szkriptet már értékelted!" editor: Szkript szerkesztő + too-long: "&cA szkript túl hosszú a szerkesztéshez!" languages: default: Szerver-alapértelmezett en: Angol diff --git a/src/main/resources/languages/messages_ja.yml b/src/main/resources/languages/messages_ja.yml index d008529e0..f01c7711e 100644 --- a/src/main/resources/languages/messages_ja.yml +++ b/src/main/resources/languages/messages_ja.yml @@ -133,6 +133,7 @@ messages: whirlwind: "&a&oタリスマンが飛び道具から身を護った" wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった" caveman: "&a&oタリスマンが採掘速度を上昇させた" + wise: "&a&oタリスマンが経験値のドロップを倍にした" soulbound-rune: fail: "&c一度に複数アイテムとのバインディングはできません" success: "&aアイテムとのバインディングが確立した!リスポーン時に当該アイテムは手繰り寄せられます" @@ -319,7 +320,6 @@ languages: el: ギリシャ語 he: ヘブライ語 pt: ポルトガル語(ポルトガル) - pt-BR: ポルトガル語(ブラジル) ar: アラビア語 af: アフリカーンス語 da: デンマーク語 @@ -331,6 +331,7 @@ languages: fa: ペルシア語 th: タイ語 ro: ルーマニア語 + pt-BR: ポルトガル語(ブラジル) bg: ブルガリア語 ko: 韓国語 tr: トルコ語 @@ -349,3 +350,5 @@ cauldron: no-discoloring: "&4Slimefunアイテムの脱色はできません" miner: no-ores: "&e周辺には鉱石が見つかりませんでした!" +placeholderapi: + profile-loading: ロード中… diff --git a/src/main/resources/languages/messages_nl.yml b/src/main/resources/languages/messages_nl.yml index 199735711..5297d9a27 100644 --- a/src/main/resources/languages/messages_nl.yml +++ b/src/main/resources/languages/messages_nl.yml @@ -4,7 +4,6 @@ commands: cheat: Geeft je toestemming om gratis spullen in het spel te brengen give: Geef iemand een aantal Slimefun spullen guide: Geef jezelf een Slimefun Handboek - timings: Laat informatie over de server's prestaties zien teleporter: Bekijk de opgeslagen locaties van andere spelers versions: Laat een lijst met alle geïnstalleerde uitbreidingen zien search: Doorzoek de Slimefun handleiding voor een bepaald trefwoord @@ -15,6 +14,18 @@ commands: description: Ontgrendel of herstart Slimefun kennissen van een speler reset: "&cJe hebt %player%'s Slimefun kennis herstart" reset-target: "&cJe Slimefun kennis is herstart" + backpack: + description: Krijg een kopie van een al bestaande rugzak + invalid-id: "&4Het id moet een positieve nummer zijn!" + player-never-joined: "&4Er is geen speler met die naam gevonden!" + backpack-does-not-exist: "& 4De opgegeven rugzak bestaat niet!" + restored-backpack-given: "&aJouw rugzak is hersteld en is toegevoegd aan jouw + inventaris." + charge: + description: Laad het item wat je vasthoud op + charge-success: Item is opgeladen! + not-rechargeable: Dit item kan niet opgeladen worden! + timings: Laat informatie over de server's prestaties zien guide: search: message: "&bOp welk woord zou je willen zoeken?" @@ -22,8 +33,8 @@ guide: tooltip: "&bKlik om naar een item te zoeken" inventory: 'Zoeken naar: %item%' lore: - - "&bOp welk woord zou je willen zoeken?" - - "&7Type je zoekterm in het gespreksvenster" + '1': "&7Type je zoekterm in het gespreksvenster" + '0': "&bOp welk woord zou je willen zoeken?" cheat: no-multiblocks: "&4Je kan geen Slimefun machines in het spel brengen, je moet ze bouwen zoals aangegeven." @@ -34,7 +45,13 @@ guide: lore: Klik om een eigen vertaling toe the voegen select: Klik om deze taal te selecteren select-default: Klik om de standaard taal te selecteren - selected-language: 'Momenteel geselecteerd:' + selected-language: " Op dit moment geselecteerd:" + change: Klik om een nieuwe taal te kiezen + description: + '0': "&7Je hebt nu de mogelijkheid om de taal" + '1': "&7van Slimefun te veranderen" + '2': "&7aan jou wordt vertoond. Items" + '3': "&7kunnen momenteel niet vertaald worden." title: main: Slimefun Handboek settings: Instellingen & Informatie @@ -44,6 +61,7 @@ guide: addons: Uitbreidingen voor Slimefun4 bugs: Fouten rapporteren source: Source Code + versions: Geïnstalleerde versies credits: commit: Bijdrage commits: Bijdragen @@ -53,6 +71,12 @@ guide: resourcepack: "&cGrafische bundel Ontwikkelaar" translator: "&9Vertaler" profile-link: Klik om hun profielen op Github te bezoeken + open: Klik om onze bijdragers te zien + description: + '0': "&7Slimefun is een open-source project" + '1': "&7en wordt in stand gehouden door een grote gemeenschap van mensen." + '2': "&7Meer dan &e%contributors% &7mensen hebben hieraan" + '3': "&7al deze jaren gewerkt." pages: previous: Vorige bladzijde next: Volgende bladzijde @@ -65,15 +89,17 @@ guide: miner: Grondstoffen die je met deze Miner kunt verkrijgen generator: Beschikbare soorten brandstof gold-pan: Grondstoffen die je kunt verkrijgen + climbing-pick: Oppervlakken die je kunt beklimmen back: title: Terug guide: Ga terug naar de Slimefun Handleiding settings: Ga terug naar Instellingen locked: VERGRENDELD locked-category: - - Om deze categorie te ontgrendelen zul je - - alle items moeten ontgrendelen van de - - volgende categorieën + '0': Om deze categorie te ontgrendelen zul je + '1': alle items moeten ontgrendelen van de + '2': volgende categorieën + work-in-progress: Dit is nog niet helemaal klaar! messages: not-researched: "&4Je hebt niet genoeg Slimefun kennis om dit te begrijpen" not-enough-xp: "&4Je hebt niet genoeg XP om dit te ontgrendelen" @@ -83,12 +109,8 @@ messages: no-permission: "&4Je hebt geen toestemming om deze actie uit te voeren" usage: "&4Gebruik, zoals: &c%usage%" not-online: "&4%player% &cis niet online!" - invalid-item: "&4%item% &cis geen geldig voorwerp!" - invalid-amount: "&4%amount% &cis geen geldige hoeveelheid: het moet meer zijn - dan 0!" given-item: '&bJe hebt &a%amount% keer &7"%item%&7" ontvangen' give-item: '&bJe hebt %player% &a%amount% keer &7"%item%&7" gegeven' - invalid-research: "&4%research% &cis geen geldig Slimefun onderzoek" give-research: '&bJe hebt %player% de kennis over &7"%research%&7" gegeven' hungry: "&cJe hebt teveel honger om zoiets te doen!" disabled-in-world: "&4&lDit voorwerp is uitgeschakeld in deze wereld" @@ -110,6 +132,8 @@ messages: whirlwind: "&a&oJe Talisman heeft het projectiel weerkaatst" wizard: "&a&oJe Talisman heeft je een hoger level van geluk gegeven, maar heeft misschien ook de levels van andere betoveringen verlaagd" + caveman: "&a&oJe talisman gaf je haast" + wise: "&a&oJe Talisman heeft je verkregen experience punten verdubbeld" soulbound-rune: fail: "&cJe kan maar één voorwerp met je ziel verbinden op elk moment" success: "&aJe hebt dit voorwerp succesvol met je ziel verbonden! Het blijft bij @@ -129,19 +153,46 @@ messages: link-prompt: "&eKlik mij:" diet-cookie: "&eJe begint je zo ligt als een veertje te voelen..." fortune-cookie: - - "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!" - - "&7Je overlijdt morgen... door een creeper..." - - "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha" - - "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld is, - maar een simulatie" - - "&7Dit koekje gaat over een paar seconden heerlijk smaken" - - '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld alleen - maar vals!"' - - "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd, - maar het is het echt niet waard" - - "&742. Het antwoord op alles is 42" - - "&7A Walshy, één dag houdt alle problemen weg" - - "&7Graaf nooit recht naar beneden!" + '0': "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!" + '1': "&7Je overlijdt morgen... door een creeper..." + '2': "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha" + '3': "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld + is, maar een simulatie" + '4': "&7Dit koekje gaat over een paar seconden heerlijk smaken" + '5': '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld + alleen maar vals!"' + '6': "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd, + maar het is het echt niet waard" + '7': "&742. Het antwoord op alles is 42" + '8': "&7A Walshy, één dag houdt alle problemen weg" + '9': "&7Graaf nooit recht naar beneden!" + '10': "&7Het is slechts een vleeswonde!" + '11': "&7Kijk altijd naar de blije kant van je leven!" + '12': "&7Deze was eigenlijk een biscuitje en geen koekje" + '13': "&7Neon borden zijn LIT!" + piglin-barter: "&4Je kunt geen Slimefun spullen met piglins ruilen" + enchantment-rune: + fail: "&cJe kunt dit item niet betoveren." + no-enchantment: "&cKon geen mogelijke betoveringen vinden voor dit item." + success: "&aJe hebt succesvol een random betovering toegevoegd op dit item." + tape-measure: + no-anchor: "&cJe hebt nog een anker nodig voordat je kunt meten!" + wrong-world: "&cJe anker lijkt in een andere wereld te zitten!" + distance: "&7Afstand gemeten. &eAfstand: %distance%" + anchor-set: "&aHet is gelukt om het anker in te stellen:&e %anchor%" + multi-tool: + mode-change: "&b%device% mode veranderd naar: &9%mode%" + not-shears: "&cEen Mutli Tool kan niet gebruikt worden als een schaar!" + climbing-pick: + dual-wielding: "&4Je moet een klim-pickaxe in bijde handen hebben om hem te gebruiken!" + wrong-material: "&cJe kunt dit oppervlak niet beklimmen. Check je Slimefun Guide + voor meer info!" + invalid-item: "&4%item% &cis geen geldig voorwerp!" + invalid-amount: "&4%amount% &cis geen geldige hoeveelheid: het moet meer zijn dan + 0!" + invalid-research: "&4%research% &cis geen geldig Slimefun onderzoek" + bee-suit-slow-fall: "&eJe Bee Wings zullen je helpen om weer veilig op de grond + te komen" mode-change: "&b%device% mode is veranderd naar: &9%mode%" machines: pattern-not-found: "&eSorry, ik heb het recept niet herkend. Plaats astublieft de @@ -187,8 +238,20 @@ machines: title: GPS - Configuratiescherm transmitters: Transmitter-overzicht waypoints: Waypoint-overzicht + INDUSTRIAL_MINER: + no-fuel: "& cUw Industrial Miner heeft geen brandstof meer! Doe de brandstof in + de kist erboven." + piston-facing: "&cJe Industrial Miner moet de duwmachines naar boven hebben!" + piston-space: "&cDe twee duwmachines moeten een leeg blok boven hem hebben!" + destroyed: "&cJouw Industrial Miner lijkt vernietigt te zijn!" + already-running: "&cDeze Industrial Miner draait al!" + full-chest: "&cDe kist van je Industrial Miner is vol!" + no-permission: "&4Het lijkt er op dat je geen permissie hebt om een Industrial + Miner hier te laten werken!" + finished: "&eJe Industrial Miner is klaar! Het heeft in totaal %ores% grondstof(fen)! " anvil: not-working: "&4Je kan geen Slimefun voorwerpen gebruiken in een aambeeld!" + mcmmo-salvaging: "&4Je kunt geen Slimefun items afbreken!" backpack: already-open: "&cSorry, deze rugzak is al ergens anders geopend!" no-stack: "&cJe kan geen rugzakken stapelen" @@ -201,10 +264,11 @@ gps: &r(Kleurcodes zijn ondersteund)" added: "&aEen nieuw locatiepunt is succesvol toegevoegd" max: "&4Je hebt het maximum aantal locatiepunten bereikt" + duplicate: "&4Je hebt al een waypoint genaamd: &f%waypoint%" insufficient-complexity: - - "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%" - - "&4a) Je hebt nog geen GPS netwerk opgezet" - - "&4b) Je GPS netwerk is niet complex genoeg" + '0': "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%" + '1': "&4a) Je hebt nog geen GPS netwerk opgezet" + '2': "&4b) Je GPS netwerk is niet complex genoeg" geo: scan-required: "&4Een GEO-Scan is nodig! &cScan deze chunk eerst met behulp van een GEO-Scanner!" @@ -243,15 +307,15 @@ android: INTERFACE_ITEMS: "&9Geef inventaris aan de geconfronteerde interface" INTERFACE_FUEL: "&cOntvang brandstof van de geconfronteerde interface" enter-name: - - - - "&eType astublieft de gewenste naam in voor het script" + '1': "&eType astublieft de gewenste naam in voor het script" uploaded: - - "&bBezig met uploaden..." - - "&aHet script is succesvol geupload!" + '0': "&bBezig met uploaden..." + '1': "&aHet script is succesvol geupload!" rating: own: "&4Je kan je eigen script geen waardering geven!" already: "&4Je hebt aan een waardering achtergelaten voor dit script!" editor: Scripteditor + too-long: "&cDe code is te lang om te kunnen editen!" languages: default: Server-Standaard en: Engels @@ -284,10 +348,25 @@ languages: fa: Perzisch th: Thais ro: Roemeens - pt: Portugees (Portugal) + pt: Portugees (Portugal) pt-BR: Portugees (Brazilië) bg: Bulgaars ko: Koreaans tr: Turks + hr: Kroatisch + mk: Macedonisch + sr: Servisch + be: Wit-Russisch/Russisch + tl: Tagalog +brewing_stand: + not-working: "&4Je kunt geen Slimefun spullen in een brouwstandaard doen!" +villagers: + no-trading: "&4Je kunt geen Slimefun spullen met villagers ruilen!" +cartography_table: + not-working: "&4Je kunt Slimefun items niet in een cartografie tafel gebruiken!" +cauldron: + no-discoloring: "&4Je kunt de kleur van Slimefun Bescherming niet er af halen" +placeholderapi: + profile-loading: Aan het laden... miner: no-ores: "&eSorry, ik kon geen ertsen vinden dichtbij!" diff --git a/src/main/resources/languages/messages_vi.yml b/src/main/resources/languages/messages_vi.yml index a889cff2d..f78002beb 100644 --- a/src/main/resources/languages/messages_vi.yml +++ b/src/main/resources/languages/messages_vi.yml @@ -26,8 +26,8 @@ commands: not-rechargeable: Vật phẩm này không thể sạc được! timings: description: Độ trễ của slimefun và addon của nó - verbose-player: "&4Cờ dài này không thể sử dụng bới Người chơi!" please-wait: "&eVui lòng đợi một chút... Kết quả chuẩn bị đến!" + verbose-player: "&4Cờ dài này không thể sử dụng bới Người chơi!" unknown-flag: "&4Không rõ cờ: &c%flag%" guide: search: @@ -138,6 +138,7 @@ messages: wizard: "&a&oBùa hộ mệnh của bạn đã cho bạn một Cấp độ may mắn tốt hơn nhưng cũng có thể hạ thấp một số Cấp độ phù phép khác" caveman: "&a&oBùa ma thuật của bạn cho bạn hiệu ứng Đào nhanh" + wise: "&a&oBùa ma thuật đã nhân đôi số kinh nghiệm của bạn" soulbound-rune: fail: "&cBạn chỉ có thể liên kết một vật phẩm với linh hồn của bạn trong cùng một thời điểm." @@ -375,3 +376,5 @@ cauldron: no-discoloring: "&4Bạn không thể đổi màu giáp của Slimefun" miner: no-ores: "&eXin lỗi, tôi không thể tìm bất kì Khoáng sản nào xung quanh!" +placeholderapi: + profile-loading: Đang tải... diff --git a/src/main/resources/languages/messages_zh-CN.yml b/src/main/resources/languages/messages_zh-CN.yml index 1e72adead..08ef7fbee 100644 --- a/src/main/resources/languages/messages_zh-CN.yml +++ b/src/main/resources/languages/messages_zh-CN.yml @@ -133,6 +133,7 @@ messages: whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物" wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降" caveman: "&a&o你的护身符给予了你急迫效果" + wise: "&a&o你的护身符让掉落的经验翻倍了" soulbound-rune: fail: "&c灵魂一次只能绑定一个物品." success: "&a物品绑定成功! 在你死亡后此物品将不会掉落." @@ -319,7 +320,6 @@ languages: el: 希腊语 he: 希伯来语 pt: 葡萄牙语 (葡萄牙) - pt-BR: 葡萄牙语 (巴西) ar: 阿拉伯语 af: 南非语 da: 丹麦语 @@ -331,6 +331,7 @@ languages: fa: 波斯语 th: 泰语 ro: 罗马尼亚语 + pt-BR: 葡萄牙语 (巴西) bg: 保加利亚语 ko: 韩语 tr: 土耳其语 @@ -349,3 +350,5 @@ cauldron: no-discoloring: "&4你不能用炼药锅洗去 Slimefun 物品的颜色" miner: no-ores: "&e抱歉, 周围找不到矿石了!" +placeholderapi: + profile-loading: 加载中... diff --git a/src/main/resources/languages/messages_zh-TW.yml b/src/main/resources/languages/messages_zh-TW.yml index e8cf8f43d..c3cdb0be1 100644 --- a/src/main/resources/languages/messages_zh-TW.yml +++ b/src/main/resources/languages/messages_zh-TW.yml @@ -133,6 +133,7 @@ messages: whirlwind: "&a&o你的護符反射了投射物" wizard: "&a&o你的護符為你升高了幸運等級,但也降低了其他附魔等級" caveman: "&a&o你的護符給了你挖掘加速效果" + wise: "&a&o你的護身符加倍了你得到的經驗值" soulbound-rune: fail: "&c你一次只能靈魂綁定一個物品。" success: "&a您已成功將此物品綁定靈魂!死後不會掉落。" @@ -318,7 +319,6 @@ languages: zh-CN: 中文(簡體) el: 希臘語 he: 希伯來語 - pt: 葡萄牙文(葡萄牙) pt-BR: 葡萄牙文(巴西) ar: 阿拉伯文 af: 南非語 @@ -331,6 +331,7 @@ languages: fa: 波斯語 th: 泰語 ro: 羅馬尼亞語 + pt: 葡萄牙文(葡萄牙) bg: 保加利亞語 ko: 韓語 tr: 土耳其 @@ -349,3 +350,5 @@ cauldron: no-discoloring: "&4你不能把 Slimefun 裝備的顏色消除!" miner: no-ores: "&e附近沒礦了!" +placeholderapi: + profile-loading: 載入中…… diff --git a/src/main/resources/languages/recipes_cs.yml b/src/main/resources/languages/recipes_cs.yml new file mode 100644 index 000000000..48fac2597 --- /dev/null +++ b/src/main/resources/languages/recipes_cs.yml @@ -0,0 +1,168 @@ +--- +slimefun: + multiblock: + name: Multiblock + lore: + '0': Postav ukázanou konstrukci, + '1': jak je ukázáno. Nevyrábí se. + enhanced_crafting_table: + name: Enhanced Crafting Table + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za pomocí Enhanced Crafting Table + '2': Normální pracovní stůl nebude stačit! + armor_forge: + name: Armor Forge + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Armor Forge + grind_stone: + name: Brusný kámen + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití brusného kamene + smeltery: + name: Smeltery + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Smeltery + ore_crusher: + name: Ore Crusher + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Ore Crusher + mob_drop: + lore: + '0': Zabij tohle stvoření + '1': k získání tohoto předmětu + name: Mob Drop + gold_pan: + name: Gold Pan + lore: + '0': Použij Gold Pan k + '1': získání tohoto předmětu + compressor: + name: Compressor + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Compressor + pressure_chamber: + name: Pressure Chamber + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Pressure Chamber + ore_washer: + name: Ore Washer + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Ore Washer + juicer: + name: Juicer + lore: + '0': Vyrob tento džus, jak je je ukázáno, + '1': za použití Juicer + magic_workbench: + name: Magic Workbench + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Magic Workbench + ancient_altar: + name: Ancient Altar + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Ancient Altar. + '2': Podívej se na Ancient Altar pro více informací + heated_pressure_chamber: + name: Heated Pressure Chamber + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Heated Pressure Chamber + food_fabricator: + name: Food Fabricator + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Food Fabricator + food_composter: + name: Food Composter + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Food Composter + freezer: + name: Freezer + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Freezer + geo_miner: + name: GEO Miner + lore: + '0': Tento předmět lze shromažďovat + '1': pomocí GEO Miner + nuclear_reactor: + name: Nuclear Reactor + lore: + '1': při provozování v Nuclear Reactor + '0': Tento předmět je vedlejší produkt + oil_pump: + name: Oil Pump + lore: + '0': Tento předmět lze shromažďovat + '1': pomocí Oil Pump + pickaxe_of_containment: + name: Pickaxe of Containment + lore: + '1': těžbou líhně pomocí + '2': Pickaxe of Containment + '0': Tento blok lze získat + refinery: + name: Refinery + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití Rafinery + barter_drop: + name: Piglin Bartering Drop + lore: + '0': Vyměňuj s pigliny zlaté + '1': ingoty k získání tohoto předmětu +minecraft: + shaped: + name: Recept na výrobu ve tvaru + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': v normálním pracovním stole + '2': Tvar je důležitý. + shapeless: + name: U receptu nezáleží na tvaru + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': v normálním pracovním stole + '2': Tento recept je beztvarý. + furnace: + lore: + '0': Roztav tento předmět v peci + '1': k vyrobení vysněného předmětu + name: Recept na pec + blasting: + name: Recept na tavicí pec + lore: + '0': Roztav tento předmět v tavící peci + '1': k vyrobení vysněného předmětu + smoking: + name: Recept na troubu + lore: + '0': Upeč tenhle předmět v troubě + '1': k vyrobení vysněného předmětu + campfire: + lore: + '0': Upeč tenhle předmět v táboráku + '1': k vyrobení vysněného předmětu + name: Recept na táborák + stonecutting: + name: Recept na řezačku kamene + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití řezačky kamene + smithing: + name: 'Recept na kovářský stůl ' + lore: + '0': Vyrob tento předmět, jak je ukázáno, + '1': za použití kovářského stolu diff --git a/src/main/resources/languages/researches_cs.yml b/src/main/resources/languages/researches_cs.yml index 98beb4b7a..3ab80b996 100644 --- a/src/main/resources/languages/researches_cs.yml +++ b/src/main/resources/languages/researches_cs.yml @@ -1,232 +1,252 @@ --- slimefun: walking_sticks: Vycházkové hole + portable_crafter: Přenosný pracovní stůl + fortune_cookie: Sušenka štěstí + portable_dustbin: Přenosný koš meat_jerky: Sušené maso - armor_forge: Crafťák brnění + armor_forge: Kovadlina na brnění + glowstone_armor: Světlitové brnění + lumps: Kousky a magie + ender_backpack: Enderitový batoh + ender_armor: Enderitové Brnění + magic_eye_of_ender: Magické endové oko + magic_sugar: Magický cukr monster_jerky: Sušené maso z monstra - steel: Ocelová doba - jetpacks: Jetpacks - multitools: Víceúčelové nástroje - synthetic_sapphire: Syntetické Safíry - damascus_steel_armor: Brnění z Damašské Oceli - portable_crafter: Přenosný Crafťák - fortune_cookie: Sušenka Štěstí - portable_dustbin: Přenosný Koš - glowstone_armor: Světlitové Brnění - lumps: Kousky a Magie - ender_backpack: Ender Batoh - ender_armor: Ender Brnění - magic_eye_of_ender: Magické Oko Endu - magic_sugar: Magický Cukr - slime_armor: Slizové Brnění - sword_of_beheading: Meč na Sekání Hlav - basic_circuit_board: Základní Deska - advanced_circuit_board: Pokročilá Deska + slime_armor: Brnění ze slizu + sword_of_beheading: Meč na sekání hlav + basic_circuit_board: Základní deska + advanced_circuit_board: Pokročilá deska s obvody smeltery: Tavírna - misc_power_items: Důležité itemy související s elekronikou + steel: Doba ocelová + misc_power_items: Důležité předměty související s elekronikou battery: Tvoje první baterie - steel_plate: Ocelové Plátování - steel_thruster: Ocelová Tryska + steel_plate: Ocelový plát + steel_thruster: Ocelová tryska parachute: Padák - grappling_hook: Záchytný Hák - solar_panel_and_helmet: Solární Energie - elemental_staff: Hůlky Elementů - grind_stone: Kámen na Broušení - cactus_armor: Kaktusový Oblek - gold_pan: Zlatá Pánev - magical_book_cover: Magická Knižní Vazba - slimefun_metals: Nové Kovy - ore_crusher: Dvojnásobení Rud - bronze: Vytvoření Bronzu - alloys: Pokročíle Slitiny - compressor_and_carbon: Vytvoření Karbonu - gilded_iron_armor: Pozlacené Železné Brnění - synthetic_diamond: Syntetické Diamanty - pressure_chamber: Tlaková Komora - damascus_steel: Damašská Ocel - reinforced_alloy: Zesílená Slitina - carbonado: Černé Diamanty - magic_workbench: Magický Pracovní Stůl - wind_staff: Větrná Hůl - reinforced_armor: Zesílené Brnění - ore_washer: Čištič Rud - gold_carats: Čisté Zlato - silicon: Silicon Valley - fire_staff: Ohnivá Hůl - smelters_pickaxe: Hutní Krumpáč - common_talisman: Běžný Talisman - anvil_talisman: Talisman Kovadliny - miner_talisman: Talisman Horníka - hunter_talisman: Talisman Lovce - lava_talisman: Talisman Chodce po Lávě - water_talisman: Talisman Dýchače Vody - angel_talisman: Talisman Anděla - fire_talisman: Talisman Požárníka - lava_crystal: Ohnivá Situace - magician_talisman: Talisman Kouzelníka - traveller_talisman: Talisman Cestovatele - warrior_talisman: Talisman Bojovníka - knight_talisman: Talisman Rytíře - gilded_iron: Lesklé Železo - synthetic_emerald: Falešný Drahokam - chainmail_armor: Řetězová Zbroj - whirlwind_talisman: Talisman Vichřice - wizard_talisman: Talisman Čaroděje - lumber_axe: Dřevorubecká Sekera - hazmat_suit: Hazmat Oblek + grappling_hook: Vystřelující hák + jetpacks: Raketový batoh + multitools: Víceúčelové nástroje + solar_panel_and_helmet: Solární energie + elemental_staff: Elementární hůlky + grind_stone: Brusný kámen + cactus_armor: Oblek z kaktusu + gold_pan: Rýžovací miska + magical_book_cover: Magické vázání knihy + slimefun_metals: Nové kovy + ore_crusher: Zdvojování rud + bronze: Výroby bronzu + alloys: Pokročilé slitiny + compressor_and_carbon: Výroby karbonu + gilded_iron_armor: Pozlacené železné brnění + synthetic_diamond: Syntetické diamanty + pressure_chamber: Tlaková komora + synthetic_sapphire: Syntetické safíry + damascus_steel: Damašková ocel + damascus_steel_armor: Brnění z damaškové ocely + reinforced_alloy: Zpevněná slitina + carbonado: Černé diamanty + magic_workbench: Magický pracovní stůl + wind_staff: Větrná hůl + reinforced_armor: Zpěvněné brnění + ore_washer: Čištič rud + gold_carats: Čisté zlato + silicon: Křemíkové údolí + fire_staff: Ohnivá hůl + smelters_pickaxe: Hutní krumpáč + common_talisman: Běžný talisman + anvil_talisman: Talisman kovadliny + miner_talisman: Talisman horníka + hunter_talisman: Talisman lovce + lava_talisman: Talisman chodce po lávě + water_talisman: Talisman dýchání pod vodou + angel_talisman: Talisman anděla + fire_talisman: Talisman hasiče + lava_crystal: Ohnivá situace + magician_talisman: Talisman kouzelníka + traveller_talisman: Talisman cestovatele + warrior_talisman: Talisman bojovníka + knight_talisman: Talisman rytíře + gilded_iron: Lesklé železo + synthetic_emerald: Falešný drahokam + chainmail_armor: Kroužková zbroj + whirlwind_talisman: Talisman vichřice + wizard_talisman: Talisman čaroděje + lumber_axe: Dřevorubecká sekera + hazmat_suit: Hazmat oblek uranium: Radioaktivní - crushed_ore: Čištění rud - redstone_alloy: Ruditové Slitiny - carbonado_tools: Nejlepší Stroje - first_aid: První Pomoc - gold_armor: Lesklé Brnění - night_vision_googles: Brýle Nočního Vidění - pickaxe_of_containment: Krumpáč Zadržení - hercules_pickaxe: Herkulesův Krumpáč - table_saw: Stolní Pila - slime_steel_armor: Slizově-Ocelové Brnění - blade_of_vampires: Čepel Vampírů - water_staff: Vodní Hůl - 24k_gold_block: Zlaté Město - composter: Kompostování Hlíny - farmer_shoes: Boty Farmáře - explosive_tools: Výbušné Nastroje - automated_panning_machine: Automatická Zlatá Pánev - boots_of_the_stomper: Boty Dupače - pickaxe_of_the_seeker: Krumpáč Hledače + crushed_ore: Očišťování rud + redstone_alloy: Ruditové slitiny + carbonado_tools: Nejlepší stroje + first_aid: První pomoc + gold_armor: Lesklé brnění + night_vision_googles: Brýle pro noční vidění + pickaxe_of_containment: Krumpáč zadržení + hercules_pickaxe: Herkulesův krumpáč + table_saw: Stolní pila + slime_steel_armor: Brnění ze slizu a oceli + blade_of_vampires: Čepel vampírů + water_staff: Vodní hůl + 24k_gold_block: Zlaté město + composter: Kompostování hlíny + farmer_shoes: Boty farmáře + explosive_tools: Výbušné nástroje + automated_panning_machine: Automatická rýžovací miska + boots_of_the_stomper: Boty dupače + pickaxe_of_the_seeker: Krumpáč hledače backpacks: Batohy - woven_backpack: Tkaný Batoh + woven_backpack: Tkaný batoh crucible: Kotel - gilded_backpack: Vázaný Batoh - armored_jetpack: Trysky s Brněním - ender_talismans: Ender Talismany + gilded_backpack: Vázaný batoh + armored_jetpack: Obrněný raketový batoh + ender_talismans: Enderitové talismany nickel_and_cobalt: Ještě více rud magnet: Magnetické kovy - infused_magnet: Infuzovaný Magnet - cobalt_pickaxe: Urychlený Krumpáč - essence_of_afterlife: Necromancie - bound_backpack: Duší-vázané Ůložistě - jetboots: Tryskové Boty - armored_jetboots: Obrněné Tryskové Boty - seismic_axe: Seizmická Sekera - pickaxe_of_vein_mining: Krumpáč Těžení Nalezišť - bound_weapons: Duší-vázané Zbraně - bound_tools: Duší-vázané Nástroje - bound_armor: Duší-vázané Brnění - juicer: Výborné Pití - repaired_spawner: Opravování Spawnerů - enhanced_furnace: Vylepšená Pec - more_enhanced_furnaces: Lepší Pece - high_tier_enhanced_furnaces: Nejlepší Pece - reinforced_furnace: Vyztužená Pec - carbonado_furnace: Carbonado Lemováná Pec + infused_magnet: Naplněný magnet + cobalt_pickaxe: Zrychlený krumpáč + essence_of_afterlife: Černá magie + bound_backpack: Uložiště spoutané duší + jetboots: Raketové boty + armored_jetboots: Obrněné raketové boty + seismic_axe: Seizmická sekera + pickaxe_of_vein_mining: Krumpáč těžby rud + bound_weapons: Zbraně spoutané duší + bound_tools: Nástroje spoutané duší + bound_armor: Brnění spoutané duší + juicer: Výborné pití + repaired_spawner: Opravování líhní + enhanced_furnace: Vylepšená pec + more_enhanced_furnaces: Lepší pece + high_tier_enhanced_furnaces: Nejlepší pece + reinforced_furnace: Zesílená pec + carbonado_furnace: Pec lemovaná černými diamanty electric_motor: Zahřívání - block_placer: Pokládač Bloků - scroll_of_dimensional_teleposition: Otáčení věcí kolem + block_placer: Pokládač bloků + scroll_of_dimensional_teleposition: Otáčí věcí kolem special_bows: Robin Hood - tome_of_knowledge_sharing: Dělení z přátely - flask_of_knowledge: XP Úložistě - hardened_glass: Odoláválí Výbuchům - golden_apple_juice: Zlatý Lektrvar - cooler: Přenášení Nápojů - ancient_altar: Starověký Oltář - wither_proof_obsidian: Obsidian co vydrží Withera - ancient_runes: Elementální Rudy - special_runes: Purple Rudy - infernal_bonemeal: Pekelný Bonemeal - rainbow_blocks: duhové Bloky - infused_hopper: Vylepšený Hopper - wither_proof_glass: Sklo co vydrží Withera - duct_tape: Lepící Páska + tome_of_knowledge_sharing: Dělení s přáteli + flask_of_knowledge: XP uložistě + hardened_glass: Odolávání výbuchům + golden_apple_juice: Zlatý lektvar + cooler: Přenašeč nápojů + ancient_altar: Starověký oltář + wither_proof_obsidian: Pevný obsidián proti witherovi + ancient_runes: Elementální rudy + special_runes: Fialové rudy + infernal_bonemeal: Pekelná kostní moučka + rainbow_blocks: Duhové bloky + infused_hopper: Vylepšená násypka + wither_proof_glass: Pevné sklo proti witherovi + duct_tape: Lepící páska plastic_sheet: Plast - android_memory_core: Memory Core + android_memory_core: Paměťové jádro oil: Olej fuel: Palivo hologram_projector: Hologramy - capacitors: Tier 1 Kondenzátory - high_tier_capacitors: Tier 2 Kondenzátory - solar_generators: Solární Elektrárna - electric_furnaces: Elektrická Pec - electric_ore_grinding: Drcení a Broušení - heated_pressure_chamber: Vyhřívaná Tlaková Komora - coal_generator: Uhelná Elektrárna - bio_reactor: Bio-Reactor - auto_enchanting: Automatická Enchantování and Oddělávání Enchantů - auto_anvil: Automatická Kovadlina - multimeter: Měření Energie - gps_setup: Základní GPS Nastavení - gps_emergency_transmitter: GPS Nouzový Cestovní Bod - programmable_androids: Programovatelní Androidi - android_interfaces: Androidové Rozhraní - geo_scanner: GEO-Skeny - combustion_reactor: Spalovací Reactor - teleporter: Teleportovač - Základní Komponenty - teleporter_activation_plates: Teleportovač - Aktivace - better_solar_generators: Vylepšené Solární Panely - better_gps_transmitters: Vylepšené Vysílače + capacitors: Kondenzátory 1. stupně + high_tier_capacitors: Kondenzátory 2. stupně + solar_generators: Solární elektrárna + electric_furnaces: Elektrická pec + electric_ore_grinding: Drcení a broušení + heated_pressure_chamber: Vytápěná tlaková komora + coal_generator: Uhelná elektrárna + bio_reactor: Bio reaktor + auto_enchanting: Automatické očarovávání a odčarovávání + auto_anvil: Automatická kovadlina + multimeter: Měření energie + gps_setup: Základní GPS nastavení + gps_emergency_transmitter: GPS nouzový záchytný bod + programmable_androids: Programovatelné androidy + android_interfaces: Rozhraní androidu + geo_scanner: GEO snímače + combustion_reactor: Spalovací reaktor + teleporter: Základní komponenty pro teleportér + teleporter_activation_plates: Aktivace teleportéru + better_solar_generators: Vylepšené solární panely + better_gps_transmitters: Vylepšené vysílače elevator: Výtahy - energized_solar_generator: 24/7 Solární Energie - energized_gps_transmitter: Nejlepší Trasmitter - energy_regulator: Energické Sítě 101 - butcher_androids: Android - Řezník - organic_food: Organické Jídlo - auto_breeder: Automatické Krmení - advanced_android: Pokročilý Androidi - advanced_butcher_android: Pokročílý Androidi - Řezníci - advanced_fisherman_android: Pokročílý Androidi - Rybář - animal_growth_accelerator: Manipulase Růstu Zvýřat - xp_collector: Zběrač XP - organic_fertilizer: Organické Hnojivo - crop_growth_accelerator: Zrychelní Růstu Plodin - better_crop_growth_accelerator: Vylepšené Zrychelní Růstu Plodin - reactor_essentials: Důležité Části Reaktoru - nuclear_reactor: Nuclearní Elektrárna - freezer: Pan Mražák - cargo_basics: Základy Carga - cargo_nodes: Nastavení Carga - electric_ingot_machines: Electrické Vyrábění Ingotů - high_tier_electric_ingot_machines: Super Rychlá Vyrábění Ingotů - automated_crafting_chamber: Automatické Crafťění - better_food_fabricator: Vylepšené Vyrábění Jídla - reactor_access_port: Interakce s Reactorem - fluid_pump: Pumpa - better_freezer: Vylepšený Mrazák - boosted_uranium: Nikdy Nekončící Kruh - trash_can: Odpatky - advanced_output_node: Vylepšený Výstupní Uzel - carbon_press: Uhlíkový Lis - electric_smeltery: Elektrická Huť - better_electric_furnace: Vylepšená Elektrická Pec - better_carbon_press: Vylepšený Uhlíkový Lis - empowered_android: Super-nabití Androidi - empowered_butcher_android: Super-nabití Androidi - Řezník - empowered_fisherman_android: Super-nabití Androidi - Rybář - high_tier_carbon_press: Ultimátní Uhlíkový Lis - wither_assembler: Automatický Zabíječ Wihera - better_heated_pressure_chamber: Vylepšená Vyhřívaná Tlaková Komora - elytra: Elytry - special_elytras: Speciální Elytry - electric_crucible: Elekryzovaný Kotel - better_electric_crucibles: Horké Kotly - advanced_electric_smeltery: Vylepšená Elekrická Huť - advanced_farmer_android: Vylepšení Androidi - Farmář - lava_generator: Generátor Energie z Lávy - nether_ice: Pekelná-Levodá Chladící Kapalina - nether_star_reactor: Nether Star Reactor - blistering_ingots: Žíravá Radioactivita - automatic_ignition_chamber: Automatická Zápalná Komora - output_chest: Základní výstup do truhly - copper_wire: Snížená Vodivost - radiant_backpack: Zářivý Batoh - auto_drier: Suchý Den - diet_cookie: Dientní Sušenka - storm_staff: Bouřková Hole - soulbound_rune: Duševně-vázaná Runa - geo_miner: GEO-Ťežič - lightning_rune: Runa Blesku - totem_of_undying: Totem Nesmrtelnosti + energized_solar_generator: Nezastavitelná solární energie + energized_gps_transmitter: Nejlepší vysílač + energy_regulator: Energické sítě 101 + butcher_androids: Řeznické androidy + organic_food: Organické jídlo + auto_breeder: Automatické krmení + advanced_android: Pokročilé androidy + advanced_butcher_android: Pokročilé řeznické androidy + advanced_fisherman_android: Pokročilé rybářské androidy + animal_growth_accelerator: Manipulace s růstem zvířat + xp_collector: Sběrač XP + organic_fertilizer: Organické hnojivo + crop_growth_accelerator: Urychlovač růstu plodin + better_crop_growth_accelerator: Vylepšený urychlovač růstu plodin + reactor_essentials: Důležité části reaktoru + nuclear_reactor: Jaderná elektrárna + freezer: Mrazák + cargo_basics: Základy nákladu + cargo_nodes: Nastavení nákladu + electric_ingot_machines: Elektrická výroba ingotů + high_tier_electric_ingot_machines: Super rychlá výroba ingotů + automated_crafting_chamber: Automatická výroba + better_food_fabricator: Vylepšená výroba jídla + reactor_access_port: Interakce s reaktorem + fluid_pump: Pumpa tekutin + better_freezer: Vylepšený mrazák + boosted_uranium: Nekonečný kruh + trash_can: Koš + advanced_output_node: Vylepšený výstupní uzel + carbon_press: Uhlíkový lis + electric_smeltery: Elektrická huť + better_electric_furnace: Vylepšená elektrická pec + better_carbon_press: Vylepšený uhlíkový lis + empowered_android: Super nabité androidy + empowered_butcher_android: Super nabité řeznické androidy + empowered_fisherman_android: Super nabité rybářské androidy + high_tier_carbon_press: Ultimátní uhlíkový lis + wither_assembler: Automatický zabiják withera + better_heated_pressure_chamber: Vylepšená vytápěná tlaková komora + elytra: Krovky + special_elytras: Speciální krovky + electric_crucible: Elektrický kotel + better_electric_crucibles: Horké kotle + advanced_electric_smeltery: Vylepšená elektrická tavírna + advanced_farmer_android: Vylepšené farmářské androidy + lava_generator: Generátor energie z lávy + nether_ice: Netherová chladící kapalina + nether_star_reactor: Netherový hvězdný reaktor + blistering_ingots: Sžíravá radioaktivita + automatic_ignition_chamber: Automatická zápalná komora + output_chest: Výstupní truhla základního zařízení + copper_wire: Snížená vodivost + radiant_backpack: Zářivý batoh + auto_drier: Suchý den + diet_cookie: Dientní sušenka + storm_staff: Bouřková hole + soulbound_rune: Runa spoutaná duší + geo_miner: GEO horník + lightning_rune: Runa blesku + totem_of_undying: Totem nesmrtelnosti charging_bench: Nabíječka - nether_gold_pan: Pekelná Zlatá Pánev - electric_press: Electrický Lis - magnesium_generator: Energie z Magnézia - kelp_cookie: Chutná Řasa + nether_gold_pan: Netherová rýžovací miska + electric_press: Elektrický lis + magnesium_generator: Energie z magnézia + kelp_cookie: Chutná řasa + advanced_industrial_miner: Lepší těžení + magical_zombie_pills: Dezombifikace + enchantment_rune: Antická očarování + climbing_pick: Blokace nájezdníků + caveman_talisman: Talisman jeskynního člověka + even_higher_tier_capacitors: Kondenzátory 3. stupně + elytra_cap: Popraskané brnění + energy_connectors: Drátové připojení + bee_armor: Včelí zbroj + wise_talisman: Talisman moudrosti + book_binder: Vázání knihy očarování + makeshift_smeltery: Vylepšená tavírna + tree_growth_accelerator: Rychlejší stromy + lead_clothing: Olověné oblečení + tape_measure: Svinovací metr + iron_golem_assembler: Automatická farma na železné golemy + shulker_shell: Syntetičtí shulkeři + villager_rune: Obnova vesnických obchodů + industrial_miner: Průmyslové těžení + auto_brewer: Průmyslový pivovar diff --git a/src/main/resources/languages/researches_de.yml b/src/main/resources/languages/researches_de.yml index d96160850..c8f40955e 100644 --- a/src/main/resources/languages/researches_de.yml +++ b/src/main/resources/languages/researches_de.yml @@ -248,3 +248,5 @@ slimefun: elytra_cap: Harter Aufprall energy_connectors: Kupferkabel bee_armor: Bienen-Rüstung + wise_talisman: Stein der Weisen + book_binder: Verzaubertes Bücherbinden diff --git a/src/main/resources/languages/researches_es.yml b/src/main/resources/languages/researches_es.yml index 4b04064a2..f816c31b2 100644 --- a/src/main/resources/languages/researches_es.yml +++ b/src/main/resources/languages/researches_es.yml @@ -248,3 +248,4 @@ slimefun: elytra_cap: Equipo de choque energy_connectors: Conexiones Instaladas bee_armor: Armadura de Abeja + wise_talisman: Talismán del Sabio diff --git a/src/main/resources/languages/researches_he.yml b/src/main/resources/languages/researches_he.yml index d355acc5e..0e1872d80 100644 --- a/src/main/resources/languages/researches_he.yml +++ b/src/main/resources/languages/researches_he.yml @@ -3,29 +3,18 @@ slimefun: walking_sticks: מקלות הליכה portable_crafter: שולחן מלאכה נייד fortune_cookie: עוגיית מזל - ender_armor: שריון אנדר - magic_eye_of_ender: עין אנדר קסומה - magic_sugar: סוכר קסום - slime_armor: שריון רפש - sword_of_beheading: חרב העריפות - parachute: מצנח - bronze: יצירת ברונזה - reinforced_alloy: סגסוגת מחוזקת - magic_workbench: שולחן מלאכה קסום - wind_staff: מטה רוח - gold_carats: זהב טהור - fire_staff: מטה אש - first_aid: עזרה ראשונה - water_staff: מטה מים - farmer_shoes: נעלי איכר - backpacks: תיקי גב portable_dustbin: פח אשפה נייד meat_jerky: בשר מלוח armor_forge: יצירת שריון glowstone_armor: שריון גלוסטון lumps: גושים וקסמים ender_backpack: תיק גב אנדר + ender_armor: שריון אנדר + magic_eye_of_ender: עין אנדר קסומה + magic_sugar: סוכר קסום monster_jerky: בשר מפלצת מלוח + slime_armor: שריון רפש + sword_of_beheading: חרב העריפות basic_circuit_board: לוח מגעים בסיסי advanced_circuit_board: לוח מגעים מתקדם smeltery: תנור התכה @@ -34,6 +23,7 @@ slimefun: battery: הסוללה הראשונה שלך steel_plate: ציפוי פלדה steel_thruster: דוחף פלדה + parachute: מצנח grappling_hook: וו אחיזה jetpacks: תרמיל רחיפה multitools: רב כלים @@ -45,6 +35,7 @@ slimefun: magical_book_cover: כריכת ספרים קסומה slimefun_metals: מתכות חדשות ore_crusher: הכפלת עפרת + bronze: יצירת ברונזה alloys: סגסוגות מתקדמות compressor_and_carbon: יצירת פחמן gilded_iron_armor: שריון ברזל מוזהב @@ -53,10 +44,15 @@ slimefun: synthetic_sapphire: ספיר סינטטי damascus_steel: פלדת דמשק damascus_steel_armor: שריון פלדת דמשק + reinforced_alloy: סגסוגת מחוזקת carbonado: יהלומים שחורים + magic_workbench: שולחן מלאכה קסום + wind_staff: מטה רוח reinforced_armor: שריון מחוזק ore_washer: שוטף עופרת + gold_carats: זהב טהור silicon: עמק הסיליקון + fire_staff: מטה אש smelters_pickaxe: מכוש התכה common_talisman: קמע נפוץ anvil_talisman: קמע הסדן @@ -82,6 +78,7 @@ slimefun: crushed_ore: טיהור עפרת redstone_alloy: סגסוגת רדסטון carbonado_tools: מכונות ברמה עליונה + first_aid: עזרה ראשונה gold_armor: שריון מבריק night_vision_googles: משקפי ראיית לילה pickaxe_of_containment: מקוש הכלה @@ -89,12 +86,15 @@ slimefun: table_saw: מסור שולחני slime_steel_armor: שריון פלדה רזה blade_of_vampires: להב הערפדים + water_staff: מטה מים 24k_gold_block: עיר מוזהבת composter: עפר קומפוסטציה + farmer_shoes: נעלי איכר explosive_tools: כלי נפץ automated_panning_machine: מסננת אוטומטית boots_of_the_stomper: מגפי הרוקע pickaxe_of_the_seeker: מכוש המחפש + backpacks: תיקי גב woven_backpack: תיק גב ארוג crucible: כור היתוך gilded_backpack: תיק גב מוזהב @@ -133,6 +133,7 @@ slimefun: wither_proof_obsidian: בזלת עמידה לוויד'ר ancient_runes: רונות אלמנטריות special_runes: רונות סגולות + infernal_bonemeal: אינפרנל בואונמיל rainbow_blocks: בלוקים צבעוניים infused_hopper: משפך חדור wither_proof_glass: זכוכית עמידה לוויד'ר @@ -247,4 +248,5 @@ slimefun: elytra_cap: גלגל שיניים מרסק energy_connectors: חיבור קווי bee_armor: שריון דבורים - infernal_bonemeal: אינפרנל בואונמיל + wise_talisman: קמע של החכמה + book_binder: כריכת ספר קסום diff --git a/src/main/resources/languages/researches_hu.yml b/src/main/resources/languages/researches_hu.yml index 9f5e930ff..fbf7e0c03 100644 --- a/src/main/resources/languages/researches_hu.yml +++ b/src/main/resources/languages/researches_hu.yml @@ -248,3 +248,4 @@ slimefun: elytra_cap: Ütközésvédelem energy_connectors: Vezetékes csatlakozás bee_armor: Méhpáncél + wise_talisman: A Bölcs talizmánja diff --git a/src/main/resources/languages/researches_ja.yml b/src/main/resources/languages/researches_ja.yml index e66c8498c..35c73be99 100644 --- a/src/main/resources/languages/researches_ja.yml +++ b/src/main/resources/languages/researches_ja.yml @@ -248,3 +248,5 @@ slimefun: elytra_cap: 衝撃緩和装備 energy_connectors: 有線接続 bee_armor: 蜂アーマー + wise_talisman: 知恵のタリスマン + book_binder: エンチャントの本の製本 diff --git a/src/main/resources/languages/researches_vi.yml b/src/main/resources/languages/researches_vi.yml index e6259c773..c920b3499 100644 --- a/src/main/resources/languages/researches_vi.yml +++ b/src/main/resources/languages/researches_vi.yml @@ -248,3 +248,5 @@ slimefun: elytra_cap: Mũ lượn energy_connectors: Đầu nối bee_armor: Giáp ong + wise_talisman: Bùa ma thuật của sự Tinh Khôn + book_binder: Sách phù phép Ràng Buộc diff --git a/src/main/resources/languages/researches_zh-CN.yml b/src/main/resources/languages/researches_zh-CN.yml index e57e46707..302ba9d67 100644 --- a/src/main/resources/languages/researches_zh-CN.yml +++ b/src/main/resources/languages/researches_zh-CN.yml @@ -248,3 +248,5 @@ slimefun: elytra_cap: 无伤落地 energy_connectors: 有线连接 bee_armor: 蜜蜂服 + wise_talisman: 智者的护身符 + book_binder: 附魔融合 diff --git a/src/main/resources/languages/researches_zh-TW.yml b/src/main/resources/languages/researches_zh-TW.yml index a1fbd7669..cb728bd43 100644 --- a/src/main/resources/languages/researches_zh-TW.yml +++ b/src/main/resources/languages/researches_zh-TW.yml @@ -248,3 +248,5 @@ slimefun: elytra_cap: 體驗動能 energy_connectors: 電線 bee_armor: 蜂裝 + wise_talisman: 智者護身符 + book_binder: 附魔書裝訂 diff --git a/src/main/resources/tags/fungus_soil.json b/src/main/resources/tags/fungus_soil.json new file mode 100644 index 000000000..b943c9e59 --- /dev/null +++ b/src/main/resources/tags/fungus_soil.json @@ -0,0 +1,17 @@ +{ + "values" : [ + "#slimefun:dirt_variants", + { + "id" : "minecraft:soul_soil", + "required" : false + }, + { + "id" : "minecraft:crimson_nylium", + "required" : false + }, + { + "id" : "minecraft:warped_nylium", + "required" : false + } + ] +} diff --git a/src/main/resources/tags/miner_talisman_triggers.json b/src/main/resources/tags/miner_talisman_triggers.json new file mode 100644 index 000000000..8dfd56669 --- /dev/null +++ b/src/main/resources/tags/miner_talisman_triggers.json @@ -0,0 +1,9 @@ +{ + "values" : [ + "#slimefun:fortune_compatible_ores", + { + "id" : "minecraft:gilded_blackstone", + "required" : false + } + ] +} diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/researches/TestResearchUnlocking.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/researches/TestResearchUnlocking.java index 6a715312f..9f4f88bac 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/researches/TestResearchUnlocking.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/researches/TestResearchUnlocking.java @@ -10,7 +10,6 @@ import org.bukkit.entity.Player; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -54,7 +53,6 @@ class TestResearchUnlocking { @ParameterizedTest @DisplayName("Test Unlocking Researches") - @Disabled(value = "Blocked by a concurrency issue in MockBukkit") @ValueSource(booleans = { true, false }) void testUnlock(boolean instant) throws InterruptedException { SlimefunPlugin.getRegistry().setResearchingEnabled(true); diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestChargeUtils.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestChargeUtils.java index bf2b4aa09..4a52485c6 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestChargeUtils.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/utils/TestChargeUtils.java @@ -1,12 +1,7 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.utils; -import java.util.Arrays; import java.util.Collections; -import be.seeseemelk.mockbukkit.MockBukkit; -import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; -import io.github.thebusybiscuit.slimefun4.utils.ChargeUtils; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -17,6 +12,11 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import be.seeseemelk.mockbukkit.MockBukkit; +import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.utils.ChargeUtils; + class TestChargeUtils { @BeforeAll