1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 03:35:51 +00:00

fix merge conflicts

This commit is contained in:
ProfElements 2021-02-18 20:39:24 -06:00
commit c643a52b4e
112 changed files with 2692 additions and 1538 deletions

View File

@ -1,8 +1,5 @@
{ {
"extends": [ "extends": [
"config:base" "config:base"
],
"labels": [
"🚨 Dependency Update"
] ]
} }

View File

@ -6,8 +6,11 @@ on:
jobs: jobs:
comment: comment:
name: Comment on Issue
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, '🐞 Bug Report') if: contains(github.event.issue.labels.*.name, '🐞 Bug Report')
steps: steps:
- name: Query recent commits - name: Query recent commits
uses: TheBusyBiscuit/recently-closed-issues@1.1.0 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! * [ ] 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 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. * [ ] 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. * [ ] 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 / CS-CoreLib, again, 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 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 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. * [ ] 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.

56
.github/workflows/pr-labels.yml vendored Normal file
View File

@ -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
<hr>
If your changes do not fall into any of these categories, don't worry.
You can just ignore this message in that case! 👀

View File

@ -1,7 +1,6 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update --> # Table of contents
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> - [Release Candidate 21 (TBD)](#release-candidate-21-tbd)
**Table of contents** - [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 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021)
- [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020) - [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020)
- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-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 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019)
- [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019) - [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> ## 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 #### Additions
* Added a new language: Bulgarian * Added a new language: Bulgarian
* Added a new language: Hebrew * Added a new language: Hebrew
* (API) Added AsyncProfileLoadEvent * (API) Added AsyncProfileLoadEvent
* Added Talisman of the Wise * Added Talisman of the Wise
* Added Book Binder
* Added Tier 3 Electric Ore Grinder
#### Changes #### Changes
* Massive performance improvements to holograms/armorstands * Massive performance improvements to holograms/armorstands
@ -50,6 +70,13 @@
* Fixed Infused Hopper picking up items with a max pickup delay * Fixed Infused Hopper picking up items with a max pickup delay
* Fixed duplication issues related to holograms/armorstands * Fixed duplication issues related to holograms/armorstands
* Fixed #2754 * 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) ## Release Candidate 19 (11 Jan 2021)

12
pom.xml
View File

@ -315,13 +315,13 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>5.7.0</version> <version>5.7.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.seeseemelk</groupId> <groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit-v1.16</artifactId> <artifactId>MockBukkit-v1.16</artifactId>
<version>0.21.0</version> <version>0.24.0</version>
<scope>test</scope> <scope>test</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -343,7 +343,7 @@
<dependency> <dependency>
<groupId>com.github.TheBusyBiscuit</groupId> <groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId> <artifactId>CS-CoreLib2</artifactId>
<version>0.29.6</version> <version>0.30.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -355,7 +355,7 @@
<dependency> <dependency>
<groupId>com.konghq</groupId> <groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId> <artifactId>unirest-java</artifactId>
<version>3.11.10</version> <version>3.11.11</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -387,7 +387,7 @@
<dependency> <dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId> <groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId> <artifactId>mcMMO</artifactId>
<version>2.1.172</version> <version>2.1.174</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -436,7 +436,7 @@
<dependency> <dependency>
<groupId>com.github.LoneDev6</groupId> <groupId>com.github.LoneDev6</groupId>
<artifactId>itemsadder-api</artifactId> <artifactId>itemsadder-api</artifactId>
<version>2.1.25</version> <version>2.1.35</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -79,6 +79,7 @@ public abstract class Network {
* *
* @param l * @param l
* The {@link Location} to classify * The {@link Location} to classify
*
* @return The assigned type of {@link NetworkComponent} for this {@link Location} * @return The assigned type of {@link NetworkComponent} for this {@link Location}
*/ */
@Nullable @Nullable

View File

@ -64,12 +64,14 @@ public final class SlimefunRegistry {
private final List<String> researchRanks = new ArrayList<>(); private final List<String> researchRanks = new ArrayList<>();
private final Set<UUID> researchingPlayers = Collections.synchronizedSet(new HashSet<>()); private final Set<UUID> researchingPlayers = Collections.synchronizedSet(new HashSet<>());
// TODO: Move this all into a proper "config cache" class
private boolean backwardsCompatibility; private boolean backwardsCompatibility;
private boolean automaticallyLoadItems; private boolean automaticallyLoadItems;
private boolean enableResearches; private boolean enableResearches;
private boolean freeCreativeResearches; private boolean freeCreativeResearches;
private boolean researchFireworks; private boolean researchFireworks;
private boolean logDuplicateBlockEntries; private boolean logDuplicateBlockEntries;
private boolean talismanActionBarMessages;
private final Set<String> tickers = new HashSet<>(); private final Set<String> tickers = new HashSet<>();
private final Set<SlimefunItem> radioactive = new HashSet<>(); private final Set<SlimefunItem> radioactive = new HashSet<>();
@ -110,6 +112,7 @@ public final class SlimefunRegistry {
freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode"); freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode");
researchFireworks = cfg.getBoolean("researches.enable-fireworks"); researchFireworks = cfg.getBoolean("researches.enable-fireworks");
logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries"); logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries");
talismanActionBarMessages = cfg.getBoolean("talismans.use-actionbar");
} }
/** /**
@ -354,6 +357,10 @@ public final class SlimefunRegistry {
return logDuplicateBlockEntries; return logDuplicateBlockEntries;
} }
public boolean useActionbarForTalismans() {
return talismanActionBarMessages;
}
@Nonnull @Nonnull
public NamespacedKey getSoulboundDataKey() { public NamespacedKey getSoulboundDataKey() {
return soulboundKey; return soulboundKey;

View File

@ -19,7 +19,6 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; 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 * 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 * @return Whether the {@link Player} has fully completed all parent categories, otherwise false
*/ */
public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) { 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 (Category category : parents) {
for (SlimefunItem item : category.getItems()) { for (SlimefunItem item : category.getItems()) {
/* // Check if the Player has researched every item (if the item is enabled)
* Should probably be replaced with Slimefun.hasUnlocked(...) if (!item.isDisabledIn(p.getWorld()) && item.hasResearch() && !profile.hasUnlocked(item.getResearch())) {
* 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())) {
return false; return false;
} }
} }

View File

@ -3,18 +3,30 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection; import java.util.Collection;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin; 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.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand; import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib; 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 { class VersionsCommand extends SubCommand {
VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) { VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
@ -24,39 +36,171 @@ class VersionsCommand extends SubCommand {
@Override @Override
public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) { public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (sender.hasPermission("slimefun.command.versions") || sender instanceof ConsoleCommandSender) { 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(); 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:"); // @formatter:off
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion())); builder.append("This Server uses the following setup of Slimefun:\n")
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion())); .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) { 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()) { 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<Plugin> addons = SlimefunPlugin.getInstalledAddons(); sender.spigot().sendMessage(builder.create());
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);
}
}
} else { } else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true); 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<Plugin> 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
}
}
} }

View File

@ -32,7 +32,7 @@ class GuideModeOption implements SlimefunGuideOption<SlimefunGuideMode> {
@Nonnull @Nonnull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return new NamespacedKey(SlimefunPlugin.instance(), "guide_layout"); return new NamespacedKey(SlimefunPlugin.instance(), "guide_mode");
} }
@Nonnull @Nonnull
@ -46,25 +46,24 @@ class GuideModeOption implements SlimefunGuideOption<SlimefunGuideMode> {
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide); Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) { if (current.isPresent()) {
SlimefunGuideMode layout = current.get(); SlimefunGuideMode selectedMode = current.get();
ItemStack item = new ItemStack(Material.AIR); ItemStack item = new ItemStack(Material.AIR);
if (layout == SlimefunGuideMode.SURVIVAL_MODE) { if (selectedMode == SlimefunGuideMode.SURVIVAL_MODE) {
item.setType(Material.CHEST); item.setType(Material.CHEST);
} else { } else {
item.setType(Material.COMMAND_BLOCK); item.setType(Material.COMMAND_BLOCK);
} }
ItemMeta meta = item.getItemMeta(); 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<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
lore.add(""); lore.add("");
lore.add((layout == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Chest"); 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((layout == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
lore.add(""); 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); meta.setLore(lore);
item.setItemMeta(meta); item.setItemMeta(meta);

View File

@ -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.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.researching.Research; 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.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
@ -71,46 +73,127 @@ public final class SlimefunGuideSettings {
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) { 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); SlimefunGuide.openGuide(pl, guide);
return false; return false;
}); });
GitHubService github = SlimefunPlugin.getGitHubService();
List<String> contributorsLore = new ArrayList<>(); List<String> contributorsLore = new ArrayList<>();
contributorsLore.add(""); 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("");
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); ContributorsMenu.open(pl, 0);
return false; 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) -> { menu.addMenuClickHandler(6, (pl, slot, item, action) -> {
pl.closeInventory(); pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4"); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4");
return false; 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(); pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki"); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki");
return false; 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(); pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki/Addons"); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/wiki/Addons");
return false; return false;
}); });
if (SlimefunPlugin.getUpdater().getBranch().isOfficial()) { 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(); pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/issues"); ChatUtils.sendURL(pl, "https://github.com/Slimefun/Slimefun4/issues");
return false; return false;
@ -119,7 +202,7 @@ public final class SlimefunGuideSettings {
menu.addItem(49, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler()); 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 // Add something here
return false; return false;
}); });
@ -158,7 +241,8 @@ public final class SlimefunGuideSettings {
for (SlimefunGuideOption<?> option : options) { for (SlimefunGuideOption<?> option : options) {
if (option instanceof FireworksOption) { if (option instanceof FireworksOption) {
FireworksOption fireworks = (FireworksOption) option; 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);
} }
} }

View File

@ -31,7 +31,6 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -114,10 +113,11 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace
} }
} }
@Nonnull
protected MultiBlockInteractionHandler getInteractionHandler() { protected MultiBlockInteractionHandler getInteractionHandler() {
return (p, mb, b) -> { return (p, mb, b) -> {
if (mb.equals(getMultiBlock())) { 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); onInteract(p, b);
} }

View File

@ -29,13 +29,25 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
*/ */
public class BackupService implements Runnable { public class BackupService implements Runnable {
/**
* The maximum amount of backups to maintain
*/
private static final int MAX_BACKUPS = 20; 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); 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"); private final File directory = new File("data-storage/Slimefun/block-backups");
@Override @Override
public void run() { public void run() {
// Make sure that the directory exists.
if (directory.exists()) {
List<File> backups = Arrays.asList(directory.listFiles()); List<File> backups = Arrays.asList(directory.listFiles());
if (backups.size() > MAX_BACKUPS) { if (backups.size() > MAX_BACKUPS) {
@ -60,7 +72,8 @@ public class BackupService implements Runnable {
SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName()); SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
} }
} catch (IOException x) { } catch (IOException x) {
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion()); SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
}
} }
} }
} }

View File

@ -1,6 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.services; package io.github.thebusybiscuit.slimefun4.core.services;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -10,6 +11,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang.Validate; 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.Server;
import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -34,9 +38,19 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunG
*/ */
public class MinecraftRecipeService { public class MinecraftRecipeService {
/**
* Our {@link Plugin} instance
*/
private final Plugin plugin; private final Plugin plugin;
/**
* The subscriber list for the {@link RecipeSnapshot}.
*/
private final List<Consumer<RecipeSnapshot>> subscriptions = new LinkedList<>(); private final List<Consumer<RecipeSnapshot>> subscriptions = new LinkedList<>();
/**
* Our {@link RecipeSnapshot} - The centerpiece of this class.
*/
private RecipeSnapshot snapshot; private RecipeSnapshot snapshot;
/** /**
@ -115,6 +129,7 @@ public class MinecraftRecipeService {
* *
* @param recipe * @param recipe
* The {@link Recipe} to get the shape from * The {@link Recipe} to get the shape from
*
* @return An Array of {@link RecipeChoice} representing the shape of this {@link Recipe} * @return An Array of {@link RecipeChoice} representing the shape of this {@link Recipe}
*/ */
@Nonnull @Nonnull
@ -149,6 +164,7 @@ public class MinecraftRecipeService {
* *
* @param item * @param item
* The {@link ItemStack} for which to get the recipes * The {@link ItemStack} for which to get the recipes
*
* @return An array of {@link Recipe Recipes} to craft the given {@link ItemStack} * @return An array of {@link Recipe Recipes} to craft the given {@link ItemStack}
*/ */
@Nonnull @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);
}
}
} }

View File

@ -26,6 +26,9 @@ import io.github.thebusybiscuit.slimefun4.api.SlimefunBranch;
import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService; import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; 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}. * This is an abstract parent class of {@link LocalizationService}.
@ -215,76 +218,84 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
} }
@Override @Override
public void sendMessage(CommandSender sender, String key, boolean addPrefix) { public void sendMessage(CommandSender recipient, String key, boolean addPrefix) {
String prefix = addPrefix ? getPrefix() : ""; String prefix = addPrefix ? getPrefix() : "";
if (sender instanceof Player) { if (recipient instanceof Player) {
sender.sendMessage(ChatColors.color(prefix + getMessage((Player) sender, key))); recipient.sendMessage(ChatColors.color(prefix + getMessage((Player) recipient, key)));
} else { } else {
sender.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + getMessage(key)))); recipient.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + getMessage(key))));
} }
} }
public void sendActionbarMessage(@Nonnull Player player, @Nonnull String key, boolean addPrefix) {
String prefix = addPrefix ? getPrefix() : "";
String message = ChatColors.color(prefix + getMessage(player, key));
BaseComponent[] components = TextComponent.fromLegacyText(message);
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, components);
}
@Override @Override
public void sendMessage(CommandSender sender, String key) { public void sendMessage(CommandSender recipient, String key) {
sendMessage(sender, key, true); sendMessage(recipient, key, true);
} }
public void sendMessage(CommandSender sender, String key, UnaryOperator<String> function) { public void sendMessage(CommandSender recipient, String key, UnaryOperator<String> function) {
sendMessage(sender, key, true, function); sendMessage(recipient, key, true, function);
} }
@Override @Override
public void sendMessage(CommandSender sender, String key, boolean addPrefix, UnaryOperator<String> function) { public void sendMessage(CommandSender recipient, String key, boolean addPrefix, UnaryOperator<String> function) {
if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) { if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
return; return;
} }
String prefix = addPrefix ? getPrefix() : ""; String prefix = addPrefix ? getPrefix() : "";
if (sender instanceof Player) { if (recipient instanceof Player) {
sender.sendMessage(ChatColors.color(prefix + function.apply(getMessage((Player) sender, key)))); recipient.sendMessage(ChatColors.color(prefix + function.apply(getMessage((Player) recipient, key))));
} else { } else {
sender.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + function.apply(getMessage(key))))); recipient.sendMessage(ChatColor.stripColor(ChatColors.color(prefix + function.apply(getMessage(key)))));
} }
} }
@Override @Override
public void sendMessages(CommandSender sender, String key) { public void sendMessages(CommandSender recipient, String key) {
String prefix = getPrefix(); String prefix = getPrefix();
if (sender instanceof Player) { if (recipient instanceof Player) {
for (String translation : getMessages((Player) sender, key)) { for (String translation : getMessages((Player) recipient, key)) {
String message = ChatColors.color(prefix + translation); String message = ChatColors.color(prefix + translation);
sender.sendMessage(message); recipient.sendMessage(message);
} }
} else { } else {
for (String translation : getMessages(key)) { for (String translation : getMessages(key)) {
String message = ChatColors.color(prefix + translation); String message = ChatColors.color(prefix + translation);
sender.sendMessage(ChatColor.stripColor(message)); recipient.sendMessage(ChatColor.stripColor(message));
} }
} }
} }
@Override @Override
public void sendMessages(CommandSender sender, String key, boolean addPrefix, UnaryOperator<String> function) { public void sendMessages(CommandSender recipient, String key, boolean addPrefix, UnaryOperator<String> function) {
String prefix = addPrefix ? getPrefix() : ""; String prefix = addPrefix ? getPrefix() : "";
if (sender instanceof Player) { if (recipient instanceof Player) {
for (String translation : getMessages((Player) sender, key)) { for (String translation : getMessages((Player) recipient, key)) {
String message = ChatColors.color(prefix + function.apply(translation)); String message = ChatColors.color(prefix + function.apply(translation));
sender.sendMessage(message); recipient.sendMessage(message);
} }
} else { } else {
for (String translation : getMessages(key)) { for (String translation : getMessages(key)) {
String message = ChatColors.color(prefix + function.apply(translation)); 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<String> function) { public void sendMessages(CommandSender recipient, String key, UnaryOperator<String> function) {
sendMessages(sender, key, true, function); sendMessages(recipient, key, true, function);
} }
} }

View File

@ -38,6 +38,7 @@ public class Translators {
addTranslator("NinoFutur", SupportedLanguage.FRENCH, true); addTranslator("NinoFutur", SupportedLanguage.FRENCH, true);
addTranslator("TheRetix", SupportedLanguage.FRENCH, true); addTranslator("TheRetix", SupportedLanguage.FRENCH, true);
addTranslator("Aeris1One", SupportedLanguage.FRENCH, true); addTranslator("Aeris1One", SupportedLanguage.FRENCH, true);
addTranslator("Aomitsu", SupportedLanguage.FRENCH, true);
// Translators - Italian // Translators - Italian
addTranslator("xXDOTTORXx", SupportedLanguage.ITALIAN, true); addTranslator("xXDOTTORXx", SupportedLanguage.ITALIAN, true);
@ -47,6 +48,14 @@ public class Translators {
addTranslator("dracrus", SupportedLanguage.ITALIAN, true); addTranslator("dracrus", SupportedLanguage.ITALIAN, true);
addTranslator("prolletto64", 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 // Translators - Latvian
addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true); addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true);
@ -81,6 +90,9 @@ public class Translators {
addTranslator("MrFriggo", SupportedLanguage.CZECH, true); addTranslator("MrFriggo", SupportedLanguage.CZECH, true);
addTranslator("100petr", SupportedLanguage.CZECH, true); addTranslator("100petr", SupportedLanguage.CZECH, true);
addTranslator("frfole", 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 // Translators - Russian
addTranslator("SoSeDiK", SupportedLanguage.RUSSIAN, false); addTranslator("SoSeDiK", SupportedLanguage.RUSSIAN, false);
@ -91,13 +103,6 @@ public class Translators {
// Translators - Ukrainian // Translators - Ukrainian
addTranslator("SoSeDiK", SupportedLanguage.UKRAINIAN, false); 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 // Translators - Swedish
addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false); addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false);
addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true); addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true);
@ -109,6 +114,7 @@ public class Translators {
addTranslator("milvantiou", SupportedLanguage.DUTCH, true); addTranslator("milvantiou", SupportedLanguage.DUTCH, true);
addTranslator("Sven313D", SupportedLanguage.DUTCH, true); addTranslator("Sven313D", SupportedLanguage.DUTCH, true);
addTranslator("TypischTeun", SupportedLanguage.DUTCH, true); addTranslator("TypischTeun", SupportedLanguage.DUTCH, true);
addTranslator("peppower", SupportedLanguage.DUTCH, true);
// Translators - Danish // Translators - Danish
addTranslator("Mini-kun", SupportedLanguage.DANISH, true); addTranslator("Mini-kun", SupportedLanguage.DANISH, true);
@ -123,6 +129,7 @@ public class Translators {
addTranslator("StarWishsama", "StarWish_Sama", SupportedLanguage.CHINESE_CHINA, false); addTranslator("StarWishsama", "StarWish_Sama", SupportedLanguage.CHINESE_CHINA, false);
addTranslator("Rothes", SupportedLanguage.CHINESE_CHINA, true); addTranslator("Rothes", SupportedLanguage.CHINESE_CHINA, true);
addTranslator("Chihsiao", SupportedLanguage.CHINESE_CHINA, true); addTranslator("Chihsiao", SupportedLanguage.CHINESE_CHINA, true);
addTranslator("Jiejue233", SupportedLanguage.CHINESE_CHINA, true);
// Translators - Chinese (Taiwan) // Translators - Chinese (Taiwan)
addTranslator("BrineYT", "HeroBrineKing", SupportedLanguage.CHINESE_TAIWAN, true); addTranslator("BrineYT", "HeroBrineKing", SupportedLanguage.CHINESE_TAIWAN, true);
@ -137,6 +144,7 @@ public class Translators {
addTranslator("Eylonnn", SupportedLanguage.HEBREW, true); addTranslator("Eylonnn", SupportedLanguage.HEBREW, true);
addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false); addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false);
addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true); addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true);
addTranslator("PaladinBear", SupportedLanguage.HEBREW, true);
addTranslator("Molioron", SupportedLanguage.HEBREW, true); addTranslator("Molioron", SupportedLanguage.HEBREW, true);
addTranslator("McAlmog", SupportedLanguage.HEBREW, true); addTranslator("McAlmog", SupportedLanguage.HEBREW, true);

View File

@ -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 = 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_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 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_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)); 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_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)); 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 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 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%"); 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%");

View File

@ -131,14 +131,26 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
*/ */
public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { 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; private static SlimefunPlugin instance;
/**
* Keep track of which {@link MinecraftVersion} we are on.
*/
private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN; private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN;
/**
* Keep track of whether this is a fresh install or a regular boot up.
*/
private boolean isNewlyInstalled = false; private boolean isNewlyInstalled = false;
// Various things we need
private final SlimefunRegistry registry = new SlimefunRegistry(); private final SlimefunRegistry registry = new SlimefunRegistry();
private final TickerTask ticker = new TickerTask();
private final SlimefunCommand command = new SlimefunCommand(this); 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 // Services - Systems that fulfill certain tasks, treat them as a black box
private final CustomItemDataService itemDataService = new CustomItemDataService(this, "slimefun_item"); 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 MinecraftRecipeService recipeService = new MinecraftRecipeService(this);
private final HologramsService hologramsService = new HologramsService(this); private final HologramsService hologramsService = new HologramsService(this);
// Some other things we need
private final IntegrationsManager integrations = new IntegrationsManager(this); private final IntegrationsManager integrations = new IntegrationsManager(this);
private final SlimefunProfiler profiler = new SlimefunProfiler(); private final SlimefunProfiler profiler = new SlimefunProfiler();
private final GPSNetwork gpsNetwork = new GPSNetwork(this); private final GPSNetwork gpsNetwork = new GPSNetwork(this);
// Even more things we need
private NetworkManager networkManager; private NetworkManager networkManager;
private LocalizationService local; private LocalizationService local;
@ -234,6 +248,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private void onPluginStart() { private void onPluginStart() {
long timestamp = System.nanoTime(); long timestamp = System.nanoTime();
// Check if Paper (<3) is installed
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied."); getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied.");
} else { } else {
@ -259,6 +274,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
int networkSize = config.getInt("networks.max-size"); int networkSize = config.getInt("networks.max-size");
// Make sure that the network size is a valid input
if (networkSize < 1) { 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); 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; networkSize = 1;
@ -362,8 +378,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
Bukkit.getScheduler().cancelTasks(this); Bukkit.getScheduler().cancelTasks(this);
// Finishes all started movements/removals of block data // Finishes all started movements/removals of block data
try {
ticker.halt(); ticker.halt();
ticker.run(); 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 // Kill our Profiler Threads
profiler.kill(); profiler.kill();
@ -619,6 +639,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new ButcherAndroidListener(this); new ButcherAndroidListener(this);
new NetworkListener(this, networkManager); new NetworkListener(this, networkManager);
new HopperListener(this); new HopperListener(this);
new TalismanListener(this);
new SoulboundListener(this);
// Bees were added in 1.15 // Bees were added in 1.15
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) { if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
@ -640,15 +662,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
bowListener.register(this); bowListener.register(this);
backpackListener.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 // Handle Slimefun Guide being given on Join
new SlimefunGuideListener(this, config.getBoolean("guide.receive-on-first-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}. * This (re)loads every {@link SlimefunTag}.
*/ */
private void loadTags() { private void loadTags() {
for (SlimefunTag tag : SlimefunTag.valuesCache) { for (SlimefunTag tag : SlimefunTag.values()) {
try { try {
// Only reload "empty" (or unloaded) Tags // Only reload "empty" (or unloaded) Tags
if (tag.isEmpty()) { if (tag.isEmpty()) {

View File

@ -266,7 +266,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
SlimefunItem sfitem = category.getItems().get(target); 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); displaySlimefunItem(menu, category, p, profile, sfitem, page, index);
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"; 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 { } else {
return item; return item;
} }

View File

@ -1,8 +1,11 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids; package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Effect; import org.bukkit.Effect;
@ -14,9 +17,10 @@ import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.Vein; 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.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -59,6 +63,7 @@ public class WoodcutterAndroid extends ProgrammableAndroid {
return true; return true;
} }
@ParametersAreNonnullByDefault
private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) { private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) {
ItemStack drop = new ItemStack(log.getType()); 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()); log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType());
if (log.getY() == android.getRelative(face).getY()) { if (log.getY() == android.getRelative(face).getY()) {
Optional<Material> sapling = MaterialConverter.getSaplingFromLog(log.getType()); replant(log);
sapling.ifPresent(log::setType);
} else { } else {
log.setType(Material.AIR); log.setType(Material.AIR);
} }
} }
} }
private void replant(@Nonnull Block block) {
Material logType = block.getType();
Material saplingType = null;
Predicate<Material> 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));
}
}
}
} }

View File

@ -3,6 +3,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
@ -13,10 +16,10 @@ import org.bukkit.block.Block;
import org.bukkit.block.Dispenser; import org.bukkit.block.Dispenser;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
@ -47,15 +50,17 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/ */
public class BlockPlacer extends SlimefunItem { public class BlockPlacer extends SlimefunItem {
private final ItemSetting<List<String>> blacklist = new MaterialTagSetting("unplaceable-blocks", SlimefunTag.UNBREAKABLE_MATERIALS); private final ItemSetting<List<String>> unplaceableBlocks = new MaterialTagSetting("unplaceable-blocks", SlimefunTag.UNBREAKABLE_MATERIALS);
@ParametersAreNonnullByDefault
public BlockPlacer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { public BlockPlacer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe); super(category, item, recipeType, recipe);
addItemSetting(blacklist); addItemSetting(unplaceableBlocks);
addItemHandler(onPlace(), onBlockDispense()); addItemHandler(onPlace(), onBlockDispense());
} }
@Nonnull
private BlockPlaceHandler onPlace() { private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) { return new BlockPlaceHandler(false) {
@ -69,6 +74,7 @@ public class BlockPlacer extends SlimefunItem {
}; };
} }
@Nonnull
private BlockDispenseHandler onBlockDispense() { private BlockDispenseHandler onBlockDispense() {
return (e, dispenser, facedBlock, machine) -> { return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) { if (!hasPermission(dispenser, facedBlock)) {
@ -79,7 +85,7 @@ public class BlockPlacer extends SlimefunItem {
Material material = e.getItem().getType(); Material material = e.getItem().getType();
if (SlimefunTag.SHULKER_BOXES.isTagged(material)) { if (SlimefunTag.SHULKER_BOXES.isTagged(material)) {
/** /*
* Since vanilla Dispensers can already place Shulker boxes, * Since vanilla Dispensers can already place Shulker boxes,
* we simply fallback to the vanilla behaviour. * we simply fallback to the vanilla behaviour.
*/ */
@ -89,7 +95,7 @@ public class BlockPlacer extends SlimefunItem {
e.setCancelled(true); e.setCancelled(true);
if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) { if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) {
/** /*
* Some materials cannot be reliably placed, like beds, * Some materials cannot be reliably placed, like beds,
* it would look kinda wonky, so we just ignore these altogether. * it would look kinda wonky, so we just ignore these altogether.
* The event has already been cancelled too, so they won't drop. * The event has already been cancelled too, so they won't drop.
@ -97,7 +103,7 @@ public class BlockPlacer extends SlimefunItem {
return; 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()); SlimefunItem item = SlimefunItem.getByItem(e.getItem());
if (item != null) { if (item != null) {
@ -123,11 +129,12 @@ public class BlockPlacer extends SlimefunItem {
* *
* @return Whether this action is permitted or not * @return Whether this action is permitted or not
*/ */
@ParametersAreNonnullByDefault
private boolean hasPermission(Dispenser dispenser, Block target) { private boolean hasPermission(Dispenser dispenser, Block target) {
String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner"); String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner");
if (owner == null) { if (owner == null) {
/** /*
* If no owner was set, then we will fallback to the previous behaviour: * If no owner was set, then we will fallback to the previous behaviour:
* Allowing block placers to bypass protection, newly placed Block placers * Allowing block placers to bypass protection, newly placed Block placers
* will respect protection plugins. * will respect protection plugins.
@ -135,20 +142,30 @@ public class BlockPlacer extends SlimefunItem {
return true; return true;
} }
// Get the corresponding OfflinePlayer
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner)); OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner));
return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK); 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)) { 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) { private void placeSlimefunBlock(SlimefunItem sfItem, ItemStack item, Block block, Dispenser dispenser) {
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, block); BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, block);
Bukkit.getPluginManager().callEvent(e); Bukkit.getPluginManager().callEvent(e);
@ -156,40 +173,31 @@ public class BlockPlacer extends SlimefunItem {
if (!e.isCancelled()) { if (!e.isCancelled()) {
boolean hasItemHandler = sfItem.callItemHandler(BlockPlaceHandler.class, handler -> { boolean hasItemHandler = sfItem.callItemHandler(BlockPlaceHandler.class, handler -> {
if (handler.isBlockPlacerAllowed()) { if (handler.isBlockPlacerAllowed()) {
schedulePlacement(block, dispenser.getInventory(), item, () -> {
block.setType(item.getType()); block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
BlockStorage.store(block, sfItem.getId()); BlockStorage.store(block, sfItem.getId());
handler.onBlockPlacerPlace(e);
if (dispenser.getInventory().containsAtLeast(item, 2)) { handler.onBlockPlacerPlace(e);
dispenser.getInventory().removeItem(new CustomItem(item, 1)); });
} else {
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
} }
}); });
if (!hasItemHandler) { if (!hasItemHandler) {
schedulePlacement(block, dispenser.getInventory(), item, () -> {
block.setType(item.getType()); block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
BlockStorage.store(block, sfItem.getId()); 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);
}
} }
} }
} }
@ParametersAreNonnullByDefault
private void placeBlock(ItemStack item, Block facedBlock, Dispenser dispenser) { private void placeBlock(ItemStack item, Block facedBlock, Dispenser dispenser) {
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, facedBlock); BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, facedBlock);
Bukkit.getPluginManager().callEvent(e); Bukkit.getPluginManager().callEvent(e);
if (!e.isCancelled()) { if (!e.isCancelled()) {
schedulePlacement(facedBlock, dispenser.getInventory(), item, () -> {
facedBlock.setType(item.getType()); facedBlock.setType(item.getType());
if (item.hasItemMeta()) { if (item.hasItemMeta()) {
@ -210,14 +218,33 @@ public class BlockPlacer extends SlimefunItem {
} }
} }
});
}
}
facedBlock.getWorld().playEffect(facedBlock.getLocation(), Effect.STEP_SOUND, item.getType()); @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);
if (dispenser.getInventory().containsAtLeast(item, 2)) { // Play particles
dispenser.getInventory().removeItem(new CustomItem(item, 1)); b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, item.getType());
} else {
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L); // 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);
} }
} }

View File

@ -7,6 +7,9 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -57,10 +60,11 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
private final Map<String, ItemStack> craftingRecipes = new HashMap<>(); private final Map<String, ItemStack> craftingRecipes = new HashMap<>();
@ParametersAreNonnullByDefault
public AutomatedCraftingChamber(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { public AutomatedCraftingChamber(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe); super(category, item, recipeType, recipe);
new BlockMenuPreset(getId(), "&6Automated Crafting Chamber") { new BlockMenuPreset(getId(), "&4Deprecated item. Do not use.") {
@Override @Override
public void init() { public void init() {
@ -94,6 +98,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
@Override @Override
public boolean canOpen(Block b, Player p) { 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); 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 @Override
public void onPlayerPlace(BlockPlaceEvent e) { 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)); BlockStorage.addBlockInfo(e.getBlock(), "enabled", String.valueOf(false));
} }

View File

@ -44,10 +44,9 @@ public class BookBinder extends AContainer {
protected MachineRecipe findNextRecipe(BlockMenu menu) { protected MachineRecipe findNextRecipe(BlockMenu menu) {
for (int slot : getInputSlots()) { for (int slot : getInputSlots()) {
ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]); ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
ItemStack item = menu.getItemInSlot(slot); ItemStack item = menu.getItemInSlot(slot);
if (isCompatible(item) && isCompatible(target)) {
if (isCompatible(item) && isCompatible(target)) {
EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) item.getItemMeta(); EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) item.getItemMeta();
EnchantmentStorageMeta targetMeta = (EnchantmentStorageMeta) target.getItemMeta(); EnchantmentStorageMeta targetMeta = (EnchantmentStorageMeta) target.getItemMeta();
@ -59,6 +58,7 @@ public class BookBinder extends AContainer {
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK); ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta(); EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta();
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) { for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
enchantMeta.addStoredEnchant(entry.getKey(), entry.getValue(), bypassVanillaMaxLevel.getValue()); enchantMeta.addStoredEnchant(entry.getKey(), entry.getValue(), bypassVanillaMaxLevel.getValue());
} }
@ -109,8 +109,8 @@ public class BookBinder extends AContainer {
private Map<Enchantment, Integer> combineEnchantments(Map<Enchantment, Integer> ech1, Map<Enchantment, Integer> ech2) { private Map<Enchantment, Integer> combineEnchantments(Map<Enchantment, Integer> ech1, Map<Enchantment, Integer> ech2) {
Map<Enchantment, Integer> enchantments = new HashMap<>(); Map<Enchantment, Integer> enchantments = new HashMap<>();
boolean conflicts = false; boolean conflicts = false;
enchantments.putAll(ech1); enchantments.putAll(ech1);
for (Map.Entry<Enchantment, Integer> entry : ech2.entrySet()) { for (Map.Entry<Enchantment, Integer> entry : ech2.entrySet()) {
for (Map.Entry<Enchantment, Integer> conflictsWith : enchantments.entrySet()) { for (Map.Entry<Enchantment, Integer> conflictsWith : enchantments.entrySet()) {
if (entry.getKey().conflictsWith(conflictsWith.getKey())) { if (entry.getKey().conflictsWith(conflictsWith.getKey())) {
@ -127,7 +127,7 @@ public class BookBinder extends AContainer {
enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> { enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> {
int enchantMaxLevel = entry.getKey().getMaxLevel(); int enchantMaxLevel = entry.getKey().getMaxLevel();
if (a == b) { if (a.intValue() == b.intValue()) {
if (enchantMaxLevel <= a) { if (enchantMaxLevel <= a) {
return enchantMaxLevel; return enchantMaxLevel;
} }
@ -136,7 +136,6 @@ public class BookBinder extends AContainer {
} else { } else {
return a + 1; return a + 1;
} }
} else { } else {
int highestLevel = Math.max(a, b); int highestLevel = Math.max(a, b);

View File

@ -1,16 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines; 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.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotHopperable; 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.CSCoreLibPlugin.general.Inventory.ClickAction;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; 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.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; 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}. * 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); processing.remove(b);
return true; return true;
}); });
this.registerDefaultRecipes();
} }
private Comparator<Integer> compareSlots(DirtyChestMenu menu) { private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount(); return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
} }
@Override @Override

View File

@ -1,15 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines; 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.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; 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.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; 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 { public class HeatedPressureChamber extends AContainer {
@ -73,12 +72,10 @@ public class HeatedPressureChamber extends AContainer {
} }
} }
}; };
this.registerDefaultRecipes();
} }
private Comparator<Integer> compareSlots(DirtyChestMenu menu) { private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount(); return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
} }
@Override @Override

View File

@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunIte
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -66,7 +65,7 @@ public class EnchantmentRune extends SimpleSlimefunItem<ItemDropHandler> {
public ItemDropHandler getItemHandler() { public ItemDropHandler getItemHandler() {
return (e, p, item) -> { return (e, p, item) -> {
if (isItem(item.getItemStack())) { if (isItem(item.getItemStack())) {
if (Slimefun.hasUnlocked(p, this, true)) { if (canUse(p, true)) {
SlimefunPlugin.runSync(() -> { SlimefunPlugin.runSync(() -> {
try { try {
addRandomEnchantment(p, item); addRandomEnchantment(p, item);

View File

@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Entity; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -47,7 +48,7 @@ public class SoulboundRune extends SimpleSlimefunItem<ItemDropHandler> {
return (e, p, item) -> { return (e, p, item) -> {
if (isItem(item.getItemStack())) { if (isItem(item.getItemStack())) {
if (!Slimefun.hasUnlocked(p, this, true)) { if (!canUse(p, true)) {
return true; return true;
} }
@ -59,7 +60,7 @@ public class SoulboundRune extends SimpleSlimefunItem<ItemDropHandler> {
}; };
} }
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. // Being sure the entity is still valid and not picked up or whatsoever.
if (!rune.isValid()) { if (!rune.isValid()) {
return; return;

View File

@ -1,5 +1,18 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans; 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.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -7,20 +20,6 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; 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} * 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}. * 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 { public class MagicianTalisman extends Talisman {
private final ItemSetting<Boolean> allowEnchantmentBooks = new ItemSetting<>("allow-enchantment-books", false);
private final Set<TalismanEnchantment> enchantments = new HashSet<>(); private final Set<TalismanEnchantment> enchantments = new HashSet<>();
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public MagicianTalisman(SlimefunItemStack item, ItemStack[] recipe) { public MagicianTalisman(SlimefunItemStack item, ItemStack[] recipe) {
super(item, recipe, false, false, "magician", 80); super(item, recipe, false, false, "magician", 80);
addItemSetting(allowEnchantmentBooks);
for (Enchantment enchantment : Enchantment.values()) { for (Enchantment enchantment : Enchantment.values()) {
try { try {
for (int i = 1; i <= enchantment.getMaxLevel(); i++) { for (int i = 1; i <= enchantment.getMaxLevel(); i++) {
@ -70,7 +73,7 @@ public class MagicianTalisman extends Talisman {
// @formatter:off // @formatter:off
List<TalismanEnchantment> enabled = enchantments.stream() List<TalismanEnchantment> 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(e -> hasConflicts(existingEnchantments, e))
.filter(TalismanEnchantment::getValue) .filter(TalismanEnchantment::getValue)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -90,4 +93,13 @@ public class MagicianTalisman extends Talisman {
return true; 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();
}
} }

View File

@ -9,6 +9,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; 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.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Talisman extends SlimefunItem { public class Talisman extends SlimefunItem {
@ -113,10 +113,6 @@ public class Talisman extends SlimefunItem {
return effects; return effects;
} }
protected String getMessageSuffix() {
return suffix;
}
protected boolean isEventCancelled() { protected boolean isEventCancelled() {
return cancel; return cancel;
} }
@ -147,36 +143,44 @@ public class Talisman extends SlimefunItem {
} }
} }
private static boolean hasMessage(@Nonnull Talisman talisman) { @ParametersAreNonnullByDefault
return talisman.getMessageSuffix() != null; public static boolean trigger(Event e, SlimefunItemStack stack) {
return trigger(e, stack.getItem(), true);
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public static boolean checkFor(Event e, SlimefunItemStack stack) { public static boolean trigger(Event e, SlimefunItemStack stack, boolean sendMessage) {
return checkFor(e, stack.getItem()); return trigger(e, stack.getItem(), sendMessage);
} }
@ParametersAreNonnullByDefault @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)) { if (!(item instanceof Talisman)) {
return false; return false;
} }
Talisman talisman = (Talisman) item; Talisman talisman = (Talisman) item;
if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) { if (ThreadLocalRandom.current().nextInt(100) > talisman.getChance()) {
return false; return false;
} }
Player p = getPlayerByEventType(e); Player p = getPlayerByEventType(e);
if (p == null || !pass(p, talisman)) {
if (p == null || !talisman.canEffectsBeApplied(p)) {
return false; return false;
} }
ItemStack talismanItem = talisman.getItem(); ItemStack talismanItem = talisman.getItem();
if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) { if (SlimefunUtils.containsSimilarItem(p.getInventory(), talismanItem, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) { if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getInventory(), talisman, talismanItem); activateTalisman(e, p, p.getInventory(), talisman, talismanItem, sendMessage);
return true; return true;
} else { } else {
return false; return false;
@ -185,8 +189,8 @@ public class Talisman extends SlimefunItem {
ItemStack enderTalisman = talisman.getEnderVariant(); ItemStack enderTalisman = talisman.getEnderVariant();
if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) { if (SlimefunUtils.containsSimilarItem(p.getEnderChest(), enderTalisman, true)) {
if (Slimefun.hasUnlocked(p, talisman, true)) { if (talisman.canUse(p, true)) {
activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman); activateTalisman(e, p, p.getEnderChest(), talisman, enderTalisman, sendMessage);
return true; return true;
} else { } else {
return false; return false;
@ -198,11 +202,30 @@ public class Talisman extends SlimefunItem {
} }
@ParametersAreNonnullByDefault @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); consumeItem(inv, talisman, talismanItem);
applyTalismanEffects(p, talisman); applyTalismanEffects(p, talisman);
cancelEvent(e, 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 @ParametersAreNonnullByDefault
@ -219,29 +242,63 @@ public class Talisman extends SlimefunItem {
} }
} }
@ParametersAreNonnullByDefault /**
private static void sendMessage(Player p, Talisman talisman) { * This returns whether the {@link Talisman} is silent.
if (hasMessage(talisman)) { * A silent {@link Talisman} will not send a message to a {@link Player}
SlimefunPlugin.getLocalization().sendMessage(p, "messages.talisman." + talisman.getMessageSuffix(), true); * when activated.
} *
* @return Whether this {@link Talisman} is silent
*/
public boolean isSilent() {
return getMessageSuffix() == null;
} }
@ParametersAreNonnullByDefault @Nullable
private static void consumeItem(Inventory inv, Talisman talisman, ItemStack talismanItem) { protected final String getMessageSuffix() {
if (talisman.isConsumable()) { return suffix;
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;
} }
/**
* 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) { if (e instanceof EntityDeathEvent) {
return ((EntityDeathEvent) e).getEntity().getKiller(); return ((EntityDeathEvent) e).getEntity().getKiller();
} else if (e instanceof BlockBreakEvent) { } else if (e instanceof BlockBreakEvent) {
@ -259,14 +316,4 @@ public class Talisman extends SlimefunItem {
return null; 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;
}
} }

View File

@ -19,7 +19,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -48,7 +47,7 @@ abstract class AbstractSmeltery extends MultiBlockMachine {
if (canCraft(inv, inputs, i)) { if (canCraft(inv, inputs, i)) {
ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); 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); Inventory outputInv = findOutputInventory(output, dispBlock, inv);
if (outputInv != null) { if (outputInv != null) {

View File

@ -21,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class ArmorForge extends AbstractCraftingTable { public class ArmorForge extends AbstractCraftingTable {
@ -44,7 +43,7 @@ public class ArmorForge extends AbstractCraftingTable {
if (isCraftable(inv, inputs.get(i))) { if (isCraftable(inv, inputs.get(i))) {
ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); 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); craft(p, output, inv, dispenser);
} }

View File

@ -20,7 +20,6 @@ import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class EnhancedCraftingTable extends AbstractCraftingTable { public class EnhancedCraftingTable extends AbstractCraftingTable {
@ -43,7 +42,7 @@ public class EnhancedCraftingTable extends AbstractCraftingTable {
if (isCraftable(inv, inputs.get(i))) { if (isCraftable(inv, inputs.get(i))) {
ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); 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); craft(inv, dispenser, p, b, output);
} }

View File

@ -4,6 +4,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
@ -27,6 +28,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class GrindStone extends MultiBlockMachine { public class GrindStone extends MultiBlockMachine {
@ParametersAreNonnullByDefault
public GrindStone(Category category, SlimefunItemStack item) { 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); 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));
recipes.add(new ItemStack(Material.PRISMARINE_SHARD, 4)); 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 @Override

View File

@ -21,7 +21,6 @@ import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class MagicWorkbench extends AbstractCraftingTable { public class MagicWorkbench extends AbstractCraftingTable {
@ -50,7 +49,7 @@ public class MagicWorkbench extends AbstractCraftingTable {
if (isCraftable(inv, inputs.get(i))) { if (isCraftable(inv, inputs.get(i))) {
ItemStack output = RecipeType.getRecipeOutputList(this, inputs.get(i)).clone(); 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); craft(inv, dispenser, p, b, output);
} }

View File

@ -25,7 +25,6 @@ import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/** /**
@ -135,7 +134,7 @@ public class OreCrusher extends MultiBlockMachine {
ItemStack adding = RecipeType.getRecipeOutput(this, convert); ItemStack adding = RecipeType.getRecipeOutput(this, convert);
Inventory outputInv = findOutputInventory(adding, dispBlock, inv); Inventory outputInv = findOutputInventory(adding, dispBlock, inv);
if (Slimefun.hasUnlocked(p, adding, true)) { if (SlimefunUtils.canPlayerUseItem(p, adding, true)) {
if (outputInv != null) { if (outputInv != null) {
ItemStack removing = current.clone(); ItemStack removing = current.clone();
removing.setAmount(convert.getAmount()); removing.setAmount(convert.getAmount());

View File

@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.Material; import org.bukkit.Material;
@ -12,7 +14,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem; import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
@ -43,6 +44,7 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
private final ItemSetting<Boolean> damageOnUse = new ItemSetting<>("damage-on-use", true); private final ItemSetting<Boolean> damageOnUse = new ItemSetting<>("damage-on-use", true);
private final ItemSetting<Boolean> callExplosionEvent = new ItemSetting<>("call-explosion-event", false); private final ItemSetting<Boolean> callExplosionEvent = new ItemSetting<>("call-explosion-event", false);
@ParametersAreNonnullByDefault
public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe); super(category, item, recipeType, recipe);
@ -59,11 +61,12 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F); b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
List<Block> blocks = findBlocks(b); List<Block> 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<Block> blocks, int fortune, List<ItemStack> drops) { @ParametersAreNonnullByDefault
private void breakBlocks(Player p, ItemStack item, Block b, List<Block> blocks, List<ItemStack> drops) {
if (callExplosionEvent.getValue().booleanValue()) { if (callExplosionEvent.getValue().booleanValue()) {
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0); BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0);
Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent); Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent);
@ -71,14 +74,14 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
if (!blockExplodeEvent.isCancelled()) { if (!blockExplodeEvent.isCancelled()) {
for (Block block : blockExplodeEvent.blockList()) { for (Block block : blockExplodeEvent.blockList()) {
if (canBreak(p, block)) { if (canBreak(p, block)) {
breakBlock(p, item, block, fortune, drops); breakBlock(p, item, block, drops);
} }
} }
} }
} else { } else {
for (Block block : blocks) { for (Block block : blocks) {
if (canBreak(p, block)) { if (canBreak(p, block)) {
breakBlock(p, item, block, fortune, drops); breakBlock(p, item, block, drops);
} }
} }
} }
@ -122,7 +125,8 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
} }
} }
private void breakBlock(Player p, ItemStack item, Block b, int fortune, List<ItemStack> drops) { @ParametersAreNonnullByDefault
private void breakBlock(Player p, ItemStack item, Block b, List<ItemStack> drops) {
SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK); SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK);
Material material = b.getType(); Material material = b.getType();
@ -135,19 +139,8 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) { if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) {
drops.add(BlockStorage.retrieve(b)); drops.add(BlockStorage.retrieve(b));
} }
} else if (material == Material.PLAYER_HEAD || SlimefunTag.SHULKER_BOXES.isTagged(material)) {
b.breakNaturally(item);
} else { } else {
boolean applyFortune = SlimefunTag.FORTUNE_COMPATIBLE_ORES.isTagged(material); b.breakNaturally(item);
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);
} }
damageItem(p, item); damageItem(p, item);

View File

@ -96,10 +96,6 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
for (GoldPanDrop setting : drops) { for (GoldPanDrop setting : drops) {
randomizer.add(setting.getOutput(), setting.getValue()); 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<ItemUseHandler> implements Recip
*/ */
@Nonnull @Nonnull
public ItemStack getRandomOutput() { public ItemStack getRandomOutput() {
return randomizer.getRandom(); ItemStack item = randomizer.getRandom();
// Fixes #2804
return item != null ? item : new ItemStack(Material.AIR);
} }
@Override @Override
@ -126,12 +125,14 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
if (block.isPresent()) { if (block.isPresent()) {
Block b = block.get(); 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)) { if (b.getType() == getTargetMaterial() && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
ItemStack output = getRandomOutput(); ItemStack output = getRandomOutput();
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType()); b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
b.setType(Material.AIR); b.setType(Material.AIR);
// Make sure that the randomly selected item is not air
if (output.getType() != Material.AIR) { if (output.getType() != Material.AIR) {
b.getWorld().dropItemNaturally(b.getLocation(), output.clone()); b.getWorld().dropItemNaturally(b.getLocation(), output.clone());
} }
@ -148,6 +149,7 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
* *
* @return the {@link EntityInteractHandler} of this {@link SlimefunItem} * @return the {@link EntityInteractHandler} of this {@link SlimefunItem}
*/ */
@Nonnull
public EntityInteractHandler onEntityInteract() { public EntityInteractHandler onEntityInteract() {
return (e, item, offHand) -> { return (e, item, offHand) -> {
if (!(e.getRightClicked() instanceof ItemFrame)) { if (!(e.getRightClicked() instanceof ItemFrame)) {

View File

@ -41,7 +41,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage; 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} * 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(); String id = slimefunBlock.get().getId();
Player p = e.getPlayer();
if (id.equals(pedestalItem.getId())) { if (id.equals(pedestalItem.getId())) {
e.cancel(); e.cancel();
usePedestal(b, e.getPlayer()); usePedestal(b, p);
} else if (id.equals(altarItem.getId())) { } 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(); e.cancel();
return; return;
} }
@ -119,7 +119,7 @@ public class AncientAltarListener implements Listener {
altarsInUse.add(b.getLocation()); altarsInUse.add(b.getLocation());
e.cancel(); e.cancel();
useAltar(b, e.getPlayer()); useAltar(b, p);
} }
} }
@ -212,8 +212,9 @@ public class AncientAltarListener implements Listener {
} }
Optional<ItemStack> result = getRecipeOutput(catalyst, input); Optional<ItemStack> result = getRecipeOutput(catalyst, input);
if (result.isPresent()) { if (result.isPresent()) {
if (Slimefun.hasUnlocked(p, result.get(), true)) { if (SlimefunUtils.canPlayerUseItem(p, result.get(), true)) {
List<ItemStack> consumed = new ArrayList<>(); List<ItemStack> consumed = new ArrayList<>();
consumed.add(catalyst); 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) { public void onBlockPlace(BlockPlaceEvent e) {
if (altarItem == null || altarItem.isDisabled()) { if (altarItem == null || altarItem.isDisabled()) {
return; return;

View File

@ -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.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.SlimefunBackpack; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.SlimefunBackpack;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; 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}. * This {@link Listener} is responsible for all events centered around a {@link SlimefunBackpack}.
@ -122,7 +121,7 @@ public class BackpackListener implements Listener {
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public void openBackpack(Player p, ItemStack item, SlimefunBackpack backpack) { public void openBackpack(Player p, ItemStack item, SlimefunBackpack backpack) {
if (item.getAmount() == 1) { if (item.getAmount() == 1) {
if (Slimefun.hasUnlocked(p, backpack, true) && !PlayerProfile.get(p, profile -> openBackpack(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"); SlimefunPlugin.getLocalization().sendMessage(p, "messages.opening-backpack");
} }
} else { } else {

View File

@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.BeeWings; import io.github.thebusybiscuit.slimefun4.implementation.items.magical.BeeWings;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.BeeWingsTask; 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} * 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(); Player player = (Player) e.getEntity();
ItemStack chestplate = player.getInventory().getChestplate(); 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); new BeeWingsTask(player).scheduleRepeating(3, 1);
} }
} }

View File

@ -10,7 +10,6 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
@ -51,10 +50,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/ */
public class BlockListener implements Listener { public class BlockListener implements Listener {
private final SlimefunPlugin plugin;
public BlockListener(@Nonnull SlimefunPlugin plugin) { public BlockListener(@Nonnull SlimefunPlugin plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
} }
@ -71,23 +67,15 @@ public class BlockListener implements Listener {
if (e.getBlockReplacedState().getType().isAir()) { if (e.getBlockReplacedState().getType().isAir()) {
SlimefunItem sfItem = BlockStorage.check(block); SlimefunItem sfItem = BlockStorage.check(block);
if (sfItem != null) { if (sfItem != null && !SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
/*
* 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()) { for (ItemStack item : sfItem.getDrops()) {
if (item != null && !item.getType().isAir()) { if (item != null && !item.getType().isAir()) {
SlimefunPlugin.runSync(() -> block.getWorld().dropItemNaturally(block.getLocation(), item)); block.getWorld().dropItemNaturally(block.getLocation(), item);
} }
} }
BlockStorage.clearBlockInfo(block); BlockStorage.clearBlockInfo(block);
} }
});
}
} else if (BlockStorage.hasBlockInfo(e.getBlock())) { } else if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true); e.setCancelled(true);
} }
@ -99,7 +87,7 @@ public class BlockListener implements Listener {
SlimefunItem sfItem = SlimefunItem.getByItem(item); SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null && !(sfItem instanceof NotPlaceable) && Slimefun.isEnabled(e.getPlayer(), sfItem, true)) { 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); e.setCancelled(true);
} else { } else {
if (SlimefunPlugin.getBlockDataService().isTileEntity(e.getBlock().getType())) { if (SlimefunPlugin.getBlockDataService().isTileEntity(e.getBlock().getType())) {
@ -124,6 +112,11 @@ public class BlockListener implements Listener {
return; return;
} }
// Ignore blocks which we have marked as deleted (Fixes #2771)
if (SlimefunPlugin.getTickerTask().isDeletedSoon(e.getBlock().getLocation())) {
return;
}
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock()); checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock());
ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
@ -146,7 +139,7 @@ public class BlockListener implements Listener {
SlimefunItem tool = SlimefunItem.getByItem(item); SlimefunItem tool = SlimefunItem.getByItem(item);
if (tool != null) { 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)); tool.callItemHandler(ToolUseHandler.class, handler -> handler.onToolUse(e, item, fortune, drops));
} else { } else {
e.setCancelled(true); e.setCancelled(true);

View File

@ -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.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice; 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 * 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()) { for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) { if (cooler.isItem(item)) {
if (Slimefun.hasUnlocked(p, cooler, true)) { if (cooler.canUse(p, true)) {
takeJuiceFromCooler(p, item); takeJuiceFromCooler(p, item);
} else { } else {
return; return;

View File

@ -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.ElytraCap;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* The {@link Listener} for the {@link ElytraCap}. * The {@link Listener} for the {@link ElytraCap}.
@ -57,7 +56,7 @@ public class ElytraImpactListener implements Listener {
if (helmet.isPresent()) { if (helmet.isPresent()) {
SlimefunItem item = helmet.get(); 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); e.setDamage(0);
p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1); p.playSound(p.getLocation(), Sound.BLOCK_STONE_HIT, 20, 1);

View File

@ -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.JetBoots;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Jetpack; 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.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.JetBootsTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.JetpackTask; 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.implementation.tasks.ParachuteTask;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* This {@link Listener} is responsible for listening to the {@link PlayerToggleSneakEvent} * 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)) { if (SlimefunUtils.containsSimilarItem(p.getInventory(), SlimefunItems.INFUSED_MAGNET, true)) {
InfusedMagnet magnet = (InfusedMagnet) SlimefunItems.INFUSED_MAGNET.getItem(); 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); 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) { 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; return;
} }
@ -83,7 +82,7 @@ public class GadgetsListener implements Listener {
} }
private void handleBoots(@Nonnull Player p, @Nullable SlimefunItem boots) { 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(); double speed = ((JetBoots) boots).getSpeed();
if (speed > 0.2) { if (speed > 0.2) {

View File

@ -62,8 +62,13 @@ public class MultiBlockListener implements Listener {
e.setCancelled(true); e.setCancelled(true);
MultiBlock mb = multiblocks.getLast(); MultiBlock mb = multiblocks.getLast();
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)); mb.getSlimefunItem().callItemHandler(MultiBlockInteractionHandler.class, handler -> handler.onInteract(p, mb, b));
Bukkit.getPluginManager().callEvent(new MultiBlockInteractEvent(p, mb, b, e.getBlockFace())); }
} }
} }

View File

@ -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.SlimefunArmorPiece;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* This {@link Listener} is responsible for handling all boots provided by * 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(); Player p = (Player) e.getEntity();
SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); 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); e.setCancelled(true);
} }
} }
@ -65,7 +64,7 @@ public class SlimefunBootsListener implements Listener {
if (boots != null) { if (boots != null) {
// Check if the boots were researched // Check if the boots were researched
if (!Slimefun.hasUnlocked(p, boots, true)) { if (!boots.canUse(p, true)) {
return; return;
} }
@ -91,7 +90,7 @@ public class SlimefunBootsListener implements Listener {
Player p = e.getPlayer(); Player p = e.getPlayer();
SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); 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); e.setCancelled(true);
} }
} }

View File

@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* This {@link Listener} is responsible for handling the {@link ItemConsumptionHandler} * This {@link Listener} is responsible for handling the {@link ItemConsumptionHandler}
@ -33,7 +32,7 @@ public class SlimefunItemConsumeListener implements Listener {
SlimefunItem sfItem = SlimefunItem.getByItem(item); SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null) { if (sfItem != null) {
if (Slimefun.hasUnlocked(p, sfItem, true)) { if (sfItem.canUse(p, true)) {
sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item)); sfItem.callItemHandler(ItemConsumptionHandler.class, handler -> handler.onConsume(e, p, item));
} else { } else {
e.setCancelled(true); e.setCancelled(true);

View File

@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage; 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.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
@ -94,8 +93,10 @@ public class SlimefunItemInteractListener implements Listener {
Optional<SlimefunItem> optional = event.getSlimefunItem(); Optional<SlimefunItem> optional = event.getSlimefunItem();
if (optional.isPresent()) { if (optional.isPresent()) {
if (Slimefun.hasUnlocked(e.getPlayer(), optional.get(), true)) { SlimefunItem sfItem = optional.get();
return optional.get().callItemHandler(ItemUseHandler.class, handler -> handler.onRightClick(event));
if (sfItem.canUse(e.getPlayer(), true)) {
return sfItem.callItemHandler(ItemUseHandler.class, handler -> handler.onRightClick(event));
} else { } else {
event.setUseItem(Result.DENY); event.setUseItem(Result.DENY);
} }
@ -109,19 +110,20 @@ public class SlimefunItemInteractListener implements Listener {
Optional<SlimefunItem> optional = event.getSlimefunBlock(); Optional<SlimefunItem> optional = event.getSlimefunBlock();
if (optional.isPresent()) { 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); event.getInteractEvent().setCancelled(true);
return false; 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) { if (!interactable) {
String id = optional.get().getId();
Player p = event.getPlayer(); Player p = event.getPlayer();
if (BlockMenuPreset.isInventory(id)) { if (BlockMenuPreset.isInventory(sfItem.getId())) {
openInventory(p, id, event.getInteractEvent().getClickedBlock(), event); openInventory(p, sfItem, event.getInteractEvent().getClickedBlock(), event);
return false; return false;
} }
} }
@ -131,12 +133,13 @@ public class SlimefunItemInteractListener implements Listener {
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
private void openInventory(Player p, String id, Block clickedBlock, PlayerRightClickEvent event) { private void openInventory(Player p, SlimefunItem item, Block clickedBlock, PlayerRightClickEvent event) {
try {
if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { if (!p.isSneaking() || event.getItem().getType() == Material.AIR) {
event.getInteractEvent().setCancelled(true); event.getInteractEvent().setCancelled(true);
if (BlockStorage.hasUniversalInventory(id)) { if (BlockStorage.hasUniversalInventory(item.getId())) {
UniversalBlockMenu menu = BlockStorage.getUniversalInventory(id); UniversalBlockMenu menu = BlockStorage.getUniversalInventory(item.getId());
if (menu.canOpen(clickedBlock, p)) { if (menu.canOpen(clickedBlock, p)) {
menu.open(p); menu.open(p);
@ -153,6 +156,9 @@ public class SlimefunItemInteractListener implements Listener {
} }
} }
} }
} catch (Exception | LinkageError x) {
item.error("An Exception was caught while trying to open the Inventory", x);
}
} }
} }

View File

@ -61,24 +61,24 @@ public class TalismanListener implements Listener {
public void onDamageGet(EntityDamageEvent e) { public void onDamageGet(EntityDamageEvent e) {
if (e.getEntity() instanceof Player) { if (e.getEntity() instanceof Player) {
if (e.getCause() == DamageCause.LAVA) { if (e.getCause() == DamageCause.LAVA) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_LAVA); Talisman.trigger(e, SlimefunItems.TALISMAN_LAVA);
} }
if (e.getCause() == DamageCause.DROWNING) { if (e.getCause() == DamageCause.DROWNING) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_WATER); Talisman.trigger(e, SlimefunItems.TALISMAN_WATER);
} }
if (e.getCause() == DamageCause.FALL) { if (e.getCause() == DamageCause.FALL) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_ANGEL); Talisman.trigger(e, SlimefunItems.TALISMAN_ANGEL);
} }
if (e.getCause() == DamageCause.FIRE) { if (e.getCause() == DamageCause.FIRE) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_FIRE); Talisman.trigger(e, SlimefunItems.TALISMAN_FIRE);
} }
if (e.getCause() == DamageCause.ENTITY_ATTACK) { if (e.getCause() == DamageCause.ENTITY_ATTACK) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_KNIGHT); Talisman.trigger(e, SlimefunItems.TALISMAN_KNIGHT);
Talisman.checkFor(e, SlimefunItems.TALISMAN_WARRIOR); Talisman.trigger(e, SlimefunItems.TALISMAN_WARRIOR);
} }
if (e.getCause() == DamageCause.PROJECTILE && e instanceof EntityDamageByEntityEvent) { 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)) { if (e.getDamager() instanceof Projectile && !(e.getDamager() instanceof Trident)) {
Projectile projectile = (Projectile) e.getDamager(); Projectile projectile = (Projectile) e.getDamager();
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_WHIRLWIND)) { if (Talisman.trigger(e, SlimefunItems.TALISMAN_WHIRLWIND)) {
Player p = (Player) e.getEntity(); Player p = (Player) e.getEntity();
returnProjectile(p, projectile); 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 // We are also excluding entities which can pickup items, this is not perfect
// but it at least prevents dupes by tossing items to zombies // 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<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops()); Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops());
for (ItemStack drop : extraDrops) { for (ItemStack drop : extraDrops) {
@ -192,7 +192,7 @@ public class TalismanListener implements Listener {
@EventHandler @EventHandler
public void onItemBreak(PlayerItemBreakEvent e) { public void onItemBreak(PlayerItemBreakEvent e) {
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_ANVIL)) { if (Talisman.trigger(e, SlimefunItems.TALISMAN_ANVIL)) {
PlayerInventory inv = e.getPlayer().getInventory(); PlayerInventory inv = e.getPlayer().getInventory();
int slot = inv.getHeldItemSlot(); int slot = inv.getHeldItemSlot();
@ -225,7 +225,7 @@ public class TalismanListener implements Listener {
@EventHandler @EventHandler
public void onSprint(PlayerToggleSprintEvent e) { public void onSprint(PlayerToggleSprintEvent e) {
if (e.isSprinting()) { 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<Enchantment, Integer> enchantments = e.getEnchantsToAdd(); Map<Enchantment, Integer> enchantments = e.getEnchantsToAdd();
// Magician Talisman // Magician Talisman
if (Talisman.checkFor(e, SlimefunItems.TALISMAN_MAGICIAN)) {
MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem(); MagicianTalisman talisman = (MagicianTalisman) SlimefunItems.TALISMAN_MAGICIAN.getItem();
TalismanEnchantment enchantment = talisman.getRandomEnchantment(e.getItem(), enchantments.keySet()); 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()); enchantments.put(enchantment.getEnchantment(), enchantment.getLevel());
} }
} }
// Wizard Talisman // Wizard Talisman
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) { if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.trigger(e, SlimefunItems.TALISMAN_WIZARD)) {
// Randomly lower some enchantments
for (Enchantment enchantment : enchantments.keySet()) { for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
if (random.nextInt(100) < 40) { if (entry.getValue() > 1 && random.nextInt(100) < 40) {
e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1); 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); enchantments.put(Enchantment.LOOT_BONUS_BLOCKS, random.nextInt(3) + 3);
} }
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onExperienceReceive(PlayerExpChangeEvent e) { 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 // Double-XP
e.setAmount(e.getAmount() * 2); e.setAmount(e.getAmount() * 2);
} }
@ -267,21 +275,27 @@ public class TalismanListener implements Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onBlockDropItems(BlockDropItemEvent e) { 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();
// We are going to ignore Silk Touch here
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) { 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<Item> drops = e.getItems(); Collection<Item> 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)); int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
// Keep track of whether we actually doubled the drops or not
boolean doubledDrops = false; boolean doubledDrops = false;
// Loop through all dropped items
for (Item drop : drops) { for (Item drop : drops) {
ItemStack droppedItem = drop.getItemStack(); ItemStack droppedItem = drop.getItemStack();
// We do not want to dupe blocks
if (!droppedItem.getType().isBlock()) { if (!droppedItem.getType().isBlock()) {
int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount()); int amount = Math.max(1, (dropAmount * 2) - droppedItem.getAmount());
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount)); e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), new CustomItem(droppedItem, amount));
@ -289,8 +303,14 @@ public class TalismanListener implements Listener {
} }
} }
// Fixes #2077
if (doubledDrops) { 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 @EventHandler
public void onBlockBreak(BlockBreakEvent e) { public void onBlockBreak(BlockBreakEvent e) {
if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) { if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) {
Talisman.checkFor(e, SlimefunItems.TALISMAN_CAVEMAN); Talisman.trigger(e, SlimefunItems.TALISMAN_CAVEMAN);
} }
} }

View File

@ -13,7 +13,6 @@ import org.bukkit.potion.PotionEffect;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.VampireBlade; 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}. * This {@link Listener} is exclusively used for the {@link VampireBlade}.
@ -44,7 +43,7 @@ public class VampireBladeListener implements Listener {
Player p = (Player) e.getDamager(); Player p = (Player) e.getDamager();
if (blade.isItem(p.getInventory().getItemInMainHand())) { if (blade.isItem(p.getInventory().getItemInMainHand())) {
if (Slimefun.hasUnlocked(p, blade, true)) { if (blade.canUse(p, true)) {
blade.heal(p); blade.heal(p);
} else { } else {
e.setCancelled(true); e.setCancelled(true);

View File

@ -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.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; 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}. * 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); SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
if (sfItem != null) { 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)); sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
} else if (sfItem.getState() != ItemState.VANILLA_FALLBACK) { } else if (sfItem.getState() != ItemState.VANILLA_FALLBACK) {
/* /*

View File

@ -18,7 +18,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard; import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard;
import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/** /**
* This {@link Listener} is responsible for handling any custom mob drops. * 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) { if (item.getType() != Material.AIR) {
SlimefunItem sfItem = SlimefunItem.getByItem(item); 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)); 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) { 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; return true;
} else if (Slimefun.hasUnlocked(p, sfi, true)) { } else if (sfItem.canUse(p, true)) {
if (sfi instanceof RandomMobDrop) { if (sfItem instanceof RandomMobDrop) {
int random = ThreadLocalRandom.current().nextInt(100); int random = ThreadLocalRandom.current().nextInt(100);
if (((RandomMobDrop) sfi).getMobDropChance() <= random) { if (((RandomMobDrop) sfItem).getMobDropChance() <= random) {
return false; return false;
} }
} }
if (sfi instanceof BasicCircuitBoard) { if (sfItem instanceof BasicCircuitBoard) {
return ((BasicCircuitBoard) sfi).isDroppedFromGolems(); return ((BasicCircuitBoard) sfItem).isDroppedFromGolems();
} }
return true; return true;

View File

@ -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_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("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("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("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("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); register("reactor_access_port", 212, "Reactor Interaction", 18, SlimefunItems.REACTOR_ACCESS_PORT);

View File

@ -1666,6 +1666,13 @@ public final class SlimefunItemSetup {
.setProcessingSpeed(4) .setProcessingSpeed(4)
.register(plugin); .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 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}) 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) .setCapacity(128)

View File

@ -117,7 +117,7 @@ public class ArmorTask implements Runnable {
SlimefunPlugin.runSync(() -> { SlimefunPlugin.runSync(() -> {
SlimefunArmorPiece slimefunArmor = armorpiece.getItem().get(); SlimefunArmorPiece slimefunArmor = armorpiece.getItem().get();
if (Slimefun.hasUnlocked(p, slimefunArmor, true)) { if (slimefunArmor.canUse(p, true)) {
for (PotionEffect effect : slimefunArmor.getPotionEffects()) { for (PotionEffect effect : slimefunArmor.getPotionEffects()) {
p.removePotionEffect(effect.getType()); p.removePotionEffect(effect.getType());
p.addPotionEffect(effect); p.addPotionEffect(effect);
@ -138,7 +138,7 @@ public class ArmorTask implements Runnable {
SlimefunItem item = SlimefunItem.getByItem(helmet); 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); ((SolarHelmet) item).rechargeItems(p);
} }
} }

View File

@ -62,7 +62,12 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion {
private boolean isPlaceholder(@Nullable OfflinePlayer p, boolean requiresProfile, @Nonnull String params, @Nonnull String placeholder) { private boolean isPlaceholder(@Nullable OfflinePlayer p, boolean requiresProfile, @Nonnull String params, @Nonnull String placeholder) {
if (requiresProfile) { 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 { } else {
return placeholder.equals(params); return placeholder.equals(params);
} }
@ -76,6 +81,8 @@ class PlaceholderAPIIntegration extends PlaceholderExpansion {
if (profile.isPresent()) { if (profile.isPresent()) {
Stream<Research> stream = profile.get().getResearches().stream(); Stream<Research> stream = profile.get().getResearches().stream();
return String.valueOf(stream.mapToInt(Research::getCost).sum()); 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()) { if (profile.isPresent()) {
Set<Research> set = profile.get().getResearches(); Set<Research> set = profile.get().getResearches();
return String.valueOf(set.size()); 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()) { if (profile.isPresent()) {
Set<Research> set = profile.get().getResearches(); Set<Research> set = profile.get().getResearches();
return String.valueOf(Math.round(((set.size() * 100.0F) / SlimefunPlugin.getRegistry().getResearches().size()) * 100.0F) / 100.0F); 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()) { if (profile.isPresent()) {
return profile.get().getTitle(); return profile.get().getTitle();
} else if (p instanceof Player) {
return SlimefunPlugin.getLocalization().getMessage((Player) p, "placeholderapi.profile-loading");
} }
} }

View File

@ -47,6 +47,28 @@ public enum ColoredMaterial {
Material.BLACK_WOOL 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. * This {@link List} contains all stained glass colors ordered by their appearance ingame.
*/ */

View File

@ -15,6 +15,7 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.entity.Item; import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@ -358,4 +359,31 @@ public final class SlimefunUtils {
SlimefunPlugin.runSync(new CapacitorTextureUpdateTask(l, charge, capacity)); 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 <code>true</code> for non-Slimefun items.
* <p>
* 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;
}
}
} }

View File

@ -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.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer; 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.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.multiblocks.miner.IndustrialMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel;
@ -120,6 +121,12 @@ public enum SlimefunTag implements Tag<Material> {
*/ */
DIRT_VARIANTS, 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. * All variants of concrete powder.
* Can you believe there is no tag for this already? * Can you believe there is no tag for this already?
@ -184,6 +191,11 @@ public enum SlimefunTag implements Tag<Material> {
*/ */
INDUSTRIAL_MINER_ORES, 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. * All materials (crops) which the {@link CropGrowthAccelerator} will recognize.
*/ */
@ -210,8 +222,16 @@ public enum SlimefunTag implements Tag<Material> {
*/ */
CAVEMAN_TALISMAN_TRIGGERS; CAVEMAN_TALISMAN_TRIGGERS;
/**
* Lookup table for tag names.
*/
private static final Map<String, SlimefunTag> nameLookup = new HashMap<>(); private static final Map<String, SlimefunTag> 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 { static {
for (SlimefunTag tag : valuesCache) { for (SlimefunTag tag : valuesCache) {

View File

@ -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.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; 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}. * 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) { public boolean isHidden(@Nonnull Player p) {
for (SlimefunItem slimefunItem : getItems()) { for (SlimefunItem slimefunItem : getItems()) {
if (!slimefunItem.isHidden() && Slimefun.isEnabled(p, slimefunItem, false)) { if (!slimefunItem.isHidden() && !slimefunItem.isDisabledIn(p.getWorld())) {
return false; return false;
} }
} }

View File

@ -16,9 +16,11 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.Permission;
import io.github.thebusybiscuit.cscorelib2.collections.OptionalMap; import io.github.thebusybiscuit.cscorelib2.collections.OptionalMap;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; 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.exceptions.WrongItemStackException;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.ItemState; 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.NotConfigurable;
import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable; import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable;
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive; import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive;
@ -377,6 +380,26 @@ public class SlimefunItem implements Placeable {
return state != ItemState.ENABLED; 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 * This method returns the {@link SlimefunAddon} that registered this
* {@link SlimefunItem}. If this Item is from Slimefun itself, the current * {@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) { public void error(@Nonnull String message, @Nonnull Throwable throwable) {
Validate.notNull(addon, "Cannot send an error for an unregistered item!"); 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() }); 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) { 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:
*
* <p>
* <ul>
* <li>The {@link SlimefunItem} is not disabled
* <li>The {@link SlimefunItem} was not disabled for that {@link Player}'s {@link World}.
* <li>The {@link Player} has the required {@link Permission} (if present)
* <li>The {@link Player} has unlocked the required {@link Research} (if present)
* </ul>
* <p>
*
* If any of these conditions evaluate to <code>false</code>, 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<PlayerProfile> 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 @Override
public final boolean equals(Object obj) { public final boolean equals(Object obj) {
if (obj instanceof SlimefunItem) { if (obj instanceof SlimefunItem) {

View File

@ -74,8 +74,6 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
processing.remove(b); processing.remove(b);
return true; return true;
}); });
registerDefaultRecipes();
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@ -239,6 +237,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!"); warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!");
} }
registerDefaultRecipes();
if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) { if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) {
super.register(addon); super.register(addon);
} }

View File

@ -60,7 +60,7 @@ public interface InventoryBlock {
@Override @Override
public boolean canOpen(Block b, Player p) { 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));
} }
}; };
} }

View File

@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
@ -27,6 +28,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.apache.commons.lang.Validate;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
@ -360,6 +363,37 @@ public class BlockStorage {
} }
} }
/**
* This will return an {@link ImmutableMap} of the underline {@code Map<String, Config>} of
* this worlds {@link BlockStorage}.
*
* @return An {@link ImmutableMap} of the raw data.
*/
@Nonnull
public Map<Location, Config> getRawStorage() {
return ImmutableMap.copyOf(this.storage);
}
/**
* This will return an {@link ImmutableMap} of the underline {@code Map<String, Config>} 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<Location, Config> 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) { public static void store(Block block, ItemStack item) {
SlimefunItem sfitem = SlimefunItem.getByItem(item); SlimefunItem sfitem = SlimefunItem.getByItem(item);

View File

@ -1,18 +1,15 @@
package me.mrCookieSlime.Slimefun.api; package me.mrCookieSlime.Slimefun.api;
import java.util.Optional;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; 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.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/** /**
* Provides a few static convenience methods. * Provides a few static convenience methods.
* This class is slowly getting stripped away in favour of a more object-oriented approach.
* *
* @author TheBusyBiscuit * @author TheBusyBiscuit
* @author Walshy * @author Walshy
@ -32,18 +29,16 @@ public final class Slimefun {
* @param message * @param message
* whether a message should be sent to the player or not * whether a message should be sent to the player or not
* *
* @deprecated Moved to
* {@link SlimefunUtils#canPlayerUseItem(Player, ItemStack, boolean)}
*
* @return <code>true</code> if the item is a SlimefunItem, enabled, researched and if the player has the permission * @return <code>true</code> if the item is a SlimefunItem, enabled, researched and if the player has the permission
* to use it, * to use it,
* <code>false</code> otherwise. * <code>false</code> otherwise.
*/ */
@Deprecated
public static boolean hasUnlocked(Player p, ItemStack item, boolean message) { public static boolean hasUnlocked(Player p, ItemStack item, boolean message) {
SlimefunItem sfItem = SlimefunItem.getByItem(item); return SlimefunUtils.canPlayerUseItem(p, item, message);
if (sfItem != null) {
return hasUnlocked(p, sfItem, message);
} else {
return true;
}
} }
/** /**
@ -56,38 +51,14 @@ public final class Slimefun {
* @param message * @param message
* whether a message should be sent to the player or not * whether a message should be sent to the player or not
* *
* @deprecated Please use {@link SlimefunItem#canUse(Player, boolean)} instead.
*
* @return <code>true</code> if the item is enabled, researched and the player has the permission to use it, * @return <code>true</code> if the item is enabled, researched and the player has the permission to use it,
* <code>false</code> otherwise. * <code>false</code> otherwise.
*/ */
@Deprecated
public static boolean hasUnlocked(Player p, SlimefunItem sfItem, boolean message) { public static boolean hasUnlocked(Player p, SlimefunItem sfItem, boolean message) {
if (sfItem.getState() == ItemState.VANILLA_FALLBACK) { return sfItem.canUse(p, message);
return true;
}
if (isEnabled(p, sfItem, message) && hasPermission(p, sfItem, message)) {
if (sfItem.getResearch() == null) {
return true;
} else {
Optional<PlayerProfile> 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;
} }
/** /**
@ -127,9 +98,12 @@ public final class Slimefun {
* @param message * @param message
* whether a message should be sent to the player or not * whether a message should be sent to the player or not
* *
* @deprecated This method will be removed.
*
* @return <code>true</code> if the item is a SlimefunItem and is enabled in the world the player is in, * @return <code>true</code> if the item is a SlimefunItem and is enabled in the world the player is in,
* <code>false</code> otherwise. * <code>false</code> otherwise.
*/ */
@Deprecated
public static boolean isEnabled(Player p, ItemStack item, boolean message) { public static boolean isEnabled(Player p, ItemStack item, boolean message) {
SlimefunItem sfItem = SlimefunItem.getByItem(item); SlimefunItem sfItem = SlimefunItem.getByItem(item);

View File

@ -105,18 +105,21 @@ public class DirtyChestMenu extends ChestMenu {
if (stack == null) { if (stack == null) {
replaceExistingItem(slot, item); replaceExistingItem(slot, item);
return null; return null;
} else if (stack.getAmount() < stack.getMaxStackSize()) { } else {
int maxStackSize = Math.min(stack.getMaxStackSize(), toInventory().getMaxStackSize());
if (stack.getAmount() < maxStackSize) {
if (wrapper == null) { if (wrapper == null) {
wrapper = new ItemStackWrapper(item); wrapper = new ItemStackWrapper(item);
} }
if (ItemUtils.canStack(wrapper, stack)) { if (ItemUtils.canStack(wrapper, stack)) {
amount -= (stack.getMaxStackSize() - stack.getAmount()); amount -= (maxStackSize - stack.getAmount());
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize())); stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), maxStackSize));
item.setAmount(amount); item.setAmount(amount);
} }
} }
} }
}
if (amount > 0) { if (amount > 0) {
return new CustomItem(item, amount); return new CustomItem(item, amount);

View File

@ -38,9 +38,8 @@ networks:
enable-visualizer: true enable-visualizer: true
delete-excess-items: false delete-excess-items: false
items: talismans:
talismans: true use-actionbar: true
soulbound: true
metrics: metrics:
auto-update: true auto-update: true

View File

@ -1,25 +1,26 @@
--- ---
slimefun: 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ě weapons: Zbraně
misc: Smíšené položky tools: Nástroje
valentines_day: Svatého Valentýna (14. Února) 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

View File

@ -2,7 +2,7 @@
slimefun: slimefun:
weapons: Wapens weapons: Wapens
tools: Gereedschappen tools: Gereedschappen
items: Voorwerpen items: Handige Voorwerpen
food: Eten food: Eten
basic_machines: Standaard machines basic_machines: Standaard machines
electricity: Energie en Elektriciteit electricity: Energie en Elektriciteit
@ -13,7 +13,7 @@ slimefun:
misc: Diverse Voorwerpen misc: Diverse Voorwerpen
technical_gadgets: Technische Gadgets technical_gadgets: Technische Gadgets
resources: Grondstoffen resources: Grondstoffen
cargo: Cargobehering cargo: Opslagbehering
tech_misc: Technische Componenten tech_misc: Technische Componenten
magical_armor: Magische Bescherming magical_armor: Magische Bescherming
talismans: Amuletten (Niveau I) talismans: Amuletten (Niveau I)

View File

@ -4,7 +4,7 @@ commands:
cheat: Позволява Ви да чийтвате Предмети cheat: Позволява Ви да чийтвате Предмети
give: Позволява Ви да давате на някого Slimefun Предмети give: Позволява Ви да давате на някого Slimefun Предмети
guide: Дава ви Slimefun Ръководство guide: Дава ви Slimefun Ръководство
teleporter: Вижте пътни точки от други играчи teleporter: Вижте пътни точки на други играчи
versions: Лист с всички инсталирани Добавки versions: Лист с всички инсталирани Добавки
search: Претърсва вашето Ръководство за даден термин / предмет search: Претърсва вашето Ръководство за даден термин / предмет
open_guide: Отваря Ви Slimefun Ръководството без да използвате книгата open_guide: Отваря Ви Slimefun Ръководството без да използвате книгата
@ -48,10 +48,10 @@ guide:
selected-language: 'Избран в момента:' selected-language: 'Избран в момента:'
change: Натисни, за да избереш нов език change: Натисни, за да избереш нов език
description: description:
- "&7Сега имаш опцията да промениш" '0': "&7Сега имаш опцията да промениш"
- "&7езика, на който е Slimefun" '1': "&7езика, на който е Slimefun"
- "&7той ще се промени само за теб. Предметите" '2': "&7той ще се промени само за теб. Предметите"
- "&7не могат да бъдат преведени за момента." '3': "&7не могат да бъдат преведени за момента."
title: title:
main: Slimefun Ръководство main: Slimefun Ръководство
settings: Настройки & Информация settings: Настройки & Информация
@ -73,10 +73,10 @@ guide:
profile-link: Натиснете, за да видите техния профил в GitHub profile-link: Натиснете, за да видите техния профил в GitHub
open: Натисни, за да видиш нашите контрибутори open: Натисни, за да видиш нашите контрибутори
description: description:
- "&7Slimefun е проект с отворен код" '0': "&7Slimefun е проект с отворен код"
- "&7и е поддържан от голямо общество от хора." '1': "&7и е поддържан от голямо общество от хора."
- "&7Над &e%contributors% &7хора са работили върху" '2': "&7Над &e%contributors% &7хора са работили върху"
- "&7Slimefun през всички тези години." '3': "&7Slimefun през всички тези години."
pages: pages:
previous: Предишна страница previous: Предишна страница
next: Следваща страница next: Следваща страница
@ -96,9 +96,9 @@ guide:
settings: Върнете се обратно в Панела с Настройки(Settings Panel) settings: Върнете се обратно в Панела с Настройки(Settings Panel)
locked: ЗАКЛЮЧЕНО locked: ЗАКЛЮЧЕНО
locked-category: locked-category:
- За да отключите тази категория '0': За да отключите тази категория
- ще трябва да отключите всички предмети от '1': ще трябва да отключите всички предмети от
- следните категории '2': следните категории
work-in-progress: Тази функция не е завършена все още! work-in-progress: Тази функция не е завършена все още!
messages: messages:
not-researched: "&4Нямате достатъчно познания, за да разберете това" not-researched: "&4Нямате достатъчно познания, за да разберете това"
@ -134,6 +134,7 @@ messages:
wizard: "&a&oВашия Талисман Ви даде по-добро Ниво Fortune, но може да е намалило wizard: "&a&oВашия Талисман Ви даде по-добро Ниво Fortune, но може да е намалило
Нивата на някои от другите Ви Enchantment-и" Нивата на някои от другите Ви Enchantment-и"
caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене" caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене"
wise: "&a&oВашия Талисман удвой вашите XP дропове"
soulbound-rune: soulbound-rune:
fail: "& cМожете да свържете само един елемент с душата си наведнъж." fail: "& cМожете да свържете само един елемент с душата си наведнъж."
success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие
@ -153,22 +154,22 @@ messages:
link-prompt: "&eНатиснете тук:" link-prompt: "&eНатиснете тук:"
diet-cookie: "&eЗапочнахте да се чувствате доста лекичък..." diet-cookie: "&eЗапочнахте да се чувствате доста лекичък..."
fortune-cookie: fortune-cookie:
- "&7Помогнете ми, аз съм затворен в Фабрика за Късметлийски Бисквитки!" '0': "&7Помогнете ми, аз съм затворен в Фабрика за Късметлийски Бисквитки!"
- "&7Утре Вие ще умрете... от Creeper" '1': "&7Утре Вие ще умрете... от Creeper"
- "&7В някакъв момент от живота Ви нещо лошо ще се случи!!!" '2': "&7В някакъв момент от живота Ви нещо лошо ще се случи!!!"
- "&7Следващата седмица ще забележите, че това не е реалния свят, а всъщност Вие '3': "&7Следващата седмица ще забележите, че това не е реалния свят, а всъщност
сте в компютърна игра" Вие сте в компютърна игра"
- "&7Тази бисквитка ще стане вкусна в следващите няколко секунди" '4': "&7Тази бисквитка ще стане вкусна в следващите няколко секунди"
- '&7Последната дума, която ще чуете ще бъде "УНИЩОЖЕТЕ!!!"' '5': '&7Последната дума, която ще чуете ще бъде "УНИЩОЖЕТЕ!!!"'
- "&7Каквото и да правите никога, ама никога не прегръщайте Creeper... Аз опитах. '6': "&7Каквото и да правите никога, ама никога не прегръщайте Creeper... Аз опитах.
Доста добре е, но не си заслужава." Доста добре е, но не си заслужава."
- "&742. Отговорът е 42." '7': "&742. Отговорът е 42."
- "&7Walshy веднъж на ден ще пази неприятностите далече." '8': "&7Walshy веднъж на ден ще пази неприятностите далече."
- "&7Никога не копайте право надолу!" '9': "&7Никога не копайте право надолу!"
- "&7Туй е само плътна рана!" '10': "&7Туй е само плътна рана!"
- "&7Винаги гледайте от към хубавата страна на живота!" '11': "&7Винаги гледайте от към хубавата страна на живота!"
- "&7Това беше Бисквитка, а не Курабийка" '12': "&7Това беше Бисквитка, а не Курабийка"
- "&7Неоновите табели светят!" '13': "&7Неоновите табели светят!"
piglin-barter: "&4Не може да разменяте предмети с Пиглините използвайки предмети piglin-barter: "&4Не може да разменяте предмети с Пиглините използвайки предмети
от Slimefun" от Slimefun"
enchantment-rune: enchantment-rune:
@ -268,9 +269,9 @@ gps:
max: "&4Достигнахте максималната бройка локации" max: "&4Достигнахте максималната бройка локации"
duplicate: "&4Вие вече сте създал локация на име: &f%waypoint%" duplicate: "&4Вие вече сте създал локация на име: &f%waypoint%"
insufficient-complexity: insufficient-complexity:
- "&4Недостатъчна Сложност на GPS Мрежата: &c%complexity%" '0': "&4Недостатъчна Сложност на GPS Мрежата: &c%complexity%"
- "&4a) Все още нямате направена GPS Мрежа" '1': "&4a) Все още нямате направена GPS Мрежа"
- "&4b) Вашата GPS Мрежа не е достатъчно сложна" '2': "&4b) Вашата GPS Мрежа не е достатъчно сложна"
geo: geo:
scan-required: "&4GEO-Scan изискан! &cПърво сканирайте този чънк използвайки GEO-Scanner!" scan-required: "&4GEO-Scan изискан! &cПърво сканирайте този чънк използвайки GEO-Scanner!"
inventory: inventory:
@ -309,11 +310,10 @@ android:
INTERFACE_ITEMS: "&9Изпратни съдаржанието на Инвентара към лицевия Интерфейс" INTERFACE_ITEMS: "&9Изпратни съдаржанието на Инвентара към лицевия Интерфейс"
INTERFACE_FUEL: "&cИзвадете Гориво от лицевия Интерфейс" INTERFACE_FUEL: "&cИзвадете Гориво от лицевия Интерфейс"
enter-name: enter-name:
- '1': "&eМоля въведете име за скрипта си"
- "&eМоля въведете име за скрипта си"
uploaded: uploaded:
- "&bКачване..." '0': "&bКачване..."
- "&aУспешно качихме твоя скрипт!" '1': "&aУспешно качихме твоя скрипт!"
rating: rating:
own: "&4Не може да оцените собствения си скрипт!" own: "&4Не може да оцените собствения си скрипт!"
already: "&4Вие вече сте оставили рейтинг за този скрипт!" already: "&4Вие вече сте оставили рейтинг за този скрипт!"
@ -369,3 +369,5 @@ cartography_table:
not-working: "&4Не може да използвате Slimefun предмети в картографска маса!" not-working: "&4Не може да използвате Slimefun предмети в картографска маса!"
cauldron: cauldron:
no-discoloring: "&4Не можете да обезцветявате Slimefun брони" no-discoloring: "&4Не можете да обезцветявате Slimefun брони"
placeholderapi:
profile-loading: Зареждане...

View File

@ -1,34 +1,38 @@
--- ---
commands: commands:
help: Zobrazí tuto nápovědu help: Zobrazí tuto nápovědu
cheat: Umožňuje nacheatovat věci cheat: Umožní našvindlovat si věci
give: Dejte někomu nějaké Slimefun věci give: Dá hráči vybrané Slimefun předměty
guide: Dá vám Slimefun příručku guide: Dá Slimefun příručku
timings: Lag-Info vašeho serveru teleporter: Zobrazí záchytné body ostatních hráčů
teleporter: "Zobrazí \nznačky \nostatních hráčů" versions: Zobrazí všechny nainstalované doplňky
versions: Seznam všech nainstalovaných doplňků search: Vyhledá v příručce daný předmět
search: Vyhledá ve vaší příručce daný příkaz
open_guide: Otevře Slimefun příručku bez použití knihy open_guide: Otevře Slimefun příručku bez použití knihy
stats: Ukáže statistiky hráče stats: Ukáže statistiky hráče
research: 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: "&cResetoval jsi výzkum hráče %player%"
reset-target: "&cTvoje znalost byla resetována " reset-target: "&cTvoje znalost byla resetována "
backpack: backpack:
description: Načíst kopii existujícího batohu description: Načíst kopii existujícího batohu
invalid-id: "&4Id nesmí být záporné!" invalid-id: "&4Id nesmí být záporné!"
player-never-joined: "&4Hráče s tímto jménem nelze nalézt!" 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!" 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: guide:
search: search:
message: "&bCo bys chtěl vyhledat?" message: "&bCo bys chtěl vyhledat?"
name: "&7Hledat..." name: "&7Hledat..."
tooltip: "&bKliknutím vyhledejte položku" tooltip: "&bKlikni pro vyhledání předmětu"
inventory: 'Hledání: %item%' inventory: 'Hledání: %item%'
lore: lore:
- "&bCo bys chtěl vyhledat?" '1': "&7Napiš do chatu co chceš vyhledat"
- "&7Napiš do chatu co chceš vyhledat" '0': "&bCo bys chtěl vyhledat?"
cheat: cheat:
no-multiblocks: "&4Nemůžeš podvádět v multiblocích, musíš je postavit!" no-multiblocks: "&4Nemůžeš podvádět v multiblocích, musíš je postavit!"
languages: languages:
@ -41,70 +45,69 @@ guide:
selected-language: 'Aktuálně vybráno:' selected-language: 'Aktuálně vybráno:'
change: Klikni pro výběr nového jazyka change: Klikni pro výběr nového jazyka
description: description:
- "&7Nyní máš možnost to změnit" '0': "&7Nyní máš možnost změnit"
- "&7jazyk, ve kterém bude Slimefun" '1': "&7jazyk, ve kterém ti bude"
- "&7bude ti představeno. Předměty" '2': "&7Slimefun prezentován. Předměty"
- "&7nelze prozatím přeložit." '3': "&7nelze prozatím přeložit."
title: title:
main: Slimefun příručka main: Slimefun příručka
settings: Nastavení a informace settings: Nastavení a informace
languages: Zvol tvůj preferovaný jazyk languages: Zvol svůj preferovaný jazyk
credits: Slimefun4 pomocníci credits: Slimefun4 pomocníci
wiki: Slimefun4 Wiki wiki: Slimefun4 Wiki
addons: Addony pro Slimefun4 addons: Doplňky pro Slimefun4
bugs: Nahlášení chyb bugs: Nahlášení chyb
source: Zdrojový kód source: Zdrojový kód
versions: Nainstalovaná verze versions: Nainstalovaná verze
credits: credits:
commit: Commit
commits: Commits commits: Commits
roles: roles:
developer: "&6Vývojář" developer: "&6Vývojář"
wiki: "&3Wiki správce" wiki: "&3Wiki správce"
resourcepack: "&cTvůrce Resourcepacku" resourcepack: "&cTvůrce modifikačního balíčku"
translator: "&9Překladač" translator: "&9Překladatel"
profile-link: Klikni pro navštívení jejich profilu na GitHubu profile-link: Klikni pro navštívení jeho profilu na GitHubu
open: Klikni pro zobrazení našich spoluúčastníků open: Klikni pro zobrazení našich pomocníků
description: description:
- "&7Slimefun je open-source projekt" '0': "&7Slimefun je open-source projekt"
- "&7a udržován velkou komunitou lidí." '1': "&7udržován velkou komunitou lidí."
- "&Přes&e%contributors% &7lidí na tom pracovalo" '2': "&7Na Slimefunu za všechny ty roky pracovalo"
- "&7Slimefun za všechny ty roky." '3': "&7přes &e%contributors% &7lidí."
pages: pages:
previous: Předchozí strana previous: Předchozí strana
next: Následující strana next: Následující strana
tooltips: tooltips:
open-category: Klikni pro otevření open-category: Klikni pro otevření
versions-notice: To jsou velmi důležité při hlášení chyb! 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: recipes:
machine: Recepty vytvářené tímto strojem machine: Recepty vytvářené tímto strojem
miner: Materiály, které můžeš získat tímto těžebním robotem miner: Materiály, které můžeš získat tímto těžebním robotem
generator: Dostupné typy paliv generator: Dostupné typy paliv
gold-pan: Materiály, které můžeš získat gold-pan: Materiály, které můžeš získat
climbing-pick: Povrchy, na které můžeš lézt
back: back:
title: Zpět title: Zpět
guide: Zpět do Slimefun Guide guide: Zpět do Slimefun příručky
settings: Zpět do Settings Panel settings: Zpět do panelu nastavení
locked: ZAMČENO locked: ZAMČENO
locked-category: locked-category:
- Chcete-li odemknout tuto kategorii, budete '0': Chceš-li odemknout tuto kategorii,
- 'je třeba odemknout všechny položky z ' '1': je potřeba odemknout všechny předměty
- následující kategorie '2': z předchozích kategorií
work-in-progress: Tato funkce ještě není zcela dokončena! work-in-progress: Tato funkce ještě není zcela dokončena!
messages: messages:
not-researched: "&4Ještě jsi nepostoupil tak daleko, abys pochopil tuhle věc" 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" not-enough-xp: "&4Nemáš dostatek XP úrovní na to, abys vyzkoumal tuhle věc"
unlocked: '&bMáš vyzkoumáno &7"%research%"' unlocked: "&bMáš vyzkoumáno &7„%research%”"
only-players: "&4Tenhle příkaz je jenom pro hráče" only-players: "&4Tenhle příkaz je jenom pro hráče"
unknown-player: "&4Neznámý hráč: &c%player%" 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%" usage: "&4Použití: &c%usage%"
not-online: "&4%player% &czrovna není připojen!" not-online: "&4%player% &czrovna není připojen!"
invalid-item: "&4%item% &cnení platný item!" given-item: "&bDostal jsi &a%amount% &7„%item%&7”"
invalid-amount: "&4%amount% &cnení platné číslo : musí být větší než 0!" give-item: "&bDal jsi %player% &a%amount% &7„%item%&7”"
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!"
give-research: '&bUdělil jsi %player% výzkum &7"%research%&7"' give-research: '&bUdělil jsi %player% výzkum &7"%research%&7"'
hungry: "&cJsi moc hladový na to, abys to zvládl!" hungry: "&cJsi moc hladový na to, abys to zvládl!"
disabled-in-world: "&4&lTahle věc není v tomhle světě povolená" disabled-in-world: "&4&lTahle věc není v tomhle světě povolená"
@ -115,83 +118,96 @@ messages:
multimeter: "&bEnergie: &3%stored% &b/ &3%capacity%" multimeter: "&bEnergie: &3%stored% &b/ &3%capacity%"
talisman: talisman:
anvil: "&a&oTvůj talisman zachránil tvůj nástroj od rozbití" anvil: "&a&oTvůj talisman zachránil tvůj nástroj od rozbití"
miner: "&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 tvoje dropy" hunter: "&a&oTvůj talisman zdvojnásobil tvou kořist"
lava: "&a&oTvůj talisman tě zachránil před uhořením" 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" 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" 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" 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" traveller: "&a&oTvůj talisman ti dal rychlost"
warrior: "&a&oTvůj talisman ti dal efekt síly na nějakou tu chvíli" warrior: "&a&oTvůj talisman ti dal na určitou chvilku efekt síly"
knight: "&a&oTvůj talisman ti dal 5 vteřin regenerace" knight: "&a&oTvůj talisman ti dal 5 sekund regenerace"
whirlwind: "&a&oTvůj talisman odrazil projektil" 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 wizard: "&a&oTvůj talisman ti dal větší úroveň štěstí, ale možná snížil úroveň
enchantů" 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: soulbound-rune:
fail: "&cKe své duši můžeš přidat jen jeden předmět." fail: "&cSvou duši můžeš spoutat jen s jedním předmětem."
success: "&aÚspěšně jsi přidal tento item ke své duši. Pokud zemřeš, item ti zůstane." success: "&aÚspěšně jsi spoutal tento předmět se svou duši. Pokud zemřeš, předmět
ti zůstane."
research: 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%)" progress: "&7Začal jsi přemýšlet nad &b%research% &e(%progress%)"
fire-extinguish: "&7Uhasil ses" fire-extinguish: "&7Uhasil ses"
cannot-place: "&cZde nemůžeš položit blok!" cannot-place: "&cZde nemůžeš položit blok!"
no-pvp: "&cZde nemůžeš bojovat s hráči!" no-pvp: "&cZde nemůžeš bojovat s hráči!"
radiation: "&4Byl jsi vystaven smrtelné radiaci! &cVyhoď radioaktivní předmět nebo radiation: "&4Byl jsi vystaven smrtelné radiaci! &cVyhoď radioaktivní předmět nebo
si obleč Hazmat oblek." si obleč hazmat oblek."
opening-guide: "&bOtevírání příručky, může to pár sekund trvat..." opening-guide: "&bOtevírá se příručka, může to pár sekund trvat..."
opening-backpack: "&bOtevírání batohu, může to pár sekund trvat..." opening-backpack: "&bOtevírá se batoh, může to pár sekund trvat..."
no-iron-golem-heal: "&cTo není Iron Ingot! S tímto nemůžeš léčit Iron Golemy!" no-iron-golem-heal: "&cTohle není železný ingot, a proto s ním nemůžeš léčit železné
golemy!"
link-prompt: "&eKlikni zde:" link-prompt: "&eKlikni zde:"
diet-cookie: "&eZačínáš se cítit velice leh..." diet-cookie: "&eZačínáš se cítit velice lehce..."
fortune-cookie: fortune-cookie:
- "&7POMOOC!! Jsem uvězněn v továrně na sušenky štěstí!" '0': "&7POMOOC!! Jsem uvězněn v továrně na sušenky štěstí!"
- "&7Zítra zemřeš... s láskou od pana Creepera" '1': "&7Zítra zemřeš... s láskou od pana creepera"
- "&7V nějaké části tvého života se stane něco špatného!!!" '2': "&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." '3': "&7Příští týden si uvědomíš, že toto není reálný život, ale že jsi v počítačové
- "&7Sušenka ti bude za pár vteřin velice chutnat" hře"
- '&7Poslední slovo, které uslyšíš bude "VYHUBIT!!!"' '4': "&7Sušenka ti bude za pár sekund velice chutnat"
- "&7Ať se stane cokoliv, nepokoušej se mazlit Creepera... Zkusil jsem to. Je to '5': "&7Poslední slovo, které uslyšíš bude „VYHUBIT!!!”"
dobrý pocit, ale nestojí to za to." '6': "&7Ať se stane cokoliv, nepokoušej se mazlit creepera... Zkusil jsem to.
- "&742. Odpověď je 42." Je to dobrý pocit, ale nestojí to za to."
- "&7Walshy udrží den problémy pryč." '7': "&742. Odpověď je 42."
- "&7Nikdy nekopej pod sebe!" '8': "&7Walshy udrží den problémy pryč."
- "&7To je jen rána masa!" '9': "&7Nikdy nekopej pod sebe!"
- "&7Vždy se podívejte na světlou stránku života!" '10': "&7To je jen rána masa!"
- "&7Tohle byl vlastně Biscuit a ne Cookie" '11': "&7Vždy se podívej na světlou stránku života!"
- "&7Neonové cedule jsou LIT!" '12': "&7Tohle byl vlastně Biscuit, a ne Cookie"
piglin-barter: "&4Nemůžete měnit s pigliny Slimefun předměty" '13': "&7Neonové cedule jsou LIT!"
piglin-barter: "&4S pigliny nemůžeš vyměňovat Slimefun předměty"
enchantment-rune: enchantment-rune:
fail: "&cNemůžeš enchantovat tento předmět" fail: "&cNemůžeš očarovat tento předmět."
no-enchantment: "&cPro tento předmět nelze najít žádný vhodný enchant." 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 daů náhodný enchant." success: "&aÚspěšně jsi na tento předmět dal náhodné vhodné očarování."
tape-measure: 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!" wrong-world: "&cTvoje kotva je pravděpodobně v jiném světa!"
distance: "&7Měření zahájeno. &eVzdálenost: %distance%" distance: "&7Měření zahájeno. &eVzdálenost: %distance%"
anchor-set: "&aÚspěšně nastavena kotva:&e %anchor%" anchor-set: "&aÚspěšně nastavena kotva:&e %anchor%"
multi-tool: multi-tool:
mode-change: "&b%device% mód změněn na: &9%mode%" 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!" 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%" mode-change: "&b%device% mód změněn na: &9%mode%"
machines: 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." předměty tak, aby odpovídaly receptu."
unknown-material: "&eOmlouvám se, ale nepoznal jsem předmět v dispenseru. Dej tam unknown-material: "&eBohužel se nepodařilo rozpoznat tento předmět v dávkovači.
něco, co znám." Dej tam něco správného."
wrong-item: "&eOmlouvám se, ale nerozpoznal jsem předmět, se kterým jsi na mě kliknul. 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." Zkontroluj recept a koukni se, jaké předměty můžeš použít."
full-inventory: "&eOmlouvám se, můj inventář je plný." full-inventory: "&eBohužel, můj inventář je plný."
in-use: "&cInventář tohoto bloku je právě otevřen jiným hráčem" in-use: "&cInventář tohoto bloku je právě otevřen jiným hráčem."
ignition-chamber-no-flint: "&cIgnition Chamberu chybí křesadlo." ignition-chamber-no-flint: "&cIgnition Chamberu chybí křesadlo."
ANCIENT_ALTAR: 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-catalyst: "&4Neznámý katalyst. &cPoužij správný recept!"
unknown-recipe: "&4Neznámý recept! &cPoužij správný recept!" unknown-recipe: "&4Neznámý recept! &cPoužij správný recept!"
ANCIENT_PEDESTAL: ANCIENT_PEDESTAL:
obstructed: "&4Podstavce jsou zablokované! &cOdstraň cokoliv nad podstavcema!" obstructed: "&4Pedestal je zablokován! &cOdstraň cokoliv nad ním!"
HOLOGRAM_PROJECTOR: 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!)" jsou podporovány!)"
inventory-title: Editor hologramu inventory-title: Editor hologramu
ELEVATOR: ELEVATOR:
@ -199,62 +215,63 @@ machines:
pick-a-floor: "&3- Vyber si patro -" pick-a-floor: "&3- Vyber si patro -"
current-floor: "&eAktuální patro:" current-floor: "&eAktuální patro:"
click-to-teleport: "&eKliknutím &7se teleportuješ na toto 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!)" enter-name: "&7Zadej název podlaží do chatu. &r(Barvy jsou podporovány!)"
named: "&2Podlaží úspěšně pojmenováno na: &r%floor%" named: "&2Podlaží úspěšně pojmenováno: &r%floor%"
TELEPORTER: TELEPORTER:
teleporting: "&3Teleportuji..." teleporting: "&3Teleportuji..."
teleported: "&3Teleportace dokončena!" teleported: "&3Teleportace dokončena!"
cancelled: "&4Teleportace zrušena!" cancelled: "&4Teleportace zrušena!"
invulnerability: "&b&lZískal jsi 30 sekund nezranitelnosti!" invulnerability: "&b&lZískal jsi 30 sekund nezranitelnosti!"
gui: gui:
title: Vaše waypointy title: Tvé záchytné body
tooltip: Klikněte pro teleportaci tooltip: Klikni pro teleportaci
time: Předpokládaný čas time: Předpokládaný čas
CARGO_NODES: CARGO_NODES:
must-be-placed: "&4Musí být umístěn na truhlu nebo stroj!" must-be-placed: "&4Musí být umístěn na truhlu nebo stroj!"
GPS_CONTROL_PANEL: GPS_CONTROL_PANEL:
title: GPS - Kontrolní panel title: GPS - Kontrolní panel
transmitters: Přehled vysílačů transmitters: Přehled vysílačů
waypoints: Přehled waypointů waypoints: Přehled záchytných bodů
INDUSTRIAL_MINER: 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-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!" 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ěží!" already-running: "&cTento průmyslový horník již běží!"
full-chest: "&cBedna vašeho průmyslového horníka je plná!" 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!" no-permission: "&4Zdá se, že zde nemáš oprávnění používat průmyslového horníka!"
finished: "&eVáš průmysloví horník dokončil práci! Získal %ores% hornin!" finished: "&eTvůj průmysloví horník dokončil práci! Získal %ores% rud!"
anvil: anvil:
not-working: "&4Předměty ze Slimefunu nelze použít v kovadlině!" not-working: "&4Předměty ze Slimefunu nelze použít v kovadlině!"
mcmmo-salvaging: "&4Nemůžeš zachránit Slimefun předměty!"
backpack: backpack:
already-open: "&cOmlouváme se, tento batoh je otevřený již někde jinde!" already-open: "&cBohužel, tento batoh je již otevřený někde jinde!"
no-stack: "&cNemůžeš stackovat batohy" no-stack: "&cNemůžeš shromažďovat batohy"
workbench: 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: gps:
deathpoint: "&4Bod úmrtí &7%date%" deathpoint: "&4Bod úmrtí &7%date%"
waypoint: waypoint:
new: "&eProsím, zadejte název waypointu do chatu. &7(Barvy jsou podporovány!)" new: "&eZadej název záchytného bodu do chatu. &7(Barvy jsou podporovány!)"
added: "&aÚspěšně přidán nový waypoint" added: "&aÚspěšně přidán nový záchytný bod"
max: "&4Dosáhl jsi maxima waypointů" max: "&4Dosáhl jsi maxima záchytných bodů"
duplicate: "&4Již jsi vytvořil waypoint pojmenovaný: &f%waypoint%" duplicate: "&4Již jsi vytvořil záchytný bod pojmenovaný: &f%waypoint%"
insufficient-complexity: insufficient-complexity:
- "&4Nedostatečná komplexita GPS Networku: &c%complexity%" '0': "&4Nedostatečná komplexita GPS Networku: &c%complexity%"
- "&4a) Nemáš nastavený GPS Network" '1': "&4a) Nemáš nastavený GPS Network"
- "&4b) TvůjGPS Network není dostatečně komplexní" '2': "&4b) Tvůj GPS Network není dostatečně komplexní"
geo: 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: inventory:
no-access: "&4Nemáš přístup k tomuto bloku" no-access: "&4Nemáš přístup k tomuto bloku"
android: android:
started: "&7Tvůj Android právě začal používat 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ý script" stopped: "&7Tvůj Android pozastavil jemu přidělený skript"
scripts: scripts:
already-uploaded: "&4Tento script byl již nahrán." already-uploaded: "&4Tento skript již byl nahrán."
instructions: instructions:
START: "&2Začít Script" START: "&2Začít skript"
REPEAT: "&9Opakovat Script" REPEAT: "&9Opakovat skript"
WAIT: "&ePočkej 0.5s" WAIT: "&ePočkej 0.5s"
GO_FORWARD: "&7Posuň se vpřed" GO_FORWARD: "&7Posuň se vpřed"
GO_UP: "&7Posuň se nahoru" GO_UP: "&7Posuň se nahoru"
@ -267,8 +284,8 @@ android:
MOVE_AND_DIG_UP: "&bPosuň se a zároveň kopej nahoru" 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_FORWARD: "&bPosuň se a zároveň kopej dopředu"
MOVE_AND_DIG_DOWN: "&bPosuň se a zároveň kopej dolů" 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_ANIMALS: "&4Útoč na &cnepřátelská stvoření a zvířata"
ATTACK_MOBS: "&4Útoč na &cnepřátelské moby" ATTACK_MOBS: "&4Útoč na &cnepřátelská stvoření"
ATTACK_ANIMALS: "&4Útoč na &czvířata" 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ď" CHOP_TREE: "&cPokácej a zasaď"
@ -280,15 +297,15 @@ android:
INTERFACE_ITEMS: "&9Přesuň obsah inventáře do rozhraní na přední straně" INTERFACE_ITEMS: "&9Přesuň obsah inventáře do rozhraní na přední straně"
INTERFACE_FUEL: "&cVyndej palivo z rozhraní přední strany" INTERFACE_FUEL: "&cVyndej palivo z rozhraní přední strany"
enter-name: enter-name:
- '1': "&eZadej název tvého skriptu"
- "&eProsíme, zadejte název vašeho scriptu"
uploaded: uploaded:
- "&bNahrávání..." '0': "&bNahrávání..."
- "&aTvůj script byl úspěšně nahrán!" '1': "&aTvůj skript byl úspěšně nahrán!"
rating: rating:
own: "&4Nemůžeš hodnotit vlastní script!" own: "&4Nemůžeš hodnotit vlastní skript!"
already: "&4K tomuto scriptu jsi již zanechal hlasování!" already: "&4K tomuto skriptu jsi již zanechal hlasování!"
editor: Editor skriptu editor: Editor skriptu
too-long: "&cSkript je příliš dlouhý na úpravu!"
languages: languages:
default: Výchozí-serverový default: Výchozí-serverový
en: Angličtina en: Angličtina
@ -298,7 +315,7 @@ languages:
es: Španělština es: Španělština
pl: Polština pl: Polština
sv: Švédština sv: Švédština
nl: Holandština nl: Nizozemština
cs: Čeština cs: Čeština
hu: Maďarština hu: Maďarština
lv: Lotyština lv: Lotyština
@ -310,8 +327,6 @@ languages:
zh-CN: Čínština (Čína) zh-CN: Čínština (Čína)
el: Řečtina el: Řečtina
he: Hebrejština he: Hebrejština
pt: Portugalština (Portugalsko)
pt-BR: Portugalština (Brazílie)
ar: Arabština ar: Arabština
af: Afrikánština af: Afrikánština
da: Dánština da: Dánština
@ -323,6 +338,8 @@ languages:
fa: Perština fa: Perština
th: Thajština th: Thajština
ro: Rumunština ro: Rumunština
pt: Portugalština (Portugalsko)
pt-BR: Portugalština (Brazílie)
bg: Bulharština bg: Bulharština
ko: Korejština ko: Korejština
tr: Turečtina tr: Turečtina
@ -330,9 +347,16 @@ languages:
mk: Makedonština mk: Makedonština
sr: Srbština sr: Srbština
be: Běloruština be: Běloruština
tl: 'Tagalština '
brewing_stand: brewing_stand:
not-working: "&4Nemůžeš používat Slimefun předměty ve varném stojanu!" not-working: "&4Nemůžeš používat Slimefun předměty ve varném stojanu!"
villagers: 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: miner:
no-ores: "&eOmlouvám se, nemohu najít rudy v okolí!" no-ores: "&eOmlouvám se, nemohu najít rudy v okolí!"

View File

@ -136,6 +136,7 @@ messages:
wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das
Level einer anderen Verzauberung vermindert" Level einer anderen Verzauberung vermindert"
caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft" caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft"
wise: "&a&oDein Talisman hat soeben deine Erfahrungspunkte verdoppelt"
soulbound-rune: soulbound-rune:
fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden" fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden"
success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest
@ -319,6 +320,7 @@ android:
own: "&4Du kannst nicht dein eigenes Skript bewerten!" own: "&4Du kannst nicht dein eigenes Skript bewerten!"
already: "&4Du hast dieses Skript bereits bewertet!" already: "&4Du hast dieses Skript bereits bewertet!"
editor: Skripteditor editor: Skripteditor
too-long: "&cDieses Skript ist zu lang, um es zu bearbeiten!"
languages: languages:
default: Server-Standard default: Server-Standard
en: Englisch en: Englisch
@ -340,7 +342,6 @@ languages:
zh-CN: Chinesisch (China) zh-CN: Chinesisch (China)
el: Griechisch el: Griechisch
he: Hebräisch he: Hebräisch
pt: Portugiesisch (Portugal)
pt-BR: Portugiesisch (Brasilien) pt-BR: Portugiesisch (Brasilien)
ar: Arabisch ar: Arabisch
af: Afrikaans af: Afrikaans
@ -353,6 +354,7 @@ languages:
fa: Persisch fa: Persisch
th: Thailändisch th: Thailändisch
ro: Rumänisch ro: Rumänisch
pt: Portugiesisch (Portugal)
bg: Bulgarisch bg: Bulgarisch
ko: Koreanisch ko: Koreanisch
tr: Türkisch tr: Türkisch
@ -371,3 +373,5 @@ cauldron:
no-discoloring: "&4Du kannst Slimefun-Rüstung nicht entfärben" no-discoloring: "&4Du kannst Slimefun-Rüstung nicht entfärben"
miner: miner:
no-ores: "&eIch konnte leider keine Erze in der Nähe finden!" no-ores: "&eIch konnte leider keine Erze in der Nähe finden!"
placeholderapi:
profile-loading: Lade...

View File

@ -32,6 +32,9 @@ commands:
verbose-player: '&4The verbose flag cannot be used by a Player!' verbose-player: '&4The verbose flag cannot be used by a Player!'
unknown-flag: '&4Unknown flag: &c%flag%' unknown-flag: '&4Unknown flag: &c%flag%'
placeholderapi:
profile-loading: 'Loading...'
guide: guide:
locked: 'LOCKED' locked: 'LOCKED'
work-in-progress: 'This feature is not fully finished yet!' work-in-progress: 'This feature is not fully finished yet!'

View File

@ -25,9 +25,9 @@ commands:
not-rechargeable: Este ítem no puede ser cargado! not-rechargeable: Este ítem no puede ser cargado!
timings: timings:
description: Timings para Slimefun y sus addon 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!" verbose-player: "&4La flag verbose no puede ser usada por un jugador!"
unknown-flag: "&4flag desconocida: &c%flag%" unknown-flag: "&4flag desconocida: &c%flag%"
please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!"
guide: guide:
search: search:
message: "&b¿Qué te gustaría buscar?" 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 wizard: "&a&oTu talismán te ha dado un mayor nivel de fortuna, pero pudo disminuír
el nivel de otros encantamientos." el nivel de otros encantamientos."
caveman: "&a&oTu Talismán te ha dado Haste" caveman: "&a&oTu Talismán te ha dado Haste"
wise: "&a&oTu Talismán ha duplicado tu drop de experiencia"
soulbound-rune: soulbound-rune:
fail: "&cSolo puedes ligar un objeto a tu alma." fail: "&cSolo puedes ligar un objeto a tu alma."
success: "&a¡Has ligado este objeto a tu alma exitosamente! No lo perderás al 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-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-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!" 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 bee-suit-slow-fall: "&eTus alas de Abeja te ayudarán a llegar seguro y lento al
piso" piso"
mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%'
machines: machines:
pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca
el objeto en el patrón correcto dentro del dispensador." el objeto en el patrón correcto dentro del dispensador."
@ -314,6 +315,7 @@ android:
own: "&4¡No puedes calificar tu propio script!" own: "&4¡No puedes calificar tu propio script!"
already: "&4¡Ya has calificado este script!" already: "&4¡Ya has calificado este script!"
editor: Editor de Guión editor: Editor de Guión
too-long: "&cEl script es demasiado largo para editar!"
languages: languages:
default: Predeterminado default: Predeterminado
en: Inglés en: Inglés
@ -335,6 +337,7 @@ languages:
zh-CN: Chino (China) zh-CN: Chino (China)
el: Griego el: Griego
he: Hebreo he: Hebreo
pt: Portugués (Portugal)
ar: Árabe ar: Árabe
af: Africano af: Africano
da: Danés da: Danés
@ -346,7 +349,6 @@ languages:
fa: Persa fa: Persa
th: Tailandés th: Tailandés
ro: Rumano ro: Rumano
pt: Portugués (Portugal)
pt-BR: Portugués (Brasil) pt-BR: Portugués (Brasil)
bg: Búlgaro bg: Búlgaro
ko: Coreano ko: Coreano

View File

@ -4,7 +4,6 @@ commands:
cheat: Vous permet de vous donnez des objets cheat: Vous permet de vous donnez des objets
give: Donne à quelqu'un des objets Slimefun give: Donne à quelqu'un des objets Slimefun
guide: Vous donne un guide Slimefun guide: Vous donne un guide Slimefun
timings: Informations sur la latence de votre serveur
teleporter: Affiche les waypoints d'un autre joueur teleporter: Affiche les waypoints d'un autre joueur
versions: Affiche toutes les extensions installées versions: Affiche toutes les extensions installées
search: Recherche dans votre guide le terme donné search: Recherche dans votre guide le terme donné
@ -25,6 +24,11 @@ commands:
description: Charge l'objet que vous avez en main description: Charge l'objet que vous avez en main
charge-success: L'objet a été chargé ! charge-success: L'objet a été chargé !
not-rechargeable: Cet objet ne peut pas être 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: guide:
search: search:
message: "&bQue souhaitez-vous rechercher?" message: "&bQue souhaitez-vous rechercher?"
@ -134,6 +138,7 @@ messages:
wizard: "&a&oVotre talisman vous a donné un meilleur niveau de Fortune mais a wizard: "&a&oVotre talisman vous a donné un meilleur niveau de Fortune mais a
peut-être diminué plusieurs autres enchantements" peut-être diminué plusieurs autres enchantements"
caveman: "&a&oVotre Talisman vous a donné Célérité" caveman: "&a&oVotre Talisman vous a donné Célérité"
wise: "&a&oVotre talisman a doublé votre XP"
soulbound-rune: soulbound-rune:
fail: "&cVous pouvez lier un seul objet à la fois à votre âme" 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 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 invalid-amount: "&4%amount% &cn'est pas un montant valide: il doit être supérieur
à 0!" à 0!"
invalid-research: "&4%research% &cn'est pas une recherche valide!" 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 bee-suit-slow-fall: "&eVos ailes d'abeille vous aideront à revenir au sol lentement
et en toute sécurité" et en toute sécurité"
mode-change: 'Vous avez changé votre &b%device% en mode : &9%mode%'
machines: machines:
pattern-not-found: "&eDésolé, je ne reconnais pas cette recette. Veuillez disposer pattern-not-found: "&eDésolé, je ne reconnais pas cette recette. Veuillez disposer
les objets correctement dans le distributeur." les objets correctement dans le distributeur."

View File

@ -1,11 +1,18 @@
--- ---
commands: commands:
help: הצגת מסך עזרה help: הצגת מסך עזרה
teleporter: ראה נקודות ציון של שחקנים אחרים
search: חפש במדריך את המונח הנתון
cheat: מאפשר לזמן פריטים ברמאות cheat: מאפשר לזמן פריטים ברמאות
give: נותן למישהו פירטי סליים פאן give: נותן למישהו פירטי סליים פאן
guide: תן לעצמך מדריך סליים פאן guide: תן לעצמך מדריך סליים פאן
teleporter: ראה נקודות ציון של שחקנים אחרים
versions: הצגת תוספים מותקנים
search: חפש במדריך את המונח הנתון
open_guide: פתח את המדריך בלי להשתמש בספר
stats: מציג כמה נתונים סטטיסטיים על שחקן
research:
description: 'בטל נעילה /מחקרים עבור שחקן זה '
reset: "&c איפס את הידע של %שחקן% זה"
reset-target: "&cהידע שלך אופס "
backpack: backpack:
description: אחזר עותק של גיבוי קיים description: אחזר עותק של גיבוי קיים
invalid-id: " המספר המזהה חייב להיות מספר לא שלילי!&4" invalid-id: " המספר המזהה חייב להיות מספר לא שלילי!&4"
@ -21,46 +28,15 @@ commands:
please-wait: "&e !אנא המתן שנייה ... התוצאות מגיעות" please-wait: "&e !אנא המתן שנייה ... התוצאות מגיעות"
verbose-player: "&4 האיתות המילולי אינו יכול להיות בשימוש על ידי שחקן!" verbose-player: "&4 האיתות המילולי אינו יכול להיות בשימוש על ידי שחקן!"
unknown-flag: "&4איתות לא ידוע: &c%flag%" unknown-flag: "&4איתות לא ידוע: &c%flag%"
versions: הצגת תוספים מותקנים
open_guide: פתח את המדריך בלי להשתמש בספר
stats: מציג כמה נתונים סטטיסטיים על שחקן
research:
description: 'בטל נעילה /מחקרים עבור שחקן זה '
reset: "&c איפס את הידע של %שחקן% זה"
reset-target: "&cהידע שלך אופס "
guide: guide:
title: search:
main: סליים פאן מדריך message: מה תרצה לחפש?
credits: סליים פאן4 תורמים name: "&7חפש...."
wiki: סליים פאן4 ויקי tooltip: "&b לחץ לחפש פריט"
addons: 'תוספות לסליים פאן ' inventory: "%item% מחפש עבור: "
versions: גרסאות מותקנות cheat:
settings: 'הגדרות & מידע ' no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!"
languages: בחר את השפה המועדפת עליך
bugs: דיווחי שגיאות
source: קוד מקור
back:
guide: חזור למדריך סליים פאן
title: חזור
settings: חזור ללוח ההגדרות
tooltips:
wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי
recipes:
climbing-pick: משטחים שאפשר לטפס עליהם
machine: מתכונים שנעשו במכונה זו
miner: משאבים שתוכלו להשיג אצל כורה זה
generator: סוגי דלק זמינים
gold-pan: משאבים שתוכלו להשיג
open-category: לחץ לפתיחה
versions-notice: אלה חשובים מאוד כשמדווחים על באגים!
work-in-progress: תכונה זו עדיין לא הושלמה במלואה!
languages: languages:
change: לחץ כדי לבחור שפה חדשה
description:
- "&7כעת יש לך אפשרות לשנות"
- "&7השפה שבה סליים פאן"
- "&7יוצג בפניך. פריטים"
- "&7לא ניתן לתרגם לעת עתה."
updated: "&a :השפה שלך הוגדרה בהצלחה ל &b%lang%" updated: "&a :השפה שלך הוגדרה בהצלחה ל &b%lang%"
translations: translations:
name: "&aIs משהו חסר?" name: "&aIs משהו חסר?"
@ -68,13 +44,23 @@ guide:
select: 'לחץ כדי לבחור שפה זאת ' select: 'לחץ כדי לבחור שפה זאת '
select-default: לחץ לבחירת שפת ברירת המחדל select-default: לחץ לבחירת שפת ברירת המחדל
selected-language: 'נבחר כעת:' selected-language: 'נבחר כעת:'
credits: change: לחץ כדי לבחור שפה חדשה
open: לחץ כדי לראות את התורמים שלנו
description: description:
- "&7 סליים פאן הוא פרויקט קוד פתוח " - "&7כעת יש לך אפשרות לשנות"
- "&7ומתוחזק על ידי קהילה גדולה של אנשים." - "&7השפה שבה סליים פאן"
- "&7על &e%contributors% &7אנשים עבדו" - "&7יוצג בפניך. פריטים"
- "&7.סליים פאן לאורך כל השנים האלה " - "&7לא ניתן לתרגם לעת עתה."
title:
main: סליים פאן מדריך
settings: 'הגדרות & מידע '
languages: בחר את השפה המועדפת עליך
credits: סליים פאן4 תורמים
wiki: סליים פאן4 ויקי
addons: 'תוספות לסליים פאן '
bugs: דיווחי שגיאות
source: קוד מקור
versions: גרסאות מותקנות
credits:
commit: להתחייב commit: להתחייב
commits: מתחייב commits: מתחייב
roles: roles:
@ -83,32 +69,60 @@ guide:
resourcepack: "&c אמן חבילת משאבים" resourcepack: "&c אמן חבילת משאבים"
translator: "&9מתרגם" translator: "&9מתרגם"
profile-link: "לחץ כדי לבקר את הפרופיל שלהם \nב -GitHub" profile-link: "לחץ כדי לבקר את הפרופיל שלהם \nב -GitHub"
search: open: לחץ כדי לראות את התורמים שלנו
message: &b מה תרצה לחפש? description:
name: "&7חפש...." - "&7 סליים פאן הוא פרויקט קוד פתוח "
tooltip: "&b לחץ לחפש פריט" - "&7ומתוחזק על ידי קהילה גדולה של אנשים."
inventory: "%item% מחפש עבור: " - "&7על &e%contributors% &7אנשים עבדו"
cheat: - "&7.סליים פאן לאורך כל השנים האלה "
no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!"
pages: pages:
previous: עמוד קודם previous: עמוד קודם
next: עמוד הבא next: עמוד הבא
tooltips:
open-category: לחץ לפתיחה
versions-notice: אלה חשובים מאוד כשמדווחים על באגים!
wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי
recipes:
machine: מתכונים שנעשו במכונה זו
miner: משאבים שתוכלו להשיג אצל כורה זה
generator: סוגי דלק זמינים
gold-pan: משאבים שתוכלו להשיג
climbing-pick: משטחים שאפשר לטפס עליהם
back:
title: חזור
guide: חזור למדריך סליים פאן
settings: חזור ללוח ההגדרות
locked: נעול locked: נעול
locked-category: locked-category:
- כדי לבטל את הנעילה של קטגוריה זו - כדי לבטל את הנעילה של קטגוריה זו
- 'צריך לפתוח את כל הפריטים מה ' - 'צריך לפתוח את כל הפריטים מה '
- הקטגוריות הבאות - הקטגוריות הבאות
work-in-progress: תכונה זו עדיין לא הושלמה במלואה!
messages: messages:
not-researched: "&4אין לך מספיק ידע להבין זאת "
not-enough-xp: "&4אין לך מספיק נקודות ניסיון\nכדי לפתוח את זה " 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: talisman:
angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה"
fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
caveman: "&a&oהקמע שלך נתן לך מהירות"
anvil: "&a&o הקמע שלך הציל את הכלי שלך מלהישבר" anvil: "&a&o הקמע שלך הציל את הכלי שלך מלהישבר"
miner: "&a&o הקמע שלך בכפיל את הפריטים הנופלים" miner: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
hunter: "&a&o הקמע שלך בכפיל את הפריטים הנופלים" hunter: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
lava: "&a&oהקמע שלך הציל אותך מלהישרף למוות" lava: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
water: "&a&oהקמע שלך הציל אותך מלטבוע " water: "&a&oהקמע שלך הציל אותך מלטבוע "
angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה"
fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
magician: "&a%o הקמע שלך העניק לך כישוף נוסף" magician: "&a%o הקמע שלך העניק לך כישוף נוסף"
traveller: "&a&o הקמע שלך נתן לך דחיפת מהירות" traveller: "&a&o הקמע שלך נתן לך דחיפת מהירות"
warrior: "&a&oהקמע שלך שיפר את כוחך לזמן מה" warrior: "&a&oהקמע שלך שיפר את כוחך לזמן מה"
@ -116,54 +130,8 @@ messages:
whirlwind: "&a&o הקמע שלך שיקף את הטיל" whirlwind: "&a&o הקמע שלך שיקף את הטיל"
wizard: "&a&o הקמע שלך העניק לך רמת הון טובה יותר אבל אולי גם הוריד כמה רמות הקסם wizard: "&a&o הקמע שלך העניק לך רמת הון טובה יותר אבל אולי גם הוריד כמה רמות הקסם
אחרות" אחרות"
fortune-cookie: caveman: "&a&oהקמע שלך נתן לך מהירות"
- "&7 עזור לי, אני כלוא במפעל לעוגיות " wise: "&a&oהקמע שלך הכפיל את ירידת נקודות הניסיון שלך"
- "&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%'
soulbound-rune: soulbound-rune:
fail: "&c אתה יכול לקשור פריט אחד בלבד לנשמתך בכל פעם." fail: "&c אתה יכול לקשור פריט אחד בלבד לנשמתך בכל פעם."
success: "&a אתה קושרת פריט זה בהצלחה לנשמתך! אתה תשמור עליו כשתמות." success: "&a אתה קושרת פריט זה בהצלחה לנשמתך! אתה תשמור עליו כשתמות."
@ -182,87 +150,43 @@ messages:
ברזל!" ברזל!"
link-prompt: "&e לחץ כאן:" link-prompt: "&e לחץ כאן:"
diet-cookie: "&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-item: "&4%item% &cאינו פריט בר תוקף!"
invalid-amount: "&4%amount% &cאינו כמות ברת תוקף : המספר חייב להיות גדול מאפס!" invalid-amount: "&4%amount% &cאינו כמות ברת תוקף : המספר חייב להיות גדול מאפס!"
invalid-research: "&4%research% &cאינו מחקר בר תוקף!" invalid-research: "&4%research% &cאינו מחקר בר תוקף!"
anvil: bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה"
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: בלארוסית
machines: 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הפריטים pattern-not-found: "&e סליחה לא יכולתי \n .לזהות את המתכון \nאנא הכנס את \nהפריטים
בדפוס הנכון לתוך המתקן " בדפוס הנכון לתוך המתקן "
unknown-material: "&e סליחה, לא יכולתי לזהות את הפריט במתקן שלי. אנא הכנס משהו שאני unknown-material: "&e סליחה, לא יכולתי לזהות את הפריט במתקן שלי. אנא הכנס משהו שאני
@ -273,7 +197,8 @@ machines:
in-use: "&c המלאי של בלוק זה נפתח כרגע על ידי שחקן אחר." in-use: "&c המלאי של בלוק זה נפתח כרגע על ידי שחקן אחר."
ignition-chamber-no-flint: "&c תא הצתה חסר צור ופלדה." ignition-chamber-no-flint: "&c תא הצתה חסר צור ופלדה."
ANCIENT_ALTAR: ANCIENT_ALTAR:
not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals% /\n8( " not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals%
/\n8( "
unknown-catalyst: "&4 זרז לא ידוע! &c השתמש במתכון הנכון במקום זאת!" unknown-catalyst: "&4 זרז לא ידוע! &c השתמש במתכון הנכון במקום זאת!"
unknown-recipe: "&4 מתכון לא ידוע! &cהשתמש במתכון הנכון במקום!" unknown-recipe: "&4 מתכון לא ידוע! &cהשתמש במתכון הנכון במקום!"
ANCIENT_PEDESTAL: ANCIENT_PEDESTAL:
@ -301,17 +226,50 @@ machines:
time: זמן משוער time: זמן משוער
CARGO_NODES: CARGO_NODES:
must-be-placed: "&4חייב להיות מונח על תיבה או מכונה!" must-be-placed: "&4חייב להיות מונח על תיבה או מכונה!"
brewing_stand: GPS_CONTROL_PANEL:
not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!" title: לוח בקרה - ג'י פי אס
villagers: transmitters: סקירה משדר
no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!" waypoints: סקירת נקודות דרך
cartography_table: INDUSTRIAL_MINER:
not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!" no-fuel: לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל.
cauldron: piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!"
no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן" 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: android:
started: "&7 האנדרואיד שלך ממשיך את תסריט"
stopped: "&7 האנדרואיד שלך \nעצר את התסריט "
scripts: scripts:
too-long: "&c!התסריט ארוך מכדי לערוך"
already-uploaded: "&4 התסריט הזה כבר הועלה." already-uploaded: "&4 התסריט הזה כבר הועלה."
instructions: instructions:
START: "&2 התחל תסריט" START: "&2 התחל תסריט"
@ -350,10 +308,56 @@ android:
own: "&4אתה לא יכול לדרג את התסריט שלך עצמך!" own: "&4אתה לא יכול לדרג את התסריט שלך עצמך!"
already: "&4אתה כבר השארת דירוג לתסריט זה!" already: "&4אתה כבר השארת דירוג לתסריט זה!"
editor: עורך תסריט editor: עורך תסריט
started: "&7 האנדרואיד שלך ממשיך את תסריט" too-long: "&c!התסריט ארוך מכדי לערוך"
stopped: "&7 האנדרואיד שלך \nעצר את התסריט " languages:
backpack: default: שרת ברירת מחדל
already-open: "&cסליחה התרמיל הזה פתוח במקום אחר " en: אנגלית
no-stack: "&cאתה לא יכול לערום תרמילים" de: 'גרמנית '
inventory: fr: צרפתית
no-access: "&4אין לך גישה לבלוק הזה" 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: בטעינה...

View File

@ -134,6 +134,7 @@ messages:
wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb
varázslatot gyengített" varázslatot gyengített"
caveman: "&a&oA talizmánod adott Sietség effektet" caveman: "&a&oA talizmánod adott Sietség effektet"
wise: "&a&oA talizmánod megduplázta a dobott tapasztalat pontokat"
soulbound-rune: soulbound-rune:
fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez." fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez."
success: "&aSikeresen hozzákötötted ezt a tárgyat a lelkedhez! Megmarad, amikor 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!" own: "&4Nem értékelheted a saját szkriptedet!"
already: "&4Ezt a szkriptet már értékelted!" already: "&4Ezt a szkriptet már értékelted!"
editor: Szkript szerkesztő editor: Szkript szerkesztő
too-long: "&cA szkript túl hosszú a szerkesztéshez!"
languages: languages:
default: Szerver-alapértelmezett default: Szerver-alapértelmezett
en: Angol en: Angol

View File

@ -133,6 +133,7 @@ messages:
whirlwind: "&a&oタリスマンが飛び道具から身を護った" whirlwind: "&a&oタリスマンが飛び道具から身を護った"
wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった" wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった"
caveman: "&a&oタリスマンが採掘速度を上昇させた" caveman: "&a&oタリスマンが採掘速度を上昇させた"
wise: "&a&oタリスマンが経験値のドロップを倍にした"
soulbound-rune: soulbound-rune:
fail: "&c一度に複数アイテムとのバインディングはできません" fail: "&c一度に複数アイテムとのバインディングはできません"
success: "&aアイテムとのバインディングが確立したリスポーン時に当該アイテムは手繰り寄せられます" success: "&aアイテムとのバインディングが確立したリスポーン時に当該アイテムは手繰り寄せられます"
@ -319,7 +320,6 @@ languages:
el: ギリシャ語 el: ギリシャ語
he: ヘブライ語 he: ヘブライ語
pt: ポルトガル語(ポルトガル) pt: ポルトガル語(ポルトガル)
pt-BR: ポルトガル語(ブラジル)
ar: アラビア語 ar: アラビア語
af: アフリカーンス語 af: アフリカーンス語
da: デンマーク語 da: デンマーク語
@ -331,6 +331,7 @@ languages:
fa: ペルシア語 fa: ペルシア語
th: タイ語 th: タイ語
ro: ルーマニア語 ro: ルーマニア語
pt-BR: ポルトガル語(ブラジル)
bg: ブルガリア語 bg: ブルガリア語
ko: 韓国語 ko: 韓国語
tr: トルコ語 tr: トルコ語
@ -349,3 +350,5 @@ cauldron:
no-discoloring: "&4Slimefunアイテムの脱色はできません" no-discoloring: "&4Slimefunアイテムの脱色はできません"
miner: miner:
no-ores: "&e周辺には鉱石が見つかりませんでした" no-ores: "&e周辺には鉱石が見つかりませんでした"
placeholderapi:
profile-loading: ロード中…

View File

@ -4,7 +4,6 @@ commands:
cheat: Geeft je toestemming om gratis spullen in het spel te brengen cheat: Geeft je toestemming om gratis spullen in het spel te brengen
give: Geef iemand een aantal Slimefun spullen give: Geef iemand een aantal Slimefun spullen
guide: Geef jezelf een Slimefun Handboek guide: Geef jezelf een Slimefun Handboek
timings: Laat informatie over de server's prestaties zien
teleporter: Bekijk de opgeslagen locaties van andere spelers teleporter: Bekijk de opgeslagen locaties van andere spelers
versions: Laat een lijst met alle geïnstalleerde uitbreidingen zien versions: Laat een lijst met alle geïnstalleerde uitbreidingen zien
search: Doorzoek de Slimefun handleiding voor een bepaald trefwoord search: Doorzoek de Slimefun handleiding voor een bepaald trefwoord
@ -15,6 +14,18 @@ commands:
description: Ontgrendel of herstart Slimefun kennissen van een speler description: Ontgrendel of herstart Slimefun kennissen van een speler
reset: "&cJe hebt %player%'s Slimefun kennis herstart" reset: "&cJe hebt %player%'s Slimefun kennis herstart"
reset-target: "&cJe Slimefun kennis is 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: guide:
search: search:
message: "&bOp welk woord zou je willen zoeken?" message: "&bOp welk woord zou je willen zoeken?"
@ -22,8 +33,8 @@ guide:
tooltip: "&bKlik om naar een item te zoeken" tooltip: "&bKlik om naar een item te zoeken"
inventory: 'Zoeken naar: %item%' inventory: 'Zoeken naar: %item%'
lore: lore:
- "&bOp welk woord zou je willen zoeken?" '1': "&7Type je zoekterm in het gespreksvenster"
- "&7Type je zoekterm in het gespreksvenster" '0': "&bOp welk woord zou je willen zoeken?"
cheat: cheat:
no-multiblocks: "&4Je kan geen Slimefun machines in het spel brengen, je moet no-multiblocks: "&4Je kan geen Slimefun machines in het spel brengen, je moet
ze bouwen zoals aangegeven." ze bouwen zoals aangegeven."
@ -34,7 +45,13 @@ guide:
lore: Klik om een eigen vertaling toe the voegen lore: Klik om een eigen vertaling toe the voegen
select: Klik om deze taal te selecteren select: Klik om deze taal te selecteren
select-default: Klik om de standaard 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: title:
main: Slimefun Handboek main: Slimefun Handboek
settings: Instellingen & Informatie settings: Instellingen & Informatie
@ -44,6 +61,7 @@ guide:
addons: Uitbreidingen voor Slimefun4 addons: Uitbreidingen voor Slimefun4
bugs: Fouten rapporteren bugs: Fouten rapporteren
source: Source Code source: Source Code
versions: Geïnstalleerde versies
credits: credits:
commit: Bijdrage commit: Bijdrage
commits: Bijdragen commits: Bijdragen
@ -53,6 +71,12 @@ guide:
resourcepack: "&cGrafische bundel Ontwikkelaar" resourcepack: "&cGrafische bundel Ontwikkelaar"
translator: "&9Vertaler" translator: "&9Vertaler"
profile-link: Klik om hun profielen op Github te bezoeken 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: pages:
previous: Vorige bladzijde previous: Vorige bladzijde
next: Volgende bladzijde next: Volgende bladzijde
@ -65,15 +89,17 @@ guide:
miner: Grondstoffen die je met deze Miner kunt verkrijgen miner: Grondstoffen die je met deze Miner kunt verkrijgen
generator: Beschikbare soorten brandstof generator: Beschikbare soorten brandstof
gold-pan: Grondstoffen die je kunt verkrijgen gold-pan: Grondstoffen die je kunt verkrijgen
climbing-pick: Oppervlakken die je kunt beklimmen
back: back:
title: Terug title: Terug
guide: Ga terug naar de Slimefun Handleiding guide: Ga terug naar de Slimefun Handleiding
settings: Ga terug naar Instellingen settings: Ga terug naar Instellingen
locked: VERGRENDELD locked: VERGRENDELD
locked-category: locked-category:
- Om deze categorie te ontgrendelen zul je '0': Om deze categorie te ontgrendelen zul je
- alle items moeten ontgrendelen van de '1': alle items moeten ontgrendelen van de
- volgende categorieën '2': volgende categorieën
work-in-progress: Dit is nog niet helemaal klaar!
messages: messages:
not-researched: "&4Je hebt niet genoeg Slimefun kennis om dit te begrijpen" not-researched: "&4Je hebt niet genoeg Slimefun kennis om dit te begrijpen"
not-enough-xp: "&4Je hebt niet genoeg XP om dit te ontgrendelen" 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" no-permission: "&4Je hebt geen toestemming om deze actie uit te voeren"
usage: "&4Gebruik, zoals: &c%usage%" usage: "&4Gebruik, zoals: &c%usage%"
not-online: "&4%player% &cis niet online!" 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' given-item: '&bJe hebt &a%amount% keer &7"%item%&7" ontvangen'
give-item: '&bJe hebt %player% &a%amount% keer &7"%item%&7" gegeven' 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' give-research: '&bJe hebt %player% de kennis over &7"%research%&7" gegeven'
hungry: "&cJe hebt teveel honger om zoiets te doen!" hungry: "&cJe hebt teveel honger om zoiets te doen!"
disabled-in-world: "&4&lDit voorwerp is uitgeschakeld in deze wereld" disabled-in-world: "&4&lDit voorwerp is uitgeschakeld in deze wereld"
@ -110,6 +132,8 @@ messages:
whirlwind: "&a&oJe Talisman heeft het projectiel weerkaatst" whirlwind: "&a&oJe Talisman heeft het projectiel weerkaatst"
wizard: "&a&oJe Talisman heeft je een hoger level van geluk gegeven, maar heeft wizard: "&a&oJe Talisman heeft je een hoger level van geluk gegeven, maar heeft
misschien ook de levels van andere betoveringen verlaagd" 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: soulbound-rune:
fail: "&cJe kan maar één voorwerp met je ziel verbinden op elk moment" 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 success: "&aJe hebt dit voorwerp succesvol met je ziel verbonden! Het blijft bij
@ -129,19 +153,46 @@ messages:
link-prompt: "&eKlik mij:" link-prompt: "&eKlik mij:"
diet-cookie: "&eJe begint je zo ligt als een veertje te voelen..." diet-cookie: "&eJe begint je zo ligt als een veertje te voelen..."
fortune-cookie: fortune-cookie:
- "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!" '0': "&7Hellup mij, ik zit vast in een gelukskoekjes-fabriek!"
- "&7Je overlijdt morgen... door een creeper..." '1': "&7Je overlijdt morgen... door een creeper..."
- "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha" '2': "&7Ooit gaat er iets ergs gebeuren in je leven!!! Muhahaha"
- "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld is, '3': "&7Volgende week zal je eindelijk doorhebben dat dit niet de echte wereld
maar een simulatie" is, maar een simulatie"
- "&7Dit koekje gaat over een paar seconden heerlijk smaken" '4': "&7Dit koekje gaat over een paar seconden heerlijk smaken"
- '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld alleen '5': '&7De laatste woorden die je ooit zal horen zijn "Voor mij is deze wereld
maar vals!"' alleen maar vals!"'
- "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd, '6': "&7What je ook wilt worden, knuffels nooit een creeper... Ik heb het geprobeerd,
maar het is het echt niet waard" maar het is het echt niet waard"
- "&742. Het antwoord op alles is 42" '7': "&742. Het antwoord op alles is 42"
- "&7A Walshy, één dag houdt alle problemen weg" '8': "&7A Walshy, één dag houdt alle problemen weg"
- "&7Graaf nooit recht naar beneden!" '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%" mode-change: "&b%device% mode is veranderd naar: &9%mode%"
machines: machines:
pattern-not-found: "&eSorry, ik heb het recept niet herkend. Plaats astublieft de pattern-not-found: "&eSorry, ik heb het recept niet herkend. Plaats astublieft de
@ -187,8 +238,20 @@ machines:
title: GPS - Configuratiescherm title: GPS - Configuratiescherm
transmitters: Transmitter-overzicht transmitters: Transmitter-overzicht
waypoints: Waypoint-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: anvil:
not-working: "&4Je kan geen Slimefun voorwerpen gebruiken in een aambeeld!" not-working: "&4Je kan geen Slimefun voorwerpen gebruiken in een aambeeld!"
mcmmo-salvaging: "&4Je kunt geen Slimefun items afbreken!"
backpack: backpack:
already-open: "&cSorry, deze rugzak is al ergens anders geopend!" already-open: "&cSorry, deze rugzak is al ergens anders geopend!"
no-stack: "&cJe kan geen rugzakken stapelen" no-stack: "&cJe kan geen rugzakken stapelen"
@ -201,10 +264,11 @@ gps:
&r(Kleurcodes zijn ondersteund)" &r(Kleurcodes zijn ondersteund)"
added: "&aEen nieuw locatiepunt is succesvol toegevoegd" added: "&aEen nieuw locatiepunt is succesvol toegevoegd"
max: "&4Je hebt het maximum aantal locatiepunten bereikt" max: "&4Je hebt het maximum aantal locatiepunten bereikt"
duplicate: "&4Je hebt al een waypoint genaamd: &f%waypoint%"
insufficient-complexity: insufficient-complexity:
- "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%" '0': "&4Er is te weinig GPS netwerk complexiteit: &c%complexity%"
- "&4a) Je hebt nog geen GPS netwerk opgezet" '1': "&4a) Je hebt nog geen GPS netwerk opgezet"
- "&4b) Je GPS netwerk is niet complex genoeg" '2': "&4b) Je GPS netwerk is niet complex genoeg"
geo: geo:
scan-required: "&4Een GEO-Scan is nodig! &cScan deze chunk eerst met behulp van scan-required: "&4Een GEO-Scan is nodig! &cScan deze chunk eerst met behulp van
een GEO-Scanner!" een GEO-Scanner!"
@ -243,15 +307,15 @@ android:
INTERFACE_ITEMS: "&9Geef inventaris aan de geconfronteerde interface" INTERFACE_ITEMS: "&9Geef inventaris aan de geconfronteerde interface"
INTERFACE_FUEL: "&cOntvang brandstof van de geconfronteerde interface" INTERFACE_FUEL: "&cOntvang brandstof van de geconfronteerde interface"
enter-name: enter-name:
- '1': "&eType astublieft de gewenste naam in voor het script"
- "&eType astublieft de gewenste naam in voor het script"
uploaded: uploaded:
- "&bBezig met uploaden..." '0': "&bBezig met uploaden..."
- "&aHet script is succesvol geupload!" '1': "&aHet script is succesvol geupload!"
rating: rating:
own: "&4Je kan je eigen script geen waardering geven!" own: "&4Je kan je eigen script geen waardering geven!"
already: "&4Je hebt aan een waardering achtergelaten voor dit script!" already: "&4Je hebt aan een waardering achtergelaten voor dit script!"
editor: Scripteditor editor: Scripteditor
too-long: "&cDe code is te lang om te kunnen editen!"
languages: languages:
default: Server-Standaard default: Server-Standaard
en: Engels en: Engels
@ -289,5 +353,20 @@ languages:
bg: Bulgaars bg: Bulgaars
ko: Koreaans ko: Koreaans
tr: Turks 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: miner:
no-ores: "&eSorry, ik kon geen ertsen vinden dichtbij!" no-ores: "&eSorry, ik kon geen ertsen vinden dichtbij!"

View File

@ -26,8 +26,8 @@ commands:
not-rechargeable: Vật phẩm này không thể sạc được! not-rechargeable: Vật phẩm này không thể sạc được!
timings: timings:
description: Độ trễ của slimefun và addon của nó 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!" 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%" unknown-flag: "&4Không rõ cờ: &c%flag%"
guide: guide:
search: 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 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" 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" 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: 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 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." 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" no-discoloring: "&4Bạn không thể đổi màu giáp của Slimefun"
miner: miner:
no-ores: "&eXin lỗi, tôi không thể tìm bất kì Khoáng sản nào xung quanh!" 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...

View File

@ -133,6 +133,7 @@ messages:
whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物" whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物"
wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降" wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降"
caveman: "&a&o你的护身符给予了你急迫效果" caveman: "&a&o你的护身符给予了你急迫效果"
wise: "&a&o你的护身符让掉落的经验翻倍了"
soulbound-rune: soulbound-rune:
fail: "&c灵魂一次只能绑定一个物品." fail: "&c灵魂一次只能绑定一个物品."
success: "&a物品绑定成功! 在你死亡后此物品将不会掉落." success: "&a物品绑定成功! 在你死亡后此物品将不会掉落."
@ -319,7 +320,6 @@ languages:
el: 希腊语 el: 希腊语
he: 希伯来语 he: 希伯来语
pt: 葡萄牙语 (葡萄牙) pt: 葡萄牙语 (葡萄牙)
pt-BR: 葡萄牙语 (巴西)
ar: 阿拉伯语 ar: 阿拉伯语
af: 南非语 af: 南非语
da: 丹麦语 da: 丹麦语
@ -331,6 +331,7 @@ languages:
fa: 波斯语 fa: 波斯语
th: 泰语 th: 泰语
ro: 罗马尼亚语 ro: 罗马尼亚语
pt-BR: 葡萄牙语 (巴西)
bg: 保加利亚语 bg: 保加利亚语
ko: 韩语 ko: 韩语
tr: 土耳其语 tr: 土耳其语
@ -349,3 +350,5 @@ cauldron:
no-discoloring: "&4你不能用炼药锅洗去 Slimefun 物品的颜色" no-discoloring: "&4你不能用炼药锅洗去 Slimefun 物品的颜色"
miner: miner:
no-ores: "&e抱歉, 周围找不到矿石了!" no-ores: "&e抱歉, 周围找不到矿石了!"
placeholderapi:
profile-loading: 加载中...

View File

@ -133,6 +133,7 @@ messages:
whirlwind: "&a&o你的護符反射了投射物" whirlwind: "&a&o你的護符反射了投射物"
wizard: "&a&o你的護符為你升高了幸運等級但也降低了其他附魔等級" wizard: "&a&o你的護符為你升高了幸運等級但也降低了其他附魔等級"
caveman: "&a&o你的護符給了你挖掘加速效果" caveman: "&a&o你的護符給了你挖掘加速效果"
wise: "&a&o你的護身符加倍了你得到的經驗值"
soulbound-rune: soulbound-rune:
fail: "&c你一次只能靈魂綁定一個物品。" fail: "&c你一次只能靈魂綁定一個物品。"
success: "&a您已成功將此物品綁定靈魂死後不會掉落。" success: "&a您已成功將此物品綁定靈魂死後不會掉落。"
@ -318,7 +319,6 @@ languages:
zh-CN: 中文(簡體) zh-CN: 中文(簡體)
el: 希臘語 el: 希臘語
he: 希伯來語 he: 希伯來語
pt: 葡萄牙文(葡萄牙)
pt-BR: 葡萄牙文(巴西) pt-BR: 葡萄牙文(巴西)
ar: 阿拉伯文 ar: 阿拉伯文
af: 南非語 af: 南非語
@ -331,6 +331,7 @@ languages:
fa: 波斯語 fa: 波斯語
th: 泰語 th: 泰語
ro: 羅馬尼亞語 ro: 羅馬尼亞語
pt: 葡萄牙文(葡萄牙)
bg: 保加利亞語 bg: 保加利亞語
ko: 韓語 ko: 韓語
tr: 土耳其 tr: 土耳其
@ -349,3 +350,5 @@ cauldron:
no-discoloring: "&4你不能把 Slimefun 裝備的顏色消除!" no-discoloring: "&4你不能把 Slimefun 裝備的顏色消除!"
miner: miner:
no-ores: "&e附近沒礦了!" no-ores: "&e附近沒礦了!"
placeholderapi:
profile-loading: 載入中……

View File

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

View File

@ -1,232 +1,252 @@
--- ---
slimefun: slimefun:
walking_sticks: Vycházkové hole 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 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 monster_jerky: Sušené maso z monstra
steel: Ocelová doba slime_armor: Brnění ze slizu
jetpacks: Jetpacks sword_of_beheading: Meč na sekání hlav
multitools: Víceúčelové nástroje basic_circuit_board: Základní deska
synthetic_sapphire: Syntetické Safíry advanced_circuit_board: Pokročilá deska s obvody
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
smeltery: Tavírna 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 battery: Tvoje první baterie
steel_plate: Ocelové Plátování steel_plate: Ocelový plát
steel_thruster: Ocelová Tryska steel_thruster: Ocelová tryska
parachute: Padák parachute: Padák
grappling_hook: Záchytný Hák grappling_hook: Vystřelující hák
solar_panel_and_helmet: Solární Energie jetpacks: Raketový batoh
elemental_staff: Hůlky Elementů multitools: Víceúčelové nástroje
grind_stone: Kámen na Broušení solar_panel_and_helmet: Solární energie
cactus_armor: Kaktusový Oblek elemental_staff: Elementární hůlky
gold_pan: Zlatá Pánev grind_stone: Brusný kámen
magical_book_cover: Magická Knižní Vazba cactus_armor: Oblek z kaktusu
slimefun_metals: Nové Kovy gold_pan: Rýžovací miska
ore_crusher: Dvojnásobení Rud magical_book_cover: Magické vázání knihy
bronze: Vytvoření Bronzu slimefun_metals: Nové kovy
alloys: Pokročíle Slitiny ore_crusher: Zdvojování rud
compressor_and_carbon: Vytvoření Karbonu bronze: Výroby bronzu
gilded_iron_armor: Pozlacené Železné Brnění alloys: Pokročilé slitiny
synthetic_diamond: Syntetické Diamanty compressor_and_carbon: Výroby karbonu
pressure_chamber: Tlaková Komora gilded_iron_armor: Pozlacené železné brnění
damascus_steel: Damašská Ocel synthetic_diamond: Syntetické diamanty
reinforced_alloy: Zesílená Slitina pressure_chamber: Tlaková komora
carbonado: Černé Diamanty synthetic_sapphire: Syntetické safíry
magic_workbench: Magický Pracovní Stůl damascus_steel: Damašková ocel
wind_staff: Větrná Hůl damascus_steel_armor: Brnění z damaškové ocely
reinforced_armor: Zesílené Brnění reinforced_alloy: Zpevněná slitina
ore_washer: Čištič Rud carbonado: Černé diamanty
gold_carats: Čisté Zlato magic_workbench: Magický pracovní stůl
silicon: Silicon Valley wind_staff: Větrná hůl
fire_staff: Ohnivá Hůl reinforced_armor: Zpěvněné brnění
smelters_pickaxe: Hutní Krumpáč ore_washer: Čištič rud
common_talisman: Běžný Talisman gold_carats: Čisté zlato
anvil_talisman: Talisman Kovadliny silicon: Křemíkové údolí
miner_talisman: Talisman Horníka fire_staff: Ohnivá hůl
hunter_talisman: Talisman Lovce smelters_pickaxe: Hutní krumpáč
lava_talisman: Talisman Chodce po Lávě common_talisman: Běžný talisman
water_talisman: Talisman Dýchače Vody anvil_talisman: Talisman kovadliny
angel_talisman: Talisman Anděla miner_talisman: Talisman horníka
fire_talisman: Talisman Požárníka hunter_talisman: Talisman lovce
lava_crystal: Ohnivá Situace lava_talisman: Talisman chodce po lávě
magician_talisman: Talisman Kouzelníka water_talisman: Talisman dýchání pod vodou
traveller_talisman: Talisman Cestovatele angel_talisman: Talisman anděla
warrior_talisman: Talisman Bojovníka fire_talisman: Talisman hasiče
knight_talisman: Talisman Rytíře lava_crystal: Ohnivá situace
gilded_iron: Lesklé Železo magician_talisman: Talisman kouzelníka
synthetic_emerald: Falešný Drahokam traveller_talisman: Talisman cestovatele
chainmail_armor: Řetězová Zbroj warrior_talisman: Talisman bojovníka
whirlwind_talisman: Talisman Vichřice knight_talisman: Talisman rytíře
wizard_talisman: Talisman Čaroděje gilded_iron: Lesklé železo
lumber_axe: Dřevorubecká Sekera synthetic_emerald: Falešný drahokam
hazmat_suit: Hazmat Oblek 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í uranium: Radioaktivní
crushed_ore: Čištění rud crushed_ore: Očišťování rud
redstone_alloy: Ruditové Slitiny redstone_alloy: Ruditové slitiny
carbonado_tools: Nejlepší Stroje carbonado_tools: Nejlepší stroje
first_aid: První Pomoc first_aid: První pomoc
gold_armor: Lesklé Brnění gold_armor: Lesklé brnění
night_vision_googles: Brýle Nočního Vidění night_vision_googles: Brýle pro noční vidění
pickaxe_of_containment: Krumpáč Zadržení pickaxe_of_containment: Krumpáč zadržení
hercules_pickaxe: Herkulesův Krumpáč hercules_pickaxe: Herkulesův krumpáč
table_saw: Stolní Pila table_saw: Stolní pila
slime_steel_armor: Slizově-Ocelové Brnění slime_steel_armor: Brnění ze slizu a oceli
blade_of_vampires: Čepel Vampírů blade_of_vampires: Čepel vampírů
water_staff: Vodní Hůl water_staff: Vodní hůl
24k_gold_block: Zlaté Město 24k_gold_block: Zlaté město
composter: Kompostování Hlíny composter: Kompostování hlíny
farmer_shoes: Boty Farmáře farmer_shoes: Boty farmáře
explosive_tools: Výbušné Nastroje explosive_tools: Výbušné stroje
automated_panning_machine: Automatická Zlatá Pánev automated_panning_machine: Automatická rýžovací miska
boots_of_the_stomper: Boty Dupače boots_of_the_stomper: Boty dupače
pickaxe_of_the_seeker: Krumpáč Hledače pickaxe_of_the_seeker: Krumpáč hledače
backpacks: Batohy backpacks: Batohy
woven_backpack: Tkaný Batoh woven_backpack: Tkaný batoh
crucible: Kotel crucible: Kotel
gilded_backpack: Vázaný Batoh gilded_backpack: Vázaný batoh
armored_jetpack: Trysky s Brněním armored_jetpack: Obrněný raketový batoh
ender_talismans: Ender Talismany ender_talismans: Enderitové talismany
nickel_and_cobalt: Ještě více rud nickel_and_cobalt: Ještě více rud
magnet: Magnetické kovy magnet: Magnetické kovy
infused_magnet: Infuzovaný Magnet infused_magnet: Naplněný magnet
cobalt_pickaxe: Urychlený Krumpáč cobalt_pickaxe: Zrychlený krumpáč
essence_of_afterlife: Necromancie essence_of_afterlife: Černá magie
bound_backpack: Duší-vázané Ůložistě bound_backpack: Uložiště spoutané duší
jetboots: Tryskové Boty jetboots: Raketové boty
armored_jetboots: Obrněné Tryskové Boty armored_jetboots: Obrněné raketové boty
seismic_axe: Seizmická Sekera seismic_axe: Seizmická sekera
pickaxe_of_vein_mining: Krumpáč Těžení Nalezišť pickaxe_of_vein_mining: Krumpáč těžby rud
bound_weapons: Duší-vázané Zbraně bound_weapons: Zbraně spoutané duší
bound_tools: Duší-vázané Nástroje bound_tools: Nástroje spoutané duší
bound_armor: Duší-vázané Brnění bound_armor: Brnění spoutané duší
juicer: Výborné Pití juicer: Výborné pití
repaired_spawner: Opravování Spawnerů repaired_spawner: Opravování líhní
enhanced_furnace: Vylepšená Pec enhanced_furnace: Vylepšená pec
more_enhanced_furnaces: Lepší Pece more_enhanced_furnaces: Lepší pece
high_tier_enhanced_furnaces: Nejlepší Pece high_tier_enhanced_furnaces: Nejlepší pece
reinforced_furnace: Vyztužená Pec reinforced_furnace: Zesílená pec
carbonado_furnace: Carbonado Lemováná Pec carbonado_furnace: Pec lemovaná černými diamanty
electric_motor: Zahřívání electric_motor: Zahřívání
block_placer: Pokládač Bloků block_placer: Pokládač bloků
scroll_of_dimensional_teleposition: Otáčení věcí kolem scroll_of_dimensional_teleposition: Otáčí věcí kolem
special_bows: Robin Hood special_bows: Robin Hood
tome_of_knowledge_sharing: Dělení z přátely tome_of_knowledge_sharing: Dělení s přáteli
flask_of_knowledge: XP Úložistě flask_of_knowledge: XP uložistě
hardened_glass: Odoláválí Výbuchům hardened_glass: Odolávání výbuchům
golden_apple_juice: Zlatý Lektrvar golden_apple_juice: Zlatý lektvar
cooler: Přenášení Nápojů cooler: Přenašeč nápojů
ancient_altar: Starověký Oltář ancient_altar: Starověký oltář
wither_proof_obsidian: Obsidian co vydrží Withera wither_proof_obsidian: Pevný obsidián proti witherovi
ancient_runes: Elementální Rudy ancient_runes: Elementální rudy
special_runes: Purple Rudy special_runes: Fialové rudy
infernal_bonemeal: Pekelný Bonemeal infernal_bonemeal: Pekelná kostní moučka
rainbow_blocks: duhové Bloky rainbow_blocks: Duhové bloky
infused_hopper: Vylepšený Hopper infused_hopper: Vylepšená násypka
wither_proof_glass: Sklo co vydrží Withera wither_proof_glass: Pevné sklo proti witherovi
duct_tape: Lepící Páska duct_tape: Lepící páska
plastic_sheet: Plast plastic_sheet: Plast
android_memory_core: Memory Core android_memory_core: Paměťové jádro
oil: Olej oil: Olej
fuel: Palivo fuel: Palivo
hologram_projector: Hologramy hologram_projector: Hologramy
capacitors: Tier 1 Kondenzátory capacitors: Kondenzátory 1. stupně
high_tier_capacitors: Tier 2 Kondenzátory high_tier_capacitors: Kondenzátory 2. stupně
solar_generators: Solární Elektrárna solar_generators: Solární elektrárna
electric_furnaces: Elektrická Pec electric_furnaces: Elektrická pec
electric_ore_grinding: Drcení a Broušení electric_ore_grinding: Drcení a broušení
heated_pressure_chamber: Vyhřívaná Tlaková Komora heated_pressure_chamber: Vytápěná tlaková komora
coal_generator: Uhelná Elektrárna coal_generator: Uhelná elektrárna
bio_reactor: Bio-Reactor bio_reactor: Bio reaktor
auto_enchanting: Automatická Enchantování and Oddělávání Enchantů auto_enchanting: Automatické očarovávání a odčarovávání
auto_anvil: Automatická Kovadlina auto_anvil: Automatická kovadlina
multimeter: Měření Energie multimeter: Měření energie
gps_setup: Základní GPS Nastavení gps_setup: Základní GPS nastavení
gps_emergency_transmitter: GPS Nouzový Cestovní Bod gps_emergency_transmitter: GPS nouzový záchytný bod
programmable_androids: Programovatelní Androidi programmable_androids: Programovatelné androidy
android_interfaces: Androidové Rozhraní android_interfaces: Rozhraní androidu
geo_scanner: GEO-Skeny geo_scanner: GEO snímače
combustion_reactor: Spalovací Reactor combustion_reactor: Spalovací reaktor
teleporter: Teleportovač - Základní Komponenty teleporter: Základní komponenty pro teleportér
teleporter_activation_plates: Teleportovač - Aktivace teleporter_activation_plates: Aktivace teleportéru
better_solar_generators: Vylepšené Solární Panely better_solar_generators: Vylepšené solární panely
better_gps_transmitters: Vylepšené Vysílače better_gps_transmitters: Vylepšené vysílače
elevator: Výtahy elevator: Výtahy
energized_solar_generator: 24/7 Solární Energie energized_solar_generator: Nezastavitelná solární energie
energized_gps_transmitter: Nejlepší Trasmitter energized_gps_transmitter: Nejlepší vysílač
energy_regulator: Energické Sítě 101 energy_regulator: Energické sítě 101
butcher_androids: Android - Řezník butcher_androids: Řeznické androidy
organic_food: Organické Jídlo organic_food: Organické jídlo
auto_breeder: Automatické Krmení auto_breeder: Automatické krmení
advanced_android: Pokročilý Androidi advanced_android: Pokročilé androidy
advanced_butcher_android: Pokročílý Androidi - Řezníci advanced_butcher_android: Pokročilé řeznické androidy
advanced_fisherman_android: Pokročílý Androidi - Rybář advanced_fisherman_android: Pokročilé rybářské androidy
animal_growth_accelerator: Manipulase Růstu Zvýřat animal_growth_accelerator: Manipulace s růstem zvířat
xp_collector: Zběrač XP xp_collector: Sběrač XP
organic_fertilizer: Organické Hnojivo organic_fertilizer: Organické hnojivo
crop_growth_accelerator: Zrychelní Růstu Plodin crop_growth_accelerator: Urychlovač růstu plodin
better_crop_growth_accelerator: Vylepšené Zrychelní Růstu Plodin better_crop_growth_accelerator: Vylepšený urychlovač růstu plodin
reactor_essentials: Důležité Části Reaktoru reactor_essentials: Důležité části reaktoru
nuclear_reactor: Nuclearní Elektrárna nuclear_reactor: Jaderná elektrárna
freezer: Pan Mražák freezer: Mrazák
cargo_basics: Základy Carga cargo_basics: Základy nákladu
cargo_nodes: Nastavení Carga cargo_nodes: Nastavení nákladu
electric_ingot_machines: Electrické Vyrábění Ingotů electric_ingot_machines: Elektrická výroba ingotů
high_tier_electric_ingot_machines: Super Rychlá Vyrábění Ingotů high_tier_electric_ingot_machines: Super rychlá výroba ingotů
automated_crafting_chamber: Automatické Crafťění automated_crafting_chamber: Automatická výroba
better_food_fabricator: Vylepšené Vyrábění Jídla better_food_fabricator: Vylepšená výroba jídla
reactor_access_port: Interakce s Reactorem reactor_access_port: Interakce s reaktorem
fluid_pump: Pumpa fluid_pump: Pumpa tekutin
better_freezer: Vylepšený Mrazák better_freezer: Vylepšený mrazák
boosted_uranium: Nikdy Nekončící Kruh boosted_uranium: Nekonečný kruh
trash_can: Odpatky trash_can: Koš
advanced_output_node: Vylepšený Výstupní Uzel advanced_output_node: Vylepšený výstupní uzel
carbon_press: Uhlíkový Lis carbon_press: Uhlíkový lis
electric_smeltery: Elektrická H electric_smeltery: Elektrická h
better_electric_furnace: Vylepšená Elektrická Pec better_electric_furnace: Vylepšená elektrická pec
better_carbon_press: Vylepšený Uhlíkový Lis better_carbon_press: Vylepšený uhlíkový lis
empowered_android: Super-nabití Androidi empowered_android: Super nabité androidy
empowered_butcher_android: Super-nabití Androidi - Řezník empowered_butcher_android: Super nabité řeznické androidy
empowered_fisherman_android: Super-nabití Androidi - Rybář empowered_fisherman_android: Super nabité rybářské androidy
high_tier_carbon_press: Ultimátní Uhlíkový Lis high_tier_carbon_press: Ultimátní uhlíkový lis
wither_assembler: Automatický Zabíječ Wihera wither_assembler: Automatický zabiják withera
better_heated_pressure_chamber: Vylepšená Vyhřívaná Tlaková Komora better_heated_pressure_chamber: Vylepšená vytápěná tlaková komora
elytra: Elytry elytra: Krovky
special_elytras: Speciální Elytry special_elytras: Speciální krovky
electric_crucible: Elekryzovaný Kotel electric_crucible: Elektrický kotel
better_electric_crucibles: Horké Kotly better_electric_crucibles: Horké kotle
advanced_electric_smeltery: Vylepšená Elekrická Huť advanced_electric_smeltery: Vylepšená elektrická tavírna
advanced_farmer_android: Vylepšení Androidi - Farmář advanced_farmer_android: Vylepšené farmářské androidy
lava_generator: Generátor Energie z Lávy lava_generator: Generátor energie z lávy
nether_ice: Pekelná-Levodá Chladící Kapalina nether_ice: Netherová chladící kapalina
nether_star_reactor: Nether Star Reactor nether_star_reactor: Netherový hvězdný reaktor
blistering_ingots: Žíravá Radioactivita blistering_ingots: Sžíravá radioaktivita
automatic_ignition_chamber: Automatická Zápalná Komora automatic_ignition_chamber: Automatická zápalná komora
output_chest: Základní výstup do truhly output_chest: Výstupní truhla základního zařízení
copper_wire: Snížená Vodivost copper_wire: Snížená vodivost
radiant_backpack: Zářivý Batoh radiant_backpack: Zářivý batoh
auto_drier: Suchý Den auto_drier: Suchý den
diet_cookie: Dientní Sušenka diet_cookie: Dientní sušenka
storm_staff: Bouřková Hole storm_staff: Bouřková hole
soulbound_rune: Duševně-vázaná Runa soulbound_rune: Runa spoutaná duší
geo_miner: GEO-Ťežič geo_miner: GEO horník
lightning_rune: Runa Blesku lightning_rune: Runa blesku
totem_of_undying: Totem Nesmrtelnosti totem_of_undying: Totem nesmrtelnosti
charging_bench: Nabíječka charging_bench: Nabíječka
nether_gold_pan: Pekelná Zlatá Pánev nether_gold_pan: Netherová rýžovací miska
electric_press: Electrický Lis electric_press: Elektrický lis
magnesium_generator: Energie z Magnézia magnesium_generator: Energie z magnézia
kelp_cookie: Chutná Řasa 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

View File

@ -248,3 +248,5 @@ slimefun:
elytra_cap: Harter Aufprall elytra_cap: Harter Aufprall
energy_connectors: Kupferkabel energy_connectors: Kupferkabel
bee_armor: Bienen-Rüstung bee_armor: Bienen-Rüstung
wise_talisman: Stein der Weisen
book_binder: Verzaubertes Bücherbinden

View File

@ -248,3 +248,4 @@ slimefun:
elytra_cap: Equipo de choque elytra_cap: Equipo de choque
energy_connectors: Conexiones Instaladas energy_connectors: Conexiones Instaladas
bee_armor: Armadura de Abeja bee_armor: Armadura de Abeja
wise_talisman: Talismán del Sabio

View File

@ -3,29 +3,18 @@ slimefun:
walking_sticks: מקלות הליכה walking_sticks: מקלות הליכה
portable_crafter: שולחן מלאכה נייד portable_crafter: שולחן מלאכה נייד
fortune_cookie: עוגיית מזל 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: פח אשפה נייד portable_dustbin: פח אשפה נייד
meat_jerky: בשר מלוח meat_jerky: בשר מלוח
armor_forge: יצירת שריון armor_forge: יצירת שריון
glowstone_armor: שריון גלוסטון glowstone_armor: שריון גלוסטון
lumps: גושים וקסמים lumps: גושים וקסמים
ender_backpack: תיק גב אנדר ender_backpack: תיק גב אנדר
ender_armor: שריון אנדר
magic_eye_of_ender: עין אנדר קסומה
magic_sugar: סוכר קסום
monster_jerky: בשר מפלצת מלוח monster_jerky: בשר מפלצת מלוח
slime_armor: שריון רפש
sword_of_beheading: חרב העריפות
basic_circuit_board: לוח מגעים בסיסי basic_circuit_board: לוח מגעים בסיסי
advanced_circuit_board: לוח מגעים מתקדם advanced_circuit_board: לוח מגעים מתקדם
smeltery: תנור התכה smeltery: תנור התכה
@ -34,6 +23,7 @@ slimefun:
battery: הסוללה הראשונה שלך battery: הסוללה הראשונה שלך
steel_plate: ציפוי פלדה steel_plate: ציפוי פלדה
steel_thruster: דוחף פלדה steel_thruster: דוחף פלדה
parachute: מצנח
grappling_hook: וו אחיזה grappling_hook: וו אחיזה
jetpacks: תרמיל רחיפה jetpacks: תרמיל רחיפה
multitools: רב כלים multitools: רב כלים
@ -45,6 +35,7 @@ slimefun:
magical_book_cover: כריכת ספרים קסומה magical_book_cover: כריכת ספרים קסומה
slimefun_metals: מתכות חדשות slimefun_metals: מתכות חדשות
ore_crusher: הכפלת עפרת ore_crusher: הכפלת עפרת
bronze: יצירת ברונזה
alloys: סגסוגות מתקדמות alloys: סגסוגות מתקדמות
compressor_and_carbon: יצירת פחמן compressor_and_carbon: יצירת פחמן
gilded_iron_armor: שריון ברזל מוזהב gilded_iron_armor: שריון ברזל מוזהב
@ -53,10 +44,15 @@ slimefun:
synthetic_sapphire: ספיר סינטטי synthetic_sapphire: ספיר סינטטי
damascus_steel: פלדת דמשק damascus_steel: פלדת דמשק
damascus_steel_armor: שריון פלדת דמשק damascus_steel_armor: שריון פלדת דמשק
reinforced_alloy: סגסוגת מחוזקת
carbonado: יהלומים שחורים carbonado: יהלומים שחורים
magic_workbench: שולחן מלאכה קסום
wind_staff: מטה רוח
reinforced_armor: שריון מחוזק reinforced_armor: שריון מחוזק
ore_washer: שוטף עופרת ore_washer: שוטף עופרת
gold_carats: זהב טהור
silicon: עמק הסיליקון silicon: עמק הסיליקון
fire_staff: מטה אש
smelters_pickaxe: מכוש התכה smelters_pickaxe: מכוש התכה
common_talisman: קמע נפוץ common_talisman: קמע נפוץ
anvil_talisman: קמע הסדן anvil_talisman: קמע הסדן
@ -82,6 +78,7 @@ slimefun:
crushed_ore: טיהור עפרת crushed_ore: טיהור עפרת
redstone_alloy: סגסוגת רדסטון redstone_alloy: סגסוגת רדסטון
carbonado_tools: מכונות ברמה עליונה carbonado_tools: מכונות ברמה עליונה
first_aid: עזרה ראשונה
gold_armor: שריון מבריק gold_armor: שריון מבריק
night_vision_googles: משקפי ראיית לילה night_vision_googles: משקפי ראיית לילה
pickaxe_of_containment: מקוש הכלה pickaxe_of_containment: מקוש הכלה
@ -89,12 +86,15 @@ slimefun:
table_saw: מסור שולחני table_saw: מסור שולחני
slime_steel_armor: שריון פלדה רזה slime_steel_armor: שריון פלדה רזה
blade_of_vampires: להב הערפדים blade_of_vampires: להב הערפדים
water_staff: מטה מים
24k_gold_block: עיר מוזהבת 24k_gold_block: עיר מוזהבת
composter: עפר קומפוסטציה composter: עפר קומפוסטציה
farmer_shoes: נעלי איכר
explosive_tools: כלי נפץ explosive_tools: כלי נפץ
automated_panning_machine: מסננת אוטומטית automated_panning_machine: מסננת אוטומטית
boots_of_the_stomper: מגפי הרוקע boots_of_the_stomper: מגפי הרוקע
pickaxe_of_the_seeker: מכוש המחפש pickaxe_of_the_seeker: מכוש המחפש
backpacks: תיקי גב
woven_backpack: תיק גב ארוג woven_backpack: תיק גב ארוג
crucible: כור היתוך crucible: כור היתוך
gilded_backpack: תיק גב מוזהב gilded_backpack: תיק גב מוזהב
@ -133,6 +133,7 @@ slimefun:
wither_proof_obsidian: בזלת עמידה לוויד'ר wither_proof_obsidian: בזלת עמידה לוויד'ר
ancient_runes: רונות אלמנטריות ancient_runes: רונות אלמנטריות
special_runes: רונות סגולות special_runes: רונות סגולות
infernal_bonemeal: אינפרנל בואונמיל
rainbow_blocks: בלוקים צבעוניים rainbow_blocks: בלוקים צבעוניים
infused_hopper: משפך חדור infused_hopper: משפך חדור
wither_proof_glass: זכוכית עמידה לוויד'ר wither_proof_glass: זכוכית עמידה לוויד'ר
@ -247,4 +248,5 @@ slimefun:
elytra_cap: גלגל שיניים מרסק elytra_cap: גלגל שיניים מרסק
energy_connectors: חיבור קווי energy_connectors: חיבור קווי
bee_armor: שריון דבורים bee_armor: שריון דבורים
infernal_bonemeal: אינפרנל בואונמיל wise_talisman: קמע של החכמה
book_binder: כריכת ספר קסום

View File

@ -248,3 +248,4 @@ slimefun:
elytra_cap: Ütközésvédelem elytra_cap: Ütközésvédelem
energy_connectors: Vezetékes csatlakozás energy_connectors: Vezetékes csatlakozás
bee_armor: Méhpáncél bee_armor: Méhpáncél
wise_talisman: A Bölcs talizmánja

View File

@ -248,3 +248,5 @@ slimefun:
elytra_cap: 衝撃緩和装備 elytra_cap: 衝撃緩和装備
energy_connectors: 有線接続 energy_connectors: 有線接続
bee_armor: 蜂アーマー bee_armor: 蜂アーマー
wise_talisman: 知恵のタリスマン
book_binder: エンチャントの本の製本

View File

@ -248,3 +248,5 @@ slimefun:
elytra_cap: Mũ lượn elytra_cap: Mũ lượn
energy_connectors: Đầu nối energy_connectors: Đầu nối
bee_armor: Giáp ong 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

View File

@ -248,3 +248,5 @@ slimefun:
elytra_cap: 无伤落地 elytra_cap: 无伤落地
energy_connectors: 有线连接 energy_connectors: 有线连接
bee_armor: 蜜蜂服 bee_armor: 蜜蜂服
wise_talisman: 智者的护身符
book_binder: 附魔融合

View File

@ -248,3 +248,5 @@ slimefun:
elytra_cap: 體驗動能 elytra_cap: 體驗動能
energy_connectors: 電線 energy_connectors: 電線
bee_armor: 蜂裝 bee_armor: 蜂裝
wise_talisman: 智者護身符
book_binder: 附魔書裝訂

View File

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

View File

@ -0,0 +1,9 @@
{
"values" : [
"#slimefun:fortune_compatible_ores",
{
"id" : "minecraft:gilded_blackstone",
"required" : false
}
]
}

View File

@ -10,7 +10,6 @@ import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
@ -54,7 +53,6 @@ class TestResearchUnlocking {
@ParameterizedTest @ParameterizedTest
@DisplayName("Test Unlocking Researches") @DisplayName("Test Unlocking Researches")
@Disabled(value = "Blocked by a concurrency issue in MockBukkit")
@ValueSource(booleans = { true, false }) @ValueSource(booleans = { true, false })
void testUnlock(boolean instant) throws InterruptedException { void testUnlock(boolean instant) throws InterruptedException {
SlimefunPlugin.getRegistry().setResearchingEnabled(true); SlimefunPlugin.getRegistry().setResearchingEnabled(true);

View File

@ -1,12 +1,7 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.utils; package io.github.thebusybiscuit.slimefun4.testing.tests.utils;
import java.util.Arrays;
import java.util.Collections; 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.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; 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.DisplayName;
import org.junit.jupiter.api.Test; 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 { class TestChargeUtils {
@BeforeAll @BeforeAll